array('numeric'), 'transaction_id' => array('numeric'), 'amount' => array('money') ); var $hasOne = array( 'DebitEntry' => array( 'className' => 'Entry', 'conditions' => array('DebitEntry.crdr' => 'DEBIT'), ), 'CreditEntry' => array( 'className' => 'Entry', 'conditions' => array('CreditEntry.crdr' => 'CREDIT'), ), ); var $hasMany = array( 'Entry', ); var $belongsTo = array( 'Transaction', 'Invoice' => array( 'className' => 'Transaction', 'conditions' => array('Invoice.type' => 'INVOICE'), ), 'Receipt' => array( 'className' => 'Transaction', 'conditions' => array('Invoice.type' => 'RECEIPT'), ), 'Customer', 'Lease', 'DebitLedger' => array( 'className' => 'Ledger', 'foreignKey' => 'debit_ledger_id', ), 'CreditLedger' => array( 'className' => 'Ledger', 'foreignKey' => 'credit_ledger_id', ), 'Ledger' => array( 'foreignKey' => false, // conditions will be used when JOINing tables // (such as find with LinkableBehavior) 'conditions' => array('OR' => array('%{MODEL_ALIAS}.debit_ledger_id = Ledger.id', '%{MODEL_ALIAS}.credit_ledger_id = Ledger.id')), // finderQuery will be used when tables are put // together across several querys, not with JOIN. // (such as find with ContainableBehavior) 'finderQuery' => 'NOT-IMPLEMENTED', 'counterQuery' => '' ), ); /************************************************************************** ************************************************************************** ************************************************************************** * function: conditionEntryAsCreditOrDebit * - returns the condition necessary to match a set of * Ledgers to all related LedgerEntries */ function conditionEntryAsCreditOrDebit($ledger_ids) { return array('OR' => array(array('debit_ledger_id' => $ledger_ids), array('credit_ledger_id' => $ledger_ids))); } function debitCreditFields($double_name = 'DoubleEntry', $ledger_name = 'Ledger', $sum = true) { $fields = array ( ($sum ? 'SUM(' : '') . "IF({$double_name}.debit_ledger_id = {$ledger_name}.id, {$double_name}.amount, NULL)" . ($sum ? ')' : '') . ' AS debit' . ($sum ? 's' : ''), ($sum ? 'SUM(' : '') . "IF({$double_name}.credit_ledger_id = {$ledger_name}.id, {$double_name}.amount, NULL)" . ($sum ? ')' : '') . ' AS credit' . ($sum ? 's' : ''), ($sum ? 'SUM(' : '') . "IF(Account.type IN ('ASSET', 'EXPENSE'), IF({$double_name}.debit_ledger_id = {$ledger_name}.id, 1, -1), IF({$double_name}.credit_ledger_id = {$ledger_name}.id, 1, -1) ) * IF({$double_name}.amount, {$double_name}.amount, 0)" . ($sum ? ')' : '') . ' AS balance', ); if ($sum) $fields[] = "COUNT({$double_name}.id) AS entries"; return $fields; } /************************************************************************** ************************************************************************** ************************************************************************** * function: ledgerContext query helpers * - Returns parameters necessary to generate a query which * puts ledger entries into the context of a ledger. Since * debit/credit depends on the account type, it is required * as an argument for each function to avoid having to * query the ledger/account to find it out. */ function ledgerContextFields($ledger_id = null, $account_type = null) { $fields = array('id', 'effective_date', 'lease_id', 'customer_id', 'comment', 'amount'); if (isset($ledger_id)) { $fields[] = ("IF(DoubleEntry.debit_ledger_id = $ledger_id," . " DoubleEntry.amount, NULL) AS debit"); $fields[] = ("IF(DoubleEntry.credit_ledger_id = $ledger_id," . " DoubleEntry.amount, NULL) AS credit"); if (isset($account_type)) { if (in_array($account_type, array('ASSET', 'EXPENSE'))) $ledger_type = 'debit'; else $ledger_type = 'credit'; $fields[] = ("(IF(DoubleEntry.{$ledger_type}_ledger_id = $ledger_id," . " 1, -1) * DoubleEntry.amount) AS balance"); } } return $fields; } function ledgerContextFields2($ledger_id = null, $account_id = null, $account_type = null) { $fields = array('id', 'effective_date', 'comment', 'amount'); if (isset($ledger_id)) { $fields[] = ("IF(DoubleEntry.debit_ledger_id = $ledger_id," . " SUM(DoubleEntry.amount), NULL) AS debit"); $fields[] = ("IF(DoubleEntry.credit_ledger_id = $ledger_id," . " SUM(DoubleEntry.amount), NULL) AS credit"); if (isset($account_id) || isset($account_type)) { $Account = new Account(); $account_ftype = $Account->fundamentalType($account_id ? $account_id : $account_type); $fields[] = ("(IF(DoubleEntry.{$account_ftype}_ledger_id = $ledger_id," . " 1, -1) * SUM(DoubleEntry.amount)) AS balance"); } } elseif (isset($account_id)) { $fields[] = ("IF(DebitLedger.account_id = $account_id," . " SUM(DoubleEntry.amount), NULL) AS debit"); $fields[] = ("IF(CreditLedger.account_id = $account_id," . " SUM(DoubleEntry.amount), NULL) AS credit"); $Account = new Account(); $account_ftype = ucfirst($Account->fundamentalType($account_id)); $fields[] = ("(IF({$account_ftype}Ledger.account_id = $account_id," . " 1, -1) * SUM(DoubleEntry.amount)) AS balance"); } return $fields; } function ledgerContextConditions($ledger_id, $account_type) { if (isset($ledger_id)) { return array ('OR' => array(array('DoubleEntry.debit_ledger_id' => $ledger_id), array('DoubleEntry.credit_ledger_id' => $ledger_id)), ); } return array(); } /************************************************************************** ************************************************************************** ************************************************************************** * function: findInLedgerContext * - Returns an array of ledger entries that belong to a given ledger. * There is extra logic to also figure out whether the double_entry * amount is either a credit, or a debit, depending on how it was * written into the ledger, as well as whether the amount increases or * decreases the balance depending on the particular account type of * the ledger. */ function findInLedgerContext($ledger_id, $account_type, $cond = null, $link = null) { if (!isset($link)) $link = array('Transaction'); if (!isset($cond)) $cond = array(); $fields = $this->ledgerContextFields($ledger_id, $account_type); $cond[] = $this->ledgerContextConditions($ledger_id, $account_type); $order = array('Transaction.stamp'); $entries = $this->find ('all', array('link' => $link, 'fields' => $fields, 'conditions' => $cond, 'order' => $order, )); return $entries; } /************************************************************************** ************************************************************************** ************************************************************************** * function: stats * - Returns summary data from the requested double entry */ function stats($id) { /* $query = array */ /* ( */ /* 'fields' => array("SUM(Reconciliation.amount) AS 'reconciled'"), */ /* 'conditions' => array(isset($cond) ? $cond : array(), */ /* array('DoubleEntry.id' => $id)), */ /* 'group' => 'DoubleEntry.id', */ /* ); */ /* // Get the applied amounts on the debit side */ /* $query['link'] = */ /* array('DebitReconciliationDoubleEntry' => array('alias' => 'DRLE', 'DRLETransaction' => array('class' => 'Transaction'))); */ /* $tmpstats = $this->find('first', $query); */ /* $stats['debit_amount_reconciled'] = $tmpstats[0]['reconciled']; */ /* // Get the applied amounts on the credit side */ /* $query['link'] = */ /* array('CreditReconciliationDoubleEntry' => array('alias' => 'CRLE', 'CRLETransaction' => array('class' => 'Transaction'))); */ /* $tmpstats = $this->find('first', $query); */ /* $stats['credit_amount_reconciled'] = $tmpstats[0]['reconciled']; */ $stats['debit']['amount_reconciled'] = 0; $stats['credit']['amount_reconciled'] = 0; return $stats; } }