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:
@@ -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',
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
|
||||
Reference in New Issue
Block a user