More work with security deposits, reversals, and balances. I've tried to work many different corner cases, but know that not everything has been tested. I think the next steps for testing will be to put in some real data.
git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@499 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
@@ -172,8 +172,6 @@ class LeasesController extends AppController {
|
||||
);
|
||||
|
||||
$this->redirect($this->data['redirect']);
|
||||
$this->autoRender = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isset($id))
|
||||
|
||||
@@ -16,6 +16,16 @@ class LedgerEntriesController extends AppController {
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: index / current / past / all
|
||||
* - Creates a list of ledger entries
|
||||
*/
|
||||
|
||||
function index() { $this->gridView('All Ledger Entries'); }
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
|
||||
@@ -16,6 +16,16 @@ class StatementEntriesController extends AppController {
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: index / current / past / all
|
||||
* - Creates a list of statement entries
|
||||
*/
|
||||
|
||||
function index() { $this->gridView('All Statement Entries'); }
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
@@ -232,14 +242,24 @@ class StatementEntriesController extends AppController {
|
||||
|
||||
|
||||
if (strtoupper($entry['StatementEntry']['type']) === 'CHARGE') {
|
||||
// Set up dynamic menu items
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'Operations', 'header' => true);
|
||||
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'Reverse',
|
||||
'url' => array('action' => 'reverse',
|
||||
$id));
|
||||
$reversal = $this->StatementEntry->find
|
||||
('first',
|
||||
array('link' => array('DisbursementEntry'),
|
||||
'conditions' => array(array('StatementEntry.id' => $id),
|
||||
array('DisbursementEntry.type' => 'REVERSAL')),
|
||||
));
|
||||
|
||||
// Set up dynamic menu items
|
||||
if (empty($reversal) || $stats['balance'] > 0)
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'Operations', 'header' => true);
|
||||
|
||||
if (empty($reversal))
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'Reverse',
|
||||
'url' => array('action' => 'reverse',
|
||||
$id));
|
||||
|
||||
if ($stats['balance'] > 0)
|
||||
$this->sidemenu_links[] =
|
||||
|
||||
@@ -99,9 +99,9 @@ class Lease extends AppModel {
|
||||
|
||||
// Since security deposits are being released, this also means
|
||||
// any unpaid (or only partially paid) security deposit should
|
||||
// have the remaining balance simply waived.
|
||||
// have the remaining balance reversed.
|
||||
if ($charge['StatementEntry']['balance'] > 0)
|
||||
$this->StatementEntry->waive($charge['StatementEntry']['id'], $stamp);
|
||||
$this->StatementEntry->reverse($charge['StatementEntry']['id'], true, $stamp);
|
||||
|
||||
$release['Entry'][] =
|
||||
array('amount' => $charge['StatementEntry']['reconciled'],
|
||||
@@ -521,10 +521,14 @@ class Lease extends AppModel {
|
||||
if (!$id)
|
||||
return $this->prReturn(null);
|
||||
|
||||
$this->queryInit($query);
|
||||
$query['conditions'][] = array('StatementEntry.lease_id' => $id);
|
||||
$stats = $this->StatementEntry->stats(null, $query);
|
||||
return $this->prReturn($stats);
|
||||
$find_stats = $this->StatementEntry->find
|
||||
('first', array
|
||||
('contain' => false,
|
||||
'fields' => $this->StatementEntry->chargeDisbursementFields(true),
|
||||
'conditions' => array('StatementEntry.lease_id' => $id),
|
||||
));
|
||||
$find_stats = $find_stats[0];
|
||||
return $this->prReturn($find_stats);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ class StatementEntry extends AppModel {
|
||||
}
|
||||
|
||||
function creditTypes() {
|
||||
return array('DISBURSEMENT', 'WAIVER', 'SURPLUS');
|
||||
return array('DISBURSEMENT', 'WAIVER', 'REVERSAL', 'SURPLUS');
|
||||
}
|
||||
|
||||
function voidTypes() {
|
||||
@@ -143,7 +143,7 @@ class StatementEntry extends AppModel {
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: waive
|
||||
* - Waives the charges
|
||||
* - Waives the charge balance
|
||||
*
|
||||
*/
|
||||
function waive($id, $stamp = null) {
|
||||
@@ -154,6 +154,9 @@ class StatementEntry extends AppModel {
|
||||
$charge = $this->read(null, $id);
|
||||
$charge = $charge['StatementEntry'];
|
||||
|
||||
if ($charge['type'] !== 'CHARGE')
|
||||
INTERNAL_ERROR("Waiver item is not CHARGE.");
|
||||
|
||||
// Query the stats to get the remaining balance
|
||||
$stats = $this->stats($id);
|
||||
|
||||
@@ -162,9 +165,6 @@ class StatementEntry extends AppModel {
|
||||
$waiver['Transaction']['stamp'] = $stamp;
|
||||
$waiver['Transaction']['comment'] = "Charge Waiver";
|
||||
|
||||
if ($charge['type'] !== 'CHARGE')
|
||||
die("INTERNAL ERROR: WAIVER ITEM IS NOT CHARGE");
|
||||
|
||||
// Add the charge waiver
|
||||
$waiver['Entry'][] =
|
||||
array('amount' => $stats['Charge']['balance'],
|
||||
@@ -185,7 +185,7 @@ class StatementEntry extends AppModel {
|
||||
* - Reverses the charges
|
||||
*
|
||||
*/
|
||||
function reverse($id, $stamp = null) {
|
||||
function reverse($id, $balance = false, $stamp = null) {
|
||||
$this->prEnter(compact('id', 'stamp'));
|
||||
|
||||
$ret = array();
|
||||
@@ -195,12 +195,18 @@ class StatementEntry extends AppModel {
|
||||
$charge = $this->read(null, $id);
|
||||
$charge = $charge['StatementEntry'];
|
||||
|
||||
if ($charge['type'] !== 'CHARGE')
|
||||
INTERNAL_ERROR("Reversal item is not CHARGE.");
|
||||
|
||||
$voided_entry_transactions = array();
|
||||
$reconciled = $this->reconciledEntries($id);
|
||||
$this->pr(21, compact('reconciled'));
|
||||
|
||||
if ($reconciled) {
|
||||
if ($reconciled && !$balance) {
|
||||
foreach ($reconciled['entries'] AS $entry) {
|
||||
if ($entry['DisbursementEntry']['type'] === 'REVERSAL')
|
||||
INTERNAL_ERROR("Charge has already been reversed");
|
||||
|
||||
$voided_entry_transactions[$entry['DisbursementEntry']['transaction_id']]
|
||||
= array_intersect_key($entry['DisbursementEntry'],
|
||||
array('customer_id'=>1, 'lease_id'=>1));
|
||||
@@ -224,12 +230,9 @@ class StatementEntry extends AppModel {
|
||||
$reversal['Transaction']['stamp'] = $stamp;
|
||||
$reversal['Transaction']['comment'] = "Credit Note: Charge Reversal";
|
||||
|
||||
if ($charge['type'] !== 'CHARGE')
|
||||
die("INTERNAL ERROR: REVERSAL ITEM IS NOT CHARGE");
|
||||
|
||||
// Add the charge reversal
|
||||
$reversal['Entry'][] =
|
||||
array('amount' => $stats['Charge']['total'],
|
||||
array('amount' => $stats['Charge']['balance'],
|
||||
'account_id' => $charge['account_id'],
|
||||
'comment' => 'Charge Reversal',
|
||||
);
|
||||
@@ -285,7 +288,7 @@ class StatementEntry extends AppModel {
|
||||
}
|
||||
|
||||
function reconciledSet($set, $query = null, $unrec = false, $if_rec_include_partial = false) {
|
||||
//$this->prFunctionLevel(16);
|
||||
//$this->prFunctionLevel(array('log' => 16, 'show' => 10));
|
||||
$this->prEnter(compact('set', 'query', 'unrec', 'if_rec_include_partial'));
|
||||
$lquery = $this->reconciledSetQuery($set, $query);
|
||||
$result = $this->find('all', $lquery);
|
||||
@@ -338,10 +341,14 @@ class StatementEntry extends AppModel {
|
||||
|
||||
$query['conditions'][] = array('StatementEntry.id' => $id);
|
||||
|
||||
if (in_array($this->data['StatementEntry']['type'], $this->debitTypes()))
|
||||
if (in_array($this->data['StatementEntry']['type'], $this->debitTypes())) {
|
||||
$query['link']['DisbursementEntry'] = array();
|
||||
if (in_array($this->data['StatementEntry']['type'], $this->creditTypes()))
|
||||
$query['conditions'][] = array('DisbursementEntry.id !=' => null);
|
||||
}
|
||||
if (in_array($this->data['StatementEntry']['type'], $this->creditTypes())) {
|
||||
$query['link']['ChargeEntry'] = array();
|
||||
$query['conditions'][] = array('ChargeEntry.id !=' => null);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
@@ -387,29 +394,39 @@ class StatementEntry extends AppModel {
|
||||
|
||||
$ret = array();
|
||||
|
||||
// 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'),
|
||||
"Credits Established");
|
||||
// First, find all known credits, unless this call is to make
|
||||
// credit adjustments to a specific charge
|
||||
// REVISIT <AP>: 20090806
|
||||
// If the theory below is correct, we should only search for
|
||||
// explicit credits if we don't have a receipt_id
|
||||
if (empty($charge_ids)) {
|
||||
$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'),
|
||||
"Credits Established");
|
||||
}
|
||||
else {
|
||||
if (empty($receipt_id))
|
||||
INTERNAL_ERROR("Can't make adjustments to a charge without a receipt ID.");
|
||||
}
|
||||
|
||||
// Next, establish credit from the newly added receipt
|
||||
$receipt_credit = null;
|
||||
@@ -428,7 +445,7 @@ class StatementEntry extends AppModel {
|
||||
);
|
||||
$receipt_credit = $this->Transaction->find('first', $lquery);
|
||||
if (!$receipt_credit)
|
||||
die("INTERNAL ERROR: UNABLE TO LOCATE RECEIPT");
|
||||
INTERNAL_ERROR("Unable to locate receipt.");
|
||||
|
||||
//$reconciled = $this->reconciledEntries($id);
|
||||
|
||||
@@ -462,6 +479,13 @@ class StatementEntry extends AppModel {
|
||||
// Initialize our list of used credits
|
||||
$used_credits = array();
|
||||
|
||||
// REVISIT <AP>: 20090806
|
||||
// Testing a theory. We should never have
|
||||
// explicit credits, as well as a new receipt,
|
||||
// and yet have outstanding charges.
|
||||
if (!empty($credits) && !empty($receipt_credit) && !empty($charges))
|
||||
INTERNAL_ERROR("Explicit credits that haven't already been applied.");
|
||||
|
||||
// Work through all unpaid charges, applying disbursements as we go
|
||||
foreach ($charges AS $charge) {
|
||||
|
||||
@@ -473,21 +497,21 @@ class StatementEntry extends AppModel {
|
||||
// will handle everything just fine. However, this
|
||||
// just saves extra processing if/when there is no
|
||||
// means to resolve a charge anyway.
|
||||
if (count($credits) == 0 && empty($receipt_credit['balance'])) {
|
||||
if (empty($credits) && empty($receipt_credit['balance'])) {
|
||||
$this->pr(17, 'No more available credits');
|
||||
break;
|
||||
}
|
||||
|
||||
$charge['balance'] = $charge['StatementEntry']['balance'];
|
||||
while ($charge['balance'] > 0 &&
|
||||
(count($credits) || !empty($receipt_credit['balance']))) {
|
||||
(!empty($credits) || !empty($receipt_credit['balance']))) {
|
||||
|
||||
$this->pr(20, compact('charge'),
|
||||
'Attempt Charge Reconciliation');
|
||||
|
||||
// Use explicit credits before using implicit credits
|
||||
// (Not sure it matters though).
|
||||
if (count($credits)) {
|
||||
if (!empty($credits)) {
|
||||
// Peel off the first credit available
|
||||
$credit =& $credits[0];
|
||||
$disbursement_date = $credit['StatementEntry']['effective_date'];
|
||||
@@ -519,14 +543,14 @@ class StatementEntry extends AppModel {
|
||||
|
||||
$this->pr(20, compact('credit'),
|
||||
($credit['balance'] > 0 ? 'Utilized' : 'Exhausted') .
|
||||
(count($credits) ? ' Credit' : ' Receipt'));
|
||||
(!empty($credits) ? ' Credit' : ' Receipt'));
|
||||
|
||||
if ($credit['balance'] < 0)
|
||||
die("HOW DID WE END UP WITH NEGATIVE SURPLUS BALANCE?");
|
||||
|
||||
// If we've exhausted the credit, get it out of the
|
||||
// available credit pool (but keep track of it for later).
|
||||
if ($credit['balance'] <= 0 && count($credits))
|
||||
if ($credit['balance'] <= 0 && !empty($credits))
|
||||
$used_credits[] = array_shift($credits);
|
||||
|
||||
// Add a disbursement that uses the available credit to pay the charge
|
||||
@@ -588,21 +612,37 @@ class StatementEntry extends AppModel {
|
||||
if (!empty($receipt_credit['balance'])) {
|
||||
$credit =& $receipt_credit;
|
||||
|
||||
$this->pr(18, compact('credit'),
|
||||
'Create Explicit Credit');
|
||||
$explicit_credit = $this->find
|
||||
('first', array('contain' => false,
|
||||
'conditions' =>
|
||||
array(array('transaction_id' => $credit['Transaction']['id']),
|
||||
array('type' => 'SURPLUS')),
|
||||
));
|
||||
|
||||
$result = $this->addStatementEntry
|
||||
(array('type' => 'SURPLUS',
|
||||
'account_id' => $credit['LedgerEntry']['account_id'],
|
||||
'amount' => $credit['balance'],
|
||||
'effective_date' => $credit['Transaction']['stamp'],
|
||||
'transaction_id' => $credit['Transaction']['id'],
|
||||
'customer_id' => $customer_id,
|
||||
'lease_id' => $lease_id,
|
||||
));
|
||||
$ret['Credit'] = $result;
|
||||
if ($result['error'])
|
||||
$ret['error'] = true;
|
||||
if (empty($explicit_credit)) {
|
||||
$this->pr(18, compact('credit'),
|
||||
'Create Explicit Credit');
|
||||
|
||||
$result = $this->addStatementEntry
|
||||
(array('type' => 'SURPLUS',
|
||||
'account_id' => $credit['LedgerEntry']['account_id'],
|
||||
'amount' => $credit['balance'],
|
||||
'effective_date' => $credit['Transaction']['stamp'],
|
||||
'transaction_id' => $credit['Transaction']['id'],
|
||||
'customer_id' => $customer_id,
|
||||
'lease_id' => $lease_id,
|
||||
));
|
||||
$ret['Credit'] = $result;
|
||||
if ($result['error'])
|
||||
$ret['error'] = true;
|
||||
}
|
||||
else {
|
||||
$this->pr(18, compact('explicit_credit', 'credit'),
|
||||
'Update Explicit Credit');
|
||||
$EC = new StatementEntry();
|
||||
$EC->id = $explicit_credit['StatementEntry']['id'];
|
||||
$EC->saveField('amount', $credit['balance']);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->prReturn($ret + array('error' => false));
|
||||
@@ -616,6 +656,7 @@ class StatementEntry extends AppModel {
|
||||
* - Returns summary data from the requested statement entry
|
||||
*/
|
||||
function stats($id = null, $query = null) {
|
||||
$this->prFunctionLevel(array('log' => 19, 'show' => 10));
|
||||
$this->prEnter(compact('id', 'query'));
|
||||
|
||||
$this->queryInit($query);
|
||||
@@ -625,80 +666,51 @@ class StatementEntry extends AppModel {
|
||||
if (isset($id))
|
||||
$query['conditions'][] = array('StatementEntry.id' => $id);
|
||||
|
||||
// Determine the total in charges
|
||||
$charge_query = $query;
|
||||
unset($charge_query['link']['ChargeEntry']);
|
||||
unset($charge_query['link']['DisbursementEntry']);
|
||||
$types = array('Charge', 'Disbursement');
|
||||
foreach ($types AS $type_index => $this_name) {
|
||||
$that_name = $types[($type_index + 1) % 2];
|
||||
if ($this_name === 'Charge') {
|
||||
$this_types = $this->debitTypes();
|
||||
$that_types = $this->creditTypes();
|
||||
} else {
|
||||
$this_types = $this->creditTypes();
|
||||
$that_types = $this->debitTypes();
|
||||
}
|
||||
|
||||
$charge_query['fields'] = array();
|
||||
$charge_query['fields'][] = "SUM(StatementEntry.amount) AS total";
|
||||
$charge_query['conditions'][] = array('StatementEntry.type' => $this->debitTypes());
|
||||
$result = $this->find('first', $charge_query);
|
||||
$stats['Charge'] = $result[0];
|
||||
$this_query = $query;
|
||||
$this_query['fields'] = array();
|
||||
$this_query['fields'][] = "SUM(StatementEntry.amount) AS total";
|
||||
$this_query['conditions'][] = array('StatementEntry.type' => $this_types);
|
||||
$result = $this->find('first', $this_query);
|
||||
$stats[$this_name] = $result[0];
|
||||
|
||||
$this->pr(17, compact('charge_query', 'result'),
|
||||
'Charges');
|
||||
$this->pr(17, compact('this_query', 'result'), $this_name.'s');
|
||||
|
||||
// Tally the amount actually _paid_ to those charges
|
||||
$charge_disbursement_query = $charge_query;
|
||||
$charge_disbursement_query['link']['DisbursementEntry'] = array('fields' => array());
|
||||
$charge_disbursement_query['fields'] = array();
|
||||
$charge_disbursement_query['fields'][] = "COALESCE(SUM(DisbursementEntry.amount),0) AS paid";
|
||||
$charge_disbursement_query['conditions'][] = array('DisbursementEntry.type' => 'DISBURSEMENT');
|
||||
$result = $this->find('first', $charge_disbursement_query);
|
||||
$stats['Charge'] += $result[0];
|
||||
|
||||
$this->pr(17, compact('charge_disbursement_query', 'result'),
|
||||
'Charge Disbursements');
|
||||
// Tally the different types that result in credits towards the charges
|
||||
$stats[$this_name]['reconciled'] = 0;
|
||||
foreach ($that_types AS $that_type) {
|
||||
$lc_that_type = strtolower($that_type);
|
||||
$that_query = $this_query;
|
||||
$that_query['link']["{$that_name}Entry"] = array('fields' => array());
|
||||
$that_query['fields'] = array();
|
||||
if ($this_name == 'Charge')
|
||||
$that_query['fields'][] = "COALESCE(SUM(${that_name}Entry.amount),0) AS $lc_that_type";
|
||||
else
|
||||
$that_query['fields'][] = "COALESCE(SUM(StatementEntry.amount), 0) AS $lc_that_type";
|
||||
$that_query['conditions'][] = array("{$that_name}Entry.type" => $that_type);
|
||||
$result = $this->find('first', $that_query);
|
||||
$stats[$this_name] += $result[0];
|
||||
|
||||
// Tally the amount of charges that have been waived
|
||||
$charge_waiver_query = $charge_query;
|
||||
$charge_waiver_query['link']['DisbursementEntry'] = array('fields' => array());
|
||||
$charge_waiver_query['fields'] = array();
|
||||
$charge_waiver_query['fields'][] = "COALESCE(SUM(DisbursementEntry.amount),0) AS waived";
|
||||
$charge_waiver_query['conditions'][] = array('DisbursementEntry.type' => 'WAIVER');
|
||||
$result = $this->find('first', $charge_waiver_query);
|
||||
$stats['Charge'] += $result[0];
|
||||
|
||||
$this->pr(17, compact('charge_waiver_query', 'result'),
|
||||
'Charge Waivers');
|
||||
$this->pr(17, compact('that_query', 'result'), "{$this_name}s: $that_type");
|
||||
$stats[$this_name]['reconciled'] += $stats[$this_name][$lc_that_type];
|
||||
}
|
||||
|
||||
// Compute some summary information for charges
|
||||
$stats['Charge']['reconciled'] =
|
||||
$stats['Charge']['paid'] + $stats['Charge']['waived'];
|
||||
$stats['Charge']['balance'] =
|
||||
$stats['Charge']['total'] - $stats['Charge']['reconciled'];
|
||||
if (!isset($stats['Charge']['balance']))
|
||||
$stats['Charge']['balance'] = 0;
|
||||
|
||||
|
||||
// Determine the total in disbursements, including those which
|
||||
// are charge waivers and those that do not even reconcile
|
||||
// to charges (i.e. they are surplus disbursements).
|
||||
$disbursement_query = $query;
|
||||
unset($disbursement_query['link']['DisbursementEntry']);
|
||||
$disbursement_query['link']['ChargeEntry'] = array('fields' => array());
|
||||
|
||||
$disbursement_query['fields'] = array();
|
||||
$disbursement_query['fields'][] = "SUM(StatementEntry.amount) AS total";
|
||||
$disbursement_query['fields'][] = "COALESCE(SUM(IF(ChargeEntry.id IS NULL, 0, StatementEntry.amount)), 0) AS charged";
|
||||
$disbursement_query['fields'][] = "COALESCE(SUM(IF(ChargeEntry.id IS NULL, StatementEntry.amount, 0)), 0) AS surplus";
|
||||
|
||||
$disbursement_query['conditions'][] = array('StatementEntry.type' => array('DISBURSEMENT', 'WAIVER', 'SURPLUS'));
|
||||
$result = $this->find('first', $disbursement_query);
|
||||
$stats['Disbursement'] = $result[0];
|
||||
|
||||
$this->pr(17, compact('disbursement_query', 'result'),
|
||||
'Disbursements');
|
||||
|
||||
// Compute some summary information for disbursements.
|
||||
// Add a reconciled field just for consistency with Charge.
|
||||
$stats['Disbursement']['reconciled'] =
|
||||
$stats['Disbursement']['charged'];
|
||||
$stats['Disbursement']['balance'] =
|
||||
$stats['Disbursement']['total'] - $stats['Disbursement']['reconciled'];
|
||||
if (!isset($stats['Disbursement']['balance']))
|
||||
$stats['Disbursement']['balance'] = 0;
|
||||
// Compute balance information for charges
|
||||
$stats[$this_name]['balance'] =
|
||||
$stats[$this_name]['total'] - $stats[$this_name]['reconciled'];
|
||||
if (!isset($stats[$this_name]['balance']))
|
||||
$stats[$this_name]['balance'] = 0;
|
||||
}
|
||||
|
||||
// 'balance' is simply the difference between
|
||||
// the balances of charges and disbursements
|
||||
@@ -711,7 +723,7 @@ class StatementEntry extends AppModel {
|
||||
// stats with respect to a particular account.
|
||||
// It represents the difference between inflow
|
||||
// and outflow from that account.
|
||||
$stats['account_balance'] = $stats['Charge']['paid'] - $stats['Disbursement']['total'];
|
||||
$stats['account_balance'] = $stats['Charge']['reconciled'] - $stats['Disbursement']['total'];
|
||||
if (!isset($stats['account_balance']))
|
||||
$stats['account_balance'] = 0;
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ class Transaction extends AppModel {
|
||||
// Just make sure the disbursement(s) are marked as waivers
|
||||
// and that they go to cover the specific charge.
|
||||
$data['Transaction']['disbursement_type'] = 'WAIVER';
|
||||
$data['Transaction']['charge_entry_id'] = $charge_id;
|
||||
$data['Transaction']['assign_charge_entry_id'] = $charge_id;
|
||||
|
||||
// In all other respects this is just a receipt.
|
||||
$ids = $this->addReceipt($data, $customer_id, $lease_id);
|
||||
@@ -150,54 +150,19 @@ class Transaction extends AppModel {
|
||||
$this->prEnter(compact('data', 'charge_id', 'customer_id', 'lease_id'));
|
||||
|
||||
if (count($data['Entry']) != 1)
|
||||
die("INTERNAL ERROR: Should be one Entry for addWaiver");
|
||||
die("INTERNAL ERROR: Should be one Entry for addReversal");
|
||||
|
||||
// Just make sure the disbursement(s) are marked as reversals
|
||||
// and that they go to cover the specific charge.
|
||||
$data['Transaction']['type'] = 'CREDIT_NOTE';
|
||||
$data['Transaction']['charge_entry_id'] = $charge_id;
|
||||
//$data['Entry'][0]['amount'] *= -1;
|
||||
//$data['Entry'][0]['type'] = 'DISBURSEMENT';
|
||||
$data['Transaction']['disbursement_type'] = 'REVERSAL';
|
||||
$data['Transaction']['assign_charge_entry_id'] = $charge_id;
|
||||
|
||||
// In all other respects this is just a receipt.
|
||||
$ids = $this->addReceipt($data, $customer_id, $lease_id);
|
||||
if (isset($ids['transaction_id']))
|
||||
$ids['reversal_id'] = $ids['transaction_id'];
|
||||
|
||||
/* $new_charge_id = $ids['entries'][0]['StatementEntry']['statement_entry_id']; */
|
||||
/* $this->StatementEntry->id = $new_charge_id; */
|
||||
/* $this->StatementEntry->saveField('charge_entry_id', $charge_id); */
|
||||
return $this->prReturn($ids);
|
||||
|
||||
|
||||
// Just make sure the transaction is marked as an INVOICE
|
||||
// and that it goes to cover the specific charge.
|
||||
//$data['Transaction']['type'] = 'INVOICE';
|
||||
$data['Transaction']['charge_entry_id'] = $charge_id;
|
||||
|
||||
// In all other respects this works just like a receipt.
|
||||
$ids = $this->addReceipt($data, $customer_id, $lease_id);
|
||||
if (isset($ids['transaction_id']))
|
||||
$ids['reversal_id'] = $ids['transaction_id'];
|
||||
|
||||
return $this->prReturn($ids);
|
||||
|
||||
// Establish the transaction as an Invoice Reversal
|
||||
$reversal =& $data['Transaction'];
|
||||
$reversal +=
|
||||
array('type' => 'INVOICE', //'CREDIT_NOTE',
|
||||
'crdr' => 'CREDIT',
|
||||
'account_id' => $this->Account->accountReceivableAccountID(),
|
||||
'customer_id' => $customer_id,
|
||||
'lease_id' => $lease_id,
|
||||
);
|
||||
|
||||
// Go through the statement entries and flag as reversals
|
||||
foreach ($data['Entry'] AS &$entry)
|
||||
$entry += array('type' => 'CHARGE', //'REVERSAL',
|
||||
'crdr' => 'DEBIT',
|
||||
);
|
||||
|
||||
$ids = $this->addTransaction($data['Transaction'], $data['Entry']);
|
||||
if (isset($ids['transaction_id']))
|
||||
$ids['reversal_id'] = $ids['transaction_id'];
|
||||
|
||||
return $this->prReturn($ids);
|
||||
}
|
||||
|
||||
@@ -650,8 +615,8 @@ class Transaction extends AppModel {
|
||||
($transaction['crdr'] == 'CREDIT'
|
||||
? $ret['transaction_id']
|
||||
: null),
|
||||
($transaction['crdr'] == 'CREDIT' && !empty($transaction['charge_entry_id'])
|
||||
? $transaction['charge_entry_id']
|
||||
($transaction['crdr'] == 'CREDIT' && !empty($transaction['assign_charge_entry_id'])
|
||||
? $transaction['assign_charge_entry_id']
|
||||
: null),
|
||||
(!empty($transaction['disbursement_type'])
|
||||
? $transaction['disbursement_type']
|
||||
|
||||
@@ -84,7 +84,7 @@ echo $this->element('statement_entries', array
|
||||
'filter' => array('Customer.id' => $customer['Customer']['id'],
|
||||
'type !=' => 'VOID'),
|
||||
'exclude' => array('Customer'),
|
||||
'sort_column' => 'Date',
|
||||
'sort_column' => 'Effective',
|
||||
'sort_order' => 'DESC',
|
||||
)));
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ echo $this->element('statement_entries', array
|
||||
'filter' => array('Lease.id' => $lease['id']),
|
||||
'include' => array('Through'),
|
||||
'exclude' => array('Customer', 'Lease', 'Unit'),
|
||||
'sort_column' => 'Date',
|
||||
'sort_column' => 'Effective',
|
||||
'sort_order' => 'DESC',
|
||||
)));
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ echo '<div CLASS="detail supporting">' . "\n";
|
||||
|
||||
if ($transaction['type'] === 'INVOICE' ||
|
||||
$transaction['type'] === 'RECEIPT' ||
|
||||
$transaction['type'] === 'CREDIT_NOTE' ||
|
||||
$transaction['type'] === 'PAYMENT'
|
||||
) {
|
||||
echo $this->element('statement_entries', array
|
||||
|
||||
Reference in New Issue
Block a user