array( 'dependent' => true, ), 'DebitDoubleEntry' => array( 'className' => 'DoubleEntry', 'foreignKey' => 'credit_entry_id', 'dependent' => true, ), 'CreditDoubleEntry' => array( 'className' => 'DoubleEntry', 'foreignKey' => 'credit_entry_id', 'dependent' => true, ), 'DoubleEntry' => array( 'foreignKey' => false, ), ); var $hasMany = array( ); var $hasAndBelongsToMany = array( // The Debit half of the double entry matching THIS Credit (if it is one) 'DebitEntry' => array( 'className' => 'LedgerEntry', 'joinTable' => 'double_entries', 'linkalias' => 'DDE', 'foreignKey' => 'credit_entry_id', 'associationForeignKey' => 'debit_entry_id', ), // The Credit half of the double entry matching THIS Debit (if it is one) 'CreditEntry' => array( 'className' => 'LedgerEntry', 'joinTable' => 'double_entries', 'linkalias' => 'CDE', 'foreignKey' => 'debit_entry_id', 'associationForeignKey' => 'credit_entry_id', ), ); /************************************************************************** ************************************************************************** ************************************************************************** * function: debitCreditFields * - Returns the fields necessary to determine whether the queried * entries are a debit, or a credit, and also the effect each have * on the overall balance of the account/ledger. */ function debitCreditFields($sum = false, $balance = true, $entry_name = 'LedgerEntry', $account_name = 'Account') { $fields = array ( ($sum ? 'SUM(' : '') . "IF({$entry_name}.crdr = 'DEBIT'," . " {$entry_name}.amount, NULL)" . ($sum ? ')' : '') . ' AS debit' . ($sum ? 's' : ''), ($sum ? 'SUM(' : '') . "IF({$entry_name}.crdr = 'CREDIT'," . " {$entry_name}.amount, NULL)" . ($sum ? ')' : '') . ' AS credit' . ($sum ? 's' : ''), ); if ($balance) $fields[] = ($sum ? 'SUM(' : '') . "IF(${account_name}.type IN ('ASSET', 'EXPENSE')," . " IF({$entry_name}.crdr = 'DEBIT', 1, -1)," . " IF({$entry_name}.crdr = 'CREDIT', 1, -1))" . " * IF({$entry_name}.amount, {$entry_name}.amount, 0)" . ($sum ? ')' : '') . ' AS balance'; if ($sum) $fields[] = "COUNT({$entry_name}.id) AS entries"; return $fields; } /************************************************************************** ************************************************************************** ************************************************************************** * function: verifyLedgerEntry * - Verifies consistenty of new ledger entry data * (not in a pre-existing ledger entry) */ function verifyLedgerEntry($entry, $tender = null) { /* pr(array("LedgerEntry::verifyLedgerEntry()" */ /* => compact('entry', 'tender'))); */ if (empty($entry['account_id']) || empty($entry['crdr']) || empty($entry['amount']) ) { /* pr(array("LedgerEntry::verifyLedgerEntry()" */ /* => "Entry verification failed")); */ return false; } if (isset($tender) && !$this->Tender->verifyTender($tender)) { /* pr(array("LedgerEntry::verifyLedgerEntry()" */ /* => "Tender verification failed")); */ return false; } return true; } /************************************************************************** ************************************************************************** ************************************************************************** * function: addLedgerEntry * - Inserts new Ledger Entry into the database */ function addLedgerEntry($entry, $tender = null) { /* pr(array('LedgerEntry::addLedgerEntry' => */ /* compact('entry', 'tender'))); */ $ret = array(); if (!$this->verifyLedgerEntry($entry, $tender)) return array('error' => true) + $ret; if (empty($entry['ledger_id'])) $entry['ledger_id'] = $this->Account->currentLedgerID($entry['account_id']); /* pr(array('LedgerEntry::addLedgerEntry' => */ /* array('checkpoint' => 'Pre-Save') */ /* + compact('entry'))); */ $this->create(); if (!$this->save($entry)) return array('error' => true) + $ret; $ret['ledger_entry_id'] = $this->id; if (isset($tender)) { $tender['account_id'] = $entry['account_id']; $tender['ledger_entry_id'] = $ret['ledger_entry_id']; $result = $this->Tender->addTender($tender); $ret['Tender'] = $result; if ($result['error']) return array('error' => true) + $ret; } return $ret + array('error' => false); } /************************************************************************** ************************************************************************** ************************************************************************** * function: stats * - Returns summary data from the requested ledger entry */ function stats($id = null, $query = null, $set = null) { $this->queryInit($query); unset($query['group']); if (!isset($query['link']['DoubleEntry'])) $query['link']['DoubleEntry'] = array(); /* if (!isset($query['link']['DoubleEntry']['fields'])) */ /* $query['link']['DoubleEntry']['fields'] = array(); */ if (isset($id)) $query['conditions'][] = array('Entry.id' => $id); if (isset($set)) $set = strtoupper($set); //pr(array('stats()', compact('id', 'query', 'set'))); $rtypes = array('charge', 'disbursement', // 'debit', 'credit', ); $stats = array(); foreach($rtypes AS $rtype) { $Rtype = ucfirst($rtype); if (($rtype == 'charge' && (!isset($set) || $set == 'DISBURSEMENT')) || ($rtype == 'disbursement' && (!isset($set) || $set == 'CHARGE')) ) { $rquery = $query; $rquery['link'][$Rtype] = array('fields' => array("SUM(COALESCE(Applied{$Rtype}.amount,0)) AS reconciled")); $rquery['fields'] = array(); //$rquery['fields'][] = "SUM(DoubleEntry.amount) AS total"; $rquery['fields'][] = "SUM(DoubleEntry.amount) - SUM(COALESCE(Applied{$Rtype}.amount,0)) AS balance"; $rquery['conditions'][] = array("Applied{$Rtype}.id !=" => null); $result = $this->find('first', $rquery); //pr(compact('Rtype', 'rquery', 'result')); $sumfld = $Rtype; $stats[$sumfld] = $result[0]; /* if (!isset($stats[$sumfld]['applied'])) */ /* $stats[$sumfld]['applied'] = 0; */ } } return $stats; } }