Fixed bug when marking NSF of a tender that has only been used as a surplus and never applied to any charges. Modified the applyCredits algorithm to try and distinguish between surplus credits of a lease and general customer surplus. I don't know if it works completely, but I do know it creates an issue since a lease surplus can now never be utilized without additional lease charges, a refund (no yet implemented), or moving the surplus to the customer level (not intended to be implemented).

git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@483 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
abijah
2009-08-04 21:19:20 +00:00
parent 1afed6a6e0
commit 67280c89e7
5 changed files with 152 additions and 77 deletions

View File

@@ -178,17 +178,33 @@ class CustomersController extends AppController {
$this->redirect(array('action'=>'index'));
}
/* //$result = $this->Customer->securityDeposits($id); */
/* $result = $this->Customer->excessPayments($id); */
/* //$result = $this->Customer->unreconciledCharges($id); */
/* echo('<HR>'); */
/* pr($result); */
/* $this->autoRender = false; */
/* return; */
// Get details on this customer, its contacts and leases
$customer = $this->Customer->find
('first', array
('contain' => array
(// Models
'Contact' =>
array('order' => array('Contact.display_name'),
// Models
'ContactPhone',
'ContactEmail',
'ContactAddress',
),
'Lease' =>
array('Unit' =>
array('order' => array('sort_order'),
'fields' => array('id', 'name'),
),
),
),
$customer = $this->Customer->details($id);
'conditions' => array('Customer.id' => $id),
));
//pr($customer);
$outstanding_balance = $customer['stats']['balance'];
// Figure out the outstanding balances for this customer
$stats = $this->Customer->stats($id);
$outstanding_balance = $stats['balance'];
$outstanding_deposit = $this->Customer->securityDepositBalance($id);
// Figure out if this customer has any non-closed leases
@@ -229,6 +245,11 @@ class CustomersController extends AppController {
$id));
}
if ($outstanding_balance < 0)
$this->sidemenu_links[] =
array('name' => 'Issue Refund',
'url' => array('action' => 'refund', $id));
// Prepare to render.
$title = 'Customer: ' . $customer['Customer']['name'];
$this->set(compact('customer', 'title',

View File

@@ -213,22 +213,38 @@ class LeasesController extends AppController {
}
/* /\************************************************************************** */
/* ************************************************************************** */
/* ************************************************************************** */
/* * action: promote_credit */
/* * - Moves any lease credit up to the customer level, so that */
/* * it may be used for charges other than those on this lease. */
/* *\/ */
/* function promote_surplus($id) { */
/* $this->Lease->promoteSurplus($id); */
/* pr("PREVENTING REDIRECT"); */
/* $this->render('fake'); */
/* $this->redirect(array('controller' => 'leases', */
/* 'action' => 'view', */
/* $id)); */
/* } */
/**************************************************************************
**************************************************************************
**************************************************************************
* action: apply_deposit
* - Applies the security deposit to charges. This is much
* like a receipt, but it's separated to keep it simple and
* to prevent feature overload on the receipt page.
* action: refund
* - Provides lease customer with a refund
*/
function apply_deposit($id) {
$this->Lease->releaseSecurityDeposits($id);
pr("PREVENTING REDIRECT");
$this->render('fake');
$this->redirect(array('controller' => 'leases',
'action' => 'view',
$id));
function refund($id) {
// Obtain the overall lease balance
$stats = $this->Lease->stats($id);
$outstanding_balance = $stats['balance'];
$this->set(compact('lease', 'title',
'outstanding_balance'));
}
@@ -290,31 +306,6 @@ class LeasesController extends AppController {
}
/**************************************************************************
**************************************************************************
**************************************************************************
* action: refund
* - Provides user with a refund
* REVISIT <AP>: 20090710
* Should this be a customer function?
*/
function refund($id) {
/* // Obtain the overall lease balance */
/* $stats = $this->Lease->stats($id); */
/* $outstanding_balance = $stats['balance']; */
/* // Determine the lease security deposit */
/* $deposits = $this->Lease->securityDeposits($id); */
/* $outstanding_deposit = $deposits['summary']['balance']; */
/* $this->set(compact('lease', 'title', */
/* 'outstanding_deposit', */
/* 'outstanding_balance')); */
}
/**************************************************************************
**************************************************************************
**************************************************************************
@@ -435,19 +426,17 @@ class LeasesController extends AppController {
'action' => 'receipt',
$lease['Customer']['id']));
if (isset($lease['Lease']['moveout_date']) && $outstanding_deposit > 0 && $outstanding_balance > 0)
$this->sidemenu_links[] =
array('name' => 'Apply Deposit', 'url' => array('action' => 'apply_deposit',
$id));
/* if ($outstanding_balance < 0) */
/* $this->sidemenu_links[] = */
/* array('name' => 'Transfer Credit to Customer', */
/* 'url' => array('action' => 'promote_surplus', $id)); */
if (isset($lease['Lease']['moveout_date']) &&
$outstanding_balance <= 0 &&
($outstanding_deposit - $outstanding_balance) > 0)
if ($outstanding_balance < 0)
$this->sidemenu_links[] =
array('name' => 'Issue Refund', 'url' => array('action' => 'refund',
$id));
array('name' => 'Issue Refund',
'url' => array('action' => 'refund', $id));
if (isset($lease['Lease']['moveout_date']) && $outstanding_deposit == 0 && $outstanding_balance > 0)
if (isset($lease['Lease']['moveout_date']) && $outstanding_balance > 0)
$this->sidemenu_links[] =
array('name' => 'Write-Off', 'url' => array('action' => 'bad_debt',
$id));

View File

@@ -48,6 +48,20 @@ class Lease extends AppModel {
$query['conditions'][] = array('StatementEntry.account_id' =>
$this->StatementEntry->Account->securityDepositAccountID());
// REVISIT <AP>: 20090804
// Dilemma... how to handle security deposits used to pay
// charges on the lease, yet are not part of the lease
// security deposit(s)? For example, Lease A & Lease B,
// each with $25 Sec. Dep. Move out of Lease A, and
// promote the lease surplus to the customer. A new
// charge on Lease B for $15, which is assigned $15/$25
// from the promoted Lease A surplus. They way this
// function works at present, it will presume the $15 is
// part of the security deposit balance, and will end up
// calculating it as only $10, which is wrong. Perhaps
// the fix is to release security deposits into some sort
// of income account.
$stats = $this->StatementEntry->stats(null, $query);
return $this->prReturn($stats['account_balance']);
}
@@ -450,18 +464,6 @@ class Lease extends AppModel {
}
/**************************************************************************
**************************************************************************
**************************************************************************
* function: addCharge
* - Adds an additional charge to the lease
*/
function addCharge($id, $charge) {
}
/**************************************************************************
**************************************************************************
**************************************************************************

View File

@@ -22,7 +22,7 @@ class StatementEntry extends AppModel {
);
//var $default_log_level = array('log' => 30, 'show' => 15);
var $default_log_level = array('log' => 30, 'show' => 15);
/**************************************************************************
**************************************************************************
@@ -380,12 +380,15 @@ OPTION 2
$charge_ids = null, $payment_type = null,
$customer_id = null, $lease_id = null)
{
//$this->prFunctionLevel(25);
$this->prFunctionLevel(25);
$this->prEnter(compact('query', 'receipt_id',
'charge_ids', 'payment_type',
'customer_id', 'lease_id'));
$this->queryInit($query);
if (!empty($customer_id))
$query['conditions'][] = array('StatementEntry.customer_id' => $customer_id);
if (empty($payment_type))
$payment_type = 'PAYMENT';
@@ -394,6 +397,22 @@ OPTION 2
// First, find all known credits
$lquery = $query;
$lquery['conditions'][] = array('StatementEntry.type' => 'SURPLUS');
// REVISIT <AP>: 20090804
// We need to ensure that we're using surplus credits ONLY from either
// the given lease, or those that do not apply to any specific lease.
// However, by doing this, it forces any lease surplus amounts to
// remain frozen with that lease until either there is a lease charge,
// we refund the money, or we "promote" that surplus to the customer
// level and out of the leases direct control.
// That seems like a pain. Perhaps we should allow any customer
// surplus to be used on any customer charge.
$lquery['conditions'][] =
array('OR' =>
array(array('StatementEntry.lease_id' => null),
(!empty($lease_id)
? array('StatementEntry.lease_id' => $lease_id)
: array()),
));
$lquery['order'][] = 'StatementEntry.effective_date ASC';
$credits = $this->find('all', $lquery);
$this->pr(18, compact('credits'),
@@ -403,6 +422,7 @@ OPTION 2
$receipt_credit = null;
if (!empty($receipt_id)) {
$lquery = $query;
$lquery['link'] = array('StatementEntry' => $lquery['link']);
$lquery['link'] += array('LedgerEntry' =>
array('conditions' =>
//array(LedgerEntry.'crdr'=>'DEBIT'),
@@ -429,6 +449,9 @@ OPTION 2
'conditions' => array('StatementEntry.id' => $charge_ids));
} else {
$lquery = $query;
// If we're working with a specific lease, then limit charges to it
if (!empty($lease_id))
$lquery['conditions'][] = array('StatementEntry.lease_id' => $lease_id);
}
$lquery['order'] = 'StatementEntry.effective_date ASC';
$charges = $this->reconciledSet('CHARGE', $lquery, true);

View File

@@ -246,6 +246,44 @@ class Transaction extends AppModel {
}
/**************************************************************************
**************************************************************************
**************************************************************************
* function: addRefund
* - Adds a new refund transaction
*/
function addRefund($data, $customer_id, $lease_id = null) {
$this->prEnter(compact('data', 'customer_id', 'lease_id'));
// REVISIT <AP>: 20090804
// NOT IMPLEMENTED AT ALL. Just cut and paste so far
return array('error' => true);
// Establish the transaction as an refund
$refund =& $data['Transaction'];
$refund +=
array('type' => 'VOUCHER',
'crdr' => 'DEBIT',
'account_id' => $this->Account->accountReceivableAccountID(),
'customer_id' => $customer_id,
'lease_id' => $lease_id,
);
// Go through the statement entries and flag as charges
foreach ($data['Entry'] AS &$entry)
$entry += array('type' => 'CHARGE',
'crdr' => 'CREDIT',
);
$ids = $this->addTransaction($data['Transaction'], $data['Entry']);
if (isset($ids['transaction_id']))
$ids['refund_id'] = $ids['transaction_id'];
return $this->prReturn($ids);
}
/**************************************************************************
**************************************************************************
**************************************************************************
@@ -511,8 +549,7 @@ class Transaction extends AppModel {
$transaction['type'] == 'RECEIPT') &&
$subtype !== 'NSF' && !$ret['error']) {
$result = $this->StatementEntry->assignCredits
(array('link' => array('Customer'),
'conditions' => array('Customer.id' => $transaction['customer_id'])),
(null,
($transaction['type'] == 'RECEIPT'
? $ret['transaction_id']
: null),
@@ -621,11 +658,13 @@ class Transaction extends AppModel {
// Record the transaction, which will un-pay previously paid
// charges, void any credits, and other similar work.
$rollback_result = $this->addTransaction($rollback['Transaction'], $rollback['Entry'], 'NSF');
$this->pr(20, compact('rollback', 'rollback_result'));
$ret['rollback'] = $rollback_result;
if ($rollback_result['error'])
return $this->prReturn(array('error' => true) + $ret);
if (count($rollback['Entry'])) {
$rollback_result = $this->addTransaction($rollback['Transaction'], $rollback['Entry'], 'NSF');
$this->pr(20, compact('rollback', 'rollback_result'));
$ret['rollback'] = $rollback_result;
if ($rollback_result['error'])
return $this->prReturn(array('error' => true) + $ret);
}
// Add NSF Charge
$charge_result = $this->addInvoice
@@ -651,7 +690,8 @@ class Transaction extends AppModel {
return $this->prReturn(array('error' => true) + $ret);
$ret['nsf_transaction_id'] = $ret['bounce']['transaction_id'];
$ret['nsf_ledger_entry_id'] = $ret['rollback']['entries'][0]['DoubleEntry']['Entry1']['ledger_entry_id'];
if (!empty($ret['rollback']))
$ret['nsf_ledger_entry_id'] = $ret['rollback']['entries'][0]['DoubleEntry']['Entry1']['ledger_entry_id'];
return $this->prReturn($ret + array('error' => false));
}