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/site@483 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
@@ -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',
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
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,6 +690,7 @@ class Transaction extends AppModel {
|
||||
return $this->prReturn(array('error' => true) + $ret);
|
||||
|
||||
$ret['nsf_transaction_id'] = $ret['bounce']['transaction_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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user