Compare commits
158 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9fea9c79f3 | |||
| 10f71a1fe3 | |||
| 73eacdbcf2 | |||
| 009ea6b44d | |||
| 7ea002850a | |||
| eee3d45c5d | |||
| de93c7545b | |||
| e00e10bbb5 | |||
| 3953e1dbf3 | |||
| 788cbde710 | |||
| 4a064df594 | |||
| c048d44972 | |||
| f6d6659d2a | |||
| 19cee7290f | |||
| 3c067f6586 | |||
| f7bcfef665 | |||
| d06f34de9a | |||
| d5388e7767 | |||
| 5a88f29600 | |||
| 8dd64f60bc | |||
| de2319e93d | |||
| 1fbc452581 | |||
| 65acd0e181 | |||
| f5bb9bac83 | |||
| 45ae013e99 | |||
| 16126b7b6e | |||
| fdd3fe2641 | |||
| c340c25eee | |||
| b8de98917a | |||
| d6c7fbb735 | |||
| 5dd3efa12f | |||
| cb02b9e1e0 | |||
| 212c982851 | |||
| 0aa94b8fe5 | |||
| 76e9b7590f | |||
| af405a44d5 | |||
| 1f9772e926 | |||
| b1a0437117 | |||
| 8db9b90157 | |||
| 33b7d3d67d | |||
| 57c73eafdb | |||
| 30b3185473 | |||
| e9dd1366bc | |||
| 7ee461d993 | |||
| 365b2295af | |||
| dfb0d90246 | |||
| af32d88605 | |||
| c9c06a9fb4 | |||
| c3139220ee | |||
| 68273302cb | |||
| abd45244e1 | |||
| e3b838d62a | |||
| 5fd7483ac1 | |||
| 274ed13644 | |||
| 4537174873 | |||
| 3c5a31aaff | |||
| fd155aaaeb | |||
| 284765e06a | |||
| 352e3487cc | |||
| b02695631e | |||
| b6317d3ee9 | |||
| 2cbd5da8ee | |||
| 960ac108b8 | |||
| 0133c85c01 | |||
| 92d8387e8c | |||
| 67d640b1a0 | |||
| ddf4d5cb29 | |||
| 2143960ce9 | |||
| 06a4a25be8 | |||
| 25677ffa5e | |||
| f06d831329 | |||
| eefc0d7bce | |||
| 046ffba340 | |||
| cf0da7d3c2 | |||
| 95181f4718 | |||
| 447c6a8376 | |||
| 54291b4467 | |||
| 94c78ccb2a | |||
| 323c88a669 | |||
| 3fb680e20f | |||
| cbdd198be5 | |||
| 8cdf061fca | |||
| 5e321888d5 | |||
| d45481b770 | |||
| ff5c7260f8 | |||
| e2f623b7ee | |||
| b47bb9d46e | |||
| 9cf245d030 | |||
| 8bce19d8c4 | |||
| ab766c2dc5 | |||
| 4a53ebd70b | |||
| ce735cad3f | |||
| ef3b5f3022 | |||
| 73ea4fa86c | |||
| 806f732de6 | |||
| b78834f7d6 | |||
| a0274b4d89 | |||
| 970b2ad202 | |||
| e0d9edc4a8 | |||
| ffd1b64580 | |||
| 3dcd83229b | |||
| ebc4a42ae9 | |||
| f08884f326 | |||
| e740cc859b | |||
| f12a95f3b9 | |||
| 677458e942 | |||
| ce24abc812 | |||
| 1ead830ad6 | |||
| 0848ab5055 | |||
| 52c72b08b2 | |||
| fc71c058fb | |||
| dd5402d2f1 | |||
| f473a91870 | |||
| cdd274adf7 | |||
| 8ea0822ed1 | |||
| 492e70b2f6 | |||
| abff728a37 | |||
| b8c4257f95 | |||
| 5f715cc076 | |||
| f40dc205f9 | |||
| feaabd29d9 | |||
| f48e7d8907 | |||
| 991b5a3317 | |||
| 68585a0b30 | |||
| a9a570d666 | |||
| 15c4b96a2a | |||
| ce252f2e70 | |||
| 4b857ff11f | |||
| 6661d26c76 | |||
| b409bf09d1 | |||
| b488054106 | |||
| 59398cb3f0 | |||
| 1145d293b2 | |||
| 2feb7f60a4 | |||
| bd6cc37d4a | |||
| 8dae1ccf84 | |||
| 50449205b4 | |||
| 77c038e880 | |||
| 44bdb384f5 | |||
| 2b135b0e66 | |||
| 23ec1b6b20 | |||
| 8f4f3c054e | |||
| 1249854514 | |||
| 7805e4d229 | |||
| 54c7287ee4 | |||
| bcec2a9891 | |||
| e772ff8755 | |||
| 3288969b0d | |||
| d268b6fe7e | |||
| e9b31d964c | |||
| 47d362750e | |||
| 47af64aefe | |||
| 1ca704157b | |||
| 8a3be97d41 | |||
| 05a4ee38f0 | |||
| 0e68fea04b | |||
| a9f47d73ba | |||
| 5b5e478bd0 |
@@ -35,7 +35,7 @@
|
|||||||
* @subpackage cake.app
|
* @subpackage cake.app
|
||||||
*/
|
*/
|
||||||
class AppController extends Controller {
|
class AppController extends Controller {
|
||||||
var $helpers = array('Html', 'Form', 'Javascript', 'Format', 'Time', 'Grid');
|
var $helpers = array('Html', 'Form', 'Javascript', 'Format', 'Time');
|
||||||
var $components = array('DebugKit.Toolbar');
|
var $components = array('DebugKit.Toolbar');
|
||||||
|
|
||||||
function sideMenuLinks() {
|
function sideMenuLinks() {
|
||||||
@@ -45,12 +45,9 @@ class AppController extends Controller {
|
|||||||
array('name' => 'Units', 'url' => array('controller' => 'units', 'action' => 'index')),
|
array('name' => 'Units', 'url' => array('controller' => 'units', 'action' => 'index')),
|
||||||
array('name' => 'Leases', 'url' => array('controller' => 'leases', 'action' => 'index')),
|
array('name' => 'Leases', 'url' => array('controller' => 'leases', 'action' => 'index')),
|
||||||
array('name' => 'Customers', 'url' => array('controller' => 'customers', 'action' => 'index')),
|
array('name' => 'Customers', 'url' => array('controller' => 'customers', 'action' => 'index')),
|
||||||
array('name' => 'Accounts', 'url' => array('controller' => 'accounts', 'action' => 'index')),
|
|
||||||
array('name' => 'Debug', 'header' => true),
|
|
||||||
array('name' => 'Contacts', 'url' => array('controller' => 'contacts', 'action' => 'index')),
|
array('name' => 'Contacts', 'url' => array('controller' => 'contacts', 'action' => 'index')),
|
||||||
|
array('name' => 'Accounts', 'url' => array('controller' => 'accounts', 'action' => 'index')),
|
||||||
array('name' => 'Ledgers', 'url' => array('controller' => 'ledgers', 'action' => 'index')),
|
array('name' => 'Ledgers', 'url' => array('controller' => 'ledgers', 'action' => 'index')),
|
||||||
array('name' => 'New Ledgers', 'url' => array('controller' => 'accounts', 'action' => 'newledger')),
|
|
||||||
array('name' => 'RESET DATA', 'url' => array('controller' => 'accounts', 'action' => 'reset_data')),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,28 +55,6 @@ class AppController extends Controller {
|
|||||||
$this->set('sidemenu', $this->sideMenuLinks());
|
$this->set('sidemenu', $this->sideMenuLinks());
|
||||||
}
|
}
|
||||||
|
|
||||||
function reset_data() {
|
|
||||||
$this->layout = null;
|
|
||||||
$this->autoLayout = false;
|
|
||||||
$this->autoRender = false;
|
|
||||||
Configure::write('debug', '0');
|
|
||||||
$script = $_SERVER['DOCUMENT_ROOT'] . '/pmgr/build.cmd';
|
|
||||||
echo "<P>" . date('r') . "\n";
|
|
||||||
//echo "<P>Script: $script" . "\n";
|
|
||||||
$db = & $this->Account->getDataSource();
|
|
||||||
$script .= ' "' . $db->config['database'] . '"';
|
|
||||||
$script .= ' "' . $db->config['login'] . '"';
|
|
||||||
$script .= ' "' . $db->config['password'] . '"';
|
|
||||||
$handle = popen($script . ' 2>&1', 'r');
|
|
||||||
//echo "<P>Handle: $handle; " . gettype($handle) . "\n";
|
|
||||||
echo "<P><PRE>\n";
|
|
||||||
while (($read = fread($handle, 2096))) {
|
|
||||||
echo $read;
|
|
||||||
}
|
|
||||||
echo "</PRE>\n";
|
|
||||||
pclose($handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -88,12 +63,12 @@ class AppController extends Controller {
|
|||||||
* - called by function to create an index listing
|
* - called by function to create an index listing
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function jqGridView($title, $action = null, $element = null) {
|
function jqGridView($title, $action = null) {
|
||||||
$this->set('title', $title);
|
$this->set('title', $title);
|
||||||
// The resulting page will contain a jqGrid, which will
|
// The resulting page will contain a jqGrid, which will
|
||||||
// use ajax to obtain the actual data for this action
|
// use ajax to obtain the actual data for this action
|
||||||
$this->set('action', $action ? $action : $this->params['action']);
|
$this->set('action', $action ? $action : $this->params['action']);
|
||||||
$this->render('/elements/' . ($element ? $element : $this->params['controller']));
|
$this->render('/elements/' . $this->params['controller']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
@@ -118,11 +93,7 @@ class AppController extends Controller {
|
|||||||
// Establish the basic query and conditions
|
// Establish the basic query and conditions
|
||||||
$query = array_intersect_key($this->jqGridDataCountTables($params, $model),
|
$query = array_intersect_key($this->jqGridDataCountTables($params, $model),
|
||||||
array('link'=>1, 'contain'=>1));
|
array('link'=>1, 'contain'=>1));
|
||||||
$query['conditions'] = $this->jqGridDataCountConditions($params, $model);
|
$query['conditions'] = $this->jqGridDataConditions($params, $model);
|
||||||
$query['group'] = $this->jqGridDataCountGroup($params, $model);
|
|
||||||
|
|
||||||
// DEBUG PURPOSES ONLY!
|
|
||||||
$params['count_query'] = $query;
|
|
||||||
|
|
||||||
// Get the number of records prior to pagination
|
// Get the number of records prior to pagination
|
||||||
$count = $this->jqGridDataRecordCount($params, $model, $query);
|
$count = $this->jqGridDataRecordCount($params, $model, $query);
|
||||||
@@ -148,15 +119,15 @@ class AppController extends Controller {
|
|||||||
$query['fields'] = $this->jqGridDataFields($params, $model);
|
$query['fields'] = $this->jqGridDataFields($params, $model);
|
||||||
$results = $this->jqGridDataRecords($params, $model, $query);
|
$results = $this->jqGridDataRecords($params, $model, $query);
|
||||||
|
|
||||||
// DEBUG PURPOSES ONLY!
|
|
||||||
$params['query'] = $query;
|
|
||||||
|
|
||||||
// Post process the records
|
// Post process the records
|
||||||
$this->jqGridRecordsPostProcess($params, $model, $results);
|
$this->jqGridRecordsPostProcess($params, $model, $results);
|
||||||
|
|
||||||
// Add in any needed hyperlinks
|
// Add in any needed hyperlinks
|
||||||
$this->jqGridRecordLinks($params, $model, $results, array());
|
$this->jqGridRecordLinks($params, $model, $results, array());
|
||||||
|
|
||||||
|
// DEBUG PURPOSES ONLY!
|
||||||
|
$params['query'] = $query;
|
||||||
|
|
||||||
// Finally, dump out the data
|
// Finally, dump out the data
|
||||||
$this->jqGridDataOutputHeader($params, $model);
|
$this->jqGridDataOutputHeader($params, $model);
|
||||||
echo "<?xml version='1.0' encoding='utf-8'?>\n";
|
echo "<?xml version='1.0' encoding='utf-8'?>\n";
|
||||||
@@ -235,10 +206,6 @@ class AppController extends Controller {
|
|||||||
return array('contain' => false);
|
return array('contain' => false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function jqGridDataCountConditions(&$params, &$model) {
|
|
||||||
return $this->jqGridDataConditions($params, $model);
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataConditions(&$params, &$model) {
|
function jqGridDataConditions(&$params, &$model) {
|
||||||
$searches = array();
|
$searches = array();
|
||||||
|
|
||||||
@@ -294,10 +261,6 @@ class AppController extends Controller {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function jqGridDataCountGroup(&$params, &$model) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataGroup(&$params, &$model) {
|
function jqGridDataGroup(&$params, &$model) {
|
||||||
return $model->alias.'.'.$model->primaryKey;
|
return $model->alias.'.'.$model->primaryKey;
|
||||||
}
|
}
|
||||||
@@ -322,14 +285,6 @@ class AppController extends Controller {
|
|||||||
$model_alias = $model->alias;
|
$model_alias = $model->alias;
|
||||||
$id = $model->primaryKey;
|
$id = $model->primaryKey;
|
||||||
|
|
||||||
$subtotals = array();
|
|
||||||
foreach ($params['fields'] AS $field) {
|
|
||||||
if (preg_match('/subtotal-(.*)$/', $field, $matches))
|
|
||||||
$subtotals[] = array('field' => $matches[1],
|
|
||||||
'name' => $field,
|
|
||||||
'amount' => 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($records AS &$record) {
|
foreach ($records AS &$record) {
|
||||||
$record['jqGrid_id'] = $record[$model_alias][$id];
|
$record['jqGrid_id'] = $record[$model_alias][$id];
|
||||||
// Add the calculated fields (if any), to the model fields
|
// Add the calculated fields (if any), to the model fields
|
||||||
@@ -337,19 +292,6 @@ class AppController extends Controller {
|
|||||||
$record[$model_alias] += $record[0];
|
$record[$model_alias] += $record[0];
|
||||||
unset($record[0]);
|
unset($record[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($subtotals AS &$subtotal) {
|
|
||||||
$field = $subtotal['field'];
|
|
||||||
if (preg_match("/\./", $field)) {
|
|
||||||
list($tbl, $col) = explode(".", $field);
|
|
||||||
$record['subtotal-'.$tbl][$col] =
|
|
||||||
($subtotal['amount'] += $record[$tbl][$col]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$record[$model->alias]['subtotal-'.$field] =
|
|
||||||
($subtotal['amount'] += $record[$model->alias][$field]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEBUG PURPOSES ONLY!
|
// DEBUG PURPOSES ONLY!
|
||||||
@@ -357,10 +299,6 @@ class AppController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function jqGridRecordLinks(&$params, &$model, &$records, $links) {
|
function jqGridRecordLinks(&$params, &$model, &$records, $links) {
|
||||||
// Don't create any links if ordered not to.
|
|
||||||
if (isset($params['nolinks']))
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach ($links AS $table => $fields) {
|
foreach ($links AS $table => $fields) {
|
||||||
$special = array('controller', 'id');
|
$special = array('controller', 'id');
|
||||||
$controller = Inflector::pluralize(Inflector::underscore($table));
|
$controller = Inflector::pluralize(Inflector::underscore($table));
|
||||||
@@ -403,11 +341,6 @@ class AppController extends Controller {
|
|||||||
echo " <page>$page</page>\n";
|
echo " <page>$page</page>\n";
|
||||||
echo " <total>$total</total>\n";
|
echo " <total>$total</total>\n";
|
||||||
echo " <records>$records</records>\n";
|
echo " <records>$records</records>\n";
|
||||||
|
|
||||||
if (isset($params['userdata'])) {
|
|
||||||
foreach ($params['userdata'] AS $field => $value)
|
|
||||||
echo ' <userdata name="'.$field.'">' . "{$value}</userdata>\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function jqGridDataOutputRecords(&$params, &$model, &$records) {
|
function jqGridDataOutputRecords(&$params, &$model, &$records) {
|
||||||
@@ -39,8 +39,6 @@
|
|||||||
class AppModel extends Model {
|
class AppModel extends Model {
|
||||||
|
|
||||||
var $actsAs = array('Containable', 'Linkable');
|
var $actsAs = array('Containable', 'Linkable');
|
||||||
var $useNullForEmpty = true;
|
|
||||||
var $formatDateFields = true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Enum Values
|
* Get Enum Values
|
||||||
@@ -49,15 +47,13 @@ class AppModel extends Model {
|
|||||||
*
|
*
|
||||||
* Gets the enum values for MySQL 4 and 5 to use in selectTag()
|
* Gets the enum values for MySQL 4 and 5 to use in selectTag()
|
||||||
*/
|
*/
|
||||||
function getEnumValues($columnName=null, $tableName=null)
|
function getEnumValues($columnName=null, $respectDefault=false)
|
||||||
{
|
{
|
||||||
if ($columnName==null) { return array(); } //no field specified
|
if ($columnName==null) { return array(); } //no field specified
|
||||||
|
|
||||||
if (!isset($tableName)) {
|
|
||||||
//Get the name of the table
|
//Get the name of the table
|
||||||
$db =& ConnectionManager::getDataSource($this->useDbConfig);
|
$db =& ConnectionManager::getDataSource($this->useDbConfig);
|
||||||
$tableName = $db->fullTableName($this, false);
|
$tableName = $db->fullTableName($this, false);
|
||||||
}
|
|
||||||
|
|
||||||
//Get the values for the specified column (database and version specific, needs testing)
|
//Get the values for the specified column (database and version specific, needs testing)
|
||||||
$result = $this->query("SHOW COLUMNS FROM {$tableName} LIKE '{$columnName}'");
|
$result = $this->query("SHOW COLUMNS FROM {$tableName} LIKE '{$columnName}'");
|
||||||
@@ -76,33 +72,12 @@ class AppModel extends Model {
|
|||||||
|
|
||||||
//Get the values
|
//Get the values
|
||||||
return array_flip(array_merge(array(''), // MySQL sets 0 to be the empty string
|
return array_flip(array_merge(array(''), // MySQL sets 0 to be the empty string
|
||||||
explode("','", strtoupper(preg_replace("/(enum)\('(.+?)'\)/","\\2", $types)))
|
explode("','", preg_replace("/(enum)\('(.+?)'\)/","\\2", $types))
|
||||||
));
|
));
|
||||||
} //end getEnumValues
|
} //end getEnumValues
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: nameToID
|
|
||||||
* - Returns the ID of the named item
|
|
||||||
*/
|
|
||||||
function nameToID($name) {
|
|
||||||
$this->cacheQueries = true;
|
|
||||||
$item = $this->find('first', array
|
|
||||||
('recursive' => -1,
|
|
||||||
'conditions' => compact('name'),
|
|
||||||
));
|
|
||||||
$this->cacheQueries = false;
|
|
||||||
if ($item) {
|
|
||||||
$item = current($item);
|
|
||||||
return $item['id'];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -136,60 +111,6 @@ class AppModel extends Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function recursive_array_replace($find, $replace, &$data) {
|
|
||||||
if (!isset($data))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (is_array($data)) {
|
|
||||||
foreach ($data as $key => &$value) {
|
|
||||||
$this->recursive_array_replace($find, $replace, $value);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($replace))
|
|
||||||
$data = preg_replace($find, $replace, $data);
|
|
||||||
elseif (preg_match($find, $data))
|
|
||||||
$data = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function beforeSave() {
|
|
||||||
/* pr(array('class' => $this->name, */
|
|
||||||
/* 'alias' => $this->alias, */
|
|
||||||
/* 'function' => 'AppModel::beforeSave')); */
|
|
||||||
|
|
||||||
// Replace all empty strings with NULL.
|
|
||||||
// If a particular model doesn't like this, they'll have to
|
|
||||||
// override the behavior, or set useNullForEmpty to false.
|
|
||||||
if ($this->useNullForEmpty)
|
|
||||||
$this->recursive_array_replace("/^\s*$/", null, $this->data);
|
|
||||||
|
|
||||||
if ($this->formatDateFields) {
|
|
||||||
$alias = $this->alias;
|
|
||||||
|
|
||||||
foreach ($this->_schema AS $field => $info) {
|
|
||||||
if ($info['type'] == 'date' || $info['type'] == 'timestamp') {
|
|
||||||
if (isset($this->data[$alias][$field])) {
|
|
||||||
/* pr("Fix Date for '$alias'.'$field'; current value = " . */
|
|
||||||
/* "'{$this->data[$alias][$field]}'"); */
|
|
||||||
if ($this->data[$alias][$field] === 'CURRENT_TIMESTAMP')
|
|
||||||
// Seems CakePHP is broken for the default timestamp.
|
|
||||||
// It tries to automagically set the value to CURRENT_TIMESTAMP
|
|
||||||
// which is wholly rejected by MySQL. Just put it back to NULL
|
|
||||||
// and let the SQL engine deal with the defaults... it's not
|
|
||||||
// Cake's place to do this anyway :-/
|
|
||||||
$this->data[$alias][$field] = null;
|
|
||||||
else
|
|
||||||
$this->data[$alias][$field] =
|
|
||||||
$this->dateFormatBeforeSave($this->data[$alias][$field]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -198,15 +119,6 @@ class AppModel extends Model {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function dateFormatBeforeSave($dateString) {
|
function dateFormatBeforeSave($dateString) {
|
||||||
/* $time = ''; */
|
|
||||||
/* if (preg_match('/(\d+(:\d+))/', $dateString, $match)) */
|
|
||||||
/* $time = ' '.$match[1]; */
|
|
||||||
/* $dateString = preg_replace('/(\d+(:\d+))/', '', $dateString); */
|
|
||||||
/* return date('Y-m-d', strtotime($dateString)) . $time; */
|
|
||||||
|
|
||||||
if (preg_match('/:/', $dateString))
|
|
||||||
return date('Y-m-d H:i:s', strtotime($dateString));
|
|
||||||
else
|
|
||||||
return date('Y-m-d', strtotime($dateString));
|
return date('Y-m-d', strtotime($dateString));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
@echo off
|
|
||||||
%~dp0\scripts\sitelink2pmgr.pl %~dp0\db\schema.sql %~dp0db\vss.mdb %*
|
|
||||||
echo Done!
|
|
||||||
@@ -26,12 +26,14 @@
|
|||||||
* @lastmodified $Date: 2008-12-18 18:16:01 -0800 (Thu, 18 Dec 2008) $
|
* @lastmodified $Date: 2008-12-18 18:16:01 -0800 (Thu, 18 Dec 2008) $
|
||||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Here, we are connecting '/' (base path) to our site map.
|
* Here, we are connecting '/' (base path) to controller called 'Pages',
|
||||||
* It's hardcoded to map #1, but at some point we'll implement
|
* its action called 'display', and we pass a param to select the view file
|
||||||
* a login mechanism and the default path will be to log on instead.
|
* to use (in this case, /app/views/pages/home.ctp)...
|
||||||
*/
|
*/
|
||||||
Router::connect('/', array('controller' => 'maps', 'action' => 'view', '1'));
|
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
|
||||||
|
/**
|
||||||
|
* ...and connect the rest of 'Pages' controller's urls.
|
||||||
|
*/
|
||||||
|
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
|
||||||
?>
|
?>
|
||||||
@@ -12,7 +12,6 @@ class AccountsController extends AppController {
|
|||||||
array('name' => 'Equity', 'url' => array('controller' => 'accounts', 'action' => 'equity')),
|
array('name' => 'Equity', 'url' => array('controller' => 'accounts', 'action' => 'equity')),
|
||||||
array('name' => 'Income', 'url' => array('controller' => 'accounts', 'action' => 'income')),
|
array('name' => 'Income', 'url' => array('controller' => 'accounts', 'action' => 'income')),
|
||||||
array('name' => 'Expense', 'url' => array('controller' => 'accounts', 'action' => 'expense')),
|
array('name' => 'Expense', 'url' => array('controller' => 'accounts', 'action' => 'expense')),
|
||||||
array('name' => 'Bank Deposit', 'url' => array('controller' => 'accounts', 'action' => 'deposit')),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@@ -120,126 +119,6 @@ class AccountsController extends AppController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: newledger
|
|
||||||
* - Close the current account ledger and create a new one,
|
|
||||||
* carrying forward any balance if necessary.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function newledger($id = null) {
|
|
||||||
if (!$this->Account->closeCurrentLedger($id)) {
|
|
||||||
$this->Session->setFlash(__('Unable to create new Ledger.', true));
|
|
||||||
}
|
|
||||||
if ($id)
|
|
||||||
$this->redirect(array('action'=>'view', $id));
|
|
||||||
else
|
|
||||||
$this->redirect(array('action'=>'index'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: collected
|
|
||||||
* - Displays the items actually collected for the period
|
|
||||||
* e.g. How much was collected in rent from 4/1/09 - 5/1/09
|
|
||||||
*/
|
|
||||||
function collected($id = null) {
|
|
||||||
if (!$id) {
|
|
||||||
$this->Session->setFlash(__('Invalid Item.', true));
|
|
||||||
$this->redirect(array('action'=>'index'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$payment_accounts = $this->Account->collectableAccounts();
|
|
||||||
//$payment_accounts[$this->Account->nameToID('Bank')] = 'Bank';
|
|
||||||
$default_accounts = array_diff_key($payment_accounts,
|
|
||||||
array($this->Account->concessionAccountID() => 1));
|
|
||||||
$this->set(compact('payment_accounts', 'default_accounts'));
|
|
||||||
|
|
||||||
$this->Account->recursive = -1;
|
|
||||||
$account = $this->Account->read(null, $id);
|
|
||||||
$account = $account['Account'];
|
|
||||||
|
|
||||||
$title = ($account['name'] . ': Collected Report');
|
|
||||||
$this->set(compact('account', 'title'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: deposit
|
|
||||||
* - Prepares the books for a bank deposit
|
|
||||||
*/
|
|
||||||
function deposit() {
|
|
||||||
if ($this->data) {
|
|
||||||
// Action the close based on provided data
|
|
||||||
//pr($this->data);
|
|
||||||
|
|
||||||
// Get data about each closed ledger.
|
|
||||||
$deposit = array('total' => 0, 'ledgers' => array());
|
|
||||||
foreach ($this->data['Tillable']['Ledger'] AS $ledger_id => $ledger) {
|
|
||||||
if (!$ledger['checked'])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
$ledger_entries =
|
|
||||||
$this->Account->Ledger->find
|
|
||||||
('all',
|
|
||||||
array('link' => array
|
|
||||||
('Account' =>
|
|
||||||
array('fields' => array('name')),
|
|
||||||
|
|
||||||
'LedgerEntry' =>
|
|
||||||
array('fields' => array('id', 'amount'),
|
|
||||||
|
|
||||||
'MonetarySource' =>
|
|
||||||
array('fields' => array('name')),
|
|
||||||
|
|
||||||
'Customer' =>
|
|
||||||
array('fields' => array('name')),
|
|
||||||
|
|
||||||
//'Transaction' =>
|
|
||||||
//array('fields' => array('stamp')),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'fields' => false,
|
|
||||||
'conditions' => array(array('Ledger.id' => $ledger_id),
|
|
||||||
array('LedgerEntry.id IS NOT NULL'),
|
|
||||||
),
|
|
||||||
));
|
|
||||||
|
|
||||||
$deposit['total'] += $ledger['amount'];
|
|
||||||
$deposit['ledgers'][] = array('id' => $ledger_id,
|
|
||||||
'name' => $ledger['account_name'],
|
|
||||||
'total' => $ledger['amount'],
|
|
||||||
'entries' => $ledger_entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform the accounting work necessary to close the
|
|
||||||
// monetary ledgers and deposit into the bank account.
|
|
||||||
$this->Account->closeAndDeposit($deposit['ledgers'], $this->data['Deposit']['Account']['id']);
|
|
||||||
|
|
||||||
$title = 'Account: Deposit Slip';
|
|
||||||
$this->set(compact('title', 'deposit'));
|
|
||||||
$this->render('deposit_slip');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare a close page...
|
|
||||||
$tillable_account = $this->Account->relatedAccounts('tillable');
|
|
||||||
$depositable_account = $this->Account->relatedAccounts('depositable');
|
|
||||||
|
|
||||||
foreach ($tillable_account AS &$acct) {
|
|
||||||
$acct['Account']['stats'] = $this->Account->stats($acct['Account']['id']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$title = 'Account: Prepare Deposit';
|
|
||||||
$this->set(compact('title', 'tillable_account', 'depositable_account'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -262,8 +141,7 @@ class AccountsController extends AppController {
|
|||||||
array('fields' => array('id', 'sequence')),
|
array('fields' => array('id', 'sequence')),
|
||||||
|
|
||||||
'Ledger' =>
|
'Ledger' =>
|
||||||
array('Close' => array
|
array('order' => array('Ledger.open_stamp' => 'DESC')),
|
||||||
('order' => array('Close.stamp' => 'DESC'))),
|
|
||||||
),
|
),
|
||||||
'conditions' => array(array('Account.id' => $id)),
|
'conditions' => array(array('Account.id' => $id)),
|
||||||
)
|
)
|
||||||
@@ -282,16 +160,8 @@ class AccountsController extends AppController {
|
|||||||
$stats = $this->Account->stats($id, true);
|
$stats = $this->Account->stats($id, true);
|
||||||
$stats = $stats['Ledger'];
|
$stats = $stats['Ledger'];
|
||||||
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Operations', 'header' => true);
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'New Ledger', 'url' => array('action' => 'newledger', $id));
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Collected', 'url' => array('action' => 'collected', $id));
|
|
||||||
|
|
||||||
// Prepare to render
|
// Prepare to render
|
||||||
$title = 'Account: ' . $account['Account']['name'];
|
$title = 'Account: ' . $account['Account']['name'];
|
||||||
$this->set(compact('account', 'title', 'stats'));
|
$this->set(compact('account', 'title', 'stats'));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class ContactsController extends AppController {
|
||||||
|
|
||||||
|
var $sidemenu_links = array();
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* override: sideMenuLinks
|
||||||
|
* - Generates controller specific links for the side menu
|
||||||
|
*/
|
||||||
|
function sideMenuLinks() {
|
||||||
|
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: index / all
|
||||||
|
* - Generate a listing of contacts
|
||||||
|
*/
|
||||||
|
|
||||||
|
function index() { $this->all(); }
|
||||||
|
function all() { $this->jqGridView('All Contacts', 'all'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtuals: jqGridData
|
||||||
|
* - With the application controller handling the jqGridData action,
|
||||||
|
* these virtual functions ensure that the correct data is passed
|
||||||
|
* to jqGrid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function jqGridDataOrder(&$params, &$model, $index, $direction) {
|
||||||
|
$order = parent::jqGridDataOrder($params, $model, $index, $direction);
|
||||||
|
if ($index === 'Contact.last_name') {
|
||||||
|
$order[] = 'Contact.first_name ' . $direction;
|
||||||
|
}
|
||||||
|
if ($index === 'Contact.first_name') {
|
||||||
|
$order[] = 'Contact.last_name ' . $direction;
|
||||||
|
}
|
||||||
|
return $order;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: view
|
||||||
|
* - Displays information about a specific contact
|
||||||
|
*/
|
||||||
|
|
||||||
|
function view($id = null) {
|
||||||
|
if (!$id) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$contact = $this->Contact->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array
|
||||||
|
(// Models
|
||||||
|
'ContactPhone',
|
||||||
|
'ContactEmail',
|
||||||
|
'ContactAddress',
|
||||||
|
'Customer'),
|
||||||
|
|
||||||
|
'conditions' => array('Contact.id' => $id),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = $contact['Contact']['display_name'];
|
||||||
|
$this->set(compact('contact', 'title'));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,250 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class CustomersController extends AppController {
|
||||||
|
var $sidemenu_links =
|
||||||
|
array(array('name' => 'Tenants', 'header' => true),
|
||||||
|
array('name' => 'Current', 'url' => array('controller' => 'customers', 'action' => 'current')),
|
||||||
|
array('name' => 'Past', 'url' => array('controller' => 'customers', 'action' => 'past')),
|
||||||
|
array('name' => 'All', 'url' => array('controller' => 'customers', 'action' => 'all')),
|
||||||
|
);
|
||||||
|
|
||||||
|
//var $components = array('RequestHandler');
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* override: sideMenuLinks
|
||||||
|
* - Generates controller specific links for the side menu
|
||||||
|
*/
|
||||||
|
function sideMenuLinks() {
|
||||||
|
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: index / current / past / all
|
||||||
|
* - Creates a list of tenants
|
||||||
|
*/
|
||||||
|
|
||||||
|
function index() { $this->current(); }
|
||||||
|
function current() { $this->jqGridView('Current Tenants'); }
|
||||||
|
function past() { $this->jqGridView('Past Tenants'); }
|
||||||
|
function all() { $this->jqGridView('All Tenants', 'all'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtuals: jqGridData
|
||||||
|
* - With the application controller handling the jqGridData action,
|
||||||
|
* these virtual functions ensure that the correct data is passed
|
||||||
|
* to jqGrid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function jqGridDataSetup(&$params) {
|
||||||
|
parent::jqGridDataSetup($params);
|
||||||
|
if (!isset($params['action']))
|
||||||
|
$params['action'] = 'all';
|
||||||
|
}
|
||||||
|
|
||||||
|
function jqGridDataTables(&$params, &$model) {
|
||||||
|
return array
|
||||||
|
('link' =>
|
||||||
|
array(// Models
|
||||||
|
'PrimaryContact',
|
||||||
|
'CurrentLease' => array('fields' => array()),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function jqGridDataFields(&$params, &$model) {
|
||||||
|
return array('Customer.*',
|
||||||
|
'COUNT(CurrentLease.id) AS lease_count');
|
||||||
|
}
|
||||||
|
|
||||||
|
function jqGridDataConditions(&$params, &$model) {
|
||||||
|
$conditions = parent::jqGridDataConditions($params, $model);
|
||||||
|
|
||||||
|
if ($params['action'] === 'current') {
|
||||||
|
$conditions[] = 'CurrentLease.id IS NOT NULL';
|
||||||
|
}
|
||||||
|
elseif ($params['action'] === 'past') {
|
||||||
|
$conditions[] = 'CurrentLease.id IS NULL';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function jqGridDataOrder(&$params, &$model, $index, $direction) {
|
||||||
|
$order = parent::jqGridDataOrder($params, $model, $index, $direction);
|
||||||
|
if ($index === 'PrimaryContact.last_name') {
|
||||||
|
$order[] = 'PrimaryContact.first_name ' . $direction;
|
||||||
|
}
|
||||||
|
if ($index === 'PrimaryContact.first_name') {
|
||||||
|
$order[] = 'PrimaryContact.last_name ' . $direction;
|
||||||
|
}
|
||||||
|
return $order;
|
||||||
|
}
|
||||||
|
|
||||||
|
function jqGridDataRecordCount(&$params, &$model, $query) {
|
||||||
|
|
||||||
|
// We don't have a good way to use the query to obtain
|
||||||
|
// our count. The problem is that we're relying on the
|
||||||
|
// group by for the query, which will destroy the count,
|
||||||
|
// whether we omit the group by or leave it in.
|
||||||
|
// So, build a fresh query for counting.
|
||||||
|
|
||||||
|
$query['conditions'] = parent::jqGridDataConditions($params, $model);
|
||||||
|
|
||||||
|
$count = $model->find('count',
|
||||||
|
array_merge(array('link' => array_diff_key($query['link'],
|
||||||
|
array('CurrentLease'=>1))),
|
||||||
|
array_diff_key($query, array('link'=>1))));
|
||||||
|
|
||||||
|
if ($params['action'] === 'all')
|
||||||
|
return $count;
|
||||||
|
|
||||||
|
$query['conditions'][] = 'CurrentLease.id IS NULL';
|
||||||
|
$count_past = $model->find('count', $query);
|
||||||
|
|
||||||
|
// Since we can't easily count 'current' directly, we
|
||||||
|
// can quickly derive it since 'current' customers
|
||||||
|
// are mutually exclusive to 'past' customers.
|
||||||
|
if ($params['action'] == 'current')
|
||||||
|
$count = $count - $count_past;
|
||||||
|
elseif ($params['action'] == 'past') {
|
||||||
|
$count = $count_past;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $count;
|
||||||
|
}
|
||||||
|
|
||||||
|
function jqGridDataRecords(&$params, &$model, $query) {
|
||||||
|
$customers = parent::jqGridDataRecords($params, $model, $query);
|
||||||
|
|
||||||
|
// Get the balance on each customer.
|
||||||
|
foreach ($customers AS &$customer) {
|
||||||
|
$stats = $this->Customer->stats($customer['Customer']['id']);
|
||||||
|
$customer['Customer']['balance'] = $stats['balance'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $customers;
|
||||||
|
}
|
||||||
|
|
||||||
|
function jqGridRecordLinks(&$params, &$model, &$records, $links) {
|
||||||
|
$links['Customer'] = array('name');
|
||||||
|
return parent::jqGridRecordLinks($params, $model, $records, $links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: view
|
||||||
|
* - Displays information about a specific customer
|
||||||
|
*/
|
||||||
|
|
||||||
|
function view($id = null) {
|
||||||
|
if (!$id) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$customer = $this->Customer->details($id);
|
||||||
|
|
||||||
|
$outstanding_balance = $customer['stats']['balance'];
|
||||||
|
$outstanding_deposit = $customer['deposits']['summary']['balance'];
|
||||||
|
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Operations', 'header' => true);
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Payment', 'url' => array('action' => 'payment', $id));
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Move-Out', 'url' => array('controller' => 'units', 'action' => 'move-out'));
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = $customer['Customer']['name'];
|
||||||
|
$this->set(compact('customer', 'title',
|
||||||
|
'outstanding_balance',
|
||||||
|
'outstanding_deposit'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: payment
|
||||||
|
* - Sets up the payment entry page for the given customer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function payment($id = null) {
|
||||||
|
/* if (!$id) { */
|
||||||
|
/* $this->Session->setFlash(__('Invalid Item.', true)); */
|
||||||
|
/* $this->redirect(array('action'=>'index')); */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
/* if ($this->RequestHandler->isPost()) { */
|
||||||
|
/* pr($this->data); */
|
||||||
|
/* //$this->redirect(array('action'=>'index')); */
|
||||||
|
/* $customer = $this->data; */
|
||||||
|
/* } */
|
||||||
|
if (isset($id)) {
|
||||||
|
$this->Customer->recursive = -1;
|
||||||
|
$customer = $this->Customer->read(null, $id);
|
||||||
|
$customer = $customer['Customer'];
|
||||||
|
$unreconciled = $this->Customer->findUnreconciledLedgerEntries($id);
|
||||||
|
$charges = $unreconciled['debit'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$customer = null;
|
||||||
|
$charges = array('balance' => 0, 'entry' => array());
|
||||||
|
}
|
||||||
|
|
||||||
|
$title = 'Payment Entry';
|
||||||
|
$this->set(compact('customer', 'charges', 'title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: unreconciledEntries
|
||||||
|
* - returns the list of unreconciled entries
|
||||||
|
*/
|
||||||
|
|
||||||
|
function unreconciled($id) {
|
||||||
|
|
||||||
|
//$this->layout = 'ajax';
|
||||||
|
$this->layout = null;
|
||||||
|
$this->autoLayout = false;
|
||||||
|
$this->autoRender = false;
|
||||||
|
Configure::write('debug', '0');
|
||||||
|
header("Content-type: text/xml;charset=utf-8");
|
||||||
|
|
||||||
|
App::import('Helper', 'Xml');
|
||||||
|
$xml = new XmlHelper();
|
||||||
|
|
||||||
|
// Find the unreconciled entries, then manipulate the structure
|
||||||
|
// slightly to accomodate the format necessary for XML Helper.
|
||||||
|
$unreconciled = $this->Customer->findUnreconciledLedgerEntries($id);
|
||||||
|
$unreconciled = array('entries' =>
|
||||||
|
array_intersect_key($unreconciled['debit'],
|
||||||
|
array('entry'=>1, 'balance'=>1)));
|
||||||
|
|
||||||
|
// XML Helper will dump an empty tag if the array is empty
|
||||||
|
if (!count($unreconciled['entries']['entry']))
|
||||||
|
unset($unreconciled['entries']['entry']);
|
||||||
|
|
||||||
|
pr($unreconciled);
|
||||||
|
//$reconciled = $cust->reconcileNewLedgerEntry($cust_id, 'credit', $amount);
|
||||||
|
|
||||||
|
$opts = array();
|
||||||
|
//$opts['format'] = 'tags';
|
||||||
|
echo $xml->header();
|
||||||
|
echo $xml->serialize($unreconciled, $opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
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')),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* override: sideMenuLinks
|
||||||
|
* - Generates controller specific links for the side menu
|
||||||
|
*/
|
||||||
|
function sideMenuLinks() {
|
||||||
|
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: index / active / closed / all
|
||||||
|
* - Generate a listing of leases
|
||||||
|
*/
|
||||||
|
|
||||||
|
function index() { $this->all(); }
|
||||||
|
function active() { $this->jqGridView('Active Leases'); }
|
||||||
|
function closed() { $this->jqGridView('Closed Leases'); }
|
||||||
|
function all() { $this->jqGridView('All Leases', 'all'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtuals: jqGridData
|
||||||
|
* - With the application controller handling the jqGridData action,
|
||||||
|
* these virtual functions ensure that the correct data is passed
|
||||||
|
* to jqGrid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function jqGridDataSetup(&$params) {
|
||||||
|
parent::jqGridDataSetup($params);
|
||||||
|
if (!isset($params['action']))
|
||||||
|
$params['action'] = 'all';
|
||||||
|
}
|
||||||
|
|
||||||
|
function jqGridDataTables(&$params, &$model) {
|
||||||
|
return array
|
||||||
|
('link' => array('Unit' => array('fields' => array('Unit.id', 'Unit.name')),
|
||||||
|
'Customer' => array('fields' => array('Customer.id', 'Customer.name'))));
|
||||||
|
}
|
||||||
|
|
||||||
|
function jqGridDataConditions(&$params, &$model) {
|
||||||
|
$conditions = parent::jqGridDataConditions($params, $model);
|
||||||
|
|
||||||
|
if ($params['action'] === 'active') {
|
||||||
|
$conditions[] = 'Lease.close_date IS NULL';
|
||||||
|
}
|
||||||
|
elseif ($params['action'] === 'closed') {
|
||||||
|
$conditions[] = 'Lease.close_date IS NOT NULL';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function jqGridRecordLinks(&$params, &$model, &$records, $links) {
|
||||||
|
$links['Lease'] = array('number');
|
||||||
|
$links['Unit'] = array('name');
|
||||||
|
$links['Customer'] = array('name');
|
||||||
|
return parent::jqGridRecordLinks($params, $model, $records, $links);
|
||||||
|
}
|
||||||
|
|
||||||
|
function jqGridDataRecords(&$params, &$model, $query) {
|
||||||
|
$leases = parent::jqGridDataRecords($params, $model, $query);
|
||||||
|
|
||||||
|
// Get the balance on each lease.
|
||||||
|
foreach ($leases AS &$lease) {
|
||||||
|
$stats = $this->Lease->stats($lease['Lease']['id']);
|
||||||
|
$lease['Lease']['balance'] = $stats['balance'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $leases;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: view
|
||||||
|
* - Displays information about a specific lease
|
||||||
|
*/
|
||||||
|
|
||||||
|
function view($id = null) {
|
||||||
|
if (!$id) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get details about the lease and its ledgers (no ledger entries yet)
|
||||||
|
$lease = $this->Lease->find
|
||||||
|
('first',
|
||||||
|
array('contain' =>
|
||||||
|
array(// Models
|
||||||
|
'LeaseType',
|
||||||
|
'Unit',
|
||||||
|
'Customer',
|
||||||
|
),
|
||||||
|
'conditions' => array(array('Lease.id' => $id)),
|
||||||
|
'limit' => 2
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Obtain the overall lease balance
|
||||||
|
$this->Lease->statsMerge($lease['Lease'],
|
||||||
|
array('stats' => $this->Lease->stats($id)));
|
||||||
|
$outstanding_balance = $lease['Lease']['stats']['balance'];
|
||||||
|
|
||||||
|
// Determine the lease security deposit
|
||||||
|
$deposits = $this->Lease->findSecurityDeposits($lease['Lease']['id']);
|
||||||
|
$outstanding_deposit = $deposits['summary']['balance'];
|
||||||
|
|
||||||
|
// Prepare to render
|
||||||
|
$title = 'Lease: #' . $lease['Lease']['id'];
|
||||||
|
$this->set(compact('lease', 'title',
|
||||||
|
'outstanding_deposit',
|
||||||
|
'outstanding_balance'));
|
||||||
|
}
|
||||||
|
}
|
||||||
+31
-154
@@ -79,51 +79,6 @@ class LedgerEntriesController extends AppController {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
elseif ($params['action'] === 'collected') {
|
|
||||||
// Income / Receipt / Money
|
|
||||||
// debit: A/R credit: Income <-- this entry
|
|
||||||
// debit: Receipt credit: A/R <-- ReceiptLedgerEntry, below
|
|
||||||
// debit: Money credit: Receipt <-- MoneyLedgerEntry, below
|
|
||||||
|
|
||||||
$link['CreditLedger'] =
|
|
||||||
array('fields' => 'sequence',
|
|
||||||
'Account' =>
|
|
||||||
array('fields' => array('id', 'name'),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// We're searching for the Receipt<->A/R entries,
|
|
||||||
// which are debits on the A/R account. Find the
|
|
||||||
// reconciling entries to that A/R debit.
|
|
||||||
$link['DebitReconciliationLedgerEntry'] =
|
|
||||||
array('alias' => 'ReceiptLedgerEntry',
|
|
||||||
|
|
||||||
'Transaction' =>
|
|
||||||
array('alias' => 'ReceiptTransaction'),
|
|
||||||
|
|
||||||
// Credit Ledger should be A/R;
|
|
||||||
// Debit Ledger should be Receipt
|
|
||||||
'DebitLedger' =>
|
|
||||||
array('alias' => 'ReceiptLedger',
|
|
||||||
'Account' => array('alias' => 'ReceiptAccount'),
|
|
||||||
),
|
|
||||||
|
|
||||||
// Finally, the Money (Cash/Check/etc) Entry is the one
|
|
||||||
// which reconciles our ReceiptLedgerEntry debit
|
|
||||||
'DebitReconciliationLedgerEntry' =>
|
|
||||||
array('alias' => 'MoneyLedgerEntry',
|
|
||||||
'linkalias' => 'MoneyLedgerEntryR',
|
|
||||||
|
|
||||||
// Credit Ledger should be Receipt;
|
|
||||||
// Debit Ledger should be our Money Account
|
|
||||||
'DebitLedger' =>
|
|
||||||
array('alias' => 'MoneyLedger',
|
|
||||||
'Account' =>
|
|
||||||
array('alias' => 'MoneyAccount'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
$link['DebitLedger'] =
|
$link['DebitLedger'] =
|
||||||
array('fields' => array('id', 'sequence'),
|
array('fields' => array('id', 'sequence'),
|
||||||
@@ -175,15 +130,7 @@ class LedgerEntriesController extends AppController {
|
|||||||
? $params['custom']['account_type']
|
? $params['custom']['account_type']
|
||||||
: null);
|
: null);
|
||||||
|
|
||||||
$fields = $model->ledgerContextFields2($ledger_id, $account_id, $account_type);
|
return $model->ledgerContextFields2($ledger_id, $account_id, $account_type);
|
||||||
|
|
||||||
if (count(array_intersect($params['fields'], array('applied'))) == 1)
|
|
||||||
$fields[] = 'SUM(Reconciliation.amount) AS applied';
|
|
||||||
|
|
||||||
if ($params['action'] === 'collected')
|
|
||||||
$fields[] = 'MAX(ReceiptTransaction.stamp) AS last_paid';
|
|
||||||
|
|
||||||
return $fields;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function jqGridDataConditions(&$params, &$model) {
|
function jqGridDataConditions(&$params, &$model) {
|
||||||
@@ -196,30 +143,6 @@ class LedgerEntriesController extends AppController {
|
|||||||
|
|
||||||
$conditions = parent::jqGridDataConditions($params, $model);
|
$conditions = parent::jqGridDataConditions($params, $model);
|
||||||
|
|
||||||
if ($params['action'] === 'collected') {
|
|
||||||
extract($params['custom']);
|
|
||||||
|
|
||||||
if (isset($collected_account_id))
|
|
||||||
$conditions[] = array('Account.id' => $params['custom']['collected_account_id']);
|
|
||||||
else
|
|
||||||
die("INTERNAL ERROR: COLLECTED ACCOUNT ID NOT SET");
|
|
||||||
|
|
||||||
if (!empty($collected_from_date))
|
|
||||||
$conditions[]
|
|
||||||
= array('ReceiptTransaction.stamp >=' =>
|
|
||||||
$this->LedgerEntry->Transaction->dateFormatBeforeSave($collected_from_date));
|
|
||||||
|
|
||||||
if (!empty($collected_through_date))
|
|
||||||
$conditions[]
|
|
||||||
= array('ReceiptTransaction.stamp <=' =>
|
|
||||||
$this->LedgerEntry->Transaction->dateFormatBeforeSave($collected_through_date . ' 23:59:59'));
|
|
||||||
|
|
||||||
if (isset($collected_payment_accounts))
|
|
||||||
$conditions[] = array('MoneyAccount.id' => $collected_payment_accounts);
|
|
||||||
else
|
|
||||||
$conditions[] = array('NOT' => array(array('MoneyAccount.id' => null)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($params['action'] === 'ledger') {
|
if ($params['action'] === 'ledger') {
|
||||||
$conditions[] = $model->ledgerContextConditions($ledger_id, $account_type);
|
$conditions[] = $model->ledgerContextConditions($ledger_id, $account_type);
|
||||||
}
|
}
|
||||||
@@ -281,11 +204,6 @@ class LedgerEntriesController extends AppController {
|
|||||||
array('Transaction.id' => $params['custom']['transaction_id']);
|
array('Transaction.id' => $params['custom']['transaction_id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($params['custom']['monetary_source_id'])) {
|
|
||||||
$conditions[] =
|
|
||||||
array('MonetarySource.id' => $params['custom']['monetary_source_id']);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $conditions;
|
return $conditions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,10 +221,10 @@ class LedgerEntriesController extends AppController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function jqGridDataGroup(&$params, &$model) {
|
function jqGridDataGroup(&$params, &$model) {
|
||||||
if (isset($params['custom']['group_by_tx']) && $params['custom']['group_by_tx'])
|
if (isset($params['custom']['notxgroup']))
|
||||||
return $model->alias.'.transaction_id';
|
|
||||||
|
|
||||||
return parent::jqGridDataGroup($params, $model);
|
return parent::jqGridDataGroup($params, $model);
|
||||||
|
|
||||||
|
return $model->alias.'.transaction_id';
|
||||||
}
|
}
|
||||||
|
|
||||||
function jqGridDataOrder(&$params, &$model, $index, $direction) {
|
function jqGridDataOrder(&$params, &$model, $index, $direction) {
|
||||||
@@ -321,28 +239,30 @@ class LedgerEntriesController extends AppController {
|
|||||||
return $order;
|
return $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
function jqGridDataRecords(&$params, &$model, $query) {
|
function jqGridRecordsPostProcess(&$params, &$model, &$records) {
|
||||||
if ($params['action'] === 'collected') {
|
parent::jqGridRecordsPostProcess($params, $model, $records);
|
||||||
$tquery = array_diff_key($query, array('fields'=>1,'group'=>1,'limit'=>1,'order'=>1));
|
|
||||||
$tquery['fields'] = array('SUM(Reconciliation.amount) AS applied');
|
|
||||||
$total = $model->find('first', $tquery);
|
|
||||||
|
|
||||||
$params['userdata']['total'] = $total[0]['applied'];
|
$subtotal = 0;
|
||||||
|
foreach ($records AS &$record) {
|
||||||
|
$amount = (isset($record['LedgerEntry']['balance'])
|
||||||
|
? $record['LedgerEntry']['balance']
|
||||||
|
: $record['LedgerEntry']['amount']);
|
||||||
|
$record['LedgerEntry']['subtotal'] = ($subtotal += $amount);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
// Experiment to minimize columns by putting the monetary source
|
||||||
|
// as the Account, when available
|
||||||
|
if ($record['MonetarySource']['name'])
|
||||||
|
$record['Account']['name'] = $record['MonetarySource']['name'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::jqGridDataRecords($params, $model, $query);
|
function jqGridDataOutputRecordCell(&$params, &$model, &$record, $field, $data) {
|
||||||
}
|
/* if ($field === 'CreditAccount.name') { */
|
||||||
|
/* $data .= '-OK'; */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
parent::jqGridDataOutputRecordCell($params, $model, $record, $field, $data);
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: reverse the ledger entry
|
|
||||||
*/
|
|
||||||
|
|
||||||
function reverse($id) {
|
|
||||||
$this->LedgerEntry->reverse($id);
|
|
||||||
$this->redirect(array('action'=>'view', $id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -364,6 +284,7 @@ class LedgerEntriesController extends AppController {
|
|||||||
('first',
|
('first',
|
||||||
array('contain' => array('MonetarySource.id',
|
array('contain' => array('MonetarySource.id',
|
||||||
'MonetarySource.name',
|
'MonetarySource.name',
|
||||||
|
'MonetarySource.MonetaryType.id',
|
||||||
'Transaction.id',
|
'Transaction.id',
|
||||||
'Transaction.stamp',
|
'Transaction.stamp',
|
||||||
'DebitLedger.id',
|
'DebitLedger.id',
|
||||||
@@ -377,7 +298,9 @@ class LedgerEntriesController extends AppController {
|
|||||||
'Lease.id',
|
'Lease.id',
|
||||||
),
|
),
|
||||||
|
|
||||||
'fields' => array('LedgerEntry.*'),
|
'fields' => array('LedgerEntry.id',
|
||||||
|
'LedgerEntry.amount',
|
||||||
|
'LedgerEntry.comment'),
|
||||||
|
|
||||||
'conditions' => array('LedgerEntry.id' => $id),
|
'conditions' => array('LedgerEntry.id' => $id),
|
||||||
));
|
));
|
||||||
@@ -394,9 +317,6 @@ class LedgerEntriesController extends AppController {
|
|||||||
'fields' => array('Account.id', 'Account.name', 'Account.type', 'Account.trackable'),
|
'fields' => array('Account.id', 'Account.name', 'Account.type', 'Account.trackable'),
|
||||||
'conditions' => array('Account.id' => $entry['DebitLedger']['account_id']),
|
'conditions' => array('Account.id' => $entry['DebitLedger']['account_id']),
|
||||||
));
|
));
|
||||||
$entry['DebitLedger']['Account']['ftype'] =
|
|
||||||
$this->LedgerEntry->DebitLedger->Account
|
|
||||||
->fundamentalType($entry['DebitLedger']['Account']['type']);
|
|
||||||
|
|
||||||
// Get the Account from CreditLedger
|
// Get the Account from CreditLedger
|
||||||
$entry['CreditLedger'] += $this->LedgerEntry->CreditLedger->Account->find
|
$entry['CreditLedger'] += $this->LedgerEntry->CreditLedger->Account->find
|
||||||
@@ -405,63 +325,20 @@ class LedgerEntriesController extends AppController {
|
|||||||
'fields' => array('Account.id', 'Account.name', 'Account.type', 'Account.trackable'),
|
'fields' => array('Account.id', 'Account.name', 'Account.type', 'Account.trackable'),
|
||||||
'conditions' => array('Account.id' => $entry['CreditLedger']['account_id']),
|
'conditions' => array('Account.id' => $entry['CreditLedger']['account_id']),
|
||||||
));
|
));
|
||||||
$entry['CreditLedger']['Account']['ftype'] =
|
|
||||||
$this->LedgerEntry->CreditLedger->Account
|
|
||||||
->fundamentalType($entry['CreditLedger']['Account']['type']);
|
|
||||||
|
|
||||||
// Get the reconciliation balances for this ledger entry
|
// Get the reconciliation balances for this ledger entry
|
||||||
$stats = $this->LedgerEntry->stats($id);
|
$stats = $this->LedgerEntry->stats($id);
|
||||||
$stats['debit']['amount_reconciled'] = $stats['debit_amount_reconciled'];
|
|
||||||
$stats['credit']['amount_reconciled'] = $stats['credit_amount_reconciled'];
|
|
||||||
if ($entry['DebitLedger']['Account']['trackable'])
|
if ($entry['DebitLedger']['Account']['trackable'])
|
||||||
$stats['debit']['amount_remaining'] = $entry['LedgerEntry']['amount'] - $stats['debit']['amount_reconciled'];
|
$stats['debit_amount_remaining'] = $entry['LedgerEntry']['amount'] - $stats['debit_amount_reconciled'];
|
||||||
if ($entry['CreditLedger']['Account']['trackable'])
|
if ($entry['CreditLedger']['Account']['trackable'])
|
||||||
$stats['credit']['amount_remaining'] = $entry['LedgerEntry']['amount'] - $stats['credit']['amount_reconciled'];
|
$stats['credit_amount_remaining'] = $entry['LedgerEntry']['amount'] - $stats['credit_amount_reconciled'];
|
||||||
//pr($stats);
|
//pr($stats);
|
||||||
|
|
||||||
$reconciled = $this->LedgerEntry->findReconciledLedgerEntries($id);
|
$reconciled = $this->LedgerEntry->findReconciledLedgerEntries($id);
|
||||||
//pr($reconciled);
|
//pr($reconciled);
|
||||||
|
|
||||||
|
|
||||||
// REVISIT <AP>: 20090711
|
|
||||||
// It's not clear whether we should be able to reverse charges that have
|
|
||||||
// already been paid/cleared/reconciled. Certainly, that will be the
|
|
||||||
// case when someone has pre-paid and then moves out early. However, this
|
|
||||||
// will work well for items accidentally charged but not yet paid for.
|
|
||||||
if ((!$entry['DebitLedger']['Account']['trackable'] ||
|
|
||||||
$stats['debit']['amount_reconciled'] == 0) &&
|
|
||||||
(!$entry['CreditLedger']['Account']['trackable'] ||
|
|
||||||
$stats['credit']['amount_reconciled'] == 0)
|
|
||||||
|
|
||||||
&& 0
|
|
||||||
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Set up dynamic menu items
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Operations', 'header' => true);
|
|
||||||
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Undo',
|
|
||||||
'url' => array('action' => 'reverse',
|
|
||||||
$id));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->LedgerEntry->Ledger->Account->type
|
|
||||||
($entry['CreditLedger']['Account']['id']) == 'INCOME')
|
|
||||||
{
|
|
||||||
// Set up dynamic menu items
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Operations', 'header' => true);
|
|
||||||
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Reverse',
|
|
||||||
'url' => array('action' => 'reverse',
|
|
||||||
$id));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare to render.
|
// Prepare to render.
|
||||||
$title = "Double Ledger Entry #{$entry['LedgerEntry']['id']}";
|
$title = "Ledger Entry #{$entry['LedgerEntry']['id']}";
|
||||||
$this->set(compact('entry', 'title', 'reconciled', 'stats'));
|
$this->set(compact('entry', 'title', 'reconciled', 'stats'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,7 +59,6 @@ class LedgersController extends AppController {
|
|||||||
array(// Models
|
array(// Models
|
||||||
'Account',
|
'Account',
|
||||||
'LedgerEntry',
|
'LedgerEntry',
|
||||||
'Close',
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,6 @@ class MapsController extends AppController {
|
|||||||
$this->redirect(array('action'=>'index'));
|
$this->redirect(array('action'=>'index'));
|
||||||
}
|
}
|
||||||
$this->set('info', $this->mapInfo($id, $requested_width));
|
$this->set('info', $this->mapInfo($id, $requested_width));
|
||||||
$this->set('title', "Site Map");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -151,6 +150,22 @@ class MapsController extends AppController {
|
|||||||
return $info;
|
return $info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Temporary function
|
||||||
|
function unitStatusList() {
|
||||||
|
return
|
||||||
|
array('DELETED' => array(),
|
||||||
|
'DAMAGED' => array(),
|
||||||
|
'COMPANY' => array(),
|
||||||
|
'UNAVAILABLE' => array(),
|
||||||
|
'RESERVED' => array(),
|
||||||
|
'DIRTY' => array(),
|
||||||
|
'VACANT' => array(),
|
||||||
|
'OCCUPIED' => array(),
|
||||||
|
'LATE' => array(),
|
||||||
|
'LOCKED' => array(),
|
||||||
|
'LIENED' => array(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -160,10 +175,9 @@ class MapsController extends AppController {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function legend($id = null, $requested_width = 400) {
|
function legend($id = null, $requested_width = 400) {
|
||||||
$status = $this->Map->Unit->activeStatusEnums();
|
$status = $this->unitStatusList();
|
||||||
//pr($status);
|
$cols = 6;
|
||||||
$rows = 2;
|
$rows = (int)((count($status) + $cols - 1) / $cols);
|
||||||
$cols = (int)((count($status) + $rows - 1) / $rows);
|
|
||||||
|
|
||||||
$info = array('units' => array());
|
$info = array('units' => array());
|
||||||
|
|
||||||
@@ -191,7 +205,7 @@ class MapsController extends AppController {
|
|||||||
$item_width *= $screen_adjustment_factor;
|
$item_width *= $screen_adjustment_factor;
|
||||||
$item_depth *= $screen_adjustment_factor;
|
$item_depth *= $screen_adjustment_factor;
|
||||||
|
|
||||||
foreach ($status AS $code => $value) {
|
foreach ($status AS $code => $color) {
|
||||||
$info['units'][] = array('name' => $code,
|
$info['units'][] = array('name' => $code,
|
||||||
'status' => $code,
|
'status' => $code,
|
||||||
'width' => $item_width,
|
'width' => $item_width,
|
||||||
+5
-38
@@ -38,7 +38,8 @@ class MonetarySourcesController extends AppController {
|
|||||||
|
|
||||||
function jqGridDataTables(&$params, &$model) {
|
function jqGridDataTables(&$params, &$model) {
|
||||||
return array
|
return array
|
||||||
('contain' => false,
|
('link' => array('MonetaryType' => array('fields' => array('MonetaryType.id', 'MonetaryType.name')),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,26 +49,6 @@ class MonetarySourcesController extends AppController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: nsf
|
|
||||||
* - Marks a monetary source as having insufficient funds.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function nsf($id = null) {
|
|
||||||
if (!$id) {
|
|
||||||
$this->Session->setFlash(__('Invalid Item.', true));
|
|
||||||
$this->redirect(array('action'=>'index'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// REVISIT <AP>: 20090713
|
|
||||||
// For testing purposes, must be deleted
|
|
||||||
$stamp = '2009-07-09';
|
|
||||||
|
|
||||||
$this->MonetarySource->nsf($id, $stamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -84,25 +65,11 @@ class MonetarySourcesController extends AppController {
|
|||||||
// Get the MonetarySource and related fields
|
// Get the MonetarySource and related fields
|
||||||
$monetary_source = $this->MonetarySource->find
|
$monetary_source = $this->MonetarySource->find
|
||||||
('first', array
|
('first', array
|
||||||
('contain' => false,
|
('contain' => array
|
||||||
|
('MonetaryType',
|
||||||
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
// REVISIT <AP>: 20090713
|
|
||||||
// Consider allowing the NSF operation only if the source is used on
|
|
||||||
// a ledger entry that is debited on a "payable" account (perhaps
|
|
||||||
// even restricted to "payable" ASSET accounts), credited on Receipt
|
|
||||||
// (or A/R), and reconciles the credit to an entry that debits on a
|
|
||||||
// "depositable" account.
|
|
||||||
|
|
||||||
// Set up dynamic menu items
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Operations', 'header' => true);
|
|
||||||
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'NSF',
|
|
||||||
'url' => array('action' => 'nsf',
|
|
||||||
$id));
|
|
||||||
|
|
||||||
// Prepare to render.
|
// Prepare to render.
|
||||||
$title = "Monetary Source #{$monetary_source['MonetarySource']['id']}";
|
$title = "Monetary Source #{$monetary_source['MonetarySource']['id']}";
|
||||||
$this->set(compact('monetary_source', 'title'));
|
$this->set(compact('monetary_source', 'title'));
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
/* SVN FILE: $Id: pages_controller.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||||
|
/**
|
||||||
|
* Static content controller.
|
||||||
|
*
|
||||||
|
* This file will render views from views/pages/
|
||||||
|
*
|
||||||
|
* PHP versions 4 and 5
|
||||||
|
*
|
||||||
|
* CakePHP(tm) : Rapid Development Framework (http://www.cakephp.org)
|
||||||
|
* Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
*
|
||||||
|
* Licensed under The MIT License
|
||||||
|
* Redistributions of files must retain the above copyright notice.
|
||||||
|
*
|
||||||
|
* @filesource
|
||||||
|
* @copyright Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
|
||||||
|
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.cake.libs.controller
|
||||||
|
* @since CakePHP(tm) v 0.2.9
|
||||||
|
* @version $Revision: 7945 $
|
||||||
|
* @modifiedby $LastChangedBy: gwoo $
|
||||||
|
* @lastmodified $Date: 2008-12-18 18:16:01 -0800 (Thu, 18 Dec 2008) $
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Static content controller
|
||||||
|
*
|
||||||
|
* Override this controller by placing a copy in controllers directory of an application
|
||||||
|
*
|
||||||
|
* @package cake
|
||||||
|
* @subpackage cake.cake.libs.controller
|
||||||
|
*/
|
||||||
|
class PagesController extends AppController {
|
||||||
|
/**
|
||||||
|
* Controller name
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
var $name = 'Pages';
|
||||||
|
/**
|
||||||
|
* Default helper
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
var $helpers = array('Html');
|
||||||
|
/**
|
||||||
|
* This controller does not use a model
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
var $uses = array();
|
||||||
|
/**
|
||||||
|
* Displays a view
|
||||||
|
*
|
||||||
|
* @param mixed What page to display
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function display() {
|
||||||
|
$path = func_get_args();
|
||||||
|
|
||||||
|
$count = count($path);
|
||||||
|
if (!$count) {
|
||||||
|
$this->redirect('/');
|
||||||
|
}
|
||||||
|
$page = $subpage = $title = null;
|
||||||
|
|
||||||
|
if (!empty($path[0])) {
|
||||||
|
$page = $path[0];
|
||||||
|
}
|
||||||
|
if (!empty($path[1])) {
|
||||||
|
$subpage = $path[1];
|
||||||
|
}
|
||||||
|
if (!empty($path[$count - 1])) {
|
||||||
|
$title = Inflector::humanize($path[$count - 1]);
|
||||||
|
}
|
||||||
|
$this->set(compact('page', 'subpage', 'title'));
|
||||||
|
$this->render(join('/', $path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -0,0 +1,288 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class TransactionsController extends AppController {
|
||||||
|
|
||||||
|
var $components = array('RequestHandler');
|
||||||
|
|
||||||
|
var $sidemenu_links =
|
||||||
|
array(array('name' => 'Transactions', 'header' => true),
|
||||||
|
array('name' => 'All', 'url' => array('controller' => 'transactions', 'action' => 'all')),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* override: sideMenuLinks
|
||||||
|
* - Generates controller specific links for the side menu
|
||||||
|
*/
|
||||||
|
function sideMenuLinks() {
|
||||||
|
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: index / all
|
||||||
|
* - Generate a listing of transactions
|
||||||
|
*/
|
||||||
|
|
||||||
|
function index() { $this->all(); }
|
||||||
|
function all() { $this->jqGridView('All Transactions', 'all'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtuals: jqGridData
|
||||||
|
* - With the application controller handling the jqGridData action,
|
||||||
|
* these virtual functions ensure that the correct data is passed
|
||||||
|
* to jqGrid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function jqGridRecordLinks(&$params, &$model, &$records, $links) {
|
||||||
|
$links['Transaction'] = array('id');
|
||||||
|
return parent::jqGridRecordLinks($params, $model, $records, $links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: view
|
||||||
|
* - Displays information about a specific transaction
|
||||||
|
*/
|
||||||
|
|
||||||
|
function view($id = null) {
|
||||||
|
if (!$id) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$transaction = $this->Transaction->find
|
||||||
|
('first',
|
||||||
|
array('contain' =>
|
||||||
|
array(// Models
|
||||||
|
'LedgerEntry' => array('fields' => array('LedgerEntry.id',
|
||||||
|
'LedgerEntry.amount',
|
||||||
|
'LedgerEntry.comment'),
|
||||||
|
//Models
|
||||||
|
|
||||||
|
'DebitLedger' => array
|
||||||
|
('fields' => array('DebitLedger.id', 'DebitLedger.sequence'),
|
||||||
|
'Account' => array
|
||||||
|
('fields' => array('Account.id', 'Account.name')),
|
||||||
|
),
|
||||||
|
|
||||||
|
'CreditLedger' => array
|
||||||
|
('fields' => array('CreditLedger.id', 'CreditLedger.sequence'),
|
||||||
|
'Account' => array
|
||||||
|
('fields' => array('Account.id', 'Account.name')),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'conditions' => array('Transaction.id' => $id),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Figure out the transaction total
|
||||||
|
$total = 0;
|
||||||
|
foreach($transaction['LedgerEntry'] AS $entry)
|
||||||
|
$total += $entry['amount'];
|
||||||
|
|
||||||
|
// OK, prepare to render.
|
||||||
|
$title = 'Transaction #' . $transaction['Transaction']['id'];
|
||||||
|
$this->set(compact('transaction', 'title', 'total'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: postReceipt
|
||||||
|
* - handles the creation of a payment receipt
|
||||||
|
*/
|
||||||
|
|
||||||
|
function postReceipt() {
|
||||||
|
$this->autoRender = false;
|
||||||
|
|
||||||
|
if (!$this->RequestHandler->isPost()) {
|
||||||
|
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//pr(array('thisdata' => $this->data));
|
||||||
|
|
||||||
|
if (isset($this->data['customer_id'])) {
|
||||||
|
$C = new Customer();
|
||||||
|
$C->recursive = -1;
|
||||||
|
$customer = $C->find
|
||||||
|
('first',
|
||||||
|
array('contain' => array('Account.CurrentLedger.id'),
|
||||||
|
'fields' => false,
|
||||||
|
'conditions' => array('Customer.id', $this->data['customer_id']),
|
||||||
|
));
|
||||||
|
$ledger_id = $customer['Account']['CurrentLedger']['id'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Payment by Unit, Lease, etc
|
||||||
|
$ledger_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$amount = 0;
|
||||||
|
foreach ($this->data['LedgerEntry'] AS &$entry) {
|
||||||
|
$reconciled = $C->reconcileNewLedgerEntry($this->data['customer_id'],
|
||||||
|
'credit',
|
||||||
|
$entry['amount']);
|
||||||
|
pr(compact('entry', 'reconciled'));
|
||||||
|
|
||||||
|
foreach ($reconciled['debit']['entry'] AS $rec) {
|
||||||
|
$entry['DebitReconciliationLedgerEntry'] =
|
||||||
|
array('amount' => $rec['applied'],
|
||||||
|
//'debit_ledger_entry_id'
|
||||||
|
'credit_ledger_entry_id' => $rec['id']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$amount += isset($entry['amount']) ? $entry['amount'] : 0;
|
||||||
|
$entry['debit_ledger_id'] = 6; // Cash/Payments
|
||||||
|
$entry['credit_ledger_id'] = $ledger_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pr($this->data);
|
||||||
|
$T = new Transaction();
|
||||||
|
$T->create();
|
||||||
|
if ($T->saveAll($this->data,
|
||||||
|
array(
|
||||||
|
'validate' => false,
|
||||||
|
//'fieldList' => array(),
|
||||||
|
//'callbacks' => true,
|
||||||
|
))) {
|
||||||
|
$tid = $T->id;
|
||||||
|
$this->Session->setFlash(__("New Transaction Created ($tid)!", true));
|
||||||
|
//$this->redirect(array('action'=>'view', $mid));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->autoRender = false;
|
||||||
|
pr(array('checkpoint' => "saveAll failed"));
|
||||||
|
}
|
||||||
|
pr($T->data);
|
||||||
|
|
||||||
|
$C = new Customer();
|
||||||
|
$LE = new LedgerEntry();
|
||||||
|
/* $reconciled = $C->reconcileNewLedgerEntry($this->data['customer_id'], */
|
||||||
|
/* 'credit', */
|
||||||
|
/* $amount); */
|
||||||
|
/* pr(compact('amount', 'unreconciled', 'reconciled')); */
|
||||||
|
/* return; */
|
||||||
|
|
||||||
|
foreach ($this->data['LedgerEntry'] AS &$entry) {
|
||||||
|
$reconciled = $C->reconcileNewLedgerEntry($this->data['customer_id'],
|
||||||
|
'credit',
|
||||||
|
$entry['amount']);
|
||||||
|
pr(compact('entry', 'reconciled'));
|
||||||
|
continue;
|
||||||
|
|
||||||
|
foreach ($reconciled['debit']['entry'] AS $rec) {
|
||||||
|
$data = array('LedgerEntry' =>
|
||||||
|
array('DebitReconciliationLedgerEntry' =>
|
||||||
|
array('amount' => $rec['applied'],
|
||||||
|
//'debit_ledger_entry_id'
|
||||||
|
'credit_ledger_entry_id' => $rec['id']
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
//'DebitReconciliationLedgerEntry' => array(
|
||||||
|
//pr(compact('amount', 'unreconciled', 'reconciled'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveTest() {
|
||||||
|
$data =
|
||||||
|
array(
|
||||||
|
/* 'Customer' => array */
|
||||||
|
/* ('id' => 7, */
|
||||||
|
/* ), */
|
||||||
|
|
||||||
|
'LedgerEntry' => array
|
||||||
|
(
|
||||||
|
'0' => array(
|
||||||
|
'amount' => 100,
|
||||||
|
'debit_ledger_id' => 1,
|
||||||
|
'credit_ledger_id' => 2,
|
||||||
|
'MonetarySource' => array('name' => 'testmoney', 'monetary_type_id' => 2),
|
||||||
|
),
|
||||||
|
'1' => array(
|
||||||
|
'amount' => 101,
|
||||||
|
'debit_ledger_id' => 1,
|
||||||
|
'credit_ledger_id' => 2,
|
||||||
|
'MonetarySource' => array('name' => 'testmoney2', 'monetary_type_id' => 2),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
'Transaction' => array
|
||||||
|
(
|
||||||
|
'stamp' => '06/18/2009',
|
||||||
|
'comment' => 'no comment',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$data =
|
||||||
|
/* array( */
|
||||||
|
/* 'LedgerEntry' => array */
|
||||||
|
/* ( */
|
||||||
|
/* '0' => */
|
||||||
|
array(
|
||||||
|
'amount' => 100,
|
||||||
|
'debit_ledger_id' => 1,
|
||||||
|
'credit_ledger_id' => 2,
|
||||||
|
'transaction_id' => 66,
|
||||||
|
'DebitReconciliationLedgerEntry' =>
|
||||||
|
array('amount' => 44,
|
||||||
|
//'debit_ledger_entry_id'
|
||||||
|
'credit_ledger_entry_id' => 17,
|
||||||
|
),
|
||||||
|
/* ), */
|
||||||
|
/* ), */
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
//$M = new Transaction();
|
||||||
|
$M = new LedgerEntry();
|
||||||
|
$M->create();
|
||||||
|
$retval = $M->saveAll($data,
|
||||||
|
array(
|
||||||
|
'validate' => false,
|
||||||
|
'fieldList' => array(),
|
||||||
|
'callbacks' => true,
|
||||||
|
));
|
||||||
|
|
||||||
|
$mid = $M->id;
|
||||||
|
pr(compact('retval', 'mid'));
|
||||||
|
if ($mid) {
|
||||||
|
$this->Session->setFlash(__("New Transaction Created ($mid)!", true));
|
||||||
|
//$this->redirect(array('action'=>'view', $mid));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->autoRender = false;
|
||||||
|
pr(array('checkpoint' => "saveAll failed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* $LE = new LedgerEntry(); */
|
||||||
|
/* $LE->create(); */
|
||||||
|
/* $ret = $LE->save($data, */
|
||||||
|
/* array( */
|
||||||
|
/* 'validate' => false, */
|
||||||
|
/* 'fieldList' => array(), */
|
||||||
|
/* 'callbacks' => true, */
|
||||||
|
/* )); */
|
||||||
|
/* $leid = $LE->id; */
|
||||||
|
/* pr(array('checkpoint' => "New Ledger Entry", */
|
||||||
|
/* compact('leid', 'ret'))); */
|
||||||
|
//pr($LE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class UnitsController extends AppController {
|
||||||
|
|
||||||
|
var $sidemenu_links =
|
||||||
|
array(array('name' => 'Units', 'header' => true),
|
||||||
|
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')),
|
||||||
|
array('name' => 'All', 'url' => array('controller' => 'units', 'action' => 'all')),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* override: sideMenuLinks
|
||||||
|
* - Generates controller specific links for the side menu
|
||||||
|
*/
|
||||||
|
function sideMenuLinks() {
|
||||||
|
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: index / unavailable / vacant / occupied / all
|
||||||
|
* - Generate a listing of units
|
||||||
|
*/
|
||||||
|
|
||||||
|
function index() { $this->all(); }
|
||||||
|
function unavailable() { $this->jqGridView('Unavailable Units'); }
|
||||||
|
function vacant() { $this->jqGridView('Vacant Units'); }
|
||||||
|
function occupied() { $this->jqGridView('Occupied Units'); }
|
||||||
|
function all() { $this->jqGridView('All Units', 'all'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtuals: jqGridData
|
||||||
|
* - With the application controller handling the jqGridData action,
|
||||||
|
* these virtual functions ensure that the correct data is passed
|
||||||
|
* to jqGrid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function jqGridDataSetup(&$params) {
|
||||||
|
parent::jqGridDataSetup($params);
|
||||||
|
if (!isset($params['action']))
|
||||||
|
$params['action'] = 'all';
|
||||||
|
}
|
||||||
|
|
||||||
|
function jqGridDataTables(&$params, &$model) {
|
||||||
|
$link = array
|
||||||
|
('link' =>
|
||||||
|
array(// Models
|
||||||
|
'UnitSize' => array('fields' => array('name')),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($params['action'] === 'occupied')
|
||||||
|
$link['Lease'] = array('fields' => array(),
|
||||||
|
// Models
|
||||||
|
'Contact' => array('fields' => array('display_name'),
|
||||||
|
//'type' => 'LEFT',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return $link;
|
||||||
|
}
|
||||||
|
|
||||||
|
function jqGridDataConditions(&$params, &$model) {
|
||||||
|
$conditions = parent::jqGridDataConditions($params, $model);
|
||||||
|
|
||||||
|
if ($params['action'] === 'unavailable') {
|
||||||
|
$conditions[] = $this->Unit->conditionUnavailable();
|
||||||
|
}
|
||||||
|
elseif ($params['action'] === 'vacant') {
|
||||||
|
$conditions[] = $this->Unit->conditionVacant();
|
||||||
|
}
|
||||||
|
elseif ($params['action'] === 'occupied') {
|
||||||
|
$conditions[] = $this->Unit->conditionOccupied();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function jqGridDataOrder(&$params, &$model, $index, $direction) {
|
||||||
|
if ($index === 'Unit.name') {
|
||||||
|
$index = 'Unit.sort_order';
|
||||||
|
}
|
||||||
|
return parent::jqGridDataOrder($params, $model, $index, $direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: view
|
||||||
|
* - Displays information about a specific unit
|
||||||
|
*/
|
||||||
|
|
||||||
|
function view($id = null) {
|
||||||
|
if (!$id) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('action'=>''));
|
||||||
|
}
|
||||||
|
|
||||||
|
$unit = $this->Unit->find
|
||||||
|
('first',
|
||||||
|
array('contain' =>
|
||||||
|
array(// Models
|
||||||
|
'UnitSize',
|
||||||
|
'Lease' => array('Customer'),
|
||||||
|
'CurrentLease' => array('Customer')
|
||||||
|
),
|
||||||
|
'conditions' => array('Unit.id' => $id),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Get the balance on each lease.
|
||||||
|
foreach ($unit['Lease'] AS &$lease) {
|
||||||
|
$stats = $this->Unit->Lease->stats($lease['id']);
|
||||||
|
$lease['balance'] = $stats['balance'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$outstanding_balance = 0;
|
||||||
|
$outstanding_deposit = 0;
|
||||||
|
if (isset($unit['CurrentLease']['id'])) {
|
||||||
|
// Figure out the outstanding balance of the current lease.
|
||||||
|
$stats = $this->Unit->stats($id);
|
||||||
|
$outstanding_balance =
|
||||||
|
$stats['CurrentLease']['balance'];
|
||||||
|
|
||||||
|
// Figure out the total security deposit for the current lease.
|
||||||
|
$deposits = $this->Unit->Lease->findSecurityDeposits($unit['CurrentLease']['id']);
|
||||||
|
$outstanding_deposit = $deposits['summary']['balance'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Operations', 'header' => true);
|
||||||
|
$this->sidemenu_links[] =
|
||||||
|
array('name' => 'Move-Out', 'url' => array('controller' => 'units', 'action' => 'move-out'));
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = 'Unit ' . $unit['Unit']['name'];
|
||||||
|
$this->set(compact('unit', 'title',
|
||||||
|
'outstanding_balance',
|
||||||
|
'outstanding_deposit'));
|
||||||
|
}
|
||||||
|
}
|
||||||
-1189
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,358 @@
|
|||||||
|
<?php
|
||||||
|
class Account extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'Account';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'name' => array('notempty'),
|
||||||
|
'external_name' => array('notempty')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasOne = array(
|
||||||
|
'CurrentLedger' => array(
|
||||||
|
'className' => 'Ledger',
|
||||||
|
'conditions' => array('NOT' => array('CurrentLedger.closed'))
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'Ledger',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: type
|
||||||
|
* - Returns the type of this account
|
||||||
|
*/
|
||||||
|
function type($id) {
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$account = $this->find('first', array
|
||||||
|
('recursive' => -1,
|
||||||
|
'fields' => array('type'),
|
||||||
|
'conditions' => array(array('Account.id' => $id)),
|
||||||
|
));
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
|
||||||
|
return $account['Account']['type'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: fundamentalType
|
||||||
|
* - Returns the fundmental type of the account, credit or debit
|
||||||
|
*/
|
||||||
|
function fundamentalType($id_or_type) {
|
||||||
|
if (is_numeric($id_or_type))
|
||||||
|
$type = $this->type($id_or_type);
|
||||||
|
else
|
||||||
|
$type = $id_or_type;
|
||||||
|
|
||||||
|
// Asset and Expense accounts are debit accounts
|
||||||
|
if (in_array(strtoupper($type), array('ASSET', 'EXPENSE')))
|
||||||
|
return 'debit';
|
||||||
|
|
||||||
|
// Otherwise, it's a credit account
|
||||||
|
return 'credit';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: fundamentalOpposite
|
||||||
|
* - Returns the opposite fundmental type of the account, credit or debit
|
||||||
|
*/
|
||||||
|
function fundamentalOpposite($id_or_type) {
|
||||||
|
if (in_array(strtolower($id_or_type), array('credit', 'debit')))
|
||||||
|
$fund = $id_or_type;
|
||||||
|
else
|
||||||
|
$fund = $this->fundamentalType($id_or_type);
|
||||||
|
|
||||||
|
if ($fund == 'debit')
|
||||||
|
return 'credit';
|
||||||
|
|
||||||
|
return 'debit';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: accountNameToID
|
||||||
|
* - Returns the ID of the named account
|
||||||
|
*/
|
||||||
|
function accountNameToID($name) {
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$account = $this->find('first', array
|
||||||
|
('recursive' => -1,
|
||||||
|
'conditions' => compact('name'),
|
||||||
|
));
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
return $account['Account']['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
function securityDepositAccountID() { return $this->accountNameToID('Security Deposit'); }
|
||||||
|
function rentAccountID() { return $this->accountNameToID('Rent'); }
|
||||||
|
function accountReceivableAccountID() { return $this->accountNameToID('A/R'); }
|
||||||
|
function invoiceAccountID() { return $this->accountReceivableAccountID(); }
|
||||||
|
function receiptAccountID() { return $this->accountReceivableAccountID(); }
|
||||||
|
//function invoiceAccountID() { return $this->accountNameToID('Invoice'); }
|
||||||
|
//function receiptAccountID() { return $this->accountNameToID('Receipt'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: ledgers
|
||||||
|
* - Returns an array of ledger ids from the given account
|
||||||
|
*/
|
||||||
|
function ledgers($id, $all = false) {
|
||||||
|
if ($all) {
|
||||||
|
$contain = array('Ledger' => array('fields' => array('Ledger.id')));
|
||||||
|
} else {
|
||||||
|
$contain = array('CurrentLedger' => array('fields' => array('CurrentLedger.id')));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$account = $this->find('first', array
|
||||||
|
('contain' => $contain,
|
||||||
|
'fields' => array(),
|
||||||
|
'conditions' => array(array('Account.id' => $id)),
|
||||||
|
));
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
|
||||||
|
if ($all) {
|
||||||
|
$ledger_ids = array();
|
||||||
|
foreach ($account['Ledger'] AS $ledger)
|
||||||
|
array_push($ledger_ids, $ledger['id']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$ledger_ids = array($account['CurrentLedger']['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pr(array('function' => 'Account::ledgers', */
|
||||||
|
/* 'args' => compact('id', 'all'), */
|
||||||
|
/* 'return' => $ledger_ids)); */
|
||||||
|
|
||||||
|
return $ledger_ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: findLedgerEntries
|
||||||
|
* - Returns an array of ledger entries that belong to the given
|
||||||
|
* account, either just from the current ledger, or from all ledgers.
|
||||||
|
*/
|
||||||
|
function findLedgerEntries($id, $all = false, $cond = null, $link = null) {
|
||||||
|
/* pr(array('function' => 'Account::findLedgerEntries', */
|
||||||
|
/* 'args' => compact('id', 'all', 'cond', 'link'), */
|
||||||
|
/* )); */
|
||||||
|
|
||||||
|
$entries = array();
|
||||||
|
foreach ($this->ledgers($id, $all) AS $ledger_id) {
|
||||||
|
$ledger_entries = $this->Ledger->findLedgerEntries
|
||||||
|
($ledger_id, $this->type($id), $cond, $link);
|
||||||
|
$entries = array_merge($entries, $ledger_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
$stats = $this->stats($id, $all, $cond);
|
||||||
|
$entries = array('Entries' => $entries,
|
||||||
|
'summary' => $stats['Ledger']);
|
||||||
|
|
||||||
|
/* pr(array('function' => 'Account::findLedgerEntries', */
|
||||||
|
/* 'args' => compact('id', 'all', 'cond', 'link'), */
|
||||||
|
/* 'vars' => compact('stats'), */
|
||||||
|
/* 'return' => compact('entries'), */
|
||||||
|
/* )); */
|
||||||
|
|
||||||
|
return $entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: findLedgerEntriesRelatedToAccount
|
||||||
|
* - Returns an array of ledger entries that belong to the given
|
||||||
|
* account, and are related to a specific account, either just from
|
||||||
|
* the current ledger, or from all ledgers.
|
||||||
|
*/
|
||||||
|
function findLedgerEntriesRelatedToAccount($id, $rel_ids, $all = false, $cond = null, $link = null) {
|
||||||
|
/* pr(array('function' => 'Account::findLedgerEntriesRelatedToAccount', */
|
||||||
|
/* 'args' => compact('id', 'rel_ids', 'all', 'cond', 'link'), */
|
||||||
|
/* )); */
|
||||||
|
|
||||||
|
if (!isset($cond))
|
||||||
|
$cond = array();
|
||||||
|
if (!is_array($rel_ids))
|
||||||
|
$rel_ids = array($rel_ids);
|
||||||
|
|
||||||
|
$ledger_ids = array();
|
||||||
|
foreach ($rel_ids AS $rel_id)
|
||||||
|
$ledger_ids = array_merge($ledger_ids, $this->ledgers($rel_id));
|
||||||
|
|
||||||
|
array_push($cond, $this->Ledger->LedgerEntry->conditionEntryAsCreditOrDebit($ledger_ids));
|
||||||
|
$entries = $this->findLedgerEntries($id, $all, $cond, $link);
|
||||||
|
|
||||||
|
/* pr(array('function' => 'Account::findLedgerEntriesRelatedToAccount', */
|
||||||
|
/* 'args' => compact('id', 'relid', 'all', 'cond', 'link'), */
|
||||||
|
/* 'vars' => compact('ledger_ids'), */
|
||||||
|
/* 'return' => compact('entries'), */
|
||||||
|
/* )); */
|
||||||
|
return $entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: findUnreconciledLedgerEntries
|
||||||
|
* - Returns ledger entries that are not yet reconciled
|
||||||
|
* (such as charges not paid).
|
||||||
|
*/
|
||||||
|
|
||||||
|
function findUnreconciledLedgerEntries($id = null, $fundamental_type = null, $cond = null) {
|
||||||
|
if (!isset($cond))
|
||||||
|
$cond = array();
|
||||||
|
$cond[] = array('Account.id' => $id);
|
||||||
|
|
||||||
|
foreach (($fundamental_type
|
||||||
|
? array($fundamental_type)
|
||||||
|
: array('debit', 'credit')) AS $fund) {
|
||||||
|
$ucfund = ucfirst($fund);
|
||||||
|
$unreconciled[$fund]['entry'] = $this->find
|
||||||
|
('all', array
|
||||||
|
('link' => array
|
||||||
|
('Ledger' => array
|
||||||
|
('fields' => array(),
|
||||||
|
"LedgerEntry" => array
|
||||||
|
('class' => "{$ucfund}LedgerEntry",
|
||||||
|
'fields' => array('id', 'amount'),
|
||||||
|
"ReconciliationLedgerEntry" => array
|
||||||
|
('class' => "{$ucfund}ReconciliationLedgerEntry",
|
||||||
|
'fields' => array
|
||||||
|
("COALESCE(SUM(Reconciliation.amount),0) AS 'reconciled'",
|
||||||
|
"LedgerEntry.amount - COALESCE(SUM(Reconciliation.amount),0) AS 'balance'",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'group' => ("LedgerEntry.id" .
|
||||||
|
" HAVING LedgerEntry.amount" .
|
||||||
|
" <> COALESCE(SUM(Reconciliation.amount),0)"),
|
||||||
|
'conditions' => $cond,
|
||||||
|
'fields' => array(),
|
||||||
|
));
|
||||||
|
$balance = 0;
|
||||||
|
foreach ($unreconciled[$fund]['entry'] AS &$entry) {
|
||||||
|
$entry = array_merge(array_diff_key($entry["LedgerEntry"], array(0=>true)),
|
||||||
|
$entry[0]);
|
||||||
|
$balance += $entry['balance'];
|
||||||
|
}
|
||||||
|
$unreconciled[$fund]['balance'] = $balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $unreconciled;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: reconcileNewLedgerEntry
|
||||||
|
* - Returns which ledger entries a new credit/debit would
|
||||||
|
* reconcile, and how much.
|
||||||
|
*
|
||||||
|
* - REVISIT <AP> 20090617
|
||||||
|
* This should be subject to different algorithms, such
|
||||||
|
* as apply to oldest charges first, newest first, to fees
|
||||||
|
* before rent, etc. Until we get there, I'll hardcode
|
||||||
|
* whatever algorithm is simplest.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function reconcileNewLedgerEntry($id, $fundamental_type, $amount, $cond = null) {
|
||||||
|
$ofund = $this->fundamentalOpposite($fundamental_type);
|
||||||
|
$unreconciled = array($ofund => array('entry'=>array(), 'balance'=>0));
|
||||||
|
$applied = 0;
|
||||||
|
|
||||||
|
// if there is no money in the entry, it can reconcile nothing
|
||||||
|
// don't bother wasting time sifting ledger entries.
|
||||||
|
if ($amount > 0) {
|
||||||
|
$unreconciled = $this->findUnreconciledLedgerEntries($id, $ofund, $cond);
|
||||||
|
|
||||||
|
foreach ($unreconciled[$ofund]['entry'] AS $i => &$entry) {
|
||||||
|
// Determine if amount is sufficient to cover the entry
|
||||||
|
if ($amount > $entry['balance'])
|
||||||
|
$apply = $entry['balance'];
|
||||||
|
elseif ($amount > 0)
|
||||||
|
$apply = $amount;
|
||||||
|
else {
|
||||||
|
unset($unreconciled[$ofund]['entry'][$i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$entry['applied'] = $apply;
|
||||||
|
$entry['reconciled'] += $apply;
|
||||||
|
$entry['balance'] -= $apply;
|
||||||
|
$applied += $apply;
|
||||||
|
$amount -= $apply;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$unreconciled[$ofund]['unapplied'] = $amount;
|
||||||
|
$unreconciled[$ofund]['applied'] = $applied;
|
||||||
|
$unreconciled[$ofund]['balance'] -= $applied;
|
||||||
|
return $unreconciled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: stats
|
||||||
|
* - Returns summary data from the requested account.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function stats($id = null, $all = false, $cond = null) {
|
||||||
|
if (!$id)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// All old, closed ledgers MUST balance to 0.
|
||||||
|
// However, the user may want the ENTIRE running totals,
|
||||||
|
// (not just the balance), so we may have to query all
|
||||||
|
// ledgers, as dictated by the $all parameter.
|
||||||
|
|
||||||
|
$account = $this->find('first',
|
||||||
|
array('contain' =>
|
||||||
|
($all
|
||||||
|
? array('Ledger' => array
|
||||||
|
('fields' => array('id')))
|
||||||
|
: array('CurrentLedger' => array
|
||||||
|
('fields' => array('id')))
|
||||||
|
),
|
||||||
|
'conditions' => array
|
||||||
|
(array('Account.id' => $id))
|
||||||
|
));
|
||||||
|
|
||||||
|
$stats = array();
|
||||||
|
if ($all) {
|
||||||
|
foreach ($account['Ledger'] AS $ledger)
|
||||||
|
$this->statsMerge($stats['Ledger'],
|
||||||
|
$this->Ledger->stats($ledger['id'], $cond));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$stats['Ledger'] =
|
||||||
|
$this->Ledger->stats($account['CurrentLedger']['id'], $cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
@@ -85,28 +85,6 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
|
|
||||||
protected $_defaults = array('type' => 'LEFT');
|
protected $_defaults = array('type' => 'LEFT');
|
||||||
|
|
||||||
function pr($lev, $mixed) {
|
|
||||||
if ($lev >= 5)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pr($mixed);
|
|
||||||
return;
|
|
||||||
|
|
||||||
$trace = debug_backtrace(false);
|
|
||||||
//array_shift($trace);
|
|
||||||
$calls = array();
|
|
||||||
foreach ($trace AS $call) {
|
|
||||||
$call = array_intersect_key($call,
|
|
||||||
array('file'=>1,
|
|
||||||
'line'=>1,
|
|
||||||
//'class'=>1,
|
|
||||||
'function'=>1,
|
|
||||||
));
|
|
||||||
$calls[] = implode("; ", $call);
|
|
||||||
}
|
|
||||||
pr(array('debug' => $mixed, 'stack' => $calls));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a function for made recursive str_replaces in an array
|
* This is a function for made recursive str_replaces in an array
|
||||||
* NOTE: The palacement of this function is terrible, but I don't
|
* NOTE: The palacement of this function is terrible, but I don't
|
||||||
@@ -130,10 +108,7 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function beforeFind(&$Model, $query) {
|
public function beforeFind(&$Model, $query) {
|
||||||
$this->pr(10,
|
/* pr("Linkable::beforeFind() begin"); pr($query); */
|
||||||
array('function' => 'Linkable::beforeFind',
|
|
||||||
'args' => array('Model->alias' => '$Model->alias') + compact('query'),
|
|
||||||
));
|
|
||||||
if (isset($query[$this->_key])) {
|
if (isset($query[$this->_key])) {
|
||||||
$optionsDefaults = $this->_defaults + array('reference' =>
|
$optionsDefaults = $this->_defaults + array('reference' =>
|
||||||
array('class' => $Model->alias,
|
array('class' => $Model->alias,
|
||||||
@@ -157,10 +132,7 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
unset($iterator['defaults']);
|
unset($iterator['defaults']);
|
||||||
}
|
}
|
||||||
$iterations = Set::normalize($iterator);
|
$iterations = Set::normalize($iterator);
|
||||||
$this->pr(25,
|
/* pr(array('checkpoint' => 'Iterations', compact('iterations'))); */
|
||||||
array('checkpoint' => 'Iterations',
|
|
||||||
compact('iterations'),
|
|
||||||
));
|
|
||||||
foreach ($iterations as $alias => $options) {
|
foreach ($iterations as $alias => $options) {
|
||||||
if (is_null($options)) {
|
if (is_null($options)) {
|
||||||
$options = array();
|
$options = array();
|
||||||
@@ -173,15 +145,7 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
if (empty($options['class']))
|
if (empty($options['class']))
|
||||||
$options['class'] = $alias;
|
$options['class'] = $alias;
|
||||||
|
|
||||||
if (!isset($options['conditions']))
|
/* pr(array('checkpoint' => 'Begin Model Work', compact('alias', 'options'))); */
|
||||||
$options['conditions'] = array();
|
|
||||||
elseif (!is_array($options['conditions']))
|
|
||||||
$options['conditions'] = array($options['conditions']);
|
|
||||||
|
|
||||||
$this->pr(20,
|
|
||||||
array('checkpoint' => 'Begin Model Work',
|
|
||||||
compact('alias', 'options'),
|
|
||||||
));
|
|
||||||
|
|
||||||
$modelClass = $options['class'];
|
$modelClass = $options['class'];
|
||||||
$modelAlias = $options['alias'];
|
$modelAlias = $options['alias'];
|
||||||
@@ -190,13 +154,11 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
|
|
||||||
$_Model =& ClassRegistry::init($modelClass); // the incoming model to be linked in query
|
$_Model =& ClassRegistry::init($modelClass); // the incoming model to be linked in query
|
||||||
$Reference =& ClassRegistry::init($referenceClass); // the already in query model that links to $_Model
|
$Reference =& ClassRegistry::init($referenceClass); // the already in query model that links to $_Model
|
||||||
$this->pr(12,
|
/* pr(array('checkpoint' => 'Aliases Established', */
|
||||||
array('checkpoint' => 'Aliases Established',
|
/* 'Model' => ($modelAlias .' : '. $modelClass . */
|
||||||
'Model' => ($modelAlias .' : '. $modelClass .
|
/* ' ('. $_Model->alias .' : '. $_Model->name .')'), */
|
||||||
' ('. $_Model->alias .' : '. $_Model->name .')'),
|
/* 'Reference' => ($referenceAlias .' : '. $referenceClass . */
|
||||||
'Reference' => ($referenceAlias .' : '. $referenceClass .
|
/* ' ('. $Reference->alias .' : '. $Reference->name .')'))); */
|
||||||
' ('. $Reference->alias .' : '. $Reference->name .')'),
|
|
||||||
));
|
|
||||||
|
|
||||||
$db =& $_Model->getDataSource();
|
$db =& $_Model->getDataSource();
|
||||||
|
|
||||||
@@ -207,20 +169,20 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
// a relationship if one doesn't otherwise already exists.
|
// a relationship if one doesn't otherwise already exists.
|
||||||
if (($associations = $Reference->getAssociated()) &&
|
if (($associations = $Reference->getAssociated()) &&
|
||||||
isset($associations[$_Model->alias])) {
|
isset($associations[$_Model->alias])) {
|
||||||
$this->pr(12, array('checkpoint' => "Reference defines association to _Model"));
|
/* pr("Reference defines association to _Model"); */
|
||||||
$associatedThroughReference = 1;
|
$associatedThroughReference = 1;
|
||||||
$type = $associations[$_Model->alias];
|
$type = $associations[$_Model->alias];
|
||||||
$association = $Reference->{$type}[$_Model->alias];
|
$association = $Reference->{$type}[$_Model->alias];
|
||||||
}
|
}
|
||||||
elseif (($associations = $_Model->getAssociated()) &&
|
elseif (($associations = $_Model->getAssociated()) &&
|
||||||
isset($associations[$Reference->alias])) {
|
isset($associations[$Reference->alias])) {
|
||||||
$this->pr(12, array('checkpoint' => "_Model defines association to Reference"));
|
/* pr("_Model defines association to Reference"); */
|
||||||
$type = $associations[$Reference->alias];
|
$type = $associations[$Reference->alias];
|
||||||
$association = $_Model->{$type}[$Reference->alias];
|
$association = $_Model->{$type}[$Reference->alias];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// No relationship... make our best effort to create one.
|
// No relationship... make our best effort to create one.
|
||||||
$this->pr(12, array('checkpoint' => "No assocation between _Model and Reference"));
|
/* pr("No assocation between _Model and Reference"); */
|
||||||
$type = 'belongsTo';
|
$type = 'belongsTo';
|
||||||
$_Model->bind($Reference->alias);
|
$_Model->bind($Reference->alias);
|
||||||
// Grab the association now, since we'll unbind in a moment.
|
// Grab the association now, since we'll unbind in a moment.
|
||||||
@@ -250,13 +212,12 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
$associationAlias,
|
$associationAlias,
|
||||||
$association['conditions']);
|
$association['conditions']);
|
||||||
|
|
||||||
$this->pr(15,
|
/* pr(array('checkpoint' => 'Models Established - Check Associations', */
|
||||||
array('checkpoint' => 'Models Established - Check Associations',
|
/* 'primaryModel' => $primaryAlias .' : '. $primaryModel->name, */
|
||||||
'primaryModel' => $primaryAlias .' : '. $primaryModel->name,
|
/* 'foreignModel' => $foreignAlias .' : '. $foreignModel->name, */
|
||||||
'foreignModel' => $foreignAlias .' : '. $foreignModel->name,
|
/* compact('type', 'association'))); */
|
||||||
compact('type', 'association'),
|
|
||||||
));
|
|
||||||
|
|
||||||
|
if (empty($options['conditions'])) {
|
||||||
if ($type === 'hasAndBelongsToMany') {
|
if ($type === 'hasAndBelongsToMany') {
|
||||||
if (isset($association['with']))
|
if (isset($association['with']))
|
||||||
$linkClass = $association['with'];
|
$linkClass = $association['with'];
|
||||||
@@ -270,11 +231,6 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
else
|
else
|
||||||
$linkAlias = $Link->alias;
|
$linkAlias = $Link->alias;
|
||||||
|
|
||||||
$this->pr(17,
|
|
||||||
array('checkpoint' => 'Linking HABTM',
|
|
||||||
compact('linkClass', 'linkAlias'),
|
|
||||||
));
|
|
||||||
|
|
||||||
// Get the foreign key fields (for the link table) directly from
|
// Get the foreign key fields (for the link table) directly from
|
||||||
// the defined model associations, if they exists. This is the
|
// the defined model associations, if they exists. This is the
|
||||||
// users direct specification, and therefore definitive if present.
|
// users direct specification, and therefore definitive if present.
|
||||||
@@ -323,11 +279,6 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
$foreignKey = $primaryModel->escapeField($association['foreignKey'], $primaryAlias);
|
$foreignKey = $primaryModel->escapeField($association['foreignKey'], $primaryAlias);
|
||||||
$primaryKey = $foreignModel->escapeField($foreignModel->primaryKey, $foreignAlias);
|
$primaryKey = $foreignModel->escapeField($foreignModel->primaryKey, $foreignAlias);
|
||||||
|
|
||||||
$this->pr(17,
|
|
||||||
array('checkpoint' => 'Linking due to foreignKey',
|
|
||||||
compact('foreignKey', 'primaryKey'),
|
|
||||||
));
|
|
||||||
|
|
||||||
// Only differentiating to help show the logical flow.
|
// Only differentiating to help show the logical flow.
|
||||||
// Either way works and this test can be tossed out
|
// Either way works and this test can be tossed out
|
||||||
if (($type === 'hasMany' || $type === 'hasOne') ^ $associatedThroughReference)
|
if (($type === 'hasMany' || $type === 'hasOne') ^ $associatedThroughReference)
|
||||||
@@ -336,20 +287,10 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
$options['conditions'][] = "{$foreignKey} = {$primaryKey}";
|
$options['conditions'][] = "{$foreignKey} = {$primaryKey}";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$this->pr(17,
|
|
||||||
array('checkpoint' => 'Linking with no logic (expecting user defined)',
|
|
||||||
));
|
|
||||||
|
|
||||||
// No Foreign Key... nothing we can do.
|
// No Foreign Key... nothing we can do.
|
||||||
|
$options['conditions'] = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->pr(19,
|
|
||||||
array('checkpoint' => 'Conditions',
|
|
||||||
array('options[conditions]' => $options['conditions'],
|
|
||||||
'association[conditions]' => $association['conditions'],
|
|
||||||
),
|
|
||||||
));
|
|
||||||
|
|
||||||
// The user may have specified conditions directly in the model
|
// The user may have specified conditions directly in the model
|
||||||
// for this join. Make sure to adhere to those conditions.
|
// for this join. Make sure to adhere to those conditions.
|
||||||
if (isset($association['conditions']) && is_array($association['conditions']))
|
if (isset($association['conditions']) && is_array($association['conditions']))
|
||||||
@@ -357,12 +298,7 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
elseif (!empty($association['conditions']))
|
elseif (!empty($association['conditions']))
|
||||||
$options['conditions'][] = $association['conditions'];
|
$options['conditions'][] = $association['conditions'];
|
||||||
|
|
||||||
$this->pr(19,
|
}
|
||||||
array('checkpoint' => 'Conditions2',
|
|
||||||
array('options[conditions]' => $options['conditions'],
|
|
||||||
),
|
|
||||||
));
|
|
||||||
|
|
||||||
if (empty($options['table'])) {
|
if (empty($options['table'])) {
|
||||||
$options['table'] = $db->fullTableName($_Model, true);
|
$options['table'] = $db->fullTableName($_Model, true);
|
||||||
}
|
}
|
||||||
@@ -376,6 +312,8 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
(empty($association['fields'])
|
(empty($association['fields'])
|
||||||
? array() : $db->fields($_Model, $modelAlias, $association['fields'])));
|
? array() : $db->fields($_Model, $modelAlias, $association['fields'])));
|
||||||
|
|
||||||
|
/* pr(array('checkpoint' => 'Model Work Complete', compact('options', 'modelClass', 'modelAlias'))); */
|
||||||
|
|
||||||
$options[$this->_key] = am($options[$this->_key], array_diff_key($options, $optionsKeys));
|
$options[$this->_key] = am($options[$this->_key], array_diff_key($options, $optionsKeys));
|
||||||
$options = array_intersect_key($options, $optionsKeys);
|
$options = array_intersect_key($options, $optionsKeys);
|
||||||
if (!empty($options[$this->_key])) {
|
if (!empty($options[$this->_key])) {
|
||||||
@@ -387,20 +325,13 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
'alias' => $modelAlias))));
|
'alias' => $modelAlias))));
|
||||||
}
|
}
|
||||||
$query['joins'][] = array_intersect_key($options, array('type' => true, 'alias' => true, 'table' => true, 'joins' => true, 'conditions' => true));
|
$query['joins'][] = array_intersect_key($options, array('type' => true, 'alias' => true, 'table' => true, 'joins' => true, 'conditions' => true));
|
||||||
|
|
||||||
$this->pr(19,
|
|
||||||
array('checkpoint' => 'Model Join Complete',
|
|
||||||
compact('options', 'modelClass', 'modelAlias', 'query'),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
++$cont;
|
++$cont;
|
||||||
$notDone = isset($iterators[$cont]);
|
$notDone = isset($iterators[$cont]);
|
||||||
} while ($notDone);
|
} while ($notDone);
|
||||||
}
|
}
|
||||||
$this->pr(20,
|
/* pr(array('checkpoint' => 'Linkable::beforeFind() end', */
|
||||||
array('function' => 'Linkable::beforeFind',
|
/* compact('query'))); */
|
||||||
'return' => compact('query'),
|
|
||||||
));
|
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
class Contact extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'Contact';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'display_name' => array('notempty'),
|
||||||
|
'id_federal' => array('ssn'),
|
||||||
|
'id_exp' => array('date')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasAndBelongsToMany = array(
|
||||||
|
'Customer',
|
||||||
|
'ContactAddress' => array(
|
||||||
|
'joinTable' => 'contacts_methods',
|
||||||
|
'associationForeignKey' => 'method_id',
|
||||||
|
'unique' => true,
|
||||||
|
'conditions' => "method = 'POST'",
|
||||||
|
),
|
||||||
|
'ContactPhone' => array(
|
||||||
|
'joinTable' => 'contacts_methods',
|
||||||
|
'associationForeignKey' => 'method_id',
|
||||||
|
'unique' => true,
|
||||||
|
'conditions' => "method = 'PHONE'",
|
||||||
|
),
|
||||||
|
'ContactEmail' => array(
|
||||||
|
'joinTable' => 'contacts_methods',
|
||||||
|
'associationForeignKey' => 'method_id',
|
||||||
|
'unique' => true,
|
||||||
|
'conditions' => "method = 'EMAIL'",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
class ContactAddress extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'ContactAddress';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'postcode' => array('postal')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasAndBelongsToMany = array(
|
||||||
|
'Contact' => array(
|
||||||
|
'className' => 'Contact',
|
||||||
|
'joinTable' => 'contacts_methods',
|
||||||
|
'foreignKey' => 'method_id',
|
||||||
|
'associationForeignKey' => 'contact_id',
|
||||||
|
'unique' => true,
|
||||||
|
'conditions' => "method = 'POST'",
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
?>
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
class ContactEmail extends AppModel {
|
class ContactEmail extends AppModel {
|
||||||
|
|
||||||
var $name = 'ContactEmail';
|
var $name = 'ContactEmail';
|
||||||
var $displayField = 'email';
|
|
||||||
var $validate = array(
|
var $validate = array(
|
||||||
'id' => array('numeric'),
|
'id' => array('numeric'),
|
||||||
'email' => array('email')
|
'email' => array('email')
|
||||||
@@ -19,9 +18,5 @@ class ContactEmail extends AppModel {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
function emailList() {
|
|
||||||
return $this->find('list');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
class ContactPhone extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'ContactPhone';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
//'type' => array('inlist'),
|
||||||
|
'phone' => array('phone'),
|
||||||
|
'ext' => array('numeric')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasAndBelongsToMany = array(
|
||||||
|
'Contact' => array(
|
||||||
|
'className' => 'Contact',
|
||||||
|
'joinTable' => 'contacts_methods',
|
||||||
|
'foreignKey' => 'method_id',
|
||||||
|
'associationForeignKey' => 'contact_id',
|
||||||
|
'unique' => true,
|
||||||
|
'conditions' => "method = 'PHONE'",
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
@@ -20,7 +20,9 @@ class Customer extends AppModel {
|
|||||||
),
|
),
|
||||||
'Lease',
|
'Lease',
|
||||||
'LedgerEntry',
|
'LedgerEntry',
|
||||||
'ContactsCustomer',
|
|
||||||
|
// Cheat to get Account set as part of this class
|
||||||
|
'Account',
|
||||||
);
|
);
|
||||||
|
|
||||||
var $hasAndBelongsToMany = array(
|
var $hasAndBelongsToMany = array(
|
||||||
@@ -84,9 +86,9 @@ class Customer extends AppModel {
|
|||||||
/* 'args' => compact('id', 'link'), */
|
/* 'args' => compact('id', 'link'), */
|
||||||
/* )); */
|
/* )); */
|
||||||
|
|
||||||
$A = new Account();
|
$entries = $this->Account->findLedgerEntriesRelatedToAccount
|
||||||
$entries = $A->findLedgerEntries
|
($this->Account->invoiceAccountID(),
|
||||||
($A->securityDepositAccountID(),
|
$this->Account->securityDepositAccountID(),
|
||||||
true, array('LedgerEntry.customer_id' => $id), $link);
|
true, array('LedgerEntry.customer_id' => $id), $link);
|
||||||
|
|
||||||
/* pr(array('function' => 'Customer::findSecurityDeposits', */
|
/* pr(array('function' => 'Customer::findSecurityDeposits', */
|
||||||
@@ -108,9 +110,8 @@ class Customer extends AppModel {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function findUnreconciledLedgerEntries($id = null, $fundamental_type = null) {
|
function findUnreconciledLedgerEntries($id = null, $fundamental_type = null) {
|
||||||
$A = new Account();
|
$unreconciled = $this->Account->findUnreconciledLedgerEntries
|
||||||
$unreconciled = $A->findUnreconciledLedgerEntries
|
($this->Account->accountReceivableAccountID(),
|
||||||
($A->accountReceivableAccountID(),
|
|
||||||
$fundamental_type,
|
$fundamental_type,
|
||||||
array('LedgerEntry.customer_id' => $id));
|
array('LedgerEntry.customer_id' => $id));
|
||||||
|
|
||||||
@@ -133,9 +134,8 @@ class Customer extends AppModel {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function reconcileNewLedgerEntry($id, $fundamental_type, $amount) {
|
function reconcileNewLedgerEntry($id, $fundamental_type, $amount) {
|
||||||
$A = new Account();
|
$reconciled = $this->Account->reconcileNewLedgerEntry
|
||||||
$reconciled = $A->reconcileNewLedgerEntry
|
($this->Account->accountReceivableAccountID(),
|
||||||
($A->accountReceivableAccountID(),
|
|
||||||
$fundamental_type,
|
$fundamental_type,
|
||||||
$amount,
|
$amount,
|
||||||
array('LedgerEntry.customer_id' => $id));
|
array('LedgerEntry.customer_id' => $id));
|
||||||
@@ -158,8 +158,7 @@ class Customer extends AppModel {
|
|||||||
('contain' => array
|
('contain' => array
|
||||||
(// Models
|
(// Models
|
||||||
'Contact' =>
|
'Contact' =>
|
||||||
array('order' => array('Contact.display_name'),
|
array(// Models
|
||||||
// Models
|
|
||||||
'ContactPhone',
|
'ContactPhone',
|
||||||
'ContactEmail',
|
'ContactEmail',
|
||||||
'ContactAddress',
|
'ContactAddress',
|
||||||
@@ -185,82 +184,6 @@ class Customer extends AppModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: saveCustomer
|
|
||||||
* - Saves the customer and related data
|
|
||||||
*/
|
|
||||||
|
|
||||||
function saveCustomer($id, $data, $primary_contact_entry) {
|
|
||||||
|
|
||||||
// Go through each contact, and create new ones as needed
|
|
||||||
foreach ($data['Contact'] AS &$contact) {
|
|
||||||
if (isset($contact['id']))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
$I = new Contact();
|
|
||||||
$I->create();
|
|
||||||
if (!$I->save($contact, false)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$contact['id'] = $I->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the primary contact ID based on caller selection
|
|
||||||
$data['Customer']['primary_contact_id']
|
|
||||||
= $data['Contact'][$primary_contact_entry]['id'];
|
|
||||||
|
|
||||||
// Provide a default customer name if not specified
|
|
||||||
if (!$data['Customer']['name']) {
|
|
||||||
$this->Contact->recursive = -1;
|
|
||||||
$pcontact = $this->Contact->read(null, $data['Customer']['primary_contact_id']);
|
|
||||||
$data['Customer']['name'] = $pcontact['Contact']['display_name'];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the customer data
|
|
||||||
$this->create();
|
|
||||||
if ($id)
|
|
||||||
$this->id = $id;
|
|
||||||
if (!$this->save($data, false)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$id = $this->id;
|
|
||||||
|
|
||||||
// Remove all associated Customer Contacts, as it ensures
|
|
||||||
// any entries deleted by the user actually get deleted
|
|
||||||
// in the system. We'll recreate the needed ones anyway.
|
|
||||||
// REVISIT <AP>: 20090706
|
|
||||||
// Appears that $this->save() is already doing the
|
|
||||||
// delete. I would have thought this would only happen
|
|
||||||
// on a saveAll??
|
|
||||||
/* $this->ContactsCustomer->deleteAll */
|
|
||||||
/* (array('customer_id' => $id), false); */
|
|
||||||
|
|
||||||
// At this point, since we've saved data to customer,
|
|
||||||
// we'll proceed forward as much as possible, even
|
|
||||||
// if we encounter an error. For now, we'll assume
|
|
||||||
// the operation will succeed.
|
|
||||||
$ret = true;
|
|
||||||
|
|
||||||
// Go through each entry of this customer method
|
|
||||||
foreach ($data['Contact'] AS &$contact) {
|
|
||||||
// Update the ContactsCustomer to reflect the appropriate IDs
|
|
||||||
$contact['ContactsCustomer']['customer_id'] = $id;
|
|
||||||
$contact['ContactsCustomer']['contact_id'] = $contact['id'];
|
|
||||||
|
|
||||||
// Save the relationship between customer and contact
|
|
||||||
$CM = new ContactsCustomer();
|
|
||||||
if (!$CM->save($contact['ContactsCustomer'], false)) {
|
|
||||||
$ret = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the result
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -272,8 +195,7 @@ class Customer extends AppModel {
|
|||||||
if (!$id)
|
if (!$id)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
$A = new Account();
|
$stats = $this->Account->stats($this->Account->accountReceivableAccountID(), true,
|
||||||
$stats = $A->stats($A->accountReceivableAccountID(), true,
|
|
||||||
array('LedgerEntry.customer_id' => $id));
|
array('LedgerEntry.customer_id' => $id));
|
||||||
|
|
||||||
// Pull to the top level and return
|
// Pull to the top level and return
|
||||||
@@ -0,0 +1,158 @@
|
|||||||
|
<?php
|
||||||
|
class Lease extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'Lease';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'number' => array('alphanumeric'),
|
||||||
|
'lease_type_id' => array('numeric'),
|
||||||
|
'unit_id' => array('numeric'),
|
||||||
|
'late_schedule_id' => array('numeric'),
|
||||||
|
'lease_date' => array('date'),
|
||||||
|
'movein_planned_date' => array('date'),
|
||||||
|
'movein_date' => array('date'),
|
||||||
|
'moveout_date' => array('date'),
|
||||||
|
'moveout_planned_date' => array('date'),
|
||||||
|
'notice_given_date' => array('date'),
|
||||||
|
'notice_received_date' => array('date'),
|
||||||
|
'close_date' => array('date'),
|
||||||
|
'deposit' => array('money'),
|
||||||
|
'amount' => array('money'),
|
||||||
|
'next_amount' => array('money'),
|
||||||
|
'next_amount_date' => array('date')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'LeaseType',
|
||||||
|
'Unit',
|
||||||
|
'Customer',
|
||||||
|
'LateSchedule',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'LedgerEntry',
|
||||||
|
|
||||||
|
// Cheat to get Account set as part of this class
|
||||||
|
'Account',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: accountId
|
||||||
|
* - Returns the accountId of the given lease
|
||||||
|
*/
|
||||||
|
function accountId($id) {
|
||||||
|
return $this->Account->invoiceAccountID();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: findAccountEntries
|
||||||
|
* - Returns an array of ledger entries from the account of the given
|
||||||
|
* lease.
|
||||||
|
*/
|
||||||
|
function findAccountEntries($id, $all = false, $cond = null, $link = null) {
|
||||||
|
/* pr(array('function' => 'Lease::findAccountEntries', */
|
||||||
|
/* 'args' => compact('id', 'all', 'cond', 'link'), */
|
||||||
|
/* )); */
|
||||||
|
|
||||||
|
if (!isset($cond))
|
||||||
|
$cond = array();
|
||||||
|
$cond[] = array('LedgerEntry.lease_id' => $id);
|
||||||
|
|
||||||
|
$entries = $this->Account->findLedgerEntries($this->accountId($id),
|
||||||
|
$all, $cond, $link);
|
||||||
|
|
||||||
|
/* pr(array('function' => 'Lease::findAccountEntries', */
|
||||||
|
/* 'args' => compact('id', 'all', 'cond', 'link'), */
|
||||||
|
/* 'vars' => compact('lease'), */
|
||||||
|
/* 'return' => compact('entries'), */
|
||||||
|
/* )); */
|
||||||
|
return $entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: findSecurityDeposits
|
||||||
|
* - Returns an array of security deposit entries
|
||||||
|
*/
|
||||||
|
function findSecurityDeposits($id, $link = null) {
|
||||||
|
/* pr(array('function' => 'Lease::findSecurityDeposits', */
|
||||||
|
/* 'args' => compact('id', 'link'), */
|
||||||
|
/* )); */
|
||||||
|
|
||||||
|
$entries = $this->Account->findLedgerEntriesRelatedToAccount
|
||||||
|
($this->accountId($id),
|
||||||
|
$this->Account->securityDepositAccountID(),
|
||||||
|
true, array('LedgerEntry.lease_id' => $id), $link);
|
||||||
|
|
||||||
|
/* pr(array('function' => 'Lease::findSecurityDeposits', */
|
||||||
|
/* 'args' => compact('id', 'link'), */
|
||||||
|
/* 'vars' => compact('lease'), */
|
||||||
|
/* 'return' => compact('entries'), */
|
||||||
|
/* )); */
|
||||||
|
return $entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: findUnreconciledLedgerEntries
|
||||||
|
* - Returns ledger entries that are not yet reconciled
|
||||||
|
* (such as charges not paid).
|
||||||
|
*/
|
||||||
|
|
||||||
|
function findUnreconciledLedgerEntries($id = null, $fundamental_type = null) {
|
||||||
|
return $this->Account->findUnreconciledLedgerEntries
|
||||||
|
($this->accountId($id), $fundamental_type, array('LedgerEntry.lease_id' => $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: reconcileNewLedgerEntry
|
||||||
|
* - Returns which ledger entries a new credit/debit would
|
||||||
|
* reconcile, and how much.
|
||||||
|
*
|
||||||
|
* - REVISIT <AP> 20090617
|
||||||
|
* This should be subject to different algorithms, such
|
||||||
|
* as apply to oldest charges first, newest first, to fees
|
||||||
|
* before rent, etc. Until we get there, I'll hardcode
|
||||||
|
* whatever algorithm is simplest.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function reconcileNewLedgerEntry($id, $fundamental_type, $amount) {
|
||||||
|
return $this->Account->reconcileNewLedgerEntry
|
||||||
|
($this->accountId($id), $fundamental_type, $amount, array('LedgerEntry.lease_id' => $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: stats
|
||||||
|
* - Returns summary data from the requested lease.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function stats($id = null) {
|
||||||
|
if (!$id)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
$stats = $this->Account->stats($this->Account->accountReceivableAccountID(), true,
|
||||||
|
array('LedgerEntry.lease_id' => $id));
|
||||||
|
|
||||||
|
// Pull to the top level and return
|
||||||
|
$stats = $stats['Ledger'];
|
||||||
|
return $stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
@@ -9,8 +9,6 @@ class Ledger extends AppModel {
|
|||||||
|
|
||||||
var $belongsTo = array(
|
var $belongsTo = array(
|
||||||
'Account',
|
'Account',
|
||||||
'PriorLedger' => array('className' => 'Ledger'),
|
|
||||||
'Close',
|
|
||||||
);
|
);
|
||||||
|
|
||||||
var $hasMany = array(
|
var $hasMany = array(
|
||||||
@@ -46,94 +44,6 @@ class Ledger extends AppModel {
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: accountID
|
|
||||||
* - Returns the account ID for the given ledger
|
|
||||||
*/
|
|
||||||
function accountID($id) {
|
|
||||||
$this->cacheQueries = true;
|
|
||||||
$item = $this->find('first', array
|
|
||||||
('contain' => 'Account.id',
|
|
||||||
'conditions' => array('Ledger.id' => $id),
|
|
||||||
));
|
|
||||||
$this->cacheQueries = false;
|
|
||||||
return $item['Account']['id'];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: currentLedgerID
|
|
||||||
* - Returns the current ledger ID of the account for the given ledger.
|
|
||||||
*/
|
|
||||||
function currentLedgerID($id) {
|
|
||||||
return $this->Account->currentLedgerID($this->accountID($id));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: closeLedger
|
|
||||||
* - Closes the current ledger, and returns a fresh one
|
|
||||||
*/
|
|
||||||
function closeLedger($id, $close_id) {
|
|
||||||
$this->recursive = -1;
|
|
||||||
|
|
||||||
$stamp = date('Y-m-d G:i:s');
|
|
||||||
$this->id = $id;
|
|
||||||
$this->read();
|
|
||||||
$this->data['Ledger']['close_id'] = $close_id;
|
|
||||||
$this->save($this->data, false);
|
|
||||||
|
|
||||||
$stats = $this->stats($id);
|
|
||||||
|
|
||||||
$this->read();
|
|
||||||
$this->data['Ledger']['id'] = null;
|
|
||||||
$this->data['Ledger']['close_id'] = null;
|
|
||||||
$this->data['Ledger']['prior_ledger_id'] = $id;
|
|
||||||
$this->data['Ledger']['comment'] = null;
|
|
||||||
++$this->data['Ledger']['sequence'];
|
|
||||||
$this->id = null;
|
|
||||||
$this->save($this->data, false);
|
|
||||||
//pr($this->data);
|
|
||||||
|
|
||||||
if ($stats['balance'] == 0)
|
|
||||||
return $this->id;
|
|
||||||
|
|
||||||
$this->read();
|
|
||||||
$ftype = $this->Account->fundamentalType($this->data['Ledger']['account_id']);
|
|
||||||
$otype = $this->Account->fundamentalOpposite($ftype);
|
|
||||||
|
|
||||||
// Create a transaction for balance transfer
|
|
||||||
$transaction = new Transaction();
|
|
||||||
$transaction->create();
|
|
||||||
if (!$transaction->save(array(), false)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create an entry to carry the balance forward
|
|
||||||
$carry_entry_data = array
|
|
||||||
($ftype.'_ledger_id' => $this->id,
|
|
||||||
$otype.'_ledger_id' => $id,
|
|
||||||
'transaction_id' => $transaction->id,
|
|
||||||
'amount' => $stats['balance'],
|
|
||||||
'comment' => "Ledger Balance Forward",
|
|
||||||
);
|
|
||||||
|
|
||||||
$carry_entry = new LedgerEntry();
|
|
||||||
$carry_entry->create();
|
|
||||||
if (!$carry_entry->save($carry_entry_data, false)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -237,13 +147,7 @@ class Ledger extends AppModel {
|
|||||||
|
|
||||||
// The fields are all tucked into the [0] index,
|
// The fields are all tucked into the [0] index,
|
||||||
// and the rest of the array is useless (empty).
|
// and the rest of the array is useless (empty).
|
||||||
$stats = $stats[0];
|
return $stats[0];
|
||||||
|
|
||||||
// Make sure we have a non-null balance
|
|
||||||
if (!isset($stats['balance']))
|
|
||||||
$stats['balance'] = 0;
|
|
||||||
|
|
||||||
return $stats;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,242 @@
|
|||||||
|
<?php
|
||||||
|
class LedgerEntry extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'LedgerEntry';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'transaction_id' => array('numeric'),
|
||||||
|
'amount' => array('money')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'MonetarySource',
|
||||||
|
'Transaction',
|
||||||
|
'Customer',
|
||||||
|
'Lease',
|
||||||
|
|
||||||
|
'DebitLedger' => array(
|
||||||
|
'className' => 'Ledger',
|
||||||
|
'foreignKey' => 'debit_ledger_id',
|
||||||
|
),
|
||||||
|
'CreditLedger' => array(
|
||||||
|
'className' => 'Ledger',
|
||||||
|
'foreignKey' => 'credit_ledger_id',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasAndBelongsToMany = array(
|
||||||
|
'DebitReconciliationLedgerEntry' => array(
|
||||||
|
'className' => 'LedgerEntry',
|
||||||
|
'joinTable' => 'reconciliations',
|
||||||
|
'foreignKey' => 'credit_ledger_entry_id',
|
||||||
|
'associationForeignKey' => 'debit_ledger_entry_id',
|
||||||
|
),
|
||||||
|
'CreditReconciliationLedgerEntry' => array(
|
||||||
|
'className' => 'LedgerEntry',
|
||||||
|
'joinTable' => 'reconciliations',
|
||||||
|
'foreignKey' => 'debit_ledger_entry_id',
|
||||||
|
'associationForeignKey' => 'credit_ledger_entry_id',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: conditionEntryAsCreditOrDebit
|
||||||
|
* - returns the condition necessary to match a set of
|
||||||
|
* Ledgers to all related LedgerEntries
|
||||||
|
*/
|
||||||
|
function conditionEntryAsCreditOrDebit($ledger_ids) {
|
||||||
|
return array('OR' =>
|
||||||
|
array(array('debit_ledger_id' => $ledger_ids),
|
||||||
|
array('credit_ledger_id' => $ledger_ids)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: ledgerContext query helpers
|
||||||
|
* - Returns parameters necessary to generate a query which
|
||||||
|
* puts ledger entries into the context of a ledger. Since
|
||||||
|
* debit/credit depends on the account type, it is required
|
||||||
|
* as an argument for each function to avoid having to
|
||||||
|
* query the ledger/account to find it out.
|
||||||
|
*/
|
||||||
|
function ledgerContextFields($ledger_id = null, $account_type = null) {
|
||||||
|
$fields = array('id', 'name', 'comment', 'amount');
|
||||||
|
|
||||||
|
if (isset($ledger_id)) {
|
||||||
|
$fields[] = ("IF(LedgerEntry.debit_ledger_id = $ledger_id," .
|
||||||
|
" LedgerEntry.amount, NULL) AS debit");
|
||||||
|
$fields[] = ("IF(LedgerEntry.credit_ledger_id = $ledger_id," .
|
||||||
|
" LedgerEntry.amount, NULL) AS credit");
|
||||||
|
|
||||||
|
if (isset($account_type)) {
|
||||||
|
if (in_array($account_type, array('ASSET', 'EXPENSE')))
|
||||||
|
$ledger_type = 'debit';
|
||||||
|
else
|
||||||
|
$ledger_type = 'credit';
|
||||||
|
|
||||||
|
$fields[] = ("(IF(LedgerEntry.{$ledger_type}_ledger_id = $ledger_id," .
|
||||||
|
" 1, -1) * LedgerEntry.amount) AS balance");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ledgerContextFields2($ledger_id = null, $account_id = null, $account_type = null) {
|
||||||
|
$fields = array('id', 'name', 'comment', 'amount');
|
||||||
|
|
||||||
|
if (isset($ledger_id)) {
|
||||||
|
$fields[] = ("IF(LedgerEntry.debit_ledger_id = $ledger_id," .
|
||||||
|
" SUM(LedgerEntry.amount), NULL) AS debit");
|
||||||
|
$fields[] = ("IF(LedgerEntry.credit_ledger_id = $ledger_id," .
|
||||||
|
" SUM(LedgerEntry.amount), NULL) AS credit");
|
||||||
|
|
||||||
|
if (isset($account_id) || isset($account_type)) {
|
||||||
|
$Account = new Account();
|
||||||
|
$account_ftype = $Account->fundamentalType($account_id ? $account_id : $account_type);
|
||||||
|
$fields[] = ("(IF(LedgerEntry.{$account_ftype}_ledger_id = $ledger_id," .
|
||||||
|
" 1, -1) * SUM(LedgerEntry.amount)) AS balance");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif (isset($account_id)) {
|
||||||
|
$fields[] = ("IF(DebitLedger.account_id = $account_id," .
|
||||||
|
" SUM(LedgerEntry.amount), NULL) AS debit");
|
||||||
|
$fields[] = ("IF(CreditLedger.account_id = $account_id," .
|
||||||
|
" SUM(LedgerEntry.amount), NULL) AS credit");
|
||||||
|
|
||||||
|
$Account = new Account();
|
||||||
|
$account_ftype = ucfirst($Account->fundamentalType($account_id));
|
||||||
|
$fields[] = ("(IF({$account_ftype}Ledger.account_id = $account_id," .
|
||||||
|
" 1, -1) * SUM(LedgerEntry.amount)) AS balance");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function ledgerContextConditions($ledger_id, $account_type) {
|
||||||
|
if (isset($ledger_id)) {
|
||||||
|
return array
|
||||||
|
('OR' =>
|
||||||
|
array(array('LedgerEntry.debit_ledger_id' => $ledger_id),
|
||||||
|
array('LedgerEntry.credit_ledger_id' => $ledger_id)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: findInLedgerContext
|
||||||
|
* - Returns an array of ledger entries that belong to a given ledger.
|
||||||
|
* There is extra logic to also figure out whether the ledger_entry
|
||||||
|
* amount is either a credit, or a debit, depending on how it was
|
||||||
|
* written into the ledger, as well as whether the amount increases or
|
||||||
|
* decreases the balance depending on the particular account type of
|
||||||
|
* the ledger.
|
||||||
|
*/
|
||||||
|
function findInLedgerContext($ledger_id, $account_type, $cond = null, $link = null) {
|
||||||
|
if (!isset($link))
|
||||||
|
$link = array('Transaction');
|
||||||
|
|
||||||
|
if (!isset($cond))
|
||||||
|
$cond = array();
|
||||||
|
|
||||||
|
$fields = $this->ledgerContextFields($ledger_id, $account_type);
|
||||||
|
$cond[] = $this->ledgerContextConditions($ledger_id, $account_type);
|
||||||
|
$order = array('Transaction.stamp');
|
||||||
|
|
||||||
|
$entries = $this->find
|
||||||
|
('all',
|
||||||
|
array('link' => $link,
|
||||||
|
'fields' => $fields,
|
||||||
|
'conditions' => $cond,
|
||||||
|
'order' => $order,
|
||||||
|
));
|
||||||
|
|
||||||
|
return $entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: findReconciledLedgerEntries
|
||||||
|
* - Returns ledger entries that are reconciled to the given entry.
|
||||||
|
* (such as payments towards a charge).
|
||||||
|
*/
|
||||||
|
|
||||||
|
function findReconciledLedgerEntries($id = null, $fundamental_type = null) {
|
||||||
|
foreach (($fundamental_type
|
||||||
|
? array($fundamental_type)
|
||||||
|
: array('debit', 'credit')) AS $fund) {
|
||||||
|
$ucfund = ucfirst($fund);
|
||||||
|
$reconciled[$fund]['entry'] = $this->find
|
||||||
|
('all', array
|
||||||
|
('link' => array
|
||||||
|
("ReconciliationLedgerEntry" => array
|
||||||
|
('class' => "{$ucfund}ReconciliationLedgerEntry",
|
||||||
|
'fields' => array
|
||||||
|
('id',
|
||||||
|
"COALESCE(SUM(Reconciliation.amount),0) AS 'reconciled'",
|
||||||
|
"LedgerEntry.amount - COALESCE(SUM(Reconciliation.amount),0) AS 'balance'",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'group' => ("ReconciliationLedgerEntry.id"),
|
||||||
|
'conditions' => array('LedgerEntry.id' => $id),
|
||||||
|
'fields' => array(),
|
||||||
|
));
|
||||||
|
//pr($reconciled);
|
||||||
|
$balance = 0;
|
||||||
|
foreach ($reconciled[$fund]['entry'] AS &$entry) {
|
||||||
|
$entry = array_merge($entry["ReconciliationLedgerEntry"], $entry[0]);
|
||||||
|
$balance += $entry['balance'];
|
||||||
|
}
|
||||||
|
$reconciled[$fund]['balance'] = $balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $reconciled;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: stats
|
||||||
|
* - Returns summary data from the requested ledger entry
|
||||||
|
*/
|
||||||
|
function stats($id) {
|
||||||
|
|
||||||
|
$query = array
|
||||||
|
(
|
||||||
|
'fields' => array("SUM(Reconciliation.amount) AS 'reconciled'"),
|
||||||
|
|
||||||
|
'conditions' => array(isset($cond) ? $cond : array(),
|
||||||
|
array('LedgerEntry.id' => $id)),
|
||||||
|
|
||||||
|
'group' => 'LedgerEntry.id',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get the applied amounts on the debit side
|
||||||
|
$query['link'] =
|
||||||
|
array('DebitReconciliationLedgerEntry' => array('alias' => 'DRLE', 'DRLETransaction' => array('class' => 'Transaction')));
|
||||||
|
$tmpstats = $this->find('first', $query);
|
||||||
|
$stats['debit_amount_reconciled'] = $tmpstats[0]['reconciled'];
|
||||||
|
|
||||||
|
// Get the applied amounts on the credit side
|
||||||
|
$query['link'] =
|
||||||
|
array('CreditReconciliationLedgerEntry' => array('alias' => 'CRLE', 'CRLETransaction' => array('class' => 'Transaction')));
|
||||||
|
$tmpstats = $this->find('first', $query);
|
||||||
|
$stats['credit_amount_reconciled'] = $tmpstats[0]['reconciled'];
|
||||||
|
|
||||||
|
return $stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
class MonetarySource extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'MonetarySource';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'name' => array('notempty'),
|
||||||
|
'tillable' => array('boolean')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'MonetaryType',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'LedgerEntry',
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
class MonetaryType extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'MonetaryType';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'name' => array('notempty'),
|
||||||
|
'tillable' => array('boolean')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'MonetarySource',
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
class Transaction extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'Transaction';
|
||||||
|
/* var $validate = array( */
|
||||||
|
/* 'stamp' => array('date') */
|
||||||
|
/* ); */
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'Customer',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'LedgerEntry',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
function beforeSave() {
|
||||||
|
|
||||||
|
if(!empty($this->data['Transaction']['stamp'])) {
|
||||||
|
$this->data['Transaction']['stamp'] =
|
||||||
|
$this->dateFormatBeforeSave($this->data['Transaction']['stamp']);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
class Unit extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'Unit';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'unit_size_id' => array('numeric'),
|
||||||
|
'name' => array('notempty'),
|
||||||
|
'sort_order' => array('numeric'),
|
||||||
|
'walk_order' => array('numeric'),
|
||||||
|
'deposit' => array('money'),
|
||||||
|
'amount' => array('money')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'UnitSize',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasOne = array(
|
||||||
|
'CurrentLease' => array(
|
||||||
|
'className' => 'Lease',
|
||||||
|
'conditions' => 'CurrentLease.close_date IS NULL',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'Lease',
|
||||||
|
);
|
||||||
|
|
||||||
|
function statusEnums() {
|
||||||
|
static $status_enums;
|
||||||
|
if (!isset($status_enums))
|
||||||
|
$status_enums = $this->getEnumValues('status');
|
||||||
|
return $status_enums;
|
||||||
|
}
|
||||||
|
|
||||||
|
function statusValue($enum) {
|
||||||
|
$enums = $this->statusEnums();
|
||||||
|
return $enums[$enum];
|
||||||
|
}
|
||||||
|
|
||||||
|
function occupiedEnumValue() {
|
||||||
|
return statusValue('OCCUPIED');
|
||||||
|
}
|
||||||
|
|
||||||
|
function conditionOccupied() {
|
||||||
|
return ('Unit.status >= ' . $this->statusValue('OCCUPIED'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function conditionVacant() {
|
||||||
|
return ('Unit.status BETWEEN ' .
|
||||||
|
($this->statusValue('UNAVAILABLE')+1) .
|
||||||
|
' AND ' .
|
||||||
|
($this->statusValue('OCCUPIED')-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
function conditionUnavailable() {
|
||||||
|
return ('Unit.status <= ' . $this->statusValue('UNAVAILABLE'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: stats
|
||||||
|
* - Returns summary data from the requested customer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function stats($id = null) {
|
||||||
|
if (!$id)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Get the basic information necessary
|
||||||
|
$unit = $this->find('first',
|
||||||
|
array('contain' => array
|
||||||
|
('Lease' => array
|
||||||
|
('fields' => array('Lease.id')),
|
||||||
|
|
||||||
|
'CurrentLease' => array
|
||||||
|
('fields' => array('CurrentLease.id'))),
|
||||||
|
|
||||||
|
'conditions' => array
|
||||||
|
(array('Unit.id' => $id)),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Get the stats for the current lease
|
||||||
|
$stats['CurrentLease'] = $this->Lease->stats($unit['CurrentLease']['id']);
|
||||||
|
|
||||||
|
// Sum the stats for all leases together
|
||||||
|
foreach ($unit['Lease'] AS $lease) {
|
||||||
|
$this->statsMerge($stats['Lease'], $this->Lease->stats($lease['id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the collection
|
||||||
|
return $stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Vendored
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -1,69 +0,0 @@
|
|||||||
N - GATE
|
|
||||||
N - ACH / CREDIT CARD PROCESSING
|
|
||||||
Y - CREDIT CARD ENTRY
|
|
||||||
Y - ACH ENTRY
|
|
||||||
P - INVENTORY TRACKING / POS
|
|
||||||
Y - UNIT TYPES
|
|
||||||
Y - UNIT SIZES
|
|
||||||
Y - UNITS
|
|
||||||
Y - MOVE IN / OUT
|
|
||||||
Y - UNIT TRANSFERS
|
|
||||||
Y - LEASE TRACKING (PDF Generation)
|
|
||||||
Y - LETTERS (PDF Generation)
|
|
||||||
Y - REMINDERS
|
|
||||||
Y - MULTIPLE LATE RENT SCHEDULES (Tenant A vs Tenant B)
|
|
||||||
Y - ACCOUNTING (assign charges to accounts)
|
|
||||||
Y - DETAILED REPORTING (HTML & PDF)
|
|
||||||
Y - SITE MAP; HOT CLICKABLE
|
|
||||||
P - PROSPECTIVE TENANTS
|
|
||||||
Y - MARKETING
|
|
||||||
P - RESERVATIONS
|
|
||||||
P - MOVE OUT NOTICES
|
|
||||||
P - MULTI-SITE (One database, multiple sites)
|
|
||||||
Y - GENERATE GEOGRAPHIC MAP OF CUSTOMERS USING GOOGLE!
|
|
||||||
- Major advantage here... MapPoint only choice with competitors
|
|
||||||
Y - WEB BASED
|
|
||||||
Y - CUSTOMER VIEW / MANAGER VIEW
|
|
||||||
Y - CUSTOMERS CAN CREATE ACCOUNTS, VIEW HISTORY
|
|
||||||
Y - CUSTOMERS CAN SIGN UP FOR AUTO PAY
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
Operations to be functional
|
|
||||||
'X' marks functionality sufficiently completed
|
|
||||||
|
|
||||||
X - Create Customer ID/Account
|
|
||||||
X - Add Contact information to Customer
|
|
||||||
X - Move Customer into Unit
|
|
||||||
X - Enter Rent Concessions given
|
|
||||||
X - Asses Rent Charges
|
|
||||||
X - Asses Late Charges
|
|
||||||
X - Asses Security Deposits
|
|
||||||
X - Receive and record Checks
|
|
||||||
X - Receive and record Money Orders
|
|
||||||
X - Receive and record Cash
|
|
||||||
X - Receive and record ACH Deposits
|
|
||||||
x - Reverse rent charges (early moveout on prepaid occupancy)
|
|
||||||
X - Handle NSF checks
|
|
||||||
X - Assess NSF Fees
|
|
||||||
X - Determine Lease Paid-Through status
|
|
||||||
- Report: List of customers overdue
|
|
||||||
- Flag unit as overlocked
|
|
||||||
- Flag unit as evicting
|
|
||||||
- Flag unit as normal status
|
|
||||||
- Flag unit as dirty
|
|
||||||
- Enter notes when communicating with Customer
|
|
||||||
- Accept pre-payments
|
|
||||||
- NOTE: As a temporary solution, disallow customer to run
|
|
||||||
a credit. Require charges be entered first.
|
|
||||||
X - Record Customer Move-Out from Unit
|
|
||||||
X - Record utilization of Security Deposit
|
|
||||||
- Record issuing of a refund
|
|
||||||
- Record Deposit into Petty Cash
|
|
||||||
- Record Payment from Petty Cash to expenses
|
|
||||||
- Record Petty Cash to refund.
|
|
||||||
X - Write Off Bad Debt
|
|
||||||
X - Perform a Deposit and Close the Books
|
|
||||||
X - Determine Rents Collected for a given period.
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,204 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
class ContactsController extends AppController {
|
|
||||||
|
|
||||||
var $sidemenu_links = array();
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* override: sideMenuLinks
|
|
||||||
* - Generates controller specific links for the side menu
|
|
||||||
*/
|
|
||||||
function sideMenuLinks() {
|
|
||||||
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: index / all
|
|
||||||
* - Generate a listing of contacts
|
|
||||||
*/
|
|
||||||
|
|
||||||
function index() { $this->all(); }
|
|
||||||
function all() { $this->jqGridView('All Contacts', 'all'); }
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* virtuals: jqGridData
|
|
||||||
* - With the application controller handling the jqGridData action,
|
|
||||||
* these virtual functions ensure that the correct data is passed
|
|
||||||
* to jqGrid.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function jqGridDataOrder(&$params, &$model, $index, $direction) {
|
|
||||||
$order = parent::jqGridDataOrder($params, $model, $index, $direction);
|
|
||||||
if ($index === 'Contact.last_name') {
|
|
||||||
$order[] = 'Contact.first_name ' . $direction;
|
|
||||||
}
|
|
||||||
if ($index === 'Contact.first_name') {
|
|
||||||
$order[] = 'Contact.last_name ' . $direction;
|
|
||||||
}
|
|
||||||
return $order;
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridRecordLinks(&$params, &$model, &$records, $links) {
|
|
||||||
$links['Contact'] = array('id');
|
|
||||||
return parent::jqGridRecordLinks($params, $model, $records, $links);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: view
|
|
||||||
* - Displays information about a specific contact
|
|
||||||
*/
|
|
||||||
|
|
||||||
function view($id = null) {
|
|
||||||
if (!$id) {
|
|
||||||
$this->Session->setFlash(__('Invalid Item.', true));
|
|
||||||
$this->redirect(array('action'=>'index'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$contact = $this->Contact->find
|
|
||||||
('first', array
|
|
||||||
('contain' => array
|
|
||||||
(// Models
|
|
||||||
'ContactPhone',
|
|
||||||
'ContactEmail',
|
|
||||||
'ContactAddress',
|
|
||||||
'Customer'),
|
|
||||||
|
|
||||||
'conditions' => array('Contact.id' => $id),
|
|
||||||
));
|
|
||||||
|
|
||||||
// Set up dynamic menu items
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Operations', 'header' => true);
|
|
||||||
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Edit',
|
|
||||||
'url' => array('action' => 'edit',
|
|
||||||
$id));
|
|
||||||
|
|
||||||
// Prepare to render.
|
|
||||||
$title = 'Contact: ' . $contact['Contact']['display_name'];
|
|
||||||
$this->set(compact('contact', 'title'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: edit
|
|
||||||
*/
|
|
||||||
|
|
||||||
function edit($id = null, $customer_id = null) {
|
|
||||||
if (isset($this->data)) {
|
|
||||||
|
|
||||||
if (isset($this->params['form']['cancel'])) {
|
|
||||||
if (isset($this->data['Contact']['id']))
|
|
||||||
$this->redirect(array('action'=>'view', $this->data['Contact']['id']));
|
|
||||||
/* else */
|
|
||||||
/* $this->redirect(array('controller' => 'customers', */
|
|
||||||
/* 'action'=>'add', $this->data['Customer']['id'])); */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go through each contact method and strip the bogus ID if new
|
|
||||||
foreach (array_intersect_key($this->data,
|
|
||||||
array('ContactPhone'=>1,
|
|
||||||
'ContactAddress'=>1,
|
|
||||||
'ContactEmail'=>1)) AS $type => $arr) {
|
|
||||||
foreach ($arr AS $idx => $item) {
|
|
||||||
if (isset($item['source']) && $item['source'] === 'new')
|
|
||||||
unset($this->data[$type][$idx]['id']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the contact and all associated data
|
|
||||||
$this->Contact->saveContact($this->data['Contact']['id'], $this->data);
|
|
||||||
|
|
||||||
// Now that the work is done, let the user view the updated contact
|
|
||||||
$this->redirect(array('action'=>'view', $this->data['Contact']['id']));
|
|
||||||
//$this->render('/empty');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($id) {
|
|
||||||
$this->data = $this->Contact->find
|
|
||||||
('first', array
|
|
||||||
('contain' => array
|
|
||||||
(// Models
|
|
||||||
'ContactPhone',
|
|
||||||
'ContactEmail',
|
|
||||||
'ContactAddress',
|
|
||||||
'Customer'),
|
|
||||||
|
|
||||||
'conditions' => array('Contact.id' => $id),
|
|
||||||
));
|
|
||||||
|
|
||||||
$title = 'Contact: ' . $this->data['Contact']['display_name'] . " : Edit";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$title = "Enter New Contact";
|
|
||||||
$this->data = array('ContactPhone' => array(),
|
|
||||||
'ContactAddress' => array(),
|
|
||||||
'ContactEmail' => array());
|
|
||||||
}
|
|
||||||
|
|
||||||
$phone_types = array_flip($this->Contact->ContactPhone->getEnumValues('type'));
|
|
||||||
unset($phone_types[0]);
|
|
||||||
// REVISIT <AP> 20090705
|
|
||||||
// Use this to have a mixed case enum
|
|
||||||
// array_map('ucfirst', array_map('strtolower', $phone_types))
|
|
||||||
$phone_types = array_combine($phone_types, $phone_types);
|
|
||||||
$this->set(compact('phone_types'));
|
|
||||||
|
|
||||||
$method_types = array_flip($this->Contact->getEnumValues
|
|
||||||
('type',
|
|
||||||
$this->Contact->tablePrefix . 'contacts_methods'));
|
|
||||||
unset($method_types[0]);
|
|
||||||
$method_types = array_combine($method_types, $method_types);
|
|
||||||
$this->set(compact('method_types'));
|
|
||||||
|
|
||||||
$method_preferences = array_flip($this->Contact->getEnumValues
|
|
||||||
('preference',
|
|
||||||
$this->Contact->tablePrefix . 'contacts_methods'));
|
|
||||||
unset($method_preferences[0]);
|
|
||||||
$method_preferences = array_combine($method_preferences, $method_preferences);
|
|
||||||
$this->set(compact('method_preferences'));
|
|
||||||
|
|
||||||
$contact_phones = $this->Contact->ContactPhone->phoneList();
|
|
||||||
$this->set(compact('contact_phones'));
|
|
||||||
|
|
||||||
$contact_addresses = $this->Contact->ContactAddress->addressList();
|
|
||||||
$this->set(compact('contact_addresses'));
|
|
||||||
|
|
||||||
$contact_emails = $this->Contact->ContactEmail->emailList();
|
|
||||||
$this->set(compact('contact_emails'));
|
|
||||||
|
|
||||||
// Prepare to render.
|
|
||||||
//pr($this->data);
|
|
||||||
$this->set(compact('title'));
|
|
||||||
$this->render('edit');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: add
|
|
||||||
* - Adds a new contact
|
|
||||||
*/
|
|
||||||
|
|
||||||
function add($customer_id = null) {
|
|
||||||
$this->edit(null, $customer_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,485 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
class CustomersController extends AppController {
|
|
||||||
var $sidemenu_links =
|
|
||||||
array(array('name' => 'Customers', 'header' => true),
|
|
||||||
array('name' => 'Current', 'url' => array('controller' => 'customers', 'action' => 'current')),
|
|
||||||
array('name' => 'Past', 'url' => array('controller' => 'customers', 'action' => 'past')),
|
|
||||||
array('name' => 'All', 'url' => array('controller' => 'customers', 'action' => 'all')),
|
|
||||||
array('name' => 'Add Customer', 'url' => array('controller' => 'customers', 'action' => 'add')),
|
|
||||||
);
|
|
||||||
|
|
||||||
//var $components = array('RequestHandler');
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* override: sideMenuLinks
|
|
||||||
* - Generates controller specific links for the side menu
|
|
||||||
*/
|
|
||||||
function sideMenuLinks() {
|
|
||||||
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: index / current / past / all
|
|
||||||
* - Creates a list of customers
|
|
||||||
*/
|
|
||||||
|
|
||||||
function index() { $this->current(); }
|
|
||||||
function current() { $this->jqGridView('Current Tenants', 'current'); }
|
|
||||||
function past() { $this->jqGridView('Past Tenants'); }
|
|
||||||
function all() { $this->jqGridView('All Customers'); }
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* virtuals: jqGridData
|
|
||||||
* - With the application controller handling the jqGridData action,
|
|
||||||
* these virtual functions ensure that the correct data is passed
|
|
||||||
* to jqGrid.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function jqGridDataSetup(&$params) {
|
|
||||||
parent::jqGridDataSetup($params);
|
|
||||||
if (!isset($params['action']))
|
|
||||||
$params['action'] = 'all';
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataCountTables(&$params, &$model) {
|
|
||||||
return array
|
|
||||||
('link' =>
|
|
||||||
array(// Models
|
|
||||||
'PrimaryContact',
|
|
||||||
'CurrentLease' => array('fields' => array()),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataTables(&$params, &$model) {
|
|
||||||
$link = $this->jqGridDataCountTables($params, $model);
|
|
||||||
$link['link']['LedgerEntry'] = array('fields' => array());
|
|
||||||
$link['link']['LedgerEntry']['Ledger'] = array('fields' => array());
|
|
||||||
$link['link']['LedgerEntry']['Ledger']['Account'] = array('fields' => array());
|
|
||||||
// INNER JOIN would be great, as it would ensure we're only looking
|
|
||||||
// at the ledger entries that we truly want. However, this also
|
|
||||||
// removes from the query any units that do not yet have a ledger
|
|
||||||
// entry in A/R. A solution would be to INNER JOIN these tables,
|
|
||||||
// and LEFT JOIN it to the rest. Grouping of JOINs, however, is
|
|
||||||
// implemented with the 'joins' tag, and is not available through
|
|
||||||
// the Linkable behavior interface.
|
|
||||||
//$link['link']['LedgerEntry']['Ledger']['Account']['type'] = 'INNER';
|
|
||||||
$link['link']['LedgerEntry']['Ledger']['Account']['conditions']
|
|
||||||
= array('Account.id' =>
|
|
||||||
$this->Customer->LedgerEntry->Ledger->Account->accountReceivableAccountID());
|
|
||||||
return $link;
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataFields(&$params, &$model) {
|
|
||||||
$db = &$model->getDataSource();
|
|
||||||
$fields = $db->fields($model, $model->alias);
|
|
||||||
$fields[] = ('COUNT(DISTINCT CurrentLease.id) AS lease_count');
|
|
||||||
$fields[] = ("SUM(IF(Account.id IS NULL, 0," .
|
|
||||||
" IF(LedgerEntry.debit_ledger_id = Account.id," .
|
|
||||||
" 1, -1))" .
|
|
||||||
" * IF(LedgerEntry.amount IS NULL, 0, LedgerEntry.amount))" .
|
|
||||||
" AS 'balance'");
|
|
||||||
return $fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataConditions(&$params, &$model) {
|
|
||||||
$conditions = parent::jqGridDataConditions($params, $model);
|
|
||||||
|
|
||||||
if ($params['action'] === 'current') {
|
|
||||||
$conditions[] = 'CurrentLease.id IS NOT NULL';
|
|
||||||
}
|
|
||||||
elseif ($params['action'] === 'past') {
|
|
||||||
$conditions[] = 'CurrentLease.id IS NULL';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $conditions;
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataOrder(&$params, &$model, $index, $direction) {
|
|
||||||
$order = array();
|
|
||||||
$order[] = parent::jqGridDataOrder($params, $model, $index, $direction);
|
|
||||||
|
|
||||||
if ($index !== 'PrimaryContact.last_name')
|
|
||||||
$order[] = parent::jqGridDataOrder($params, $model,
|
|
||||||
'PrimaryContact.last_name', $direction);
|
|
||||||
if ($index !== 'PrimaryContact.first_name')
|
|
||||||
$order[] = parent::jqGridDataOrder($params, $model,
|
|
||||||
'PrimaryContact.first_name', $direction);
|
|
||||||
if ($index !== 'Customer.id')
|
|
||||||
$order[] = parent::jqGridDataOrder($params, $model,
|
|
||||||
'Customer.id', $direction);
|
|
||||||
|
|
||||||
return $order;
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataRecordCount(&$params, &$model, $query) {
|
|
||||||
|
|
||||||
// We don't have a good way to use the query to obtain
|
|
||||||
// our count. The problem is that we're relying on the
|
|
||||||
// group by for the query, which will destroy the count,
|
|
||||||
// whether we omit the group by or leave it in.
|
|
||||||
// So, build a fresh query for counting.
|
|
||||||
|
|
||||||
$query['conditions'] = parent::jqGridDataConditions($params, $model);
|
|
||||||
|
|
||||||
$count = $model->find('count',
|
|
||||||
array_merge(array('link' => array_diff_key($query['link'],
|
|
||||||
array('CurrentLease'=>1))),
|
|
||||||
array_diff_key($query, array('link'=>1))));
|
|
||||||
|
|
||||||
if ($params['action'] === 'all')
|
|
||||||
return $count;
|
|
||||||
|
|
||||||
$query['conditions'][] = 'CurrentLease.id IS NULL';
|
|
||||||
$count_past = $model->find('count', $query);
|
|
||||||
|
|
||||||
// Since we can't easily count 'current' directly, we
|
|
||||||
// can quickly derive it since 'current' customers
|
|
||||||
// are mutually exclusive to 'past' customers.
|
|
||||||
if ($params['action'] == 'current')
|
|
||||||
$count = $count - $count_past;
|
|
||||||
elseif ($params['action'] == 'past') {
|
|
||||||
$count = $count_past;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $count;
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataRecords(&$params, &$model, $query) {
|
|
||||||
$customers = parent::jqGridDataRecords($params, $model, $query);
|
|
||||||
|
|
||||||
// Get the balance on each customer.
|
|
||||||
foreach ($customers AS &$customer) {
|
|
||||||
$stats = $this->Customer->stats($customer['Customer']['id']);
|
|
||||||
$customer['Customer']['balance'] = $stats['balance'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $customers;
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridRecordLinks(&$params, &$model, &$records, $links) {
|
|
||||||
$links['Customer'] = array('name');
|
|
||||||
return parent::jqGridRecordLinks($params, $model, $records, $links);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: move_in
|
|
||||||
* - Sets up the move-in page for the given customer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function move_in($id = null) {
|
|
||||||
$customer = array();
|
|
||||||
$unit = array();
|
|
||||||
|
|
||||||
if (isset($id)) {
|
|
||||||
$this->Customer->recursive = -1;
|
|
||||||
$customer = current($this->Customer->read(null, $id));
|
|
||||||
}
|
|
||||||
$this->set(compact('customer', 'unit'));
|
|
||||||
|
|
||||||
$title = 'Customer Move-In';
|
|
||||||
$this->set(compact('title'));
|
|
||||||
$this->render('/leases/move');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: move_out
|
|
||||||
* - prepare to move a customer out of one of their units
|
|
||||||
*/
|
|
||||||
|
|
||||||
function move_out($id) {
|
|
||||||
|
|
||||||
$customer = $this->Customer->find
|
|
||||||
('first', array
|
|
||||||
('contain' => array
|
|
||||||
(// Models
|
|
||||||
'Lease' =>
|
|
||||||
array('conditions' => array('Lease.moveout_date' => null),
|
|
||||||
// Models
|
|
||||||
'Unit' =>
|
|
||||||
array('order' => array('sort_order'),
|
|
||||||
'fields' => array('id', 'name'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
'conditions' => array('Customer.id' => $id),
|
|
||||||
));
|
|
||||||
$this->set('customer', $lease['Customer']);
|
|
||||||
$this->set('unit', array());
|
|
||||||
|
|
||||||
$redirect = array('controller' => 'customers',
|
|
||||||
'action' => 'view',
|
|
||||||
$id);
|
|
||||||
|
|
||||||
$title = $customer['Customer']['name'] . ': Prepare Move-Out';
|
|
||||||
$this->set(compact('title', 'customer', 'redirect'));
|
|
||||||
$this->render('/leases/move');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: view
|
|
||||||
* - Displays information about a specific customer
|
|
||||||
*/
|
|
||||||
|
|
||||||
function view($id = null) {
|
|
||||||
if (!$id) {
|
|
||||||
$this->Session->setFlash(__('Invalid Item.', true));
|
|
||||||
$this->redirect(array('action'=>'index'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$customer = $this->Customer->details($id);
|
|
||||||
|
|
||||||
$outstanding_balance = $customer['stats']['balance'];
|
|
||||||
$outstanding_deposit = $customer['deposits']['summary']['balance'];
|
|
||||||
|
|
||||||
// Figure out if this customer has any non-closed leases
|
|
||||||
$show_moveout = false;
|
|
||||||
$show_payment = false;
|
|
||||||
foreach ($customer['Lease'] AS $lease) {
|
|
||||||
if (!isset($lease['close_date']))
|
|
||||||
$show_payment = true;
|
|
||||||
if (!isset($lease['moveout_date']))
|
|
||||||
$show_moveout = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up dynamic menu items
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Operations', 'header' => true);
|
|
||||||
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Edit',
|
|
||||||
'url' => array('action' => 'edit',
|
|
||||||
$id));
|
|
||||||
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Move-In',
|
|
||||||
'url' => array('action' => 'move_in',
|
|
||||||
$id));
|
|
||||||
|
|
||||||
/* if ($show_moveout) { */
|
|
||||||
/* $this->sidemenu_links[] = */
|
|
||||||
/* array('name' => 'Move-Out', */
|
|
||||||
/* 'url' => array('action' => 'move_out', */
|
|
||||||
/* $id)); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
if ($show_payment) {
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Payment',
|
|
||||||
'url' => array('action' => 'receipt',
|
|
||||||
$id));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare to render.
|
|
||||||
$title = 'Customer: ' . $customer['Customer']['name'];
|
|
||||||
$this->set(compact('customer', 'title',
|
|
||||||
'outstanding_balance',
|
|
||||||
'outstanding_deposit'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: edit
|
|
||||||
* - Edit customer information
|
|
||||||
*/
|
|
||||||
|
|
||||||
function edit($id = null) {
|
|
||||||
if (isset($this->data)) {
|
|
||||||
// Check to see if the operation was cancelled.
|
|
||||||
if (isset($this->params['form']['cancel'])) {
|
|
||||||
if (isset($this->data['Customer']['id']))
|
|
||||||
$this->redirect(array('action'=>'view', $this->data['Customer']['id']));
|
|
||||||
else
|
|
||||||
$this->redirect(array('action'=>'index'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we have at least one contact
|
|
||||||
if (!isset($this->data['Contact']) || count($this->data['Contact']) == 0) {
|
|
||||||
$this->Session->setFlash("MUST SPECIFY AT LEAST ONE CONTACT", true);
|
|
||||||
$this->redirect(array('action'=>'view', $this->data['Customer']['id']));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure there is a primary contact
|
|
||||||
if (!isset($this->data['Customer']['primary_contact_entry'])) {
|
|
||||||
$this->Session->setFlash("MUST SPECIFY A PRIMARY CONTACT", true);
|
|
||||||
$this->redirect(array('action'=>'view', $this->data['Customer']['id']));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go through each customer and strip the bogus ID if new
|
|
||||||
foreach ($this->data['Contact'] AS &$contact) {
|
|
||||||
if (isset($contact['source']) && $contact['source'] === 'new')
|
|
||||||
unset($contact['id']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the customer and all associated data
|
|
||||||
if (!$this->Customer->saveCustomer($this->data['Customer']['id'],
|
|
||||||
$this->data,
|
|
||||||
$this->data['Customer']['primary_contact_entry'])) {
|
|
||||||
$this->Session->setFlash("CUSTOMER SAVE FAILED", true);
|
|
||||||
pr("CUSTOMER SAVE FAILED");
|
|
||||||
}
|
|
||||||
|
|
||||||
// If existing customer, then view it. Otherwise, since
|
|
||||||
// this is a new customer, go to the move in screen.
|
|
||||||
if ($this->data['Customer']['id'])
|
|
||||||
$this->redirect(array('action'=>'view', $this->Customer->id));
|
|
||||||
else
|
|
||||||
$this->redirect(array('action'=>'move_in', $this->Customer->id));
|
|
||||||
|
|
||||||
// For debugging, only if the redirects above have been
|
|
||||||
// commented out, otherwise this section isn't reached.
|
|
||||||
$this->render('/empty');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($id) {
|
|
||||||
$this->data = $this->Customer->details($id);
|
|
||||||
$title = 'Customer: ' . $this->data['Customer']['name'] . " : Edit";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$title = "Enter New Customer";
|
|
||||||
$this->data = array('Contact' => array(), 'PrimaryContact' => null);
|
|
||||||
}
|
|
||||||
|
|
||||||
$contact_types = array_flip($this->Customer->ContactsCustomer->getEnumValues('type'));
|
|
||||||
unset($contact_types[0]);
|
|
||||||
$contact_types = array_combine($contact_types, $contact_types);
|
|
||||||
$this->set(compact('contact_types'));
|
|
||||||
|
|
||||||
$contacts = $this->Customer->Contact->contactList();
|
|
||||||
$this->set(compact('contacts'));
|
|
||||||
|
|
||||||
// Prepare to render.
|
|
||||||
//pr($this->data);
|
|
||||||
$this->set(compact('title'));
|
|
||||||
$this->render('edit');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: add
|
|
||||||
* - Add a new customer
|
|
||||||
*/
|
|
||||||
|
|
||||||
function add() {
|
|
||||||
$this->edit();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: receipt
|
|
||||||
* - Sets up the receipt entry page for the given customer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function receipt($id = null) {
|
|
||||||
if (isset($id)) {
|
|
||||||
$this->Customer->recursive = -1;
|
|
||||||
$customer = $this->Customer->read(null, $id);
|
|
||||||
$customer = $customer['Customer'];
|
|
||||||
$unreconciled = $this->Customer->findUnreconciledLedgerEntries($id);
|
|
||||||
$charges = $unreconciled['debit'];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$customer = null;
|
|
||||||
$charges = array('balance' => 0, 'entry' => array());
|
|
||||||
}
|
|
||||||
|
|
||||||
$A = new Account();
|
|
||||||
$payment_accounts = $A->paymentAccounts();
|
|
||||||
$default_account = $A->cashAccountID();
|
|
||||||
$this->set(compact('payment_accounts', 'default_account'));
|
|
||||||
|
|
||||||
$title = ($customer['name'] . ': Payment Entry');
|
|
||||||
$this->set(compact('customer', 'charges', 'title'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: refund
|
|
||||||
* - Refunds customer charges
|
|
||||||
*/
|
|
||||||
|
|
||||||
function refund() {
|
|
||||||
$entries = $this->Customer->LedgerEntry->find
|
|
||||||
('all', array
|
|
||||||
('contain' => false,
|
|
||||||
'conditions' => array('LedgerEntry.id' =>
|
|
||||||
//array(199,200,201)
|
|
||||||
61
|
|
||||||
),
|
|
||||||
));
|
|
||||||
pr(compact('entries'));
|
|
||||||
|
|
||||||
$this->Customer->LedgerEntry->reverse($entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: unreconciledEntries
|
|
||||||
* - returns the list of unreconciled entries
|
|
||||||
*/
|
|
||||||
|
|
||||||
function unreconciled($id) {
|
|
||||||
|
|
||||||
//$this->layout = 'ajax';
|
|
||||||
$this->layout = null;
|
|
||||||
$this->autoLayout = false;
|
|
||||||
$this->autoRender = false;
|
|
||||||
Configure::write('debug', '0');
|
|
||||||
header("Content-type: text/xml;charset=utf-8");
|
|
||||||
|
|
||||||
App::import('Helper', 'Xml');
|
|
||||||
$xml = new XmlHelper();
|
|
||||||
|
|
||||||
// Find the unreconciled entries, then manipulate the structure
|
|
||||||
// slightly to accomodate the format necessary for XML Helper.
|
|
||||||
$unreconciled = $this->Customer->findUnreconciledLedgerEntries($id);
|
|
||||||
$unreconciled = array('entries' =>
|
|
||||||
array_intersect_key($unreconciled['debit'],
|
|
||||||
array('entry'=>1, 'balance'=>1)));
|
|
||||||
|
|
||||||
// XML Helper will dump an empty tag if the array is empty
|
|
||||||
if (!count($unreconciled['entries']['entry']))
|
|
||||||
unset($unreconciled['entries']['entry']);
|
|
||||||
|
|
||||||
pr($unreconciled);
|
|
||||||
//$reconciled = $cust->reconcileNewLedgerEntry($cust_id, 'credit', $amount);
|
|
||||||
|
|
||||||
$opts = array();
|
|
||||||
//$opts['format'] = 'tags';
|
|
||||||
echo $xml->header();
|
|
||||||
echo $xml->serialize($unreconciled, $opts);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,507 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
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')),
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* override: sideMenuLinks
|
|
||||||
* - Generates controller specific links for the side menu
|
|
||||||
*/
|
|
||||||
function sideMenuLinks() {
|
|
||||||
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: index / active / closed / all
|
|
||||||
* - Generate a listing of leases
|
|
||||||
*/
|
|
||||||
|
|
||||||
function index() { $this->all(); }
|
|
||||||
function active() { $this->jqGridView('Active Leases'); }
|
|
||||||
function closed() { $this->jqGridView('Closed Leases'); }
|
|
||||||
function all() { $this->jqGridView('All Leases', 'all'); }
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* virtuals: jqGridData
|
|
||||||
* - With the application controller handling the jqGridData action,
|
|
||||||
* these virtual functions ensure that the correct data is passed
|
|
||||||
* to jqGrid.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function jqGridDataSetup(&$params) {
|
|
||||||
parent::jqGridDataSetup($params);
|
|
||||||
if (!isset($params['action']))
|
|
||||||
$params['action'] = 'all';
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataCountTables(&$params, &$model) {
|
|
||||||
return array
|
|
||||||
('link' => array('Unit' => array('fields' => array('Unit.id', 'Unit.name')),
|
|
||||||
'Customer' => array('fields' => array('Customer.id', 'Customer.name'))));
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataTables(&$params, &$model) {
|
|
||||||
$link = $this->jqGridDataCountTables($params, $model);
|
|
||||||
$link['link']['LedgerEntry'] = array('fields' => array());
|
|
||||||
$link['link']['LedgerEntry']['Ledger'] = array('fields' => array());
|
|
||||||
$link['link']['LedgerEntry']['Ledger']['Account'] = array('fields' => array());
|
|
||||||
// INNER JOIN would be great, as it would ensure we're only looking
|
|
||||||
// at the ledger entries that we truly want. However, this also
|
|
||||||
// removes from the query any leases that do not yet have a ledger
|
|
||||||
// entry in A/R. A solution would be to INNER JOIN these tables,
|
|
||||||
// and LEFT JOIN it to the rest. Grouping of JOINs, however, is
|
|
||||||
// implemented with the 'joins' tag, and is not available through
|
|
||||||
// the Linkable behavior interface.
|
|
||||||
//$link['link']['LedgerEntry']['Ledger']['Account']['type'] = 'INNER';
|
|
||||||
$link['link']['LedgerEntry']['Ledger']['Account']['conditions']
|
|
||||||
= array('Account.id' =>
|
|
||||||
$this->Lease->LedgerEntry->Ledger->Account->accountReceivableAccountID());
|
|
||||||
return $link;
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataFields(&$params, &$model) {
|
|
||||||
$db = &$model->getDataSource();
|
|
||||||
$fields = $db->fields($model, $model->alias);
|
|
||||||
$fields[] = ("SUM(IF(Account.id IS NULL, 0," .
|
|
||||||
" IF(LedgerEntry.debit_ledger_id = Account.id," .
|
|
||||||
" 1, -1))" .
|
|
||||||
" * IF(LedgerEntry.amount IS NULL, 0, LedgerEntry.amount))" .
|
|
||||||
" AS 'balance'");
|
|
||||||
return $fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataConditions(&$params, &$model) {
|
|
||||||
$conditions = parent::jqGridDataConditions($params, $model);
|
|
||||||
|
|
||||||
if ($params['action'] === 'active') {
|
|
||||||
$conditions[] = 'Lease.close_date IS NULL';
|
|
||||||
}
|
|
||||||
elseif ($params['action'] === 'closed') {
|
|
||||||
$conditions[] = 'Lease.close_date IS NOT NULL';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $conditions;
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataOrder(&$params, &$model, $index, $direction) {
|
|
||||||
// Do not sort by number, which is type varchar and
|
|
||||||
// sorts on an ascii basis. Sort by ID instead.
|
|
||||||
if ($index === 'Lease.number')
|
|
||||||
$index = 'Lease.id';
|
|
||||||
|
|
||||||
// Instead of sorting by name, sort by defined order
|
|
||||||
if ($index === 'Unit.name')
|
|
||||||
$index = 'Unit.sort_order';
|
|
||||||
|
|
||||||
$order = array();
|
|
||||||
$order[] = parent::jqGridDataOrder($params, $model, $index, $direction);
|
|
||||||
|
|
||||||
// If sorting by anything other than id/number
|
|
||||||
// add sorting by id as a secondary condition.
|
|
||||||
if ($index !== 'Lease.id' && $index !== 'Lease.number')
|
|
||||||
$order[] = parent::jqGridDataOrder($params, $model,
|
|
||||||
'Lease.id', $direction);
|
|
||||||
|
|
||||||
return $order;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* function jqGridRecordsPostProcess(&$params, &$model, &$records) { */
|
|
||||||
/* foreach ($records AS &$record) { */
|
|
||||||
/* $record['Lease']['through_date'] */
|
|
||||||
/* = $this->Lease->rentChargeThrough($record['Lease']['id']); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
/* parent::jqGridRecordsPostProcess($params, $model, $records); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
function jqGridRecordLinks(&$params, &$model, &$records, $links) {
|
|
||||||
$links['Lease'] = array('number');
|
|
||||||
$links['Unit'] = array('name');
|
|
||||||
$links['Customer'] = array('name');
|
|
||||||
return parent::jqGridRecordLinks($params, $model, $records, $links);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: move_in
|
|
||||||
* - execute a move in on a new lease
|
|
||||||
*/
|
|
||||||
|
|
||||||
function move_in() {
|
|
||||||
if (!$this->data)
|
|
||||||
die("Should have some data");
|
|
||||||
|
|
||||||
// Handle the move in based on the data given
|
|
||||||
//pr(array('Move-in data', $this->data));
|
|
||||||
|
|
||||||
$lid = $this->Lease->moveIn($this->data['Lease']['customer_id'],
|
|
||||||
$this->data['Lease']['unit_id'],
|
|
||||||
null, null,
|
|
||||||
$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));
|
|
||||||
|
|
||||||
// For debugging, only if the redirect above have been
|
|
||||||
// commented out, otherwise this section isn't reached.
|
|
||||||
$this->render('/empty');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: move_out
|
|
||||||
* - prepare or execute a move out on a specific lease
|
|
||||||
*/
|
|
||||||
|
|
||||||
function move_out($id = null) {
|
|
||||||
if ($this->data) {
|
|
||||||
// Handle the move out based on the data given
|
|
||||||
//pr($this->data);
|
|
||||||
|
|
||||||
$this->Lease->moveOut($this->data['Lease']['id'],
|
|
||||||
'VACANT',
|
|
||||||
$this->data['Lease']['moveout_date'],
|
|
||||||
//true // Close this lease, if able
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->redirect($this->data['redirect']);
|
|
||||||
$this->autoRender = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($id))
|
|
||||||
die("Oh Nooooo!!");
|
|
||||||
|
|
||||||
$lease = $this->Lease->find
|
|
||||||
('first', array
|
|
||||||
('contain' => array
|
|
||||||
(// Models
|
|
||||||
'Unit' =>
|
|
||||||
array('order' => array('sort_order'),
|
|
||||||
'fields' => array('id', 'name'),
|
|
||||||
),
|
|
||||||
|
|
||||||
'Customer' =>
|
|
||||||
array('fields' => array('id', 'name'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
'conditions' => array(array('Lease.id' => $id),
|
|
||||||
array('Lease.close_date' => null),
|
|
||||||
),
|
|
||||||
));
|
|
||||||
$this->set('customer', $lease['Customer']);
|
|
||||||
$this->set('unit', $lease['Unit']);
|
|
||||||
$this->set('lease', $lease['Lease']);
|
|
||||||
|
|
||||||
$redirect = array('controller' => 'leases',
|
|
||||||
'action' => 'view',
|
|
||||||
$id);
|
|
||||||
|
|
||||||
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
|
|
||||||
$lease['Unit']['name'] . ': ' .
|
|
||||||
$lease['Customer']['name'] . ': Prepare Move-Out');
|
|
||||||
$this->set(compact('title', 'redirect'));
|
|
||||||
$this->render('/leases/move');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: apply_deposit
|
|
||||||
* - Applies the security deposit to charges. This is much
|
|
||||||
* like a receipt, but it's separated to keep it simple and
|
|
||||||
* to prevent feature overload on the receipt page.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function apply_deposit($id) {
|
|
||||||
$A = new Account();
|
|
||||||
|
|
||||||
$lease = $this->Lease->find
|
|
||||||
('first', array
|
|
||||||
('contain' => array
|
|
||||||
(// Models
|
|
||||||
'Unit' =>
|
|
||||||
array('order' => array('sort_order'),
|
|
||||||
'fields' => array('id', 'name'),
|
|
||||||
),
|
|
||||||
|
|
||||||
'Customer' =>
|
|
||||||
array('fields' => array('id', 'name'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
'conditions' => array(array('Lease.id' => $id),
|
|
||||||
array('Lease.close_date' => null),
|
|
||||||
),
|
|
||||||
));
|
|
||||||
|
|
||||||
|
|
||||||
// Get the lease balance, part of lease stats
|
|
||||||
$this->Lease->statsMerge($lease['Lease'],
|
|
||||||
array('stats' => $this->Lease->stats($id)));
|
|
||||||
|
|
||||||
// Determine the lease security deposit
|
|
||||||
$deposit = $this->Lease->findSecurityDeposits($lease['Lease']['id']);
|
|
||||||
$this->set(compact('deposit'));
|
|
||||||
$this->set('customer', $lease['Customer']);
|
|
||||||
$this->set('unit', $lease['Unit']);
|
|
||||||
$this->set('lease', $lease['Lease']);
|
|
||||||
$this->set('account', array('id' => $A->securityDepositAccountID()));
|
|
||||||
|
|
||||||
/* $redirect = array('controller' => 'leases', */
|
|
||||||
/* 'action' => 'view', */
|
|
||||||
/* $id); */
|
|
||||||
|
|
||||||
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
|
|
||||||
$lease['Unit']['name'] . ': ' .
|
|
||||||
$lease['Customer']['name'] . ': Utilize Security Deposit');
|
|
||||||
$this->set(compact('title', 'redirect'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: bad_debt
|
|
||||||
* - Writes off remaining charges on a lease.
|
|
||||||
* REVISIT <AP>: 20090710
|
|
||||||
* Should this be a customer function? What customer
|
|
||||||
* would have only one lease that results in bad debt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function bad_debt($id) {
|
|
||||||
$A = new Account();
|
|
||||||
|
|
||||||
$lease = $this->Lease->find
|
|
||||||
('first', array
|
|
||||||
('contain' => array
|
|
||||||
(// Models
|
|
||||||
'Unit' =>
|
|
||||||
array('order' => array('sort_order'),
|
|
||||||
'fields' => array('id', 'name'),
|
|
||||||
),
|
|
||||||
|
|
||||||
'Customer' =>
|
|
||||||
array('fields' => array('id', 'name'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
'conditions' => array(array('Lease.id' => $id),
|
|
||||||
array('Lease.close_date' => null),
|
|
||||||
),
|
|
||||||
));
|
|
||||||
|
|
||||||
|
|
||||||
// Get the lease balance, part of lease stats
|
|
||||||
$this->Lease->statsMerge($lease['Lease'],
|
|
||||||
array('stats' => $this->Lease->stats($id)));
|
|
||||||
|
|
||||||
// Determine the lease security deposit
|
|
||||||
$deposit = $this->Lease->findSecurityDeposits($lease['Lease']['id']);
|
|
||||||
if ($deposit['summary']['balance'] > 0)
|
|
||||||
die("Still have un-utilized security deposit");
|
|
||||||
|
|
||||||
$this->set('customer', $lease['Customer']);
|
|
||||||
$this->set('unit', $lease['Unit']);
|
|
||||||
$this->set('lease', $lease['Lease']);
|
|
||||||
$this->set('account', array('id' => $A->badDebtAccountID()));
|
|
||||||
|
|
||||||
/* $redirect = array('controller' => 'leases', */
|
|
||||||
/* 'action' => 'view', */
|
|
||||||
/* $id); */
|
|
||||||
|
|
||||||
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
|
|
||||||
$lease['Unit']['name'] . ': ' .
|
|
||||||
$lease['Customer']['name'] . ': Write Off Bad Debt');
|
|
||||||
$this->set(compact('title', 'redirect'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: refund
|
|
||||||
* - Provides user with a refund
|
|
||||||
* REVISIT <AP>: 20090710
|
|
||||||
* Should this be a customer function?
|
|
||||||
*/
|
|
||||||
|
|
||||||
function refund($id) {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: close
|
|
||||||
* - Closes a lease to any further action
|
|
||||||
*/
|
|
||||||
|
|
||||||
function close($id) {
|
|
||||||
// REVISIT <AP>: 20090708
|
|
||||||
// We should probably seek confirmation first...
|
|
||||||
$this->Lease->close($id);
|
|
||||||
$this->redirect(array('action'=>'view', $id));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: invoice
|
|
||||||
* - Sets up the invoice entry page for the given customer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function invoice($id = null, $type = null) {
|
|
||||||
|
|
||||||
$lease = $this->Lease->find
|
|
||||||
('first', array
|
|
||||||
('contain' => array
|
|
||||||
(// Models
|
|
||||||
'Unit' =>
|
|
||||||
array('order' => array('sort_order'),
|
|
||||||
'fields' => array('id', 'name'),
|
|
||||||
),
|
|
||||||
|
|
||||||
'Customer' =>
|
|
||||||
array('fields' => array('id', 'name'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
'conditions' => array(array('Lease.id' => $id),
|
|
||||||
array('Lease.close_date' => null),
|
|
||||||
),
|
|
||||||
));
|
|
||||||
|
|
||||||
$A = new Account();
|
|
||||||
$charge_accounts = $A->chargeAccounts();
|
|
||||||
$default_account = $A->rentAccountID();
|
|
||||||
$this->set(compact('charge_accounts', 'default_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'));
|
|
||||||
|
|
||||||
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
|
|
||||||
$lease['Unit']['name'] . ': ' .
|
|
||||||
$lease['Customer']['name'] . ': Charge Entry');
|
|
||||||
$this->set(compact('title', 'lease', 'charge'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: view
|
|
||||||
* - Displays information about a specific lease
|
|
||||||
*/
|
|
||||||
|
|
||||||
function view($id = null) {
|
|
||||||
if (!$id) {
|
|
||||||
$this->Session->setFlash(__('Invalid Item.', true));
|
|
||||||
$this->redirect(array('action'=>'index'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get details about the lease and its ledgers (no ledger entries yet)
|
|
||||||
$lease = $this->Lease->find
|
|
||||||
('first',
|
|
||||||
array('contain' =>
|
|
||||||
array(// Models
|
|
||||||
'LeaseType',
|
|
||||||
'Unit',
|
|
||||||
'Customer',
|
|
||||||
),
|
|
||||||
'conditions' => array(array('Lease.id' => $id)),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$lease['Lease']['paid_through'] = $this->Lease->rentPaidThrough($id);
|
|
||||||
|
|
||||||
|
|
||||||
$this->set('charge_gaps', $this->Lease->rentChargeGaps($id));
|
|
||||||
$this->set('charge_through', $this->Lease->rentChargeThrough($id));
|
|
||||||
|
|
||||||
// Obtain the overall lease balance
|
|
||||||
$this->Lease->statsMerge($lease['Lease'],
|
|
||||||
array('stats' => $this->Lease->stats($id)));
|
|
||||||
$outstanding_balance = $lease['Lease']['stats']['balance'];
|
|
||||||
|
|
||||||
// Determine the lease security deposit
|
|
||||||
$deposits = $this->Lease->findSecurityDeposits($lease['Lease']['id']);
|
|
||||||
$outstanding_deposit = $deposits['summary']['balance'];
|
|
||||||
|
|
||||||
// Set up dynamic menu items
|
|
||||||
if (!isset($lease['Lease']['close_date'])) {
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Operations', 'header' => true);
|
|
||||||
|
|
||||||
if (!isset($lease['Lease']['moveout_date']))
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Move-Out', 'url' => array('action' => 'move_out',
|
|
||||||
$id));
|
|
||||||
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Charges', 'url' => array('action' => 'invoice',
|
|
||||||
$id));
|
|
||||||
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Payments', 'url' => array('controller' => 'customers',
|
|
||||||
'action' => 'receipt',
|
|
||||||
$lease['Customer']['id']));
|
|
||||||
|
|
||||||
if (isset($lease['Lease']['moveout_date']) && $outstanding_deposit > 0 && $outstanding_balance > 0)
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Apply Deposit', 'url' => array('action' => 'apply_deposit',
|
|
||||||
$id));
|
|
||||||
|
|
||||||
if (isset($lease['Lease']['moveout_date']) &&
|
|
||||||
$outstanding_balance <= 0 &&
|
|
||||||
($outstanding_deposit - $outstanding_balance) > 0)
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Issue Refund', 'url' => array('action' => 'refund',
|
|
||||||
$id));
|
|
||||||
|
|
||||||
if (isset($lease['Lease']['moveout_date']) && $outstanding_deposit == 0 && $outstanding_balance > 0)
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Write-Off', 'url' => array('action' => 'bad_debt',
|
|
||||||
$id));
|
|
||||||
|
|
||||||
if ($this->Lease->closeable($id))
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Close', 'url' => array('action' => 'close',
|
|
||||||
$id));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare to render
|
|
||||||
$title = 'Lease: #' . $lease['Lease']['id'];
|
|
||||||
$this->set(compact('lease', 'title',
|
|
||||||
'outstanding_deposit',
|
|
||||||
'outstanding_balance'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
class TransactionsController extends AppController {
|
|
||||||
|
|
||||||
var $components = array('RequestHandler');
|
|
||||||
|
|
||||||
var $sidemenu_links =
|
|
||||||
array(array('name' => 'Transactions', 'header' => true),
|
|
||||||
array('name' => 'All', 'url' => array('controller' => 'transactions', 'action' => 'all')),
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* override: sideMenuLinks
|
|
||||||
* - Generates controller specific links for the side menu
|
|
||||||
*/
|
|
||||||
function sideMenuLinks() {
|
|
||||||
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: index / all
|
|
||||||
* - Generate a listing of transactions
|
|
||||||
*/
|
|
||||||
|
|
||||||
function index() { $this->all(); }
|
|
||||||
function all() { $this->jqGridView('All Transactions', 'all'); }
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* virtuals: jqGridData
|
|
||||||
* - With the application controller handling the jqGridData action,
|
|
||||||
* these virtual functions ensure that the correct data is passed
|
|
||||||
* to jqGrid.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function jqGridRecordLinks(&$params, &$model, &$records, $links) {
|
|
||||||
$links['Transaction'] = array('id');
|
|
||||||
return parent::jqGridRecordLinks($params, $model, $records, $links);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: view
|
|
||||||
* - Displays information about a specific transaction
|
|
||||||
*/
|
|
||||||
|
|
||||||
function view($id = null) {
|
|
||||||
if (!$id) {
|
|
||||||
$this->Session->setFlash(__('Invalid Item.', true));
|
|
||||||
$this->redirect(array('action'=>'index'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$transaction = $this->Transaction->find
|
|
||||||
('first',
|
|
||||||
array('contain' =>
|
|
||||||
array(// Models
|
|
||||||
'LedgerEntry' => array('fields' => array('LedgerEntry.id',
|
|
||||||
'LedgerEntry.amount',
|
|
||||||
'LedgerEntry.comment'),
|
|
||||||
//Models
|
|
||||||
|
|
||||||
'DebitLedger' => array
|
|
||||||
('fields' => array('DebitLedger.id', 'DebitLedger.sequence'),
|
|
||||||
'Account' => array
|
|
||||||
('fields' => array('Account.id', 'Account.name')),
|
|
||||||
),
|
|
||||||
|
|
||||||
'CreditLedger' => array
|
|
||||||
('fields' => array('CreditLedger.id', 'CreditLedger.sequence'),
|
|
||||||
'Account' => array
|
|
||||||
('fields' => array('Account.id', 'Account.name')),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'conditions' => array('Transaction.id' => $id),
|
|
||||||
));
|
|
||||||
|
|
||||||
// Figure out the transaction total
|
|
||||||
$total = 0;
|
|
||||||
foreach($transaction['LedgerEntry'] AS $entry)
|
|
||||||
$total += $entry['amount'];
|
|
||||||
|
|
||||||
// OK, prepare to render.
|
|
||||||
$title = 'Transaction #' . $transaction['Transaction']['id'];
|
|
||||||
$this->set(compact('transaction', 'title', 'total'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: postInvoice
|
|
||||||
* - handles the creation of a charge invoice
|
|
||||||
*/
|
|
||||||
|
|
||||||
function postInvoice() {
|
|
||||||
if (!$this->RequestHandler->isPost()) {
|
|
||||||
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$this->Transaction->addInvoice($this->data, null,
|
|
||||||
$this->data['Lease']['id'])) {
|
|
||||||
$this->Session->setFlash("INVOICE FAILED", true);
|
|
||||||
// REVISIT <AP> 20090706:
|
|
||||||
// Until we can work out the session problems,
|
|
||||||
// just die.
|
|
||||||
die("<H1>INVOICE FAILED</H1>");
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->layout = null;
|
|
||||||
$this->autoLayout = false;
|
|
||||||
$this->autoRender = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: postReceipt
|
|
||||||
* - handles the creation of a payment receipt
|
|
||||||
*/
|
|
||||||
|
|
||||||
function postReceipt() {
|
|
||||||
if (!$this->RequestHandler->isPost()) {
|
|
||||||
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach($this->data['LedgerEntry'] AS &$entry) {
|
|
||||||
if (!isset($entry['acct'][$entry['account_id']]))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
$entry['MonetarySource'] = $entry['acct'][$entry['account_id']];
|
|
||||||
}
|
|
||||||
|
|
||||||
pr($this->data);
|
|
||||||
if (!$this->Transaction->addReceipt($this->data,
|
|
||||||
$this->data['Customer']['id'],
|
|
||||||
(isset($this->data['Lease']['id'])
|
|
||||||
? $this->data['Lease']['id']
|
|
||||||
: null ))) {
|
|
||||||
$this->Session->setFlash("RECEIPT FAILED", true);
|
|
||||||
// REVISIT <AP> 20090706:
|
|
||||||
// Until we can work out the session problems,
|
|
||||||
// just die.
|
|
||||||
die("<H1>RECEIPT FAILED</H1>");
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->layout = null;
|
|
||||||
$this->autoLayout = false;
|
|
||||||
$this->autoRender = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,278 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
class UnitsController extends AppController {
|
|
||||||
|
|
||||||
var $sidemenu_links =
|
|
||||||
array(array('name' => 'Units', 'header' => true),
|
|
||||||
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')),
|
|
||||||
array('name' => 'All', 'url' => array('controller' => 'units', 'action' => 'all')),
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* override: sideMenuLinks
|
|
||||||
* - Generates controller specific links for the side menu
|
|
||||||
*/
|
|
||||||
function sideMenuLinks() {
|
|
||||||
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: index / unavailable / vacant / occupied / all
|
|
||||||
* - Generate a listing of units
|
|
||||||
*/
|
|
||||||
|
|
||||||
function index() { $this->all(); }
|
|
||||||
function unavailable() { $this->jqGridView('Unavailable Units'); }
|
|
||||||
function vacant() { $this->jqGridView('Vacant Units'); }
|
|
||||||
function occupied() { $this->jqGridView('Occupied Units'); }
|
|
||||||
function all() { $this->jqGridView('All Units', 'all'); }
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* virtuals: jqGridData
|
|
||||||
* - With the application controller handling the jqGridData action,
|
|
||||||
* these virtual functions ensure that the correct data is passed
|
|
||||||
* to jqGrid.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function jqGridDataSetup(&$params) {
|
|
||||||
parent::jqGridDataSetup($params);
|
|
||||||
if (!isset($params['action']))
|
|
||||||
$params['action'] = 'all';
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataCountTables(&$params, &$model) {
|
|
||||||
$link = array
|
|
||||||
('link' =>
|
|
||||||
array(// Models
|
|
||||||
'UnitSize' => array('fields' => array('id', 'name')),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($params['action'] === 'occupied')
|
|
||||||
$link['Lease'] = array('fields' => array(),
|
|
||||||
// Models
|
|
||||||
'Contact' => array('fields' => array('display_name'),
|
|
||||||
//'type' => 'LEFT',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
return $link;
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataTables(&$params, &$model) {
|
|
||||||
$link = $this->jqGridDataCountTables($params, $model);
|
|
||||||
$link['link']['CurrentLease']['LedgerEntry'] = array('fields' => array());
|
|
||||||
$link['link']['CurrentLease']['LedgerEntry']['Ledger'] = array('fields' => array());
|
|
||||||
$link['link']['CurrentLease']['LedgerEntry']['Ledger']['Account'] = array('fields' => array());
|
|
||||||
// INNER JOIN would be great, as it would ensure we're only looking
|
|
||||||
// at the ledger entries that we truly want. However, this also
|
|
||||||
// removes from the query any leases that do not yet have a ledger
|
|
||||||
// entry in A/R. A solution would be to INNER JOIN these tables,
|
|
||||||
// and LEFT JOIN it to the rest. Grouping of JOINs, however, is
|
|
||||||
// implemented with the 'joins' tag, and is not available through
|
|
||||||
// the Linkable behavior interface.
|
|
||||||
//$link['link']['CurrentLease']['LedgerEntry']['Ledger']['Account']['type'] = 'INNER';
|
|
||||||
$link['link']['CurrentLease']['LedgerEntry']['Ledger']['Account']['conditions']
|
|
||||||
= array('Account.id' =>
|
|
||||||
$this->Unit->CurrentLease->LedgerEntry->Ledger->Account->accountReceivableAccountID());
|
|
||||||
return $link;
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataFields(&$params, &$model) {
|
|
||||||
$db = &$model->getDataSource();
|
|
||||||
$fields = $db->fields($model, $model->alias);
|
|
||||||
$fields[] = ("SUM(IF(Account.id IS NULL, 0," .
|
|
||||||
" IF(LedgerEntry.debit_ledger_id = Account.id," .
|
|
||||||
" 1, -1))" .
|
|
||||||
" * LedgerEntry.amount) AS 'balance'");
|
|
||||||
return $fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataConditions(&$params, &$model) {
|
|
||||||
$conditions = parent::jqGridDataConditions($params, $model);
|
|
||||||
|
|
||||||
if ($params['action'] === 'unavailable') {
|
|
||||||
$conditions[] = $this->Unit->conditionUnavailable();
|
|
||||||
}
|
|
||||||
elseif ($params['action'] === 'vacant') {
|
|
||||||
$conditions[] = $this->Unit->conditionVacant();
|
|
||||||
}
|
|
||||||
elseif ($params['action'] === 'occupied') {
|
|
||||||
$conditions[] = $this->Unit->conditionOccupied();
|
|
||||||
}
|
|
||||||
elseif ($params['action'] === 'unoccupied') {
|
|
||||||
$conditions[] = array('NOT' => array($this->Unit->conditionOccupied()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $conditions;
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridDataOrder(&$params, &$model, $index, $direction) {
|
|
||||||
// Instead of sorting by name, sort by defined order
|
|
||||||
if ($index === 'Unit.name')
|
|
||||||
$index = 'Unit.sort_order';
|
|
||||||
|
|
||||||
$order = array();
|
|
||||||
$order[] = parent::jqGridDataOrder($params, $model, $index, $direction);
|
|
||||||
|
|
||||||
// If sorting by anything other than name (defined order)
|
|
||||||
// add the sort-order as a secondary condition
|
|
||||||
if ($index !== 'Unit.name')
|
|
||||||
$order[] = parent::jqGridDataOrder($params, $model,
|
|
||||||
'Unit.sort_order', $direction);
|
|
||||||
|
|
||||||
return $order;
|
|
||||||
}
|
|
||||||
|
|
||||||
function jqGridRecordLinks(&$params, &$model, &$records, $links) {
|
|
||||||
$links['Unit'] = array('name');
|
|
||||||
$links['UnitSize'] = array('name');
|
|
||||||
return parent::jqGridRecordLinks($params, $model, $records, $links);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: move_in
|
|
||||||
* - Sets up the move-in page for the given unit.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function move_in($id = null) {
|
|
||||||
$customer = array();
|
|
||||||
$unit = array();
|
|
||||||
|
|
||||||
if (isset($id)) {
|
|
||||||
$this->Unit->recursive = -1;
|
|
||||||
$unit = current($this->Unit->read(null, $id));
|
|
||||||
}
|
|
||||||
|
|
||||||
$title = 'Unit Move-In';
|
|
||||||
$this->set(compact('customer', 'unit', 'title'));
|
|
||||||
$this->render('/leases/move');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: move_out
|
|
||||||
* - prepare or execute a move out on a specific lease
|
|
||||||
*/
|
|
||||||
|
|
||||||
function move_out($id) {
|
|
||||||
|
|
||||||
$unit = $this->Unit->find
|
|
||||||
('first', array
|
|
||||||
('contain' => array
|
|
||||||
(// Models
|
|
||||||
'CurrentLease' =>
|
|
||||||
array(//'conditions' => array('Lease.moveout_date' => null),
|
|
||||||
// Models
|
|
||||||
'Customer' =>
|
|
||||||
array('fields' => array('id', 'name'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'conditions' => array('Unit.id' => $id),
|
|
||||||
));
|
|
||||||
$this->set('customer', $unit['CurrentLease']['Customer']);
|
|
||||||
$this->set('unit', $unit['Unit']);
|
|
||||||
$this->set('lease', $unit['CurrentLease']);
|
|
||||||
|
|
||||||
$redirect = array('controller' => 'units',
|
|
||||||
'action' => 'view',
|
|
||||||
$id);
|
|
||||||
|
|
||||||
$title = ('Lease #' . $unit['CurrentLease']['number'] . ': ' .
|
|
||||||
$unit['Unit']['name'] . ': ' .
|
|
||||||
$unit['CurrentLease']['Customer']['name'] . ': Prepare Move-Out');
|
|
||||||
$this->set(compact('title', 'redirect'));
|
|
||||||
$this->render('/leases/move');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: view
|
|
||||||
* - Displays information about a specific unit
|
|
||||||
*/
|
|
||||||
|
|
||||||
function view($id = null) {
|
|
||||||
if (!$id) {
|
|
||||||
$this->Session->setFlash(__('Invalid Item.', true));
|
|
||||||
$this->redirect(array('action'=>''));
|
|
||||||
}
|
|
||||||
|
|
||||||
$unit = $this->Unit->find
|
|
||||||
('first',
|
|
||||||
array('contain' =>
|
|
||||||
array(// Models
|
|
||||||
'UnitSize',
|
|
||||||
'Lease' => array('Customer'),
|
|
||||||
'CurrentLease' => array('Customer')
|
|
||||||
),
|
|
||||||
'conditions' => array('Unit.id' => $id),
|
|
||||||
));
|
|
||||||
|
|
||||||
// Get the balance on each lease.
|
|
||||||
foreach ($unit['Lease'] AS &$lease) {
|
|
||||||
$stats = $this->Unit->Lease->stats($lease['id']);
|
|
||||||
$lease['balance'] = $stats['balance'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$outstanding_balance = 0;
|
|
||||||
$outstanding_deposit = 0;
|
|
||||||
if (isset($unit['CurrentLease']['id'])) {
|
|
||||||
// Figure out the outstanding balance of the current lease.
|
|
||||||
$stats = $this->Unit->stats($id);
|
|
||||||
$outstanding_balance =
|
|
||||||
$stats['CurrentLease']['balance'];
|
|
||||||
|
|
||||||
// Figure out the total security deposit for the current lease.
|
|
||||||
$deposits = $this->Unit->Lease->findSecurityDeposits($unit['CurrentLease']['id']);
|
|
||||||
$outstanding_deposit = $deposits['summary']['balance'];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up dynamic menu items
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Operations', 'header' => true);
|
|
||||||
|
|
||||||
if (isset($unit['CurrentLease']['id']) &&
|
|
||||||
!isset($unit['CurrentLease']['moveout_date'])) {
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Move-Out', 'url' => array('action' => 'move_out',
|
|
||||||
$id));
|
|
||||||
} else {
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Move-In', 'url' => array('action' => 'move_in',
|
|
||||||
$id));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($unit['CurrentLease']['id']) &&
|
|
||||||
!isset($unit['CurrentLease']['close_date'])) {
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Payment', 'url' => array('controller' => 'customers',
|
|
||||||
'action' => 'receipt',
|
|
||||||
$unit['CurrentLease']['customer_id']));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare to render.
|
|
||||||
$title = 'Unit ' . $unit['Unit']['name'];
|
|
||||||
$this->set(compact('unit', 'title',
|
|
||||||
'outstanding_balance',
|
|
||||||
'outstanding_deposit'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,850 +0,0 @@
|
|||||||
<?php
|
|
||||||
class Account extends AppModel {
|
|
||||||
|
|
||||||
var $name = 'Account';
|
|
||||||
var $validate = array(
|
|
||||||
'id' => array('numeric'),
|
|
||||||
'name' => array('notempty'),
|
|
||||||
'external_name' => array('notempty')
|
|
||||||
);
|
|
||||||
|
|
||||||
var $hasOne = array(
|
|
||||||
'CurrentLedger' => array(
|
|
||||||
'className' => 'Ledger',
|
|
||||||
// REVISIT <AP> 20090702:
|
|
||||||
// I would prefer this statement, which has no
|
|
||||||
// engine specific code. However, it doesn't
|
|
||||||
// work with the Linkable behavior. I need to
|
|
||||||
// look into that, just not right now.
|
|
||||||
//'conditions' => array('CurrentLedger.close_id' => null),
|
|
||||||
'conditions' => array('CurrentLedger.close_id IS NULL'),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
var $hasMany = array(
|
|
||||||
'Ledger',
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: type
|
|
||||||
* - Returns the type of this account
|
|
||||||
*/
|
|
||||||
function type($id) {
|
|
||||||
$this->cacheQueries = true;
|
|
||||||
$account = $this->find('first', array
|
|
||||||
('recursive' => -1,
|
|
||||||
'fields' => array('type'),
|
|
||||||
'conditions' => array(array('Account.id' => $id)),
|
|
||||||
));
|
|
||||||
$this->cacheQueries = false;
|
|
||||||
|
|
||||||
return $account['Account']['type'];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: fundamentalType
|
|
||||||
* - Returns the fundmental type of the account, credit or debit
|
|
||||||
*/
|
|
||||||
function fundamentalType($id_or_type) {
|
|
||||||
if (is_numeric($id_or_type))
|
|
||||||
$type = $this->type($id_or_type);
|
|
||||||
else
|
|
||||||
$type = $id_or_type;
|
|
||||||
|
|
||||||
// Asset and Expense accounts are debit accounts
|
|
||||||
if (in_array(strtoupper($type), array('ASSET', 'EXPENSE')))
|
|
||||||
return 'debit';
|
|
||||||
|
|
||||||
// Otherwise, it's a credit account
|
|
||||||
return 'credit';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: fundamentalOpposite
|
|
||||||
* - Returns the opposite fundmental type of the account, credit or debit
|
|
||||||
*/
|
|
||||||
function fundamentalOpposite($id_or_type) {
|
|
||||||
if (in_array(strtolower($id_or_type), array('credit', 'debit')))
|
|
||||||
$fund = $id_or_type;
|
|
||||||
else
|
|
||||||
$fund = $this->fundamentalType($id_or_type);
|
|
||||||
|
|
||||||
if ($fund == 'debit')
|
|
||||||
return 'credit';
|
|
||||||
|
|
||||||
return 'debit';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: name
|
|
||||||
* - Returns the name of this account
|
|
||||||
*/
|
|
||||||
function name($id) {
|
|
||||||
$this->cacheQueries = true;
|
|
||||||
$account = $this->find('first', array
|
|
||||||
('recursive' => -1,
|
|
||||||
'fields' => array('name'),
|
|
||||||
'conditions' => array(array('Account.id' => $id)),
|
|
||||||
));
|
|
||||||
$this->cacheQueries = false;
|
|
||||||
|
|
||||||
return $account['Account']['name'];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: Account IDs
|
|
||||||
* - Returns the ID of the desired account
|
|
||||||
*/
|
|
||||||
|
|
||||||
function securityDepositAccountID() { return $this->nameToID('Security Deposit'); }
|
|
||||||
function rentAccountID() { return $this->nameToID('Rent'); }
|
|
||||||
function lateChargeAccountID() { return $this->nameToID('Late Charge'); }
|
|
||||||
function nsfAccountID() { return $this->nameToID('NSF'); }
|
|
||||||
function nsfChargeAccountID() { return $this->nameToID('NSF Charge'); }
|
|
||||||
function taxAccountID() { return $this->nameToID('Tax'); }
|
|
||||||
function accountReceivableAccountID() { return $this->nameToID('A/R'); }
|
|
||||||
function cashAccountID() { return $this->nameToID('Cash'); }
|
|
||||||
function checkAccountID() { return $this->nameToID('Check'); }
|
|
||||||
function moneyOrderAccountID() { return $this->nameToID('Money Order'); }
|
|
||||||
function concessionAccountID() { return $this->nameToID('Concession'); }
|
|
||||||
function pettyCashAccountID() { return $this->nameToID('Petty Cash'); }
|
|
||||||
function invoiceAccountID() { return $this->nameToID('Invoice'); }
|
|
||||||
function receiptAccountID() { return $this->nameToID('Receipt'); }
|
|
||||||
function badDebtAccountID() { return $this->nameToID('Bad Debt'); }
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: fundamentalAccounts
|
|
||||||
* - Returns an array of accounts by their fundamental type
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fundamentalAccounts($ftype) {
|
|
||||||
$this->cacheQueries = true;
|
|
||||||
$account = $this->find('all', array
|
|
||||||
('contain' => array('CurrentLedger'),
|
|
||||||
'fields' => array('Account.id', 'Account.type', 'Account.name', 'CurrentLedger.id'),
|
|
||||||
'conditions' => array('Account.type' => strtoupper($ftype))
|
|
||||||
));
|
|
||||||
$this->cacheQueries = false;
|
|
||||||
|
|
||||||
return $account;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: relatedAccounts
|
|
||||||
* - Returns an array of accounts related by similar attributes
|
|
||||||
*/
|
|
||||||
|
|
||||||
function relatedAccounts($attribute, $extra = null) {
|
|
||||||
$this->cacheQueries = true;
|
|
||||||
$account = $this->find('all', array
|
|
||||||
('contain' => array('CurrentLedger'),
|
|
||||||
'fields' => array('Account.id', 'Account.type', 'Account.name', 'CurrentLedger.id'),
|
|
||||||
'conditions' => array('Account.'.$attribute => true),
|
|
||||||
'order' => array('Account.name'),
|
|
||||||
) + (isset($extra) ? $extra : array())
|
|
||||||
);
|
|
||||||
$this->cacheQueries = false;
|
|
||||||
|
|
||||||
return $account;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: chargeAccounts
|
|
||||||
* - Returns an array of accounts suitable for charges
|
|
||||||
*/
|
|
||||||
|
|
||||||
function chargeAccounts() {
|
|
||||||
// Get all accounts that support charges
|
|
||||||
$accounts = $this->relatedAccounts('chargeable', array('order' => 'name'));
|
|
||||||
|
|
||||||
// Rearrange to be of the form (id => name)
|
|
||||||
$charge_accounts = array();
|
|
||||||
foreach ($accounts AS $acct) {
|
|
||||||
$charge_accounts[$acct['Account']['id']] = $acct['Account']['name'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $charge_accounts;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: paymentAccounts
|
|
||||||
* - Returns an array of accounts suitable for payments
|
|
||||||
*/
|
|
||||||
|
|
||||||
function paymentAccounts() {
|
|
||||||
// Get all accounts that support payments
|
|
||||||
$accounts = $this->relatedAccounts('payable', array('order' => 'name'));
|
|
||||||
|
|
||||||
// Rearrange to be of the form (id => name)
|
|
||||||
$payment_accounts = array();
|
|
||||||
foreach ($accounts AS $acct) {
|
|
||||||
$payment_accounts[$acct['Account']['id']] = $acct['Account']['name'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $payment_accounts;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: collectableAccounts
|
|
||||||
* - Returns an array of accounts suitable to show income collection
|
|
||||||
*/
|
|
||||||
|
|
||||||
function collectableAccounts() {
|
|
||||||
$accounts = $this->paymentAccounts();
|
|
||||||
|
|
||||||
foreach(array($this->nsfAccountID(),
|
|
||||||
$this->securityDepositAccountID())
|
|
||||||
AS $account_id) {
|
|
||||||
$accounts[$account_id] = $this->name($account_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $accounts;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: currentLedgerID
|
|
||||||
* - Returns the current ledger ID of the account
|
|
||||||
*/
|
|
||||||
function currentLedgerID($id) {
|
|
||||||
$this->cacheQueries = true;
|
|
||||||
$item = $this->find('first', array
|
|
||||||
('contain' => 'CurrentLedger',
|
|
||||||
'conditions' => array('Account.id' => $id),
|
|
||||||
));
|
|
||||||
$this->cacheQueries = false;
|
|
||||||
return $item['CurrentLedger']['id'];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: ledgers
|
|
||||||
* - Returns an array of ledger ids from the given account
|
|
||||||
*/
|
|
||||||
function ledgers($id, $all = false) {
|
|
||||||
if ($all) {
|
|
||||||
$contain = array('Ledger' => array('fields' => array('Ledger.id')));
|
|
||||||
} else {
|
|
||||||
$contain = array('CurrentLedger' => array('fields' => array('CurrentLedger.id')));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->cacheQueries = true;
|
|
||||||
$account = $this->find('first', array
|
|
||||||
('contain' => $contain,
|
|
||||||
'fields' => array(),
|
|
||||||
'conditions' => array(array('Account.id' => $id)),
|
|
||||||
));
|
|
||||||
$this->cacheQueries = false;
|
|
||||||
|
|
||||||
if ($all) {
|
|
||||||
$ledger_ids = array();
|
|
||||||
foreach ($account['Ledger'] AS $ledger)
|
|
||||||
array_push($ledger_ids, $ledger['id']);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$ledger_ids = array($account['CurrentLedger']['id']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* pr(array('function' => 'Account::ledgers', */
|
|
||||||
/* 'args' => compact('id', 'all'), */
|
|
||||||
/* 'return' => $ledger_ids)); */
|
|
||||||
|
|
||||||
return $ledger_ids;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: closeCurrentLedger
|
|
||||||
* - Closes the current account ledger, and opens a new one
|
|
||||||
* with the old balance carried forward.
|
|
||||||
*/
|
|
||||||
function closeCurrentLedger($id = null, $close_id = null) {
|
|
||||||
$contain = array('CurrentLedger' => array('fields' => array('CurrentLedger.id')));
|
|
||||||
|
|
||||||
if (!$close_id) {
|
|
||||||
$close = new Close();
|
|
||||||
$close->create();
|
|
||||||
if (!$close->save(array('stamp' => null), false)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$close_id = $close->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->cacheQueries = true;
|
|
||||||
$account = $this->find('all', array
|
|
||||||
('contain' => $contain,
|
|
||||||
'fields' => array(),
|
|
||||||
'conditions' =>
|
|
||||||
$id ? array(array('Account.id' => $id)) : array()
|
|
||||||
));
|
|
||||||
$this->cacheQueries = false;
|
|
||||||
//pr(compact('id', 'account'));
|
|
||||||
|
|
||||||
foreach ($account AS $acct) {
|
|
||||||
if (!$this->Ledger->closeLedger($acct['CurrentLedger']['id'], $close_id))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: findLedgerEntries
|
|
||||||
* - Returns an array of ledger entries that belong to the given
|
|
||||||
* account, either just from the current ledger, or from all ledgers.
|
|
||||||
*/
|
|
||||||
function findLedgerEntries($id, $all = false, $cond = null, $link = null) {
|
|
||||||
/* pr(array('function' => 'Account::findLedgerEntries', */
|
|
||||||
/* 'args' => compact('id', 'all', 'cond', 'link'), */
|
|
||||||
/* )); */
|
|
||||||
|
|
||||||
$entries = array();
|
|
||||||
foreach ($this->ledgers($id, $all) AS $ledger_id) {
|
|
||||||
$ledger_entries = $this->Ledger->findLedgerEntries
|
|
||||||
($ledger_id, $this->type($id), $cond, $link);
|
|
||||||
$entries = array_merge($entries, $ledger_entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
$stats = $this->stats($id, $all, $cond);
|
|
||||||
$entries = array('Entries' => $entries,
|
|
||||||
'summary' => $stats['Ledger']);
|
|
||||||
|
|
||||||
/* pr(array('function' => 'Account::findLedgerEntries', */
|
|
||||||
/* 'args' => compact('id', 'all', 'cond', 'link'), */
|
|
||||||
/* 'vars' => compact('stats'), */
|
|
||||||
/* 'return' => compact('entries'), */
|
|
||||||
/* )); */
|
|
||||||
|
|
||||||
return $entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: findLedgerEntriesRelatedToAccount
|
|
||||||
* - Returns an array of ledger entries that belong to the given
|
|
||||||
* account, and are related to a specific account, either just from
|
|
||||||
* the current ledger, or from all ledgers.
|
|
||||||
*/
|
|
||||||
function findLedgerEntriesRelatedToAccount($id, $rel_ids, $all = false, $cond = null, $link = null) {
|
|
||||||
/* pr(array('function' => 'Account::findLedgerEntriesRelatedToAccount', */
|
|
||||||
/* 'args' => compact('id', 'rel_ids', 'all', 'cond', 'link'), */
|
|
||||||
/* )); */
|
|
||||||
|
|
||||||
if (!isset($cond))
|
|
||||||
$cond = array();
|
|
||||||
if (!is_array($rel_ids))
|
|
||||||
$rel_ids = array($rel_ids);
|
|
||||||
|
|
||||||
$ledger_ids = array();
|
|
||||||
foreach ($rel_ids AS $rel_id)
|
|
||||||
$ledger_ids = array_merge($ledger_ids, $this->ledgers($rel_id));
|
|
||||||
|
|
||||||
array_push($cond, $this->Ledger->LedgerEntry->conditionEntryAsCreditOrDebit($ledger_ids));
|
|
||||||
$entries = $this->findLedgerEntries($id, $all, $cond, $link);
|
|
||||||
|
|
||||||
/* pr(array('function' => 'Account::findLedgerEntriesRelatedToAccount', */
|
|
||||||
/* 'args' => compact('id', 'relid', 'all', 'cond', 'link'), */
|
|
||||||
/* 'vars' => compact('ledger_ids'), */
|
|
||||||
/* 'return' => compact('entries'), */
|
|
||||||
/* )); */
|
|
||||||
return $entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: findUnreconciledLedgerEntries
|
|
||||||
* - Returns ledger entries that are not yet reconciled
|
|
||||||
* (such as charges not paid).
|
|
||||||
*/
|
|
||||||
|
|
||||||
function findUnreconciledLedgerEntries($id = null, $fundamental_type = null, $cond = null) {
|
|
||||||
if (!isset($cond))
|
|
||||||
$cond = array();
|
|
||||||
$cond[] = array('Account.id' => $id);
|
|
||||||
|
|
||||||
foreach (($fundamental_type
|
|
||||||
? array($fundamental_type)
|
|
||||||
: array('debit', 'credit')) AS $fund) {
|
|
||||||
$ucfund = ucfirst($fund);
|
|
||||||
$unreconciled[$fund]['entry'] = $this->find
|
|
||||||
('all', array
|
|
||||||
('link' => array
|
|
||||||
('Ledger' => array
|
|
||||||
('fields' => array(),
|
|
||||||
"LedgerEntry" => array
|
|
||||||
('class' => "{$ucfund}LedgerEntry",
|
|
||||||
'fields' => array('id', 'customer_id', 'lease_id', 'amount'),
|
|
||||||
"ReconciliationLedgerEntry" => array
|
|
||||||
('class' => "{$ucfund}ReconciliationLedgerEntry",
|
|
||||||
'fields' => array
|
|
||||||
("COALESCE(SUM(Reconciliation.amount),0) AS 'reconciled'",
|
|
||||||
"LedgerEntry.amount - COALESCE(SUM(Reconciliation.amount),0) AS 'balance'",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'group' => ("LedgerEntry.id" .
|
|
||||||
" HAVING LedgerEntry.amount" .
|
|
||||||
" <> COALESCE(SUM(Reconciliation.amount),0)"),
|
|
||||||
'conditions' => $cond,
|
|
||||||
'fields' => array(),
|
|
||||||
));
|
|
||||||
$balance = 0;
|
|
||||||
foreach ($unreconciled[$fund]['entry'] AS &$entry) {
|
|
||||||
$entry = array_merge(array_diff_key($entry["LedgerEntry"], array(0=>true)),
|
|
||||||
$entry[0]);
|
|
||||||
$balance += $entry['balance'];
|
|
||||||
}
|
|
||||||
$unreconciled[$fund]['balance'] = $balance;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $unreconciled;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: reconcileNewLedgerEntry
|
|
||||||
* - Returns which ledger entries a new credit/debit would
|
|
||||||
* reconcile, and how much.
|
|
||||||
*
|
|
||||||
* - REVISIT <AP> 20090617
|
|
||||||
* This should be subject to different algorithms, such
|
|
||||||
* as apply to oldest charges first, newest first, to fees
|
|
||||||
* before rent, etc. Until we get there, I'll hardcode
|
|
||||||
* whatever algorithm is simplest.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function reconcileNewLedgerEntry($id, $fundamental_type, $amount, $cond = null) {
|
|
||||||
$ofund = $this->fundamentalOpposite($fundamental_type);
|
|
||||||
$unreconciled = array($ofund => array('entry'=>array(), 'balance'=>0));
|
|
||||||
$applied = 0;
|
|
||||||
|
|
||||||
// if there is no money in the entry, it can reconcile nothing
|
|
||||||
// don't bother wasting time sifting ledger entries.
|
|
||||||
if ($amount > 0) {
|
|
||||||
$unreconciled = $this->findUnreconciledLedgerEntries($id, $ofund, $cond);
|
|
||||||
|
|
||||||
foreach ($unreconciled[$ofund]['entry'] AS $i => &$entry) {
|
|
||||||
// Determine if amount is sufficient to cover the entry
|
|
||||||
if ($amount > $entry['balance'])
|
|
||||||
$apply = $entry['balance'];
|
|
||||||
elseif ($amount > 0)
|
|
||||||
$apply = $amount;
|
|
||||||
else {
|
|
||||||
unset($unreconciled[$ofund]['entry'][$i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$entry['applied'] = $apply;
|
|
||||||
$entry['reconciled'] += $apply;
|
|
||||||
$entry['balance'] -= $apply;
|
|
||||||
$applied += $apply;
|
|
||||||
$amount -= $apply;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$unreconciled[$ofund]['unapplied'] = $amount;
|
|
||||||
$unreconciled[$ofund]['applied'] = $applied;
|
|
||||||
$unreconciled[$ofund]['balance'] -= $applied;
|
|
||||||
return $unreconciled;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: postLedgerEntry
|
|
||||||
* -
|
|
||||||
* transaction_data
|
|
||||||
* - transaction_id (optional... if set all else is ignored)
|
|
||||||
* - Transaction
|
|
||||||
* - stamp (optional... otherwise NOW is used)
|
|
||||||
* - comment
|
|
||||||
*
|
|
||||||
* monetary_source_data
|
|
||||||
* - monetary_source_id (optional... if set all else is ignored)
|
|
||||||
* - account_name
|
|
||||||
* - MonetarySource
|
|
||||||
* - name
|
|
||||||
*/
|
|
||||||
|
|
||||||
function postLedgerEntry($transaction_data,
|
|
||||||
$monetary_data,
|
|
||||||
$entry_data,
|
|
||||||
$reconcile = null) {
|
|
||||||
//pr(compact('transaction_data', 'monetary_data', 'entry_data', 'reconcile'));
|
|
||||||
|
|
||||||
// Automatically figure out the customer if we have the lease
|
|
||||||
if (isset($entry_data['lease_id']) && !isset($entry_data['customer_id'])) {
|
|
||||||
$L = new Lease();
|
|
||||||
$L->recursive = -1;
|
|
||||||
$lease = $L->read(null, $entry_data['lease_id']);
|
|
||||||
$entry_data['customer_id'] = $lease['Lease']['customer_id'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($entry_data['lease_id']))
|
|
||||||
$entry_data['lease_id'] = null;
|
|
||||||
|
|
||||||
if (!isset($entry_data['customer_id']))
|
|
||||||
$entry_data['customer_id'] = null;
|
|
||||||
|
|
||||||
// Get the Transaction squared away
|
|
||||||
if (isset($transaction_data['transaction_id'])) {
|
|
||||||
$transaction_data
|
|
||||||
= array_intersect_key($transaction_data,
|
|
||||||
array('transaction_id'=>1,
|
|
||||||
'split_transaction_id'=>1));
|
|
||||||
}
|
|
||||||
elseif (isset($transaction_data['Transaction'])) {
|
|
||||||
$transaction_data
|
|
||||||
= array_intersect_key($transaction_data,
|
|
||||||
array('Transaction'=>1,
|
|
||||||
'split_transaction_id'=>1));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$transaction_data = array('Transaction'=>array('stamp' => null));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Get the Monetary Source squared away
|
|
||||||
if (isset($monetary_data)) {
|
|
||||||
if (!isset($monetary_data['monetary_source_id'])) {
|
|
||||||
|
|
||||||
// Convert Account ID to name or vice versa
|
|
||||||
if (isset($monetary_data['account_id'])) {
|
|
||||||
$monetary_data['account_name'] = $this->name($monetary_data['account_id']);
|
|
||||||
} elseif (isset($monetary_data['account_name'])) {
|
|
||||||
$monetary_data['account_id'] = $this->nameToID($monetary_data['account_name']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($monetary_data['account_id'] == $this->cashAccountID()) {
|
|
||||||
// No distinguishing features of Cash, just
|
|
||||||
// use the shared monetary source
|
|
||||||
$monetary_data['monetary_source_id'] =
|
|
||||||
$this->Ledger->LedgerEntry->MonetarySource->nameToID('Cash');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($monetary_data['monetary_source_id'])) {
|
|
||||||
$monetary_data
|
|
||||||
= array_intersect_key($monetary_data,
|
|
||||||
array('monetary_source_id'=>1));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// The monetary source needs to be unique
|
|
||||||
// Create a new one dedicated to this entry
|
|
||||||
// Give it a fancy name based on the check number
|
|
||||||
$monetary_data['MonetarySource']['name'] = $monetary_data['account_name'];
|
|
||||||
if ($monetary_data['account_name'] === $this->name($this->checkAccountID()) ||
|
|
||||||
$monetary_data['account_name'] === $this->name($this->moneyOrderAccountID())) {
|
|
||||||
$monetary_data['MonetarySource']['name'] .=
|
|
||||||
' #' . $monetary_data['MonetarySource']['data1'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$monetary_data
|
|
||||||
= array_intersect_key($monetary_data,
|
|
||||||
array('MonetarySource'=>1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$monetary_data = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure to clean out any unwanted data from the entry
|
|
||||||
$entry_data
|
|
||||||
= array_diff_key($entry_data,
|
|
||||||
array('transaction_id'=>1, 'Transaction'=>1,
|
|
||||||
'monetary_source_id'=>1, 'MonetarySource'=>1));
|
|
||||||
|
|
||||||
// Then add in the transaction and monetary source data
|
|
||||||
//pr(compact('transaction_data', 'monetary_data', 'entry_data'));
|
|
||||||
if (isset($transaction_data))
|
|
||||||
$entry_data += $transaction_data;
|
|
||||||
if (isset($monetary_data))
|
|
||||||
$entry_data += $monetary_data;
|
|
||||||
|
|
||||||
// Set up the debit ledger id
|
|
||||||
if (!isset($entry_data['debit_ledger_id'])) {
|
|
||||||
$entry_data['debit_ledger_id'] =
|
|
||||||
(isset($entry_data['debit_account_id'])
|
|
||||||
? $this->currentLedgerID($entry_data['debit_account_id'])
|
|
||||||
: (isset($entry_data['debit_account_name'])
|
|
||||||
? $this->currentLedgerID($this->nameToID($entry_data['debit_account_name']))
|
|
||||||
: null
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up the credit ledger id
|
|
||||||
if (!isset($entry_data['credit_ledger_id'])) {
|
|
||||||
$entry_data['credit_ledger_id'] =
|
|
||||||
(isset($entry_data['credit_account_id'])
|
|
||||||
? $this->currentLedgerID($entry_data['credit_account_id'])
|
|
||||||
: (isset($entry_data['credit_account_name'])
|
|
||||||
? $this->currentLedgerID($this->nameToID($entry_data['credit_account_name']))
|
|
||||||
: null
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//pr(array('pre-save', compact('entry_data')));
|
|
||||||
// Create it!
|
|
||||||
$new_entry = new LedgerEntry();
|
|
||||||
$new_entry->create();
|
|
||||||
if (!$new_entry->saveAll($entry_data, array('validate'=>false))) {
|
|
||||||
return array('error' => true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if the user has entered some sort of non-array
|
|
||||||
// for the reconcile parameter.
|
|
||||||
if (isset($reconcile) && is_bool($reconcile) && $reconcile) {
|
|
||||||
$reconcile = array('debit' => true, 'credit' => true);
|
|
||||||
}
|
|
||||||
elseif (isset($reconcile) && $reconcile == 'invoice') {
|
|
||||||
$reconcile = array('credit' => 'invoice');
|
|
||||||
}
|
|
||||||
elseif (isset($reconcile) && $reconcile == 'receipt') {
|
|
||||||
$reconcile = array('debit' => 'receipt');
|
|
||||||
}
|
|
||||||
elseif (!isset($reconcile) || !is_array($reconcile)) {
|
|
||||||
$reconcile = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reconcile the new entry... assume we'll have success
|
|
||||||
$err = false;
|
|
||||||
foreach (array_intersect_key($reconcile, array('credit'=>1,'debit'=>1))
|
|
||||||
AS $dc_type => $reconcile_set) {
|
|
||||||
if (!isset($reconcile_set) || (is_bool($reconcile_set) && !$reconcile_set))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ($reconcile_set === 'receipt') {
|
|
||||||
$C = new Customer();
|
|
||||||
$reconciled = $C->reconcileNewLedgerEntry($entry_data['customer_id'],
|
|
||||||
$this->fundamentalOpposite($dc_type),
|
|
||||||
$entry_data['amount']);
|
|
||||||
|
|
||||||
/* pr(array("reconcile receipt", */
|
|
||||||
/* compact('reconciled', 'split_transaction', 'transaction_data'))); */
|
|
||||||
$split_transaction = array_intersect_key($transaction_data,
|
|
||||||
array('Transaction'=>1,
|
|
||||||
'split_transaction_id'=>1));
|
|
||||||
|
|
||||||
if (isset($split_transaction['split_transaction_id']))
|
|
||||||
$split_transaction['transaction_id'] = $split_transaction['split_transaction_id'];
|
|
||||||
|
|
||||||
if (is_array($reconciled) && count($reconciled[$dc_type]['entry'])) {
|
|
||||||
foreach ($reconciled[$dc_type]['entry'] AS $rec) {
|
|
||||||
//pr(compact('rec', 'split_transaction'));
|
|
||||||
if (!$rec['applied'])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Create an entry to handle the splitting of the funds ("Payment")
|
|
||||||
// and reconcile against the new cash/check/etc entry created above,
|
|
||||||
// as well as the A/R account.
|
|
||||||
|
|
||||||
// Payment must debit the Receipt ledger, and credit the A/R ledger
|
|
||||||
// debit: Receipt credit: A/R
|
|
||||||
$ids = $this->postLedgerEntry
|
|
||||||
($split_transaction,
|
|
||||||
null,
|
|
||||||
array('debit_ledger_id' => $this->currentLedgerID($this->receiptAccountID()),
|
|
||||||
'credit_ledger_id' => $this->currentLedgerID($this->accountReceivableAccountID()),
|
|
||||||
'amount' => $rec['applied'],
|
|
||||||
'lease_id' => $rec['lease_id'],
|
|
||||||
'customer_id' => $rec['customer_id'],
|
|
||||||
),
|
|
||||||
array('debit' => array(array('LedgerEntry' => array('id' => $new_entry->id,
|
|
||||||
'amount' => $rec['applied']))),
|
|
||||||
'credit' => array(array('LedgerEntry' => array('id' => $rec['id'],
|
|
||||||
'amount' => $rec['applied']))))
|
|
||||||
);
|
|
||||||
// Keep using the same split transaction for all reconciled entries
|
|
||||||
$split_transaction = array_intersect_key($ids, array('transaction_id'=>1));
|
|
||||||
//pr(compact('ids', 'split_transaction'));
|
|
||||||
}
|
|
||||||
|
|
||||||
//pr("end reconciled is array");
|
|
||||||
}
|
|
||||||
|
|
||||||
//pr("end reconcile receipt");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_array($reconcile_set)) {
|
|
||||||
//pr("reconcile_set is array");
|
|
||||||
foreach ($reconcile_set AS $reconcile_entry) {
|
|
||||||
if (!isset($reconcile_entry['LedgerEntry']['id']))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
$amount = $reconcile_entry['LedgerEntry']['amount'];
|
|
||||||
if (!$amount)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ($dc_type == 'debit') {
|
|
||||||
$debit_ledger_entry_id = $new_entry->id;
|
|
||||||
$credit_ledger_entry_id = $reconcile_entry['LedgerEntry']['id'];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$debit_ledger_entry_id = $reconcile_entry['LedgerEntry']['id'];
|
|
||||||
$credit_ledger_entry_id = $new_entry->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
$R = new Reconciliation();
|
|
||||||
$R->create();
|
|
||||||
if (!$R->save(compact('amount',
|
|
||||||
'debit_ledger_entry_id',
|
|
||||||
'credit_ledger_entry_id'), false))
|
|
||||||
$err = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$new_entry->recursive = -1;
|
|
||||||
$new_entry->read();
|
|
||||||
//pr(array('post-save', $entry->data));
|
|
||||||
|
|
||||||
$ret = array
|
|
||||||
('error' => $err,
|
|
||||||
'id' => $new_entry->data['LedgerEntry']['id'],
|
|
||||||
'transaction_id' => $new_entry->data['LedgerEntry']['transaction_id'],
|
|
||||||
'monetary_source_id' => $new_entry->data['LedgerEntry']['monetary_source_id']);
|
|
||||||
|
|
||||||
if (isset($split_transaction['transaction_id']))
|
|
||||||
$ret['split_transaction_id'] = $split_transaction['transaction_id'];
|
|
||||||
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: closeAndDeposit
|
|
||||||
* - Closes the current set of ledgers, transferring
|
|
||||||
* their balances to specified ledger.
|
|
||||||
*/
|
|
||||||
function closeAndDeposit($set, $deposit_account_id) {
|
|
||||||
|
|
||||||
$close = new Close();
|
|
||||||
$close->create();
|
|
||||||
if (!$close->save(array('stamp' => null, 'comment' => 'Deposit'), false)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$transaction = array();
|
|
||||||
foreach ($set AS $ledger) {
|
|
||||||
// REVISIT <AP>: 20090710
|
|
||||||
// If the user said to include a ledger in the
|
|
||||||
// set, should we really be excluding it?
|
|
||||||
if ($ledger['total'] == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
$ids = $this->postLedgerEntry
|
|
||||||
($transaction,
|
|
||||||
null,
|
|
||||||
array('debit_account_id' => $deposit_account_id,
|
|
||||||
'credit_ledger_id' => $ledger['id'],
|
|
||||||
'amount' => $ledger['total']),
|
|
||||||
// Reconcile the account for cash/check/etc,
|
|
||||||
// which is the credit side of this entry.
|
|
||||||
array('credit' => $ledger['entries']));
|
|
||||||
//pr(compact('ids'));
|
|
||||||
|
|
||||||
if ($ids['error'])
|
|
||||||
die("closeAndDeposit : postLedgerEntry returned error!");
|
|
||||||
|
|
||||||
$transaction = array_intersect_key($ids, array('transaction_id'=>1));
|
|
||||||
|
|
||||||
$this->Ledger->closeLedger($ledger['id'], $close->id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: stats
|
|
||||||
* - Returns summary data from the requested account.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function stats($id = null, $all = false, $cond = null) {
|
|
||||||
if (!$id)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
// All old, closed ledgers MUST balance to 0.
|
|
||||||
// However, the user may want the ENTIRE running totals,
|
|
||||||
// (not just the balance), so we may have to query all
|
|
||||||
// ledgers, as dictated by the $all parameter.
|
|
||||||
|
|
||||||
$account = $this->find('first',
|
|
||||||
array('contain' =>
|
|
||||||
($all
|
|
||||||
? array('Ledger' => array
|
|
||||||
('fields' => array('id')))
|
|
||||||
: array('CurrentLedger' => array
|
|
||||||
('fields' => array('id')))
|
|
||||||
),
|
|
||||||
'conditions' => array
|
|
||||||
(array('Account.id' => $id))
|
|
||||||
));
|
|
||||||
|
|
||||||
$stats = array();
|
|
||||||
if ($all) {
|
|
||||||
foreach ($account['Ledger'] AS $ledger)
|
|
||||||
$this->statsMerge($stats['Ledger'],
|
|
||||||
$this->Ledger->stats($ledger['id'], $cond));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$stats['Ledger'] =
|
|
||||||
$this->Ledger->stats($account['CurrentLedger']['id'], $cond);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $stats;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user