Merge in from surplus_account_20090815 r592
git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716/site@593 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
@@ -7,6 +7,13 @@ class Transaction extends AppModel {
|
||||
'Ledger',
|
||||
);
|
||||
|
||||
var $hasOne = array(
|
||||
'NsfTender' => array(
|
||||
'className' => 'Tender',
|
||||
'foreignKey' => 'nsf_transaction_id',
|
||||
),
|
||||
);
|
||||
|
||||
var $hasMany = array(
|
||||
'LedgerEntry' => array(
|
||||
'dependent' => true,
|
||||
@@ -44,6 +51,7 @@ class Transaction extends AppModel {
|
||||
|
||||
|
||||
var $default_log_level = array('log' => 30, 'show' => 15);
|
||||
//var $max_log_level = 10;
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
@@ -75,7 +83,6 @@ class Transaction extends AppModel {
|
||||
// Go through the statement entries and flag as charges
|
||||
foreach ($data['Entry'] AS &$entry)
|
||||
$entry += array('type' => 'CHARGE',
|
||||
'crdr' => 'CREDIT',
|
||||
);
|
||||
|
||||
$ids = $this->addTransaction($data['control'], $data['Transaction'], $data['Entry']);
|
||||
@@ -117,7 +124,6 @@ class Transaction extends AppModel {
|
||||
// Go through the statement entries and flag as disbursements
|
||||
foreach ($data['Entry'] AS &$entry)
|
||||
$entry += array('type' => 'DISBURSEMENT', // not used
|
||||
'crdr' => 'DEBIT',
|
||||
'account_id' =>
|
||||
(isset($entry['Tender']['tender_type_id'])
|
||||
? ($this->LedgerEntry->Tender->TenderType->
|
||||
@@ -237,7 +243,6 @@ class Transaction extends AppModel {
|
||||
if (!isset($group[$entry['account_id']]))
|
||||
$group[$entry['account_id']] =
|
||||
array('account_id' => $entry['account_id'],
|
||||
'crdr' => strtoupper($this->Account->fundamentalOpposite($data['Transaction']['crdr'])),
|
||||
'amount' => 0);
|
||||
$group[$entry['account_id']]['amount'] += $entry['amount'];
|
||||
}
|
||||
@@ -392,7 +397,6 @@ class Transaction extends AppModel {
|
||||
// Go through the statement entries and flag as payments
|
||||
foreach ($data['Entry'] AS &$entry)
|
||||
$entry += array('type' => 'PAYMENT',
|
||||
'crdr' => 'CREDIT',
|
||||
);
|
||||
|
||||
$ids = $this->addTransaction($data['control'], $data['Transaction'], $data['Entry']);
|
||||
@@ -453,59 +457,203 @@ class Transaction extends AppModel {
|
||||
* entries, as layed out in the $data['Entry'] array. The array is
|
||||
* overloaded, since it is used to create both ledger _and_ statement
|
||||
* entries.
|
||||
*
|
||||
* $data
|
||||
* - Transaction
|
||||
* - [MANDATORY]
|
||||
* - type (INVOICE, RECEIPT)
|
||||
* - account_id
|
||||
* - crdr
|
||||
* - [OPTIONAL]
|
||||
* - stamp
|
||||
* (default: NOW)
|
||||
* - comment
|
||||
* - [AUTOMATICALLY SET] (if set, these items will be overwritten)
|
||||
* - id
|
||||
* - amount
|
||||
* - customer_id
|
||||
* - ledger_id
|
||||
*
|
||||
* - Entry (array)
|
||||
* - [MANDATORY]
|
||||
* - type (CHARGE, DISBURSEMENT)
|
||||
* - account_id
|
||||
* - crdr
|
||||
* - amount
|
||||
* - [OPTIONAL]
|
||||
* - effective_date
|
||||
* - through_date
|
||||
* - due_date
|
||||
* - comment (used for statement or ledger entry, based on context)
|
||||
* - ledger_entry_comment
|
||||
* - statement_entry_comment
|
||||
* - Tender
|
||||
* - [MANDATORY]
|
||||
* - tender_type_id
|
||||
* - [OPTIONAL]
|
||||
* - name
|
||||
* (default: Entry Account Name & data1)
|
||||
* - data1, data2, data3, data4
|
||||
* - comment
|
||||
* - [AUTOMATICALLY SET] (if set, these items will be overwritten)
|
||||
* - id
|
||||
* - ledger_entry_id
|
||||
* - deposit_transaction_id
|
||||
* - nsf_transaction_id
|
||||
* - [AUTOMATICALLY SET] (if set, these items will be overwritten)
|
||||
* - id
|
||||
* - transaction_id
|
||||
* - ledger_id
|
||||
*
|
||||
*/
|
||||
|
||||
function addTransaction($control, $transaction, $entries) {
|
||||
$this->prEnter(compact('control', 'transaction', 'entries'));
|
||||
|
||||
$result = $this->_splitEntries($control, $transaction, $entries);
|
||||
if (!empty($result['error']))
|
||||
return $this->prReturn(array('error' => true));
|
||||
|
||||
// Make use of the work done by splitEntries
|
||||
$transaction = $this->filter_null($transaction) + $result['transaction'];
|
||||
$entries = $result['entries'];
|
||||
extract($result['vars']);
|
||||
|
||||
$this->pr(20, compact('transaction', 'entries'));
|
||||
|
||||
// Move forward, verifying and saving everything.
|
||||
$ret = array('data' => $transaction);
|
||||
if (!$this->verifyTransaction($transaction, $entries))
|
||||
return $this->prReturn(array('error' => true) + $ret);
|
||||
|
||||
// Save transaction to the database
|
||||
$this->create();
|
||||
if (!$this->save($transaction))
|
||||
return $this->prReturn(array('error' => true) + $ret);
|
||||
$ret['transaction_id'] = $transaction['id'] = $this->id;
|
||||
|
||||
// Add the entries
|
||||
$ret += $this->addTransactionEntries($control, $transaction, $entries, false);
|
||||
|
||||
// If the caller requests 'assign'=>true, they really
|
||||
// want to do a credit assignment, and _then_ create
|
||||
// an explicit credit with any leftover. If an array
|
||||
// is specified, they get full control of the order.
|
||||
if (empty($control['assign']))
|
||||
$assign_ops = array();
|
||||
elseif (is_array($control['assign']))
|
||||
$assign_ops = $control['assign'];
|
||||
elseif (is_bool($control['assign']))
|
||||
$assign_ops = (empty($control['assign_receipt'])
|
||||
? array('assign')
|
||||
: array('assign', 'create'));
|
||||
else
|
||||
$this->INTERNAL_ERROR('Invalid control[assign] parameter');
|
||||
|
||||
$this->pr(17, compact('assign_ops'), 'Credit operations');
|
||||
|
||||
// Go through the requested assignment mechanisms
|
||||
foreach ($assign_ops AS $method) {
|
||||
if (!empty($ret['error']))
|
||||
break;
|
||||
|
||||
$this->pr(17, compact('method'), 'Handling credits');
|
||||
|
||||
if ($method === 'assign') {
|
||||
$result = $this->StatementEntry->assignCredits
|
||||
(null,
|
||||
(empty($control['assign_receipt']) ? null
|
||||
: $ret['transaction_id']),
|
||||
null,
|
||||
$assign_disbursement_type,
|
||||
$transaction['customer_id'],
|
||||
$transaction['lease_id']
|
||||
);
|
||||
}
|
||||
elseif ($method === 'create' || is_numeric($method)) {
|
||||
if (is_numeric($method))
|
||||
$credit_amount = $method;
|
||||
else {
|
||||
$stats = $this->stats($transaction['id']);
|
||||
$credit_amount = $stats['undisbursed'];
|
||||
}
|
||||
|
||||
if ($credit_amount < 0)
|
||||
$this->INTERNAL_ERROR('Receipt has negative undisbursed balance');
|
||||
|
||||
if (empty($credit_amount))
|
||||
continue;
|
||||
|
||||
$result = $this->addTransactionEntries
|
||||
(array('include_ledger_entry' => true,
|
||||
'include_statement_entry' => true),
|
||||
array('crdr' => 'DEBIT') + $transaction,
|
||||
array(array('type' => 'SURPLUS',
|
||||
'account_id' => $this->Account->customerCreditAccountID(),
|
||||
'amount' => $credit_amount,
|
||||
),
|
||||
));
|
||||
}
|
||||
else
|
||||
$this->INTERNAL_ERROR('Invalid assign method');
|
||||
|
||||
$ret['credit'][$method] = $result;
|
||||
if (!empty($result['error']))
|
||||
$ret['error'] = true;
|
||||
}
|
||||
|
||||
$this->Customer->update($transaction['customer_id']);
|
||||
return $this->prReturn($ret);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: addTransactionEntries
|
||||
* - Largely a helper function to addTransaction, this function is
|
||||
* responsible for adding ledger/statement entries to an existing
|
||||
* transaction. If needed, this function can also be called outside
|
||||
* of addTransaction, although it's not clear where that would be
|
||||
* appropriate, since transactions are really snapshots of some
|
||||
* event, and shouldn't be mucked with after creation.
|
||||
*/
|
||||
|
||||
function addTransactionEntries($control, $transaction, $entries, $split = true) {
|
||||
$this->prEnter(compact('control', 'transaction', 'entries', 'split'));
|
||||
|
||||
// Verify that we have a transaction
|
||||
if (empty($transaction['id']))
|
||||
return $this->prReturn(array('error' => true));
|
||||
|
||||
// If the entries are not already split, do so now.
|
||||
if ($split) {
|
||||
$result = $this->_splitEntries($control, $transaction, $entries);
|
||||
if (!empty($result['error']))
|
||||
return $this->prReturn(array('error' => true));
|
||||
|
||||
// Make use of the work done by splitEntries
|
||||
$transaction = $this->filter_null($transaction) + $result['transaction'];
|
||||
$entries = $result['entries'];
|
||||
extract($result['vars']);
|
||||
|
||||
/* // Verify the entries */
|
||||
/* $ret = array(); */
|
||||
/* if (!$this->verifyTransaction($transaction, $entries)) */
|
||||
/* return $this->prReturn(array('error' => true) + $ret); */
|
||||
}
|
||||
|
||||
$this->id = $transaction['id'];
|
||||
$transaction['stamp'] = $this->field('stamp');
|
||||
$transaction['customer_id'] = $this->field('customer_id');
|
||||
|
||||
// Set up our return array
|
||||
$ret = array();
|
||||
$ret['entries'] = array();
|
||||
$ret['error'] = false;
|
||||
|
||||
// Go through the entries
|
||||
foreach ($entries AS $e_index => &$entry) {
|
||||
// Ensure these items are null'ed out so we don't
|
||||
// accidentally pick up stale data.
|
||||
$le1 = $le1_tender = $le2 = $se = null;
|
||||
extract($entry);
|
||||
|
||||
if (!empty($le1) && !empty($le2)) {
|
||||
$le1['transaction_id'] = $le2['transaction_id'] = $transaction['id'];
|
||||
if (isset($le1_tender))
|
||||
$le1_tender['customer_id'] = $transaction['customer_id'];
|
||||
$result = $this->LedgerEntry->DoubleEntry->addDoubleEntry($le1, $le2, $le1_tender);
|
||||
$ret['entries'][$e_index]['DoubleEntry'] = $result;
|
||||
if ($result['error']) {
|
||||
$ret['error'] = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($se)) {
|
||||
$se['transaction_id'] = $transaction['id'];
|
||||
if (empty($se['effective_date']))
|
||||
$se['effective_date'] = $transaction['stamp'];
|
||||
$result = $this->StatementEntry->addStatementEntry($se);
|
||||
$ret['entries'][$e_index]['StatementEntry'] = $result;
|
||||
if ($result['error']) {
|
||||
$ret['error'] = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->prReturn($ret);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: _splitEntries
|
||||
* - An internal helper function capable of splitting an array of
|
||||
* combined ledger/statement entries into their indivdual entry
|
||||
* components (2 ledger entries, and a statement entry), based
|
||||
* on the typical requirements. Any custom split will have to
|
||||
* be done outside of this function.
|
||||
*/
|
||||
|
||||
function _splitEntries($control, $transaction, $entries) {
|
||||
$this->prEnter(compact('control', 'transaction', 'entries'));
|
||||
|
||||
// Verify that we have a transaction and entries
|
||||
if (empty($transaction) ||
|
||||
($transaction['type'] !== 'CLOSE' && empty($entries)))
|
||||
@@ -523,8 +671,18 @@ class Transaction extends AppModel {
|
||||
$transaction['customer_id'] = $L->field('customer_id');
|
||||
}
|
||||
|
||||
if (!empty($transaction['account_id'])) {
|
||||
if (empty($transaction['ledger_id']))
|
||||
$transaction['ledger_id'] =
|
||||
$this->Account->currentLedgerID($transaction['account_id']);
|
||||
|
||||
if (empty($transaction['crdr']))
|
||||
$transaction['crdr'] = strtoupper($this->Account->fundamentalType
|
||||
($transaction['account_id']));
|
||||
}
|
||||
|
||||
// Some transactions do not have their statement entries
|
||||
// generated from this function, but they are instead
|
||||
// generated directly as part of the transaction, but are
|
||||
// created in the final steps during the reconciliation
|
||||
// phase by the assignCredits function. Keep track of
|
||||
// what type the statement entries _would_ have been, so
|
||||
@@ -534,7 +692,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.
|
||||
@@ -558,6 +716,10 @@ class Transaction extends AppModel {
|
||||
$entry['statement_entry_comment'] = null;
|
||||
}
|
||||
|
||||
if (empty($entry['crdr']) && !empty($transaction['crdr']))
|
||||
$entry['crdr'] = strtoupper($this->Account->fundamentalOpposite
|
||||
($transaction['crdr']));
|
||||
|
||||
// Priority goes to settings defined in $entry, but
|
||||
// use the control information as defaults.
|
||||
$entry += $control;
|
||||
@@ -576,7 +738,7 @@ class Transaction extends AppModel {
|
||||
array_intersect_key($entry,
|
||||
array_flip(array('account_id', 'amount')));
|
||||
$le2['ledger_id'] = $entry['new_ledger_id'];
|
||||
$le2['crdr'] = strtoupper($this->Account->fundamentalOpposite($le1['crdr']));
|
||||
$le2['crdr'] = strtoupper($this->Account->fundamentalType($le2['account_id']));
|
||||
$le2['comment'] = "Ledger Balance Forward (b/f)";
|
||||
}
|
||||
else {
|
||||
@@ -586,6 +748,15 @@ class Transaction extends AppModel {
|
||||
array_intersect_key($transaction,
|
||||
array_flip(array('ledger_id', 'account_id', 'crdr')));
|
||||
}
|
||||
|
||||
if ($entry['amount'] < 0 && !empty($entry['force_positive'])) {
|
||||
$le1['amount'] *= -1;
|
||||
$le2['amount'] *= -1;
|
||||
$entry += array('swap_crdr' => true);
|
||||
}
|
||||
|
||||
if (!empty($entry['swap_crdr']))
|
||||
list($le1['crdr'], $le2['crdr']) = array($le2['crdr'], $le1['crdr']);
|
||||
}
|
||||
else
|
||||
$le1 = $le1_tender = $le2 = null;
|
||||
@@ -620,84 +791,15 @@ 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);
|
||||
|
||||
$this->pr(20, compact('transaction', 'entries'));
|
||||
|
||||
// Move forward, verifying and saving everything.
|
||||
$ret = array();
|
||||
if (!$this->verifyTransaction($transaction, $entries))
|
||||
return $this->prReturn(array('error' => true) + $ret);
|
||||
|
||||
// Save transaction to the database
|
||||
$this->create();
|
||||
if (!$this->save($transaction))
|
||||
return $this->prReturn(array('error' => true) + $ret);
|
||||
$transaction_stamp = $this->field('stamp');
|
||||
|
||||
// Set up our return ids array
|
||||
$ret['transaction_id'] = $this->id;
|
||||
$ret['entries'] = array();
|
||||
$ret['error'] = false;
|
||||
|
||||
// Go through the entries
|
||||
foreach ($entries AS $e_index => &$entry) {
|
||||
// Ensure these items are null'ed out so we don't
|
||||
// accidentally pick up stale data.
|
||||
$le1 = $le1_tender = $le2 = $se = null;
|
||||
extract($entry);
|
||||
|
||||
if (!empty($le1) && !empty($le2)) {
|
||||
$le1['transaction_id'] = $le2['transaction_id'] = $ret['transaction_id'];
|
||||
if (isset($le1_tender))
|
||||
$le1_tender['customer_id'] = $transaction['customer_id'];
|
||||
$result = $this->LedgerEntry->DoubleEntry->addDoubleEntry($le1, $le2, $le1_tender);
|
||||
$ret['entries'][$e_index]['DoubleEntry'] = $result;
|
||||
if ($result['error']) {
|
||||
$ret['error'] = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($se)) {
|
||||
$se['transaction_id'] = $ret['transaction_id'];
|
||||
if (empty($se['effective_date']))
|
||||
$se['effective_date'] = $transaction_stamp;
|
||||
$result = $this->StatementEntry->addStatementEntry($se);
|
||||
$ret['entries'][$e_index]['StatementEntry'] = $result;
|
||||
if ($result['error']) {
|
||||
$ret['error'] = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($control['assign']) && !$ret['error']) {
|
||||
$result = $this->StatementEntry->assignCredits
|
||||
(null,
|
||||
(empty($control['assign_receipt']) ? null
|
||||
: $ret['transaction_id']),
|
||||
null,
|
||||
$assign_disbursement_type,
|
||||
$transaction['customer_id'],
|
||||
$transaction['lease_id']
|
||||
);
|
||||
|
||||
$ret['assigned'] = $result;
|
||||
if ($result['error'])
|
||||
$ret['error'] = true;
|
||||
}
|
||||
|
||||
$this->Customer->update($transaction['customer_id']);
|
||||
return $this->prReturn($ret);
|
||||
return $this->prReturn(compact('transaction', 'entries')
|
||||
+ array('vars' => compact('assign_disbursement_type'))
|
||||
+ array('error' => false));
|
||||
}
|
||||
|
||||
|
||||
@@ -726,7 +828,6 @@ class Transaction extends AppModel {
|
||||
'Entry' =>
|
||||
array(array('tender_id' => null,
|
||||
'account_id' => $this->Account->nsfAccountID(),
|
||||
'crdr' => 'DEBIT',
|
||||
'amount' => $tender['LedgerEntry']['amount'],
|
||||
))),
|
||||
$tender['Transaction']['account_id']);
|
||||
@@ -807,7 +908,6 @@ class Transaction extends AppModel {
|
||||
'include_statement_entry' => false,
|
||||
'amount' => $rollback['Transaction']['amount'],
|
||||
'account_id' => $this->Account->accountReceivableAccountID(),
|
||||
'crdr' => 'DEBIT',
|
||||
);
|
||||
|
||||
// Set the transaction amount to be negative
|
||||
@@ -848,9 +948,28 @@ class Transaction extends AppModel {
|
||||
if ($charge_result['error'])
|
||||
return $this->prReturn(array('error' => true) + $ret);
|
||||
|
||||
if (!empty($ret['rollback'])) {
|
||||
foreach ($ret['rollback']['entries'] AS $rentry) {
|
||||
if (!empty($rentry['DoubleEntry'])) {
|
||||
if (!empty($rentry['DoubleEntry']['error']))
|
||||
continue;
|
||||
|
||||
foreach (array('Entry1', 'Entry2') AS $n) {
|
||||
$entry = $rentry['DoubleEntry'][$n];
|
||||
if ($entry['data']['account_id'] == $this->Account->nsfAccountID()) {
|
||||
if (!empty($ret['nsf_ledger_entry_id']))
|
||||
$this->INTERNAL_ERROR("More than one NSF LE ID");
|
||||
|
||||
$ret['nsf_ledger_entry_id'] = $entry['ledger_entry_id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (empty($ret['rollback']['error']) && empty($ret['nsf_ledger_entry_id']))
|
||||
$this->INTERNAL_ERROR("NSF LE ID not found under rollback entries");
|
||||
|
||||
$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));
|
||||
}
|
||||
|
||||
@@ -885,18 +1004,16 @@ class Transaction extends AppModel {
|
||||
// These are all disbursements against the charge we're reversing
|
||||
$rollback =
|
||||
array('control' =>
|
||||
array('assign' => true,
|
||||
'assign_receipt' => true,
|
||||
'include_ledger_entry' => false,
|
||||
array('include_ledger_entry' => false,
|
||||
'include_statement_entry' => true,
|
||||
),
|
||||
|
||||
'Transaction' =>
|
||||
array('stamp' => $stamp,
|
||||
'type' => 'CREDIT_NOTE',
|
||||
'crdr' => 'DEBIT',
|
||||
'crdr' => 'CREDIT',
|
||||
'account_id' => $this->Account->accountReceivableAccountID(),
|
||||
'amount' => $charge['StatementEntry']['amount'],
|
||||
'account_id' => $charge['StatementEntry']['account_id'],
|
||||
'customer_id' => $charge['StatementEntry']['customer_id'],
|
||||
'lease_id' => null,
|
||||
'comment' => $comment,
|
||||
@@ -904,32 +1021,49 @@ class Transaction extends AppModel {
|
||||
|
||||
'Entry' => array());
|
||||
|
||||
foreach ($disb_entries['DisbursementEntry'] AS $disbursement) {
|
||||
$rollback['Entry'][] =
|
||||
array(
|
||||
'type' => $disbursement['type'],
|
||||
//'type' => 'REVERSAL',
|
||||
'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
|
||||
// Reverse the charge
|
||||
$rollback['Entry'][] =
|
||||
array('include_ledger_entry' => true,
|
||||
'include_statement_entry' => true,
|
||||
'type' => 'REVERSAL',
|
||||
'crdr' => 'CREDIT',
|
||||
'amount' => $rollback['Transaction']['amount'],
|
||||
'account_id' => $this->Account->accountReceivableAccountID(),
|
||||
'account_id' => $charge['StatementEntry']['account_id'],
|
||||
'amount' => $charge['StatementEntry']['amount'],
|
||||
'customer_id' => $charge['StatementEntry']['customer_id'],
|
||||
'lease_id' => $charge['StatementEntry']['lease_id'],
|
||||
'charge_entry_id' => $charge['StatementEntry']['id'],
|
||||
);
|
||||
|
||||
$customer_credit = 0;
|
||||
foreach ($disb_entries['DisbursementEntry'] AS $disbursement) {
|
||||
$rollback['Entry'][] =
|
||||
array(
|
||||
'include_ledger_entry' =>
|
||||
($disbursement['type'] !== 'DISBURSEMENT'),
|
||||
|
||||
'force_positive' => true,
|
||||
'type' => $disbursement['type'],
|
||||
'amount' => -1 * $disbursement['amount'],
|
||||
'account_id' =>
|
||||
($disbursement['type'] === 'DISBURSEMENT'
|
||||
? $this->Account->customerCreditAccountID()
|
||||
: $disbursement['account_id']),
|
||||
'customer_id' => $disbursement['customer_id'],
|
||||
'lease_id' => $disbursement['lease_id'],
|
||||
'charge_entry_id' => $disbursement['charge_entry_id'],
|
||||
);
|
||||
|
||||
if ($disbursement['type'] === 'DISBURSEMENT')
|
||||
$customer_credit += $disbursement['amount'];
|
||||
}
|
||||
|
||||
// Create an explicit surplus entry for the customer credit.
|
||||
// Do it BEFORE assigning credits to outstanding charges to
|
||||
// ensure that those charges are paid from the customer surplus
|
||||
// account thus and we don't end up with bizarre disbursements,
|
||||
// like having Rent paid from Damage (or whatever account the
|
||||
// reversed charge came from).
|
||||
$rollback['control']['assign'] = array($customer_credit, 'assign');
|
||||
|
||||
// Record the transaction, which will un-disburse previously
|
||||
// disbursed payments, and other similar work.
|
||||
if (count($rollback['Entry'])) {
|
||||
@@ -1030,7 +1164,17 @@ class Transaction extends AppModel {
|
||||
if (empty($query['fields']))
|
||||
$query['fields'] = array();
|
||||
|
||||
$stats = array();
|
||||
// Get the overall total
|
||||
$squery = $query;
|
||||
$squery['fields'][] = "SUM(Transaction.amount) AS total";
|
||||
$squery['fields'][] = "COUNT(Transaction.id) AS count";
|
||||
$stats = $this->find('first', $squery);
|
||||
if (empty($stats))
|
||||
return $this->prReturn(array());
|
||||
$stats = $stats[0];
|
||||
unset($stats[0]);
|
||||
|
||||
|
||||
foreach ($this->hasMany AS $table => $association) {
|
||||
// Only calculate stats for *Entry types
|
||||
if (!preg_match("/Entry$/", $table) &&
|
||||
@@ -1069,6 +1213,11 @@ class Transaction extends AppModel {
|
||||
unset($stats[$table][0]);
|
||||
}
|
||||
|
||||
// Add summary data, which may or may not be useful
|
||||
// or even meaningful, depending on what the caller
|
||||
// has queried (it's up to them to make that decision).
|
||||
$stats['undisbursed'] = $stats['total'] - $stats['StatementEntry']['disbursements'];
|
||||
|
||||
return $this->prReturn($stats);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user