diff --git a/db/schema.sql b/db/schema.sql index c8933f1..e8caaa2 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -1137,11 +1137,11 @@ CREATE TABLE `pmgr_payments` ( -- The ledger entry this physical payment applies to - `ledger_entry_id` INT(10) UNSIGNED NOT NULL, - -- The deposit that included these monies - `deposit_entry_id` INT(10) UNSIGNED DEFAULT NULL, - -- The NSF entry, should this come back from the bank. - `nsf_ledger_entry_id` INT(10) UNSIGNED DEFAULT NULL, + `ledger_entry_id` INT(10) UNSIGNED NOT NULL, + -- The deposit transaction that included these monies + `deposit_transaction_id` INT(10) UNSIGNED DEFAULT NULL, + -- The NSF transaction, should this come back from the bank. + `nsf_transaction_id` INT(10) UNSIGNED DEFAULT NULL, `comment` VARCHAR(255) DEFAULT NULL, diff --git a/site/app_controller.php b/site/app_controller.php index 504741a..45a9523 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -219,6 +219,9 @@ class AppController extends Controller { if (isset($params['idlist'])) $params['idlist'] = unserialize($params['idlist']); + // Make sure the action parameter at least exists + if (!isset($params['action'])) + $params['action'] = null; } function jqGridDataModel(&$params) { diff --git a/site/controllers/accounts_controller.php b/site/controllers/accounts_controller.php index 6b39961..4b65740 100644 --- a/site/controllers/accounts_controller.php +++ b/site/controllers/accounts_controller.php @@ -2,7 +2,7 @@ class AccountsController extends AppController { - var $uses = array('Account', 'DoubleEntry'); + var $uses = array('Account', 'LedgerEntry'); var $sidemenu_links = array(array('name' => 'Accounts', 'header' => true), @@ -68,7 +68,7 @@ class AccountsController extends AppController { array(// Models 'CurrentLedger' => array (// Models - 'DoubleEntry' + 'LedgerEntry' ), ), ); @@ -76,7 +76,7 @@ class AccountsController extends AppController { function jqGridDataFields(&$params, &$model) { return array_merge(array('Account.*'), - $this->Account->Ledger->DoubleEntry->debitCreditFields(true, 'DoubleEntry', 'CurrentLedger')); + $this->Account->Ledger->LedgerEntry->debitCreditFields(true, 'LedgerEntry', 'CurrentLedger')); } function jqGridDataConditions(&$params, &$model) { @@ -166,7 +166,7 @@ class AccountsController extends AppController { ('Account' => array('fields' => array('name')), - 'DoubleEntry' => + 'LedgerEntry' => array('fields' => array('id', 'amount'), 'MonetarySource' => @@ -181,7 +181,7 @@ class AccountsController extends AppController { ), 'fields' => false, 'conditions' => array(array('Ledger.id' => $ledger_id), - array('DoubleEntry.id IS NOT NULL'), + array('LedgerEntry.id IS NOT NULL'), ), )); @@ -247,7 +247,7 @@ class AccountsController extends AppController { // Get all ledger entries of the CURRENT ledger $entries = $this->Account->ledgerEntries($id); //pr(compact('entries')); - $account['CurrentLedger']['DoubleEntry'] = $entries; + $account['CurrentLedger']['LedgerEntry'] = $entries; // Summarize each ledger foreach($account['Ledger'] AS &$ledger) diff --git a/site/controllers/double_entries_controller.php b/site/controllers/double_entries_controller.php index 4fd76c7..f7c63cc 100644 --- a/site/controllers/double_entries_controller.php +++ b/site/controllers/double_entries_controller.php @@ -16,203 +16,6 @@ class DoubleEntriesController extends AppController { } - /************************************************************************** - ************************************************************************** - ************************************************************************** - * 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']['collected_account_id'])) - $params['custom']['account_id'] = $params['custom']['collected_account_id']; - } - - function jqGridDataTables(&$params, &$model) { - $link = - array(// Models - 'Transaction' => - array('fields' => array('id', 'stamp'), - ), - - 'Customer' => - array('fields' => array('id', 'name'), - ), - - 'Lease' => - array('fields' => array('id', 'number'), - 'Unit' => - array('fields' => array('id', 'name'), - ), - ), - ); - - if ($params['action'] == 'collected' || $params['action'] == 'reconcile') { - $link['Payment'] = array('Account' => array('alias' => 'PaymentAccount'), - 'Receipt'); - $link['Charge'] = array('Account' => array('alias' => 'ChargeAccount'), - 'Invoice'); - } - - if (isset($params['custom']['ledger_id'])) { - $link['Ledger'] = - array('fields' => array('id', 'sequence'), - 'Account' => - array('fields' => array('id', 'name'), - ), - ); - } - - return array('link' => $link); - } - - function jqGridDataFields(&$params, &$model) { - if ($params['action'] == 'collected') { - $fields[] = ('SUM(COALESCE(AppliedPayment.amount,0)' . - ' + COALESCE(AppliedCharge.amount,0)) AS applied'); - $fields[] = 'MAX(Receipt.stamp) AS last_paid'; - } - elseif ($params['action'] == 'reconcile') { - $fields[] = array("IF(Entry.type = 'CHARGE',", - " COALESCE(AppliedCharge.amount,0),", - " COALESCE(AppliedPayment.amount,0))", - " AS 'applied'"); - $fields[] = array("Entry.amount - (", - "IF(Entry.type = 'CHARGE',", - " COALESCE(AppliedCharge.amount,0),", - " COALESCE(AppliedPayment.amount,0))", - ") AS 'balance'"); - } - - return $fields; - } - - function jqGridDataConditions(&$params, &$model) { - if ($params['action'] === 'collected') { - if (!isset($params['custom']['account_id'])) - die("INTERNAL ERROR: ACCOUNT ID NOT SET"); - - extract($params['custom']); - - if (!empty($collected_from_date)) - $conditions[] - = array('Receipt.stamp >=' => - $this->DoubleEntry->Transaction->dateFormatBeforeSave($collected_from_date)); - - if (!empty($collected_through_date)) - $conditions[] - = array('Receipt.stamp <=' => - $this->DoubleEntry->Transaction->dateFormatBeforeSave($collected_through_date . ' 23:59:59')); - - if (isset($collected_payment_accounts)) - $conditions[] = array('PaymentAccount.id' => $collected_payment_accounts); - else - $conditions[] = array('NOT' => array(array('PaymentAccount.id' => null))); - } - - if ($params['action'] === 'ledger') { - $ledger_id = $params['custom']['ledger_id']; - $conditions[] = array('Ledger.id' => $ledger_id); - } - - if (isset($params['custom']['reconcile_id'])) { - $conditions[] = array('OR' => - array('AppliedCharge.id' => $reconcile_id), - array('AppliedPayment.id' => $reconcile_id)); - } - - if (isset($params['custom']['account_id'])) { - $account_id = $params['custom']['account_id']; - $conditions[] = array('Account.id' => $account_id); - } - - if (isset($params['custom']['customer_id'])) { - $conditions[] = - array('Customer.id' => $params['custom']['customer_id']); - } - - if (isset($params['custom']['lease_id'])) { - $conditions[] = - array('Lease.id' => $params['custom']['lease_id']); - } - - if (isset($params['custom']['transaction_id'])) { - $conditions[] = - array('Transaction.id' => $params['custom']['transaction_id']); - } - - return $conditions; - } - - function jqGridRecordLinks(&$params, &$model, &$records, $links) { - $links['Transaction'] = array('id'); - $links['Entry'] = 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) { - 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[] = 'Entry.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['group'] = array('AppliedPayment.id'); - $tquery['fields'] = array("IF(Entry.type = 'CHARGE',", - " SUM(COALESCE(AppliedCharge.amount,0)),", - " SUM(COALESCE(AppliedPayment.amount,0)))", - " AS 'applied'", - - "Charge.amount - (", - "IF(Entry.type = 'CHARGE',", - " SUM(COALESCE(AppliedCharge.amount,0)),", - " SUM(COALESCE(AppliedPayment.amount,0)))", - ") AS 'balance'", - ); - - $total = $model->find('first', $tquery); - $params['userdata']['total'] = $total[0]['applied']; - $params['userdata']['balance'] = $total[0]['balance']; - } - - return parent::jqGridDataRecords($params, $model, $query); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: reverse the ledger entry - */ - - function reverse($id) { - $this->DoubleEntry->reverse($id); - $this->redirect(array('action'=>'view', $id)); - } - - /************************************************************************** ************************************************************************** ************************************************************************** @@ -229,107 +32,13 @@ class DoubleEntriesController extends AppController { // Get the Entry and related fields $entry = $this->DoubleEntry->find ('first', - array('contain' => array - ('Transaction' => array('fields' => array('id', 'stamp')), - 'Customer' => array('fields' => array('id', 'name')), - 'Lease' => array('fields' => array('id')), - 'DebitLedger' => array('fields' => array('id', 'sequence'), - 'Account' => array('id', 'name', 'type', 'trackable')), - 'CreditLedger' => array('fields' => array('id', 'sequence'), - 'Account' => array('id', 'name', 'type', 'trackable')), - 'DebitEntry'/* => array('fields' => array('id'))*/, - 'CreditEntry'/* => array('fields' => array('id'))*/, - 'Entry' => array('fields' => array('id')), - ), - - //'fields' => array('DoubleEntry.*'), - + array('contain' => array('DebitEntry', 'CreditEntry'), 'conditions' => array('DoubleEntry.id' => $id), )); - pr($entry); - - $stats = $this->DoubleEntry->stats($id); - - foreach (array('debit', 'credit') AS $crdr) { - $CrDr = ucfirst($crdr); - $entry[$CrDr.'Ledger']['Account']['ftype'] = - $this->DoubleEntry->Ledger->Account->fundamentalType - ($entry[$CrDr.'Ledger']['Account']['type']); - - $stats[$crdr]['amount_reconciled'] = null; - $stats[$crdr]['amount_remaining'] = null; - } - -/* // Get the reconciliation balances for this ledger entry */ -/* $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['Entry']['amount'] - $stats['debit']['amount_reconciled']; */ -/* if ($entry['CreditLedger']['Account']['trackable']) */ -/* $stats['credit']['amount_remaining'] = $entry['Entry']['amount'] - $stats['credit']['amount_reconciled']; */ -/* //pr($stats); */ - -/* $reconciled = $this->DoubleEntry->findReconciledDoubleEntries($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->DoubleEntry->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['DoubleEntry']['id']}"; - $this->set(compact('entry', 'title', 'reconciled', 'stats')); - } - - function tst($id = null) { - $entry = $this->DoubleEntry->find - ('first', - array('contain' => array('Account', - - 'DoubleEntry', - - 'Payment' => array('fields' => array('Payment.*'/*, 'AppliedPayment.*'*/), - 'DoubleEntry'/* => array('alias' => 'PaymentDoubleEntry')*/), - 'Charge' => array('fields' => array('Charge.*'/*, 'AppliedCharge.*'*/), - 'DoubleEntry'/* => array('alias' => 'ChargeDoubleEntry')*/), - ), - 'conditions' => array('Entry.id' => $id), - )); - pr($entry); + $this->set(compact('entry', 'title')); } } diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index 29ec349..2dc4da3 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -57,31 +57,15 @@ class LeasesController extends AppController { function jqGridDataTables(&$params, &$model) { $link = $this->jqGridDataCountTables($params, $model); - $link['link']['DoubleEntry'] = array('fields' => array()); - $link['link']['DoubleEntry']['Ledger'] = array('fields' => array()); - $link['link']['DoubleEntry']['Ledger']['Account'] = array('fields' => array()); - // INNER JOIN would be great, as it would ensure we're only looking - // at the ledger entries that we truly want. However, this also - // removes from the query any leases that do not yet have a ledger - // entry in A/R. A solution would be to INNER JOIN these tables, - // and LEFT JOIN it to the rest. Grouping of JOINs, however, is - // implemented with the 'joins' tag, and is not available through - // the Linkable behavior interface. - //$link['link']['DoubleEntry']['Ledger']['Account']['type'] = 'INNER'; - $link['link']['DoubleEntry']['Ledger']['Account']['conditions'] - = array('Account.id' => - $this->Lease->DoubleEntry->Ledger->Account->accountReceivableAccountID()); + $link['link']['StatementEntry'] = array('fields' => array()); return $link; } function jqGridDataFields(&$params, &$model) { $db = &$model->getDataSource(); $fields = $db->fields($model, $model->alias); - $fields[] = ("SUM(IF(Account.id IS NULL, 0," . - " IF(DoubleEntry.debit_ledger_id = Account.id," . - " 1, -1))" . - " * IF(DoubleEntry.amount IS NULL, 0, DoubleEntry.amount))" . - " AS 'balance'"); + $fields = array_merge($fields, + $this->Lease->StatementEntry->chargePaymentFields(true)); return $fields; } @@ -95,6 +79,9 @@ class LeasesController extends AppController { $conditions[] = 'Lease.close_date IS NOT NULL'; } + if (isset($params['custom']['customer_id'])) + $conditions[] = array('Lease.customer_id' => $params['custom']['customer_id']); + return $conditions; } @@ -252,10 +239,10 @@ class LeasesController extends AppController { $receipt_transaction = array_intersect_key($this->data, array('Transaction'=>1, 'transaction_id'=>1)); - foreach ($data['DoubleEntry'] AS $entry) { + foreach ($data['StatementEntry'] AS $entry) { // Create the receipt entry, and reconcile the credit side // of the double-entry (which should be A/R) as a payment. - $ids = $this->DoubleEntry->Ledger->Account->postDoubleEntry + $ids = $this->StatementEntry->Ledger->Account->postLedgerEntry ($receipt_transaction, array_intersect_key($entry, array('MonetarySource'=>1)) + array_intersect_key($entry, array('account_id'=>1)), diff --git a/site/controllers/entries_controller.php b/site/controllers/ledger_entries_controller.php similarity index 96% rename from site/controllers/entries_controller.php rename to site/controllers/ledger_entries_controller.php index 64ed2d4..0a8cec2 100644 --- a/site/controllers/entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -1,6 +1,6 @@ array(// Models 'Account', - 'DoubleEntry', + 'LedgerEntry', 'Close', ), ); @@ -67,7 +67,7 @@ class LedgersController extends AppController { function jqGridDataFields(&$params, &$model) { return array_merge(array('Ledger.*', 'CONCAT(Account.id, "-", Ledger.sequence) AS id_sequence'), - $this->Ledger->DoubleEntry->debitCreditFields(true)); + $this->Ledger->LedgerEntry->debitCreditFields(true)); } function jqGridDataConditions(&$params, &$model) { diff --git a/site/controllers/statement_entries_controller.php b/site/controllers/statement_entries_controller.php new file mode 100644 index 0000000..00395b3 --- /dev/null +++ b/site/controllers/statement_entries_controller.php @@ -0,0 +1,292 @@ +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); + } + + function jqGridDataTables(&$params, &$model) { + $link = + array(// Models + 'Transaction' => + array('fields' => array('id', 'stamp'), + ), + + 'Customer' => + array('fields' => array('id', 'name'), + ), + + 'Lease' => + array('fields' => array('id', 'number'), + 'Unit' => + array('fields' => array('id', 'name'), + ), + ), + + 'Account' => + array('fields' => array('id', 'name', 'type'), + ), + ); + + if (isset($params['custom']['statement_entry_id'])) { + $link['PaymentEntry'] = array(); + $link['ChargeEntry'] = array(); + } +/* if (count(array_intersect($params['fields'], array('applied'))) == 1) { */ +/* $link['PaymentEntry'] = array(); */ +/* $link['ChargeEntry'] = array(); */ +/* } */ +/* elseif (isset($params['custom']['customer_id']) || isset($params['custom']['lease_id'])) { */ +/* $link['PaymentEntry'] = array(); */ +/* } */ + + return array('link' => $link); + } + + function jqGridDataFields(&$params, &$model) { + $fields = parent::jqGridDataFields($params, $model); + + if (!isset($fields)) + $fields = array('StatementEntry.*'); + +/* if (isset($params['custom']['reconcile_id'])) { */ +/* $fields[] = array("IF(StatementEntry.type = 'CHARGE',", */ +/* " COALESCE(AppliedCharge.amount,0),", */ +/* " COALESCE(AppliedPayment.amount,0))", */ +/* " AS 'applied'"); */ +/* $fields[] = array("StatementEntry.amount - (", */ +/* "IF(StatementEntry.type = 'CHARGE',", */ +/* " COALESCE(AppliedCharge.amount,0),", */ +/* " COALESCE(AppliedPayment.amount,0))", */ +/* ") AS 'balance'"); */ +/* } */ + + if (isset($params['custom']['customer_id']) || isset($params['custom']['lease_id']) + || isset($params['custom']['statement_entry_id'])) { + $fields = array_merge($fields, + $this->StatementEntry->chargePaymentFields()); + } + + if ($params['action'] === 'collected') + $fields[] = 'MAX(Receipt.stamp) AS last_paid'; + + return $fields; + } + + function jqGridDataConditions(&$params, &$model) { + $conditions = parent::jqGridDataConditions($params, $model); + extract($params['custom']); + + if (isset($transaction_id)) + $conditions[] = array('Transaction.id' => $transaction_id); + + if (isset($account_id)) + $conditions[] = array('Account.id' => $account_id); + + if (isset($customer_id)) + $conditions[] = array('Customer.id' => $customer_id); + + if (isset($lease_id)) + $conditions[] = array('Lease.id' => $lease_id); + + if (!empty($from_date)) + $conditions[] + = array('Transaction.stamp >=' => + $this->StatementEntry->Transaction->dateFormatBeforeSave($from_date)); + + if (!empty($through_date)) + $conditions[] + = array('Transaction.stamp <=' => + $this->StatementEntry->Transaction->dateFormatBeforeSave($through_date . ' 23:59:59')); + + if (isset($payment_accounts)) + $conditions[] = array('PaymentEntry.account_id' => $payment_accounts); + + if (isset($charge_accounts)) + $conditions[] = array('ChargeEntry.account_id' => $charge_accounts); + + if (isset($statement_entry_id)) { + $conditions[] = array('OR' => + array(array('ChargeEntry.id' => $statement_entry_id), + array('PaymentEntry.id' => $statement_entry_id))); + } + + return $conditions; + } + + function jqGridRecordLinks(&$params, &$model, &$records, $links) { + $links['StatementEntry'] = array('id'); + $links['Transaction'] = array('id'); + $links['Account'] = 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) { + return parent::jqGridDataGroup($params, $model); + } + + function jqGridDataOrder(&$params, &$model, $index, $direction) { + $order = parent::jqGridDataOrder($params, $model, $index, $direction); + + if ($index === 'Transaction.stamp') + $order[] = 'StatementEntry.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['group'] = array('AppliedPayment.id'); + $tquery['fields'] = array("IF(StatementEntry.type = 'CHARGE',", + " SUM(COALESCE(PaymentEntry.amount,0)),", + " SUM(COALESCE(ChargeEntry.amount,0)))", + " AS 'applied'", + + "StatementEntry.amount - (", + "IF(StatementEntry.type = 'CHARGE',", + " SUM(COALESCE(PaymentEntry.amount,0)),", + " SUM(COALESCE(ChargeEntry.amount,0)))", + ") AS 'balance'", + ); + + $total = $model->find('first', $tquery); + $params['userdata']['total'] = $total[0]['applied']; + $params['userdata']['balance'] = $total[0]['balance']; + } + + return parent::jqGridDataRecords($params, $model, $query); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: reverse the ledger entry + */ + + function reverse($id) { + $this->StatementEntry->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 StatementEntry and related fields + $entry = $this->StatementEntry->find + ('first', + array('contain' => array + ('Transaction' => array('fields' => array('id', 'stamp')), + 'Account' => array('id', 'name', 'type', 'trackable'), + 'Customer' => array('fields' => array('id', 'name')), + 'Lease' => array('fields' => array('id')), + ), + + 'conditions' => array('StatementEntry.id' => $id), + )); + + $reconciled = $this->StatementEntry->reconciledEntries($id); + + +/* // 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->StatementEntry->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)); */ +/* } */ + + $stats = $this->StatementEntry->stats($id); + pr($stats); + + // Prepare to render. + $title = "Statement Entry #{$entry['StatementEntry']['id']}"; + $this->set(compact('entry', 'title', 'reconciled', 'stats')); + } + + function tst($id = null) { + $entry = $this->StatementEntry->find + ('first', + array('contain' => array('Account', + + 'DoubleStatementEntry', + + 'Payment' => array('fields' => array('Payment.*'/*, 'AppliedPayment.*'*/), + 'DoubleStatementEntry'/* => array('alias' => 'PaymentDoubleStatementEntry')*/), + 'Charge' => array('fields' => array('Charge.*'/*, 'AppliedCharge.*'*/), + 'DoubleStatementEntry'/* => array('alias' => 'ChargeDoubleStatementEntry')*/), + ), + 'conditions' => array('StatementEntry.id' => $id), + )); + pr($entry); + } + +} diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php index f5d2053..87c8895 100644 --- a/site/controllers/transactions_controller.php +++ b/site/controllers/transactions_controller.php @@ -64,31 +64,19 @@ class TransactionsController extends AppController { ('first', array('contain' => array(// Models - 'LedgerEntry' => array('fields' => array('LedgerEntry.id', - 'LedgerEntry.amount', - 'LedgerEntry.comment'), - //Models - - 'DebitLedger' => array - ('fields' => array('DebitLedger.id', 'DebitLedger.sequence'), - 'Account' => array - ('fields' => array('Account.id', 'Account.name')), - ), - - 'CreditLedger' => array - ('fields' => array('CreditLedger.id', 'CreditLedger.sequence'), - 'Account' => array - ('fields' => array('Account.id', 'Account.name')), - ), - ), + 'LedgerEntry' => + array('fields' => array('LedgerEntry.id', + 'LedgerEntry.amount', + 'LedgerEntry.comment'), + ), ), 'conditions' => array('Transaction.id' => $id), )); - // Figure out the transaction total - $total = 0; - foreach($transaction['LedgerEntry'] AS $entry) - $total += $entry['amount']; +/* // Figure out the transaction total */ +/* $total = 0; */ +/* foreach($transaction['LedgerEntry'] AS $entry) */ +/* $total += $entry['amount']; */ // OK, prepare to render. $title = 'Transaction #' . $transaction['Transaction']['id']; @@ -145,6 +133,7 @@ class TransactionsController extends AppController { } pr($this->data); + if (!$this->Transaction->addReceipt($this->data, $this->data['Customer']['id'], (isset($this->data['Lease']['id']) diff --git a/site/models/account.php b/site/models/account.php index d2f4d0d..fe87390 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -16,6 +16,7 @@ class Account extends AppModel { var $hasMany = array( 'Ledger', + 'LedgerEntry', ); @@ -105,30 +106,10 @@ class Account extends AppModel { * entries are a debit, or a credit, and also the effect each have * on the overall balance of the account. */ - function debitCreditFields($id, $sum = false, - $entry_name = 'Entry', $double_name = 'DoubleEntry') { - $ftype = strtoupper($this->fundamentalType($id)); - $fields = array - ( - ($sum ? 'SUM(' : '') . - "IF({$entry_name}.crdr = 'DEBIT', {$double_name}.amount, NULL)" . - ($sum ? ')' : '') . ' AS debit' . ($sum ? 's' : ''), - - ($sum ? 'SUM(' : '') . - "IF({$entry_name}.crdr = 'CREDIT', {$double_name}.amount, NULL)" . - ($sum ? ')' : '') . ' AS credit' . ($sum ? 's' : ''), - - ($sum ? 'SUM(' : '') . - "IF({$entry_name}.crdr = '$ftype', 1, -1) * {$double_name}.amount" . - // IF({$double_name}.amount, {$double_name}.amount, 0)" . - ($sum ? ')' : '') . ' AS balance', - ); - - if ($sum) - $fields[] = "COUNT({$entry_name}.id) AS entries"; - - return $fields; + function debitCreditFields($sum = false, $entry_name = 'Entry', $account_name = 'Account') { + return $this->LedgerEntry->debitCreditFields + ($sum, $entry_name, $account_name); } @@ -410,7 +391,7 @@ class Account extends AppModel { $unreconciled = $this->unreconciledEntries($id, 'CHARGE', $cond, $link); foreach ($unreconciled AS $i => &$item) { - $entry =& $item['DoubleEntry']; + $entry =& $item['LedgerEntry']; // Determine if amount is sufficient to cover the entry if ($amount > $entry['balance']) $apply = $entry['balance']; @@ -509,7 +490,7 @@ class Account extends AppModel { /************************************************************************** ************************************************************************** ************************************************************************** - * function: postDoubleEntry + * function: postLedgerEntry * - * transaction_data * - transaction_id (optional... if set all else is ignored) @@ -524,7 +505,7 @@ class Account extends AppModel { * - name */ - function postDoubleEntry($transaction_data, + function postLedgerEntry($transaction_data, $monetary_data, $entry_data, $reconcile = null) { @@ -577,7 +558,7 @@ class Account extends AppModel { // No distinguishing features of Cash, just // use the shared monetary source $monetary_data['monetary_source_id'] = - $this->Ledger->DoubleEntry->MonetarySource->nameToID('Cash'); + $this->Ledger->LedgerEntry->MonetarySource->nameToID('Cash'); } } @@ -645,7 +626,7 @@ class Account extends AppModel { //pr(array('pre-save', compact('entry_data'))); // Create it! - $new_entry = new DoubleEntry(); + $new_entry = new LedgerEntry(); $new_entry->create(); if (!$new_entry->saveAll($entry_data, array('validate'=>false))) { return array('error' => true); @@ -700,7 +681,7 @@ class Account extends AppModel { // Payment must debit the Receipt ledger, and credit the A/R ledger // debit: Receipt credit: A/R - $ids = $this->postDoubleEntry + $ids = $this->postLedgerEntry ($split_transaction, null, array('debit_ledger_id' => $this->currentLedgerID($this->receiptAccountID()), @@ -709,9 +690,9 @@ class Account extends AppModel { 'lease_id' => $rec['lease_id'], 'customer_id' => $rec['customer_id'], ), - array('debit' => array(array('DoubleEntry' => array('id' => $new_entry->id, + array('debit' => array(array('LedgerEntry' => array('id' => $new_entry->id, 'amount' => $rec['applied']))), - 'credit' => array(array('DoubleEntry' => array('id' => $rec['id'], + 'credit' => array(array('LedgerEntry' => array('id' => $rec['id'], 'amount' => $rec['applied'])))) ); // Keep using the same split transaction for all reconciled entries @@ -728,19 +709,19 @@ class Account extends AppModel { if (is_array($reconcile_set)) { //pr("reconcile_set is array"); foreach ($reconcile_set AS $reconcile_entry) { - if (!isset($reconcile_entry['DoubleEntry']['id'])) + if (!isset($reconcile_entry['LedgerEntry']['id'])) continue; - $amount = $reconcile_entry['DoubleEntry']['amount']; + $amount = $reconcile_entry['LedgerEntry']['amount']; if (!$amount) continue; if ($dc_type == 'debit') { $debit_ledger_entry_id = $new_entry->id; - $credit_ledger_entry_id = $reconcile_entry['DoubleEntry']['id']; + $credit_ledger_entry_id = $reconcile_entry['LedgerEntry']['id']; } else { - $debit_ledger_entry_id = $reconcile_entry['DoubleEntry']['id']; + $debit_ledger_entry_id = $reconcile_entry['LedgerEntry']['id']; $credit_ledger_entry_id = $new_entry->id; } @@ -760,9 +741,9 @@ class Account extends AppModel { $ret = array ('error' => $err, - 'id' => $new_entry->data['DoubleEntry']['id'], - 'transaction_id' => $new_entry->data['DoubleEntry']['transaction_id'], - 'monetary_source_id' => $new_entry->data['DoubleEntry']['monetary_source_id']); + 'id' => $new_entry->data['LedgerEntry']['id'], + 'transaction_id' => $new_entry->data['LedgerEntry']['transaction_id'], + 'monetary_source_id' => $new_entry->data['LedgerEntry']['monetary_source_id']); if (isset($split_transaction['transaction_id'])) $ret['split_transaction_id'] = $split_transaction['transaction_id']; @@ -794,7 +775,7 @@ class Account extends AppModel { if ($ledger['total'] == 0) continue; - $ids = $this->postDoubleEntry + $ids = $this->postLedgerEntry ($transaction, null, array('debit_account_id' => $deposit_account_id, @@ -806,7 +787,7 @@ class Account extends AppModel { //pr(compact('ids')); if ($ids['error']) - die("closeAndDeposit : postDoubleEntry returned error!"); + die("closeAndDeposit : postLedgerEntry returned error!"); $transaction = array_intersect_key($ids, array('transaction_id'=>1)); diff --git a/site/models/double_entry.php b/site/models/double_entry.php index 800b095..4c6d84b 100644 --- a/site/models/double_entry.php +++ b/site/models/double_entry.php @@ -1,261 +1,13 @@ array('numeric'), - 'transaction_id' => array('numeric'), - 'amount' => array('money') - ); - - var $hasOne = array( + var $belongsTo = array( 'DebitEntry' => array( - 'className' => 'Entry', - 'conditions' => array('DebitEntry.crdr' => 'DEBIT'), + 'className' => 'LedgerEntry', ), 'CreditEntry' => array( - 'className' => 'Entry', - 'conditions' => array('CreditEntry.crdr' => 'CREDIT'), + 'className' => 'LedgerEntry', ), ); - var $hasMany = array( - 'Entry', - ); - - - var $belongsTo = array( - 'Transaction', - 'Invoice' => array( - 'className' => 'Transaction', - 'conditions' => array('Invoice.type' => 'INVOICE'), - 'foreignKey' => 'transaction_id', - ), - 'Receipt' => array( - 'className' => 'Transaction', - 'conditions' => array('Invoice.type' => 'RECEIPT'), - 'foreignKey' => 'transaction_id', - ), - - - '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($sum = false, $double_name = 'DoubleEntry', $ledger_name = 'Ledger', $account_name = 'Account') { - $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_name}.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; - } - } diff --git a/site/models/lease.php b/site/models/lease.php index dd19bcb..6733991 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -9,7 +9,7 @@ class Lease extends AppModel { ); var $hasMany = array( - 'DoubleEntry', + 'StatementEntry', ); @@ -22,21 +22,19 @@ class Lease extends AppModel { function securityDeposits($id, $query = null) { $this->queryInit($query); - $this->id = $id; - $this->recursive = -1; - $this->read(); + $A = new Account(); - if (!isset($query['link']['DoubleEntry'])) - $query['link']['DoubleEntry'] = array(); - if (!isset($query['link']['DoubleEntry']['Lease'])) - $query['link']['DoubleEntry']['Lease'] = array(); - if (!isset($query['link']['DoubleEntry']['Lease']['fields'])) - $query['link']['DoubleEntry']['Lease']['fields'] = array(); + if (!isset($query['link']['Lease'])) + $query['link']['Lease'] = array(); + if (!isset($query['link']['Lease']['fields'])) + $query['link']['Lease']['fields'] = array(); $query['conditions'][] = array('Lease.id' => $id); + $query['conditions'][] = array('StatementEntry.account_id' => $A->securityDepositAccountID()); - return $this->Customer->securityDeposits - ($this->data['Lease']['customer_id'], $query); + $set = $this->StatementEntry->reconciledSet('CHARGE', $query); + //pr(compact('set')); + return $set; } @@ -52,40 +50,28 @@ class Lease extends AppModel { */ function rentLastCharges($id) { - $rent_account_id = $this->DoubleEntry->Entry->Account->rentAccountID(); + $rent_account_id = $this->StatementEntry->Account->rentAccountID(); $entries = $this->find ('all', array('link' => array(// Models - 'DoubleEntry' => - array('Entry'// => - //array('fields'), - ), + 'StatementEntry' => array(), - 'DEx' => - array('class' => 'DoubleEntry', + 'SEx' => + array('class' => 'StatementEntry', 'conditions' => array - ('DEx.effective_date = DATE_ADD(Entry.through_date, INTERVAL 1 day)', - 'DEx.lease_id = DoubleEntry.lease_id', + ('SEx.effective_date = DATE_ADD(StatementEntry.through_date, INTERVAL 1 day)', + 'SEx.lease_id = StatementEntry.lease_id', ), - - 'Ex' => - array('class' => 'Entry', - 'type' => 'INNER', - 'conditions' => array - ('Ex.account_id = Entry.account_id', - 'Ex.type = Entry.type', - 'Ex.crdr = Entry.crdr'), - ), ), ), //'fields' => array('id', 'amount', 'effective_date', 'through_date'), 'fields' => array(), 'conditions' => array(array('Lease.id' => $id), - array('Entry.type' => 'CHARGE'), - array('Entry.account_id' => $rent_account_id), - array('DEx.id' => null), + array('StatementEntry.type' => 'CHARGE'), + array('StatementEntry.account_id' => $rent_account_id), + array('SEx.id' => null), ), ) ); @@ -125,7 +111,7 @@ class Lease extends AppModel { return false; if (count($entries) != 1) return null; - return $entries[0]['DoubleEntry']['through_date']; + return $entries[0]['StatementEntry']['through_date']; } @@ -137,76 +123,77 @@ class Lease extends AppModel { */ function rentPaidThrough($id) { - $rent_account_id = $this->DoubleEntry->Entry->Account->rentAccountID(); + $rent_account_id = $this->StatementEntry->Account->rentAccountID(); - $rent = $this->DoubleEntry->Entry->reconciledSet + $rent = $this->StatementEntry->reconciledSet ('CHARGE', array('fields' => - array('DATE_SUB(DoubleEntry.effective_date, INTERVAL 1 DAY) AS paid_through', + array('StatementEntry.*', + 'DATE_SUB(StatementEntry.effective_date, INTERVAL 1 DAY) AS paid_through', ), 'conditions' => - array(array('DoubleEntry.lease_id' => $id), - array('Entry.account_id' => $rent_account_id)), + array(array('StatementEntry.lease_id' => $id), + array('StatementEntry.account_id' => $rent_account_id)), - 'order' => array('DoubleEntry.effective_date'), + 'order' => array('StatementEntry.effective_date'), ), true); /* $query = array */ /* ('link' => */ /* array(// Models */ -/* 'DoubleEntry' => */ +/* 'StatementEntry' => */ /* array('Entry' => */ /* array(), */ -/* 'fields' => array('SUM(COALESCE(MoneyDoubleEntryR.amount,0)) AS paid'), */ +/* 'fields' => array('SUM(COALESCE(MoneyStatementEntryR.amount,0)) AS paid'), */ /* ), */ /* ), */ /* // Finally, the Money (Cash/Check/etc) Entry is the one */ -/* // which reconciles our ReceiptDoubleEntry debit */ -/* 'DebitReconciliationDoubleEntry' => */ -/* array('alias' => 'MoneyDoubleEntry', */ -/* 'linkalias' => 'MoneyDoubleEntryR', */ +/* // which reconciles our ReceiptStatementEntry debit */ +/* 'DebitReconciliationStatementEntry' => */ +/* array('alias' => 'MoneyStatementEntry', */ +/* 'linkalias' => 'MoneyStatementEntryR', */ /* ), */ /* ), */ /* ), */ -/* 'fields' => array('DoubleEntry.amount', */ -/* 'DATE_SUB(DoubleEntry.effective_date, INTERVAL 1 DAY) AS paid_through', */ +/* 'fields' => array('StatementEntry.amount', */ +/* 'DATE_SUB(StatementEntry.effective_date, INTERVAL 1 DAY) AS paid_through', */ /* ), */ -/* 'group' => 'DoubleEntry.id HAVING paid <> DoubleEntry.amount', */ +/* 'group' => 'StatementEntry.id HAVING paid <> StatementEntry.amount', */ -/* 'conditions' => array(array('DoubleEntry.lease_id' => $id), */ -/* array('Account.id' => $this->DoubleEntry->Ledger->Account->rentAccountID()), */ +/* 'conditions' => array(array('StatementEntry.lease_id' => $id), */ +/* array('Account.id' => $this->StatementEntry->Ledger->Account->rentAccountID()), */ /* ), */ -/* 'order' => array('DoubleEntry.effective_date', */ +/* 'order' => array('StatementEntry.effective_date', */ /* ), */ /* ); */ -/* $rent = $this->DoubleEntry->find('first', $query); */ +/* $rent = $this->StatementEntry->find('first', $query); */ //pr($rent); if ($rent['entries']) - return $rent['entries'][0]['DoubleEntry']['paid_through']; + return $rent['entries'][0]['StatementEntry']['paid_through']; - $rent = $this->DoubleEntry->Entry->reconciledSet + $rent = $this->StatementEntry->reconciledSet ('CHARGE', array('conditions' => - array(array('DoubleEntry.lease_id' => $id), - array('Entry.account_id' => $rent_account_id)), + array(array('StatementEntry.lease_id' => $id), + array('StatementEntry.account_id' => $rent_account_id)), 'order' => array('Entry.through_date DESC'), ), false); if ($rent) - return $rent[0]['Entry']['through_date']; + return $rent[0]['StatementEntry']['through_date']; /* $query['fields'] = 'Entry.through_date'; */ /* $query['order'] = 'Entry.through_date DESC'; */ -/* $query['group'] = 'DoubleEntry.id'; */ -/* $rent = $this->DoubleEntry->find('first', $query); */ +/* $query['group'] = 'StatementEntry.id'; */ +/* $rent = $this->StatementEntry->find('first', $query); */ /* if ($rent) */ -/* return $rent['DoubleEntry']['through_date']; */ +/* return $rent['StatementEntry']['through_date']; */ return null; } @@ -416,43 +403,28 @@ class Lease extends AppModel { $this->queryInit($query); //$query['link'] = array('Lease' => $query['link']); - if (!isset($query['link']['DoubleEntry'])) - $query['link']['DoubleEntry'] = array(); - if (!isset($query['link']['Charge'])) - $query['link']['Charge'] = array(); - if (!isset($query['link']['Charge']['DoubleEntry'])) - $query['link']['Charge']['DoubleEntry'] = array(); - if (!isset($query['link']['Charge']['DoubleEntry']['Invoice'])) - $query['link']['Charge']['DoubleEntry']['Invoice'] = array(); - if (!isset($query['link']['Charge']['Account'])) - $query['link']['Charge']['Account'] = array(); +/* if (!isset($query['link']['StatementEntry'])) */ +/* $query['link']['StatementEntry'] = array(); */ +/* if (!isset($query['link']['StatementEntry']['ChargeEntry'])) */ +/* $query['link']['StatementEntry']['ChargeEntry'] = array(); */ -/* $query['link']['DoubleEntry']['fields'] = array(); */ -/* $query['link']['Charge']['fields'] = array(); */ -/* $query['link']['Charge']['Account']['fields'] = array(); */ -/* $query['link']['Charge']['DoubleEntry']['fields'] = array(); */ -/* $query['link']['Charge']['DoubleEntry']['Invoice']['fields'] = array(); */ - - $query['link']['Charge']['Account']['alias'] = 'ChargeAccount'; - $query['link']['Charge']['DoubleEntry']['alias'] = 'ChargeDoubleEntry'; +/* $query['link']['StatementEntry']['fields'] = array(); */ +/* $query['link']['ChargeEntry']['fields'] = array(); */ +/* $query['link']['ChargeEntry']['Account']['fields'] = array(); */ +/* $query['link']['ChargeEntry']['StatementEntry']['fields'] = array(); */ +/* $query['link']['ChargeEntry']['StatementEntry']['Invoice']['fields'] = array(); */ if (!isset($query['fields'])) $query['fields'] = array(); $query['fields'] = array_merge($query['fields'], - $this->DoubleEntry->Entry->chargePaymentFields(false)); + $this->StatementEntry->chargePaymentFields(true)); - $query['conditions'][] = array('OR' => - array(array(array('Entry.type' => 'CHARGE'), - array('DoubleEntry.lease_id' => $id)), - array(array('Entry.type' => 'PAYMENT'), - array('ChargeDoubleEntry.lease_id' => $id)), - ), - ); + $query['conditions'][] = array('StatementEntry.lease_id' => $id); $query['group'] = null; - $stats = $this->DoubleEntry->Entry->find('all', $query); + $stats = $this->StatementEntry->find('first', $query); pr(compact('query', 'stats')); // The fields are all tucked into the [0] index, diff --git a/site/models/ledger.php b/site/models/ledger.php index e2a53b0..5d97669 100644 --- a/site/models/ledger.php +++ b/site/models/ledger.php @@ -8,27 +8,8 @@ class Ledger extends AppModel { ); var $hasMany = array( - 'Entry', - - 'DoubleEntry' => array( - 'foreignKey' => false, - - // conditions will be used when JOINing tables - // (such as find with LinkableBehavior) - 'conditions' => array('OR' => - array('DoubleEntry.debit_ledger_id = %{MODEL_ALIAS}.id', - 'DoubleEntry.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 `DoubleEntry`.* - FROM pmgr_double_entries AS `DoubleEntry` - WHERE DoubleEntry.debit_ledger_id = ({$__cakeID__$}) - OR DoubleEntry.credit_ledger_id = ({$__cakeID__$})', - - 'counterQuery' => '' - ), + 'Transaction', + 'LedgerEntry', ); @@ -111,7 +92,7 @@ class Ledger extends AppModel { 'comment' => "Ledger Balance Forward", ); - $carry_entry = new DoubleEntry(); + $carry_entry = new LedgerEntry(); $carry_entry->create(); if (!$carry_entry->save($carry_entry_data, false)) { return null; @@ -129,10 +110,9 @@ class Ledger extends AppModel { * entries are a debit, or a credit, and also the effect each have * on the overall balance of the ledger. */ - function debitCreditFields($id, $sum = false, - $entry_name = 'Entry', $double_name = 'DoubleEntry') { - return $this->Account->debitCreditFields - ($this->accountID($id), $sum, $entry_name, $double_name); + function debitCreditFields($sum = false, $entry_name = 'Entry', $account_name = 'Account') { + return $this->LedgerEntry->debitCreditFields + ($sum, $entry_name, $account_name); } /************************************************************************** @@ -142,23 +122,16 @@ class Ledger extends AppModel { * - Returns an array of ledger entries that belong to a given * ledger. There is extra work done to establish debit/credit */ - function ledgerEntries($ids, $cond = null, $link = null) { + function ledgerEntries($ids, $query = null) { if (empty($ids)) return null; -/* $id = (is_array($ids) ? $ids[0] : $ids); */ -/* $ftype = strtoupper($this->Account->fundamentalType($this->accountID($id))); */ - - $entries = $this->Entry->find + $entries = $this->LedgerEntry->find ('all', array - ('contain' => array('DoubleEntry' => array('fields' => array('amount'))), - 'fields' => array_merge(array("Entry.*"), - $this->debitCreditFields(is_array($ids) ? $ids[0] : $ids)), -/* "IF(Entry.crdr = 'CREDIT', DoubleEntry.amount, NULL) AS credit", */ -/* "IF(Entry.crdr = 'DEBIT', DoubleEntry.amount, NULL) AS debit", */ -/* "IF(Entry.crdr = '$ftype', 1, -1) * DoubleEntry.amount AS balance", */ - - 'conditions' => array('Entry.ledger_id' => $ids), + ('contain' => array('Ledger' => array('Account')), + 'fields' => array_merge(array("LedgerEntry.*"), + $this->LedgerEntry->debitCreditFields()), + 'conditions' => array('LedgerEntry.ledger_id' => $ids), )); //pr(compact('entries')); @@ -178,37 +151,37 @@ class Ledger extends AppModel { $this->queryInit($query); - if (!isset($query['link']['Account'])) - $query['link']['Account'] = array(); - if (!isset($query['link']['Account']['fields'])) - $query['link']['Account']['fields'] = array(); - if (!isset($query['link']['Entry'])) - $query['link']['Entry'] = array(); - if (!isset($query['link']['Entry']['DoubleEntry'])) - $query['link']['Entry']['DoubleEntry'] = array(); - if (!isset($query['link']['Entry']['DoubleEntry']['fields'])) - $query['link']['Entry']['DoubleEntry']['fields'] = array(); - if (!isset($query['link']['Entry']['DoubleEntry']['Transaction'])) - $query['link']['Entry']['DoubleEntry']['Transaction'] = array(); - if (!isset($query['link']['Entry']['DoubleEntry']['Transaction']['fields'])) - $query['link']['Entry']['DoubleEntry']['Transaction']['fields'] = array(); - $query['link']['Entry']['DoubleEntry']['Transaction']['fields'][] = 'stamp'; + if (!isset($query['link']['Ledger'])) + $query['link']['Ledger'] = array(); + if (!isset($query['link']['Ledger']['fields'])) + $query['link']['Ledger']['fields'] = array(); + if (!isset($query['link']['Ledger']['Account'])) + $query['link']['Ledger']['Account'] = array(); + if (!isset($query['link']['Ledger']['Account']['fields'])) + $query['link']['Ledger']['Account']['fields'] = array(); +/* if (!isset($query['link']['Transaction'])) */ +/* $query['link']['Transaction'] = array(); */ +/* if (!isset($query['link']['Transaction']['fields'])) */ +/* $query['link']['Transaction']['fields'] = array(); */ +/* $query['link']['Transaction']['fields'][] = 'stamp'; */ if (!isset($query['fields'])) $query['fields'] = array(); $query['fields'] = array_merge($query['fields'], - $this->debitCreditFields($id, true)); + $this->debitCreditFields(true)); - $query['conditions'][] = array('Ledger.id' => $id); - $query['group'][] = 'Ledger.id'; + $query['conditions'][] = array('LedgerEntry.ledger_id' => $id); + $query['group'][] = 'LedgerEntry.ledger_id'; - $stats = $this->find('first', $query); + $stats = $this->LedgerEntry->find('first', $query); + pr(compact('stats')); - unset($query['group']); - $query['fields'] = $this->debitCreditFields($id, false); - $stats = $this->find('all', $query); - pr(compact('query', 'stats')); + +/* unset($query['group']); */ +/* $query['fields'] = $this->debitCreditFields($id, false); */ +/* $stats = $this->find('all', $query); */ +/* pr(compact('query', 'stats')); */ // The fields are all tucked into the [0] index, // and the rest of the array is useless (empty). diff --git a/site/models/ledger_entry.php b/site/models/ledger_entry.php new file mode 100644 index 0000000..f426d95 --- /dev/null +++ b/site/models/ledger_entry.php @@ -0,0 +1,320 @@ + 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, $entry_name = 'Entry', $account_name = 'Account') { + $fields = array + ( + ($sum ? 'SUM(' : '') . + "IF({$entry_name}.type = 'DEBIT'," . + " {$entry_name}.amount, NULL)" . + ($sum ? ')' : '') . ' AS debit' . ($sum ? 's' : ''), + + ($sum ? 'SUM(' : '') . + "IF({$entry_name}.type = 'CREDIT'," . + " {$entry_name}.amount, NULL)" . + ($sum ? ')' : '') . ' AS credit' . ($sum ? 's' : ''), + + ($sum ? 'SUM(' : '') . + "IF(${account_name}.type IN ('ASSET', 'EXPENSE')," . + " IF({$entry_name}.type = 'DEBIT', 1, -1)," . + " IF({$entry_name}.type = '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: addCharge + * - Adds a new charge + */ + + function addCharge($data, $transaction, $customer_id, $lease_id = null) { + // Create some models for convenience + $A = new Account(); + + // Assume this will succeed + $ret = true; + + // Establish the key charge parameters + $charge = array_intersect_key($data, array('stamp'=>1, 'amount'=>1, 'account_id'=>1)); + + $charge['customer_id'] = $customer_id; + $charge['lease_id'] = $lease_id; + $charge['type'] = 'CHARGE'; + + $ids = $this->Entry->Ledger->Account->postLedgerEntry + ($transaction, + $charge, + array('debit_ledger_id' => $A->currentLedgerID($data['account_id']), + 'credit_ledger_id' => $A->currentLedgerID($A->accountReceivableAccountID()) + ) + $data + ); + + if ($ids['error']) + $ret = false; + + return $ids['charge_id']; + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: addPayment + * - Adds a new payment + */ + + function addPayment($data, $transaction, $customer_id, $lease_id = null) { + // Create some models for convenience + $A = new Account(); + + // Assume this will succeed + $ret = true; + + // Establish the key payment parameters + $payment = array_intersect_key($data, array('stamp'=>1, 'name'=>1, 'monetary_type'=>1, + 'data1'=>1, 'data2'=>1, 'data3'=>1, 'data4'=>1, + 'amount'=>1, 'account_id'=>1)); + $payment['customer_id'] = $customer_id; + $payment['type'] = 'PAYMENT'; + + $ids = $this->Entry->Ledger->Account->postLedgerEntry + ($transaction, + $payment, + array('debit_ledger_id' => $A->currentLedgerID($data['account_id']), + 'credit_ledger_id' => $A->currentLedgerID($A->accountReceivableAccountID()) + ) + $data + ); + + if ($ids['error']) + $ret = false; + + return $ids['payment_id']; + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: reverse + * - Reverses the charges + * + * SAMPLE MOVE IN w/ PRE PAYMENT + * DEPOSIT RENT A/R RECEIPT CHECK PETTY BANK + * ------- ------- ------- ------- ------- ------- ------- + * |25 | 25| | | | | + * | |20 20| | | | | + * | |20 20| | | | | + * | |20 20| | | | | + * | | |25 25| | | | + * | | |20 20| | | | + * | | |20 20| | | | + * | | |20 20| | | | + * | | | |85 85| | | + * | | | | |85 | 85| + + * MOVE OUT and REFUND FINAL MONTH + * DEPOSIT RENT C/P RECEIPT CHECK PETTY BANK + * ------- ------- ------- ------- ------- ------- ------- + * 25| | |25 | | | | t20 e20a + * | 20| |20 | | | | t20 e20b + + * -ONE REFUND CHECK- + * | | 25| |25 | | | t30 e30a + * | | 20| |20 | | | t30 e30b + * | | | 45| | | |45 t40 e40 + * -OR MULTIPLE- + * | | 15| |15 | | | t50a e50a + * | | | 15| | |15 | t60a e60a + * | | 30| |30 | | | t50b e50b + * | | | 30| | | |30 t60b e60b + * | | | | | | | + + +OPTION 1 + * |-25 | -25| | | | | + * | |-20 -20| | | | | + * | | |-25 -25| | | | + * | | |-20 -20| | | | + +OPTION 2 + * |-25 | | -25| | | | + * | |-20 | -20| | | | + * | | | |-15 | -15| | + * | | | |-30 | | -30| + * | | | | | | | + * + */ + function reverse($ledger_entries, $stamp = null) { + pr(array('Entry::reverse', + compact('ledger_entries', 'stamp'))); + + // If the user only wants to reverse one ID, we'll allow it + if (!is_array($ledger_entries)) + $ledger_entries = $this->find + ('all', array + ('contain' => false, + 'conditions' => array('Entry.id' => $ledger_entries))); + + $A = new Account(); + + $ar_account_id = $A->accountReceivableAccountID(); + $receipt_account_id = $A->receiptAccountID(); + + $transaction_id = null; + foreach ($ledger_entries AS $entry) { + $entry = $entry['Entry']; + $amount = -1*$entry['amount']; + + if (isset($entry['credit_account_id'])) + $refund_account_id = $entry['credit_account_id']; + elseif (isset($entry['CreditLedger']['Account']['id'])) + $refund_account_id = $entry['CreditLedger']['Account']['id']; + elseif (isset($entry['credit_ledger_id'])) + $refund_account_id = $this->Ledger->accountID($entry['credit_ledger_id']); + else + return null; + + // post new refund in the income account + $ids = $A->postEntry + (array('transaction_id' => $transaction_id), + null, + array('debit_ledger_id' => $A->currentLedgerID($ar_account_id), + 'credit_ledger_id' => $A->currentLedgerID($refund_account_id), + 'effective_date' => $entry['effective_date'], + 'through_date' => $entry['through_date'], + 'amount' => $amount, + 'lease_id' => $entry['lease_id'], + 'customer_id' => $entry['customer_id'], + 'comment' => "Refund; Entry #{$entry['id']}", + ), + array('debit' => array + (array('Entry' => + array('id' => $entry['id'], + 'amount' => $amount))), + ) + ); + + if ($ids['error']) + return null; + $transaction_id = $ids['transaction_id']; + + pr(array('checkpoint' => 'Posted Refund Ledger Entry', + compact('ids', 'amount', 'refund_account_id', 'ar_account_id'))); + } + + return true; + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * 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', 'payment', + // 'debit', 'credit', + ); + + $stats = array(); + foreach($rtypes AS $rtype) { + $Rtype = ucfirst($rtype); + + if (($rtype == 'charge' && (!isset($set) || $set == 'PAYMENT')) || + ($rtype == 'payment' && (!isset($set) || $set == 'CHARGE')) +/* ($rtype == 'debit' && (!isset($set) || $set == 'CREDIT')) || */ +/* ($rtype == 'credit' && (!isset($set) || $set == 'DEBIT')) */ + ) { + + $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; + } + +} diff --git a/site/models/payment.php b/site/models/payment.php index 47d0785..30334d7 100644 --- a/site/models/payment.php +++ b/site/models/payment.php @@ -2,16 +2,13 @@ class Payment extends AppModel { var $belongsTo = array( - 'Customer', - 'Lease', - ); - - var $hasMany = array( - 'DoubleEntry', - ); - - var $hasAndBelongsToMany = array( - 'DoubleEntry', + 'LedgerEntry', + 'DepositTransaction' => array( + 'className' => 'Transaction', + ), + 'NsfTransaction' => array( + 'className' => 'Transaction', + ), ); @@ -36,7 +33,7 @@ class Payment extends AppModel { // Create the payment entry, and reconcile the credit side // of the double-entry (which should be A/R) as a payment. - $ids = $this->DoubleEntry->Ledger->Account->postDoubleEntry + $ids = $this->LedgerEntry->Ledger->Account->postLedgerEntry ($payment, array('debit_ledger_id' => $A->currentLedgerID($entry['account_id']), 'credit_ledger_id' => $A->currentLedgerID($A->paymentAccountID()) @@ -97,7 +94,7 @@ class Payment extends AppModel { ('first', array('contain' => array(/* e3 */ - 'DoubleEntry' => + 'LedgerEntry' => array('Transaction.id', 'Payment.id', 'Customer.id', @@ -126,7 +123,7 @@ class Payment extends AppModel { ), /* e2 */ - 'DebitReconciliationDoubleEntry' => + 'DebitReconciliationLedgerEntry' => array(/* e2 credit */ 'CreditLedger' => /* i.e. A/R Ledger */ array('fields' => array(), @@ -141,11 +138,11 @@ class Payment extends AppModel { /* e1 */ // STUPID CakePHP bug screws up CLASS contains CLASS. // Use the same class, but with different name. - 'DebitReconciliationDoubleEntry2', + 'DebitReconciliationLedgerEntry2', ), /* e4 */ - 'CreditReconciliationDoubleEntry' => + 'CreditReconciliationLedgerEntry' => array(/* e4 debit */ 'DebitLedger' => /* e.g. BANK Ledger */ array('fields' => array('id'), @@ -170,9 +167,9 @@ class Payment extends AppModel { $t4_id = null; $t5_id = null; - foreach ($source['DoubleEntry'] AS $e3) { + foreach ($source['LedgerEntry'] AS $e3) { // We expect only a single e4 entry - $e4 = $e3['CreditReconciliationDoubleEntry']; + $e4 = $e3['CreditReconciliationLedgerEntry']; if (count($e4) < 1) continue; if (count($e4) > 1) @@ -188,7 +185,7 @@ class Payment extends AppModel { $bank_account_id = $e4['DebitLedger']['account_id']; // post new e5 - $e5_ids = $A->postDoubleEntry + $e5_ids = $A->postLedgerEntry (array('transaction_id' => $t4_id), null, array('debit_ledger_id' => $A->currentLedgerID($bank_account_id), @@ -211,7 +208,7 @@ class Payment extends AppModel { // post new e6... this will be our crossover point // from typical positive entries to negative entries. // Therefore, no reconciliation on this account. - $e6_ids = $A->postDoubleEntry + $e6_ids = $A->postLedgerEntry (array('transaction_id' => $t5_id), array('monetary_source_id' => $e3['monetary_source_id']), array('debit_ledger_id' => $A->currentLedgerID($nsf_account_id), @@ -223,7 +220,7 @@ class Payment extends AppModel { 'comment' => "NSF tracker; Monetary Source #{$id}", ), array('debit' => array - (array('DoubleEntry' => + (array('LedgerEntry' => array('id' => $e5_ids['id'], 'amount' => $amount))), ) @@ -237,12 +234,12 @@ class Payment extends AppModel { compact('e6_ids', 'amount'))); $t6_id = null; - foreach ($e3['DebitReconciliationDoubleEntry'] AS $e2) { - foreach ($e2['DebitReconciliationDoubleEntry2'] AS $e1) { + foreach ($e3['DebitReconciliationLedgerEntry'] AS $e2) { + foreach ($e2['DebitReconciliationLedgerEntry2'] AS $e1) { $amount = -1*$e1['Reconciliation']['amount']; // post new e7 - $e7_ids = $A->postDoubleEntry + $e7_ids = $A->postLedgerEntry (array('transaction_id' => $t6_id), null, array('debit_ledger_id' => $A->currentLedgerID($receipt_account_id), @@ -254,12 +251,12 @@ class Payment extends AppModel { 'comment' => "NSF Receipt; Monetary Source #{$id}", ), array('debit' => array - (array('DoubleEntry' => + (array('LedgerEntry' => array('id' => $e6_ids['id'], 'amount' => $amount))), 'credit' => array - (array('DoubleEntry' => + (array('LedgerEntry' => array('id' => $e1['id'], 'amount' => $amount))), ) @@ -276,11 +273,11 @@ class Payment extends AppModel { } // Cheat for now - $customer_id = $source['DoubleEntry'][0]['customer_id']; + $customer_id = $source['LedgerEntry'][0]['customer_id']; $lease_id = null; // post new e8 - $e8_ids = $A->postDoubleEntry + $e8_ids = $A->postLedgerEntry (array('transaction_id' => $t6_id), null, array('debit_ledger_id' => $A->currentLedgerID($ar_account_id), diff --git a/site/models/reconciliation.php b/site/models/reconciliation.php deleted file mode 100644 index 53e6c13..0000000 --- a/site/models/reconciliation.php +++ /dev/null @@ -1,13 +0,0 @@ - array( - 'className' => 'Entry', - ), - 'CreditEntry' => array( - 'className' => 'Entry', - ), - ); - -} diff --git a/site/models/entry.php b/site/models/statement_entry.php similarity index 60% rename from site/models/entry.php rename to site/models/statement_entry.php index c797308..3ff6024 100644 --- a/site/models/entry.php +++ b/site/models/statement_entry.php @@ -1,72 +1,25 @@ array( + 'className' => 'StatementEntry', + ), ); - var $hasAndBelongsToMany = array( - - // The Charges that match THIS Payment (if it is one) - 'Charge' => array( - 'className' => 'Entry', - 'joinTable' => 'charges_payments', - 'linkalias' => 'AppliedCharge', - 'foreignKey' => 'payment_entry_id', - 'associationForeignKey' => 'charge_entry_id', - ), - - // The Payments that match THIS Charge (if it is one) - 'Payment' => array( - 'className' => 'Entry', - 'joinTable' => 'charges_payments', - 'linkalias' => 'AppliedPayment', + var $hasMany = array( + // The payments that apply to this charge (if it is one) + 'PaymentEntry' => array( + 'className' => 'StatementEntry', 'foreignKey' => 'charge_entry_id', - 'associationForeignKey' => 'payment_entry_id', ), -/* // The Deposits that match THIS Payment (if it is one) */ -/* 'Deposit' => array( */ -/* 'className' => 'Entry', */ -/* 'joinTable' => 'deposits_payments', */ -/* 'linkalias' => 'AppliedDeposit', */ -/* 'foreignKey' => 'payment_entry_id', */ -/* 'associationForeignKey' => 'deposit_entry_id', */ -/* ), */ - -/* // The Debits of this same account matching THIS Credit (if it is one) */ -/* 'Debit' => array( */ -/* 'className' => 'Entry', */ -/* 'joinTable' => 'reconciliations', */ -/* 'linkalias' => 'AppliedDebit', */ -/* 'foreignKey' => 'credit_entry_id', */ -/* 'associationForeignKey' => 'debit_entry_id', */ -/* ), */ - -/* // The Credits of this same account matching THIS Debit (if it is one) */ -/* 'Credit' => array( */ -/* 'className' => 'Entry', */ -/* 'joinTable' => 'reconciliations', */ -/* 'linkalias' => 'AppliedCredit', */ -/* 'foreignKey' => 'debit_entry_id', */ -/* 'associationForeignKey' => 'credit_entry_id', */ -/* ), */ - -/* // The Entries of this same account matching THIS Entry */ -/* 'REntry' => array( */ -/* 'className' => 'Entry', */ -/* 'joinTable' => 'reconciliations', */ -/* //'linkalias' => 'AppliedCredit', */ -/* 'foreignKey' => false, */ -/* 'associationForeignKey' => false, */ -/* 'conditions' => array( */ -/* "Reconciliation.credit_entry_id */ -/* = IF(Entry.crdr = 'CREDIT', Entry.id, REntry.id)", */ -/* "Reconciliation.debit_entry_id */ -/* = IF(Entry.crdr = 'DEBIT', Entry.id, REntry.id)" */ -/* ), */ -/* ), */ ); @@ -77,22 +30,22 @@ class Entry extends AppModel { */ - function chargePaymentFields($sum = false, $entry_name = 'Entry', $double_name = 'DoubleEntry') { + function chargePaymentFields($sum = false, $entry_name = 'StatementEntry') { $fields = array ( ($sum ? 'SUM(' : '') . "IF({$entry_name}.type = 'CHARGE'," . - " {$double_name}.amount, NULL)" . + " {$entry_name}.amount, NULL)" . ($sum ? ')' : '') . ' AS charge' . ($sum ? 's' : ''), ($sum ? 'SUM(' : '') . "IF({$entry_name}.type = 'PAYMENT'," . - " {$double_name}.amount, NULL)" . + " {$entry_name}.amount, NULL)" . ($sum ? ')' : '') . ' AS payment' . ($sum ? 's' : ''), ($sum ? 'SUM(' : '') . "IF({$entry_name}.type = 'CHARGE', 1, -1)" . - " * IF({$double_name}.amount, {$double_name}.amount, 0)" . + " * IF({$entry_name}.amount, {$entry_name}.amount, 0)" . ($sum ? ')' : '') . ' AS balance', ); @@ -124,7 +77,7 @@ class Entry extends AppModel { $charge['lease_id'] = $lease_id; $charge['type'] = 'CHARGE'; - $ids = $this->Entry->Ledger->Account->postDoubleEntry + $ids = $this->Entry->Ledger->Account->postLedgerEntry ($transaction, $charge, array('debit_ledger_id' => $A->currentLedgerID($data['account_id']), @@ -160,7 +113,7 @@ class Entry extends AppModel { $payment['customer_id'] = $customer_id; $payment['type'] = 'PAYMENT'; - $ids = $this->Entry->Ledger->Account->postDoubleEntry + $ids = $this->Entry->Ledger->Account->postLedgerEntry ($transaction, $payment, array('debit_ledger_id' => $A->currentLedgerID($data['account_id']), @@ -300,24 +253,16 @@ OPTION 2 $this->queryInit($query); if ($set == 'CHARGE' || $set == 'PAYMENT') - $query['conditions'][] = array('Entry.type' => $set); - elseif ($set == 'DEBIT' || $set == 'CREDIT') - $query['conditions'][] = array('Entry.crdr' => $set); + $query['conditions'][] = array('StatementEntry.type' => $set); else die("INVALID RECONCILE SET"); - if (!isset($query['link']['DoubleEntry'])) - $query['link']['DoubleEntry'] = array(); if ($set == 'CHARGE') - $query['link']['Payment'] = array('fields' => array("SUM(AppliedPayment.amount) AS reconciled")); + $query['link']['PaymentEntry'] = array('fields' => array("SUM(PaymentEntry.amount) AS reconciled")); if ($set == 'PAYMENT') - $query['link']['Charge'] = array('fields' => array("SUM(AppliedCharge.amount) AS reconciled")); -/* if ($set == 'DEBIT') */ -/* $query['link']['Credit'] = array('fields' => array("SUM(AppliedCredit.amount) AS reconciled")); */ -/* if ($set == 'CREDIT') */ -/* $query['link']['Debit'] = array('fields' => array("SUM(AppliedDebit.amount) AS reconciled")); */ + $query['link']['ChargeEntry'] = array('fields' => array("SUM(ChargeEntry.amount) AS reconciled")); - $query['group'] = 'Entry.id'; + $query['group'] = 'StatementEntry.id'; return $query; } @@ -329,15 +274,16 @@ OPTION 2 $resultset = array(); foreach ($result AS $i => $entry) { - $entry['DoubleEntry'] += $entry[0]; + pr(compact('entry')); + $entry['StatementEntry'] += $entry[0]; unset($entry[0]); - $entry['DoubleEntry']['balance'] = - $entry['DoubleEntry']['amount'] - $entry['DoubleEntry']['reconciled']; + $entry['StatementEntry']['balance'] = + $entry['StatementEntry']['amount'] - $entry['StatementEntry']['reconciled']; // Since HAVING isn't a builtin feature of CakePHP, // we'll have to post-process to get the desired entries - if ($entry['DoubleEntry']['balance'] == 0) { + if ($entry['StatementEntry']['balance'] == 0) { if (!$unrec) $resultset[] = $entry; } @@ -347,10 +293,12 @@ OPTION 2 } } + //pr(array('StatementEntry::reconciledSet()' => compact('resultset'))); + //$resultset['stats'] = $this->stats(null, $query); //pr($this->stats(null, $query)); return array('entries' => $resultset, - 'summary' => $this->stats(null, $query, $set)); + 'summary' => $this->stats(null, $query)); } @@ -364,20 +312,16 @@ OPTION 2 function reconciledEntriesQuery($id, $query = null) { $this->queryInit($query, false); - $entry = $this->find('first', array('conditions' => array('Entry.id' => $id), - 'recursive' => -1)); - $entry = $entry['Entry']; + $this->id = $id; + $this->recursive = -1; + $this->read(); - $query['conditions'][] = array('Entry.id' => $id); + $query['conditions'][] = array('StatementEntry.id' => $id); - if ($entry['type'] == 'CHARGE') - $query['contain']['Payment'] = array('fields' => array('Payment.*', 'ChargesPayment.amount')); - if ($entry['type'] == 'PAYMENT') - $query['contain']['Charge'] = array('fields' => array('Charge.*', 'ChargesPayment.amount')); -/* if ($entry['crdr'] == 'DEBIT') */ -/* $query['contain']['Credit'] = array('fields' => array('Credit.*', 'Reconciliation.amount')); */ -/* if ($entry['crdr'] == 'CREDIT') */ -/* $query['contain']['Debit'] = array('fields' => array('Debit.*', 'Reconciliation.amount')); */ + if ($this->data['StatementEntry']['type'] == 'CHARGE') + $query['link']['PaymentEntry'] = array(); + if ($this->data['StatementEntry']['type'] == 'PAYMENT') + $query['link']['ChargeEntry'] = array(); return $query; } @@ -386,11 +330,13 @@ OPTION 2 $lquery = $this->reconciledEntriesQuery($id, $query); //pr(array('reconciledEntries', compact('entry', 'contain'))); - $result = $this->find('first', $lquery); - unset($result['Entry']); + $result = $this->find('all', $lquery); + foreach (array_keys($result) AS $i) + unset($result[$i]['StatementEntry']); - return array('entries' => $result, - 'summary' => $this->stats($id, $query)); + //pr(array('StatementEntry::reconciledEntries()' => compact('result'))); + return array('entries' => $result); + //'summary' => $this->stats($id, $query)); } @@ -398,59 +344,138 @@ OPTION 2 ************************************************************************** ************************************************************************** * function: stats - * - Returns summary data from the requested ledger entry + * - Returns summary data from the requested statement entry */ - function stats($id = null, $query = null, $set = null) { + function stats($id = null, $query = 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($id)) { + $this->id = $id; + $this->recursive = -1; + $this->read(); - if (isset($set)) - $set = strtoupper($set); + if ($this->data['StatementEntry']['type'] == 'PAYMENT') { + // Payment has only a _single_ charge, and by definition + // 100% of the payment is used to reconcile that charge. + return array('total' => $this->data['StatementEntry']['amount'], + 'reconciled' => $this->data['StatementEntry']['amount'], + 'balance' => 0); + } + + $query['link']['PaymentEntry'] = + array('fields' => array("SUM(COALESCE(PaymentEntry.amount,0)) AS reconciled"), + //'type' => 'INNER', + ); + + $query['fields'] = array(); + $query['fields'][] = "StatementEntry.amount AS total"; + //$query['conditions'][] = array("{$Set}Entry.id !=" => null); + + $query['conditions'][] = array('StatementEntry.id' => $id); + + $query['group'] = 'StatementEntry.id'; + + $result = $this->find('first', $query); + $result[0]['balance'] = $result[0]['total'] - $result[0]['reconciled']; + //pr(compact('query', 'result')); + + return $result['StatementEntry'] + $result[0]; + } + + $stats = array(); + + $rquery = $query; + $rquery['link']['PaymentEntry'] = + array('fields' => array("SUM(COALESCE(PaymentEntry.amount,0)) AS reconciled"), + //'type' => 'INNER', + ); + + $rquery['fields'] = array(); + $rquery['fields'][] = "SUM(StatementEntry.amount) AS total"; + + $rquery['conditions'][] = array("PaymentEntry.id !=" => null); + + $result = $this->find('first', $rquery); + $result[0]['balance'] = $result[0]['total'] - $result[0]['reconciled']; + $stats['Payment'] = $result[0]; + //pr(array('stats Payment', compact('rquery', 'stats'))); + + $rquery = $query; + $rquery['fields'] = array(); + $rquery['fields'][] = "SUM(StatementEntry.amount) AS total"; + $rquery['fields'][] = "SUM(StatementEntry.amount) AS reconciled"; + + $result = $this->find('first', $rquery); + $result[0]['balance'] = $result[0]['total'] - $result[0]['reconciled']; + $stats['Charge'] = $result[0]; + //pr(array('stats Charge', compact('rquery', 'stats'))); + + + return $stats; + + + $this->id = $id; + $this->recursive = -1; + $this->read(); //pr(array('stats()', compact('id', 'query', 'set'))); - $rtypes = array('charge', 'payment', - // 'debit', 'credit', - ); - $stats = array(); - foreach($rtypes AS $rtype) { - $Rtype = ucfirst($rtype); - if (($rtype == 'charge' && (!isset($set) || $set == 'PAYMENT')) || - ($rtype == 'payment' && (!isset($set) || $set == 'CHARGE')) -/* ($rtype == 'debit' && (!isset($set) || $set == 'CREDIT')) || */ -/* ($rtype == 'credit' && (!isset($set) || $set == 'DEBIT')) */ - ) { +/* if ($this->data['StatementEntry']['type'] == 'CHARGE') */ +/* $set = 'PAYMENT'; */ +/* else */ +/* $set = 'CHARGE'; */ - $rquery = $query; - $rquery['link'][$Rtype] = - array('fields' => array("SUM(COALESCE(Applied{$Rtype}.amount,0)) AS reconciled")); +/* $Set = ucfirst(strtolower($set)); */ - $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); +/* $query['link'][$Set.'Entry'] = */ +/* array('fields' => array("SUM(COALESCE({$Set}Entry.amount,0)) AS reconciled"), */ +/* //'type' => 'INNER', */ +/* ); */ - $result = $this->find('first', $rquery); - //pr(compact('Rtype', 'rquery', 'result')); +/* $query['fields'] = array(); */ +/* $query['fields'][] = "StatementEntry.amount AS total"; */ +/* $query['fields'][] = "StatementEntry.amount - SUM(COALESCE({$Set}Entry.amount,0)) AS balance"; */ +/* //$query['conditions'][] = array("{$Set}Entry.id !=" => null); */ - $sumfld = $Rtype; - $stats[$sumfld] = $result[0]; -/* if (!isset($stats[$sumfld]['applied'])) */ -/* $stats[$sumfld]['applied'] = 0; */ - } +/* $query['conditions'][] = array('StatementEntry.id' => $id); */ + +/* $query['group'] = 'StatementEntry.id'; */ + +/* $result = $this->find('first', $query); */ +/* pr(compact('Rtype', 'query', 'result')); */ + +/* return $result['StatementEntry'] + $result[0]; */ + + if ($this->data['StatementEntry']['type'] == 'PAYMENT') { + // Payment has only a _single_ charge, and by definition + // 100% of the payment is used to reconcile that charge. + return array('total' => $this->data['StatementEntry']['amount'], + 'reconciled' => $this->data['StatementEntry']['amount'], + 'balance' => 0); } - return $stats; + $query['link']['PaymentEntry'] = + array('fields' => array("SUM(COALESCE(PaymentEntry.amount,0)) AS reconciled"), + //'type' => 'INNER', + ); + + $query['fields'] = array(); + $query['fields'][] = "StatementEntry.amount AS total"; + $query['fields'][] = "StatementEntry.amount - SUM(COALESCE(PaymentEntry.amount,0)) AS balance"; + //$query['conditions'][] = array("{$Set}Entry.id !=" => null); + + $query['conditions'][] = array('StatementEntry.id' => $id); + + $query['group'] = 'StatementEntry.id'; + + $result = $this->find('first', $query); + //pr(compact('Rtype', 'query', 'result')); + + return $result['StatementEntry'] + $result[0]; } } diff --git a/site/models/transaction.php b/site/models/transaction.php index 69de7ea..dc4d4e1 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -1,17 +1,14 @@ array('date') - ); - var $belongsTo = array( - 'Customer', - 'Lease', + 'Account', + 'Ledger', ); var $hasMany = array( - 'DoubleEntry', + 'LedgerEntry', + 'StatementEntry', ); @@ -37,15 +34,15 @@ class Transaction extends AppModel { // Determine the total charges on the invoice $invoice['amount'] = 0; - foreach ($data['DoubleEntry'] AS $entry) + foreach ($data['LedgerEntry'] AS $entry) $invoice['amount'] += $entry['amount']; // Go through the entered charges - foreach ($data['DoubleEntry'] AS $entry) { + foreach ($data['LedgerEntry'] AS $entry) { //pr(compact('entry')); // Create the receipt entry, and reconcile the credit side // of the double-entry (which should be A/R) as a payment. - $ids = $this->DoubleEntry->Ledger->Account->postDoubleEntry + $ids = $this->LedgerEntry->Ledger->Account->postLedgerEntry ($invoice, array('debit_ledger_id' => $A->currentLedgerID($A->accountReceivableAccountID()), 'credit_ledger_id' => $A->currentLedgerID($entry['account_id']) @@ -83,14 +80,14 @@ class Transaction extends AppModel { // Determine the total charges on the receipt $receipt['amount'] = 0; - foreach ($data['DoubleEntry'] AS $entry) + foreach ($data['LedgerEntry'] AS $entry) $receipt['amount'] += $entry['amount']; // Go through the entered charges - foreach ($data['DoubleEntry'] AS $entry) { + foreach ($data['LedgerEntry'] AS $entry) { // Create the receipt entry, and reconcile the credit side // of the double-entry (which should be A/R) as a receipt. - $ids = $this->DoubleEntry->Ledger->Account->postDoubleEntry + $ids = $this->LedgerEntry->Ledger->Account->postLedgerEntry ($receipt, array('debit_ledger_id' => $A->currentLedgerID($entry['account_id']), 'credit_ledger_id' => $A->currentLedgerID($A->receiptAccountID()) diff --git a/site/tmp/cache/models/cake_model_default_pmgr_list b/site/tmp/cache/models/cake_model_default_pmgr_list deleted file mode 100644 index fbaa15f..0000000 --- a/site/tmp/cache/models/cake_model_default_pmgr_list +++ /dev/null @@ -1,2 +0,0 @@ -1243395559 -a:36:{i:0;s:12:"pmgr_actions";i:1;s:27:"pmgr_actions_late_schedules";i:2;s:17:"pmgr_charge_types";i:3;s:19:"pmgr_config_options";i:4;s:18:"pmgr_config_system";i:5;s:20:"pmgr_config_versions";i:6;s:22:"pmgr_contact_addresses";i:7;s:19:"pmgr_contact_emails";i:8;s:20:"pmgr_contact_methods";i:9;s:19:"pmgr_contact_phones";i:10;s:13:"pmgr_contacts";i:11;s:18:"pmgr_group_options";i:12;s:22:"pmgr_group_permissions";i:13;s:11:"pmgr_groups";i:14;s:19:"pmgr_late_schedules";i:15;s:19:"pmgr_lease_contacts";i:16;s:16:"pmgr_lease_types";i:17;s:11:"pmgr_leases";i:18;s:14:"pmgr_map_units";i:19;s:9:"pmgr_maps";i:20;s:10:"pmgr_notes";i:21;s:18:"pmgr_payment_types";i:22;s:15:"pmgr_site_areas";i:23;s:21:"pmgr_site_memberships";i:24;s:17:"pmgr_site_options";i:25;s:10:"pmgr_sites";i:26;s:24:"pmgr_transaction_charges";i:27;s:25:"pmgr_transaction_payments";i:28;s:25:"pmgr_transaction_receipts";i:29;s:32:"pmgr_transaction_reconciliations";i:30;s:15:"pmgr_unit_sizes";i:31;s:15:"pmgr_unit_types";i:32;s:10:"pmgr_units";i:33;s:17:"pmgr_user_options";i:34;s:10:"pmgr_users";i:35;s:5:"posts";} diff --git a/site/views/customers/view.ctp b/site/views/customers/view.ctp index bf4334f..d94f038 100644 --- a/site/views/customers/view.ctp +++ b/site/views/customers/view.ctp @@ -62,7 +62,7 @@ echo $this->element('contacts', array */ echo $this->element('leases', array - ('customer_id' => $customer['id'], + ('customer_id' => $customer['Customer']['id'], 'config' => array ('caption' => 'Lease History', diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index 7ba6ade..04f2f6f 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -16,6 +16,9 @@ $cols['Comment'] = array('index' => 'Customer.comment', 'formatter if (isset($searchfields)) $grid->searchFields(array('Last Name', 'First Name')); +// Include custom data +//$grid->customData(compact('lease_id')); + // Render the grid $grid ->columns($cols) diff --git a/site/views/elements/leases.ctp b/site/views/elements/leases.ctp index 0a5d8eb..c90c1d8 100644 --- a/site/views/elements/leases.ctp +++ b/site/views/elements/leases.ctp @@ -18,9 +18,12 @@ $cols['Comment'] = array('index' => 'Lease.comment', 'formatter' => 'com if (isset($searchfields)) $grid->searchFields(array('Customer', 'Unit')); -if (isset($no_customer)) +if (isset($customer_id)) $grid->invalidFields('Customer'); +// Include custom data +$grid->customData(compact('customer_id')); + // Render the grid $grid ->columns($cols) diff --git a/site/views/elements/entries.ctp b/site/views/elements/ledger_entries.ctp similarity index 100% rename from site/views/elements/entries.ctp rename to site/views/elements/ledger_entries.ctp diff --git a/site/views/elements/statement_entries.ctp b/site/views/elements/statement_entries.ctp new file mode 100644 index 0000000..14d27a2 --- /dev/null +++ b/site/views/elements/statement_entries.ctp @@ -0,0 +1,79 @@ + 'Transaction.id', 'formatter' => 'id'); +$cols['StatementEntry'] = array('index' => 'StatementEntry.id', 'formatter' => 'id'); + +$cols['Date'] = array('index' => 'Transaction.stamp', 'formatter' => 'date'); +$cols['Effective'] = array('index' => 'StatementEntry.effective_date', 'formatter' => 'date'); +$cols['Through'] = array('index' => 'StatementEntry.through_date', 'formatter' => 'date'); + +$cols['Account'] = array('index' => 'Account.name', 'formatter' => 'name'); + +$cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'longname'); +$cols['Lease'] = array('index' => 'Lease.number', 'formatter' => 'id'); +$cols['Unit'] = array('index' => 'Unit.name', 'formatter' => 'name'); + +$cols['Comment'] = array('index' => 'StatementEntry.comment', 'formatter' => 'comment', 'width'=>150); + +$cols['Charge'] = array('index' => 'charge', 'formatter' => 'currency'); +$cols['Payment'] = array('index' => 'payment', 'formatter' => 'currency'); + +$cols['Last Payment'] = array('index' => 'last_paid', 'formatter' => 'date'); +$cols['Applied'] = array('index' => "applied", 'formatter' => 'currency'); +$cols['Sub-Total'] = array('index' => 'subtotal-StatementEntry.amount', 'formatter' => 'currency', 'sortable' => false); + + +if (isset($transaction_id)) + $grid->invalidFields('Transaction'); + +if (!isset($collected_account_id)) + $grid->invalidFields('Last Payment'); + +if (isset($ledger_id) || isset($account_id)) + $grid->invalidFields(array('Account')); + +if (isset($lease_id) || isset($customer_id)) + $grid->invalidFields(array('Customer')); + +if (isset($lease_id)) + $grid->invalidFields(array('Lease', 'Unit')); + +if (!isset($statement_entry_id)) + $grid->invalidFields('Applied'); +else + $cols['Sub-Total']['index'] = 'subtotal-applied'; + +$grid->invalidFields('Sub-Total'); +$grid->invalidFields('Applied'); + + +// Now that columns are defined, establish basic grid parameters +$grid +->columns($cols) +->sortField('Date') +->defaultFields(array('Entry', 'Date', 'Amount', 'Credit', 'Debit')); + + +/* // Set up search fields if requested by caller */ +/* if (isset($searchfields)) */ +/* $grid->searchFields(array('Customer', 'Unit')); */ + + +// Include custom data +$grid->customData(compact('transaction_id', 'account_id', 'customer_id', 'lease_id', + 'statement_entry_id', 'from_date', 'through_date', + 'payment_accounts', 'charge_accounts')); + +// Render the grid +$grid +->render($this, isset($config) ? $config : null, + array('Transaction', 'StatementEntry', 'Date', 'Effective', 'Last Payment', + 'Account', + 'Customer', 'Unit', + 'Comment', + 'Charge', 'Payment', 'Amount', + 'Applied', 'Sub-Total') + ); + diff --git a/site/views/leases/view.ctp b/site/views/leases/view.ctp index 4e09aff..35d9cf7 100644 --- a/site/views/leases/view.ctp +++ b/site/views/leases/view.ctp @@ -79,11 +79,9 @@ echo '
' . "\n"; * Lease Account History */ -echo $this->element('entries', array +echo $this->element('ledger_entries', array (// Element configuration 'lease_id' => $lease['id'], - //'charge_payment' => true, - //'entry_type' => array('CHARGE', 'PAYMENT'), // Grid configuration 'config' => array diff --git a/site/views/statement_entries/view.ctp b/site/views/statement_entries/view.ctp new file mode 100644 index 0000000..4df5039 --- /dev/null +++ b/site/views/statement_entries/view.ctp @@ -0,0 +1,114 @@ +' . "\n"; + +/********************************************************************** + ********************************************************************** + ********************************************************************** + ********************************************************************** + * Entry Detail Main Section + */ + +$transaction = $entry['Transaction']; +$account = $entry['Account']; +$customer = $entry['Customer']; +$lease = $entry['Lease']; +$entry = $entry['StatementEntry']; + +$rows = array(); +$rows[] = array('ID', $entry['id']); +$rows[] = array('Transaction', $html->link('#'.$transaction['id'], + array('controller' => 'transactions', + 'action' => 'view', + $transaction['id']))); +$rows[] = array('Timestamp', FormatHelper::datetime($transaction['stamp'])); +$rows[] = array('Effective', FormatHelper::date($entry['effective_date'])); +$rows[] = array('Through', FormatHelper::date($entry['through_date'])); +$rows[] = array('Type', $entry['type']); +$rows[] = array('Amount', FormatHelper::currency($entry['amount'])); +$rows[] = array('Account', $html->link($account['name'], + array('controller' => 'accounts', + 'action' => 'view', + $account['id']))); +$rows[] = array('Customer', (isset($customer['name']) + ? $html->link($customer['name'], + array('controller' => 'customers', + 'action' => 'view', + $customer['id'])) + : null)); +$rows[] = array('Lease', (isset($lease['id']) + ? $html->link('#'.$lease['id'], + array('controller' => 'leases', + 'action' => 'view', + $lease['id'])) + : null)); +$rows[] = array('Comment', $entry['comment']); + +echo $this->element('table', + array('class' => 'item statement-entry detail', + 'caption' => 'Statement Entry Detail', + 'rows' => $rows, + 'column_class' => array('field', 'value'))); + + +/********************************************************************** + * Entry Info Box + */ + +echo '
' . "\n"; + +$applied_caption = "Applied"; +$remaining_caption = "Balance"; + +$rows = array(); +$rows[] = array($applied_caption, + '' . + FormatHelper::currency($stats['reconciled']) . + ''); +$rows[] = array($remaining_caption, + '' . + FormatHelper::currency($stats['balance']) . + ''); + +echo $this->element('table', + array('class' => 'item summary', + 'caption' => null, + 'rows' => $rows, + 'column_class' => array('field', 'value'), + //'suppress_alternate_rows' => true, + )); + +echo '
' . "\n"; + + +/********************************************************************** + ********************************************************************** + ********************************************************************** + ********************************************************************** + * Supporting Elements Section + */ + +echo '
' . "\n"; + + +/********************************************************************** + * Reconciliation Ledger Entries + */ + +echo $this->element('statement_entries', array + (// Element configuration + 'statement_entry_id' => $entry['id'], +/* 'action' => 'reconcile', */ + + // Grid configuration + 'config' => array + ('caption' => 'Entries Applied', + ), + )); + + +/* End "detail supporting" div */ +echo '
' . "\n"; + +/* End page div */ +echo '
' . "\n";