Some of the finer detail work, mostly around pre-populating the move-in invoice with useful and correct data, and allowing the lease rent and deposit to be set at movein.

git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@503 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
abijah
2009-08-07 22:52:01 +00:00
parent 2e36d46329
commit 654eb0960e
12 changed files with 223 additions and 24 deletions

View File

@@ -5,6 +5,7 @@ use Data::Dumper;
use File::Copy;
my $closing_one_transaction = 0;
my $work_from_scratch = 1;
# Internally adjust all numbers coming from the database to
# be in inches. Not necessary to go to this detail, but the
@@ -1468,7 +1469,7 @@ addRow('double_entries', {
######################################################################
## Debug ... work from scratch
if (defined $work_from_scratch) {
if ($work_from_scratch) {
# delete $newdb{'tables'}{'contacts'}{'rows'};
# delete $newdb{'tables'}{'contacts_methods'}{'rows'};
# delete $newdb{'tables'}{'contacts_addresses'}{'rows'};
@@ -1482,6 +1483,11 @@ if (defined $work_from_scratch) {
delete $newdb{'tables'}{'statement_entries'}{'rows'};
delete $newdb{'tables'}{'tenders'}{'rows'};
delete $newdb{'tables'}{'transactions'}{'rows'};
foreach (@{$newdb{'tables'}{'units'}{'rows'}}) {
$_->{'status'} = 'VACANT'
if defined $_ && ($_->{'status'} =~ /^(OCCUPIED)$/ || $_->{'name'} =~ /^Y/);
}
}

View File

@@ -135,17 +135,22 @@ class LeasesController extends AppController {
// Handle the move in based on the data given
//pr(array('Move-in data', $this->data));
foreach (array('deposit', 'rent') AS $currency) {
$this->data['Lease'][$currency]
= str_replace('$', '', $this->data['Lease'][$currency]);
}
$lid = $this->Lease->moveIn($this->data['Lease']['customer_id'],
$this->data['Lease']['unit_id'],
null, null,
$this->data['Lease']['deposit'],
$this->data['Lease']['rent'],
$this->data['Lease']['movein_date'],
$this->data['Lease']['comment']
);
// Since this is a new lease, go to the invoice
// screen so we can start assessing charges.
$this->redirect(array('action'=>'invoice', $lid));
$this->redirect(array('action'=>'invoice', $lid, 'move-in'));
// For debugging, only if the redirect above have been
// commented out, otherwise this section isn't reached.
@@ -362,13 +367,30 @@ class LeasesController extends AppController {
$A = new Account();
$charge_accounts = $A->invoiceAccounts();
$default_account = $A->rentAccountID();
$this->set(compact('charge_accounts', 'default_account'));
$rent_account = $A->rentAccountID();
$security_deposit_account = $A->securityDepositAccountID();
$this->set(compact('charge_accounts', 'default_account',
'rent_account', 'security_deposit_account'));
// REVISIT <AP> 20090705:
// Of course, the late charge should come from the late_schedule
$default_rent = $lease['Lease']['rent'];
$default_late = 10;
$this->set(compact('default_rent', 'default_late'));
$this->set(compact('default_late'));
if ($type === 'move-in') {
$movein = array();
$movein['time'] = strtotime($lease['Lease']['movein_date']);
$movein['effective_time'] = strtotime($lease['Lease']['movein_date']);
$movein_date = getdate($movein['effective_time']);
$movein['through_time'] = mktime(0, 0, 0, $movein_date['mon'] + 1, 0, $movein_date['year']);
$days_in_month = idate('d', $movein['through_time']);
$movein['prorated_days'] = $days_in_month - $movein_date['mday'] + 1;
$movein['prorated_rent'] = $lease['Lease']['rent'] * $movein['prorated_days'] / $days_in_month;
$movein['prorated'] = $movein['prorated_days'] != $days_in_month;
$movein['deposit'] = $lease['Lease']['deposit'];
$this->set(compact('movein'));
}
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
$lease['Unit']['name'] . ': ' .

View File

@@ -245,10 +245,12 @@ class UnitsController extends AppController {
$this->sidemenu_links[] =
array('name' => 'Move-Out', 'url' => array('action' => 'move_out',
$id));
} else {
} elseif ($this->Unit->available($unit['Unit']['status'])) {
$this->sidemenu_links[] =
array('name' => 'Move-In', 'url' => array('action' => 'move_in',
$id));
} else {
// Unit is unavailable (dirty, damaged, reserved, business-use, etc)
}
if (isset($unit['CurrentLease']['id']) &&

View File

@@ -656,7 +656,7 @@ class StatementEntry extends AppModel {
* - Returns summary data from the requested statement entry
*/
function stats($id = null, $query = null) {
$this->prFunctionLevel(array('log' => 19, 'show' => 10));
//$this->prFunctionLevel(array('log' => 19, 'show' => 10));
$this->prEnter(compact('id', 'query'));
$this->queryInit($query);

View File

@@ -475,6 +475,10 @@ class Transaction extends AppModel {
// accidentally pick up stale data.
$le1 = $le1_tender = $le2 = $se = null;
// Really, data should be sanitized at the controller,
// and not here. However, it's a one stop cleanup.
$entry['amount'] = str_replace('$', '', $entry['amount']);
// Add entry amount into the transaction total
$transaction['amount'] += $entry['amount'];

View File

@@ -55,10 +55,50 @@ class Unit extends AppModel {
return $this->statusValue('OCCUPIED');
}
function statusCheck($id_or_enum,
$min = null, $min_strict = false,
$max = null, $max_strict = false)
{
$this->prEnter(compact('id_or_enum', 'min', 'min_strict', 'max', 'max_strict'));
if (is_int($id_or_enum)) {
$this->id = $id_or_enum;
$id_or_enum = $this->field('status');
}
$enum_val = $this->statusValue($id_or_enum);
if (isset($min) && is_string($min))
$min = $this->statusValue($min);
if (isset($max) && is_string($max))
$max = $this->statusValue($max);
$this->pr(17, compact('enum_val', 'min', 'min_strict', 'max', 'max_strict'));
if (isset($min) &&
($enum_val < $min ||
($min_strict && $enum_val == $min)))
return $this->prReturn(false);
if (isset($max) &&
($enum_val > $max ||
($max_strict && $enum_val == $max)))
return $this->prReturn(false);
return $this->prReturn(true);
}
function occupied($enum) {
return $this->statusCheck($enum, 'OCCUPIED', false, null, false);
}
function conditionOccupied() {
return ('Unit.status >= ' . $this->statusValue('OCCUPIED'));
}
function vacant($enum) {
return $this->statusCheck($enum, 'UNAVAILABLE', true, 'OCCUPIED', true);
}
function conditionVacant() {
return ('Unit.status BETWEEN ' .
($this->statusValue('UNAVAILABLE')+1) .
@@ -66,10 +106,16 @@ class Unit extends AppModel {
($this->statusValue('OCCUPIED')-1));
}
function unavailable($enum) {
return $this->statusCheck($enum, null, false, 'UNAVAILABLE', false);
}
function conditionUnavailable() {
return ('Unit.status <= ' . $this->statusValue('UNAVAILABLE'));
}
function available($enum) { return $this->vacant($enum); }
/**************************************************************************
**************************************************************************

View File

@@ -123,7 +123,7 @@ foreach ($fields AS $field => $config) {
}
echo $this->element('table',
compact('class', 'caption', 'headers',
compact('id', 'class', 'caption', 'headers',
'rows', 'row_class', 'suppress_alternate_rows',
'column_class')
);

View File

@@ -64,7 +64,10 @@ if (isset($rows) && is_array($rows) && count($rows)) {
$class = implode(' ', $class);
// OK, output the table HTML
echo('<TABLE' . (isset($class) ? ' CLASS="'.$class.'"' : '') . '>' . "\n");
echo('<TABLE' .
(isset($id) ? ' ID="'.$id.'"' : '') .
(isset($class) ? ' CLASS="'.$class.'"' : '') .
'>' . "\n");
if (isset($caption))
echo(' <CAPTION>' . $caption . '</CAPTION>' . "\n");

View File

@@ -8,6 +8,7 @@ $cols['ID'] = array('index' => 'Unit.id', 'formatter' => 'id');
$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' => 'Unit.status', 'formatter' => 'name'); // We have enough real estate
$cols['Balance'] = array('index' => 'balance', 'formatter' => 'currency');
$cols['Comment'] = array('index' => 'Unit.comment', 'formatter' => 'comment');
@@ -19,4 +20,4 @@ $grid
->defaultFields(array('Sort', 'ID', 'Unit'))
->searchFields(array('Unit', 'Size', 'Status'))
->render($this, isset($config) ? $config : null,
array_diff(array_keys($cols), array('Walk', 'Comment')));
array_diff(array_keys($cols), array('Walk', 'Deposit', 'Comment')));

View File

@@ -4,6 +4,13 @@
<?php
; // Editor alignment
$unit = $lease['Unit'];
$customer = $lease['Customer'];
if (isset($lease['Lease']))
$lease = $lease['Lease'];
/**********************************************************************
**********************************************************************
**********************************************************************
@@ -11,6 +18,9 @@
* Javascript
*/
// Warnings _really_ screw up javascript
$saved_debug_state = Configure::read('debug');
Configure::write('debug', '0');
?>
<script type="text/javascript"><!--
@@ -90,8 +100,74 @@ function resetForm() {
$("#invoice-late").html("INTERNAL ERROR");
$("#invoice-deposit").html("INTERNAL ERROR");
<?php if (empty($movein)): ?>
addChargeSource(false);
datepickerNow('TransactionStamp');
<?php else: ?>
var id;
$("#TransactionStamp").datepicker('disable');
$("#TransactionStamp").val("<?php echo date('m/d/Y', $movein['time']); ?>");
$('#TransactionStamp').after
('<input type="hidden"' +
' name="data[Transaction][stamp]"' +
' value="<?php echo date('m/d/Y', $movein['time']); ?>">');
$("#TransactionComment").val('Move-In Charges');
id = addChargeSource(false);
$('#Entry'+id+'Form').removeCol(2);
$('#Entry'+id+'Form input, #Entry'+id+'Form select').attr('disabled', true);
$('#Entry'+id+'EffectiveDate').val("<?php echo date('m/d/Y', $movein['effective_time']); ?>");
$('#Entry'+id+'EffectiveDate').after
('<input type="hidden"' +
' name="data[Entry]['+id+'][effective_date]"' +
' value="<?php echo date('m/d/Y', $movein['effective_time']); ?>">');
$('#Entry'+id+'AccountId').val(<?php echo $securityDepositAccount; ?>);
$('#Entry'+id+'AccountId').after
('<input type="hidden"' +
' name="data[Entry]['+id+'][account_id]"' +
' value="<?php echo $securityDepositAccount; ?>">');
$('#Entry'+id+'Amount').val("<?php echo FormatHelper::currency($movein['deposit']); ?>");
$('#Entry'+id+'Amount').after
('<input type="hidden"' +
' name="data[Entry]['+id+'][amount]"' +
' value="<?php echo FormatHelper::currency($movein['deposit']); ?>">');
//$('#Entry'+id+'Comment').val('Move-In Security Deposit');
$('#Entry'+id+'Comment').removeAttr('disabled');
id = addChargeSource(false);
$('#Entry'+id+'Form').removeCol(2);
$('#Entry'+id+'Form input, #Entry'+id+'Form select').attr('disabled', true);
$('#Entry'+id+'EffectiveDate').val("<?php echo date('m/d/Y', $movein['effective_time']); ?>");
$('#Entry'+id+'EffectiveDate').after
('<input type="hidden"' +
' name="data[Entry]['+id+'][effective_date]"' +
' value="<?php echo date('m/d/Y', $movein['effective_time']); ?>">');
$('#Entry'+id+'ThroughDate').val("<?php echo date('m/d/Y', $movein['through_time']); ?>");
$('#Entry'+id+'ThroughDate').after
('<input type="hidden"' +
' name="data[Entry]['+id+'][through_date]"' +
' value="<?php echo date('m/d/Y', $movein['through_time']); ?>">');
$('#Entry'+id+'AccountId').val(<?php echo $rentAccount; ?>);
$('#Entry'+id+'AccountId').after
('<input type="hidden"' +
' name="data[Entry]['+id+'][account_id]"' +
' value="<?php echo $rentAccount; ?>">');
$('#Entry'+id+'Amount').val("<?php echo FormatHelper::currency($movein['prorated_rent']); ?>");
$('#Entry'+id+'Amount').after
('<input type="hidden"' +
' name="data[Entry]['+id+'][amount]"' +
' value="<?php echo FormatHelper::currency($movein['prorated_rent']); ?>">');
$('#Entry'+id+'Comment').val('Move-In Rent'
<?php if ($movein['prorated']) echo "+ ' (Prorated)'" ?>);
$('#Entry'+id+'Comment').removeAttr('disabled');
<?php endif; ?>
}
@@ -152,7 +228,8 @@ function addChargeSource(flash) {
<?php
echo FormatHelper::phpVarToJavascript
($this->element('form_table',
array('class' => "item invoice ledger-entry entry",
array('id' => 'Entry%{id}Form',
'class' => "item invoice ledger-entry entry",
//'with_name_after' => ':',
'field_prefix' => 'Entry.%{id}',
'fields' => array
@@ -192,12 +269,16 @@ function addChargeSource(flash) {
numberOfMonths: [1, 1],
showCurrentAtPos: 0,
dateFormat: 'mm/dd/yy' });
return id;
}
--></script>
<?php
; // align
// Re-Enable warnings
Configure::write('debug', $saved_debug_state);
echo $this->element('leases', array
('config' => array
@@ -205,7 +286,7 @@ echo $this->element('leases', array
'grid_div_class' => 'text-below',
'caption' => ('<A HREF="#" ONCLICK="$(\'#leases-list .HeaderButton\').click();'.
' return false;">Select Lease</A>'),
'grid_setup' => array('hiddengrid' => isset($lease['Lease']['id'])),
'grid_setup' => array('hiddengrid' => isset($lease['id'])),
'grid_events' => array('onSelectRow' =>
array('ids' =>
'if (ids != null){onRowSelect("#"+$(this).attr("id"), ids);}'),
@@ -285,7 +366,17 @@ echo $form->submit('Generate Invoice') . "\n";
<div><H4>Response</H4><div id="response-debug"></div></div>
<div><H4>Output</H4><div id="output-debug"></div></div>
<?php
// Warnings _really_ screw up javascript
Configure::write('debug', '0');
?>
<script type="text/javascript"><!--
$.fn.removeCol = function(col){
if(!col){ col = 1; }
$('tr td:nth-child('+col+'), tr th:nth-child('+col+')', this).remove();
};
$(document).ready(function(){
$("#TransactionStamp")
.attr('autocomplete', 'off')
@@ -296,19 +387,19 @@ echo $form->submit('Generate Invoice') . "\n";
resetForm();
<?php if (isset($lease['Lease']['id'])): ?>
$("#lease-id").val(<?php echo $lease['Lease']['id']; ?>);
//$("#invoice-lease").html("<?php echo '#'.$lease['Lease']['number']; ?>");
<?php if (isset($lease['id'])): ?>
$("#lease-id").val(<?php echo $lease['id']; ?>);
//$("#invoice-lease").html("<?php echo '#'.$lease['number']; ?>");
$("#invoice-lease").html('<A HREF="/pmgr/site/leases/view/' +
"<?php echo $lease['Lease']['id']; ?>" +
"<?php echo $lease['id']; ?>" +
'">#' +
"<?php echo $lease['Lease']['number']; ?>" +
"<?php echo $lease['number']; ?>" +
'</A>');
$("#invoice-unit").html("<?php echo $lease['Unit']['name']; ?>");
$("#invoice-customer").html("<?php echo $lease['Customer']['name']; ?>");
$("#invoice-rent").html("<?php echo FormatHelper::currency($lease['Lease']['rent']); ?>");
$("#invoice-late").html('$10.00');
$("#invoice-deposit").html("<?php echo FormatHelper::currency($lease['Lease']['deposit']); ?>");
$("#invoice-unit").html("<?php echo $unit['name']; ?>");
$("#invoice-customer").html("<?php echo $customer['name']; ?>");
$("#invoice-rent").html("<?php echo FormatHelper::currency($lease['rent']); ?>");
$("#invoice-late").html("<?php echo FormatHelper::currency($defaultLate); ?>");
$("#invoice-deposit").html("<?php echo FormatHelper::currency($lease['deposit']); ?>");
onGridState(null, 'hidden');
<?php else: ?>
onGridState(null, 'visible');

View File

@@ -41,6 +41,12 @@ function onRowSelect(grid_id, item_type, item_id) {
// Get the item name from the grid
$("#move-"+item_type).html($(grid_id).getCell(item_id, cell_name));
// If a unit was selected, update the rent and deposit
if (item_type == 'unit') {
$("#LeaseRent").val($(grid_id).getCell(item_id, 'Unit-rent'));
$("#LeaseDeposit").val($(grid_id).getCell(item_id, 'Unit-deposit'));
}
// Hide the "no customer" message and show the current customer
$("."+item_type+"-selection-invalid").hide();
$("."+item_type+"-selection-valid").show();
@@ -120,6 +126,8 @@ if ($move_type !== 'out') {
array('gridstate' =>
'onGridState("#"+$(this).attr("id"), "unit", gridstate)'),
),
'include' => array('Deposit'),
'exclude' => array('Balance'),
'action' => 'unoccupied',
'nolinks' => true,
'limit' => 10,
@@ -169,7 +177,20 @@ echo $this->element('form_table',
'id' => "LeaseMoveDate"),
'between' => '<A HREF="#" ONCLICK="datepickerNow(\'LeaseMoveDate\', false); return false;">Now</A>',
),
"comment" =>
) +
($move_type === 'in' ? array
("deposit" =>
array('opts' => array
('value' => (!empty($unit)
? FormatHelper::currency($unit['deposit'])
: null))),
"rent" =>
array('opts' => array
('value' => (!empty($unit)
? FormatHelper::currency($unit['rent'])
: null))),
) : array()) + array
("comment" =>
($move_type !== 'out'
? array('opts' => array('size' => 50))
: null),

View File

@@ -18,6 +18,9 @@ security deposits charged.
Customer Selection on the Receipt Page is broken.
(Selecting a row and waiting for the update).
Invoice
- Have some sort of rent-proration tool
Allow waiving a complete charge, even if it already has payments
applied (at the moment, we just can waive the charge balance).