Many bug fixes, found while entering real facility data. Most are quite minor, although there was a functionality change to assignCredits, to support concessions without assigning them to anything other than rent. I've found that there is a glaring problem with charge reversals, which don't work correctly with the collected report. Of course, we're deleting prior disbursements, which obviously needs to be rectified.

git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@540 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
abijah
2009-08-12 09:37:49 +00:00
parent e74f8987d9
commit 1d27b4dcb5
15 changed files with 120 additions and 137 deletions

View File

@@ -252,7 +252,7 @@ class StatementEntry extends AppModel {
null,
null,
$tx['customer_id'],
$tx['lease_id']
null
);
$this->pr(21, compact('result'));
$ret['assigned'][] = $result;
@@ -396,10 +396,11 @@ class StatementEntry extends AppModel {
// 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)) {
if (empty($receipt_id)) {
if (!empty($charge_ids))
INTERNAL_ERROR("Charge IDs, yet no corresponding receipt");
$lquery = $query;
$lquery['conditions'][] = array('StatementEntry.type' => 'SURPLUS');
// REVISIT <AP>: 20090804
@@ -424,13 +425,7 @@ class StatementEntry extends AppModel {
"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;
if (!empty($receipt_id)) {
// Next, establish credit from the newly added receipt
$lquery =
array('link' =>
array('StatementEntry',
@@ -447,13 +442,13 @@ class StatementEntry extends AppModel {
if (!$receipt_credit)
INTERNAL_ERROR("Unable to locate receipt.");
//$reconciled = $this->reconciledEntries($id);
$stats = $this->Transaction->stats($receipt_id);
$receipt_credit['balance'] =
$receipt_credit['Transaction']['amount'] - $stats['Disbursement']['total'];
$this->pr(18, compact('receipt_credit'),
$receipt_credit['receipt'] = true;
$credits = array($receipt_credit);
$this->pr(18, compact('credits'),
"Receipt Credit Added");
}
@@ -476,44 +471,22 @@ class StatementEntry extends AppModel {
$this->pr(18, compact('dtype', 'entries'), "Outstanding Debit Entries");
}
// 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) {
$this->pr(20, compact('charge'),
'Process Charge');
// Check that we have available credits.
// Technically, this isn't necessary, since the loop
// will handle everything just fine. However, this
// just saves extra processing if/when there is no
// means to resolve a charge anyway.
if (empty($credits) && empty($receipt_credit['balance'])) {
$this->pr(17, 'No more available credits');
break;
}
$charge['balance'] = $charge['StatementEntry']['balance'];
while ($charge['balance'] > 0 &&
(!empty($credits) || !empty($receipt_credit['balance']))) {
$this->pr(20, compact('charge'),
'Attempt Charge Reconciliation');
// Use explicit credits before using the new receipt credit
foreach ($credits AS &$credit) {
if (empty($charge['balance']))
break;
if ($charge['balance'] < 0)
INTERNAL_ERROR("Negative Charge Balance");
// Use explicit credits before using implicit credits
// (Not sure it matters though).
if (!empty($credits)) {
// Peel off the first credit available
$credit =& $credits[0];
if (empty($credit['receipt'])) {
// Explicit Credit
$disbursement_date = $credit['StatementEntry']['effective_date'];
$disbursement_transaction_id = $credit['StatementEntry']['transaction_id'];
$disbursement_account_id = $credit['StatementEntry']['account_id'];
@@ -521,16 +494,29 @@ class StatementEntry extends AppModel {
if (!isset($credit['balance']))
$credit['balance'] = $credit['StatementEntry']['amount'];
}
elseif (!empty($receipt_credit['balance'])) {
// Use our only receipt credit
$credit =& $receipt_credit;
else {
// Receipt Credit
$disbursement_date = $credit['Transaction']['stamp'];
$disbursement_transaction_id = $credit['Transaction']['id'];
$disbursement_account_id = $credit['LedgerEntry']['account_id'];
}
else {
die("HOW DID WE GET HERE WITH NO SURPLUS?");
}
if (empty($credit['balance']))
continue;
if ($credit['balance'] < 0)
INTERNAL_ERROR("Negative Credit Balance");
$this->pr(20, compact('charge'),
'Attempt Charge Reconciliation');
// REVISIT <AP>: 20090811
// Need to come up with a better strategy for handling
// concessions. For now, just restricting concessions
// to apply only towards rent will resolve the most
// predominant (or only) needed usage case.
if ($disbursement_account_id == $this->Account->concessionAccountID() &&
$charge['StatementEntry']['account_id'] != $this->Account->rentAccountID())
continue;
// Set the disbursement amount to the maximum amount
// possible without exceeding the charge or credit balance
@@ -543,15 +529,7 @@ class StatementEntry extends AppModel {
$this->pr(20, compact('credit'),
($credit['balance'] > 0 ? 'Utilized' : 'Exhausted') .
(!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 && !empty($credits))
$used_credits[] = array_shift($credits);
(empty($credit['receipt']) ? ' Credit' : ' Receipt'));
// Add a disbursement that uses the available credit to pay the charge
$disbursement = array('type' => $disbursement_type,
@@ -581,67 +559,69 @@ class StatementEntry extends AppModel {
if ($charge['balance'] <= 0)
$this->pr(20, 'Fully Paid Charge');
}
}
// Partially used credits must be added to the used list
if (isset($credits[0]['applied']))
$used_credits[] = array_shift($credits);
$this->pr(18, compact('credits', 'used_credits', 'receipt_credit'),
'Disbursements added');
$this->pr(18, compact('credits'),
'Disbursements complete');
// Clean up any explicit credits that have been used
foreach ($used_credits AS $credit) {
if ($credit['balance'] > 0) {
$this->pr(20, compact('credit'),
'Update Credit Entry');
foreach ($credits AS $credit) {
if (empty($credit['receipt'])) {
// Explicit Credit
if (empty($credit['applied']))
continue;
$this->id = $credit['StatementEntry']['id'];
$this->saveField('amount', $credit['balance']);
if ($credit['balance'] > 0) {
$this->pr(20, compact('credit'),
'Update Credit Entry');
$this->id = $credit['StatementEntry']['id'];
$this->saveField('amount', $credit['balance']);
}
else {
$this->pr(20, compact('credit'),
'Delete Exhausted Credit Entry');
$this->del($credit['StatementEntry']['id'], false);
}
}
else {
$this->pr(20, compact('credit'),
'Delete Exhausted Credit Entry');
// Receipt Credit
if (empty($credit['balance']))
continue;
$this->del($credit['StatementEntry']['id'], false);
}
}
// Convert non-exhausted receipt credit to an explicit one
$explicit_credit = $this->find
('first', array('contain' => false,
'conditions' =>
array(array('transaction_id' => $credit['Transaction']['id']),
array('type' => 'SURPLUS')),
));
// Convert non-exhausted receipt credit to an explicit one
if (!empty($receipt_credit['balance'])) {
$credit =& $receipt_credit;
if (empty($explicit_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')),
));
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']);
$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']);
}
}
}