array( 'className' => 'Ledger', // REVISIT 20090702: // I would prefer this statement, which has no // engine specific code. However, it doesn't // work with the Linkable behavior. I need to // look into that, just not right now. //'conditions' => array(array('CurrentLedger.close_transaction_id' => null)), 'conditions' => array('CurrentLedger.close_transaction_id IS NULL'), ), ); var $hasMany = array( 'Ledger', 'LedgerEntry', ); /************************************************************************** ************************************************************************** ************************************************************************** * function: type * - Returns the type of this account */ function type($id) { $this->cacheQueries = true; $account = $this->find('first', array ('recursive' => -1, 'fields' => array('type'), 'conditions' => array(array('Account.id' => $id)), )); $this->cacheQueries = false; return $account['Account']['type']; } /************************************************************************** ************************************************************************** ************************************************************************** * function: fundamentalType * - Returns the fundmental type of the account, credit or debit */ function fundamentalType($id_or_type) { if (is_numeric($id_or_type)) $type = $this->type($id_or_type); else $type = $id_or_type; // Asset and Expense accounts are debit accounts if (in_array(strtoupper($type), array('ASSET', 'EXPENSE'))) return 'debit'; // Otherwise, it's a credit account return 'credit'; } /************************************************************************** ************************************************************************** ************************************************************************** * function: fundamentalOpposite * - Returns the opposite fundmental type of the account, credit or debit */ function fundamentalOpposite($id_or_type) { if (in_array(strtolower($id_or_type), array('credit', 'debit'))) $fund = $id_or_type; else $fund = $this->fundamentalType($id_or_type); if (strtolower($fund) == 'debit') return 'credit'; return 'debit'; } /************************************************************************** ************************************************************************** ************************************************************************** * function: name * - Returns the name of this account */ function name($id) { $this->cacheQueries = true; $account = $this->find('first', array ('recursive' => -1, 'fields' => array('name'), 'conditions' => array(array('Account.id' => $id)), )); $this->cacheQueries = false; return $account['Account']['name']; } /************************************************************************** ************************************************************************** ************************************************************************** * 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. */ function debitCreditFields($sum = false, $balance = true, $entry_name = 'LedgerEntry', $account_name = 'Account') { return $this->LedgerEntry->debitCreditFields ($sum, $balance, $entry_name, $account_name); } /************************************************************************** ************************************************************************** ************************************************************************** * function: Account IDs * - Returns the ID of the desired account */ function lookup($name, $check = true) { $id = $this->nameToID($name); if (empty($id) && $check) $this->INTERNAL_ERROR("Missing Account '$name'"); return $id; } function securityDepositAccountID() { return $this->lookup('Security Deposit'); } function rentAccountID() { return $this->lookup('Rent'); } function lateChargeAccountID() { return $this->lookup('Late Charge'); } function nsfAccountID() { return $this->lookup('NSF'); } function nsfChargeAccountID() { return $this->lookup('NSF Charge'); } function taxAccountID() { return $this->lookup('Tax'); } function accountReceivableAccountID() { return $this->lookup('A/R'); } function accountPayableAccountID() { return $this->lookup('A/P'); } function cashAccountID() { return $this->lookup('Cash'); } function checkAccountID() { return $this->lookup('Check'); } function moneyOrderAccountID() { return $this->lookup('Money Order'); } function achAccountID() { return $this->lookup('ACH'); } function concessionAccountID() { return $this->lookup('Concession'); } function waiverAccountID() { return $this->lookup('Waiver'); } function pettyCashAccountID() { return $this->lookup('Petty Cash'); } function invoiceAccountID() { return $this->lookup('Invoice'); } function receiptAccountID() { return $this->lookup('Receipt'); } function badDebtAccountID() { return $this->lookup('Bad Debt'); } function customerCreditAccountID() { return $this->lookup( // REVISIT : 20090816 // Use of A/R works, and saves an excess of accounts. // However, a dedicated account is nice, since it can // quickly be spotted how much is _really_ due, vs // how much has been pre-paid. Customer credits in // A/R is not as clear, although a report is an // obvious solution. //'A/R' 'Credit' ); } /************************************************************************** ************************************************************************** ************************************************************************** * function: fundamentalAccounts * - Returns an array of accounts by their fundamental type */ function fundamentalAccounts($ftype) { $this->cacheQueries = true; $account = $this->find('all', array ('contain' => array('CurrentLedger'), 'fields' => array('Account.id', 'Account.type', 'Account.name', 'CurrentLedger.id'), 'conditions' => array('Account.type' => strtoupper($ftype)) )); $this->cacheQueries = false; return $account; } /************************************************************************** ************************************************************************** ************************************************************************** * function: relatedAccounts * - Returns an array of accounts related by similar attributes */ function relatedAccounts($attribute, $extra = null) { $this->cacheQueries = true; $accounts = $this->find('all', array ('fields' => array('Account.id', 'Account.name'), 'conditions' => array('Account.'.$attribute => true), 'order' => array('Account.name'), ) + (isset($extra) ? $extra : array()) ); $this->cacheQueries = false; // Rearrange to be of the form (id => name) $rel_accounts = array(); foreach ($accounts AS $acct) { $rel_accounts[$acct['Account']['id']] = $acct['Account']['name']; } return $rel_accounts; } /************************************************************************** ************************************************************************** ************************************************************************** * function: xxxAccounts * - Returns an array of accounts suitable for activity xxx */ function invoiceAccounts() { return $this->relatedAccounts('invoices'); } function receiptAccounts() { return $this->relatedAccounts('receipts'); } function depositAccounts() { return $this->relatedAccounts('deposits'); } function refundAccounts() { return $this->relatedAccounts('refunds'); } /************************************************************************** ************************************************************************** ************************************************************************** * function: collectableAccounts * - Returns an array of accounts suitable to show income collection */ function collectableAccounts() { $accounts = $this->receiptAccounts(); foreach(array($this->customerCreditAccountID(), $this->securityDepositAccountID(), $this->nsfAccountID(), $this->waiverAccountID(), $this->badDebtAccountID(), //$this->lookup('Closing'), //$this->lookup('Equity'), ) AS $account_id) { $accounts[$account_id] = $this->name($account_id); } $accounts['all'] = $accounts['default'] = $accounts; foreach(array($this->concessionAccountID(), $this->waiverAccountID(), $this->badDebtAccountID(), ) AS $account_id) { unset($accounts['default'][$account_id]); } return $accounts; } /************************************************************************** ************************************************************************** ************************************************************************** * function: currentLedgerID * - Returns the current ledger ID of the account */ function currentLedgerID($id) { $this->cacheQueries = true; $item = $this->find('first', array ('contain' => 'CurrentLedger', 'conditions' => array('Account.id' => $id), )); $this->cacheQueries = false; return $item['CurrentLedger']['id']; } /************************************************************************** ************************************************************************** ************************************************************************** * function: ledgers * - Returns an array of ledger ids from the given account */ function ledgers($id, $all = false) { if ($all) { $contain = array('Ledger' => array('fields' => array('Ledger.id'))); } else { $contain = array('CurrentLedger' => array('fields' => array('CurrentLedger.id'))); } $this->cacheQueries = true; $account = $this->find('first', array ('contain' => $contain, 'fields' => array(), 'conditions' => array(array('Account.id' => $id)), )); $this->cacheQueries = false; if ($all) { $ledger_ids = array(); foreach ($account['Ledger'] AS $ledger) array_push($ledger_ids, $ledger['id']); } else { $ledger_ids = array($account['CurrentLedger']['id']); } /* pr(array('function' => 'Account::ledgers', */ /* 'args' => compact('id', 'all'), */ /* 'return' => $ledger_ids)); */ return $ledger_ids; } /************************************************************************** ************************************************************************** ************************************************************************** * function: closeCurrentLedger * - Closes the current account ledger, and opens a new one * with the old balance carried forward. */ function closeCurrentLedgers($ids = null) { $this->cacheQueries = true; $account = $this->find('all', array ('contain' => array('CurrentLedger.id'), 'fields' => array(), 'conditions' => (empty($ids) ? array() : array(array('Account.id' => $ids))) )); $this->cacheQueries = false; //pr(compact('id', 'account')); $ledger_ids = array(); foreach ($account AS $acct) $ledger_ids[] = $acct['CurrentLedger']['id']; return $this->Ledger->closeLedgers($ledger_ids); } /************************************************************************** ************************************************************************** ************************************************************************** * function: ledgerEntries * - Returns an array of ledger entries that belong to the given * account, either just from the current ledger, or from all ledgers. */ function ledgerEntries($id, $all = false, $cond = null, $link = null) { $ledgers = $this->ledgers($id, $all); return $this->Ledger->ledgerEntries($ledgers, $cond, $link); } /************************************************************************** ************************************************************************** ************************************************************************** * function: stats * - Returns summary data from the requested account. */ function stats($id = null, $all = false, $query = null) { if (!$id) return null; $this->queryInit($query); $query['link'] = array('Account' => $query['link']); $stats = array(); foreach ($this->ledgers($id, $all) AS $ledger) $this->statsMerge($stats['Ledger'], $this->Ledger->stats($ledger, $query)); return $stats; } } ?>