From 58d3cbf66b1a29d8f87af08c09813274331cf275 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 6 Jul 2009 18:34:44 +0000 Subject: [PATCH] First pass at entering charges for a lease. This works, but does not have the ability to add multiple charges, and does not mirror the payment method, which is ajax based. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629/site@231 97e9348a-65ac-dc4b-aefc-98561f571b83 --- app_model.php | 12 ++ controllers/leases_controller.php | 62 ++++++++- controllers/transactions_controller.php | 159 ++++++++++++++++++++++++ models/account.php | 1 + models/lease.php | 13 ++ models/transaction.php | 2 +- views/elements/form_table.ctp | 4 +- views/leases/assess.ctp | 155 +++++++++++++++++++++++ 8 files changed, 405 insertions(+), 3 deletions(-) create mode 100644 views/leases/assess.ctp diff --git a/app_model.php b/app_model.php index 12d1f58..c06ec08 100644 --- a/app_model.php +++ b/app_model.php @@ -40,6 +40,7 @@ class AppModel extends Model { var $actsAs = array('Containable', 'Linkable'); var $useNullForEmpty = true; + var $dateFields = array(); /** * Get Enum Values @@ -155,6 +156,17 @@ class AppModel extends Model { // override the behavior, or set useNullForEmpty to false. if ($this->useNullForEmpty) $this->recursive_array_replace("/^\s*$/", null, $this->data); + + foreach ($this->dateFields AS $field) { +/* if(isset($this->data['Transaction']['stamp']) && */ +/* $this->data['Transaction']['stamp'] !== 'CURRENT_TIMESTAMP') { */ +/* $this->data['Transaction']['stamp'] = */ +/* $this->dateFormatBeforeSave($this->data['Transaction']['stamp']); */ +/* } */ +/* else { */ +/* $this->data['Transaction']['stamp'] = null; */ + } + return true; } diff --git a/controllers/leases_controller.php b/controllers/leases_controller.php index 08293ec..d930fd9 100644 --- a/controllers/leases_controller.php +++ b/controllers/leases_controller.php @@ -125,7 +125,7 @@ class LeasesController extends AppController { function move_out($id = null) { if ($this->data) { // Handle the move out based on the data given - pr($this->data); + //pr($this->data); $this->Lease->moveOut($this->data['Lease']['id']); $this->redirect($this->data['redirect']); @@ -166,6 +166,58 @@ class LeasesController extends AppController { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: assess + * - Assesses charges to the lease + */ + + function assess($id = null, $type = null) { + if ($this->data) { + // Assess the charges based on the given data + pr($this->data); + + $this->Lease->addCharge($this->data['Lease']['id'], $this->data['Charge']); + //$this->redirect($this->data['redirect']); + $this->render('/empty'); + return; + } + + $lease = $this->Lease->find + ('first', array + ('contain' => array + (// Models + 'Unit' => + array('order' => array('sort_order'), + 'fields' => array('id', 'name'), + ), + + 'Customer' => + array('fields' => array('id', 'name'), + ), + ), + + 'conditions' => array(array('Lease.id' => $id), + array('Lease.close_date' => null), + ), + )); + + $charge['type'] = $type; + if ($type == 'rent') + $charge['amount'] = $lease['Lease']['rent']; + else + // REVISIT 20090705: + // Of course, the late charge should come from the late_schedule + $charge['amount'] = 10.00; + + $title = ('Lease #' . $lease['Lease']['number'] . ': ' . + $lease['Unit']['name'] . ': ' . + $lease['Customer']['name'] . ': Assess Charges'); + $this->set(compact('title', 'lease', 'charge')); + } + + /************************************************************************** ************************************************************************** ************************************************************************** @@ -206,6 +258,14 @@ class LeasesController extends AppController { $this->sidemenu_links[] = array('name' => 'Operations', 'header' => true); + $this->sidemenu_links[] = + array('name' => 'Assess Rent', 'url' => array('action' => 'assess', + $id, 'rent')); + + $this->sidemenu_links[] = + array('name' => 'Assess Late Charge', 'url' => array('action' => 'assess', + $id, 'late')); + if (!isset($lease['Lease']['moveout_date'])) { $this->sidemenu_links[] = array('name' => 'Move-Out', 'url' => array('action' => 'move_out', diff --git a/controllers/transactions_controller.php b/controllers/transactions_controller.php index 8f182cf..5c031bc 100644 --- a/controllers/transactions_controller.php +++ b/controllers/transactions_controller.php @@ -95,6 +95,165 @@ class TransactionsController extends AppController { $this->set(compact('transaction', 'title', 'total')); } + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: postInvoice + * - handles the creation of a charge invoice + */ + + function postInvoice() { + if (!$this->RequestHandler->isPost()) { + echo('

THIS IS NOT A POST FOR SOME REASON

'); + return; + } + + pr($this->data); + +/* $this->layout = null; */ +/* $this->autoLayout = false; */ +/* $this->autoRender = false; */ +/* Configure::write('debug', '0'); */ + + // Sanitize the transaction data + if (!$this->data['Transaction']['comment']) + $this->data['Transaction']['comment'] = null; + + if(empty($this->data['Transaction']['stamp'])) { + die("Time/Date not valid"); + } + pr($this->data['Transaction']); + + // Create some models for convenience + $A = new Account(); + $C = new Customer(); + $L = new Lease(); + + $L->recursive = -1; + $lease = $L->read(null, $this->data['Lease']['id']); + + // Create a transaction for the invoice + $invoice_transaction = new Transaction(); + $invoice_transaction->create(); + if (!$invoice_transaction->save($this->data['Transaction'], + array('validate' => false, + ))) { + pr(array('checkpoint' => "invoice transaction save failed")); + return; + die("Unknown Database Failure"); + } + pr("New Transaction Created ({$invoice_transaction->id})!"); + $invoice_transaction->read(); + pr($invoice_transaction->data); + + // Create a transaction for the A/R + $ar_transaction = new Transaction(); + $ar_transaction->create(); + if (!$ar_transaction->save($this->data['Transaction'], + array('validate' => false, + ))) { + pr(array('checkpoint' => "A/R transaction save failed")); + die("Unknown Database Failure"); + } + pr("New Transaction Created ({$ar_transaction->id})!"); + $ar_transaction->read(); + pr($ar_transaction->data); + + // Go through the entered charges + $grand_total = 0; + foreach ($this->data['LedgerEntry'] AS &$entry) { + pr(compact('entry')); + + // Invoice Transaction + // debit: Invoice credit: Charge + $entry['transaction_id'] = $invoice_transaction->id; + + // Invoice must debit the "invoice" asset... + $entry['debit_ledger_id'] + = $A->currentLedgerID($A->invoiceAccountID()); + + // ...and credit the charge ledger + // REVISIT 20090706 + // The charge page should have a list of all income types + // and thus the field _should_ contain a valid account + // name. At the moment, however, I'm still cobbling things + // together, and only have two types. +/* $entry['credit_ledger_id'] */ +/* = $A->currentLedgerID($A->nameToID($entry['charge_account'])); */ + if ($entry['charge_type'] === 'rent') { + $entry['credit_ledger_id'] + = $A->currentLedgerID($A->rentAccountID()); + } elseif ($entry['charge_type'] === 'late') { + $entry['credit_ledger_id'] + = $A->currentLedgerID($A->lateChargeAccountID()); + } else { + die("Invalid charge account"); + } + + $entry['customer_id'] + = $lease['Lease']['customer_id']; + $entry['lease_id'] + = $lease['Lease']['id']; + + // Create it + $invoice_entry = new LedgerEntry(); + $invoice_entry->create(); + if (!$invoice_entry->save($entry, false)) { + pr(array('checkpoint' => "invoice entry saveAll failed")); + die("Unknown Database Failure"); + } + pr("New Invoice LedgerEntry Created ({$invoice_entry->id})!"); + $invoice_entry->read(); + pr($invoice_entry->data); + + $grand_total += $entry['amount']; + } + + // Create an account receivable entry + // debit: A/R credit: Invoice + $ar_entry_data = array + ('debit_ledger_id' => $A->currentLedgerID($A->accountReceivableAccountID()), + 'credit_ledger_id' => $A->currentLedgerID($A->invoiceAccountID()), + 'transaction_id' => $ar_transaction->id, + 'amount' => $grand_total, + 'lease_id' => $lease['Lease']['id'], + 'customer_id' => $lease['Lease']['customer_id'], + ); + + // Create a new A/R entry from the data + $ar_entry = new LedgerEntry(); + $ar_entry->create(); + if (!$ar_entry->save($ar_entry_data, false)) { + pr(array('checkpoint' => "ar entry save failed")); + die("Unknown Database Failure"); + } + pr("New A/R LedgerEntry Created ({$ar_entry->id})!"); + $ar_entry->read(); + pr($ar_entry->data); + + // Reconcile the Invoice account. Our two entries look like: + // debit: Invoice credit: Charge + // debit: A/R credit: Invoice + // Since this is from the perspective of the Invoice account, + // the credit entry is the Invoice<->A/R, and the debit + // entry is the actual invoice ledger entry. + $R = new Reconciliation(); + $R->create(); + if (!$R->save(array('debit_ledger_entry_id' => $invoice_entry->id, + 'credit_ledger_entry_id' => $ar_entry->id, + 'amount' => $grand_total), false)) { + pr(array('checkpoint' => "invoice reconcile save failed")); + die("Unknown Database Failure"); + } + pr("New Invoice Reconciliation Created ({$R->id})!"); + $R->read(); + pr($R->data); + + $this->render('/empty'); + } + + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/models/account.php b/models/account.php index f3541f5..da02936 100644 --- a/models/account.php +++ b/models/account.php @@ -94,6 +94,7 @@ class Account extends AppModel { function securityDepositAccountID() { return $this->nameToID('Security Deposit'); } function rentAccountID() { return $this->nameToID('Rent'); } + function lateChargeAccountID() { return $this->nameToID('Late Charge'); } function accountReceivableAccountID() { return $this->nameToID('A/R'); } function invoiceAccountID() { return $this->nameToID('Invoice'); } function receiptAccountID() { return $this->nameToID('Receipt'); } diff --git a/models/lease.php b/models/lease.php index 631e14f..c3628a6 100644 --- a/models/lease.php +++ b/models/lease.php @@ -266,6 +266,19 @@ class Lease extends AppModel { $this->Unit->updateStatus($this->data['Lease']['unit_id'], $status); } + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: addCharge + * - Adds an additional charge to the lease + */ + + function addCharge($id, $charge) { + + } + + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/models/transaction.php b/models/transaction.php index e7ccb03..e2af783 100644 --- a/models/transaction.php +++ b/models/transaction.php @@ -25,7 +25,7 @@ class Transaction extends AppModel { $this->data['Transaction']['stamp'] = null; } - return true; + return parent::beforeSave(); } } diff --git a/views/elements/form_table.ctp b/views/elements/form_table.ctp index c3c15bc..7085238 100644 --- a/views/elements/form_table.ctp +++ b/views/elements/form_table.ctp @@ -16,7 +16,9 @@ foreach ($fields AS $field => $config) { if (!isset($config['opts'])) $config['opts'] = null; - if (isset($field_prefix) && !isset($config['no_prefix'])) + if (isset($config['prefix']) && !isset($config['no_prefix'])) + $field = $config['prefix'] . '.' . $field; + elseif (isset($field_prefix) && !isset($config['no_prefix'])) $field = $field_prefix . '.' . $field; $config['opts']['label'] = false; diff --git a/views/leases/assess.ctp b/views/leases/assess.ctp new file mode 100644 index 0000000..655b59e --- /dev/null +++ b/views/leases/assess.ctp @@ -0,0 +1,155 @@ + + +
+ + 'function(ids) { if (ids != null) { onRowSelect("#"+$(this).attr("id"), ids); } }' + ); + +$lease_grid_setup['onHeaderClick'] = array + ('--special' => + 'function(gridstate) { onGridState("#"+$(this).attr("id"), gridstate); }' + ); + +?> + + + +element('leases', + array('grid_div_id' => 'leases-list', + 'grid_div_class' => 'text-below', + 'caption' => ('Select Lease'), + 'grid_setup' => $lease_grid_setup, + 'nolinks' => true, + 'limit' => 10, + )); + +echo ('

' . + 'Lease: ' . + 'Please select lease' . + '

' . "\n"); + + +echo $form->create(null, array('id' => 'assess-form', + 'url' => array('controller' => 'transactions', + 'action' => 'postInvoice'))); + +echo $form->input("Lease.id", + array('id' => 'lease-id', + 'type' => 'hidden', + 'value' => 0)); + +echo $this->element('form_table', + array('class' => "item assess entry", + 'field_prefix' => 'Transaction', + 'fields' => array + ("stamp" => array('opts' => array('id' => 'charge_date', + 'type' => 'text')), + "through_date" => array('opts' => array('id' => 'through_date', + 'type' => 'text')), + "charge_type" => array('prefix' => 'LedgerEntry.0', + 'opts' => + array('options' => + array('rent' => 'Rent', + 'late' => 'Late Charge'), + 'value' => $charge['type'])), + "amount" => array('prefix' => 'LedgerEntry.0', + 'opts' => + array('value' => $charge['amount'])), + "comment" => array('opts' => array('size' => 50)), + ))); + +echo $form->end('Assess Charge'); + +?> + + + +