Got the ledger closings to work again. This seems to work ok, although I notice closing the ledger after deposit results in a balance forward entry of $0.00 . I'll work on it next

git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716/site@421 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
abijah
2009-07-30 01:59:10 +00:00
parent eb209a455b
commit 25e3c87213
10 changed files with 181 additions and 174 deletions

View File

@@ -111,7 +111,11 @@ class AccountsController extends AppController {
*/
function newledger($id = null) {
if (!$this->Account->closeCurrentLedger($id)) {
$result = $this->Account->closeCurrentLedgers($id);
if ($result['error']) {
pr(compact('result'));
die("Unable to create new ledger.");
$this->Session->setFlash(__('Unable to create new Ledger.', true));
}
if ($id)
@@ -172,8 +176,8 @@ class AccountsController extends AppController {
array('fields' => array('id', 'sequence', 'name')),
'Ledger' =>
array('Close' => array
('order' => array('Close.stamp' => 'DESC'))),
array('CloseTransaction' => array
('order' => array('CloseTransaction.stamp' => 'DESC'))),
),
'conditions' => array(array('Account.id' => $id)),
)

View File

@@ -63,7 +63,7 @@ class LedgersController extends AppController {
array(// Models
'Account',
'LedgerEntry',
'Close',
'CloseTransaction',
),
);
}
@@ -79,10 +79,10 @@ class LedgersController extends AppController {
$conditions = parent::gridDataConditions($params, $model);
if ($params['action'] === 'current') {
$conditions[] = array('NOT' => array('Ledger.closed'));
$conditions[] = array('Ledger.close_transaction_id' => null);
}
elseif ($params['action'] === 'closed') {
$conditions[] = 'Ledger.closed';
$conditions[] = array('Ledger.close_transaction_id !=' => null);
}
return $conditions;

View File

@@ -162,53 +162,60 @@ class TransactionsController extends AppController {
//pr($this->data);
// Start building data for our deposit
$deposit = array('close_id' => null,
'Transaction' => array(),
'Entry' => array());
// Go through each type of tender presented to the user
// Determine which are to be deposited, and which are to
// have their corresponding account ledgers closed.
$type_ids = $close_type_ids = array();
foreach ($this->data['TenderType'] AS $type_id => $type) {
if (!$type['checked'])
continue;
$type_ids[] = $type_id;
$tenders = $this->Transaction->DepositTender->find
('all',
array('contain' => array
('TenderType', 'LedgerEntry'),
'conditions' => array(array('DepositTender.deposit_transaction_id' => null),
array('TenderType.id' => $type_id)),
));
// Prepare for the actual deposit
foreach ($tenders AS $tender) {
$deposit['Entry'][] =
array('tender_id' => $tender['DepositTender']['id'],
'account_id' => $tender['LedgerEntry']['account_id'],
'amount' => $tender['LedgerEntry']['amount'],
);
}
if (!empty($type['close']) && !empty($tenders)) {
// Close the associated ledger
$result = $this->Transaction->Account->closeCurrentLedger
($tenders[0]['TenderType']['account_id'], $deposit['close_id']);
if (!$result['error'] && empty($deposit['close_id']))
$deposit['close_id'] = $result['close_id'];
}
if (!empty($type['close']))
$close_type_ids[] = $type_id;
}
// Find all items which are actually to be deposited
$tenders = $this->Transaction->DepositTender->find
('all',
array('contain' => array('TenderType', 'LedgerEntry'),
'conditions' => array(array('DepositTender.deposit_transaction_id' => null),
array('TenderType.id' => $type_ids)),
));
// Prepare for the deposit by building a list of entries
$deposit = array('Transaction' => array(), 'Entry' => array());
foreach ($tenders AS $tender) {
$deposit['Entry'][] =
array('tender_id' => $tender['DepositTender']['id'],
'account_id' => $tender['LedgerEntry']['account_id'],
'amount' => $tender['LedgerEntry']['amount'],
);
}
// OK, perform the deposit and associated accounting
$result = $this->Transaction->addDeposit
($deposit, $this->data['Deposit']['Account']['id']);
//pr(compact('deposit', 'result'));
// Now find out which accounts are to be closed...
$accounts = $this->Transaction->DepositTender->find
('all',
array('contain' => array('TenderType.account_id'),
'conditions' => array(array('TenderType.id' => $close_type_ids)),
));
// ... and close them
$this->Transaction->Account->closeCurrentLedgers
(array_map(create_function('$item', 'return $item["TenderType"]["account_id"];'), $accounts));
// Look out for errors
if ($result['error']) {
$this->Session->setFlash(__('Unable to Create Deposit', true));
$this->redirect(array('controller' => 'tenders', 'action'=>'deposit'));
}
// Present the deposit slip to the user
$this->redirect(array('controller' => 'transactions',
'action' => 'deposit_slip',
$result['transaction_id']));

View File

@@ -9,8 +9,8 @@ class Account extends AppModel {
// engine specific code. However, it doesn't
// work with the Linkable behavior. I need to
// look into that, just not right now.
//'conditions' => array('CurrentLedger.close_id' => null),
'conditions' => array('CurrentLedger.close_id IS NULL'),
//'conditions' => array(array('CurrentLedger.close_transaction_id' => null)),
'conditions' => array('CurrentLedger.close_transaction_id IS NULL'),
),
);
@@ -72,7 +72,7 @@ class Account extends AppModel {
else
$fund = $this->fundamentalType($id_or_type);
if ($fund == 'debit')
if (strtolower($fund) == 'debit')
return 'credit';
return 'debit';
@@ -289,39 +289,24 @@ class Account extends AppModel {
* - Closes the current account ledger, and opens a new one
* with the old balance carried forward.
*/
function closeCurrentLedger($id = null, $close_id = null) {
$ret = array();
if (!$close_id) {
$close = new Close();
$close->create();
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')));
function closeCurrentLedgers($ids = null) {
$this->cacheQueries = true;
$account = $this->find('all', array
('contain' => $contain,
('contain' => array('CurrentLedger.id'),
'fields' => array(),
'conditions' =>
$id ? array(array('Account.id' => $id)) : array()
'conditions' => (empty($ids)
? array()
: array(array('Account.id' => $ids)))
));
$this->cacheQueries = false;
//pr(compact('id', 'account'));
foreach ($account AS $acct) {
if (!$this->Ledger->closeLedger($acct['CurrentLedger']['id'], $ret['close_id']))
return array('error' => true) + $ret;
$ret['ledgers'][] = $acct['CurrentLedger']['id'];
}
$ledger_ids = array();
foreach ($account AS $acct)
$ledger_ids[] = $acct['CurrentLedger']['id'];
return $ret + array('error' => false);
return $this->Ledger->closeLedgers($ledger_ids);
}
@@ -744,50 +729,6 @@ class Account extends AppModel {
}
/**************************************************************************
**************************************************************************
**************************************************************************
* function: closeAndDeposit
* - Closes the current set of ledgers, transferring
* their balances to specified ledger.
*/
function closeAndDeposit($set, $deposit_account_id) {
$close = new Close();
$close->create();
if (!$close->save(array('stamp' => null, 'comment' => 'Deposit'), false)) {
return false;
}
$transaction = array();
foreach ($set AS $ledger) {
// REVISIT <AP>: 20090710
// If the user said to include a ledger in the
// set, should we really be excluding it?
if ($ledger['total'] == 0)
continue;
$ids = $this->postLedgerEntry
($transaction,
null,
array('debit_account_id' => $deposit_account_id,
'credit_ledger_id' => $ledger['id'],
'amount' => $ledger['total']),
// Reconcile the account for cash/check/etc,
// which is the credit side of this entry.
array('credit' => $ledger['entries']));
//pr(compact('ids'));
if ($ids['error'])
die("closeAndDeposit : postLedgerEntry returned error!");
$transaction = array_intersect_key($ids, array('transaction_id'=>1));
$this->Ledger->closeLedger($ledger['id'], $close->id);
}
}
/**************************************************************************
**************************************************************************
**************************************************************************

View File

@@ -4,7 +4,7 @@ class Ledger extends AppModel {
var $belongsTo = array(
'Account',
'PriorLedger' => array('className' => 'Ledger'),
'Close',
'CloseTransaction' => array('className' => 'Transaction'),
);
var $hasMany = array(
@@ -48,57 +48,49 @@ class Ledger extends AppModel {
* function: closeLedger
* - Closes the current ledger, and returns a fresh one
*/
function closeLedger($id, $close_id) {
$this->recursive = -1;
function closeLedgers($ids) {
$ret = array('new_ledger_ids' => array());
$stamp = date('Y-m-d G:i:s');
$this->id = $id;
$this->read();
$this->data['Ledger']['close_id'] = $close_id;
$this->save($this->data, false);
$entries = array();
foreach ($ids AS $id) {
// Query stats to get the balance forward
$stats = $this->stats($id);
$stats = $this->stats($id);
// Populate fields from the current ledger
$this->recursive = -1;
$this->id = $id;
$this->read();
$this->read();
$this->data['Ledger']['id'] = null;
$this->data['Ledger']['close_id'] = null;
$this->data['Ledger']['prior_ledger_id'] = $id;
$this->data['Ledger']['comment'] = null;
++$this->data['Ledger']['sequence'];
$this->id = null;
$this->save($this->data, false);
//pr($this->data);
// Build a new ledger to replace the current one
$this->data['Ledger']['id'] = null;
$this->data['Ledger']['close_transaction_id'] = null;
$this->data['Ledger']['prior_ledger_id'] = $id;
$this->data['Ledger']['comment'] = null;
++$this->data['Ledger']['sequence'];
$this->data['Ledger']['name'] =
($this->data['Ledger']['account_id'] .
'-' .
$this->data['Ledger']['sequence']);
if ($stats['balance'] == 0)
return $this->id;
// Save the new ledger
$this->id = null;
if (!$this->save($this->data, false))
return array('error' => true, 'new_ledger_data' => $this->data) + $ret;
$ret['new_ledger_ids'][] = $this->id;
$this->read();
$ftype = $this->Account->fundamentalType($this->data['Ledger']['account_id']);
$otype = $this->Account->fundamentalOpposite($ftype);
// Create a transaction for balance transfer
$transaction = new Transaction();
$transaction->create();
if (!$transaction->save(array(), false)) {
return null;
$entries[] = array('old_ledger_id' => $id,
'new_ledger_id' => $this->id,
'amount' => $stats['balance']);
}
// Create an entry to carry the balance forward
$carry_entry_data = array
($ftype.'_ledger_id' => $this->id,
$otype.'_ledger_id' => $id,
'transaction_id' => $transaction->id,
'amount' => $stats['balance'],
'comment' => "Ledger Balance Forward",
);
// Perform the close
$result = $this->Transaction->addClose(array('Transaction' => array(),
'Ledger' => $entries));
$ret['Transaction'] = $result;
if ($result['error'])
return array('error' => true) + $ret;
$carry_entry = new LedgerEntry();
$carry_entry->create();
if (!$carry_entry->save($carry_entry_data, false)) {
return null;
}
return $this->id;
return $ret + array('error' => false);
}

View File

@@ -148,6 +148,60 @@ class Transaction extends AppModel {
}
/**************************************************************************
**************************************************************************
**************************************************************************
* function: addClose
* - Adds a new transaction for closing ledgers
*/
function addClose($data) {
// Establish the transaction as a close
$close =& $data['Transaction'];
$close['type'] = 'CLOSE';
$close['account_id'] = null;
$close['customer_id'] = null;
$close['lease_id'] = null;
$ledger_ids = array();
foreach ($data['Ledger'] AS $ledger) {
$ledger_id = $ledger['old_ledger_id'];
$new_ledger_id = $ledger['new_ledger_id'];
$amount = $ledger['amount'];
$account_id = $this->Account->Ledger->accountID($ledger_id);
$crdr = strtoupper($this->Account->fundamentalOpposite($account_id));
$comment = "Ledger Carry Forward (c/f)";
// Save the ledger ID for later, to mark it as closed
$ledger_ids[] = $ledger_id;
// No need to generate ledger entries if there is no balance
if (empty($ledger['amount']))
continue;
// Add an entry to carry the ledger balance forward
$data['Entry'][] = compact('account_id', 'ledger_id', 'new_ledger_id',
'crdr', 'amount', 'comment');
}
unset($data['Ledger']);
// Add the transaction and carry forward balances
$ids = $this->addTransaction($data);
if (isset($ids['transaction_id']))
$ids['close_id'] = $ids['transaction_id'];
// Mark the older ledgers as closed
if (!empty($ids['close_id'])) {
$this->LedgerEntry->Ledger->updateAll
(array('Ledger.close_transaction_id' => $ids['close_id']),
array('Ledger.id' => $ledger_ids)
);
}
return $ids;
}
/**************************************************************************
**************************************************************************
**************************************************************************
@@ -157,12 +211,13 @@ class Transaction extends AppModel {
*/
function verifyTransaction($transaction, $entries) {
/* pr(array("Transaction::verifyTransaction()" */
/* => compact('transaction', 'entries', 'customer_id', 'lease_id'))); */
/* => compact('transaction', 'entries'))); */
// Verify required Transaction data is present
if (empty($transaction['type']) ||
empty($transaction['account_id']) ||
empty($transaction['crdr']) ||
($transaction['type'] != 'CLOSE'
&& (empty($transaction['account_id']) ||
empty($transaction['crdr']))) ||
(in_array($transaction['type'], array('INVOICE', 'RECEIPT'))
&& empty($transaction['customer_id'])) ||
(in_array($transaction['type'], array('INVOICE'))
@@ -304,16 +359,26 @@ class Transaction extends AppModel {
// Create one half of the Double Ledger Entry (and the Tender)
$le1 =
array_intersect_key($entry,
array_flip(array('account_id', 'crdr', 'amount')));
array_flip(array('ledger_id', 'account_id', 'crdr', 'amount')));
$le1['comment'] = $entry['ledger_entry_comment'];
$le1_tender = isset($entry['Tender']) ? $entry['Tender'] : null;
// Create the second half of the Double Ledger Entry
$le2 =
array_intersect_key($transaction,
array_flip(array('account_id', 'crdr'))) +
array_intersect_key($entry,
array_flip(array('amount')));
if ($transaction['type'] == 'CLOSE') {
$le2 =
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['comment'] = "Ledger Balance Forward (b/f)";
}
else {
$le2 =
array_intersect_key($transaction,
array_flip(array('ledger_id', 'account_id', 'crdr'))) +
array_intersect_key($entry,
array_flip(array('amount')));
}
if ($transaction['type'] == 'INVOICE') {
// Create a statement entry

View File

@@ -81,8 +81,8 @@ echo $this->element('ledger_entries', array
'caption' => ("Current Ledger: " .
"(". $current_ledger['name'] .")"),
'filter' => array('ledger_id' => $current_ledger['id']),
'exclude' => array('Account', 'Amount', 'Cr/Dr', 'Debit', 'Credit'),
'include' => array('Balance', 'Sub-Total'),
'exclude' => array('Account', 'Amount', 'Cr/Dr', 'Balance'),
'include' => array('Debit', 'Credit', 'Sub-Total'),
)));
@@ -98,8 +98,8 @@ echo $this->element('ledger_entries', array
'grid_setup' => array('hiddengrid' => true),
'caption' => "Entire Ledger",
'filter' => array('account_id' => $account['id']),
'exclude' => array('Account', 'Amount', 'Cr/Dr', 'Debit', 'Credit'),
'include' => array('Balance', 'Sub-Total'),
'exclude' => array('Account', 'Amount', 'Cr/Dr', 'Balance'),
'include' => array('Debit', 'Credit', 'Sub-Total'),
)));

View File

@@ -5,8 +5,8 @@ $cols = array();
$cols['ID'] = array('index' => 'id_sequence', 'formatter' => 'id');
$cols['Name'] = array('index' => 'Ledger.name', 'formatter' => 'name');
$cols['Account'] = array('index' => 'Account.name', 'formatter' => 'longname');
$cols['Open Date'] = array('index' => 'PriorClose.stamp', 'formatter' => 'date');
$cols['Close Date'] = array('index' => 'Close.stamp', 'formatter' => 'date');
$cols['Open Date'] = array('index' => 'PriorCloseTransaction.stamp', 'formatter' => 'date');
$cols['Close Date'] = array('index' => 'CloseTransaction.stamp', 'formatter' => 'date');
$cols['Comment'] = array('index' => 'Ledger.comment', 'formatter' => 'comment');
$cols['Entries'] = array('index' => 'entries', 'formatter' => 'number');
$cols['Debits'] = array('index' => 'debits', 'formatter' => 'currency');

View File

@@ -10,7 +10,7 @@ echo '<div class="ledger view">' . "\n";
*/
$account = $ledger['Account'];
//$close = $ledger['Close'];
//$close = $ledger['CloseTransaction'];
if (isset($ledger['Ledger']))
$ledger = $ledger['Ledger'];
@@ -23,7 +23,7 @@ $rows[] = array('Account', $html->link($account['name'],
'action' => 'view',
$account['id'])));
$rows[] = array('Sequence', $ledger['sequence']);
$rows[] = array('Status', $ledger['close_id'] ? 'Closed' : 'Open');
$rows[] = array('Status', $ledger['close_transaction_id'] ? 'Closed' : 'Open');
$rows[] = array('Comment', $ledger['comment']);
echo $this->element('table',
@@ -70,10 +70,8 @@ echo $this->element('ledger_entries', array
'config' => array
('caption' => "Ledger Entries",
'filter' => array('ledger_id' => $ledger['id']),
'exclude' => array('Ledger', 'Account', 'Amount', 'Cr/Dr', 'Debit', 'Credit'),
'include' => array('Balance', 'Sub-Total'),
/* 'exclude' => array('Ledger', 'Account', 'Amount', 'Cr/Dr', 'Balance'), */
/* 'include' => array('Debit', 'Credit', 'Sub-Total'), */
'exclude' => array('Ledger', 'Account', 'Amount', 'Cr/Dr', 'Balance'),
'include' => array('Debit', 'Credit', 'Sub-Total'),
)));

View File

@@ -34,7 +34,7 @@ foreach ($depositTypes AS $type) {
echo "\n";
echo $form->input("TenderType.{$type['id']}.close",
array('type' => 'hidden',
'value' => false,
'value' => true,
));
echo "\n";