git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629/site@200 97e9348a-65ac-dc4b-aefc-98561f571b83
216 lines
7.3 KiB
PHP
216 lines
7.3 KiB
PHP
<?php
|
|
class Ledger extends AppModel {
|
|
|
|
var $name = 'Ledger';
|
|
var $validate = array(
|
|
'id' => array('numeric'),
|
|
'name' => array('notempty'),
|
|
);
|
|
|
|
var $belongsTo = array(
|
|
'Account',
|
|
'PriorLedger' => array('className' => 'Ledger'),
|
|
'Close',
|
|
);
|
|
|
|
var $hasMany = array(
|
|
'LedgerEntry' => array(
|
|
'foreignKey' => false,
|
|
|
|
// conditions will be used when JOINing tables
|
|
// (such as find with LinkableBehavior)
|
|
'conditions' => array('OR' =>
|
|
array('LedgerEntry.debit_ledger_id = %{MODEL_ALIAS}.id',
|
|
'LedgerEntry.credit_ledger_id = %{MODEL_ALIAS}.id')),
|
|
|
|
// finderQuery will be used when tables are put
|
|
// together across several querys, not with JOIN.
|
|
// (such as find with ContainableBehavior)
|
|
'finderQuery' => 'SELECT `LedgerEntry`.*
|
|
FROM pmgr_ledger_entries AS `LedgerEntry`
|
|
WHERE LedgerEntry.debit_ledger_id = ({$__cakeID__$})
|
|
OR LedgerEntry.credit_ledger_id = ({$__cakeID__$})',
|
|
|
|
'counterQuery' => ''
|
|
),
|
|
'DebitLedgerEntry' => array(
|
|
'className' => 'LedgerEntry',
|
|
'foreignKey' => 'debit_ledger_id',
|
|
'dependent' => false,
|
|
),
|
|
'CreditLedgerEntry' => array(
|
|
'className' => 'LedgerEntry',
|
|
'foreignKey' => 'credit_ledger_id',
|
|
'dependent' => false,
|
|
),
|
|
);
|
|
|
|
|
|
/**************************************************************************
|
|
**************************************************************************
|
|
**************************************************************************
|
|
* function: closeLedger
|
|
* - Closes the current ledger, and returns a fresh one
|
|
*/
|
|
function closeLedger($id, $close_id) {
|
|
$this->recursive = -1;
|
|
|
|
$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);
|
|
|
|
$stats = $this->stats($id);
|
|
|
|
$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);
|
|
|
|
if ($stats['balance'] == 0)
|
|
return $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;
|
|
}
|
|
|
|
// 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",
|
|
);
|
|
|
|
$carry_entry = new LedgerEntry();
|
|
$carry_entry->create();
|
|
if (!$carry_entry->save($carry_entry_data, false)) {
|
|
return null;
|
|
}
|
|
|
|
return $this->id;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
**************************************************************************
|
|
**************************************************************************
|
|
* function: findLedgerEntries
|
|
* - Returns an array of ledger entries that belong to a given
|
|
* ledger. There is extra work done... see the LedgerEntry model.
|
|
*/
|
|
function findLedgerEntries($id, $account_type = null, $cond = null, $link = null) {
|
|
/* pr(array('function' => 'Ledger::findLedgerEntries', */
|
|
/* 'args' => compact('id', 'account_type', 'cond', 'link'), */
|
|
/* )); */
|
|
|
|
if (!isset($account_type)) {
|
|
$ledger = $this->find('first', array
|
|
('contain' => array
|
|
('Account' => array
|
|
('fields' => array('type'),
|
|
),
|
|
),
|
|
'fields' => array(),
|
|
'conditions' => array(array('Ledger.id' => $id)),
|
|
));
|
|
$account_type = $ledger['Account']['type'];
|
|
}
|
|
|
|
// If the requested entries are limited by date, we must calculate
|
|
// a balance forward, or the resulting balance will be thrown off.
|
|
//
|
|
// REVISIT <AP>: This obviously is more general than date.
|
|
// As such, it will not work (or, only work if the
|
|
// condition only manages to exclude the first parts
|
|
// of the ledger, nothing in the middle or at the
|
|
// end. For now, I'll just create an 'other' entry,
|
|
// not necessarily a balance forward.
|
|
|
|
$bf = array();
|
|
if (0 && isset($cond)) {
|
|
//$date = '<NOT IMPLEMENTED>';
|
|
$stats = $this->stats($id, array('NOT' => array($cond)));
|
|
$bf = array(array(array('debit' => $stats['debits'],
|
|
'credit' => $stats['credits'],
|
|
'balance' => $stats['balance']),
|
|
|
|
'LedgerEntry' => array('id' => null,
|
|
//'comment' => "Balance Forward from $date"),
|
|
'comment' => "-- SUMMARY OF EXCLUDED ENTRIES --"),
|
|
|
|
'Transaction' => array('id' => null,
|
|
//'stamp' => $date,
|
|
'stamp' => null,
|
|
'comment' => null),
|
|
));
|
|
}
|
|
|
|
$entries = $this->LedgerEntry->findInLedgerContext($id, $account_type, $cond, $link);
|
|
/* pr(array('function' => 'Ledger::findLedgerEntries', */
|
|
/* 'args' => compact('id', 'account_type', 'cond', 'link'), */
|
|
/* 'vars' => compact('ledger'), */
|
|
/* 'return' => compact('entries'), */
|
|
/* )); */
|
|
return $entries;
|
|
}
|
|
|
|
|
|
/**************************************************************************
|
|
**************************************************************************
|
|
**************************************************************************
|
|
* function: stats
|
|
* - Returns summary data from the requested ledger.
|
|
*/
|
|
function stats($id, $cond = null) {
|
|
if (!isset($cond))
|
|
$cond = array();
|
|
$cond[] = array('Ledger.id' => $id);
|
|
|
|
$stats = $this->find
|
|
('first', array
|
|
('link' =>
|
|
array(// Models
|
|
'Account' => array('fields' => array()),
|
|
//'LedgerEntry' => array('fields' => array()),
|
|
'LedgerEntry' =>
|
|
array('fields' => array(),
|
|
'Transaction' => array('fields' => array('stamp')),
|
|
),
|
|
),
|
|
'fields' =>
|
|
array("SUM(IF(LedgerEntry.debit_ledger_id = Ledger.id,
|
|
LedgerEntry.amount, NULL)) AS debits",
|
|
"SUM(IF(LedgerEntry.credit_ledger_id = Ledger.id,
|
|
LedgerEntry.amount, NULL)) AS credits",
|
|
"SUM(IF(Account.type IN ('ASSET', 'EXPENSE'),
|
|
IF(LedgerEntry.debit_ledger_id = Ledger.id, 1, -1),
|
|
IF(LedgerEntry.credit_ledger_id = Ledger.id, 1, -1)
|
|
) * IF(LedgerEntry.amount, LedgerEntry.amount, 0)
|
|
) AS balance",
|
|
"COUNT(LedgerEntry.id) AS entries"),
|
|
'conditions' => $cond,
|
|
'group' => 'Ledger.id',
|
|
));
|
|
|
|
// The fields are all tucked into the [0] index,
|
|
// and the rest of the array is useless (empty).
|
|
return $stats[0];
|
|
}
|
|
|
|
}
|
|
?>
|