Got rid of LATE as a unit status, as it did not represent an physical condition. The logic was moved to Lease, where it is a much better fit. The sitemap still presents LATE units, as it is a useful view, but the underlying logic is driven from Lease, not Unit. This checkin also includes a small feature change to how late charges are assessed, as well as a menu item to kick off the charge assessments (both accidentally wedged in to this changeset).

git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716/site@547 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
abijah
2009-08-13 20:55:19 +00:00
parent 97d16bd712
commit 1fee7646b6
8 changed files with 87 additions and 97 deletions

View File

@@ -3,10 +3,11 @@
class LeasesController extends AppController {
var $sidemenu_links =
array(array('name' => 'Leases', 'header' => true),
array('name' => 'Active', 'url' => array('controller' => 'leases', 'action' => 'active')),
array('name' => 'Closed', 'url' => array('controller' => 'leases', 'action' => 'closed')),
array('name' => 'All', 'url' => array('controller' => 'leases', 'action' => 'all')),
array(array('name' => 'Leases', 'header' => true),
array('name' => 'Active', 'url' => array('controller' => 'leases', 'action' => 'active')),
array('name' => 'Closed', 'url' => array('controller' => 'leases', 'action' => 'closed')),
array('name' => 'Delinquent', 'url' => array('controller' => 'leases', 'action' => 'delinquent')),
array('name' => 'All', 'url' => array('controller' => 'leases', 'action' => 'all')),
);
@@ -28,10 +29,11 @@ class LeasesController extends AppController {
* - Generate a listing of leases
*/
function index() { $this->all(); }
function active() { $this->gridView('Active Leases'); }
function closed() { $this->gridView('Closed Leases'); }
function all() { $this->gridView('All Leases', 'all'); }
function index() { $this->all(); }
function active() { $this->gridView('Active Leases'); }
function delinquent() { $this->gridView('Delinquent Leases'); }
function closed() { $this->gridView('Closed Leases'); }
function all() { $this->gridView('All Leases', 'all'); }
/**************************************************************************
@@ -63,6 +65,8 @@ class LeasesController extends AppController {
function gridDataFields(&$params, &$model) {
$fields = parent::gridDataFields($params, $model);
$fields[] = ("IF(" . $this->Lease->conditionDelinquent() . "," .
" 'DELINQUENT', 'CURRENT') AS 'status'");
return array_merge($fields,
$this->Lease->StatementEntry->chargeDisbursementFields(true));
}
@@ -73,6 +77,9 @@ class LeasesController extends AppController {
if ($params['action'] === 'active') {
$conditions[] = 'Lease.close_date IS NULL';
}
elseif ($params['action'] === 'delinquent') {
$conditions[] = $this->Lease->conditionDelinquent();
}
elseif ($params['action'] === 'closed') {
$conditions[] = 'Lease.close_date IS NOT NULL';
}
@@ -422,7 +429,11 @@ class LeasesController extends AppController {
$this->Lease->assessMonthlyLateAll($date);
$this->redirect(array('action'=>'index'));
}
function assess_all($date = null) {
$this->Lease->assessMonthlyRentAll($date);
$this->Lease->assessMonthlyLateAll($date);
$this->redirect(array('action'=>'index'));
}
/**************************************************************************
**************************************************************************
@@ -450,13 +461,7 @@ class LeasesController extends AppController {
)
);
$lease['Lease']['paid_through'] = $this->Lease->rentPaidThrough($id);
$this->set('charge_gaps', $this->Lease->rentChargeGaps($id));
$this->set('charge_through', $this->Lease->rentChargeThrough($id));
// Figure out the outstanding balances for this lease
// Figure out the outstanding balances for this lease
$outstanding_balance = $this->Lease->balance($id);
$outstanding_deposit = $this->Lease->securityDepositBalance($id);

View File

@@ -95,7 +95,8 @@ class MapsController extends AppController {
array('fields' => array()),
'CurrentLease' =>
array('fields' => array()),
array('fields' => array($this->Map->Unit->CurrentLease->
delinquentField('CurrentLease'))),
'UnitSize' =>
array('fields' => array('id', 'depth', 'width',
@@ -103,8 +104,7 @@ class MapsController extends AppController {
'MapsUnit.pt_left',
'MapsUnit.transpose')),
),
'fields' => array_merge(array('id', 'name'),
$this->Map->Unit->statusFields()),
'fields' => array('id', 'name', 'status'),
'conditions' => array('Map.id' => $id),
));
@@ -136,9 +136,6 @@ class MapsController extends AppController {
// Go through each unit in the map, calculating the map location
foreach ($units AS $unit) {
// Add the calculated fields to the Unit
$unit['Unit'] = $unit[0] + $unit['Unit'];
$lft = $unit['MapsUnit']['pt_left'] + $boundary_adjustment;
$top = $unit['MapsUnit']['pt_top'] + $boundary_adjustment;
@@ -167,7 +164,9 @@ class MapsController extends AppController {
'width' => $width,
'depth' => $depth,
'n-s' => $unit['MapsUnit']['transpose'] ? 0 : 1,
'status' => $unit['Unit']['status']
'status' => (($unit['Unit']['status'] === 'OCCUPIED' &&
!empty($unit[0]['delinquent']))
? 'LATE' : $unit['Unit']['status'])
);
}
@@ -185,8 +184,10 @@ class MapsController extends AppController {
*/
function legend($id = null, $requested_width = 400) {
$status = $this->Map->Unit->activeStatusEnums();
//pr($status);
$status = array_keys($this->Map->Unit->activeStatusEnums());
$occupied_key = array_search('OCCUPIED', $status);
array_splice($status, $occupied_key+1, 0, array('LATE'));
$rows = 2;
$cols = (int)((count($status) + $rows - 1) / $rows);
@@ -216,7 +217,7 @@ class MapsController extends AppController {
$item_width *= $screen_adjustment_factor;
$item_depth *= $screen_adjustment_factor;
foreach ($status AS $code => $value) {
foreach ($status AS $code) {
$info['units'][] = array('name' => $code,
'status' => $code,
'width' => $item_width,
@@ -268,7 +269,7 @@ class MapsController extends AppController {
$info['palate']['unit']['OCCUPIED']['bg'] = array('red' => 0, 'green' => 128, 'blue' => 255);
$info['palate']['unit']['LATE']['bg'] = array('red' => 255, 'green' => 192, 'blue' => 192);
$info['palate']['unit']['LOCKED']['bg'] = array('red' => 255, 'green' => 64, 'blue' => 64);
$info['palate']['unit']['LIENED']['bg'] = array('red' => 255, 'green' => 128, 'blue' => 128);
$info['palate']['unit']['LIENED']['bg'] = array('red' => 255, 'green' => 0, 'blue' => 128);
// Determine text color to go with each background
foreach ($info['palate']['unit'] AS &$code) {

View File

@@ -4,7 +4,6 @@ class UnitsController extends AppController {
var $sidemenu_links =
array(array('name' => 'Units', 'header' => true),
array('name' => 'Delinquent', 'url' => array('controller' => 'units', 'action' => 'delinquent')),
array('name' => 'Occupied', 'url' => array('controller' => 'units', 'action' => 'occupied')),
array('name' => 'Vacant', 'url' => array('controller' => 'units', 'action' => 'vacant')),
array('name' => 'Unavailable', 'url' => array('controller' => 'units', 'action' => 'unavailable')),
@@ -34,7 +33,6 @@ class UnitsController extends AppController {
function unavailable() { $this->gridView('Unavailable Units'); }
function vacant() { $this->gridView('Vacant Units'); }
function occupied() { $this->gridView('Occupied Units'); }
function delinquent() { $this->gridView('Delinquent Units'); }
function all() { $this->gridView('All Units', 'all'); }
@@ -84,7 +82,6 @@ class UnitsController extends AppController {
$fields = parent::gridDataFields($params, $model);
return array_merge($fields,
$this->Unit->statusFields(),
$this->Unit->Lease->StatementEntry->chargeDisbursementFields(true));
}
@@ -100,9 +97,6 @@ class UnitsController extends AppController {
elseif ($params['action'] === 'occupied') {
$conditions[] = $this->Unit->conditionOccupied();
}
elseif ($params['action'] === 'delinquent') {
$conditions[] = $this->Unit->conditionDelinquent();
}
elseif ($params['action'] === 'unoccupied') {
$conditions[] = array('NOT' => array($this->Unit->conditionOccupied()));
}
@@ -216,8 +210,6 @@ class UnitsController extends AppController {
'Lease' => array('Customer'),
'CurrentLease' => array('Customer')
),
'fields' => array_merge(array('Unit.*'),
$this->Unit->statusFields()),
'conditions' => array('Unit.id' => $id),
));
$unit['Unit'] = $unit[0] + $unit['Unit'];

View File

@@ -426,6 +426,17 @@ class Lease extends AppModel {
$date = mktime(0, 0, 0, $date_parts['mon'], 11, $date_parts['year']);
}
// Don't assess a late charge if the late charge date hasn't
// even come yet. This is questionable whether we really
// should restrict, since the user could know what they're
// doing, and/or the server clock could be off (although that
// would certainly have much larger ramifications). But, the
// fact is that this check likely handles the vast majority
// of the expected behavior, and presents an issue for very
// few users, if any at all.
if ($date > time())
return $this->prReturn(null);
// Make sure we're not trying to assess late charges on a closed lease
$close_date = $this->field('close_date');
$this->pr(17, compact('close_date'));
@@ -449,6 +460,10 @@ class Lease extends AppModel {
// Determine if the customer is actually late. This is based on
// when they've paid through, plus 10 days before they're late.
// REVISIT <AP>: 20090813
// Of course, 10 days is a terrible hardcode. This should be
// driven from the late schedule, saved as part of the lease
// (when finally implemented).
$paid_through_date = strtotime($this->rentPaidThrough($id));
$this->pr(17, compact('date', 'paid_through_date')
+ array('date_str' => date('Y-m-d', $date),
@@ -512,6 +527,31 @@ class Lease extends AppModel {
}
/**************************************************************************
**************************************************************************
**************************************************************************
* functions: delinquency
* - SQL fragments to determine whether a lease is delinquent
*/
function conditionDelinquent($table_name = 'Lease') {
if (empty($table_name)) $t = ''; else $t = $table_name . '.';
return ("({$t}close_date IS NULL AND" .
" NOW() > DATE_ADD({$t}paid_through_date, INTERVAL 15 DAY))");
}
function delinquentDaysSQL($table_name = 'Lease') {
if (empty($table_name)) $t = ''; else $t = $table_name . '.';
return ("IF(" . $this->conditionDelinquent($table_name) . "," .
" DATEDIFF(NOW(), {$t}paid_through_date)-1," .
" NULL)");
}
function delinquentField($table_name = 'Lease') {
return ($this->delinquentDaysSQL($table_name) . " AS 'delinquent'");
}
/**************************************************************************
**************************************************************************
**************************************************************************

View File

@@ -1,15 +0,0 @@
<?php
class MapsUnit extends AppModel {
var $name = 'MapsUnit';
var $validate = array(
'id' => array('numeric'),
'map_id' => array('numeric'),
'unit_id' => array('numeric'),
'pt_top' => array('numeric'),
'pt_left' => array('numeric'),
'transpose' => array('boolean')
);
}
?>

View File

@@ -25,7 +25,6 @@ class Unit extends AppModel {
var $hasMany = array(
'Lease',
'MapsUnit',
);
//var $default_log_level = array('log' => 30, 'show' => 15);
@@ -88,16 +87,6 @@ class Unit extends AppModel {
return $this->prReturn(true);
}
function delinquent($enum) {
INTERNAL_ERROR("NOT YET FULLY IMPLEMENTED (Need check for LATE)");
return $this->statusCheck($enum, 'OCCUPIED', true, null, false);
}
function conditionDelinquent() {
return ('(Unit.status > ' . $this->statusValue('OCCUPIED') .
" OR " . $this->delinquentTest() . ")");
}
function occupied($enum) {
return $this->statusCheck($enum, 'OCCUPIED', false, null, false);
}
@@ -149,13 +138,6 @@ class Unit extends AppModel {
($val < $this->occupiedEnumValue())) {
unset($enums[$enum]);
}
// REVISIT <AP>: 20090812
// LATE is the only temporal condition, and somehow
// feels like it should be treated differently than
// the rest. How can a unit be marked as LATE when
// it is not inherent, but a function of time?
if ($enum === 'LATE')
unset($enums[$enum]);
}
return $this->prReturn($enums);
@@ -199,27 +181,6 @@ class Unit extends AppModel {
}
/**************************************************************************
**************************************************************************
**************************************************************************
* function: statusField
* - Returns the status field SQL query
*/
function delinquentTest() {
return ("(`status` = 'OCCUPIED' AND " .
/* "(DATE_ADD(CurrentLease.paid_through_date, INTERVAL 10 DAY)" . */
/* " < CurrentLease.charge_through_date)," . */
" (DATE_ADD(CurrentLease.paid_through_date, INTERVAL 15 DAY)" .
" < NOW()))");
}
function statusFields() {
return array(
//"IF(`status` = 'OCCUPIED' AND " . $this->delinquentTest() . "," .
"IF(" . $this->delinquentTest() . "," .
" 'LATE', `status`) AS 'status'");
}
/**************************************************************************
**************************************************************************
**************************************************************************
@@ -227,11 +188,6 @@ class Unit extends AppModel {
* - Update any cached or calculated fields
*/
function update($id) {
$unit = $this->find('first',
array('contain' => array('CurrentLease'),
'conditions' => array('Unit.id' => $id),
));
}

View File

@@ -12,9 +12,20 @@ $cols['Signed'] = array('index' => 'Lease.lease_date', 'formatter' => 'dat
$cols['Move-In'] = array('index' => 'Lease.movein_date', 'formatter' => 'date');
$cols['Move-Out'] = array('index' => 'Lease.moveout_date', 'formatter' => 'date');
$cols['Closed'] = array('index' => 'Lease.close_date', 'formatter' => 'date');
$cols['Paid-Thru'] = array('index' => 'Lease.paid_through_date', 'formatter' => 'date');
$cols['Status'] = array('index' => 'status', 'formatter' => 'enum', 'width' => 100);
$cols['Balance'] = array('index' => 'balance', 'formatter' => 'currency');
$cols['Comment'] = array('index' => 'Lease.comment', 'formatter' => 'comment');
if (!empty($this->params['action'])) {
if ($this->params['action'] === 'closed')
$grid->invalidFields(array('Paid-Thru', 'Status'));
elseif ($this->params['action'] === 'active')
$grid->invalidFields(array('Closed'));
elseif ($this->params['action'] === 'delinquent')
$grid->invalidFields(array('Closed'));
}
// Render the grid
$grid
->columns($cols)
@@ -22,4 +33,4 @@ $grid
->defaultFields(array('LeaseID', 'Lease'))
->searchFields(array('Customer', 'Unit'))
->render($this, isset($config) ? $config : null,
array_diff(array_keys($cols), array('Signed', 'Comment')));
array_diff(array_keys($cols), array('Signed', 'Status', 'Comment')));

View File

@@ -9,7 +9,7 @@ $cols['Unit'] = array('index' => 'Unit.name', 'formatter' => 'shortname'
$cols['Size'] = array('index' => 'UnitSize.name', 'formatter' => 'shortname');
$cols['Rent'] = array('index' => 'Unit.rent', 'formatter' => 'currency');
$cols['Deposit'] = array('index' => 'Unit.deposit', 'formatter' => 'currency');
$cols['Status'] = array('index' => 'status', 'formatter' => 'name'); // We have enough real estate
$cols['Status'] = array('index' => 'Unit.status', 'formatter' => 'name'); // We have enough real estate
$cols['Balance'] = array('index' => 'balance', 'formatter' => 'currency');
$cols['Comment'] = array('index' => 'Unit.comment', 'formatter' => 'comment');