Implemented a bank deposit routine, to transfer funds out of the till and into the bank.

git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@196 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
abijah
2009-07-01 11:10:57 +00:00
parent 44df78e69f
commit 8d87a0698c
6 changed files with 316 additions and 19 deletions

View File

@@ -838,7 +838,9 @@ CREATE TABLE `pmgr_accounts` (
-- For LIABILITY, EQUITY, and INCOME, the opposite
-- is true, with reconciliations posted, under
-- normal circumstances, when a debit occurs.
`trackable` INT UNSIGNED DEFAULT 1,
`trackable` TINYINT(1) UNSIGNED NOT NULL DEFAULT 1,
`tillable` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Does manager collect by hand?
`depositable` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Does this account receive deposits?
-- Security Level
`level` INT UNSIGNED DEFAULT 1,
@@ -853,23 +855,23 @@ CREATE TABLE `pmgr_accounts` (
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
LOCK TABLES `pmgr_accounts` WRITE;
INSERT INTO `pmgr_accounts` (`type`, `name`, `trackable`)
INSERT INTO `pmgr_accounts` (`type`, `name`, `tillable`, `depositable`)
VALUES
('ASSET', 'A/R', 1),
('ASSET', 'Invoice', 1),
('ASSET', 'Receipt', 1),
('LIABILITY', 'A/P', 1),
('LIABILITY', 'Tax', 1),
('LIABILITY', 'Customer Credit', 1),
('ASSET', 'Bank', 1),
('ASSET', 'Cash', 1),
('ASSET', 'Check', 1),
('ASSET', 'Money Order', 1),
('LIABILITY', 'Security Deposit', 1),
('INCOME', 'Rent', 1),
('INCOME', 'Late Charge', 1),
('EXPENSE', 'Concession', 1),
('EXPENSE', 'Bad Debt', 1);
('ASSET', 'A/R', 0, 0),
('ASSET', 'Invoice', 0, 0),
('ASSET', 'Receipt', 0, 0),
('LIABILITY', 'A/P', 0, 0),
('LIABILITY', 'Tax', 0, 0),
('LIABILITY', 'Customer Credit', 0, 0),
('ASSET', 'Bank', 0, 1),
('ASSET', 'Cash', 1, 0),
('ASSET', 'Check', 1, 0),
('ASSET', 'Money Order', 1, 0),
('LIABILITY', 'Security Deposit', 0, 0),
('INCOME', 'Rent', 0, 0),
('INCOME', 'Late Charge', 0, 0),
('EXPENSE', 'Concession', 0, 0),
('EXPENSE', 'Bad Debt', 0, 0);
UNLOCK TABLES;

View File

@@ -12,6 +12,7 @@ class AccountsController extends AppController {
array('name' => 'Equity', 'url' => array('controller' => 'accounts', 'action' => 'equity')),
array('name' => 'Income', 'url' => array('controller' => 'accounts', 'action' => 'income')),
array('name' => 'Expense', 'url' => array('controller' => 'accounts', 'action' => 'expense')),
array('name' => 'Bank Deposit', 'url' => array('controller' => 'accounts', 'action' => 'deposit')),
);
@@ -189,4 +190,48 @@ class AccountsController extends AppController {
$this->set(compact('account', 'title', 'stats'));
}
/**************************************************************************
**************************************************************************
**************************************************************************
* action: deposit
* - Prepares the books for a bank deposit
*/
function deposit() {
if ($this->data) {
pr($this->data);
/* $this->autoRender = false; */
/* return; */
$transaction = array();
foreach ($this->data['Tillable']['Ledger']['id'] AS $acct_id) {
if ($this->data['Tillable']['Ledger'][$acct_id]['amount'] == 0)
continue;
$ids = $this->Account->postLedgerEntry
($transaction,
null,
array('debit_account_id' => $this->data['Deposit']['Account']['id'],
'credit_account_id' => $acct_id,
'amount' => $this->data['Tillable']['Ledger'][$acct_id]['amount']));
$transaction = array_intersect_key($ids, array('transaction_id'=>1));
$this->Account->closeCurrentLedger($acct_id);
}
$this->autoRender = false;
return;
}
$tillable_account = $this->Account->relatedAccounts('tillable');
$depositable_account = $this->Account->relatedAccounts('depositable');
foreach ($tillable_account AS &$acct) {
$acct['Account']['stats'] = $this->Account->stats($acct['Account']['id']);
}
$this->set(compact('tillable_account', 'depositable_account'));
}
}

View File

@@ -92,6 +92,26 @@ class Account extends AppModel {
function invoiceAccountID() { return $this->nameToID('Invoice'); }
function receiptAccountID() { return $this->nameToID('Receipt'); }
/**************************************************************************
**************************************************************************
**************************************************************************
* function: relatedAccounts
* - Returns an array of accounts related by similar attributes
*/
function relatedAccounts($attribute) {
$this->cacheQueries = true;
$account = $this->find('all', array
('contain' => array('CurrentLedger'),
'fields' => array('Account.id', 'Account.type', 'Account.name', 'CurrentLedger.id'),
'conditions' => array('Account.'.$attribute => true)
));
$this->cacheQueries = false;
return $account;
}
/**************************************************************************
**************************************************************************
**************************************************************************
@@ -346,6 +366,165 @@ class Account extends AppModel {
return $unreconciled;
}
/**************************************************************************
**************************************************************************
**************************************************************************
* function: postLedgerEntry
* -
* transaction_data
* - transaction_id (optional... if set all else is ignored)
* - Transaction
* - stamp (optional... otherwise NOW is used)
* - comment
*
* monetary_source_data
* - monetary_source_id (optional... if set all else is ignored)
* - monetary_type_name
* - MonetarySource
* - name
* - monetary_type_id
*/
function postLedgerEntry($transaction_data,
$monetary_data,
$entry_data) {
/* if (!isset($entry_data) || */
/* !isset($entry_data['amount']) || */
/* !$entry_data['amount']) */
/* return false; */
$A = new Account();
/* // Create a transaction if necessary */
/* if (!isset($transaction_data['id'])) { */
/* $transaction = new Transaction(); */
/* $transaction->create(); */
/* if (!$transaction->save($transaction_data, false)) { */
/* return false; */
/* } */
/* $transaction_data['id'] = $transaction->id; */
/* } */
// Get the Transaction squared away
if (isset($transaction_data['transaction_id'])) {
$transaction_data
= array_intersect_key($transaction_data,
array('transaction_id'=>1));
}
elseif (isset($transaction_data['Transaction'])) {
$transaction_data
= array_intersect_key($transaction_data,
array('Transaction'=>1));
}
else {
$transaction_data = array('Transaction'=>array('stamp' => null));
}
// Get the Monetary Source squared away
if (isset($monetary_data['monetary_source_id'])) {
$monetary_data
= array_intersect_key($monetary_data,
array('monetary_source_id'=>1));
}
elseif (isset($monetary_data['monetary_type_name'])) {
if ($monetary_data['monetary_type_name'] === 'Cash') {
// No distinguishing features of Cash, just
// use the shared monetary source
$monetary_data['monetary_source_id'] =
$this->Ledger->LedgerEntry->MonetarySource->nameToID('Cash');
$monetary_data
= array_intersect_key($monetary_data,
array('monetary_source_id'=>1));
}
else {
// The monetary source needs to be unique
// Create a new one dedicated to this entry
$monetary_data['MonetarySource']['monetary_type_id'] =
$this->Ledger->LedgerEntry->MonetarySource->MonetaryType
->nameToID($monetary_data['monetary_type_name']);
$monetary_data['MonetarySource']['name'] =
$this->Ledger->LedgerEntry->MonetarySource->MonetaryType
->nameToID($monetary_data['monetary_type_name']);
// Give it a fancy name based on the check number
$monetary_data['MonetarySource']['name'] = $monetary_data['monetary_type_name'];
if ($monetary_data['monetary_type_name'] === 'Check' ||
$monetary_data['monetary_type_name'] === 'Money Order') {
$monetary_data['MonetarySource']['name'] .=
' #' . $monetary_data['MonetarySource']['data1'];
}
$monetary_data
= array_intersect_key($monetary_data,
array('MonetarySource'=>1));
}
}
elseif (isset($monetary_data)) {
$monetary_data
= array_intersect_key($monetary_data,
array('MonetarySource'=>1));
}
else {
$monetary_data = array();
}
// Make sure to clean out any unwanted data from the entry
$entry_data
= array_diff_key($entry_data,
array('transaction_id'=>1, 'Transaction'=>1,
'monetary_source_id'=>1, 'MonetarySource'=>1));
// Then add in the transaction and monetary source data
//pr(compact('transaction_data', 'monetary_data', 'entry_data'));
if (isset($transaction_data))
$entry_data += $transaction_data;
if (isset($monetary_data))
$entry_data += $monetary_data;
// Set up the debit ledger id
if (!isset($entry_data['debit_ledger_id'])) {
$entry_data['debit_ledger_id'] =
($entry_data['debit_account_id']
? $A->currentLedgerID($entry_data['debit_account_id'])
: ($entry_data['debit_account_name']
? $A->currentLedgerID($A->nameToID($entry_data['debit_account_name']))
: null
)
);
}
// Set up the credit ledger id
if (!isset($entry_data['credit_ledger_id'])) {
$entry_data['credit_ledger_id'] =
($entry_data['credit_account_id']
? $A->currentLedgerID($entry_data['credit_account_id'])
: ($entry_data['credit_account_name']
? $A->currentLedgerID($A->nameToID($entry_data['credit_account_name']))
: null
)
);
}
//pr(array('pre-save', compact('entry_data')));
// Create it!
$entry = new LedgerEntry();
$entry->create();
if (!$entry->saveAll($entry_data, array('validate'=>false))) {
return false;
}
$entry->read();
//pr(array('post-save', $entry->data));
return array('transaction_id' => $entry->data['LedgerEntry']['transaction_id'],
'monetary_source_id' => $entry->data['LedgerEntry']['monetary_source_id'],
'id' => $entry->data['LedgerEntry']['id']);
}
/**************************************************************************
**************************************************************************
**************************************************************************

View File

@@ -0,0 +1,58 @@
<?php /* -*- mode:PHP -*- */
echo '<div class="account deposit">' . "\n";
echo '<H2>Perform Bank Deposit</H2>' . "\n";
//pr(compact('tillableAccount', 'depositableAccount'));
echo $form->create(null, array('id' => 'deposit-form',
'url' => array('controller' => 'accounts',
'action' => 'deposit')));
$grid_setup = array();
$grid_setup['hiddengrid'] = true;
foreach ($tillableAccount AS $acct) {
//$acct = $acct['Account'];
echo ('<INPUT type="checkbox"' .
' name="data[Tillable][Ledger][id][]"' .
' value="'.$acct['CurrentLedger']['id'].'"' .
' CHECKED> ');
echo ("I have exactly " .
FormatHelper::currency($acct['Account']['stats']['Ledger']['balance']) .
" in " . ($acct['Account']['name'] === 'Cash'
? 'Cash'
: Inflector::pluralize($acct['Account']['name'])) .
" and will be depositing it all." .
"" . "\n");
echo ('<INPUT type="hidden"' .
' name="data[Tillable][Ledger]['.$acct['CurrentLedger']['id'].'][amount]"' .
' value="'.$acct['Account']['stats']['Ledger']['balance'].'"' .
'> ');
$grid_div_id = 'ledger_entries'.$acct['CurrentLedger']['id'].'-list';
echo $this->element('ledger_entries',
array('grid_div_id' => $grid_div_id,
'caption' => ('<A HREF="#" ONCLICK="$(\'#'.$grid_div_id.' .HeaderButton\').click();'.
' return false;">Items in '.$acct['Account']['name'].' Ledger</A>'),
'ledger_id' => $acct['CurrentLedger']['id'],
'no_account' => true,
'grid_setup' => $grid_setup,
//'account_id' => $acct['Account']['id'],
//'account_type' => $acct['Account']['type'],
//'account_ftype' => 'debit',
));
}
$options = array();
foreach ($depositableAccount AS $acct) {
$options[$acct['Account']['id']] = $acct['Account']['name'];
}
echo $form->input('Deposit.Account.id', array('label' => 'Deposit Account ',
'options' => $options));
echo $form->end('Perform Deposit');
/* End page div */
echo '</div>' . "\n";

View File

@@ -11,9 +11,14 @@ $cols['Credits'] = array('index' => 'credits', 'formatter' => 'currenc
$cols['Balance'] = array('index' => 'balance', 'formatter' => 'currency');
$cols['Comment'] = array('index' => 'Account.comment', 'formatter' => 'comment');
$custom_post_data = compact('nothing');
$jqGrid_options = array('jqGridColumns' => $cols,
'controller' => 'accounts',
'caption' => isset($caption) ? $caption : null);
);
$jqGrid_options += compact('grid_div_id', 'grid_id', 'caption', 'grid_setup', 'limit');
if (isset($accounts)) {
$jqGrid_options += array('custom_ids' =>
@@ -26,4 +31,6 @@ else {
$jqGrid_options += array('search_fields' => array('Name'));
}
$jqGrid_options += compact('custom_post_data');
$jqGrid_options['sort_column'] = 'Name';
echo $this->element('jqGrid', $jqGrid_options);

View File

@@ -2,10 +2,15 @@
if (isset($account_ftype) || isset($ledger_id) || isset($account_id) || isset($ar_account)) {
$single_account = true;
$double_account = false;
} else {
$single_account = false;
$double_account = true;
}
if (isset($no_account))
$single_account = $double_account = false;
if (isset($ledger_id) || isset($account_id) || isset($ar_account)) {
$single_amount = false;
} else {
@@ -49,7 +54,8 @@ $cols['Date'] = array('index' => 'Transaction.stamp', 'formatter' =>
if ($single_account) {
$cols['Account'] = array('index' => 'Account.name', 'formatter' => 'name');
}
else {
if ($double_account) {
$cols['Debit Account'] = array('index' => 'DebitAccount.name', 'formatter' => 'name');
$cols['Credit Account'] = array('index' => 'CreditAccount.name', 'formatter' => 'name');
}