Getting closer on the reversal issue. There is definitely more testing to do, and some tweaks as well, but this may be approximately what we will finally settle on.

git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716/site@565 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
abijah
2009-08-15 03:11:16 +00:00
parent e9d92494c6
commit e76ad897a4
3 changed files with 147 additions and 55 deletions

View File

@@ -245,19 +245,14 @@ class StatementEntriesController extends AppController {
if (strtoupper($entry['StatementEntry']['type']) === 'CHARGE') {
$reversal = $this->StatementEntry->find
('first',
array('link' => array('DisbursementEntry'),
'conditions' => array(array('StatementEntry.id' => $id),
array('DisbursementEntry.type' => 'REVERSAL')),
));
$reversable = $this->StatementEntry->reversable($id);
// Set up dynamic menu items
if (empty($reversal) || $stats['balance'] > 0)
if ($reversable || $stats['balance'] > 0)
$this->sidemenu_links[] =
array('name' => 'Operations', 'header' => true);
if (empty($reversal))
if ($reversable)
$this->sidemenu_links[] =
array('name' => 'Reverse',
'url' => array('action' => 'reverse',

View File

@@ -181,8 +181,8 @@ class StatementEntry extends AppModel {
/**************************************************************************
**************************************************************************
**************************************************************************
* function: reverse
* - Reverses the charges
* function: reversable
* - Returns true if the charge can be reversed; false otherwise
*/
function reversable($id) {
$this->prEnter(compact('id'));
@@ -194,15 +194,9 @@ class StatementEntry extends AppModel {
return $this->prReturn(false);
// Determine anything reconciled against the charge
$reconciled = $this->reconciledEntries($id);
$this->pr(21, compact('reconciled'));
if (!empty($reconciled)) {
// Double check that this charge has not already been reversed
foreach ($reconciled['entries'] AS $entry)
if ($entry['DisbursementEntry']['type'] === 'REVERSAL')
return $this->prReturn(false);
}
$reverse_transaction_id = $this->field('reverse_transaction_id');
if (!empty($reverse_transaction_id))
return $this->prReturn(false);
return $this->prReturn(true);
}
@@ -222,28 +216,19 @@ class StatementEntry extends AppModel {
// Get the basic information about this charge
$charge = $this->find('first', array('contain' => true));
$charge = $charge['StatementEntry'];
//$charge = $charge['StatementEntry'];
// Query the stats to get the remaining balance
$stats = $this->stats($id);
// Build a transaction
$reversal = array('Transaction' => array(), 'Entry' => array());
$reversal['Transaction']['stamp'] = $stamp;
$reversal['Transaction']['comment'] = "Credit Note: Charge Reversal";
// Add the charge reversal
$reversal['Entry'][] =
array('amount' => $stats['Charge']['total'],
'account_id' => $charge['account_id'],
'comment' => 'Charge Reversal',
);
$charge['paid'] = $stats['Charge']['disbursement'];
// Record the reversal transaction
$result = $this->Transaction->addReversal
($reversal,
$id, $stats['Charge']['disbursement'],
$charge['customer_id'], $charge['lease_id']);
($charge, $stamp, 'Charge Reversal');
// Mark the charge as reversed
$this->id = $id;
$this->saveField('reverse_transaction_id', $result['transaction_id']);
return $this->prReturn($result);
}
@@ -416,8 +401,8 @@ class StatementEntry extends AppModel {
array('StatementEntry',
'LedgerEntry' =>
array('conditions' =>
array('LedgerEntry.account_id !=' =>
$this->Account->accountReceivableAccountID()),
array('LedgerEntry.account_id <> Transaction.account_id')
//$this->Account->accountReceivableAccountID()),
),
),
'conditions' => array('Transaction.id' => $receipt_id),

View File

@@ -178,14 +178,17 @@ class Transaction extends AppModel {
* - Adds a new charge reversal
*/
function addReversal($data, $charge_id, $credit_amount, $customer_id, $lease_id = null) {
$this->prEnter(compact('data', 'charge_id', 'credit_amount', 'customer_id', 'lease_id'));
function addReversal1($data, $charge) {
$this->prEnter(compact('data', 'charge'));
if (count($data['Entry']) != 1)
$this->INTERNAL_ERROR("Should be one Entry for addReversal");
$data += array('control' => array());
/* 'amount' => $stats['Charge']['total'], */
/* 'account_id' => $charge['account_id'], */
// First, reverse the charge
$reversal = $data;
$reversal['control'] +=
@@ -194,20 +197,22 @@ class Transaction extends AppModel {
'include_statement_entry' => true,
);
$reversal['Transaction']['type'] = 'CREDIT_NOTE';
//$reversal['Transaction']['crdr'] = 'CREDIT';
//$reversal['Transaction']['type'] = 'CREDIT_NOTE';
$reversal['Entry'][0]['charge_entry_id'] = $charge_id;
$reversal['Entry'][0]['type'] = 'REVERSAL';
//$reversal['Entry'][0]['type'] = 'REVERSAL';
$reversal['Entry'][0]['amount'] *= -1;
//$reversal['Transaction']['crdr'] = 'CREDIT';
//$reversal['Entry'][0]['crdr'] = 'DEBIT';
$ids['reversal'] = $this->addReceipt($reversal, $customer_id, $lease_id);
$ids['reversal'] = $this->addInvoice($reversal, $customer_id, $lease_id);
// Then issue a credit for the amount already paid, if any
if ($credit_amount > 0) {
$ids['credit'] = $this->addReceipt
(array('control' =>
array('assign' => true,
'assign_receipt' => true,
'include_ledger_entry' => false,
array('include_ledger_entry' => false,
'include_statement_entry' => true,
),
@@ -218,6 +223,8 @@ class Transaction extends AppModel {
'Entry' =>
array(array('amount' => $credit_amount,
'charge_entry_id' => $charge_id,
// REVISIT <AP>: 20090814
// TEMPORARY. JUST NEED AN ACCOUNT AT THE MOMENT
'account_id' => $this->StatementEntry->Account->accountPayableAccountID(),
))),
$customer_id, $lease_id);
@@ -590,7 +597,7 @@ class Transaction extends AppModel {
// Break each entry out of the combined statement/ledger entry
// and into individual entries appropriate for saving. While
// we're at it, calculate the transaction total as well.
$transaction['amount'] = 0;
$transaction_amount = 0;
foreach ($entries AS &$entry) {
// Ensure these items are null'ed out so we don't
// accidentally pick up stale data.
@@ -614,7 +621,11 @@ class Transaction extends AppModel {
$entry['statement_entry_comment'] = null;
}
if (!empty($control['include_ledger_entry']) || !empty($entry['include_ledger_entry'])) {
// Priority goes to settings defined in $entry, but
// use the control information as defaults.
$entry += $control;
if (!empty($entry['include_ledger_entry'])) {
// Create one half of the Double Ledger Entry (and the Tender)
$le1 =
array_intersect_key($entry,
@@ -643,10 +654,10 @@ class Transaction extends AppModel {
$le1 = $le1_tender = $le2 = null;
// Now that the ledger entries are in place, respect the 'negative' flag
if (!empty($control['negative']))
if (!empty($entry['negative']))
$entry['amount'] *= -1;
if (!empty($control['include_statement_entry']) || !empty($entry['include_statement_entry'])) {
if (!empty($entry['include_statement_entry'])) {
// Create the statement entry
$se =
array_intersect_key($entry,
@@ -659,7 +670,9 @@ class Transaction extends AppModel {
$se['comment'] = $entry['statement_entry_comment'];
}
else {
if (!empty($control['assign'])) {
if (!empty($entry['assign']) &&
!empty($entry['type']) &&
empty($entry['charge_entry_id'])) {
if (empty($assign_disbursement_type))
$assign_disbursement_type = $entry['type'];
elseif ($entry['type'] != $assign_disbursement_type)
@@ -670,12 +683,16 @@ class Transaction extends AppModel {
}
// Add entry amount into the transaction total
$transaction['amount'] += $entry['amount'];
$transaction_amount += $entry['amount'];
// Replace combined entry with our new individual entries
$entry = compact('le1', 'le1_tender', 'le2', 'se');
}
// If transaction amount is not already set, use the
// sum of the entry amounts.
$transaction += array('amount' => $transaction_amount);
/* // Add a summary ledger entry if requested */
/* if (!empty($control['summary_double_entry'])) { */
/* $entry = $control['summary_double_entry']; */
@@ -854,7 +871,7 @@ class Transaction extends AppModel {
'Entry' => array());
$summary_amount = 0;
$rollback['Transaction']['amount'] = 0;
foreach ($nsf_ledger_entry['Transaction']['StatementEntry'] AS $disbursement) {
if ($disbursement['type'] === 'SURPLUS') {
$disbursement['type'] = 'VOID';
@@ -870,7 +887,7 @@ class Transaction extends AppModel {
'lease_id' => $disbursement['lease_id'],
'charge_entry_id' => $disbursement['charge_entry_id'],
);
$summary_amount += $disbursement['amount'];
$rollback['Transaction']['amount'] += $disbursement['amount'];
}
}
@@ -878,11 +895,14 @@ class Transaction extends AppModel {
$rollback['Entry'][] =
array('include_ledger_entry' => true,
'include_statement_entry' => false,
'amount' => $summary_amount,
'amount' => $rollback['Transaction']['amount'],
'account_id' => $this->Account->accountReceivableAccountID(),
'crdr' => 'DEBIT',
);
// Set the transaction amount to be negative
$rollback['Transaction']['amount'] *= -1;
// Record the transaction, which will un-pay previously paid
// charges, void any credits, and other similar work.
if (count($rollback['Entry'])) {
@@ -925,6 +945,98 @@ class Transaction extends AppModel {
}
/**************************************************************************
**************************************************************************
**************************************************************************
* function: addReversal
* - Adds a new charge reversal
*/
function addReversal($charge, $stamp = null, $comment = null) {
$this->prEnter(compact('charge', 'stamp', 'comment'));
$ret = array();
// Finding all statement entries affected by reversing this charge.
$disb_entries = $this->StatementEntry->find
('first', array
('contain' => array('DisbursementEntry' =>
array(//'fields' => array(),
),
),
'conditions' => array('StatementEntry.id' => $charge['StatementEntry']['id']),
));
$this->pr(20, compact('disb_entries'));
if (!$disb_entries)
return $this->prReturn(array('error' => true) + $ret);
// Build a transaction to adjust all of the statement entries
// These are all disbursements against the charge we're reversing
$rollback =
array('control' =>
array('assign' => true,
'assign_receipt' => true,
'include_ledger_entry' => false,
'include_statement_entry' => true,
),
'Transaction' =>
array('stamp' => $stamp,
//'type' => 'RECEIPT',
'type' => 'CREDIT_NOTE',
// The transaction amount will equal that of the charge
'amount' => $charge['StatementEntry']['amount'],
'account_id' => $charge['StatementEntry']['account_id'],
'crdr' => 'DEBIT',
'customer_id' => $charge['StatementEntry']['customer_id'],
'lease_id' => null,
'comment' => $comment,
),
'Entry' => array());
foreach ($disb_entries['DisbursementEntry'] AS $disbursement) {
$rollback['Entry'][] =
array('type' => $disbursement['type'],
'amount' => -1 * $disbursement['amount'],
'account_id' => $disbursement['account_id'],
'customer_id' => $disbursement['customer_id'],
'lease_id' => $disbursement['lease_id'],
'charge_entry_id' => $disbursement['charge_entry_id'],
);
}
// Add the sole ledger entry for this transaction
$rollback['Entry'][] =
array('include_ledger_entry' => true,
'include_statement_entry' => false,
'type' => 'REVERSAL',
'amount' => $rollback['Transaction']['amount'],
//'account_id' => $this->Account->accountPayableAccountID(),
'account_id' => $this->Account->accountReceivableAccountID(),
'crdr' => 'CREDIT',
);
// Record the transaction, which will un-disburse previously
// disbursed payments, and other similar work.
if (count($rollback['Entry'])) {
$rollback_result = $this->addTransaction($rollback['control'],
$rollback['Transaction'],
$rollback['Entry']);
$this->pr(20, compact('rollback', 'rollback_result'));
$ret['rollback'] = $rollback_result;
if ($rollback_result['error'])
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']; */
$ret = $ret['rollback'];
return $this->prReturn($ret + array('error' => false));
}
/**************************************************************************
**************************************************************************
**************************************************************************