sidemenu_links); } /************************************************************************** ************************************************************************** ************************************************************************** * virtuals: jqGridData * - With the application controller handling the jqGridData action, * these virtual functions ensure that the correct data is passed * to jqGrid. */ function jqGridDataSetup(&$params) { parent::jqGridDataSetup($params); if (isset($params['custom']['ar_account'])) { $params['custom']['account_id'] = $this->LedgerEntry->DebitLedger->Account->accountReceivableAccountID(); } } function jqGridDataTables(&$params, &$model) { $link = array(// Models 'Transaction' => array('fields' => array('id', 'stamp'), ), 'MonetarySource' => array('fields' => array('id', 'name'), ), 'Customer' => array('fields' => array('id', 'name'), ), 'Lease' => array('fields' => array('id', 'number'), 'Unit' => array('fields' => array('id', 'name'), ), ), ); if (isset($params['custom']['account_ftype'])) { $ftype = $params['custom']['account_ftype']; $ftype = ucfirst($ftype); //$ftype = $this->LedgerEntry->DebitLedger->Account->fundamentalOpposite($ftype); $link[$ftype . 'Ledger'] = array('fields' => array('id', 'sequence'), 'Account' => array('class' => 'Account', 'fields' => array('id', 'name'), ), ); } elseif (isset($params['custom']['ledger_id'])) { $ledger_id = $params['custom']['ledger_id']; $link['Ledger'] = array('fields' => array('id', 'sequence'), 'conditions' => ("Ledger.id = IF(LedgerEntry.debit_ledger_id = $ledger_id," . " LedgerEntry.credit_ledger_id," . " LedgerEntry.debit_ledger_id)"), 'Account' => array( 'fields' => array('id', 'name'), ), ); } elseif ($params['action'] === 'collected') { // Income / Receipt / Money // debit: A/R credit: Income <-- this entry // debit: Receipt credit: A/R <-- ReceiptLedgerEntry, below // debit: Money credit: Receipt <-- MoneyLedgerEntry, below $link['CreditLedger'] = array('fields' => 'sequence', 'Account' => array('fields' => array('id', 'name'), ), ); // We're searching for the Receipt<->A/R entries, // which are debits on the A/R account. Find the // reconciling entries to that A/R debit. $link['DebitReconciliationLedgerEntry'] = array('alias' => 'ReceiptLedgerEntry', 'Transaction' => array('alias' => 'ReceiptTransaction'), // Credit Ledger should be A/R; // Debit Ledger should be Receipt 'DebitLedger' => array('alias' => 'ReceiptLedger', 'Account' => array('alias' => 'ReceiptAccount'), ), // Finally, the Money (Cash/Check/etc) Entry is the one // which reconciles our ReceiptLedgerEntry debit 'DebitReconciliationLedgerEntry' => array('alias' => 'MoneyLedgerEntry', 'linkalias' => 'MoneyLedgerEntryR', // Credit Ledger should be Receipt; // Debit Ledger should be our Money Account 'DebitLedger' => array('alias' => 'MoneyLedger', 'Account' => array('alias' => 'MoneyAccount'), ), ), ); } else { $link['DebitLedger'] = array('fields' => array('id', 'sequence'), 'DebitAccount' => array('class' => 'Account', 'fields' => array('id', 'name'), ), ); $link['CreditLedger'] = array('fields' => array('id', 'sequence'), 'CreditAccount' => array('class' => 'Account', 'fields' => array('id', 'name'), ), ); } if (isset($params['custom']['account_id'])) { $account_id = $params['custom']['account_id']; $link['Ledger'] = array('fields' => array('id', 'sequence'), 'conditions' => ("Ledger.id = IF(DebitLedger.account_id = $account_id," . " LedgerEntry.credit_ledger_id," . " LedgerEntry.debit_ledger_id)"), 'Account' => array( 'fields' => array('id', 'name'), ), ); } if (isset($params['custom']['reconcile_id'])) { $ftype = $params['custom']['account_ftype']; $ftype = $this->LedgerEntry->DebitLedger->Account->fundamentalOpposite($ftype); $ftype = ucfirst($ftype); $link[$ftype.'ReconciliationLedgerEntry'] = array('fields' => array('Reconciliation.amount')); } return array('link' => $link); } function jqGridDataFields(&$params, &$model) { $ledger_id = (isset($params['custom']['ledger_id']) ? $params['custom']['ledger_id'] : null); $account_id = (isset($params['custom']['account_id']) ? $params['custom']['account_id'] : null); $account_type = (isset($params['custom']['account_type']) ? $params['custom']['account_type'] : null); $fields = $model->ledgerContextFields2($ledger_id, $account_id, $account_type); if (count(array_intersect($params['fields'], array('applied'))) == 1) $fields[] = 'SUM(Reconciliation.amount) AS applied'; if ($params['action'] === 'collected') $fields[] = 'MAX(ReceiptTransaction.stamp) AS last_paid'; return $fields; } function jqGridDataConditions(&$params, &$model) { $ledger_id = (isset($params['custom']['ledger_id']) ? $params['custom']['ledger_id'] : null); $account_type = (isset($params['custom']['account_type']) ? $params['custom']['account_type'] : null); $conditions = parent::jqGridDataConditions($params, $model); if ($params['action'] === 'collected') { extract($params['custom']); if (isset($collected_account_id)) $conditions[] = array('Account.id' => $params['custom']['collected_account_id']); else die("INTERNAL ERROR: COLLECTED ACCOUNT ID NOT SET"); if (!empty($collected_from_date)) $conditions[] = array('ReceiptTransaction.stamp >=' => $this->LedgerEntry->Transaction->dateFormatBeforeSave($collected_from_date)); if (!empty($collected_through_date)) $conditions[] = array('ReceiptTransaction.stamp <=' => $this->LedgerEntry->Transaction->dateFormatBeforeSave($collected_through_date . ' 23:59:59')); if (isset($collected_payment_accounts)) $conditions[] = array('MoneyAccount.id' => $collected_payment_accounts); else $conditions[] = array('NOT' => array(array('MoneyAccount.id' => null))); } if ($params['action'] === 'ledger') { $conditions[] = $model->ledgerContextConditions($ledger_id, $account_type); } if (isset($params['custom']['reconcile_id'])) { $ftype = $params['custom']['account_ftype']; //$ftype = $this->LedgerEntry->DebitLedger->Account->fundamentalOpposite($ftype); $conditions[] = array('Reconciliation.'.$ftype.'_ledger_entry_id' => $params['custom']['reconcile_id']); } if (isset($params['custom']['account_id'])) { $conditions[] = array('OR' => array(array('CreditAccount.id' => $params['custom']['account_id']), array('DebitAccount.id' => $params['custom']['account_id']))); } if (isset($params['custom']['customer_id'])) { $conditions[] = array('Customer.id' => $params['custom']['customer_id']); /* $Account = new Account(); */ /* if (isset($params['custom']['account_ftype']) || */ /* isset($params['custom']['ledger_id'])) { */ /* $conditions[] = */ /* array('OR' => array('Account.id' => $Account->invoiceAccountID(), */ /* 'Account.id' => $Account->receiptAccountID())); */ /* } else { */ /* $conditions[] = */ /* array('OR' => array('DebitAccount.id' => $Account->invoiceAccountID(), */ /* //'CreditAccount.id' => $Account->invoiceAccountID(), */ /* //'DebitAccount.id' => $Account->receiptAccountID(), */ /* 'CreditAccount.id' => $Account->receiptAccountID(), */ /* )); */ /* } */ } if (isset($params['custom']['lease_id'])) { $conditions[] = array('Lease.id' => $params['custom']['lease_id']); /* $Account = new Account(); */ /* if (isset($params['custom']['account_ftype']) || */ /* isset($params['custom']['ledger_id'])) { */ /* $conditions[] = */ /* array('OR' => array('Account.id' => $Account->invoiceAccountID(), */ /* 'Account.id' => $Account->receiptAccountID())); */ /* } else { */ /* $conditions[] = */ /* array('OR' => array('DebitAccount.id' => $Account->invoiceAccountID(), */ /* //'CreditAccount.id' => $Account->invoiceAccountID(), */ /* //'DebitAccount.id' => $Account->receiptAccountID(), */ /* 'CreditAccount.id' => $Account->receiptAccountID(), */ /* )); */ /* } */ } if (isset($params['custom']['transaction_id'])) { $conditions[] = array('Transaction.id' => $params['custom']['transaction_id']); } if (isset($params['custom']['monetary_source_id'])) { $conditions[] = array('MonetarySource.id' => $params['custom']['monetary_source_id']); } return $conditions; } function jqGridRecordLinks(&$params, &$model, &$records, $links) { $links['Transaction'] = array('id'); $links['LedgerEntry'] = array('id'); $links['Account'] = array('controller' => 'accounts', 'name'); $links['DebitAccount'] = array('controller' => 'accounts', 'name'); $links['CreditAccount'] = array('controller' => 'accounts', 'name'); $links['MonetarySource'] = array('name'); $links['Customer'] = array('name'); $links['Lease'] = array('number'); $links['Unit'] = array('name'); return parent::jqGridRecordLinks($params, $model, $records, $links); } function jqGridDataGroup(&$params, &$model) { if (isset($params['custom']['group_by_tx']) && $params['custom']['group_by_tx']) return $model->alias.'.transaction_id'; return parent::jqGridDataGroup($params, $model); } function jqGridDataOrder(&$params, &$model, $index, $direction) { /* if ($index === 'balance') */ /* return ($index .' '. $direction); */ $order = parent::jqGridDataOrder($params, $model, $index, $direction); if ($index === 'Transaction.stamp') { $order[] = 'LedgerEntry.id ' . $direction; } return $order; } function jqGridDataRecords(&$params, &$model, $query) { if ($params['action'] === 'collected') { $tquery = array_diff_key($query, array('fields'=>1,'group'=>1,'limit'=>1,'order'=>1)); $tquery['fields'] = array('SUM(Reconciliation.amount) AS applied'); $total = $model->find('first', $tquery); $params['userdata']['total'] = $total[0]['applied']; } return parent::jqGridDataRecords($params, $model, $query); } /************************************************************************** ************************************************************************** ************************************************************************** * action: reverse the ledger entry */ function reverse($id) { $this->LedgerEntry->reverse($id); $this->redirect(array('action'=>'view', $id)); } /************************************************************************** ************************************************************************** ************************************************************************** * action: view * - Displays information about a specific entry */ function view($id = null) { if (!$id) { $this->Session->setFlash(__('Invalid Item.', true)); $this->redirect(array('controller' => 'accounts', 'action'=>'index')); } // Get the LedgerEntry and related fields $entry = $this->LedgerEntry->find ('first', array('contain' => array('MonetarySource.id', 'MonetarySource.name', 'Transaction.id', 'Transaction.stamp', 'DebitLedger.id', 'DebitLedger.sequence', 'DebitLedger.account_id', 'CreditLedger.id', 'CreditLedger.sequence', 'CreditLedger.account_id', 'Customer.id', 'Customer.name', 'Lease.id', ), 'fields' => array('LedgerEntry.*'), 'conditions' => array('LedgerEntry.id' => $id), )); //pr($entry); // Because 'DebitLedger' and 'CreditLedger' both relate to 'Account', // CakePHP will not include them in the LedgerEntry->find (or so it // seems). We'll have to break out each Account separately. // Get the Account from DebitLedger $entry['DebitLedger'] += $this->LedgerEntry->DebitLedger->Account->find ('first', array('contain' => true, 'fields' => array('Account.id', 'Account.name', 'Account.type', 'Account.trackable'), 'conditions' => array('Account.id' => $entry['DebitLedger']['account_id']), )); $entry['DebitLedger']['Account']['ftype'] = $this->LedgerEntry->DebitLedger->Account ->fundamentalType($entry['DebitLedger']['Account']['type']); // Get the Account from CreditLedger $entry['CreditLedger'] += $this->LedgerEntry->CreditLedger->Account->find ('first', array('contain' => true, 'fields' => array('Account.id', 'Account.name', 'Account.type', 'Account.trackable'), 'conditions' => array('Account.id' => $entry['CreditLedger']['account_id']), )); $entry['CreditLedger']['Account']['ftype'] = $this->LedgerEntry->CreditLedger->Account ->fundamentalType($entry['CreditLedger']['Account']['type']); // Get the reconciliation balances for this ledger entry $stats = $this->LedgerEntry->stats($id); $stats['debit']['amount_reconciled'] = $stats['debit_amount_reconciled']; $stats['credit']['amount_reconciled'] = $stats['credit_amount_reconciled']; if ($entry['DebitLedger']['Account']['trackable']) $stats['debit']['amount_remaining'] = $entry['LedgerEntry']['amount'] - $stats['debit']['amount_reconciled']; if ($entry['CreditLedger']['Account']['trackable']) $stats['credit']['amount_remaining'] = $entry['LedgerEntry']['amount'] - $stats['credit']['amount_reconciled']; //pr($stats); $reconciled = $this->LedgerEntry->findReconciledLedgerEntries($id); //pr($reconciled); // REVISIT : 20090711 // It's not clear whether we should be able to reverse charges that have // already been paid/cleared/reconciled. Certainly, that will be the // case when someone has pre-paid and then moves out early. However, this // will work well for items accidentally charged but not yet paid for. if ((!$entry['DebitLedger']['Account']['trackable'] || $stats['debit']['amount_reconciled'] == 0) && (!$entry['CreditLedger']['Account']['trackable'] || $stats['credit']['amount_reconciled'] == 0) && 0 ) { // Set up dynamic menu items $this->sidemenu_links[] = array('name' => 'Operations', 'header' => true); $this->sidemenu_links[] = array('name' => 'Undo', 'url' => array('action' => 'reverse', $id)); } if ($this->LedgerEntry->Ledger->Account->type ($entry['CreditLedger']['Account']['id']) == 'INCOME') { // Set up dynamic menu items $this->sidemenu_links[] = array('name' => 'Operations', 'header' => true); $this->sidemenu_links[] = array('name' => 'Reverse', 'url' => array('action' => 'reverse', $id)); } // Prepare to render. $title = "Double Ledger Entry #{$entry['LedgerEntry']['id']}"; $this->set(compact('entry', 'title', 'reconciled', 'stats')); } }