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:
@@ -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);
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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'];
|
||||
|
||||
@@ -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'");
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
|
||||
@@ -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')
|
||||
);
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -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),
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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')));
|
||||
|
||||
@@ -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');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user