Re-implemented the deposit functionality. This is mostly working, although I'd like to get customer added to the tenders table, and probably change to a single deposit ledger entry for each tender type. A single entry would require that all tender types have been recorded to the same account, something that isn't mandated at the present, but is likely to be true most of the time. Perhaps they could just be grouped by account id, which should work in all cases and yet align with tender type 99% of the time. I'll have to think about it.
git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@412 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
@@ -290,16 +290,20 @@ class Account extends AppModel {
|
||||
* with the old balance carried forward.
|
||||
*/
|
||||
function closeCurrentLedger($id = null, $close_id = null) {
|
||||
$contain = array('CurrentLedger' => array('fields' => array('CurrentLedger.id')));
|
||||
$ret = array();
|
||||
|
||||
if (!$close_id) {
|
||||
$close = new Close();
|
||||
$close->create();
|
||||
if (!$close->save(array('stamp' => null), false)) {
|
||||
return false;
|
||||
}
|
||||
$close_id = $close->id;
|
||||
if (!$close->save(array('stamp' => null), false))
|
||||
return array('error' => true) + $ret;
|
||||
$ret['close_id'] = $close->id;
|
||||
}
|
||||
else {
|
||||
$ret['close_id'] = $close_id;
|
||||
}
|
||||
|
||||
$contain = array('CurrentLedger' => array('fields' => array('CurrentLedger.id')));
|
||||
|
||||
$this->cacheQueries = true;
|
||||
$account = $this->find('all', array
|
||||
@@ -312,10 +316,12 @@ class Account extends AppModel {
|
||||
//pr(compact('id', 'account'));
|
||||
|
||||
foreach ($account AS $acct) {
|
||||
if (!$this->Ledger->closeLedger($acct['CurrentLedger']['id'], $close_id))
|
||||
return false;
|
||||
if (!$this->Ledger->closeLedger($acct['CurrentLedger']['id'], $ret['close_id']))
|
||||
return array('error' => true) + $ret;
|
||||
$ret['ledgers'][] = $acct['CurrentLedger']['id'];
|
||||
}
|
||||
return true;
|
||||
|
||||
return $ret + array('error' => false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -63,7 +63,12 @@ class TenderType extends AppModel {
|
||||
$types = $this->find('all', $query);
|
||||
$this->cacheQueries = false;
|
||||
|
||||
return $types;
|
||||
// Rearrange to be of the form (id => name)
|
||||
$result = array();
|
||||
foreach ($types AS $type)
|
||||
$result[$type['TenderType']['id']] = $type['TenderType']['name'];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,4 +83,33 @@ class TenderType extends AppModel {
|
||||
return $this->nameToID('Check');
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: stats
|
||||
* - Returns the stats for the given tender type
|
||||
*/
|
||||
|
||||
function stats($id = null, $query = null) {
|
||||
if (!$id)
|
||||
return null;
|
||||
|
||||
$this->queryInit($query);
|
||||
|
||||
if (!isset($query['link']['Tender']))
|
||||
$query['link']['Tender'] = array('fields' => array());
|
||||
if (!isset($query['link']['Tender']['LedgerEntry']))
|
||||
$query['link']['Tender']['LedgerEntry'] = array('fields' => array());
|
||||
|
||||
$query['fields'][] = "SUM(COALESCE(LedgerEntry.amount,0)) AS 'total'";
|
||||
$query['fields'][] = "SUM(IF(deposit_transaction_id IS NULL, COALESCE(LedgerEntry.amount,0), 0)) AS 'undeposited'";
|
||||
$query['fields'][] = "SUM(IF(deposit_transaction_id IS NULL, 0, COALESCE(LedgerEntry.amount,0))) AS 'deposited'";
|
||||
$query['fields'][] = "SUM(IF(nsf_transaction_id IS NULL, 0, COALESCE(LedgerEntry.amount,0))) AS 'nsf'";
|
||||
|
||||
$this->id = $id;
|
||||
$stats = $this->find('first', $query);
|
||||
return $stats[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,7 +45,9 @@ class Transaction extends AppModel {
|
||||
$invoice =& $data['Transaction'];
|
||||
$invoice['type'] = 'INVOICE';
|
||||
$invoice['crdr'] = 'DEBIT';
|
||||
$invoice['account_id'] = $this->Account->accountReceivableAccountID();
|
||||
$invoice['account_id'] = $this->Account->accountReceivableAccountID();
|
||||
$invoice['customer_id'] = $customer_id;
|
||||
$invoice['lease_id'] = $lease_id;
|
||||
|
||||
// Go through the statement entries and flag as charges
|
||||
foreach ($data['Entry'] AS &$entry) {
|
||||
@@ -53,7 +55,7 @@ class Transaction extends AppModel {
|
||||
$entry['crdr'] = 'CREDIT';
|
||||
}
|
||||
|
||||
$ids = $this->addTransaction($data, $customer_id, $lease_id);
|
||||
$ids = $this->addTransaction($data);
|
||||
if (isset($ids['transaction_id']))
|
||||
$ids['invoice_id'] = $ids['transaction_id'];
|
||||
|
||||
@@ -69,15 +71,16 @@ class Transaction extends AppModel {
|
||||
*/
|
||||
|
||||
function addReceipt($data, $customer_id, $lease_id = null) {
|
||||
// Establish the transaction as an receipt
|
||||
// Establish the transaction as a receipt
|
||||
$receipt =& $data['Transaction'];
|
||||
$receipt['type'] = 'RECEIPT';
|
||||
$receipt['crdr'] = 'CREDIT';
|
||||
$receipt['account_id'] = $this->Account->accountReceivableAccountID();
|
||||
$receipt['account_id'] = $this->Account->accountReceivableAccountID();
|
||||
$receipt['customer_id'] = $customer_id;
|
||||
$receipt['lease_id'] = $lease_id;
|
||||
|
||||
// Go through the statement entries and flag as payments
|
||||
foreach ($data['Entry'] AS &$entry) {
|
||||
$entry['type'] = 'PAYMENT';
|
||||
$entry['crdr'] = 'DEBIT';
|
||||
if (isset($entry['Tender']['tender_type_id'])) {
|
||||
$entry['account_id'] = $this->LedgerEntry->Tender->TenderType->
|
||||
@@ -85,7 +88,7 @@ class Transaction extends AppModel {
|
||||
}
|
||||
}
|
||||
|
||||
$ids = $this->addTransaction($data, $customer_id, $lease_id);
|
||||
$ids = $this->addTransaction($data);
|
||||
if (isset($ids['transaction_id']))
|
||||
$ids['receipt_id'] = $ids['transaction_id'];
|
||||
|
||||
@@ -93,6 +96,56 @@ class Transaction extends AppModel {
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: addDeposit
|
||||
* - Adds a new bank deposit
|
||||
*/
|
||||
|
||||
function addDeposit($data, $account_id) {
|
||||
// Establish the transaction as a deposit
|
||||
$deposit =& $data['Transaction'];
|
||||
$deposit['type'] = 'DEPOSIT';
|
||||
$deposit['crdr'] = 'DEBIT';
|
||||
$deposit['account_id'] = $account_id;
|
||||
$deposit['customer_id'] = null;
|
||||
$deposit['lease_id'] = null;
|
||||
|
||||
// Go through the statement entries and flag as credits
|
||||
foreach ($data['Entry'] AS &$entry) {
|
||||
$entry['crdr'] = 'CREDIT';
|
||||
}
|
||||
|
||||
// For some reason, $data is being modified by the
|
||||
// addTransaction call, even though we're not passing by
|
||||
// reference. Not all items in $data['Entry'] are being
|
||||
// stomped on... only the last one in the list :-/
|
||||
// Save off all the tender ids now, before calling
|
||||
// addTransaction, to make sure we don't lose any.
|
||||
$tender_ids = array_map(create_function('$item',
|
||||
/* 'if (!isset($item))' . */
|
||||
/* ' pr("NO ITEM");' . */
|
||||
/* 'if (!isset($item["tender_id"]))' . */
|
||||
/* ' pr(array("BAD ITEM" => compact("item")));' . */
|
||||
'return $item["tender_id"];'),
|
||||
$data['Entry']);
|
||||
|
||||
$ids = $this->addTransaction($data);
|
||||
if (isset($ids['transaction_id']))
|
||||
$ids['deposit_id'] = $ids['transaction_id'];
|
||||
|
||||
if (!empty($ids['deposit_id'])) {
|
||||
$this->LedgerEntry->Tender->updateAll
|
||||
(array('Tender.deposit_transaction_id' => $ids['deposit_id']),
|
||||
array('Tender.id' => $tender_ids)
|
||||
);
|
||||
}
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
@@ -126,7 +179,8 @@ class Transaction extends AppModel {
|
||||
/* => "Double Entry verification failed")); */
|
||||
return false;
|
||||
}
|
||||
if (!$this->StatementEntry->verifyStatementEntry($se)) {
|
||||
if ($transaction['type'] == 'INVOICE' &&
|
||||
!$this->StatementEntry->verifyStatementEntry($se)) {
|
||||
/* pr(array("Transaction::verifyTransaction()" */
|
||||
/* => "Statement Entry verification failed")); */
|
||||
return false;
|
||||
@@ -195,29 +249,28 @@ class Transaction extends AppModel {
|
||||
*
|
||||
*/
|
||||
|
||||
function addTransaction($data, $customer_id, $lease_id = null) {
|
||||
function addTransaction($data) {
|
||||
/* pr(array("Transaction::addTransaction()" */
|
||||
/* => compact('data', 'customer_id', 'lease_id'))); */
|
||||
|
||||
if (!isset($data['Transaction']) || !isset($data['Entry']))
|
||||
// Verify that we have a transaction and entries
|
||||
if (empty($data['Transaction']) || empty($data['Entry']))
|
||||
return array('error' => true);
|
||||
|
||||
// Automatically figure out the customer if we have the lease
|
||||
if (!empty($lease_id) && empty($customer_id)) {
|
||||
$L = new Lease();
|
||||
$L->recursive = -1;
|
||||
$lease = $L->read(null, $lease_id);
|
||||
$customer_id = $lease['Lease']['customer_id'];
|
||||
}
|
||||
|
||||
// Set the customer based on caller request, and set
|
||||
// ledger ID as the current ledger of the specified account
|
||||
// Extract the transaction to a local variable
|
||||
$transaction = $data['Transaction'];
|
||||
$transaction['customer_id'] = $customer_id;
|
||||
$transaction['lease_id'] = $lease_id;
|
||||
|
||||
// set ledger ID as the current ledger of the specified account
|
||||
$transaction['ledger_id'] =
|
||||
$this->Account->currentLedgerID($transaction['account_id']);
|
||||
|
||||
// Automatically figure out the customer if we have the lease
|
||||
if (!empty($transaction['lease_id']) && empty($transaction['customer_id'])) {
|
||||
$L = new Lease();
|
||||
$L->recursive = -1;
|
||||
$lease = $L->read(null, $transaction['lease_id']);
|
||||
$transaction['customer_id'] = $lease['Lease']['customer_id'];
|
||||
}
|
||||
|
||||
// Break each entry out of the combined statement/ledger entry
|
||||
// and into individual entries appropriate for saving. While
|
||||
@@ -234,13 +287,13 @@ class Transaction extends AppModel {
|
||||
|
||||
// Set up our comments, possibly using the default 'comment' field
|
||||
if (empty($entry['ledger_entry_comment'])) {
|
||||
if (!empty($entry['comment']) && $entry['type'] === 'PAYMENT')
|
||||
if ($transaction['type'] != 'INVOICE' && !empty($entry['comment']))
|
||||
$entry['ledger_entry_comment'] = $entry['comment'];
|
||||
else
|
||||
$entry['ledger_entry_comment'] = null;
|
||||
}
|
||||
if (empty($entry['statement_entry_comment'])) {
|
||||
if (!empty($entry['comment']) && $entry['type'] === 'CHARGE')
|
||||
if ($transaction['type'] == 'INVOICE' && !empty($entry['comment']))
|
||||
$entry['statement_entry_comment'] = $entry['comment'];
|
||||
else
|
||||
$entry['statement_entry_comment'] = null;
|
||||
@@ -260,14 +313,18 @@ class Transaction extends AppModel {
|
||||
array_intersect_key($entry,
|
||||
array_flip(array('amount')));
|
||||
|
||||
// Create a statement entry
|
||||
$se =
|
||||
array_intersect_key($transaction,
|
||||
array_flip(array('customer_id', 'lease_id'))) +
|
||||
array_intersect_key($entry,
|
||||
array_flip(array('type', 'account_id', 'amount',
|
||||
if ($transaction['type'] == 'INVOICE') {
|
||||
// Create a statement entry
|
||||
// (PAYMENTS will have statement entries created below, when
|
||||
// assigning credits, and DEPOSITS don't have statement entries)
|
||||
$se =
|
||||
array_intersect_key($transaction,
|
||||
array_flip(array('customer_id', 'lease_id'))) +
|
||||
array_intersect_key($entry,
|
||||
array_flip(array('type', 'account_id', 'amount',
|
||||
'effective_date', 'through_date', 'due_date')));
|
||||
$se['comment'] = $entry['statement_entry_comment'];
|
||||
$se['comment'] = $entry['statement_entry_comment'];
|
||||
}
|
||||
|
||||
// Replace combined entry with our new individual entries
|
||||
$entry = compact('le1', 'le1_tender', 'le2', 'se');
|
||||
@@ -275,7 +332,7 @@ class Transaction extends AppModel {
|
||||
|
||||
// Move forward, verifying and saving everything.
|
||||
$ret = array();
|
||||
if (!$this->verifyTransaction($transaction, $data['Entry'], $customer_id, $lease_id))
|
||||
if (!$this->verifyTransaction($transaction, $data['Entry']))
|
||||
return array('error' => true) + $ret;
|
||||
|
||||
/* pr(array('Transaction::addTransaction' => */
|
||||
@@ -295,10 +352,7 @@ class Transaction extends AppModel {
|
||||
// Go through the entered charges
|
||||
foreach ($data['Entry'] AS $e_index => &$entry) {
|
||||
extract($entry);
|
||||
$le1['transaction_id'] = $ret['transaction_id'];
|
||||
$le2['transaction_id'] = $ret['transaction_id'];
|
||||
$se['transaction_id'] = $ret['transaction_id'];
|
||||
|
||||
$le1['transaction_id'] = $le2['transaction_id'] = $ret['transaction_id'];
|
||||
$result = $this->LedgerEntry->DoubleEntry->addDoubleEntry($le1, $le2, $le1_tender);
|
||||
$ret['entries'][$e_index]['DoubleEntry'] = $result;
|
||||
if ($result['error']) {
|
||||
@@ -306,9 +360,8 @@ class Transaction extends AppModel {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($se['type'] === 'CHARGE') {
|
||||
// CHARGES need to be added as statement entries.
|
||||
// PAYMENTS will be added later after reconciliation
|
||||
if (isset($se)) {
|
||||
$se['transaction_id'] = $ret['transaction_id'];
|
||||
$result = $this->StatementEntry->addStatementEntry($se);
|
||||
$ret['entries'][$e_index]['StatementEntry'] = $result;
|
||||
if ($result['error']) {
|
||||
@@ -318,18 +371,13 @@ class Transaction extends AppModel {
|
||||
}
|
||||
}
|
||||
|
||||
// REVISIT <AP>: 20090723
|
||||
// Now that we have new entries, WE MUST RECONCILE
|
||||
// THE CHARGES TO CUSTOMER ACCOUNT BALANCE! This
|
||||
// is the only way "payments" are generated, and
|
||||
// the only way to make use of a positive customer
|
||||
// balance if new charges have been entered.
|
||||
|
||||
if (!$ret['error']) {
|
||||
if (($transaction['type'] == 'INVOICE' ||
|
||||
$transaction['type'] == 'RECEIPT') &&
|
||||
!$ret['error']) {
|
||||
$result = $this->StatementEntry->assignCredits
|
||||
(array('link' => array('Customer'),
|
||||
'conditions' => array('Customer.id' => $customer_id)),
|
||||
($transaction['type'] === 'RECEIPT'
|
||||
($transaction['type'] == 'RECEIPT'
|
||||
? $ret['transaction_id']
|
||||
: null));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user