diff --git a/controllers/leases_controller.php b/controllers/leases_controller.php index 54c2fee..241b43b 100644 --- a/controllers/leases_controller.php +++ b/controllers/leases_controller.php @@ -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); diff --git a/controllers/maps_controller.php b/controllers/maps_controller.php index bd971db..79d6692 100644 --- a/controllers/maps_controller.php +++ b/controllers/maps_controller.php @@ -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,15 +104,14 @@ 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), )); /* pr(compact('map', 'units')); */ /* $this->render('/fake'); */ /* return; */ - + /***** * The preference would be to leave all things "screen" related * to reside in the view. However, two separate views need this @@ -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) { diff --git a/controllers/units_controller.php b/controllers/units_controller.php index e2c11eb..7dac5ef 100644 --- a/controllers/units_controller.php +++ b/controllers/units_controller.php @@ -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']; diff --git a/models/lease.php b/models/lease.php index 67ffec7..9926427 100644 --- a/models/lease.php +++ b/models/lease.php @@ -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 : 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'"); + } + + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/models/maps_unit.php b/models/maps_unit.php deleted file mode 100644 index 4486e27..0000000 --- a/models/maps_unit.php +++ /dev/null @@ -1,15 +0,0 @@ - array('numeric'), - 'map_id' => array('numeric'), - 'unit_id' => array('numeric'), - 'pt_top' => array('numeric'), - 'pt_left' => array('numeric'), - 'transpose' => array('boolean') - ); - -} -?> \ No newline at end of file diff --git a/models/unit.php b/models/unit.php index cbbb5ff..602460a 100644 --- a/models/unit.php +++ b/models/unit.php @@ -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 : 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), - )); - } diff --git a/views/elements/leases.ctp b/views/elements/leases.ctp index 7293f8c..cdd4602 100644 --- a/views/elements/leases.ctp +++ b/views/elements/leases.ctp @@ -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'))); diff --git a/views/elements/units.ctp b/views/elements/units.ctp index 4dbb165..b5b5220 100644 --- a/views/elements/units.ctp +++ b/views/elements/units.ctp @@ -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');