diff --git a/db/schema.sql b/db/schema.sql
index e09ee29..91f2555 100644
--- a/db/schema.sql
+++ b/db/schema.sql
@@ -968,6 +968,7 @@ CREATE TABLE `pmgr_transactions` (
'CREDIT_NOTE', -- Inverse of Sales Invoice
'PAYMENT', -- Actual payment
'DEPOSIT',
+ 'WITHDRAWAL',
'CLOSE', -- Essentially an internal (not accounting) transaction
-- 'CREDIT',
-- 'REFUND',
diff --git a/site/app_controller.php b/site/app_controller.php
index e2e7dba..2f3cac2 100644
--- a/site/app_controller.php
+++ b/site/app_controller.php
@@ -52,7 +52,7 @@ class AppController extends Controller {
array('onclick' => '$(".pr-section").show(); return false;')),
array('name' => 'Contacts', 'url' => array('controller' => 'contacts', 'action' => 'index')),
array('name' => 'Ledgers', 'url' => array('controller' => 'ledgers', 'action' => 'index')),
- //array('name' => 'New Ledgers', 'url' => array('controller' => 'accounts', 'action' => 'newledger')),
+ array('name' => 'New Ledgers', 'url' => array('controller' => 'accounts', 'action' => 'newledger')),
//array('name' => 'RESET DATA', 'url' => array('controller' => 'accounts', 'action' => 'reset_data')),
);
}
diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php
index 1db1927..54c2fee 100644
--- a/site/controllers/leases_controller.php
+++ b/site/controllers/leases_controller.php
@@ -171,9 +171,7 @@ class LeasesController extends AppController {
$this->Lease->moveOut($this->data['Lease']['id'],
'VACANT',
- $this->data['Lease']['moveout_date'],
- //true // Close this lease, if able
- false
+ $this->data['Lease']['moveout_date']
);
$this->redirect($this->data['redirect']);
@@ -418,9 +416,11 @@ class LeasesController extends AppController {
function assess_rent($date = null) {
$this->Lease->assessMonthlyRentAll($date);
+ $this->redirect(array('action'=>'index'));
}
function assess_late($date = null) {
$this->Lease->assessMonthlyLateAll($date);
+ $this->redirect(array('action'=>'index'));
}
diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php
index 30a2b95..3677324 100644
--- a/site/controllers/transactions_controller.php
+++ b/site/controllers/transactions_controller.php
@@ -349,8 +349,6 @@ class TransactionsController extends AppController {
die("
REFUND FAILED
");
}
- $this->render('/fake');
-
// Return to viewing the lease/customer
if (empty($data['Lease']['id']))
$this->redirect(array('controller' => 'customers',
@@ -388,7 +386,9 @@ class TransactionsController extends AppController {
'conditions' => array(array('Transaction.id' => $id),
// REVISIT : 20090811
// No security issues have been worked out yet
- array('Account.level >=' => 5),
+ array('OR' =>
+ array(array('Account.level >=' => 5),
+ array('Account.id' => null))),
),
));
diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php
index 5b452d7..05f26ef 100644
--- a/site/controllers/units_controller.php
+++ b/site/controllers/units_controller.php
@@ -256,13 +256,13 @@ class UnitsController extends AppController {
if (isset($unit['CurrentLease']['id']) &&
!isset($unit['CurrentLease']['close_date'])) {
$this->sidemenu_links[] =
- array('name' => 'Charge', 'url' => array('controller' => 'leases',
- 'action' => 'invoice',
- $unit['CurrentLease']['id']));
+ array('name' => 'New Invoice', 'url' => array('controller' => 'leases',
+ 'action' => 'invoice',
+ $unit['CurrentLease']['id']));
$this->sidemenu_links[] =
- array('name' => 'Payment', 'url' => array('controller' => 'customers',
- 'action' => 'receipt',
- $unit['CurrentLease']['customer_id']));
+ array('name' => 'New Receipt', 'url' => array('controller' => 'customers',
+ 'action' => 'receipt',
+ $unit['CurrentLease']['customer_id']));
}
// Prepare to render.
diff --git a/site/models/customer.php b/site/models/customer.php
index 42ac10e..cd2272c 100644
--- a/site/models/customer.php
+++ b/site/models/customer.php
@@ -142,10 +142,8 @@ class Customer extends AppModel {
continue;
$I = new Contact();
- $I->create();
- if (!$I->save($contact, false)) {
+ if (!$I->saveContact(null, array('Contact' => $contact)))
return false;
- }
$contact['id'] = $I->id;
}
diff --git a/site/models/lease.php b/site/models/lease.php
index bedec46..87e263d 100644
--- a/site/models/lease.php
+++ b/site/models/lease.php
@@ -610,7 +610,7 @@ class Lease extends AppModel {
*/
function moveOut($id, $status = 'VACANT',
- $stamp = null, $close = false)
+ $stamp = null, $close = true)
{
$this->prEnter(compact('id', 'status', 'stamp', 'close'));
diff --git a/site/models/statement_entry.php b/site/models/statement_entry.php
index 322d977..0572196 100644
--- a/site/models/statement_entry.php
+++ b/site/models/statement_entry.php
@@ -252,7 +252,7 @@ class StatementEntry extends AppModel {
null,
null,
$tx['customer_id'],
- $tx['lease_id']
+ null
);
$this->pr(21, compact('result'));
$ret['assigned'][] = $result;
@@ -396,10 +396,11 @@ class StatementEntry extends AppModel {
// First, find all known credits, unless this call is to make
// credit adjustments to a specific charge
- // REVISIT : 20090806
- // If the theory below is correct, we should only search for
- // explicit credits if we don't have a receipt_id
- if (empty($charge_ids)) {
+ if (empty($receipt_id)) {
+
+ if (!empty($charge_ids))
+ INTERNAL_ERROR("Charge IDs, yet no corresponding receipt");
+
$lquery = $query;
$lquery['conditions'][] = array('StatementEntry.type' => 'SURPLUS');
// REVISIT : 20090804
@@ -424,13 +425,7 @@ class StatementEntry extends AppModel {
"Credits Established");
}
else {
- if (empty($receipt_id))
- INTERNAL_ERROR("Can't make adjustments to a charge without a receipt ID.");
- }
-
- // Next, establish credit from the newly added receipt
- $receipt_credit = null;
- if (!empty($receipt_id)) {
+ // Next, establish credit from the newly added receipt
$lquery =
array('link' =>
array('StatementEntry',
@@ -447,13 +442,13 @@ class StatementEntry extends AppModel {
if (!$receipt_credit)
INTERNAL_ERROR("Unable to locate receipt.");
- //$reconciled = $this->reconciledEntries($id);
-
$stats = $this->Transaction->stats($receipt_id);
$receipt_credit['balance'] =
$receipt_credit['Transaction']['amount'] - $stats['Disbursement']['total'];
- $this->pr(18, compact('receipt_credit'),
+ $receipt_credit['receipt'] = true;
+ $credits = array($receipt_credit);
+ $this->pr(18, compact('credits'),
"Receipt Credit Added");
}
@@ -476,44 +471,22 @@ class StatementEntry extends AppModel {
$this->pr(18, compact('dtype', 'entries'), "Outstanding Debit Entries");
}
- // Initialize our list of used credits
- $used_credits = array();
-
- // REVISIT : 20090806
- // Testing a theory. We should never have
- // explicit credits, as well as a new receipt,
- // and yet have outstanding charges.
- if (!empty($credits) && !empty($receipt_credit) && !empty($charges))
- INTERNAL_ERROR("Explicit credits that haven't already been applied.");
-
// Work through all unpaid charges, applying disbursements as we go
foreach ($charges AS $charge) {
-
$this->pr(20, compact('charge'),
'Process Charge');
- // Check that we have available credits.
- // Technically, this isn't necessary, since the loop
- // will handle everything just fine. However, this
- // just saves extra processing if/when there is no
- // means to resolve a charge anyway.
- if (empty($credits) && empty($receipt_credit['balance'])) {
- $this->pr(17, 'No more available credits');
- break;
- }
-
$charge['balance'] = $charge['StatementEntry']['balance'];
- while ($charge['balance'] > 0 &&
- (!empty($credits) || !empty($receipt_credit['balance']))) {
- $this->pr(20, compact('charge'),
- 'Attempt Charge Reconciliation');
+ // Use explicit credits before using the new receipt credit
+ foreach ($credits AS &$credit) {
+ if (empty($charge['balance']))
+ break;
+ if ($charge['balance'] < 0)
+ INTERNAL_ERROR("Negative Charge Balance");
- // Use explicit credits before using implicit credits
- // (Not sure it matters though).
- if (!empty($credits)) {
- // Peel off the first credit available
- $credit =& $credits[0];
+ if (empty($credit['receipt'])) {
+ // Explicit Credit
$disbursement_date = $credit['StatementEntry']['effective_date'];
$disbursement_transaction_id = $credit['StatementEntry']['transaction_id'];
$disbursement_account_id = $credit['StatementEntry']['account_id'];
@@ -521,16 +494,29 @@ class StatementEntry extends AppModel {
if (!isset($credit['balance']))
$credit['balance'] = $credit['StatementEntry']['amount'];
}
- elseif (!empty($receipt_credit['balance'])) {
- // Use our only receipt credit
- $credit =& $receipt_credit;
+ else {
+ // Receipt Credit
$disbursement_date = $credit['Transaction']['stamp'];
$disbursement_transaction_id = $credit['Transaction']['id'];
$disbursement_account_id = $credit['LedgerEntry']['account_id'];
}
- else {
- die("HOW DID WE GET HERE WITH NO SURPLUS?");
- }
+
+ if (empty($credit['balance']))
+ continue;
+ if ($credit['balance'] < 0)
+ INTERNAL_ERROR("Negative Credit Balance");
+
+ $this->pr(20, compact('charge'),
+ 'Attempt Charge Reconciliation');
+
+ // REVISIT : 20090811
+ // Need to come up with a better strategy for handling
+ // concessions. For now, just restricting concessions
+ // to apply only towards rent will resolve the most
+ // predominant (or only) needed usage case.
+ if ($disbursement_account_id == $this->Account->concessionAccountID() &&
+ $charge['StatementEntry']['account_id'] != $this->Account->rentAccountID())
+ continue;
// Set the disbursement amount to the maximum amount
// possible without exceeding the charge or credit balance
@@ -543,15 +529,7 @@ class StatementEntry extends AppModel {
$this->pr(20, compact('credit'),
($credit['balance'] > 0 ? 'Utilized' : 'Exhausted') .
- (!empty($credits) ? ' Credit' : ' Receipt'));
-
- if ($credit['balance'] < 0)
- die("HOW DID WE END UP WITH NEGATIVE SURPLUS BALANCE?");
-
- // If we've exhausted the credit, get it out of the
- // available credit pool (but keep track of it for later).
- if ($credit['balance'] <= 0 && !empty($credits))
- $used_credits[] = array_shift($credits);
+ (empty($credit['receipt']) ? ' Credit' : ' Receipt'));
// Add a disbursement that uses the available credit to pay the charge
$disbursement = array('type' => $disbursement_type,
@@ -581,67 +559,69 @@ class StatementEntry extends AppModel {
if ($charge['balance'] <= 0)
$this->pr(20, 'Fully Paid Charge');
}
-
}
- // Partially used credits must be added to the used list
- if (isset($credits[0]['applied']))
- $used_credits[] = array_shift($credits);
-
- $this->pr(18, compact('credits', 'used_credits', 'receipt_credit'),
- 'Disbursements added');
+ $this->pr(18, compact('credits'),
+ 'Disbursements complete');
// Clean up any explicit credits that have been used
- foreach ($used_credits AS $credit) {
- if ($credit['balance'] > 0) {
- $this->pr(20, compact('credit'),
- 'Update Credit Entry');
+ foreach ($credits AS $credit) {
+ if (empty($credit['receipt'])) {
+ // Explicit Credit
+ if (empty($credit['applied']))
+ continue;
- $this->id = $credit['StatementEntry']['id'];
- $this->saveField('amount', $credit['balance']);
+ if ($credit['balance'] > 0) {
+ $this->pr(20, compact('credit'),
+ 'Update Credit Entry');
+
+ $this->id = $credit['StatementEntry']['id'];
+ $this->saveField('amount', $credit['balance']);
+ }
+ else {
+ $this->pr(20, compact('credit'),
+ 'Delete Exhausted Credit Entry');
+
+ $this->del($credit['StatementEntry']['id'], false);
+ }
}
else {
- $this->pr(20, compact('credit'),
- 'Delete Exhausted Credit Entry');
+ // Receipt Credit
+ if (empty($credit['balance']))
+ continue;
- $this->del($credit['StatementEntry']['id'], false);
- }
- }
+ // Convert non-exhausted receipt credit to an explicit one
+ $explicit_credit = $this->find
+ ('first', array('contain' => false,
+ 'conditions' =>
+ array(array('transaction_id' => $credit['Transaction']['id']),
+ array('type' => 'SURPLUS')),
+ ));
- // Convert non-exhausted receipt credit to an explicit one
- if (!empty($receipt_credit['balance'])) {
- $credit =& $receipt_credit;
+ if (empty($explicit_credit)) {
+ $this->pr(18, compact('credit'),
+ 'Create Explicit Credit');
- $explicit_credit = $this->find
- ('first', array('contain' => false,
- 'conditions' =>
- array(array('transaction_id' => $credit['Transaction']['id']),
- array('type' => 'SURPLUS')),
- ));
-
- if (empty($explicit_credit)) {
- $this->pr(18, compact('credit'),
- 'Create Explicit Credit');
-
- $result = $this->addStatementEntry
- (array('type' => 'SURPLUS',
- 'account_id' => $credit['LedgerEntry']['account_id'],
- 'amount' => $credit['balance'],
- 'effective_date' => $credit['Transaction']['stamp'],
- 'transaction_id' => $credit['Transaction']['id'],
- 'customer_id' => $customer_id,
- 'lease_id' => $lease_id,
- ));
- $ret['Credit'] = $result;
- if ($result['error'])
- $ret['error'] = true;
- }
- else {
- $this->pr(18, compact('explicit_credit', 'credit'),
- 'Update Explicit Credit');
- $EC = new StatementEntry();
- $EC->id = $explicit_credit['StatementEntry']['id'];
- $EC->saveField('amount', $credit['balance']);
+ $result = $this->addStatementEntry
+ (array('type' => 'SURPLUS',
+ 'account_id' => $credit['LedgerEntry']['account_id'],
+ 'amount' => $credit['balance'],
+ 'effective_date' => $credit['Transaction']['stamp'],
+ 'transaction_id' => $credit['Transaction']['id'],
+ 'customer_id' => $customer_id,
+ 'lease_id' => $lease_id,
+ ));
+ $ret['Credit'] = $result;
+ if ($result['error'])
+ $ret['error'] = true;
+ }
+ else {
+ $this->pr(18, compact('explicit_credit', 'credit'),
+ 'Update Explicit Credit');
+ $EC = new StatementEntry();
+ $EC->id = $explicit_credit['StatementEntry']['id'];
+ $EC->saveField('amount', $credit['balance']);
+ }
}
}
diff --git a/site/models/tender.php b/site/models/tender.php
index 405816e..b0e913b 100644
--- a/site/models/tender.php
+++ b/site/models/tender.php
@@ -21,7 +21,7 @@ class Tender extends AppModel {
* - Performs any work needed before the save occurs
*/
- function afterSave() {
+ function afterSave($created) {
// Come up with a (not necessarily unique) name for the tender.
// For checks & money orders, this will be based on the check
// number. For other types of tender, we'll just use the
@@ -45,7 +45,7 @@ class Tender extends AppModel {
if ($newname !== $this->field('name'))
$this->saveField('name', $newname);
- return parent::afterSave();
+ return parent::afterSave($created);
}
diff --git a/site/models/transaction.php b/site/models/transaction.php
index 0e85c06..8813f99 100644
--- a/site/models/transaction.php
+++ b/site/models/transaction.php
@@ -685,6 +685,7 @@ class Transaction extends AppModel {
// with the customer statement (charges, disbursements, credits, etc).
$bounce_result = $this->addDeposit
(array('Transaction' => array('stamp' => $stamp,
+ 'type' => 'WITHDRAWAL',
'crdr' => 'CREDIT'),
'Entry' => array(array('tender_id' => null,
'account_id' => $this->Account->nsfAccountID(),
diff --git a/site/views/customers/receipt.ctp b/site/views/customers/receipt.ctp
index 76fdb86..35e8cfb 100644
--- a/site/views/customers/receipt.ctp
+++ b/site/views/customers/receipt.ctp
@@ -315,7 +315,7 @@ echo $this->element('statement_entries', array
'grid_setup' => array('hiddengrid' => true),
'caption' => '',
'action' => 'idlist',
- 'exclude' => array('Customer', 'Unit', 'Type', 'Debit', 'Credit'),
+ 'exclude' => array('Customer', 'Type', 'Debit', 'Credit'),
'include' => array('Applied', 'Balance'),
'remap' => array('Applied' => 'Paid'),
'limit' => 8,
diff --git a/site/views/leases/invoice.ctp b/site/views/leases/invoice.ctp
index 07aca35..30edd1b 100644
--- a/site/views/leases/invoice.ctp
+++ b/site/views/leases/invoice.ctp
@@ -71,7 +71,7 @@ function showResponse(responseText, statusText) {
}
// get a clean slate
- //resetForm();
+ resetForm();
}
else {
$('#results').html('Failed to save invoice!
');
@@ -331,6 +331,7 @@ Configure::write('debug', '0');
' value="">');
$("#TransactionComment").val('Move-In Charges');
+
id = addChargeSource(false);
$('#Entry'+id+'Form').removeCol(2);
$('#Entry'+id+'Form input, #Entry'+id+'Form select').attr('disabled', true);
@@ -351,7 +352,7 @@ Configure::write('debug', '0');
' value="">');
//$('#Entry'+id+'Comment').val('Move-In Security Deposit');
$('#Entry'+id+'Comment').removeAttr('disabled');
-
+
id = addChargeSource(false);
$('#Entry'+id+'Form').removeCol(2);
@@ -376,8 +377,7 @@ Configure::write('debug', '0');
('');
- $('#Entry'+id+'Comment').val('Move-In Rent'
- );
+ $('#Entry'+id+'Comment').val("");
$('#Entry'+id+'Comment').removeAttr('disabled');
diff --git a/site/views/leases/move.ctp b/site/views/leases/move.ctp
index 4787c7d..028a8d6 100644
--- a/site/views/leases/move.ctp
+++ b/site/views/leases/move.ctp
@@ -128,7 +128,7 @@ if ($move_type !== 'out') {
),
'include' => array('Deposit'),
'exclude' => array('Balance'),
- 'action' => 'unoccupied',
+ 'action' => 'vacant',
'nolinks' => true,
'limit' => 10,
)));
diff --git a/site/views/tenders/deposit.ctp b/site/views/tenders/deposit.ctp
index 4616d18..b073b28 100644
--- a/site/views/tenders/deposit.ctp
+++ b/site/views/tenders/deposit.ctp
@@ -30,7 +30,8 @@ foreach ($depositTypes AS $type) {
'separator' => '
',
'onclick' => "switchSelection({$type['id']})",
'legend' => false,
- 'value' => $type['stats']['undeposited'] > 0 ? 'all' : 'none',
+ // REVISIT : 20080811; Make opt-in, or opt-out?
+ 'value' => $type['stats']['undeposited'] > 0 ? 'none' : 'none',
'disabled' => $type['stats']['undeposited'] <= 0,
'options' => $radioOptions,
));
diff --git a/site/views/units/view.ctp b/site/views/units/view.ctp
index 47aa53d..cb3741f 100644
--- a/site/views/units/view.ctp
+++ b/site/views/units/view.ctp
@@ -87,6 +87,8 @@ if (isset($current_lease['id'])) {
'filter' => array('Lease.id' => $current_lease['id']),
'include' => array('Through'),
'exclude' => array('Customer', 'Lease', 'Unit'),
+ 'sort_column' => 'Effective',
+ 'sort_order' => 'DESC',
)));
}