Pseudo merge-in, which is a wholesale copy from the branch directly to trunk. This is fine since trunk has always been empty up to this point.
git-svn-id: file:///svn-source/pmgr/trunk/site@732 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
5
.htaccess
Normal file
5
.htaccess
Normal file
@@ -0,0 +1,5 @@
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine on
|
||||
RewriteRule ^$ webroot/ [L]
|
||||
RewriteRule (.*) webroot/$1 [L]
|
||||
</IfModule>
|
||||
881
app_controller.php
Normal file
881
app_controller.php
Normal file
@@ -0,0 +1,881 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: app_controller.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||
/**
|
||||
* Short description for file.
|
||||
*
|
||||
* This file is application-wide controller file. You can put all
|
||||
* application-wide controller-related methods here.
|
||||
*
|
||||
* 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.app
|
||||
* @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
|
||||
*/
|
||||
/**
|
||||
* Short description for class.
|
||||
*
|
||||
* Add your application-wide methods in the class below, your controllers
|
||||
* will inherit them.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.app
|
||||
*/
|
||||
class AppController extends Controller {
|
||||
var $helpers = array('Html', 'Form', 'Javascript', 'Format', 'Time', 'Grid');
|
||||
var $components = array('DebugKit.Toolbar');
|
||||
|
||||
function __construct() {
|
||||
$this->params['dev'] = false;
|
||||
$this->params['admin'] = false;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
function sideMenuLinks() {
|
||||
// Stupid Cake... our constructor sets admin/dev,
|
||||
// but cake stomps it somewhere along the way
|
||||
// after constructing the CakeError controller.
|
||||
if ($this->name === 'CakeError') {
|
||||
$this->params['dev'] = false;
|
||||
$this->params['admin'] = false;
|
||||
}
|
||||
|
||||
$menu = array();
|
||||
$menu[] = array('name' => 'Common', 'header' => true);
|
||||
$menu[] = array('name' => 'Site Map', 'url' => array('controller' => 'maps', 'action' => 'view', 1));
|
||||
$menu[] = array('name' => 'Units', 'url' => array('controller' => 'units', 'action' => 'index'));
|
||||
$menu[] = array('name' => 'Leases', 'url' => array('controller' => 'leases', 'action' => 'index'));
|
||||
$menu[] = array('name' => 'Customers', 'url' => array('controller' => 'customers', 'action' => 'index'));
|
||||
$menu[] = array('name' => 'Deposits', 'url' => array('controller' => 'transactions', 'action' => 'deposit'));
|
||||
|
||||
if ($this->params['admin']) {
|
||||
$menu[] = array('name' => 'Admin', 'header' => true);
|
||||
$menu[] = array('name' => 'Accounts', 'url' => array('controller' => 'accounts', 'action' => 'index'));
|
||||
$menu[] = array('name' => 'Contacts', 'url' => array('controller' => 'contacts', 'action' => 'index'));
|
||||
$menu[] = array('name' => 'Ledgers', 'url' => array('controller' => 'ledgers', 'action' => 'index'));
|
||||
$menu[] = array('name' => 'Tenders', 'url' => array('controller' => 'tenders', 'action' => 'index'));
|
||||
$menu[] = array('name' => 'Transactions', 'url' => array('controller' => 'transactions', 'action' => 'index'));
|
||||
$menu[] = array('name' => 'Ldgr Entries', 'url' => array('controller' => 'ledger_entries', 'action' => 'index'));
|
||||
$menu[] = array('name' => 'Stmt Entries', 'url' => array('controller' => 'statement_entries', 'action' => 'index'));
|
||||
$menu[] = array('name' => 'New Ledgers', 'url' => array('controller' => 'accounts', 'action' => 'newledger'));
|
||||
$menu[] = array('name' => 'Assess Charges', 'url' => array('controller' => 'leases', 'action' => 'assess_all'));
|
||||
}
|
||||
|
||||
if ($this->params['dev']) {
|
||||
$menu[] = array('name' => 'Development', 'header' => true);
|
||||
$menu[] = array('name' => 'Un-Nuke', 'url' => '#', 'htmlAttributes' =>
|
||||
array('onclick' => '$(".pr-section").show(); return false;'));
|
||||
$menu[] = array('name' => 'New Ledgers', 'url' => array('controller' => 'accounts', 'action' => 'newledger'));
|
||||
//array('name' => 'RESET DATA', 'url' => array('controller' => 'accounts', 'action' => 'reset_data'));
|
||||
}
|
||||
|
||||
return $menu;
|
||||
}
|
||||
|
||||
function beforeFilter() {
|
||||
$this->params['dev'] =
|
||||
(!empty($this->params['dev_route']));
|
||||
$this->params['admin'] =
|
||||
(!empty($this->params['admin_route']) || !empty($this->params['dev_route']));
|
||||
|
||||
if (!$this->params['dev'])
|
||||
Configure::write('debug', '0');
|
||||
}
|
||||
|
||||
function beforeRender() {
|
||||
$this->set('sidemenu', $this->sideMenuLinks());
|
||||
}
|
||||
|
||||
function redirect($url, $status = null, $exit = true) {
|
||||
// OK, since the controller will not be able to
|
||||
// utilize our overriden url function in AppHelper,
|
||||
// we'll have to do it manually here.
|
||||
App::import('Helper', 'Html');
|
||||
$url = HtmlHelper::url($url, true);
|
||||
|
||||
if (headers_sent()) {
|
||||
// If we've already sent the headers, it's because
|
||||
// we're debugging, and our debug output has gotten
|
||||
// out before the redirect. That's probably a good
|
||||
// thing, as we don't typically want pages to be
|
||||
// jerked out from under us while trying to read
|
||||
// the debug output. So, since we can't redirect
|
||||
// anyway, we may as well go with the flow and just
|
||||
// render this page instead, using an empty template
|
||||
$this->set('message',
|
||||
("Intended redirect:<P><BR>" .
|
||||
'<A HREF="'.$url.'">'.$url.'</A>'));
|
||||
|
||||
echo $this->render('/empty');
|
||||
if ($exit)
|
||||
$this->_stop();
|
||||
}
|
||||
|
||||
return parent::redirect($url, $status, $exit);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* helper: gridView
|
||||
* - called by derived controllers to create an index listing
|
||||
*/
|
||||
|
||||
function gridView($title, $action = null, $element = null) {
|
||||
$this->set('title', $title);
|
||||
// The resulting page will contain a grid, which will
|
||||
// use ajax to obtain the actual data for this action
|
||||
$this->set('action', $action ? $action : $this->params['action']);
|
||||
$this->render('/elements/' . ($element ? $element : $this->params['controller']));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: gridData
|
||||
* - Fetches the actual data requested by grid as XML
|
||||
*/
|
||||
|
||||
function gridData() {
|
||||
// Grab a copy of the parameters that control this request
|
||||
$params = array();
|
||||
if (isset($this->params['url']) && is_array($this->params['url']))
|
||||
$params = $this->params['url'];
|
||||
|
||||
// Do any preliminary setup necessary
|
||||
$this->gridDataSetup($params);
|
||||
|
||||
// Get the top level model for this grid
|
||||
$model = $this->gridDataModel($params);
|
||||
|
||||
// Get the number of records prior to pagination
|
||||
$count = $this->gridDataCount($params, $model);
|
||||
|
||||
// Determine pagination configuration (and save to $params)
|
||||
$pagination = $this->gridDataPagination($params, $model, $count);
|
||||
|
||||
// Retreive the appropriate subset of data
|
||||
$records = $this->gridDataRecords($params, $model, $pagination);
|
||||
|
||||
// Post process the records
|
||||
$this->gridDataPostProcess($params, $model, $records);
|
||||
|
||||
// Output the resulting record set
|
||||
$this->gridDataOutput($params, $model, $records, $pagination);
|
||||
|
||||
// Call out to finalize everything
|
||||
$this->gridDataFinalize($params);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* virtual: gridData* functions
|
||||
* - These set up the context for the grid data, and will
|
||||
* need to be overridden in the derived class for anything
|
||||
* other than the most basic of grids.
|
||||
*/
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* gridData SETUP / CLEANUP
|
||||
*/
|
||||
|
||||
function gridDataModel(&$params) {
|
||||
return $this->{$this->modelClass};
|
||||
}
|
||||
|
||||
function gridDataSetup(&$params) {
|
||||
// Debug only if requested
|
||||
$params['debug'] = !empty($this->passedArgs['debug']);
|
||||
|
||||
if ($params['debug']) {
|
||||
ob_start();
|
||||
}
|
||||
else {
|
||||
$this->layout = null;
|
||||
$this->autoLayout = false;
|
||||
$this->autoRender = false;
|
||||
Configure::write('debug', '0');
|
||||
}
|
||||
|
||||
// Establish some defaults (except for serialized items)
|
||||
$params = array_merge(array('page' => 1,
|
||||
'rows' => 20),
|
||||
$params);
|
||||
|
||||
// Unserialize our complex structure of post data.
|
||||
// This SHOULD always be set, except when debugging
|
||||
if (isset($params['post']))
|
||||
$params['post'] = unserialize($params['post']);
|
||||
else
|
||||
$params['post'] = array();
|
||||
|
||||
// Unserialize our complex structure of dynamic post data
|
||||
if (isset($params['dynamic_post']))
|
||||
$params['dynamic_post'] = unserialize($params['dynamic_post']);
|
||||
else
|
||||
$params['dynamic_post'] = null;
|
||||
|
||||
// Unserialize our complex structure of dynamic post data
|
||||
if (isset($params['dynamic_post_replace']))
|
||||
$params['dynamic_post_replace'] = unserialize($params['dynamic_post_replace']);
|
||||
else
|
||||
$params['dynamic_post_replace'] = null;
|
||||
|
||||
// Merge the static and dynamic post data
|
||||
if (!empty($params['dynamic_post']))
|
||||
$params['post'] = array_merge_recursive($params['post'], $params['dynamic_post']);
|
||||
if (!empty($params['dynamic_post_replace']))
|
||||
$params['post'] = array_merge($params['post'], $params['dynamic_post_replace']);
|
||||
|
||||
// This SHOULD always be set, except when debugging
|
||||
if (!isset($params['post']['fields']))
|
||||
$params['post']['fields'] = array($this->{$this->modelClass}->alias
|
||||
.'.'.
|
||||
$this->{$this->modelClass}->primaryKey);
|
||||
|
||||
// Make sure the action parameter at least exists, and
|
||||
// promote it to the top level (since it drives the operation).
|
||||
if (isset($params['post']['action']))
|
||||
$params['action'] = $params['post']['action'];
|
||||
else
|
||||
$params['action'] = null;
|
||||
}
|
||||
|
||||
function gridDataFinalize(&$params) {
|
||||
if ($params['debug']) {
|
||||
$xml = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
$xml = preg_replace("/&/", "&", $xml);
|
||||
$xml = preg_replace("/</", "<", $xml);
|
||||
$xml = preg_replace("/>/", ">", $xml);
|
||||
echo ("\n<PRE>\n$xml\n</PRE>\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* gridData COUNTING
|
||||
*/
|
||||
|
||||
function gridDataCount(&$params, &$model) {
|
||||
// Establish the tables and conditions for counting
|
||||
$query = array_intersect_key($this->gridDataCountTableSet($params, $model),
|
||||
array('link'=>1, 'contain'=>1));
|
||||
|
||||
// Conditions for the count
|
||||
$query['conditions'] = $this->gridDataCountConditionSet($params, $model);
|
||||
|
||||
// Grouping (which would not be typical)
|
||||
$query['group'] = $this->gridDataCountGroup($params, $model);
|
||||
|
||||
// DEBUG PURPOSES ONLY!
|
||||
$params['count_query'] = $query;
|
||||
|
||||
// Get the number of records prior to pagination
|
||||
return $this->gridDataCountExecute($params, $model, $query);
|
||||
}
|
||||
|
||||
function gridDataCountExecute(&$params, &$model, $query) {
|
||||
return $model->find('count', $query);
|
||||
}
|
||||
|
||||
function gridDataCountTables(&$params, &$model) {
|
||||
// Same tables for counting as for retreiving
|
||||
return $this->gridDataTables($params, $model);
|
||||
}
|
||||
|
||||
function gridDataCountTableSet(&$params, &$model) {
|
||||
// Preliminary set of tables
|
||||
$query = array_intersect_key($this->gridDataCountTables($params, $model),
|
||||
array('link'=>1, 'contain'=>1));
|
||||
|
||||
// Perform filtering based on user request: $params['post']['filter']
|
||||
return array_intersect_key($this->gridDataFilterTables($params, $model, $query),
|
||||
array('link'=>1, 'contain'=>1));
|
||||
}
|
||||
|
||||
function gridDataCountConditions(&$params, &$model) {
|
||||
// Same conditions for counting as for retreiving
|
||||
return $this->gridDataConditions($params, $model);
|
||||
}
|
||||
|
||||
function gridDataCountConditionSet(&$params, &$model) {
|
||||
// Conditions for the count
|
||||
$conditions = $this->gridDataCountConditions($params, $model);
|
||||
|
||||
// Perform filtering based on user request: $params['post']['filter']
|
||||
return $this->gridDataFilterConditions($params, $model, $conditions);
|
||||
}
|
||||
|
||||
function gridDataCountGroup(&$params, &$model) {
|
||||
// Grouping will screw up the count, since it
|
||||
// causes the results to be split into chunks
|
||||
// based on the GROUP BY clause. We can't have
|
||||
// more than one row of data in the count query,
|
||||
// just a _single_ row with the actual count.
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* gridData FILTERING
|
||||
*/
|
||||
|
||||
function gridDataFilterTables(&$params, &$model, $query) {
|
||||
if (isset($query['contain']))
|
||||
$link = 'contain';
|
||||
else
|
||||
$link = 'link';
|
||||
|
||||
if (empty($params['post']['filter']))
|
||||
return $query;
|
||||
|
||||
foreach ($params['post']['filter'] AS $filter => $filter_value) {
|
||||
$split = $this->gridDataFilterSplit($params, $model, $filter, $filter_value);
|
||||
|
||||
/* pr(array('AppController::gridDataFilterTable' => */
|
||||
/* array('checkpoint' => "Filter split") */
|
||||
/* + compact('split'))); */
|
||||
|
||||
$table = $this->gridDataFilterTablesTable($params, $model, $split['table']);
|
||||
if (!$table)
|
||||
continue;
|
||||
|
||||
$config = $this->gridDataFilterTablesConfig($params, $model, $split['table']);
|
||||
|
||||
/* pr(array('AppController::gridDataFilterTable' => */
|
||||
/* array('checkpoint' => "Add filter config to query") */
|
||||
/* + array('query[link]' => $query[$link]) */
|
||||
/* + compact('config'))); */
|
||||
|
||||
// If the table is already part of the query, append to it
|
||||
if ($table == $model->alias) {
|
||||
$query[$link] =
|
||||
array_merge_recursive(array_diff_key($config, array('fields'=>1)),
|
||||
$query[$link]);
|
||||
}
|
||||
elseif (isset($query[$link][$table])) {
|
||||
$query[$link][$table] =
|
||||
array_merge_recursive($config, $query[$link][$table]);
|
||||
}
|
||||
elseif (in_array($table, $query[$link])) {
|
||||
// REVISIT <AP>: 20090727
|
||||
// This presents a dilema. $config may specify fields
|
||||
// as array(), whereas the user has already indicated
|
||||
// they desire ALL fields (by the fact that table is
|
||||
// a member of the query['link'] array without anything
|
||||
// specified). However, $config _could_ specify a
|
||||
// non-standard field in the array, such as using SUM()
|
||||
// or other equation. In that case, we'd have to add
|
||||
// in all the fields of table to the array. That
|
||||
// wouldn't be very hard, but I'll ignore it at the
|
||||
// moment and wait until it's needed.
|
||||
$key = array_search($table, $query[$link]);
|
||||
$query[$link][$table] = array('fields' => null) + $config;
|
||||
unset($query[$link][$key]);
|
||||
}
|
||||
else {
|
||||
// Table is NOT already part of the query... set it now
|
||||
$query[$link][$table] = $config;
|
||||
}
|
||||
|
||||
/* pr(array('post-filter-table-config' => */
|
||||
/* array('query[link]' => $query[$link]))); */
|
||||
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
function gridDataFilterTablesTable(&$params, &$model, $table) {
|
||||
// By default, don't add anything if the filter
|
||||
// condition occurs on the actual model table
|
||||
if ($table == $model->alias)
|
||||
return null;
|
||||
return $this->gridDataFilterTableName($params, $model, $table);
|
||||
}
|
||||
|
||||
function gridDataFilterTablesConfig(&$params, &$model, $table) {
|
||||
return array('fields' => array());
|
||||
}
|
||||
|
||||
function gridDataFilterConditions(&$params, &$model, $conditions) {
|
||||
if (empty($params['post']['filter']))
|
||||
return $conditions;
|
||||
|
||||
foreach ($params['post']['filter'] AS $filter => $filter_value) {
|
||||
$split = $this->gridDataFilterSplit($params, $model, $filter, $filter_value);
|
||||
|
||||
$table = $this->gridDataFilterConditionsTable($params, $model, $split['table']);
|
||||
$key = $this->gridDataFilterConditionsKey($params, $model, $split['table'], $split['field']);
|
||||
if (!$key)
|
||||
continue;
|
||||
|
||||
$conditions[]
|
||||
= $this->gridDataFilterConditionsStatement($params, $model, $table, $key,
|
||||
array_intersect_key
|
||||
($split,
|
||||
array('value'=>1,
|
||||
'value_present'=>1)));
|
||||
}
|
||||
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
function gridDataFilterConditionsTable(&$params, &$model, $table) {
|
||||
return $this->gridDataFilterTableName($params, $model, $table);
|
||||
}
|
||||
|
||||
function gridDataFilterConditionsKey(&$params, &$model, $table, $id) {
|
||||
// REVISIT <AP>: 20090722
|
||||
// When $id is null, we could instantiate the table,
|
||||
// and use the _actual_ primary key. However, I don't
|
||||
// expect that functionality to be used, and will just
|
||||
// stick with 'id' for now.
|
||||
return $id ? $id : 'id';
|
||||
}
|
||||
|
||||
function gridDataFilterConditionsStatement(&$params, &$model, $table, $key, $value) {
|
||||
$key = (empty($table)?"":"{$table}.") . $key;
|
||||
if (isset($value['value_present']) && $value['value_present'])
|
||||
return array($key => $value['value']);
|
||||
else
|
||||
return array($key);
|
||||
}
|
||||
|
||||
function gridDataFilterSplit(&$params, &$model, $filter, $value) {
|
||||
$value_present = true;
|
||||
if (!is_string($filter)) {
|
||||
// only a filter condition was set, not filter=>value
|
||||
$filter = $value;
|
||||
$value = null;
|
||||
$value_present = false;
|
||||
}
|
||||
|
||||
$table = $field = null;
|
||||
if (preg_match("/^\w+\.\w+(\s*[!<>=]+)?$/", $filter)) {
|
||||
list($table, $field) = explode(".", $filter);
|
||||
}
|
||||
elseif (preg_match('/^[A-Z][A-Za-z]*$/', $filter)) {
|
||||
$table = $filter;
|
||||
$field = null;
|
||||
}
|
||||
elseif (preg_match('/^\w+(\s*[!<>=]+)?$/', $filter)) {
|
||||
$table = $model->alias;
|
||||
$field = $filter;
|
||||
}
|
||||
else {
|
||||
// $filter must be a function or other complicated condition
|
||||
$table = null;
|
||||
$field = $filter;
|
||||
}
|
||||
|
||||
return compact('table', 'field', 'value', 'value_present');
|
||||
}
|
||||
|
||||
function gridDataFilterTableName(&$params, &$model, $table) {
|
||||
return Inflector::camelize($table);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
* gridData PAGINATION
|
||||
*/
|
||||
|
||||
function gridDataPagination(&$params, &$model, $record_count) {
|
||||
// Retrieve, or calculate, all parameters necesssary for
|
||||
// pagination. Verify the passed in parameters are valid.
|
||||
|
||||
$limit = $params['rows'] > 0 ? $params['rows'] : 10;
|
||||
$total = ($record_count < 0) ? 0 : ceil($record_count/$limit);
|
||||
$page = ($params['page'] <= 1) ? 1 : (($params['page'] > $total) ? $total : $params['page']);
|
||||
$start = $limit * ($page - 1);
|
||||
|
||||
return compact('record_count', 'limit', 'page', 'start', 'total');
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
* gridData RETREIVAL
|
||||
*/
|
||||
|
||||
function gridDataRecords(&$params, &$model, $pagination) {
|
||||
// Establish the tables for this query
|
||||
$query = array_intersect_key($this->gridDataTableSet($params, $model),
|
||||
array('link'=>1, 'contain'=>1));
|
||||
|
||||
// Specify the fields for the query
|
||||
$query['fields'] = $this->gridDataFields($params, $model);
|
||||
|
||||
// Conditions of the query
|
||||
$query['conditions'] = $this->gridDataConditionSet($params, $model);
|
||||
|
||||
// Data record grouping
|
||||
$query['group'] = $this->gridDataGroup($params, $model);
|
||||
|
||||
// The subset of data based on pagination
|
||||
$query['limit'] = $this->gridDataLimit($params, $model, $pagination['start'], $pagination['limit']);
|
||||
|
||||
// Ordering based on user request
|
||||
$query['order'] = $this->gridDataOrder($params, $model,
|
||||
isset($params['sidx']) ? $params['sidx'] : null,
|
||||
isset($params['sord']) ? $params['sord'] : null);
|
||||
|
||||
// DEBUG PURPOSES ONLY!
|
||||
$params['query'] = $query;
|
||||
|
||||
return $this->gridDataRecordsExecute($params, $model, $query);
|
||||
}
|
||||
|
||||
function gridDataRecordsExecute(&$params, &$model, $query) {
|
||||
return $model->find('all', $query);
|
||||
}
|
||||
|
||||
function gridDataTables(&$params, &$model) {
|
||||
return array('link' => array());
|
||||
}
|
||||
|
||||
function gridDataTableSet(&$params, &$model) {
|
||||
// Preliminary set of tables
|
||||
$query = array_intersect_key($this->gridDataTables($params, $model),
|
||||
array('link'=>1, 'contain'=>1));
|
||||
|
||||
// Perform filtering based on user request: $params['post']['filter']
|
||||
$query = array_intersect_key($this->gridDataFilterTables($params, $model, $query),
|
||||
array('link'=>1, 'contain'=>1));
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
||||
function gridDataConditions(&$params, &$model) {
|
||||
$searches = array();
|
||||
|
||||
if (isset($params['_search']) && $params['_search'] === 'true') {
|
||||
if (isset($params['searchOper'])) {
|
||||
$searches[] = array('op' => $params['searchOper'],
|
||||
'field' => $params['searchField'],
|
||||
'value' => $params['searchString']);
|
||||
}
|
||||
else {
|
||||
// DOH! Crappy mechanism puts toolbar search terms
|
||||
// directly into params as name/value pairs. No
|
||||
// way to know which elements of params are search
|
||||
// terms, so skipping this at the moment.
|
||||
}
|
||||
}
|
||||
elseif (isset($params['filt']) && $params['filt']) {
|
||||
$searches[] = array('op' => 'bw',
|
||||
'field' => $params['filtField'],
|
||||
'value' => $params['filtValue']);
|
||||
}
|
||||
|
||||
$ops = array('eq' => array('op' => null, 'pre' => '', 'post' => ''),
|
||||
'ne' => array('op' => '<>', 'pre' => '', 'post' => ''),
|
||||
'lt' => array('op' => '<', 'pre' => '', 'post' => ''),
|
||||
'le' => array('op' => '<=', 'pre' => '', 'post' => ''),
|
||||
'gt' => array('op' => '>', 'pre' => '', 'post' => ''),
|
||||
'ge' => array('op' => '>=', 'pre' => '', 'post' => ''),
|
||||
'bw' => array('op' => 'LIKE', 'pre' => '', 'post' => '%'),
|
||||
'ew' => array('op' => 'LIKE', 'pre' => '%', 'post' => ''),
|
||||
'cn' => array('op' => 'LIKE', 'pre' => '%', 'post' => '%'),
|
||||
);
|
||||
|
||||
$conditions = array();
|
||||
foreach ($searches AS $search) {
|
||||
$op = $ops[$search['op']];
|
||||
$field = $search['field'] . ($op['op'] ? ' '.$op['op'] : '');
|
||||
$value = $op['pre'] . $search['value']. $op['post'];
|
||||
$conditions[] = array($field => $value);
|
||||
}
|
||||
|
||||
if (isset($params['action']) && $params['action'] === 'idlist') {
|
||||
if (count($params['post']['idlist']))
|
||||
$conditions[] = array($model->alias.'.'.$model->primaryKey => $params['post']['idlist']);
|
||||
else
|
||||
$conditions[] = '0=1';
|
||||
}
|
||||
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
function gridDataConditionSet(&$params, &$model) {
|
||||
// Conditions for record retrieval
|
||||
$conditions = $this->gridDataConditions($params, $model);
|
||||
|
||||
// Perform filtering based on user request: $params['post']['filter']
|
||||
return $this->gridDataFilterConditions($params, $model, $conditions);
|
||||
}
|
||||
|
||||
function gridDataFields(&$params, &$model) {
|
||||
$db = &$model->getDataSource();
|
||||
$fields = $db->fields($model, $model->alias);
|
||||
return $fields;
|
||||
}
|
||||
|
||||
function gridDataGroup(&$params, &$model) {
|
||||
return $model->alias.'.'.$model->primaryKey;
|
||||
}
|
||||
|
||||
function gridDataOrder(&$params, &$model, $index, $direction) {
|
||||
return $index ? array($index .' '. $direction) : null;
|
||||
}
|
||||
|
||||
function gridDataLimit(&$params, &$model, $start, $limit) {
|
||||
return $start . ', ' . $limit;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
* gridData POST PROCESSING
|
||||
*/
|
||||
|
||||
function gridDataPostProcess(&$params, &$model, &$records) {
|
||||
// Add grid IDs to each record
|
||||
$this->gridDataPostProcessGridIDs($params, $model, $records);
|
||||
|
||||
// Add the calculated fields (if any), to the model fields
|
||||
$this->gridDataPostProcessCalculatedFields($params, $model, $records);
|
||||
|
||||
// Perform any requested subtotaling of fields
|
||||
$this->gridDataPostProcessSubtotal($params, $model, $records);
|
||||
|
||||
// Add in any needed hyperlinks
|
||||
$this->gridDataPostProcessLinks($params, $model, $records, array());
|
||||
|
||||
// DEBUG PURPOSES ONLY!
|
||||
//$params['records'] = $records;
|
||||
}
|
||||
|
||||
function gridDataPostProcessGridIDs(&$params, &$model, &$records) {
|
||||
$model_alias = $model->alias;
|
||||
$id = $model->primaryKey;
|
||||
|
||||
foreach ($records AS &$record) {
|
||||
$record['grid_id'] = $record[$model_alias][$id];
|
||||
}
|
||||
}
|
||||
|
||||
function gridDataPostProcessCalculatedFields(&$params, &$model, &$records) {
|
||||
$model_alias = $model->alias;
|
||||
|
||||
foreach ($records AS &$record) {
|
||||
// Add the calculated fields (if any), to the model fields
|
||||
if (isset($record[0])) {
|
||||
$record[$model_alias] = $record[0] + $record[$model_alias];
|
||||
unset($record[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function gridDataPostProcessSubtotal(&$params, &$model, &$records) {
|
||||
$model_alias = $model->alias;
|
||||
|
||||
// REVISIT <AP>: 20090722
|
||||
// Horrible solution to something that should be done
|
||||
// in SQL. But, it works for now, so what the heck...
|
||||
|
||||
$subtotals = array();
|
||||
foreach ($params['post']['fields'] AS $field) {
|
||||
if (preg_match('/subtotal-(.*)$/', $field, $matches))
|
||||
$subtotals[] = array('field' => $matches[1],
|
||||
'name' => $field,
|
||||
'amount' => 0);
|
||||
}
|
||||
|
||||
foreach ($records AS &$record) {
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||
// Don't create any links if ordered not to.
|
||||
if (isset($params['post']['nolinks']))
|
||||
return;
|
||||
|
||||
App::import('Helper', 'Html');
|
||||
|
||||
foreach ($links AS $table => $fields) {
|
||||
$special = array('controller', 'action', 'id');
|
||||
$controller = Inflector::pluralize(Inflector::underscore($table));
|
||||
$action = 'view';
|
||||
$id = 'id';
|
||||
extract(array_intersect_key($fields, array_flip($special)));
|
||||
foreach ($records AS &$record) {
|
||||
if (!isset($record[$table]))
|
||||
continue;
|
||||
|
||||
foreach (array_diff_key($fields, array_flip($special)) AS $field) {
|
||||
if (!isset($record[$table][$id]) || !isset($record[$table][$field]))
|
||||
continue;
|
||||
|
||||
// DEBUG PURPOSES ONLY!
|
||||
//$params['linkrecord'][] = compact('table', 'field', 'id', 'controller', 'record');
|
||||
$record[$table][$field] =
|
||||
'<A HREF="' .
|
||||
HtmlHelper::url(array('controller' => $controller,
|
||||
'action' => $action,
|
||||
$record[$table][$id])) .
|
||||
'">' .
|
||||
$record[$table][$field] .
|
||||
'</A>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
* gridData OUTPUT
|
||||
*/
|
||||
|
||||
function gridDataOutput(&$params, &$model, &$records, $pagination) {
|
||||
$this->gridDataOutputHeader($params, $model);
|
||||
$this->gridDataOutputXMLHeader($params, $model);
|
||||
$this->gridDataOutputRootNodeBegin($params, $model);
|
||||
$this->gridDataOutputSummary($params, $model, $pagination);
|
||||
$this->gridDataOutputRecords($params, $model, $records);
|
||||
$this->gridDataOutputRootNodeEnd($params, $model);
|
||||
}
|
||||
|
||||
function gridDataOutputHeader(&$params, &$model) {
|
||||
if (!$params['debug']) {
|
||||
header("Content-type: text/xml;charset=utf-8");
|
||||
}
|
||||
}
|
||||
|
||||
function gridDataOutputXMLHeader(&$params, &$model) {
|
||||
echo "<?xml version='1.0' encoding='utf-8'?>\n";
|
||||
}
|
||||
|
||||
function gridDataOutputRootNodeBegin(&$params, &$model) {
|
||||
echo "<rows>\n";
|
||||
}
|
||||
|
||||
function gridDataOutputRootNodeEnd(&$params, &$model) {
|
||||
echo "</rows>\n";
|
||||
}
|
||||
|
||||
function gridDataOutputSummary(&$params, &$model, $pagination) {
|
||||
echo " <params><![CDATA[\n" . print_r($params, true) . "\n]]></params>\n";
|
||||
echo " <page>{$pagination['page']}</page>\n";
|
||||
echo " <total>{$pagination['total']}</total>\n";
|
||||
echo " <records>{$pagination['record_count']}</records>\n";
|
||||
|
||||
if (isset($params['userdata'])) {
|
||||
foreach ($params['userdata'] AS $field => $value)
|
||||
echo ' <userdata name="'.$field.'">' . "{$value}</userdata>\n";
|
||||
}
|
||||
}
|
||||
|
||||
function gridDataOutputRecords(&$params, &$model, &$records) {
|
||||
$id_field = 'grid_id';
|
||||
foreach ($records AS $record) {
|
||||
$this->gridDataOutputRecord($params, $model, $record,
|
||||
$record[$id_field], $params['post']['fields']);
|
||||
}
|
||||
}
|
||||
|
||||
function gridDataOutputRecord(&$params, &$model, &$record, $id, $fields) {
|
||||
echo " <row id='$id'>\n";
|
||||
foreach ($fields AS $field) {
|
||||
$this->gridDataOutputRecordField($params, $model, $record, $field);
|
||||
}
|
||||
echo " </row>\n";
|
||||
}
|
||||
|
||||
function gridDataOutputRecordField(&$params, &$model, &$record, $field) {
|
||||
if (preg_match("/\./", $field)) {
|
||||
list($tbl, $col) = explode(".", $field);
|
||||
//pr(compact('record', 'field', 'tbl', 'col'));
|
||||
$data = $record[$tbl][$col];
|
||||
}
|
||||
else {
|
||||
$data = $record[$model->alias][$field];
|
||||
}
|
||||
$this->gridDataOutputRecordCell($params, $model, $record, $field, $data);
|
||||
}
|
||||
|
||||
function gridDataOutputRecordCell(&$params, &$model, &$record, $field, $data) {
|
||||
// be sure to put text data in CDATA
|
||||
if (preg_match("/^\d*$/", $data))
|
||||
echo " <cell>$data</cell>\n";
|
||||
else
|
||||
echo " <cell><![CDATA[$data]]></cell>\n";
|
||||
}
|
||||
|
||||
function INTERNAL_ERROR($msg, $depth = 0) {
|
||||
INTERNAL_ERROR($msg, false, $depth+1);
|
||||
$this->render_empty();
|
||||
$this->_stop();
|
||||
}
|
||||
|
||||
function render_empty() {
|
||||
$this->render('/empty');
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
50
app_helper.php
Normal file
50
app_helper.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: app_helper.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||
/**
|
||||
* Short description for file.
|
||||
*
|
||||
* This file is application-wide helper file. You can put all
|
||||
* application-wide helper-related methods here.
|
||||
*
|
||||
* 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
|
||||
* @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
|
||||
*/
|
||||
App::import('Core', 'Helper');
|
||||
/**
|
||||
* This is a placeholder class.
|
||||
* Create the same file in app/app_helper.php
|
||||
*
|
||||
* Add your application-wide methods in the class below, your helpers
|
||||
* will inherit them.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.cake
|
||||
*/
|
||||
class AppHelper extends Helper {
|
||||
|
||||
function url($url = null, $full = false) {
|
||||
foreach(array('admin_route', 'dev_route') AS $mod) {
|
||||
if (isset($this->params[$mod]) && is_array($url) && !isset($url[$mod]))
|
||||
$url[$mod] = $this->params[$mod];
|
||||
}
|
||||
return parent::url($url, $full);
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
491
app_model.php
Normal file
491
app_model.php
Normal file
@@ -0,0 +1,491 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: app_model.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||
|
||||
/**
|
||||
* Application model for Cake.
|
||||
*
|
||||
* This file is application-wide model file. You can put all
|
||||
* application-wide model-related methods here.
|
||||
*
|
||||
* 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.app
|
||||
* @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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Application model for Cake.
|
||||
*
|
||||
* Add your application-wide methods in the class below, your models
|
||||
* will inherit them.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.app
|
||||
*/
|
||||
class AppModel extends Model {
|
||||
|
||||
var $actsAs = array('Containable', 'Linkable');
|
||||
var $useNullForEmpty = true;
|
||||
var $formatDateFields = true;
|
||||
|
||||
// Default Log Level, if not specified at the function level
|
||||
var $default_log_level = 5;
|
||||
|
||||
// Class specific log levels
|
||||
var $class_log_level = array('Model' => 5);
|
||||
|
||||
// Function specific log levels
|
||||
var $function_log_level = array();
|
||||
|
||||
// Force the module to log at LEAST at this level
|
||||
var $min_log_level;
|
||||
|
||||
// Force logging of nothing higher than this level
|
||||
var $max_log_level;
|
||||
|
||||
|
||||
// REVISIT <AP>: 20090730
|
||||
// Why is this constructor crashing?
|
||||
// Clearly it's in some sort of infinite
|
||||
// loop, but it seems the correct way
|
||||
// to have a constructor call the parent...
|
||||
|
||||
/* function __construct() { */
|
||||
/* parent::__construct(); */
|
||||
/* $this->prClassLevel(5, 'Model'); */
|
||||
/* } */
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: pr
|
||||
* - Prints out debug information, if the log level allows
|
||||
*/
|
||||
|
||||
function prClassLevel($level, $class = null) {
|
||||
$trace = debug_backtrace(false);
|
||||
$caller = array_shift($trace);
|
||||
$caller = array_shift($trace);
|
||||
if (empty($class))
|
||||
$class = $caller['class'];
|
||||
$this->class_log_level[$class] = $level;
|
||||
}
|
||||
|
||||
function prFunctionLevel($level, $function = null, $class = null) {
|
||||
$trace = debug_backtrace(false);
|
||||
$caller = array_shift($trace);
|
||||
$caller = array_shift($trace);
|
||||
if (empty($class))
|
||||
$class = $caller['class'];
|
||||
if (empty($function))
|
||||
$function = $caller['function'];
|
||||
$this->function_log_level["{$class}-{$function}"] = $level;
|
||||
}
|
||||
|
||||
function _pr($level, $mixed, $checkpoint = null) {
|
||||
if (Configure::read() <= 0)
|
||||
return;
|
||||
|
||||
$log_level = $this->default_log_level;
|
||||
|
||||
$trace = debug_backtrace(false);
|
||||
|
||||
// Get rid of pr/prEnter/prReturn
|
||||
$caller = array_shift($trace);
|
||||
|
||||
// The next entry shows where pr was called from, but it
|
||||
// shows _what_ was called, which is pr/prEntry/prReturn.
|
||||
$caller = array_shift($trace);
|
||||
$file = $caller['file'];
|
||||
$line = $caller['line'];
|
||||
|
||||
// So, this caller holds the calling function name
|
||||
$caller = $trace[0];
|
||||
$function = $caller['function'];
|
||||
$class = $caller['class'];
|
||||
//$class = $this->name;
|
||||
|
||||
// Use class or function specific log level if available
|
||||
if (isset($this->class_log_level[$class]))
|
||||
$log_level = $this->class_log_level[$class];
|
||||
if (isset($this->function_log_level["{$class}-{$function}"]))
|
||||
$log_level = $this->function_log_level["{$class}-{$function}"];
|
||||
|
||||
// Establish log level minimums
|
||||
$min_log_level = $this->min_log_level;
|
||||
if (is_array($this->min_log_level)) {
|
||||
$min_show_level = $min_log_level['show'];
|
||||
$min_log_level = $min_log_level['log'];
|
||||
}
|
||||
|
||||
// Establish log level maximums
|
||||
$max_log_level = $this->max_log_level;
|
||||
if (is_array($this->max_log_level)) {
|
||||
$max_show_level = $max_log_level['show'];
|
||||
$max_log_level = $max_log_level['log'];
|
||||
}
|
||||
|
||||
// Determine the applicable log and show levels
|
||||
if (is_array($log_level)) {
|
||||
$show_level = $log_level['show'];
|
||||
$log_level = $log_level['log'];
|
||||
}
|
||||
|
||||
// Adjust log level up/down to min/max
|
||||
if (isset($min_log_level))
|
||||
$log_level = max($log_level, $min_log_level);
|
||||
if (isset($max_log_level))
|
||||
$log_level = min($log_level, $max_log_level);
|
||||
|
||||
// Adjust show level up/down to min/max
|
||||
if (isset($min_show_level))
|
||||
$show_level = max($show_level, $min_show_level);
|
||||
if (isset($max_show_level))
|
||||
$show_level = min($show_level, $max_show_level);
|
||||
|
||||
// If the level is insufficient, bail out
|
||||
if ($level > $log_level)
|
||||
return;
|
||||
|
||||
if (!empty($checkpoint)) {
|
||||
$chk = array("checkpoint" => $checkpoint);
|
||||
if (is_array($mixed))
|
||||
$mixed = $chk + $mixed;
|
||||
else
|
||||
$mixed = $chk + array($mixed);
|
||||
}
|
||||
|
||||
static $pr_unique_number = 0;
|
||||
$pr_id = 'pr-section-class-' . $class . '-print-' . (++$pr_unique_number);
|
||||
$pr_trace_id = $pr_id . '-trace';
|
||||
$pr_output_id = $pr_id . '-output';
|
||||
|
||||
$pr_entire_base_class = "pr-section";
|
||||
$pr_entire_class_class = $pr_entire_base_class . '-class-' . $class;
|
||||
$pr_entire_function_class = $pr_entire_class_class . '-function-' . $function;
|
||||
$pr_entire_class = "$pr_entire_base_class $pr_entire_class_class $pr_entire_function_class";
|
||||
$pr_header_class = "pr-caller";
|
||||
$pr_trace_class = "pr-trace";
|
||||
$pr_output_base_class = 'pr-output';
|
||||
$pr_output_class_class = $pr_output_base_class . '-class-' . $class;
|
||||
$pr_output_function_class = $pr_output_class_class . '-function-' . $function;
|
||||
$pr_output_class = "$pr_output_base_class $pr_output_class_class $pr_output_function_class";
|
||||
|
||||
echo '<DIV class="'.$pr_entire_class.'" id="'.$pr_id.'">'."\n";
|
||||
echo '<DIV class="'.$pr_header_class.'">'."\n";
|
||||
echo '<DIV class="'.$pr_trace_class.'" id="'.$pr_trace_id.'" style="display:none;">'."\n";
|
||||
echo '<HR />' . "\n";
|
||||
|
||||
// Flip trace around so the sequence flows from top to bottom
|
||||
// Then print out the entire stack trace (in hidden div)
|
||||
$trace = array_reverse($trace);
|
||||
for ($i = 0; $i < count($trace); ++$i) {
|
||||
$bline = $trace[$i]['line'];
|
||||
$bfile = $trace[$i]['file'];
|
||||
$bfile = str_replace(ROOT.DS, '', $bfile);
|
||||
$bfile = str_replace(CAKE_CORE_INCLUDE_PATH.DS, '', $bfile);
|
||||
|
||||
if ($i > 0) {
|
||||
$bfunc = $trace[$i-1]['function'];
|
||||
$bclas = $trace[$i-1]['class'];
|
||||
} else {
|
||||
$bfunc = null;
|
||||
$bclas = null;
|
||||
}
|
||||
|
||||
echo("$bfile:$bline (" . ($bclas ? "$bclas::$bfunc" : "entry point") . ")<BR>\n");
|
||||
//echo(($bclas ? "$bclas::$bfunc" : "entry point") . "; $bfile : $bline<BR>\n");
|
||||
}
|
||||
echo '</DIV>' . "\n"; // End pr_trace_class
|
||||
$file = str_replace(ROOT.DS, '', $file);
|
||||
$file = str_replace(CAKE_CORE_INCLUDE_PATH.DS, '', $file);
|
||||
|
||||
echo "<strong>$file:$line ($class::$function)</strong>" . ";\n";
|
||||
/* $log_show_level = isset($show_level) ? $show_level : '?'; */
|
||||
/* echo ' L' . $level . "({$log_level}/{$log_show_level})" . ";\n"; */
|
||||
echo ' L' . $level . ";\n";
|
||||
echo ' <A HREF="#" onclick="$' . "('#{$pr_trace_id}').slideToggle(); return false;" . '">stack</A>'.";\n";
|
||||
|
||||
echo " this ";
|
||||
echo '<A HREF="#" onclick="$' . "('#{$pr_output_id}').slideToggle(); return false;" . '">t</A>'."/";
|
||||
echo '<A HREF="#" onclick="$' . "('#{$pr_id}').hide(); return false;" . '">n</A>'.";\n";
|
||||
|
||||
echo " $class ";
|
||||
echo '<A HREF="#" onclick="$' . "('.{$pr_output_class_class}').slideDown(); return false;" . '">s</A>'."/";
|
||||
echo '<A HREF="#" onclick="$' . "('.{$pr_output_class_class}').slideUp(); return false;" . '">h</A>'."/";
|
||||
echo '<A HREF="#" onclick="$' . "('.{$pr_entire_class_class}').hide(); return false;" . '">n</A>'.";\n";
|
||||
|
||||
echo " $function ";
|
||||
echo '<A HREF="#" onclick="$' . "('.{$pr_output_function_class}').slideDown(); return false;" . '">s</A>'."/";
|
||||
echo '<A HREF="#" onclick="$' . "('.{$pr_output_function_class}').slideUp(); return false;" . '">h</A>'."/";
|
||||
echo '<A HREF="#" onclick="$' . "('.{$pr_entire_function_class}').hide(); return false;" . '">n</A>'.";\n";
|
||||
|
||||
echo " all ";
|
||||
echo '<A HREF="#" onclick="$' . "('.{$pr_output_base_class}').show(); return false;" . '">s</A>'."/";
|
||||
echo '<A HREF="#" onclick="$' . "('.{$pr_output_base_class}').hide(); return false;" . '">h</A>'."/";
|
||||
echo '<A HREF="#" onclick="$' . "('.{$pr_entire_base_class}').hide(); return false;" . '">n</A>'."\n";
|
||||
|
||||
echo '</DIV>' . "\n"; // End pr_header_class
|
||||
|
||||
if (isset($show_level) && $level > $show_level)
|
||||
$display = 'none';
|
||||
else
|
||||
$display = 'block';
|
||||
|
||||
echo '<DIV class="'.$pr_output_class.'" id="'.$pr_output_id.'" style="display:'.$display.';">'."\n";
|
||||
pr($mixed, false, false);
|
||||
echo '</DIV>' . "\n"; // End pr_output_class
|
||||
echo '</DIV>' . "\n"; // End pr_entire_class
|
||||
}
|
||||
|
||||
function pr($level, $mixed, $checkpoint = null) {
|
||||
$this->_pr($level, $mixed, $checkpoint);
|
||||
}
|
||||
|
||||
function prEnter($args, $level = 15) {
|
||||
$this->_pr($level, $args, 'Function Entry');
|
||||
}
|
||||
|
||||
function prReturn($retval, $level = 16) {
|
||||
$this->_pr($level, $retval, 'Function Return');
|
||||
return $retval;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: queryInit
|
||||
* - Initializes the query fields
|
||||
*/
|
||||
function prDump($all = false) {
|
||||
$vars = get_object_vars($this);
|
||||
foreach (array_keys($vars) AS $name) {
|
||||
if (preg_match("/^[A-Z]/", $name))
|
||||
unset($vars[$name]);
|
||||
if (preg_match("/^_/", $name) && !$all)
|
||||
unset($vars[$name]);
|
||||
}
|
||||
pr($vars);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get Enum Values
|
||||
* Snippet v0.1.3
|
||||
* http://cakeforge.org/snippet/detail.php?type=snippet&id=112
|
||||
*
|
||||
* Gets the enum values for MySQL 4 and 5 to use in selectTag()
|
||||
*/
|
||||
function getEnumValues($columnName=null, $tableName=null)
|
||||
{
|
||||
if ($columnName==null) { return array(); } //no field specified
|
||||
|
||||
if (!isset($tableName)) {
|
||||
//Get the name of the table
|
||||
$db =& ConnectionManager::getDataSource($this->useDbConfig);
|
||||
$tableName = $db->fullTableName($this, false);
|
||||
}
|
||||
|
||||
//Get the values for the specified column (database and version specific, needs testing)
|
||||
$result = $this->query("SHOW COLUMNS FROM {$tableName} LIKE '{$columnName}'");
|
||||
|
||||
//figure out where in the result our Types are (this varies between mysql versions)
|
||||
$types = null;
|
||||
if ( isset( $result[0]['COLUMNS']['Type'] ) ) { //MySQL 5
|
||||
$types = $result[0]['COLUMNS']['Type']; $default = $result[0]['COLUMNS']['Default'];
|
||||
}
|
||||
elseif ( isset( $result[0][0]['Type'] ) ) { //MySQL 4
|
||||
$types = $result[0][0]['Type']; $default = $result[0][0]['Default'];
|
||||
}
|
||||
else { //types return not accounted for
|
||||
return array();
|
||||
}
|
||||
|
||||
//Get the values
|
||||
return array_flip(array_merge(array(''), // MySQL sets 0 to be the empty string
|
||||
explode("','", strtoupper(preg_replace("/(enum)\('(.+?)'\)/","\\2", $types)))
|
||||
));
|
||||
} //end getEnumValues
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: queryInit
|
||||
* - Initializes the query fields
|
||||
*/
|
||||
function queryInit(&$query, $link = true) {
|
||||
if (!isset($query))
|
||||
$query = array();
|
||||
if (!isset($query['conditions']))
|
||||
$query['conditions'] = array();
|
||||
if (!isset($query['group']))
|
||||
$query['group'] = null;
|
||||
if (!isset($query['fields']))
|
||||
$query['fields'] = null;
|
||||
if ($link && !isset($query['link']))
|
||||
$query['link'] = array();
|
||||
if (!$link && !isset($query['contain']))
|
||||
$query['contain'] = array();
|
||||
|
||||
// In case caller expects query to come back
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: statMerge
|
||||
* - Merges summary data from $b into $a
|
||||
*/
|
||||
|
||||
function statsMerge (&$a, $b) {
|
||||
if (!isset($b))
|
||||
return;
|
||||
|
||||
if (!isset($a)) {
|
||||
$a = $b;
|
||||
}
|
||||
elseif (!is_array($a) && !is_array($b)) {
|
||||
$a += $b;
|
||||
}
|
||||
elseif (is_array($a) && is_array($b)) {
|
||||
foreach (array_intersect_key($a, $b) AS $k => $v)
|
||||
{
|
||||
if (preg_match("/^sp\./", $k))
|
||||
$a[$k] .= '; ' . $b[$k];
|
||||
else
|
||||
$this->statsMerge($a[$k], $b[$k]);
|
||||
}
|
||||
$a = array_merge($a, array_diff_key($b, $a));
|
||||
}
|
||||
else {
|
||||
die ("Can't yet merge array and non-array stats");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function filter_null($array) {
|
||||
return array_diff_key($array, array_filter($array, 'is_null'));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: dateFormatBeforeSave
|
||||
* - convert dates to database format
|
||||
*/
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
function INTERNAL_ERROR($msg, $depth = 0) {
|
||||
INTERNAL_ERROR($msg, false, $depth+1);
|
||||
echo $this->requestAction(array('controller' => 'accounts',
|
||||
'action' => 'render_empty'),
|
||||
array('return', 'bare' => false)
|
||||
);
|
||||
$this->_stop();
|
||||
}
|
||||
}
|
||||
74
config/acl.ini.php
Normal file
74
config/acl.ini.php
Normal file
@@ -0,0 +1,74 @@
|
||||
;<?php die() ?>
|
||||
; SVN FILE: $Id: acl.ini.php 7945 2008-12-19 02:16:01Z gwoo $
|
||||
;/**
|
||||
; * Short description for file.
|
||||
; *
|
||||
; *
|
||||
; * 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.app.config
|
||||
; * @since CakePHP(tm) v 0.10.0.1076
|
||||
; * @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
|
||||
; */
|
||||
|
||||
; acl.ini.php - Cake ACL Configuration
|
||||
; ---------------------------------------------------------------------
|
||||
; Use this file to specify user permissions.
|
||||
; aco = access control object (something in your application)
|
||||
; aro = access request object (something requesting access)
|
||||
;
|
||||
; User records are added as follows:
|
||||
;
|
||||
; [uid]
|
||||
; groups = group1, group2, group3
|
||||
; allow = aco1, aco2, aco3
|
||||
; deny = aco4, aco5, aco6
|
||||
;
|
||||
; Group records are added in a similar manner:
|
||||
;
|
||||
; [gid]
|
||||
; allow = aco1, aco2, aco3
|
||||
; deny = aco4, aco5, aco6
|
||||
;
|
||||
; The allow, deny, and groups sections are all optional.
|
||||
; NOTE: groups names *cannot* ever be the same as usernames!
|
||||
;
|
||||
; ACL permissions are checked in the following order:
|
||||
; 1. Check for user denies (and DENY if specified)
|
||||
; 2. Check for user allows (and ALLOW if specified)
|
||||
; 3. Gather user's groups
|
||||
; 4. Check group denies (and DENY if specified)
|
||||
; 5. Check group allows (and ALLOW if specified)
|
||||
; 6. If no aro, aco, or group information is found, DENY
|
||||
;
|
||||
; ---------------------------------------------------------------------
|
||||
|
||||
;-------------------------------------
|
||||
;Users
|
||||
;-------------------------------------
|
||||
|
||||
[username-goes-here]
|
||||
groups = group1, group2
|
||||
deny = aco1, aco2
|
||||
allow = aco3, aco4
|
||||
|
||||
;-------------------------------------
|
||||
;Groups
|
||||
;-------------------------------------
|
||||
|
||||
[groupname-goes-here]
|
||||
deny = aco5, aco6
|
||||
allow = aco7, aco8
|
||||
84
config/bootstrap.php
Normal file
84
config/bootstrap.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: bootstrap.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||
/**
|
||||
* Short description for file.
|
||||
*
|
||||
* Long description for file
|
||||
*
|
||||
* 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.app.config
|
||||
* @since CakePHP(tm) v 0.10.8.2117
|
||||
* @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
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* This file is loaded automatically by the app/webroot/index.php file after the core bootstrap.php is loaded
|
||||
* This is an application wide file to load any function that is not used within a class define.
|
||||
* You can also use this to include or require any files in your application.
|
||||
*
|
||||
*/
|
||||
|
||||
function INTERNAL_ERROR($message, $exit = true, $drop = 0) {
|
||||
echo '<DIV class="internal-error" style="color:#000; background:#c22; padding:0.5em 1.5em 0.5em 1.5em;">' . "\n";
|
||||
echo '<H1 style="color:#000; margin-bottom:0.2em; font-size:2em;">INTERNAL ERROR:</H1>' . "\n";
|
||||
echo '<H2 style="color:#000; margin-top:0; margin-left:1.5em; font-size:1.5em">' . $message . '</H2>' . "\n";
|
||||
echo '<H4 style="color:#000;">This error was not caused by anything that you did wrong.' . "\n";
|
||||
echo '<BR>It is a problem within the application itself and should be reported to the administrator.</H4>' . "\n";
|
||||
|
||||
// Print out the entire stack trace
|
||||
echo '<HR style="margin-top:1.0em; margin-bottom:0.5em;">' . "\nStack Trace:\n";
|
||||
echo '<OL style="margin-left:1.5em";>' . "\n";
|
||||
$trace = array_slice(debug_backtrace(false), $drop);
|
||||
for ($i = 0; $i < count($trace); ++$i) {
|
||||
$bline = $trace[$i]['line'];
|
||||
$bfile = $trace[$i]['file'];
|
||||
$bfile = str_replace(ROOT.DS, '', $bfile);
|
||||
$bfile = str_replace(CAKE_CORE_INCLUDE_PATH.DS, '', $bfile);
|
||||
|
||||
if ($i < count($trace)-1) {
|
||||
$bfunc = $trace[$i+1]['function'];
|
||||
$bclas = $trace[$i+1]['class'];
|
||||
} else {
|
||||
$bfunc = null;
|
||||
$bclas = null;
|
||||
}
|
||||
|
||||
echo("<LI>$bfile:$bline (" . ($bclas ? "$bclas::$bfunc" : "entry point") . ")</LI>\n");
|
||||
}
|
||||
echo "</OL>\n";
|
||||
|
||||
echo '<HR style="margin-top:1.0em; margin-bottom:0.5em;">' . "\nHTTP Request:\n";
|
||||
echo '<P><PRE style="color:#000; background:#c22;">' . "\n";
|
||||
print_r($_REQUEST);
|
||||
echo "\n</PRE>\n";
|
||||
|
||||
echo '</DIV>';
|
||||
if ($exit)
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* The settings below can be used to set additional paths to models, views and controllers.
|
||||
* This is related to Ticket #470 (https://trac.cakephp.org/ticket/470)
|
||||
*
|
||||
* $modelPaths = array('full path to models', 'second full path to models', 'etc...');
|
||||
* $viewPaths = array('this path to views', 'second full path to views', 'etc...');
|
||||
* $controllerPaths = array('this path to controllers', 'second full path to controllers', 'etc...');
|
||||
*
|
||||
*/
|
||||
//EOF
|
||||
?>
|
||||
227
config/core.php
Normal file
227
config/core.php
Normal file
@@ -0,0 +1,227 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: core.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||
/**
|
||||
* This is core configuration file.
|
||||
*
|
||||
* Use it to configure core behavior of Cake.
|
||||
*
|
||||
* 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.app.config
|
||||
* @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
|
||||
*/
|
||||
/**
|
||||
* CakePHP Debug Level:
|
||||
*
|
||||
* Production Mode:
|
||||
* 0: No error messages, errors, or warnings shown. Flash messages redirect.
|
||||
*
|
||||
* Development Mode:
|
||||
* 1: Errors and warnings shown, model caches refreshed, flash messages halted.
|
||||
* 2: As in 1, but also with full debug messages and SQL output.
|
||||
* 3: As in 2, but also with full controller dump.
|
||||
*
|
||||
* In production mode, flash messages redirect after a time interval.
|
||||
* In development mode, you need to click the flash message to continue.
|
||||
*/
|
||||
Configure::write('debug', 2);
|
||||
/**
|
||||
* Application wide charset encoding
|
||||
*/
|
||||
Configure::write('App.encoding', 'UTF-8');
|
||||
/**
|
||||
* To configure CakePHP *not* to use mod_rewrite and to
|
||||
* use CakePHP pretty URLs, remove these .htaccess
|
||||
* files:
|
||||
*
|
||||
* /.htaccess
|
||||
* /app/.htaccess
|
||||
* /app/webroot/.htaccess
|
||||
*
|
||||
* And uncomment the App.baseUrl below:
|
||||
*/
|
||||
//Configure::write('App.baseUrl', env('SCRIPT_NAME'));
|
||||
/**
|
||||
* Uncomment the define below to use CakePHP admin routes.
|
||||
*
|
||||
* The value of the define determines the name of the route
|
||||
* and its associated controller actions:
|
||||
*
|
||||
* 'admin' -> admin_index() and /admin/controller/index
|
||||
* 'superuser' -> superuser_index() and /superuser/controller/index
|
||||
*/
|
||||
//Configure::write('Routing.admin', 'admin');
|
||||
|
||||
/**
|
||||
* Turn off all caching application-wide.
|
||||
*
|
||||
*/
|
||||
//Configure::write('Cache.disable', true);
|
||||
/**
|
||||
* Enable cache checking.
|
||||
*
|
||||
* If set to true, for view caching you must still use the controller
|
||||
* var $cacheAction inside your controllers to define caching settings.
|
||||
* You can either set it controller-wide by setting var $cacheAction = true,
|
||||
* or in each action using $this->cacheAction = true.
|
||||
*
|
||||
*/
|
||||
//Configure::write('Cache.check', true);
|
||||
/**
|
||||
* Defines the default error type when using the log() function. Used for
|
||||
* differentiating error logging and debugging. Currently PHP supports LOG_DEBUG.
|
||||
*/
|
||||
define('LOG_ERROR', 2);
|
||||
/**
|
||||
* The preferred session handling method. Valid values:
|
||||
*
|
||||
* 'php' Uses settings defined in your php.ini.
|
||||
* 'cake' Saves session files in CakePHP's /tmp directory.
|
||||
* 'database' Uses CakePHP's database sessions.
|
||||
*
|
||||
* To define a custom session handler, save it at /app/config/<name>.php.
|
||||
* Set the value of 'Session.save' to <name> to utilize it in CakePHP.
|
||||
*
|
||||
* To use database sessions, execute the SQL file found at /app/config/sql/sessions.sql.
|
||||
*
|
||||
*/
|
||||
Configure::write('Session.save', 'php');
|
||||
/**
|
||||
* The name of the table used to store CakePHP database sessions.
|
||||
*
|
||||
* 'Session.save' must be set to 'database' in order to utilize this constant.
|
||||
*
|
||||
* The table name set here should *not* include any table prefix defined elsewhere.
|
||||
*/
|
||||
//Configure::write('Session.table', 'cake_sessions');
|
||||
/**
|
||||
* The DATABASE_CONFIG::$var to use for database session handling.
|
||||
*
|
||||
* 'Session.save' must be set to 'database' in order to utilize this constant.
|
||||
*/
|
||||
//Configure::write('Session.database', 'default');
|
||||
/**
|
||||
* The name of CakePHP's session cookie.
|
||||
*/
|
||||
Configure::write('Session.cookie', 'CAKEPHP');
|
||||
/**
|
||||
* Session time out time (in seconds).
|
||||
* Actual value depends on 'Security.level' setting.
|
||||
*/
|
||||
Configure::write('Session.timeout', '120');
|
||||
/**
|
||||
* If set to false, sessions are not automatically started.
|
||||
*/
|
||||
Configure::write('Session.start', true);
|
||||
/**
|
||||
* When set to false, HTTP_USER_AGENT will not be checked
|
||||
* in the session
|
||||
*/
|
||||
Configure::write('Session.checkAgent', true);
|
||||
/**
|
||||
* The level of CakePHP security. The session timeout time defined
|
||||
* in 'Session.timeout' is multiplied according to the settings here.
|
||||
* Valid values:
|
||||
*
|
||||
* 'high' Session timeout in 'Session.timeout' x 10
|
||||
* 'medium' Session timeout in 'Session.timeout' x 100
|
||||
* 'low' Session timeout in 'Session.timeout' x 300
|
||||
*
|
||||
* CakePHP session IDs are also regenerated between requests if
|
||||
* 'Security.level' is set to 'high'.
|
||||
*/
|
||||
Configure::write('Security.level', 'high');
|
||||
/**
|
||||
* A random string used in security hashing methods.
|
||||
*/
|
||||
Configure::write('Security.salt', 'fbd497077ac32a7ab159333cd7e3eeb85db5c2a5');
|
||||
/**
|
||||
* Compress CSS output by removing comments, whitespace, repeating tags, etc.
|
||||
* This requires a/var/cache directory to be writable by the web server for caching.
|
||||
* and /vendors/csspp/csspp.php
|
||||
*
|
||||
* To use, prefix the CSS link URL with '/ccss/' instead of '/css/' or use HtmlHelper::css().
|
||||
*/
|
||||
//Configure::write('Asset.filter.css', 'css.php');
|
||||
/**
|
||||
* Plug in your own custom JavaScript compressor by dropping a script in your webroot to handle the
|
||||
* output, and setting the config below to the name of the script.
|
||||
*
|
||||
* To use, prefix your JavaScript link URLs with '/cjs/' instead of '/js/' or use JavaScriptHelper::link().
|
||||
*/
|
||||
//Configure::write('Asset.filter.js', 'custom_javascript_output_filter.php');
|
||||
/**
|
||||
* The classname and database used in CakePHP's
|
||||
* access control lists.
|
||||
*/
|
||||
Configure::write('Acl.classname', 'DbAcl');
|
||||
Configure::write('Acl.database', 'default');
|
||||
/**
|
||||
*
|
||||
* Cache Engine Configuration
|
||||
* Default settings provided below
|
||||
*
|
||||
* File storage engine.
|
||||
*
|
||||
* Cache::config('default', array(
|
||||
* 'engine' => 'File', //[required]
|
||||
* 'duration'=> 3600, //[optional]
|
||||
* 'probability'=> 100, //[optional]
|
||||
* 'path' => CACHE, //[optional] use system tmp directory - remember to use absolute path
|
||||
* 'prefix' => 'cake_', //[optional] prefix every cache file with this string
|
||||
* 'lock' => false, //[optional] use file locking
|
||||
* 'serialize' => true, [optional]
|
||||
* ));
|
||||
*
|
||||
*
|
||||
* APC (http://pecl.php.net/package/APC)
|
||||
*
|
||||
* Cache::config('default', array(
|
||||
* 'engine' => 'Apc', //[required]
|
||||
* 'duration'=> 3600, //[optional]
|
||||
* 'probability'=> 100, //[optional]
|
||||
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
|
||||
* ));
|
||||
*
|
||||
* Xcache (http://xcache.lighttpd.net/)
|
||||
*
|
||||
* Cache::config('default', array(
|
||||
* 'engine' => 'Xcache', //[required]
|
||||
* 'duration'=> 3600, //[optional]
|
||||
* 'probability'=> 100, //[optional]
|
||||
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
|
||||
* 'user' => 'user', //user from xcache.admin.user settings
|
||||
* 'password' => 'password', //plaintext password (xcache.admin.pass)
|
||||
* ));
|
||||
*
|
||||
*
|
||||
* Memcache (http://www.danga.com/memcached/)
|
||||
*
|
||||
* Cache::config('default', array(
|
||||
* 'engine' => 'Memcache', //[required]
|
||||
* 'duration'=> 3600, //[optional]
|
||||
* 'probability'=> 100, //[optional]
|
||||
* 'prefix' => Inflector::slug(APP_DIR) . '_', //[optional] prefix every cache file with this string
|
||||
* 'servers' => array(
|
||||
* '127.0.0.1:11211' // localhost, default port 11211
|
||||
* ), //[optional]
|
||||
* 'compress' => false, // [optional] compress data in Memcache (slower, but uses less memory)
|
||||
* ));
|
||||
*
|
||||
*/
|
||||
Cache::config('default', array('engine' => 'File'));
|
||||
?>
|
||||
14
config/database.php
Normal file
14
config/database.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
class DATABASE_CONFIG {
|
||||
|
||||
var $default = array(
|
||||
'driver' => 'mysql',
|
||||
'persistent' => false,
|
||||
'host' => 'localhost',
|
||||
'login' => 'pmgr',
|
||||
'password' => 'pmgruser',
|
||||
'database' => 'property_manager',
|
||||
'prefix' => 'pmgr_',
|
||||
);
|
||||
}
|
||||
?>
|
||||
101
config/database.php.default
Normal file
101
config/database.php.default
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: database.php.default 8004 2009-01-16 20:15:21Z gwoo $ */
|
||||
/**
|
||||
* This is core configuration file.
|
||||
*
|
||||
* Use it to configure core behaviour ofCake.
|
||||
*
|
||||
* 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.app.config
|
||||
* @since CakePHP(tm) v 0.2.9
|
||||
* @version $Revision: 8004 $
|
||||
* @modifiedby $LastChangedBy: gwoo $
|
||||
* @lastmodified $Date: 2009-01-16 12:15:21 -0800 (Fri, 16 Jan 2009) $
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
/**
|
||||
* In this file you set up your database connection details.
|
||||
*
|
||||
* @package cake
|
||||
* @subpackage cake.config
|
||||
*/
|
||||
/**
|
||||
* Database configuration class.
|
||||
* You can specify multiple configurations for production, development and testing.
|
||||
*
|
||||
* driver => The name of a supported driver; valid options are as follows:
|
||||
* mysql - MySQL 4 & 5,
|
||||
* mysqli - MySQL 4 & 5 Improved Interface (PHP5 only),
|
||||
* sqlite - SQLite (PHP5 only),
|
||||
* postgres - PostgreSQL 7 and higher,
|
||||
* mssql - Microsoft SQL Server 2000 and higher,
|
||||
* db2 - IBM DB2, Cloudscape, and Apache Derby (http://php.net/ibm-db2)
|
||||
* oracle - Oracle 8 and higher
|
||||
* firebird - Firebird/Interbase
|
||||
* sybase - Sybase ASE
|
||||
* adodb-[drivername] - ADOdb interface wrapper (see below),
|
||||
* odbc - ODBC DBO driver
|
||||
*
|
||||
* You can add custom database drivers (or override existing drivers) by adding the
|
||||
* appropriate file to app/models/datasources/dbo. Drivers should be named 'dbo_x.php',
|
||||
* where 'x' is the name of the database.
|
||||
*
|
||||
* persistent => true / false
|
||||
* Determines whether or not the database should use a persistent connection
|
||||
*
|
||||
* connect =>
|
||||
* ADOdb set the connect to one of these
|
||||
* (http://phplens.com/adodb/supported.databases.html) and
|
||||
* append it '|p' for persistent connection. (mssql|p for example, or just mssql for not persistent)
|
||||
* For all other databases, this setting is deprecated.
|
||||
*
|
||||
* host =>
|
||||
* the host you connect to the database. To add a socket or port number, use 'port' => #
|
||||
*
|
||||
* prefix =>
|
||||
* Uses the given prefix for all the tables in this database. This setting can be overridden
|
||||
* on a per-table basis with the Model::$tablePrefix property.
|
||||
*
|
||||
* schema =>
|
||||
* For Postgres and DB2, specifies which schema you would like to use the tables in. Postgres defaults to
|
||||
* 'public', DB2 defaults to empty.
|
||||
*
|
||||
* encoding =>
|
||||
* For MySQL, MySQLi, Postgres and DB2, specifies the character encoding to use when connecting to the
|
||||
* database. Uses database default.
|
||||
*
|
||||
*/
|
||||
class DATABASE_CONFIG {
|
||||
|
||||
var $default = array(
|
||||
'driver' => 'mysql',
|
||||
'persistent' => false,
|
||||
'host' => 'localhost',
|
||||
'login' => 'user',
|
||||
'password' => 'password',
|
||||
'database' => 'database_name',
|
||||
'prefix' => '',
|
||||
);
|
||||
|
||||
var $test = array(
|
||||
'driver' => 'mysql',
|
||||
'persistent' => false,
|
||||
'host' => 'localhost',
|
||||
'login' => 'user',
|
||||
'password' => 'password',
|
||||
'database' => 'test_database_name',
|
||||
'prefix' => '',
|
||||
);
|
||||
}
|
||||
?>
|
||||
70
config/inflections.php
Normal file
70
config/inflections.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: inflections.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||
/**
|
||||
* Custom Inflected Words.
|
||||
*
|
||||
* This file is used to hold words that are not matched in the normail Inflector::pluralize() and
|
||||
* Inflector::singularize()
|
||||
*
|
||||
* PHP versions 4 and %
|
||||
*
|
||||
* 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.app.config
|
||||
* @since CakePHP(tm) v 1.0.0.2312
|
||||
* @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
|
||||
*/
|
||||
/**
|
||||
* This is a key => value array of regex used to match words.
|
||||
* If key matches then the value is returned.
|
||||
*
|
||||
* $pluralRules = array('/(s)tatus$/i' => '\1\2tatuses', '/^(ox)$/i' => '\1\2en', '/([m|l])ouse$/i' => '\1ice');
|
||||
*/
|
||||
$pluralRules = array();
|
||||
/**
|
||||
* This is a key only array of plural words that should not be inflected.
|
||||
* Notice the last comma
|
||||
*
|
||||
* $uninflectedPlural = array('.*[nrlm]ese', '.*deer', '.*fish', '.*measles', '.*ois', '.*pox');
|
||||
*/
|
||||
$uninflectedPlural = array('.*cash');
|
||||
/**
|
||||
* This is a key => value array of plural irregular words.
|
||||
* If key matches then the value is returned.
|
||||
*
|
||||
* $irregularPlural = array('atlas' => 'atlases', 'beef' => 'beefs', 'brother' => 'brothers')
|
||||
*/
|
||||
$irregularPlural = array();
|
||||
/**
|
||||
* This is a key => value array of regex used to match words.
|
||||
* If key matches then the value is returned.
|
||||
*
|
||||
* $singularRules = array('/(s)tatuses$/i' => '\1\2tatus', '/(matr)ices$/i' =>'\1ix','/(vert|ind)ices$/i')
|
||||
*/
|
||||
$singularRules = array();
|
||||
/**
|
||||
* This is a key only array of singular words that should not be inflected.
|
||||
* You should not have to change this value below if you do change it use same format
|
||||
* as the $uninflectedPlural above.
|
||||
*/
|
||||
$uninflectedSingular = $uninflectedPlural;
|
||||
/**
|
||||
* This is a key => value array of singular irregular words.
|
||||
* Most of the time this will be a reverse of the above $irregularPlural array
|
||||
* You should not have to change this value below if you do change it use same format
|
||||
*
|
||||
* $irregularSingular = array('atlases' => 'atlas', 'beefs' => 'beef', 'brothers' => 'brother')
|
||||
*/
|
||||
$irregularSingular = array_flip($irregularPlural);
|
||||
?>
|
||||
55
config/routes.php
Normal file
55
config/routes.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: routes.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||
/**
|
||||
* Short description for file.
|
||||
*
|
||||
* In this file, you set up routes to your controllers and their actions.
|
||||
* Routes are very important mechanism that allows you to freely connect
|
||||
* different urls to chosen controllers and their actions (functions).
|
||||
*
|
||||
* 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.app.config
|
||||
* @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
|
||||
*/
|
||||
|
||||
$default_path = array('controller' => 'maps', 'action' => 'view', '1');
|
||||
|
||||
/**
|
||||
* Here, we are connecting '/' (base path) to our site map.
|
||||
* It's hardcoded to map #1, but at some point we'll implement
|
||||
* a login mechanism and the default path will be to log on instead.
|
||||
*/
|
||||
Router::connect('/', $default_path);
|
||||
|
||||
/*
|
||||
* Route for admin functionality
|
||||
*/
|
||||
Router::connect('/admin',
|
||||
array('admin_route' => true) + $default_path);
|
||||
Router::connect('/admin/:controller/:action/*',
|
||||
array('admin_route' => true, 'action' => null));
|
||||
|
||||
/*
|
||||
* Route for development functionality
|
||||
*/
|
||||
Router::connect('/dev',
|
||||
array('dev_route' => true) + $default_path);
|
||||
Router::connect('/dev/:controller/:action/*',
|
||||
array('dev_route' => true, 'action' => null));
|
||||
|
||||
?>
|
||||
79
config/sql/db_acl.php
Normal file
79
config/sql/db_acl.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: db_acl.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||
/*DbAcl schema generated on: 2007-11-24 15:11:13 : 1195945453*/
|
||||
/**
|
||||
* This is Acl Schema file
|
||||
*
|
||||
* Use it to configure database for ACL
|
||||
*
|
||||
* 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.app.config.sql
|
||||
* @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
|
||||
*/
|
||||
/*
|
||||
*
|
||||
* Using the Schema command line utility
|
||||
* cake schema run create DbAcl
|
||||
*
|
||||
*/
|
||||
class DbAclSchema extends CakeSchema {
|
||||
|
||||
var $name = 'DbAcl';
|
||||
|
||||
function before($event = array()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function after($event = array()) {
|
||||
}
|
||||
|
||||
var $acos = array(
|
||||
'id' => array('type'=>'integer', 'null' => false, 'default' => NULL, 'length' => 10, 'key' => 'primary'),
|
||||
'parent_id' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
|
||||
'model' => array('type'=>'string', 'null' => true),
|
||||
'foreign_key' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
|
||||
'alias' => array('type'=>'string', 'null' => true),
|
||||
'lft' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
|
||||
'rght' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
|
||||
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1))
|
||||
);
|
||||
|
||||
var $aros = array(
|
||||
'id' => array('type'=>'integer', 'null' => false, 'default' => NULL, 'length' => 10, 'key' => 'primary'),
|
||||
'parent_id' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
|
||||
'model' => array('type'=>'string', 'null' => true),
|
||||
'foreign_key' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
|
||||
'alias' => array('type'=>'string', 'null' => true),
|
||||
'lft' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
|
||||
'rght' => array('type'=>'integer', 'null' => true, 'default' => NULL, 'length' => 10),
|
||||
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1))
|
||||
);
|
||||
|
||||
var $aros_acos = array(
|
||||
'id' => array('type'=>'integer', 'null' => false, 'default' => NULL, 'length' => 10, 'key' => 'primary'),
|
||||
'aro_id' => array('type'=>'integer', 'null' => false, 'length' => 10, 'key' => 'index'),
|
||||
'aco_id' => array('type'=>'integer', 'null' => false, 'length' => 10),
|
||||
'_create' => array('type'=>'string', 'null' => false, 'default' => '0', 'length' => 2),
|
||||
'_read' => array('type'=>'string', 'null' => false, 'default' => '0', 'length' => 2),
|
||||
'_update' => array('type'=>'string', 'null' => false, 'default' => '0', 'length' => 2),
|
||||
'_delete' => array('type'=>'string', 'null' => false, 'default' => '0', 'length' => 2),
|
||||
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1), 'ARO_ACO_KEY' => array('column' => array('aro_id', 'aco_id'), 'unique' => 1))
|
||||
);
|
||||
|
||||
}
|
||||
?>
|
||||
40
config/sql/db_acl.sql
Normal file
40
config/sql/db_acl.sql
Normal file
@@ -0,0 +1,40 @@
|
||||
# $Id: db_acl.sql 7945 2008-12-19 02:16:01Z gwoo $
|
||||
#
|
||||
# Copyright 2005-2008, Cake Software Foundation, Inc.
|
||||
#
|
||||
# Licensed under The MIT License
|
||||
# Redistributions of files must retain the above copyright notice.
|
||||
# http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
|
||||
CREATE TABLE acos (
|
||||
id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
parent_id INTEGER(10) DEFAULT NULL,
|
||||
model VARCHAR(255) DEFAULT '',
|
||||
foreign_key INTEGER(10) UNSIGNED DEFAULT NULL,
|
||||
alias VARCHAR(255) DEFAULT '',
|
||||
lft INTEGER(10) DEFAULT NULL,
|
||||
rght INTEGER(10) DEFAULT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE aros_acos (
|
||||
id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
aro_id INTEGER(10) UNSIGNED NOT NULL,
|
||||
aco_id INTEGER(10) UNSIGNED NOT NULL,
|
||||
_create CHAR(2) NOT NULL DEFAULT 0,
|
||||
_read CHAR(2) NOT NULL DEFAULT 0,
|
||||
_update CHAR(2) NOT NULL DEFAULT 0,
|
||||
_delete CHAR(2) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY(id)
|
||||
);
|
||||
|
||||
CREATE TABLE aros (
|
||||
id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
parent_id INTEGER(10) DEFAULT NULL,
|
||||
model VARCHAR(255) DEFAULT '',
|
||||
foreign_key INTEGER(10) UNSIGNED DEFAULT NULL,
|
||||
alias VARCHAR(255) DEFAULT '',
|
||||
lft INTEGER(10) DEFAULT NULL,
|
||||
rght INTEGER(10) DEFAULT NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
56
config/sql/i18n.php
Normal file
56
config/sql/i18n.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: i18n.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||
/*i18n schema generated on: 2007-11-25 07:11:25 : 1196004805*/
|
||||
/**
|
||||
* This is i18n Schema file
|
||||
*
|
||||
* Use it to configure database for i18n
|
||||
*
|
||||
* 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.app.config.sql
|
||||
* @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
|
||||
*/
|
||||
/*
|
||||
*
|
||||
* Using the Schema command line utility
|
||||
* cake schema run create i18n
|
||||
*
|
||||
*/
|
||||
class i18nSchema extends CakeSchema {
|
||||
|
||||
var $name = 'i18n';
|
||||
|
||||
function before($event = array()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function after($event = array()) {
|
||||
}
|
||||
|
||||
var $i18n = array(
|
||||
'id' => array('type'=>'integer', 'null' => false, 'default' => NULL, 'length' => 10, 'key' => 'primary'),
|
||||
'locale' => array('type'=>'string', 'null' => false, 'length' => 6, 'key' => 'index'),
|
||||
'model' => array('type'=>'string', 'null' => false, 'key' => 'index'),
|
||||
'foreign_key' => array('type'=>'integer', 'null' => false, 'length' => 10, 'key' => 'index'),
|
||||
'field' => array('type'=>'string', 'null' => false, 'key' => 'index'),
|
||||
'content' => array('type'=>'text', 'null' => true, 'default' => NULL),
|
||||
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1), 'locale' => array('column' => 'locale', 'unique' => 0), 'model' => array('column' => 'model', 'unique' => 0), 'row_id' => array('column' => 'foreign_key', 'unique' => 0), 'field' => array('column' => 'field', 'unique' => 0))
|
||||
);
|
||||
|
||||
}
|
||||
?>
|
||||
26
config/sql/i18n.sql
Normal file
26
config/sql/i18n.sql
Normal file
@@ -0,0 +1,26 @@
|
||||
# $Id: i18n.sql 7945 2008-12-19 02:16:01Z gwoo $
|
||||
#
|
||||
# Copyright 2005-2008, Cake Software Foundation, Inc.
|
||||
#
|
||||
# Licensed under The MIT License
|
||||
# Redistributions of files must retain the above copyright notice.
|
||||
# http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
|
||||
CREATE TABLE i18n (
|
||||
id int(10) NOT NULL auto_increment,
|
||||
locale varchar(6) NOT NULL,
|
||||
model varchar(255) NOT NULL,
|
||||
foreign_key int(10) NOT NULL,
|
||||
field varchar(255) NOT NULL,
|
||||
content mediumtext,
|
||||
PRIMARY KEY (id),
|
||||
# UNIQUE INDEX I18N_LOCALE_FIELD(locale, model, foreign_key, field),
|
||||
# INDEX I18N_LOCALE_ROW(locale, model, foreign_key),
|
||||
# INDEX I18N_LOCALE_MODEL(locale, model),
|
||||
# INDEX I18N_FIELD(model, foreign_key, field),
|
||||
# INDEX I18N_ROW(model, foreign_key),
|
||||
INDEX locale (locale),
|
||||
INDEX model (model),
|
||||
INDEX row_id (foreign_key),
|
||||
INDEX field (field)
|
||||
);
|
||||
53
config/sql/sessions.php
Normal file
53
config/sql/sessions.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: sessions.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||
/*Sessions schema generated on: 2007-11-25 07:11:54 : 1196004714*/
|
||||
/**
|
||||
* This is Sessions Schema file
|
||||
*
|
||||
* Use it to configure database for Sessions
|
||||
*
|
||||
* 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.app.config.sql
|
||||
* @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
|
||||
*/
|
||||
/*
|
||||
*
|
||||
* Using the Schema command line utility
|
||||
* cake schema run create Sessions
|
||||
*
|
||||
*/
|
||||
class SessionsSchema extends CakeSchema {
|
||||
|
||||
var $name = 'Sessions';
|
||||
|
||||
function before($event = array()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function after($event = array()) {
|
||||
}
|
||||
|
||||
var $cake_sessions = array(
|
||||
'id' => array('type'=>'string', 'null' => false, 'key' => 'primary'),
|
||||
'data' => array('type'=>'text', 'null' => true, 'default' => NULL),
|
||||
'expires' => array('type'=>'integer', 'null' => true, 'default' => NULL),
|
||||
'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1))
|
||||
);
|
||||
|
||||
}
|
||||
?>
|
||||
16
config/sql/sessions.sql
Normal file
16
config/sql/sessions.sql
Normal file
@@ -0,0 +1,16 @@
|
||||
# $Id: sessions.sql 7118 2008-06-04 20:49:29Z gwoo $
|
||||
#
|
||||
# Copyright 2005-2008, Cake Software Foundation, Inc.
|
||||
# 1785 E. Sahara Avenue, Suite 490-204
|
||||
# Las Vegas, Nevada 89104
|
||||
#
|
||||
# Licensed under The MIT License
|
||||
# Redistributions of files must retain the above copyright notice.
|
||||
# http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
|
||||
CREATE TABLE cake_sessions (
|
||||
id varchar(255) NOT NULL default '',
|
||||
data text,
|
||||
expires int(11) default NULL,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
204
controllers/accounts_controller.php
Normal file
204
controllers/accounts_controller.php
Normal file
@@ -0,0 +1,204 @@
|
||||
<?php
|
||||
|
||||
class AccountsController extends AppController {
|
||||
|
||||
var $uses = array('Account', 'LedgerEntry');
|
||||
|
||||
var $sidemenu_links =
|
||||
array(array('name' => 'Accounts', 'header' => true),
|
||||
array('name' => 'All', 'url' => array('controller' => 'accounts', 'action' => 'all')),
|
||||
array('name' => 'Asset', 'url' => array('controller' => 'accounts', 'action' => 'asset')),
|
||||
array('name' => 'Liability', 'url' => array('controller' => 'accounts', 'action' => 'liability')),
|
||||
array('name' => 'Equity', 'url' => array('controller' => 'accounts', 'action' => 'equity')),
|
||||
array('name' => 'Income', 'url' => array('controller' => 'accounts', 'action' => 'income')),
|
||||
array('name' => 'Expense', 'url' => array('controller' => 'accounts', 'action' => 'expense')),
|
||||
);
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* override: sideMenuLinks
|
||||
* - Generates controller specific links for the side menu
|
||||
*/
|
||||
function sideMenuLinks() {
|
||||
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: index / asset / liability / equity / income / expense / all
|
||||
* - Generate a chart of accounts
|
||||
*/
|
||||
|
||||
function index() { $this->all(); }
|
||||
function asset() { $this->gridView('Asset Accounts'); }
|
||||
function liability() { $this->gridView('Liability Accounts'); }
|
||||
function equity() { $this->gridView('Equity Accounts'); }
|
||||
function income() { $this->gridView('Income Accounts'); }
|
||||
function expense() { $this->gridView('Expense Accounts'); }
|
||||
function all() { $this->gridView('All Accounts', 'all'); }
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* virtuals: gridData
|
||||
* - With the application controller handling the gridData action,
|
||||
* these virtual functions ensure that the correct data is passed
|
||||
* to jqGrid.
|
||||
*/
|
||||
|
||||
function gridDataSetup(&$params) {
|
||||
parent::gridDataSetup($params);
|
||||
if (!isset($params['action']))
|
||||
$params['action'] = 'all';
|
||||
}
|
||||
|
||||
function gridDataCountTables(&$params, &$model) {
|
||||
// Our count should NOT include anything extra,
|
||||
// so we need the virtual function to prevent
|
||||
// the base class from just calling our
|
||||
// gridDataTables function
|
||||
return parent::gridDataTables($params, $model);
|
||||
}
|
||||
|
||||
function gridDataTables(&$params, &$model) {
|
||||
return array
|
||||
('link' =>
|
||||
array(// Models
|
||||
'CurrentLedger' => array
|
||||
(// Models
|
||||
'LedgerEntry'
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function gridDataFields(&$params, &$model) {
|
||||
$fields = parent::gridDataFields($params, $model);
|
||||
return array_merge($fields,
|
||||
$this->Account->Ledger->LedgerEntry->debitCreditFields(true));
|
||||
}
|
||||
|
||||
function gridDataConditions(&$params, &$model) {
|
||||
$conditions = parent::gridDataConditions($params, $model);
|
||||
|
||||
if (in_array($params['action'], array('asset', 'liability', 'equity', 'income', 'expense'))) {
|
||||
$conditions[] = array('Account.type' => strtoupper($params['action']));
|
||||
}
|
||||
|
||||
// REVISIT <AP>: 20090811
|
||||
// No security issues have been worked out yet
|
||||
$conditions[] = array('Account.level >=' => 10);
|
||||
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||
$links['Account'] = array('name');
|
||||
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: newledger
|
||||
* - Close the current account ledger and create a new one,
|
||||
* carrying forward any balance if necessary.
|
||||
*/
|
||||
|
||||
function newledger($id = null) {
|
||||
$result = $this->Account->closeCurrentLedgers($id);
|
||||
|
||||
if ($result['error']) {
|
||||
pr(compact('result'));
|
||||
die("Unable to create new ledger.");
|
||||
$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'));
|
||||
}
|
||||
|
||||
$this->Account->recursive = -1;
|
||||
$account = $this->Account->read(null, $id);
|
||||
$account = $account['Account'];
|
||||
|
||||
$accounts = $this->Account->collectableAccounts();
|
||||
$payment_accounts = $accounts['all'];
|
||||
$default_accounts = $accounts['default'];
|
||||
$this->set(compact('payment_accounts', 'default_accounts'));
|
||||
|
||||
$title = ($account['name'] . ': Collected Report');
|
||||
$this->set(compact('account', 'title'));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: view
|
||||
* - Displays information about a specific account
|
||||
*/
|
||||
|
||||
function view($id = null) {
|
||||
$account = $this->Account->find
|
||||
('first',
|
||||
array('contain' =>
|
||||
array(// Models
|
||||
'CurrentLedger' =>
|
||||
array('fields' => array('id', 'sequence', 'name')),
|
||||
|
||||
'Ledger' =>
|
||||
array('CloseTransaction' => array
|
||||
('order' => array('CloseTransaction.stamp' => 'DESC'))),
|
||||
),
|
||||
'conditions' => array(array('Account.id' => $id),
|
||||
// REVISIT <AP>: 20090811
|
||||
// No security issues have been worked out yet
|
||||
array('Account.level >=' => 10),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
if (empty($account)) {
|
||||
$this->Session->setFlash(__('Invalid Item.', true));
|
||||
$this->redirect(array('action'=>'index'));
|
||||
}
|
||||
|
||||
// Obtain stats across ALL ledgers for the summary infobox
|
||||
$stats = $this->Account->stats($id, true);
|
||||
$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
|
||||
$title = 'Account: ' . $account['Account']['name'];
|
||||
$this->set(compact('account', 'title', 'stats'));
|
||||
}
|
||||
|
||||
}
|
||||
202
controllers/contacts_controller.php
Normal file
202
controllers/contacts_controller.php
Normal file
@@ -0,0 +1,202 @@
|
||||
<?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->gridView('All Contacts', 'all'); }
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* virtuals: gridData
|
||||
* - With the application controller handling the gridData action,
|
||||
* these virtual functions ensure that the correct data is passed
|
||||
* to jqGrid.
|
||||
*/
|
||||
|
||||
function gridDataOrder(&$params, &$model, $index, $direction) {
|
||||
$order = parent::gridDataOrder($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 gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||
$links['Contact'] = array('id');
|
||||
return parent::gridDataPostProcessLinks($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']));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
486
controllers/customers_controller.php
Normal file
486
controllers/customers_controller.php
Normal file
@@ -0,0 +1,486 @@
|
||||
<?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->gridView('Current Tenants', 'current'); }
|
||||
function past() { $this->gridView('Past Tenants'); }
|
||||
function all() { $this->gridView('All Customers'); }
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* virtuals: gridData
|
||||
* - With the application controller handling the gridData action,
|
||||
* these virtual functions ensure that the correct data is passed
|
||||
* to jqGrid.
|
||||
*/
|
||||
|
||||
function gridDataCountTables(&$params, &$model) {
|
||||
return array
|
||||
('link' =>
|
||||
array(// Models
|
||||
'PrimaryContact',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function gridDataTables(&$params, &$model) {
|
||||
$link = $this->gridDataCountTables($params, $model);
|
||||
// StatementEntry is needed to determine customer balance
|
||||
$link['link']['StatementEntry'] = array('fields' => array());
|
||||
return $link;
|
||||
}
|
||||
|
||||
function gridDataFields(&$params, &$model) {
|
||||
$fields = parent::gridDataFields($params, $model);
|
||||
return array_merge($fields,
|
||||
$this->Customer->StatementEntry->chargeDisbursementFields(true));
|
||||
}
|
||||
|
||||
function gridDataConditions(&$params, &$model) {
|
||||
$conditions = parent::gridDataConditions($params, $model);
|
||||
|
||||
if ($params['action'] === 'current') {
|
||||
$conditions[] = array('Customer.current_lease_count >' => 0);
|
||||
}
|
||||
elseif ($params['action'] === 'past') {
|
||||
$conditions[] = array('Customer.current_lease_count' => 0);
|
||||
$conditions[] = array('Customer.past_lease_count >' => 0);
|
||||
}
|
||||
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
function gridDataOrder(&$params, &$model, $index, $direction) {
|
||||
$order = array();
|
||||
$order[] = parent::gridDataOrder($params, $model, $index, $direction);
|
||||
|
||||
if ($index !== 'PrimaryContact.last_name')
|
||||
$order[] = parent::gridDataOrder($params, $model,
|
||||
'PrimaryContact.last_name', $direction);
|
||||
if ($index !== 'PrimaryContact.first_name')
|
||||
$order[] = parent::gridDataOrder($params, $model,
|
||||
'PrimaryContact.first_name', $direction);
|
||||
if ($index !== 'Customer.id')
|
||||
$order[] = parent::gridDataOrder($params, $model,
|
||||
'Customer.id', $direction);
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||
$links['Customer'] = array('name');
|
||||
return parent::gridDataPostProcessLinks($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'));
|
||||
}
|
||||
|
||||
// Get details on this customer, its contacts and leases
|
||||
$customer = $this->Customer->find
|
||||
('first', array
|
||||
('contain' => array
|
||||
(// Models
|
||||
'Contact' =>
|
||||
array('order' => array('Contact.display_name'),
|
||||
// Models
|
||||
'ContactPhone',
|
||||
'ContactEmail',
|
||||
'ContactAddress',
|
||||
),
|
||||
'Lease' =>
|
||||
array('Unit' =>
|
||||
array('order' => array('sort_order'),
|
||||
'fields' => array('id', 'name'),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
'conditions' => array('Customer.id' => $id),
|
||||
));
|
||||
//pr($customer);
|
||||
|
||||
// Determine how long this customer has been with us.
|
||||
$leaseinfo = $this->Customer->find
|
||||
('first', array
|
||||
('link' => array('Lease' => array('fields' => array())),
|
||||
'fields' => array('MIN(Lease.movein_date) AS since',
|
||||
'IF(Customer.current_lease_count = 0, MAX(Lease.moveout_date), NULL) AS until'),
|
||||
'conditions' => array('Customer.id' => $id),
|
||||
'group' => 'Customer.id',
|
||||
));
|
||||
$this->set($leaseinfo[0]);
|
||||
|
||||
// Figure out the outstanding balances for this customer
|
||||
//$this->set('stats', $this->Customer->stats($id));
|
||||
$outstanding_balance = $this->Customer->balance($id);
|
||||
$outstanding_deposit = $this->Customer->securityDepositBalance($id);
|
||||
|
||||
// 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 || $outstanding_balance > 0)
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'New Receipt',
|
||||
'url' => array('action' => 'receipt',
|
||||
$id));
|
||||
|
||||
if (!$show_moveout && $outstanding_balance > 0)
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'Write-Off',
|
||||
'url' => array('action' => 'bad_debt',
|
||||
$id));
|
||||
|
||||
if ($outstanding_balance < 0)
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'Issue Refund',
|
||||
'url' => array('action' => 'refund', $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']));
|
||||
|
||||
$this->redirect(array('action'=>'index'));
|
||||
}
|
||||
|
||||
// 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']));
|
||||
}
|
||||
|
||||
// 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']));
|
||||
}
|
||||
|
||||
// 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.
|
||||
if ($this->data['Customer']['id'])
|
||||
$this->redirect(array('action'=>'view', $this->Customer->id));
|
||||
|
||||
// Since this is a new customer, go to the move in screen.
|
||||
$this->redirect(array('action'=>'move_in', $this->Customer->id));
|
||||
}
|
||||
|
||||
if ($id) {
|
||||
// REVISIT <AP>: 20090816
|
||||
// This should never need to be done by a controller.
|
||||
// However, until things stabilize, this gives the
|
||||
// user a way to update any cached items on the
|
||||
// customer, by just clicking Edit then Cancel.
|
||||
$this->Customer->update($id);
|
||||
|
||||
// Get details on this customer, its contacts and leases
|
||||
$customer = $this->Customer->find
|
||||
('first', array
|
||||
('contain' => array
|
||||
(// Models
|
||||
'Contact' =>
|
||||
array('order' => array('Contact.display_name'),
|
||||
// Models
|
||||
'ContactPhone',
|
||||
'ContactEmail',
|
||||
'ContactAddress',
|
||||
),
|
||||
'Lease' =>
|
||||
array('Unit' =>
|
||||
array('order' => array('sort_order'),
|
||||
'fields' => array('id', 'name'),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
'conditions' => array('Customer.id' => $id),
|
||||
));
|
||||
|
||||
$this->data = $customer;
|
||||
$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'];
|
||||
}
|
||||
else {
|
||||
$customer = null;
|
||||
}
|
||||
|
||||
$TT = new TenderType();
|
||||
$payment_types = $TT->paymentTypes();
|
||||
$default_type = $TT->defaultPaymentType();
|
||||
$this->set(compact('payment_types', 'default_type'));
|
||||
|
||||
$title = ($customer['name'] . ': Receipt Entry');
|
||||
$this->set(compact('customer', 'title'));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: refund
|
||||
* - Refunds customer charges
|
||||
*/
|
||||
|
||||
function refund($id) {
|
||||
$customer = $this->Customer->find
|
||||
('first', array
|
||||
('contain' => false,
|
||||
'conditions' => array(array('Customer.id' => $id),
|
||||
),
|
||||
));
|
||||
if (empty($customer)) {
|
||||
$this->redirect(array('action'=>'view', $id));
|
||||
}
|
||||
|
||||
// Determine the customer balance, bailing if the customer owes money
|
||||
$balance = $this->Customer->balance($id);
|
||||
if ($balance >= 0) {
|
||||
$this->redirect(array('action'=>'view', $id));
|
||||
}
|
||||
|
||||
// The refund will be for a positive amount
|
||||
$balance *= -1;
|
||||
|
||||
// Get the accounts capable of paying the refund
|
||||
$refundAccounts = $this->Customer->StatementEntry->Account->refundAccounts();
|
||||
$defaultAccount = current($refundAccounts);
|
||||
$this->set(compact('refundAccounts', 'defaultAccount'));
|
||||
|
||||
// Prepare to render
|
||||
$title = ($customer['Customer']['name'] . ': Refund');
|
||||
$this->set(compact('title', 'customer', 'balance'));
|
||||
$this->render('/transactions/refund');
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: bad_debt
|
||||
* - Sets up the write-off entry page, so that the
|
||||
* user can write off remaining charges of a customer.
|
||||
*/
|
||||
|
||||
function bad_debt($id) {
|
||||
$this->Customer->id = $id;
|
||||
$customer = $this->Customer->find
|
||||
('first', array
|
||||
('contain' => false,
|
||||
));
|
||||
|
||||
// Make sure we have a valid customer to write off
|
||||
if (empty($customer))
|
||||
$this->redirect(array('action' => 'index'));
|
||||
|
||||
// Get the customer balance
|
||||
$balance = $this->Customer->balance($id);
|
||||
|
||||
// Prepare to render
|
||||
$title = ($customer['Customer']['name'] . ': Write Off Bad Debt');
|
||||
$this->set(compact('title', 'customer', 'balance'));
|
||||
$this->render('/transactions/bad_debt');
|
||||
}
|
||||
|
||||
}
|
||||
66
controllers/double_entries_controller.php
Normal file
66
controllers/double_entries_controller.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
class DoubleEntriesController 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: view
|
||||
* - Displays information about a specific entry
|
||||
*/
|
||||
|
||||
function view($id = null) {
|
||||
if (!$id) {
|
||||
$this->Session->setFlash(__('Invalid Item.', true));
|
||||
$this->redirect(array('controller' => 'accounts', 'action'=>'index'));
|
||||
}
|
||||
|
||||
// Get the Entry and related fields
|
||||
$entry = $this->DoubleEntry->find
|
||||
('first',
|
||||
array('contain' => array('DebitEntry', 'CreditEntry'),
|
||||
'conditions' => array('DoubleEntry.id' => $id),
|
||||
));
|
||||
|
||||
$entry += $this->DoubleEntry->DebitEntry->Transaction->find
|
||||
('first',
|
||||
array('contain' => false,
|
||||
'conditions' => array('id' => $entry['DebitEntry']['transaction_id']),
|
||||
));
|
||||
|
||||
$entry += $this->DoubleEntry->DebitEntry->find
|
||||
('first',
|
||||
array('contain' => array('Ledger' => array('Account')),
|
||||
'conditions' => array('DebitEntry.id' => $entry['DebitEntry']['id']),
|
||||
));
|
||||
$entry['DebitLedger'] = $entry['Ledger'];
|
||||
unset($entry['Ledger']);
|
||||
|
||||
$entry += $this->DoubleEntry->CreditEntry->find
|
||||
('first',
|
||||
array('contain' => array('Ledger' => array('Account')),
|
||||
'conditions' => array('CreditEntry.id' => $entry['CreditEntry']['id']),
|
||||
));
|
||||
$entry['CreditLedger'] = $entry['Ledger'];
|
||||
unset($entry['Ledger']);
|
||||
|
||||
// Prepare to render.
|
||||
$title = "Double Ledger Entry #{$entry['DoubleEntry']['id']}";
|
||||
$this->set(compact('entry', 'title'));
|
||||
}
|
||||
|
||||
}
|
||||
524
controllers/leases_controller.php
Normal file
524
controllers/leases_controller.php
Normal file
@@ -0,0 +1,524 @@
|
||||
<?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' => 'Delinquent', 'url' => array('controller' => 'leases', 'action' => 'delinquent')),
|
||||
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->gridView('Active Leases'); }
|
||||
function delinquent() { $this->gridView('Delinquent Leases'); }
|
||||
function closed() { $this->gridView('Closed Leases'); }
|
||||
function all() { $this->gridView('All Leases', 'all'); }
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* virtuals: gridData
|
||||
* - With the application controller handling the gridData action,
|
||||
* these virtual functions ensure that the correct data is passed
|
||||
* to jqGrid.
|
||||
*/
|
||||
|
||||
function gridDataSetup(&$params) {
|
||||
parent::gridDataSetup($params);
|
||||
if (!isset($params['action']))
|
||||
$params['action'] = 'all';
|
||||
}
|
||||
|
||||
function gridDataCountTables(&$params, &$model) {
|
||||
return array
|
||||
('link' => array('Unit' => array('fields' => array('id', 'name')),
|
||||
'Customer' => array('fields' => array('id', 'name'))));
|
||||
}
|
||||
|
||||
function gridDataTables(&$params, &$model) {
|
||||
$link = $this->gridDataCountTables($params, $model);
|
||||
$link['link']['StatementEntry'] = array('fields' => array());
|
||||
return $link;
|
||||
}
|
||||
|
||||
function gridDataFields(&$params, &$model) {
|
||||
$fields = parent::gridDataFields($params, $model);
|
||||
$fields[] = ("IF(" . $this->Lease->conditionDelinquent() . "," .
|
||||
" 'DELINQUENT', 'CURRENT') AS 'status'");
|
||||
return array_merge($fields,
|
||||
$this->Lease->StatementEntry->chargeDisbursementFields(true));
|
||||
}
|
||||
|
||||
function gridDataConditions(&$params, &$model) {
|
||||
$conditions = parent::gridDataConditions($params, $model);
|
||||
|
||||
if ($params['action'] === 'active') {
|
||||
$conditions[] = 'Lease.close_date IS NULL';
|
||||
}
|
||||
elseif ($params['action'] === 'delinquent') {
|
||||
$conditions[] = $this->Lease->conditionDelinquent();
|
||||
}
|
||||
elseif ($params['action'] === 'closed') {
|
||||
$conditions[] = 'Lease.close_date IS NOT NULL';
|
||||
}
|
||||
|
||||
if (isset($customer_id))
|
||||
$conditions[] = array('Lease.customer_id' => $customer_id);
|
||||
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
function gridDataOrder(&$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::gridDataOrder($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::gridDataOrder($params, $model,
|
||||
'Lease.id', $direction);
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
/* function gridDataPostProcess(&$params, &$model, &$records) { */
|
||||
/* foreach ($records AS &$record) { */
|
||||
/* $record['Lease']['through_date'] */
|
||||
/* = $this->Lease->rentChargeThrough($record['Lease']['id']); */
|
||||
/* } */
|
||||
|
||||
/* parent::gridDataPostProcess($params, $model, $records); */
|
||||
/* } */
|
||||
|
||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||
$links['Lease'] = array('number');
|
||||
$links['Unit'] = array('name');
|
||||
$links['Customer'] = array('name');
|
||||
return parent::gridDataPostProcessLinks($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));
|
||||
foreach (array('deposit', 'rent') AS $currency) {
|
||||
$this->data['Lease'][$currency]
|
||||
= str_replace('$', '', $this->data['Lease'][$currency]);
|
||||
}
|
||||
|
||||
$lid = $this->Lease->moveIn($this->data['Lease']['customer_id'],
|
||||
$this->data['Lease']['unit_id'],
|
||||
$this->data['Lease']['deposit'],
|
||||
$this->data['Lease']['rent'],
|
||||
$this->data['Lease']['movein_date'],
|
||||
$this->data['Lease']['comment']
|
||||
);
|
||||
|
||||
// Since this is a new lease, go to the invoice
|
||||
// screen so we can start assessing charges.
|
||||
$this->redirect(array('action'=>'invoice', $lid, 'move-in'));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* 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']
|
||||
);
|
||||
|
||||
$this->redirect($this->data['redirect']);
|
||||
}
|
||||
|
||||
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: promote_credit */
|
||||
/* * - Moves any lease credit up to the customer level, so that */
|
||||
/* * it may be used for charges other than those on this lease. */
|
||||
/* *\/ */
|
||||
|
||||
/* function promote_surplus($id) { */
|
||||
/* $this->Lease->promoteSurplus($id); */
|
||||
/* $this->redirect(array('controller' => 'leases', */
|
||||
/* 'action' => 'view', */
|
||||
/* $id)); */
|
||||
/* } */
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: refund
|
||||
* - Provides lease customer with a refund
|
||||
*/
|
||||
|
||||
function refund($id) {
|
||||
$lease = $this->Lease->find
|
||||
('first', array
|
||||
('contain' => array
|
||||
(// Models
|
||||
'Unit' => array('fields' => array('id', 'name')),
|
||||
'Customer' => array('fields' => array('id', 'name')),
|
||||
),
|
||||
|
||||
'conditions' => array(array('Lease.id' => $id),
|
||||
// Make sure lease is not closed...
|
||||
array('Lease.close_date' => null),
|
||||
),
|
||||
));
|
||||
if (empty($lease)) {
|
||||
$this->redirect(array('action'=>'view', $id));
|
||||
}
|
||||
|
||||
// Determine the lease balance, bailing if the customer owes money
|
||||
$balance = $this->Lease->balance($id);
|
||||
if ($balance >= 0) {
|
||||
$this->redirect(array('action'=>'view', $id));
|
||||
}
|
||||
|
||||
// The refund will be for a positive amount
|
||||
$balance *= -1;
|
||||
|
||||
// Get the accounts capable of paying the refund
|
||||
$refundAccounts = $this->Lease->StatementEntry->Account->refundAccounts();
|
||||
$defaultAccount = current($refundAccounts);
|
||||
$this->set(compact('refundAccounts', 'defaultAccount'));
|
||||
|
||||
// Prepare to render
|
||||
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
|
||||
$lease['Unit']['name'] . ': ' .
|
||||
$lease['Customer']['name'] . ': Refund');
|
||||
$this->set(compact('title', 'lease', 'balance'));
|
||||
$this->render('/transactions/refund');
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: bad_debt
|
||||
* - Sets up the write-off entry page, so that the
|
||||
* user can write off remaining charges on a lease.
|
||||
*/
|
||||
|
||||
function bad_debt($id) {
|
||||
$this->Lease->id = $id;
|
||||
$lease = $this->Lease->find
|
||||
('first', array
|
||||
('contain' => array
|
||||
(// Models
|
||||
'Unit' => array('fields' => array('id', 'name')),
|
||||
'Customer' => array('fields' => array('id', 'name')),
|
||||
),
|
||||
));
|
||||
|
||||
// Make sure we have a valid lease to write off
|
||||
if (empty($lease))
|
||||
$this->redirect(array('action' => 'view', $id));
|
||||
|
||||
// Get the lease balance
|
||||
$balance = $this->Lease->balance($id);
|
||||
|
||||
// Prepare to render
|
||||
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
|
||||
$lease['Unit']['name'] . ': ' .
|
||||
$lease['Customer']['name'] . ': Write Off Bad Debt');
|
||||
$this->set(compact('title', 'lease', 'balance'));
|
||||
$this->render('/transactions/bad_debt');
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: close
|
||||
* - Closes a lease to any further action
|
||||
*/
|
||||
|
||||
// REVISIT <AP>: 20090809
|
||||
// While cleaning up the sitelink data, then delete reldep()
|
||||
function reldep($id) {
|
||||
$this->Lease->id = $id;
|
||||
$stamp = $this->Lease->field('moveout_date');
|
||||
$this->Lease->releaseSecurityDeposits($id, $stamp);
|
||||
$this->redirect(array('action'=>'view', $id));
|
||||
}
|
||||
|
||||
function close($id) {
|
||||
// REVISIT <AP>: 20090708
|
||||
// We should probably seek confirmation first...
|
||||
if (!$this->Lease->closeable($id)) {
|
||||
$this->INTERNAL_ERROR("This lease is not ready to close");
|
||||
$this->redirect(array('action'=>'view', $id));
|
||||
}
|
||||
|
||||
$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->invoiceAccounts();
|
||||
$default_account = $A->rentAccountID();
|
||||
$rent_account = $A->rentAccountID();
|
||||
$security_deposit_account = $A->securityDepositAccountID();
|
||||
$this->set(compact('charge_accounts', 'default_account',
|
||||
'rent_account', 'security_deposit_account'));
|
||||
|
||||
// REVISIT <AP> 20090705:
|
||||
// Of course, the late charge should come from the late_schedule
|
||||
$default_late = 10;
|
||||
$this->set(compact('default_late'));
|
||||
|
||||
if ($type === 'move-in') {
|
||||
$movein = array();
|
||||
$movein['time'] = strtotime($lease['Lease']['movein_date']);
|
||||
$movein['effective_time'] = strtotime($lease['Lease']['movein_date']);
|
||||
$movein_date = getdate($movein['effective_time']);
|
||||
$movein['through_time'] = mktime(0, 0, 0, $movein_date['mon'] + 1, 0, $movein_date['year']);
|
||||
$days_in_month = idate('d', $movein['through_time']);
|
||||
$movein['prorated_days'] = $days_in_month - $movein_date['mday'] + 1;
|
||||
$movein['prorated_rent'] = $lease['Lease']['rent'] * $movein['prorated_days'] / $days_in_month;
|
||||
$movein['prorated'] = $movein['prorated_days'] != $days_in_month;
|
||||
$movein['deposit'] = $lease['Lease']['deposit'];
|
||||
$this->set(compact('movein'));
|
||||
}
|
||||
|
||||
|
||||
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
|
||||
$lease['Unit']['name'] . ': ' .
|
||||
$lease['Customer']['name'] . ': Charge Entry');
|
||||
$this->set(compact('title', 'lease', 'charge'));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: assess_rent/late
|
||||
* - Assesses the new monthly rent/late charge, if need be
|
||||
*/
|
||||
|
||||
function assess_rent($date = null) {
|
||||
$this->Lease->assessMonthlyRentAll($date);
|
||||
$this->redirect(array('action'=>'index'));
|
||||
}
|
||||
function assess_late($date = null) {
|
||||
$this->Lease->assessMonthlyLateAll($date);
|
||||
$this->redirect(array('action'=>'index'));
|
||||
}
|
||||
function assess_all($date = null) {
|
||||
$this->Lease->assessMonthlyRentAll($date);
|
||||
$this->Lease->assessMonthlyLateAll($date);
|
||||
$this->redirect(array('action'=>'index'));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* 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(id,name)',
|
||||
'Unit(id,name)',
|
||||
'Customer(id,name)',
|
||||
),
|
||||
'fields' => array('Lease.*', $this->Lease->delinquentField()),
|
||||
'conditions' => array(array('Lease.id' => $id)),
|
||||
)
|
||||
);
|
||||
$lease['Lease'] += $lease[0];
|
||||
unset($lease[0]);
|
||||
|
||||
// Figure out the outstanding balances for this lease
|
||||
$outstanding_balance = $this->Lease->balance($id);
|
||||
$outstanding_deposit = $this->Lease->securityDepositBalance($id);
|
||||
|
||||
// Set up dynamic menu items. Normally, these will only be present
|
||||
// on an open lease, but it's possible for a lease to be closed, and
|
||||
// yet still have an outstanding balance. This can happen if someone
|
||||
// were to reverse charges, or if a payment should come back NSF.
|
||||
if (!isset($lease['Lease']['close_date']) || $outstanding_balance > 0) {
|
||||
$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));
|
||||
|
||||
if (!isset($lease['Lease']['close_date']))
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'New Invoice', 'url' => array('action' => 'invoice',
|
||||
$id));
|
||||
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'New Receipt', 'url' => array('controller' => 'customers',
|
||||
'action' => 'receipt',
|
||||
$lease['Customer']['id']));
|
||||
|
||||
/* if ($outstanding_balance < 0) */
|
||||
/* $this->sidemenu_links[] = */
|
||||
/* array('name' => 'Transfer Credit to Customer', */
|
||||
/* 'url' => array('action' => 'promote_surplus', $id)); */
|
||||
|
||||
// REVISIT <AP>:
|
||||
// Not allowing refund to be issued from the lease, as
|
||||
// in fact, we should never have a positive lease balance.
|
||||
// I'll flag this at the moment, since we might get one
|
||||
// when a charge is reimbursed; a bug that we'll either
|
||||
// need to fix, or we'll have to revisit this assumption.
|
||||
if ($outstanding_balance < 0)
|
||||
$this->INTERNAL_ERROR("Should not have a customer lease credit.");
|
||||
|
||||
/* if ($outstanding_balance < 0) */
|
||||
/* $this->sidemenu_links[] = */
|
||||
/* array('name' => 'Issue Refund', */
|
||||
/* 'url' => array('action' => 'refund', $id)); */
|
||||
|
||||
if (isset($lease['Lease']['moveout_date']) && $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'));
|
||||
}
|
||||
}
|
||||
217
controllers/ledger_entries_controller.php
Normal file
217
controllers/ledger_entries_controller.php
Normal file
@@ -0,0 +1,217 @@
|
||||
<?php
|
||||
|
||||
class LedgerEntriesController 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 / current / past / all
|
||||
* - Creates a list of ledger entries
|
||||
*/
|
||||
|
||||
function index() { $this->gridView('All Ledger Entries'); }
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* virtuals: gridData
|
||||
* - With the application controller handling the gridData action,
|
||||
* these virtual functions ensure that the correct data is passed
|
||||
* to jqGrid.
|
||||
*/
|
||||
|
||||
function gridDataTables(&$params, &$model) {
|
||||
$link =
|
||||
array(// Models
|
||||
'Transaction' =>
|
||||
array('fields' => array('id', 'stamp'),
|
||||
),
|
||||
|
||||
'Ledger' =>
|
||||
array('fields' => array('id', 'sequence'),
|
||||
'Account' =>
|
||||
array('fields' => array('id', 'name', 'type'),
|
||||
),
|
||||
),
|
||||
|
||||
'Tender' =>
|
||||
array('fields' => array('id', 'name', 'nsf_transaction_id'),
|
||||
),
|
||||
|
||||
/* 'DebitEntry', */
|
||||
/* 'CreditEntry', */
|
||||
);
|
||||
|
||||
return array('link' => $link);
|
||||
}
|
||||
|
||||
function gridDataFields(&$params, &$model) {
|
||||
$fields = parent::gridDataFields($params, $model);
|
||||
return array_merge($fields,
|
||||
$this->LedgerEntry->debitCreditFields());
|
||||
}
|
||||
|
||||
function gridDataFilterTablesTable(&$params, &$model, $table) {
|
||||
$table = $this->gridDataFilterTableName($params, $model, $table);
|
||||
// Account is already part of our standard table set.
|
||||
// Ensure we don't add it in again as part of filtering.
|
||||
if ($table == 'Account')
|
||||
return null;
|
||||
|
||||
// Customer needs to be added beneath Transaction
|
||||
if ($table == 'Customer')
|
||||
return 'Transaction';
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
function gridDataFilterTablesConfig(&$params, &$model, $table) {
|
||||
$config = parent::gridDataFilterTablesConfig($params, $model, $table);
|
||||
|
||||
// Customer is special in that its linked in by Transaction
|
||||
// Therefore, the actual table used for the join is 'Transaction',
|
||||
// not 'Customer', and so we need to specify Customer here.
|
||||
if ($table == 'Customer')
|
||||
$config = array('Customer' => $config);
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
function gridDataFilterConditionsStatement(&$params, &$model, $table, $key, $value) {
|
||||
//pr(compact('table', 'key', 'value'));
|
||||
if ($table == 'Account' && $value['value_present'] && $value['value'] === '-AR-')
|
||||
$value = $this->LedgerEntry->Ledger->Account->accountReceivableAccountID();
|
||||
return parent::gridDataFilterConditionsStatement($params, $model, $table, $key, $value);
|
||||
}
|
||||
|
||||
|
||||
function gridDataOrder(&$params, &$model, $index, $direction) {
|
||||
/* if ($index === 'balance') */
|
||||
/* return ($index .' '. $direction); */
|
||||
$order = parent::gridDataOrder($params, $model, $index, $direction);
|
||||
|
||||
if ($index === 'Transaction.stamp') {
|
||||
$order[] = 'LedgerEntry.id ' . $direction;
|
||||
}
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
function gridDataPostProcessCalculatedFields(&$params, &$model, &$records) {
|
||||
parent::gridDataPostProcessCalculatedFields($params, $model, $records);
|
||||
foreach ($records AS &$record) {
|
||||
// REVISIT <AP>: 20090730
|
||||
// We really need the grid to handle this. We probably need to
|
||||
// either create a hidden column with the nsf id, or pass back
|
||||
// a list of nsf items as user data. We can then add an onload
|
||||
// function to sweep through the nsf items and format them.
|
||||
// For now... this works.
|
||||
if (!empty($record['Tender']['nsf_transaction_id']))
|
||||
$record['Tender']['name'] =
|
||||
'<SPAN class="nsf-tender">' . $record['Tender']['name'] . '</SPAN>';
|
||||
}
|
||||
}
|
||||
|
||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||
$links['LedgerEntry'] = array('id');
|
||||
$links['Transaction'] = array('id');
|
||||
$links['Ledger'] = array('id');
|
||||
$links['Account'] = array('controller' => 'accounts', 'name');
|
||||
$links['Tender'] = array('name');
|
||||
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: view
|
||||
* - Displays information about a specific entry
|
||||
*/
|
||||
|
||||
function view($id = null) {
|
||||
$entry = $this->LedgerEntry->find
|
||||
('first',
|
||||
array('contain' => array
|
||||
(
|
||||
'Transaction' =>
|
||||
array('fields' => array('id', 'stamp'),
|
||||
),
|
||||
|
||||
'Ledger' =>
|
||||
array('fields' => array('id', 'sequence', 'name'),
|
||||
'Account' =>
|
||||
array('fields' => array('id', 'name', 'type'),
|
||||
'conditions' =>
|
||||
// REVISIT <AP>: 20090811
|
||||
// No security issues have been worked out yet
|
||||
array('Account.level >=' => 5),
|
||||
),
|
||||
),
|
||||
|
||||
'Tender' =>
|
||||
array('fields' => array('id', 'name'),
|
||||
),
|
||||
|
||||
'DebitDoubleEntry' => array('id'),
|
||||
'CreditDoubleEntry' => array('id'),
|
||||
|
||||
'DebitEntry' => array('fields' => array('id', 'crdr')),
|
||||
'CreditEntry' => array('fields' => array('id', 'crdr')),
|
||||
),
|
||||
|
||||
'conditions' => array('LedgerEntry.id' => $id),
|
||||
));
|
||||
|
||||
if (empty($entry) || empty($entry['Ledger']['Account'])) {
|
||||
$this->Session->setFlash(__('Invalid Item.', true));
|
||||
$this->redirect(array('controller' => 'accounts', 'action'=>'index'));
|
||||
}
|
||||
|
||||
if (!empty($entry['DebitEntry']) && !empty($entry['CreditEntry']))
|
||||
die("LedgerEntry has both a matching DebitEntry and CreditEntry");
|
||||
if (empty($entry['DebitEntry']) && empty($entry['CreditEntry']))
|
||||
die("LedgerEntry has neither a matching DebitEntry nor a CreditEntry");
|
||||
if (empty($entry['DebitEntry']) && count($entry['CreditEntry']) != 1)
|
||||
die("LedgerEntry has more than one CreditEntry");
|
||||
if (empty($entry['CreditEntry']) && count($entry['DebitEntry']) != 1)
|
||||
die("LedgerEntry has more than one DebitEntry");
|
||||
|
||||
if (empty($entry['DebitEntry']))
|
||||
$entry['MatchingEntry'] = $entry['CreditEntry'][0];
|
||||
else
|
||||
$entry['MatchingEntry'] = $entry['DebitEntry'][0];
|
||||
|
||||
if (empty($entry['DebitDoubleEntry']['id']))
|
||||
$entry['DoubleEntry'] = $entry['CreditDoubleEntry'];
|
||||
else
|
||||
$entry['DoubleEntry'] = $entry['DebitDoubleEntry'];
|
||||
|
||||
// REVISIT <AP>: 20090816
|
||||
// This page doesn't seem very useful, let's just keep it
|
||||
// all to the double entry view.
|
||||
$this->redirect(array('controller' => 'double_entries',
|
||||
'action' => 'view',
|
||||
$entry['DoubleEntry']['id']));
|
||||
|
||||
// Prepare to render.
|
||||
$title = "Ledger Entry #{$entry['LedgerEntry']['id']}";
|
||||
$this->set(compact('entry', 'title'));
|
||||
}
|
||||
|
||||
}
|
||||
149
controllers/ledgers_controller.php
Normal file
149
controllers/ledgers_controller.php
Normal file
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
class LedgersController extends AppController {
|
||||
|
||||
var $sidemenu_links =
|
||||
array(array('name' => 'Ledgers', 'header' => true),
|
||||
array('name' => 'Current', 'url' => array('controller' => 'ledgers', 'action' => 'current')),
|
||||
array('name' => 'Closed', 'url' => array('controller' => 'ledgers', 'action' => 'closed')),
|
||||
array('name' => 'All', 'url' => array('controller' => 'ledgers', 'action' => 'all')),
|
||||
);
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* override: sideMenuLinks
|
||||
* - Generates controller specific links for the side menu
|
||||
*/
|
||||
function sideMenuLinks() {
|
||||
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: index / current / closed / all
|
||||
* - Generate a list of ledgers
|
||||
*/
|
||||
|
||||
function index() { $this->all(); }
|
||||
function current() { $this->gridView('Current Ledgers'); }
|
||||
function closed() { $this->gridView('Closed Ledgers'); }
|
||||
function all() { $this->gridView('All Ledgers', 'all'); }
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* virtuals: gridData
|
||||
* - With the application controller handling the gridData action,
|
||||
* these virtual functions ensure that the correct data is passed
|
||||
* to jqGrid.
|
||||
*/
|
||||
|
||||
function gridDataSetup(&$params) {
|
||||
parent::gridDataSetup($params);
|
||||
if (!isset($params['action']))
|
||||
$params['action'] = 'all';
|
||||
}
|
||||
|
||||
function gridDataCountTables(&$params, &$model) {
|
||||
return array
|
||||
('link' =>
|
||||
array(// Models
|
||||
'Account',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function gridDataTables(&$params, &$model) {
|
||||
$tables = $this->gridDataCountTables($params, $model);
|
||||
$tables['link'][] = 'LedgerEntry';
|
||||
$tables['link'][] = 'CloseTransaction';
|
||||
return $tables;
|
||||
}
|
||||
|
||||
function gridDataFields(&$params, &$model) {
|
||||
$fields = parent::gridDataFields($params, $model);
|
||||
$fields[] = 'CONCAT(Account.id, "-", Ledger.sequence) AS id_sequence';
|
||||
return array_merge($fields,
|
||||
$this->Ledger->LedgerEntry->debitCreditFields(true));
|
||||
}
|
||||
|
||||
function gridDataConditions(&$params, &$model) {
|
||||
$conditions = parent::gridDataConditions($params, $model);
|
||||
|
||||
if ($params['action'] === 'current') {
|
||||
$conditions[] = array('Ledger.close_transaction_id' => null);
|
||||
}
|
||||
elseif ($params['action'] === 'closed') {
|
||||
$conditions[] = array('Ledger.close_transaction_id !=' => null);
|
||||
}
|
||||
|
||||
// REVISIT <AP>: 20090811
|
||||
// No security issues have been worked out yet
|
||||
$conditions[] = array('Account.level >=' => 10);
|
||||
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
function gridDataOrder(&$params, &$model, $index, $direction) {
|
||||
$id_sequence = false;
|
||||
if ($index === 'id_sequence') {
|
||||
$id_sequence = true;
|
||||
$index = 'Ledger.account_id';
|
||||
}
|
||||
|
||||
$order = parent::gridDataOrder($params, $model, $index, $direction);
|
||||
|
||||
if ($id_sequence) {
|
||||
$order[] = 'Ledger.sequence ' . $direction;
|
||||
}
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||
$links['Ledger'] = array('id_sequence');
|
||||
$links['Account'] = array('name');
|
||||
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: view
|
||||
* - Displays information about a specific ledger
|
||||
*/
|
||||
|
||||
function view($id = null) {
|
||||
$ledger = $this->Ledger->find
|
||||
('first',
|
||||
array('contain' =>
|
||||
array(// Models
|
||||
'Account',
|
||||
),
|
||||
'conditions' => array(array('Ledger.id' => $id),
|
||||
// REVISIT <AP>: 20090811
|
||||
// No security issues have been worked out yet
|
||||
array('Account.level >=' => 10),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
if (empty($ledger)) {
|
||||
$this->Session->setFlash(__('Invalid Item.', true));
|
||||
$this->redirect(array('action'=>'index'));
|
||||
}
|
||||
|
||||
// Get ledger stats for our summary box
|
||||
$stats = $this->Ledger->stats($id);
|
||||
|
||||
// OK, set our view variables and render!
|
||||
$title = 'Ledger: #' . $ledger['Account']['id'] .'-'. $ledger['Ledger']['sequence'];
|
||||
$this->set(compact('ledger', 'title', 'stats'));
|
||||
}
|
||||
}
|
||||
306
controllers/maps_controller.php
Normal file
306
controllers/maps_controller.php
Normal file
@@ -0,0 +1,306 @@
|
||||
<?php
|
||||
|
||||
class MapsController extends AppController {
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: index / all
|
||||
* - Generate a listing of maps
|
||||
*
|
||||
* REVISIT <AP> 20090528:
|
||||
* We'll need to present only those site area maps that correspond
|
||||
* to the users particular site.
|
||||
*/
|
||||
|
||||
function index() { $this->all(); }
|
||||
function all() { $this->gridView('All Maps', 'all'); }
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* virtuals: gridData
|
||||
* - With the application controller handling the gridData action,
|
||||
* these virtual functions ensure that the correct data is passed
|
||||
* to jqGrid.
|
||||
*/
|
||||
|
||||
function gridDataTables(&$params, &$model) {
|
||||
return array
|
||||
('link' => array('SiteArea' => array('fields' => array('SiteArea.id', 'SiteArea.name')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||
$links['Map'] = array('id');
|
||||
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: view
|
||||
* - Generates a site map page
|
||||
*/
|
||||
|
||||
function view($id = null, $requested_width = 800) {
|
||||
if (!$id) {
|
||||
$this->Session->setFlash(__('Invalid Item.', true));
|
||||
$this->redirect(array('action'=>'index'));
|
||||
}
|
||||
$this->set('info', $this->mapInfo($id, $requested_width));
|
||||
$this->set('title', "Site Map");
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: map
|
||||
* - Produces a PNG site map image
|
||||
*/
|
||||
|
||||
function map($id = null, $requested_width = 800) {
|
||||
if (!$id) {
|
||||
$this->Session->setFlash(__('Invalid Item.', true));
|
||||
$this->redirect(array('action'=>'index'));
|
||||
}
|
||||
$this->image($this->mapInfo($id, $requested_width));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* mapInfo
|
||||
*/
|
||||
|
||||
function mapInfo($id, $requested_width) {
|
||||
// Set up array to hold the map information
|
||||
$info = array('map_id' => $id,
|
||||
'border' => true,
|
||||
'units' => array());
|
||||
|
||||
// Find all of the map/unit information from this SiteArea
|
||||
$map = $this->Map->find('first', array('contain' => false,
|
||||
'conditions' => array('id' => $id)));
|
||||
|
||||
$units = $this->Map->Unit->find
|
||||
('all',
|
||||
array('link' =>
|
||||
array('Map' =>
|
||||
array('fields' => array()),
|
||||
|
||||
'CurrentLease' =>
|
||||
array('fields' => array('id', 'paid_through_date',
|
||||
$this->Map->Unit->CurrentLease->
|
||||
delinquentField('CurrentLease')),
|
||||
'Customer'),
|
||||
|
||||
'UnitSize' =>
|
||||
array('fields' => array('id', 'depth', 'width',
|
||||
'MapsUnit.pt_top',
|
||||
'MapsUnit.pt_left',
|
||||
'MapsUnit.transpose')),
|
||||
),
|
||||
'fields' => array('id', 'name', 'status'),
|
||||
'conditions' => array('Map.id' => $id),
|
||||
));
|
||||
|
||||
/* pr(compact('map', 'units')); */
|
||||
/* $this->render('/empty'); */
|
||||
/* return; */
|
||||
|
||||
/*****
|
||||
* The preference would be to leave all things "screen" related
|
||||
* to reside in the view. However, two separate views need this
|
||||
* information. The 'view' needs it to include a clickable map
|
||||
* that corresponds to the map image, and of course, the 'map'
|
||||
* (or 'image') view needs it to render the image. So, in the
|
||||
* controller for now, unless I come up with a better idea.
|
||||
*****/
|
||||
|
||||
// Get the overall site limits, and then compute the
|
||||
// actual boundary extents, adjusting for a border
|
||||
$boundary_adjustment = 12;
|
||||
$bottom = 2*$boundary_adjustment + $map['Map']['depth'];
|
||||
$right = 2*$boundary_adjustment + $map['Map']['width'];
|
||||
|
||||
// Scale things according to desired display width
|
||||
$screen_adjustment_factor = $requested_width / $right;
|
||||
|
||||
// Define the overall canvas size
|
||||
$info['width'] = $right * $screen_adjustment_factor;
|
||||
$info['depth'] = $bottom * $screen_adjustment_factor;
|
||||
|
||||
// Go through each unit in the map, calculating the map location
|
||||
foreach ($units AS $unit) {
|
||||
$lft = $unit['MapsUnit']['pt_left'] + $boundary_adjustment;
|
||||
$top = $unit['MapsUnit']['pt_top'] + $boundary_adjustment;
|
||||
|
||||
$width =
|
||||
$unit['MapsUnit']['transpose']
|
||||
? $unit['UnitSize']['depth']
|
||||
: $unit['UnitSize']['width'];
|
||||
|
||||
$depth =
|
||||
$unit['MapsUnit']['transpose']
|
||||
? $unit['UnitSize']['width']
|
||||
: $unit['UnitSize']['depth'];
|
||||
|
||||
$lft *= $screen_adjustment_factor;
|
||||
$top *= $screen_adjustment_factor;
|
||||
$width *= $screen_adjustment_factor;
|
||||
$depth *= $screen_adjustment_factor;
|
||||
|
||||
$info['units'][] =
|
||||
array( 'id' => $unit['Unit']['id'],
|
||||
'name' => $unit['Unit']['name'],
|
||||
'left' => $lft,
|
||||
'right' => $lft + $width,
|
||||
'top' => $top,
|
||||
'bottom' => $top + $depth,
|
||||
'width' => $width,
|
||||
'depth' => $depth,
|
||||
'n-s' => $unit['MapsUnit']['transpose'] ? 0 : 1,
|
||||
'status' => (($unit['Unit']['status'] === 'OCCUPIED' &&
|
||||
!empty($unit[0]['delinquent']))
|
||||
? 'LATE' : $unit['Unit']['status']),
|
||||
'data' => $unit,
|
||||
);
|
||||
}
|
||||
|
||||
/* pr($info); */
|
||||
/* $this->render('/empty'); exit(); */
|
||||
return $info;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: legend
|
||||
* - Produces a PNG color legend image
|
||||
*/
|
||||
|
||||
function legend($id = null, $requested_width = 400) {
|
||||
$status = array_keys($this->Map->Unit->activeStatusEnums());
|
||||
$occupied_key = array_search('OCCUPIED', $status);
|
||||
array_splice($status, $occupied_key+1, 0, array('LATE'));
|
||||
|
||||
$rows = 2;
|
||||
$cols = (int)((count($status) + $rows - 1) / $rows);
|
||||
|
||||
$info = array('units' => array());
|
||||
|
||||
// Get the overall site limits, and then compute the
|
||||
// actual boundary extents, adjusting for a border
|
||||
$boundary_adjustment = 1;
|
||||
$item_width = 40; // Absolute values are irrelevant, as they
|
||||
$item_depth = 10; // will be scaled in the end anyway.
|
||||
$bottom = 2*$boundary_adjustment + $rows*$item_depth;
|
||||
$right = 2*$boundary_adjustment + $cols*$item_width;
|
||||
|
||||
// Scale things according to desired display width
|
||||
$screen_adjustment_factor = $requested_width / $right;
|
||||
|
||||
// Define the overall canvas size
|
||||
$info['width'] = $right * $screen_adjustment_factor;
|
||||
$info['depth'] = $bottom * $screen_adjustment_factor;
|
||||
|
||||
// Get a starting point for our top left position.
|
||||
$top = $lft = $boundary_adjustment;
|
||||
|
||||
// Scale it appropriately.
|
||||
$top *= $screen_adjustment_factor;
|
||||
$lft *= $screen_adjustment_factor;
|
||||
$item_width *= $screen_adjustment_factor;
|
||||
$item_depth *= $screen_adjustment_factor;
|
||||
|
||||
foreach ($status AS $code) {
|
||||
$info['units'][] = array('name' => $code,
|
||||
'status' => $code,
|
||||
'width' => $item_width,
|
||||
'depth' => $item_depth,
|
||||
'left' => $lft,
|
||||
'right' => $lft + $item_width,
|
||||
'top' => $top,
|
||||
'bottom' => $top + $item_depth);
|
||||
$top += $item_depth;
|
||||
if ($top >= $item_depth * $rows) {
|
||||
$top = $boundary_adjustment * $screen_adjustment_factor;
|
||||
$lft += $item_width;
|
||||
}
|
||||
}
|
||||
|
||||
$this->image($info, true);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* helper: image
|
||||
* - used by actions map & legend to set up unit information and
|
||||
* color palates before rendering the PNG image.
|
||||
*/
|
||||
|
||||
function image($info, $legend = false) {
|
||||
$debug = false;
|
||||
|
||||
if (!$debug) {
|
||||
$this->layout = null;
|
||||
$this->autoLayout = false;
|
||||
Configure::write('debug', '0');
|
||||
}
|
||||
|
||||
// Define our color palate
|
||||
// REVISIT <AP>: 20090513
|
||||
// Get colors from DB option tables
|
||||
$info['palate']['main']['layout']['bg'] = array('red' => 255, 'green' => 255, 'blue' => 255);
|
||||
$info['palate']['main']['layout']['border'] = array('red' => 192, 'green' => 192, 'blue' => 192);
|
||||
$info['palate']['main']['layout']['wall'] = array('red' => 0, 'green' => 0, 'blue' => 0);
|
||||
$info['palate']['unit']['DELETED']['bg'] = array('red' => 0, 'green' => 0, 'blue' => 0);
|
||||
$info['palate']['unit']['DAMAGED']['bg'] = array('red' => 192, 'green' => 128, 'blue' => 128);
|
||||
$info['palate']['unit']['COMPANY']['bg'] = array('red' => 128, 'green' => 192, 'blue' => 128);
|
||||
$info['palate']['unit']['UNAVAILABLE']['bg'] = array('red' => 128, 'green' => 128, 'blue' => 192);
|
||||
$info['palate']['unit']['RESERVED']['bg'] = array('red' => 192, 'green' => 192, 'blue' => 128);
|
||||
$info['palate']['unit']['DIRTY']['bg'] = array('red' => 128, 'green' => 192, 'blue' => 192);
|
||||
$info['palate']['unit']['VACANT']['bg'] = array('red' => 0, 'green' => 255, 'blue' => 128);
|
||||
$info['palate']['unit']['OCCUPIED']['bg'] = array('red' => 0, 'green' => 128, 'blue' => 255);
|
||||
$info['palate']['unit']['LATE']['bg'] = array('red' => 255, 'green' => 192, 'blue' => 192);
|
||||
$info['palate']['unit']['LOCKED']['bg'] = array('red' => 255, 'green' => 64, 'blue' => 64);
|
||||
$info['palate']['unit']['LIENED']['bg'] = array('red' => 255, 'green' => 0, 'blue' => 128);
|
||||
|
||||
// Determine text color to go with each background
|
||||
foreach ($info['palate']['unit'] AS &$code) {
|
||||
$component = $code['bg'];
|
||||
$method = 3;
|
||||
if ($method == 1) {
|
||||
foreach (array('red', 'green', 'blue') AS $prim)
|
||||
$component[$prim] = 255 - $component[$prim];
|
||||
} elseif ($method == 2) {
|
||||
foreach (array('red', 'green', 'blue') AS $prim)
|
||||
$component[$prim] = ($component[$prim]) >= 128 ? 0 : 255;
|
||||
} elseif ($method == 3) {
|
||||
$val = (sqrt(pow($component['red'], 2) +
|
||||
pow($component['green'], 2) +
|
||||
pow($component['blue'], 2)) >= sqrt(3) * 128) ? 0 : 255;
|
||||
foreach (array('red', 'green', 'blue') AS $prim)
|
||||
$component[$prim] = $val;
|
||||
}
|
||||
|
||||
$code['fg'] = $component;
|
||||
}
|
||||
|
||||
$this->set(compact('info', 'debug'));
|
||||
$this->render('image');
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
321
controllers/statement_entries_controller.php
Normal file
321
controllers/statement_entries_controller.php
Normal file
@@ -0,0 +1,321 @@
|
||||
<?php
|
||||
|
||||
class StatementEntriesController 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 / current / past / all
|
||||
* - Creates a list of statement entries
|
||||
*/
|
||||
|
||||
function index() { $this->gridView('All Statement Entries'); }
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* virtuals: gridData
|
||||
* - With the application controller handling the gridData action,
|
||||
* these virtual functions ensure that the correct data is passed
|
||||
* to jqGrid.
|
||||
*/
|
||||
|
||||
function gridDataCountTables(&$params, &$model) {
|
||||
$link =
|
||||
array(// Models
|
||||
'Transaction' =>
|
||||
array('fields' => array('id', 'stamp'),
|
||||
),
|
||||
|
||||
'Customer' =>
|
||||
array('fields' => array('id', 'name'),
|
||||
),
|
||||
|
||||
'Lease' =>
|
||||
array('fields' => array('id', 'number'),
|
||||
'Unit' =>
|
||||
array('fields' => array('id', 'name'),
|
||||
),
|
||||
),
|
||||
|
||||
'Account' =>
|
||||
array('fields' => array('id', 'name', 'type'),
|
||||
),
|
||||
);
|
||||
|
||||
if (!empty($params['post']['custom']['statement_entry_id'])) {
|
||||
$link['ChargeEntry'] = array();
|
||||
$link['DisbursementEntry'] = array();
|
||||
}
|
||||
|
||||
return array('link' => $link);
|
||||
}
|
||||
|
||||
function gridDataTables(&$params, &$model) {
|
||||
$tables = $this->gridDataCountTables($params, $model);
|
||||
|
||||
if (in_array('applied', $params['post']['fields'])) {
|
||||
$tables['link'] +=
|
||||
array('ChargeEntry' => array(),
|
||||
'DisbursementEntry' => array());
|
||||
}
|
||||
|
||||
return $tables;
|
||||
}
|
||||
|
||||
function gridDataFields(&$params, &$model) {
|
||||
$fields = parent::gridDataFields($params, $model);
|
||||
|
||||
if (in_array('applied', $params['post']['fields'])) {
|
||||
$fields[] = ("IF(StatementEntry.type = 'CHARGE'," .
|
||||
" SUM(COALESCE(DisbursementEntry.amount,0))," .
|
||||
" SUM(COALESCE(ChargeEntry.amount,0)))" .
|
||||
" AS 'applied'");
|
||||
}
|
||||
if (in_array('unapplied', $params['post']['fields'])) {
|
||||
$fields[] = ("StatementEntry.amount - (" .
|
||||
"IF(StatementEntry.type = 'CHARGE'," .
|
||||
" SUM(COALESCE(DisbursementEntry.amount,0))," .
|
||||
" SUM(COALESCE(ChargeEntry.amount,0)))" .
|
||||
") AS 'unapplied'");
|
||||
}
|
||||
|
||||
$fields = array_merge($fields,
|
||||
$this->StatementEntry->chargeDisbursementFields());
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
function gridDataConditions(&$params, &$model) {
|
||||
$conditions = parent::gridDataConditions($params, $model);
|
||||
extract($params['post']['custom']);
|
||||
|
||||
if (!empty($from_date))
|
||||
$conditions[]
|
||||
= array('Transaction.stamp >=' =>
|
||||
$this->StatementEntry->Transaction->dateFormatBeforeSave($from_date));
|
||||
|
||||
if (!empty($through_date))
|
||||
$conditions[]
|
||||
= array('Transaction.stamp <=' =>
|
||||
$this->StatementEntry->Transaction->dateFormatBeforeSave($through_date . ' 23:59:59'));
|
||||
|
||||
if (isset($account_id))
|
||||
$conditions[] = array('StatementEntry.account_id' => $account_id);
|
||||
|
||||
if (isset($customer_id))
|
||||
$conditions[] = array('StatementEntry.customer_id' => $customer_id);
|
||||
|
||||
if (isset($statement_entry_id)) {
|
||||
$conditions[] = array('OR' =>
|
||||
array(array('ChargeEntry.id' => $statement_entry_id),
|
||||
array('DisbursementEntry.id' => $statement_entry_id)));
|
||||
}
|
||||
|
||||
if ($params['action'] === 'unreconciled') {
|
||||
$query = array('conditions' => $conditions);
|
||||
$set = $this->StatementEntry->reconciledSet('CHARGE', $query, true);
|
||||
|
||||
$entries = array();
|
||||
foreach ($set['entries'] AS $entry)
|
||||
$entries[] = $entry['StatementEntry']['id'];
|
||||
|
||||
$conditions[] = array('StatementEntry.id' => $entries);
|
||||
$params['userdata']['balance'] = $set['summary']['balance'];
|
||||
}
|
||||
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||
$links['StatementEntry'] = array('id');
|
||||
$links['Transaction'] = array('id');
|
||||
$links['Account'] = array('name');
|
||||
$links['Customer'] = array('name');
|
||||
$links['Lease'] = array('number');
|
||||
$links['Unit'] = array('name');
|
||||
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||
}
|
||||
|
||||
function gridDataOrder(&$params, &$model, $index, $direction) {
|
||||
$order = parent::gridDataOrder($params, $model, $index, $direction);
|
||||
|
||||
// After sorting by whatever the user wants, add these
|
||||
// defaults into the sort mechanism. If we're already
|
||||
// sorting by one of them, it will only be redundant,
|
||||
// and should cause no harm (possible a longer query?)
|
||||
$order[] = 'Transaction.stamp ' . $direction;
|
||||
$order[] = 'StatementEntry.effective_date ' . $direction;
|
||||
$order[] = 'StatementEntry.id ' . $direction;
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
function gridDataRecordsExecute(&$params, &$model, $query) {
|
||||
/* if ($params['action'] === '???') { */
|
||||
/* $tquery = array_diff_key($query, array('fields'=>1,'group'=>1,'limit'=>1,'order'=>1)); */
|
||||
/* $tquery['fields'] = array("IF(StatementEntry.type = 'CHARGE'," . */
|
||||
/* " SUM(COALESCE(DisbursementEntry.amount,0))," . */
|
||||
/* " SUM(COALESCE(ChargeEntry.amount,0)))" . */
|
||||
/* " AS 'applied'", */
|
||||
|
||||
/* "StatementEntry.amount - (" . */
|
||||
/* "IF(StatementEntry.type = 'CHARGE'," . */
|
||||
/* " SUM(COALESCE(DisbursementEntry.amount,0))," . */
|
||||
/* " SUM(COALESCE(ChargeEntry.amount,0)))" . */
|
||||
/* ") AS 'balance'", */
|
||||
/* ); */
|
||||
|
||||
/* //pr(compact('tquery')); */
|
||||
/* $total = $model->find('first', $tquery); */
|
||||
/* $params['userdata']['total'] = $total[0]['applied']; */
|
||||
/* $params['userdata']['balance'] = $total[0]['balance']; */
|
||||
/* } */
|
||||
if ($params['action'] === 'collected') {
|
||||
$tquery = array_diff_key($query, array('fields'=>1,'group'=>1,'limit'=>1,'order'=>1));
|
||||
$tquery['fields'] = array("SUM(COALESCE(StatementEntry.amount,0)) AS 'total'");
|
||||
$total = $model->find('first', $tquery);
|
||||
$params['userdata']['total'] = $total[0]['total'];
|
||||
}
|
||||
|
||||
return parent::gridDataRecordsExecute($params, $model, $query);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: reverse the ledger entry
|
||||
*/
|
||||
|
||||
function reverse($id = null) {
|
||||
if ($this->data) {
|
||||
//pr($this->data); die();
|
||||
|
||||
$this->StatementEntry->reverse
|
||||
($this->data['StatementEntry']['id'],
|
||||
$this->data['Transaction']['stamp'],
|
||||
$this->data['Transaction']['comment']);
|
||||
|
||||
$this->redirect(array('action'=>'view',
|
||||
$this->data['StatementEntry']['id']));
|
||||
$this->INTERNAL_ERROR('SHOULD HAVE REDIRECTED');
|
||||
}
|
||||
|
||||
$this->StatementEntry->id = $id;
|
||||
$entry = $this->StatementEntry->find
|
||||
('first', array
|
||||
('contain' => array('Customer', 'Transaction', 'Account'),
|
||||
));
|
||||
|
||||
if (empty($entry)) {
|
||||
$this->Session->setFlash(__('Invalid Item.', true));
|
||||
$this->redirect(array('controller' => 'customers',
|
||||
'action'=>'index'));
|
||||
}
|
||||
|
||||
if (!$this->StatementEntry->reversable($id)) {
|
||||
$this->Session->setFlash(__('Item not reversable.', true));
|
||||
$this->redirect(array('action'=>'view', $id));
|
||||
}
|
||||
|
||||
// Prepare to render.
|
||||
$title = ("Charge #{$entry['StatementEntry']['id']}" .
|
||||
" : {$entry['StatementEntry']['amount']}" .
|
||||
" : Reverse");
|
||||
$this->set(compact('entry', 'title'));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: waive the ledger entry
|
||||
*/
|
||||
|
||||
function waive($id) {
|
||||
$this->StatementEntry->waive($id);
|
||||
$this->redirect(array('action'=>'view', $id));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: view
|
||||
* - Displays information about a specific entry
|
||||
*/
|
||||
|
||||
function view($id = null) {
|
||||
$entry = $this->StatementEntry->find
|
||||
('first',
|
||||
array('contain' => array
|
||||
('Transaction' => array('fields' => array('id', 'type', 'stamp')),
|
||||
'Account' => array('id', 'name', 'type'),
|
||||
'Customer' => array('fields' => array('id', 'name')),
|
||||
'Lease' => array('fields' => array('id')),
|
||||
),
|
||||
|
||||
'conditions' => array(array('StatementEntry.id' => $id),
|
||||
// REVISIT <AP>: 20090811
|
||||
// No security issues have been worked out yet
|
||||
array('Account.level >=' => 5)
|
||||
),
|
||||
));
|
||||
|
||||
if (empty($entry)) {
|
||||
$this->Session->setFlash(__('Invalid Item.', true));
|
||||
$this->redirect(array('controller' => 'accounts', 'action'=>'index'));
|
||||
}
|
||||
|
||||
$stats = $this->StatementEntry->stats($id);
|
||||
|
||||
if (in_array(strtoupper($entry['StatementEntry']['type']), $this->StatementEntry->debitTypes()))
|
||||
$stats = $stats['Charge'];
|
||||
else
|
||||
$stats = $stats['Disbursement'];
|
||||
|
||||
|
||||
if (strtoupper($entry['StatementEntry']['type']) === 'CHARGE') {
|
||||
|
||||
$reversable = $this->StatementEntry->reversable($id);
|
||||
|
||||
// Set up dynamic menu items
|
||||
if ($reversable || $stats['balance'] > 0)
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'Operations', 'header' => true);
|
||||
|
||||
if ($reversable)
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'Reverse',
|
||||
'url' => array('action' => 'reverse',
|
||||
$id));
|
||||
|
||||
if ($stats['balance'] > 0)
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'Waive Balance',
|
||||
'url' => array('action' => 'waive',
|
||||
$id));
|
||||
}
|
||||
|
||||
// Prepare to render.
|
||||
$title = "Statement Entry #{$entry['StatementEntry']['id']}";
|
||||
$this->set(compact('entry', 'title', 'stats'));
|
||||
}
|
||||
|
||||
}
|
||||
258
controllers/tenders_controller.php
Normal file
258
controllers/tenders_controller.php
Normal file
@@ -0,0 +1,258 @@
|
||||
<?php
|
||||
|
||||
class TendersController 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 Tenders
|
||||
*/
|
||||
|
||||
function index() { $this->all(); }
|
||||
function all() { $this->gridView('All Legal Tender', 'all'); }
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* virtuals: gridData
|
||||
* - With the application controller handling the gridData action,
|
||||
* these virtual functions ensure that the correct data is passed
|
||||
* to jqGrid.
|
||||
*/
|
||||
|
||||
function gridDataTables(&$params, &$model) {
|
||||
return array
|
||||
('link' =>
|
||||
array('TenderType',
|
||||
'Customer',
|
||||
'LedgerEntry' =>
|
||||
array('Transaction',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function gridDataRecordsExecute(&$params, &$model, $query) {
|
||||
$tquery = array_diff_key($query, array('fields'=>1,'group'=>1,'limit'=>1,'order'=>1));
|
||||
$tquery['fields'] = array("SUM(COALESCE(LedgerEntry.amount,0)) AS 'total'");
|
||||
$total = $model->find('first', $tquery);
|
||||
$params['userdata']['total'] = $total[0]['total'];
|
||||
|
||||
return parent::gridDataRecordsExecute($params, $model, $query);
|
||||
}
|
||||
|
||||
function gridDataPostProcessCalculatedFields(&$params, &$model, &$records) {
|
||||
parent::gridDataPostProcessCalculatedFields($params, $model, $records);
|
||||
foreach ($records AS &$record) {
|
||||
// REVISIT <AP>: 20090730
|
||||
// We really need the grid to handle this. We probably need to
|
||||
// either create a hidden column with the nsf id, or pass back
|
||||
// a list of nsf items as user data. We can then add an onload
|
||||
// function to sweep through the nsf items and format them.
|
||||
// For now... this works.
|
||||
if (!empty($record['Tender']['nsf_transaction_id']))
|
||||
$record['Tender']['name'] =
|
||||
'<SPAN class="nsf-tender">' . $record['Tender']['name'] . '</SPAN>';
|
||||
}
|
||||
}
|
||||
|
||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||
$links['Tender'] = array('name', 'id');
|
||||
$links['Customer'] = array('name');
|
||||
$links['TenderType'] = array('name');
|
||||
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: deposit
|
||||
* - Prepares the books for a bank deposit
|
||||
*/
|
||||
|
||||
function deposit() {
|
||||
// Prepare a close page...
|
||||
$deposit_types = $this->Tender->TenderType->depositTypes(
|
||||
// Testing... limit to only one type
|
||||
//array('limit' => 1)
|
||||
);
|
||||
$deposit_accounts = $this->Tender->TenderType->Account->depositAccounts();
|
||||
|
||||
foreach ($deposit_types AS $type_id => &$type)
|
||||
$type = array('id' => $type_id,
|
||||
'name' => $type,
|
||||
'stats' => $this->Tender->TenderType->stats($type_id));
|
||||
|
||||
//pr(compact('deposit_types', 'deposit_accounts'));
|
||||
|
||||
$title = 'Prepare Deposit';
|
||||
$this->set(compact('title', 'deposit_types', 'deposit_accounts'));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: nsf
|
||||
* - Marks a tender as having insufficient funds.
|
||||
*/
|
||||
|
||||
function nsf($id = null) {
|
||||
if ($this->data) {
|
||||
$result = $this->Tender->nsf
|
||||
($this->data['Tender']['id'],
|
||||
$this->data['Transaction']['stamp'],
|
||||
$this->data['Transaction']['comment']);
|
||||
$this->redirect(array('controller' => 'tenders',
|
||||
'action' => 'view',
|
||||
$this->data['Tender']['id']));
|
||||
}
|
||||
|
||||
if (!$id) {
|
||||
$this->Session->setFlash(__('Invalid Item.', true));
|
||||
$this->redirect(array('action'=>'index'));
|
||||
}
|
||||
|
||||
$this->Tender->id = $id;
|
||||
$tender = $this->Tender->find
|
||||
('first', array
|
||||
('contain' => array('Customer', 'LedgerEntry' => array('Transaction')),
|
||||
));
|
||||
|
||||
// Prepare to render.
|
||||
$title = "Tender #{$tender['Tender']['id']} : {$tender['Tender']['name']} : NSF";
|
||||
$this->set(compact('tender', 'title'));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: view
|
||||
* - Displays information about a specific entry
|
||||
*/
|
||||
|
||||
function view($id = null) {
|
||||
if (!$id) {
|
||||
$this->Session->setFlash(__('Invalid Item.', true));
|
||||
$this->redirect(array('controller' => 'accounts', 'action'=>'index'));
|
||||
}
|
||||
|
||||
// Get the Tender and related fields
|
||||
$this->Tender->id = $id;
|
||||
$tender = $this->Tender->find
|
||||
('first', array
|
||||
('contain' => array('TenderType', 'Customer', 'LedgerEntry' => array('Transaction')),
|
||||
));
|
||||
|
||||
|
||||
// Set up dynamic menu items
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'Operations', 'header' => true);
|
||||
|
||||
// Watch out for the special "Closing" entries
|
||||
if (!empty($tender['TenderType']['id']))
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'Edit',
|
||||
'url' => array('action' => 'edit',
|
||||
$id));
|
||||
|
||||
if (!empty($tender['Tender']['deposit_transaction_id'])
|
||||
&& empty($tender['Tender']['nsf_transaction_id'])
|
||||
// Hard to tell what types of items can come back as NSF.
|
||||
// For now, assume iff it is a named item, it can be NSF.
|
||||
// (or if we're in development mode)
|
||||
&& (!empty($tender['TenderType']['data1_name']) || !empty($this->params['dev']))
|
||||
) {
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'NSF',
|
||||
'url' => array('action' => 'nsf',
|
||||
$id));
|
||||
}
|
||||
|
||||
// Prepare to render.
|
||||
$title = "Tender #{$tender['Tender']['id']} : {$tender['Tender']['name']}";
|
||||
$this->set(compact('tender', 'title'));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: edit
|
||||
* - Edit tender information
|
||||
*/
|
||||
|
||||
function edit($id = null) {
|
||||
if (isset($this->data)) {
|
||||
// Check to see if the operation was cancelled.
|
||||
if (isset($this->params['form']['cancel'])) {
|
||||
if (empty($this->data['Tender']['id']))
|
||||
$this->redirect(array('action'=>'index'));
|
||||
|
||||
$this->redirect(array('action'=>'view', $this->data['Tender']['id']));
|
||||
}
|
||||
|
||||
// Make sure we have tender data
|
||||
if (empty($this->data['Tender']) || empty($this->data['Tender']['id']))
|
||||
$this->redirect(array('action'=>'index'));
|
||||
|
||||
// Figure out which tender type was chosen
|
||||
// REVISIT <AP>: 20090810; Not ready to change tender type
|
||||
// $tender_type_id = $this->data['Tender']['tender_type_id'];
|
||||
$tender_type_id = $this->Tender->field('tender_type_id');
|
||||
if (empty($tender_type_id))
|
||||
$this->redirect(array('action'=>'view', $this->data['Tender']['id']));
|
||||
|
||||
// Get data fields from the selected tender type
|
||||
$this->data['Tender'] += $this->data['type'][$tender_type_id];
|
||||
unset($this->data['type']);
|
||||
|
||||
// Save the tender and all associated data
|
||||
$this->Tender->create();
|
||||
$this->Tender->id = $this->data['Tender']['id'];
|
||||
if (!$this->Tender->save($this->data, false)) {
|
||||
$this->Session->setFlash("TENDER SAVE FAILED", true);
|
||||
pr("TENDER SAVE FAILED");
|
||||
}
|
||||
|
||||
$this->redirect(array('action'=>'view', $this->Tender->id));
|
||||
}
|
||||
|
||||
if ($id) {
|
||||
$this->data = $this->Tender->findById($id);
|
||||
} else {
|
||||
$this->redirect(array('action'=>'index'));
|
||||
}
|
||||
|
||||
$tender_types = $this->Tender->TenderType->find
|
||||
('list', array('order' => array('name')));
|
||||
$this->set(compact('tender_types'));
|
||||
|
||||
$types = $this->Tender->TenderType->find('all', array('contain' => false));
|
||||
$this->set(compact('types'));
|
||||
|
||||
// Prepare to render.
|
||||
$title = ('Tender #' . $this->data['Tender']['id'] .
|
||||
' : ' . $this->data['Tender']['name'] .
|
||||
" : Edit");
|
||||
$this->set(compact('title'));
|
||||
}
|
||||
}
|
||||
496
controllers/transactions_controller.php
Normal file
496
controllers/transactions_controller.php
Normal file
@@ -0,0 +1,496 @@
|
||||
<?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')),
|
||||
array('name' => 'Invoices', 'url' => array('controller' => 'transactions', 'action' => 'invoice')),
|
||||
array('name' => 'Receipts', 'url' => array('controller' => 'transactions', 'action' => 'receipt')),
|
||||
array('name' => 'Deposits', 'url' => array('controller' => 'transactions', 'action' => 'deposit')),
|
||||
);
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* 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->gridView('All Transactions', 'all'); }
|
||||
function invoice() { $this->gridView('Invoices'); }
|
||||
function receipt() { $this->gridView('Receipts'); }
|
||||
function deposit() {
|
||||
$this->sidemenu_links = array
|
||||
(array('name' => 'Operations', 'header' => true),
|
||||
array('name' => 'New Deposit', 'url' => array('controller' => 'tenders',
|
||||
'action' => 'deposit')));
|
||||
$this->gridView('Deposits');
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* virtuals: gridData
|
||||
* - With the application controller handling the gridData action,
|
||||
* these virtual functions ensure that the correct data is passed
|
||||
* to jqGrid.
|
||||
*/
|
||||
|
||||
function gridDataCountTables(&$params, &$model) {
|
||||
return array
|
||||
('link' =>
|
||||
array(// Models
|
||||
'Account' => array('fields' => array()),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function gridDataTables(&$params, &$model) {
|
||||
$link = $this->gridDataCountTables($params, $model);
|
||||
$link['link']['StatementEntry'] = array('fields' => array());
|
||||
$link['link']['DepositTender'] = array('fields' => array());
|
||||
return $link;
|
||||
}
|
||||
|
||||
function gridDataFields(&$params, &$model) {
|
||||
$fields = parent::gridDataFields($params, $model);
|
||||
//$fields[] = 'COUNT(StatementEntry.id) AS entries';
|
||||
$fields[] = ("IF(Transaction.type = 'DEPOSIT'," .
|
||||
" COUNT(DepositTender.id)," .
|
||||
" COUNT(StatementEntry.id)) AS entries");
|
||||
return $fields;
|
||||
}
|
||||
|
||||
function gridDataConditions(&$params, &$model) {
|
||||
$conditions = parent::gridDataConditions($params, $model);
|
||||
|
||||
if (in_array($params['action'], array('invoice', 'receipt', 'deposit')))
|
||||
$conditions[] = array('Transaction.type' => strtoupper($params['action']));
|
||||
|
||||
// REVISIT <AP>: 20090811
|
||||
// No security issues have been worked out yet
|
||||
$conditions[] = array('Account.level >=' => 5);
|
||||
|
||||
return $conditions;
|
||||
}
|
||||
|
||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||
$links['Transaction'] = array('id', 'action' => ($params['action'] == 'deposit'
|
||||
? 'deposit_slip' : 'view'));
|
||||
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* 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 receipt
|
||||
*/
|
||||
|
||||
function postReceipt() {
|
||||
if (!$this->RequestHandler->isPost()) {
|
||||
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
||||
return;
|
||||
}
|
||||
|
||||
foreach($this->data['Entry'] AS &$entry) {
|
||||
$entry['Tender'] = $entry['type'][$entry['tender_type_id']];
|
||||
unset($entry['type']);
|
||||
unset($entry['tender_type_id']);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: postDeposit
|
||||
* - handles the creation of a deposit transaction
|
||||
*/
|
||||
|
||||
function postDeposit() {
|
||||
if (!$this->RequestHandler->isPost()) {
|
||||
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
||||
return;
|
||||
}
|
||||
|
||||
//pr($this->data);
|
||||
|
||||
// Go through each type of tender presented to the user
|
||||
// Determine which are to be deposited, and which are to
|
||||
// have their corresponding account ledgers closed.
|
||||
$deposit_tender_ids = array();
|
||||
$deposit_type_ids = array();
|
||||
$close_type_ids = array();
|
||||
foreach ($this->data['TenderType'] AS $type_id => $type) {
|
||||
$type['items'] = unserialize($type['items']);
|
||||
if (empty($type['selection']) ||
|
||||
$type['selection'] === 'none' ||
|
||||
($type['selection'] === 'subset' && count($type['items']) == 0))
|
||||
continue;
|
||||
|
||||
// The deposit includes either the whole type, or just certain tenders
|
||||
if ($type['selection'] === 'all')
|
||||
$deposit_type_ids[] = $type_id;
|
||||
else
|
||||
$deposit_tender_ids = array_merge($deposit_tender_ids, $type['items']);
|
||||
|
||||
// Should we close the ledger for this tender type?
|
||||
// First, the user would have to request that we do so,
|
||||
// but additionally, we shouldn't close a ledger unless
|
||||
// all the tenders are included in this deposit. That
|
||||
// doesn't guarantee that the ledger has a zero balance,
|
||||
// but it does carry the balance forward, and a total
|
||||
// deposit would imply a fresh start, so go for it.
|
||||
if (!empty($type['close']) && $type['selection'] === 'all')
|
||||
$close_type_ids[] = $type_id;
|
||||
}
|
||||
|
||||
// Make sure we actually have something to deposit
|
||||
if (empty($deposit_type_ids) && empty($deposit_tender_ids)) {
|
||||
$this->Session->setFlash(__('Nothing to Deposit', true));
|
||||
$this->redirect(array('controller' => 'tenders', 'action'=>'deposit'));
|
||||
}
|
||||
|
||||
// Build up a set of conditions based on user selection
|
||||
$deposit_conditions = array();
|
||||
if (!empty($deposit_type_ids))
|
||||
$deposit_conditions[] = array('TenderType.id' => $deposit_type_ids);
|
||||
if (!empty($deposit_tender_ids))
|
||||
$deposit_conditions[] = array('DepositTender.id' => $deposit_tender_ids);
|
||||
|
||||
// Add in confirmation that items have not already been deposited
|
||||
$deposit_conditions =
|
||||
array(array('DepositTender.deposit_transaction_id' => null),
|
||||
array('OR' => $deposit_conditions));
|
||||
|
||||
// Lookup the items to be deposited
|
||||
$tenders = $this->Transaction->DepositTender->find
|
||||
('all',
|
||||
array('contain' => array('TenderType', 'LedgerEntry'),
|
||||
'conditions' => $deposit_conditions,
|
||||
));
|
||||
|
||||
// Build the deposit transaction
|
||||
$deposit = array('Transaction' => array(), 'Entry' => array());
|
||||
foreach ($tenders AS $tender) {
|
||||
$deposit['Entry'][] =
|
||||
array('tender_id' => $tender['DepositTender']['id'],
|
||||
'account_id' => $tender['LedgerEntry']['account_id'],
|
||||
'amount' => $tender['LedgerEntry']['amount'],
|
||||
);
|
||||
}
|
||||
|
||||
//pr(compact('deposit_type_ids', 'deposit_tender_ids', 'close_type_ids', 'deposit_conditions', 'deposit'));
|
||||
|
||||
// OK, perform the deposit and associated accounting
|
||||
$result = $this->Transaction->addDeposit
|
||||
($deposit, $this->data['Deposit']['Account']['id']);
|
||||
//pr(compact('deposit', 'result'));
|
||||
|
||||
// Close any ledgers necessary
|
||||
if (!empty($close_type_ids)) {
|
||||
// Find the accounts associated with the types to close ...
|
||||
$accounts = $this->Transaction->DepositTender->find
|
||||
('all',
|
||||
array('contain' => array('TenderType.account_id'),
|
||||
'conditions' => array(array('TenderType.id' => $close_type_ids)),
|
||||
));
|
||||
|
||||
// ... and close them
|
||||
$this->Transaction->Account->closeCurrentLedgers
|
||||
(array_map(create_function('$item', 'return $item["TenderType"]["account_id"];'), $accounts));
|
||||
}
|
||||
|
||||
// Look out for errors
|
||||
if ($result['error']) {
|
||||
$this->Session->setFlash(__('Unable to Create Deposit', true));
|
||||
$this->redirect(array('controller' => 'tenders', 'action'=>'deposit'));
|
||||
}
|
||||
|
||||
// Present the deposit slip to the user
|
||||
$this->redirect(array('controller' => 'transactions',
|
||||
'action' => 'deposit_slip',
|
||||
$result['transaction_id']));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: postWriteOff
|
||||
* - handles the write off of bad debt
|
||||
*/
|
||||
|
||||
function postWriteOff() {
|
||||
if (!$this->RequestHandler->isPost()) {
|
||||
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
||||
return;
|
||||
}
|
||||
|
||||
$data = $this->data;
|
||||
if (empty($data['Customer']['id']))
|
||||
$data['Customer']['id'] = null;
|
||||
if (empty($data['Lease']['id']))
|
||||
$data['Lease']['id'] = null;
|
||||
|
||||
pr(compact('data'));
|
||||
|
||||
if (!$this->Transaction->addWriteOff($data,
|
||||
$data['Customer']['id'],
|
||||
$data['Lease']['id'])) {
|
||||
$this->Session->setFlash("WRITE OFF FAILED", true);
|
||||
// REVISIT <AP> 20090706:
|
||||
// Until we can work out the session problems,
|
||||
// just die.
|
||||
die("<H1>WRITE-OFF FAILED</H1>");
|
||||
}
|
||||
|
||||
// Return to viewing the lease/customer
|
||||
if (empty($data['Lease']['id']))
|
||||
$this->redirect(array('controller' => 'customers',
|
||||
'action' => 'view',
|
||||
$data['Customer']['id']));
|
||||
else
|
||||
$this->redirect(array('controller' => 'leases',
|
||||
'action' => 'view',
|
||||
$data['Lease']['id']));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: postRefund
|
||||
* - handles issuing a customer refund
|
||||
*/
|
||||
|
||||
function postRefund() {
|
||||
if (!$this->RequestHandler->isPost()) {
|
||||
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
||||
return;
|
||||
}
|
||||
|
||||
$data = $this->data;
|
||||
if (empty($data['Customer']['id']))
|
||||
$data['Customer']['id'] = null;
|
||||
if (empty($data['Lease']['id']))
|
||||
$data['Lease']['id'] = null;
|
||||
|
||||
if (!$this->Transaction->addRefund($data,
|
||||
$data['Customer']['id'],
|
||||
$data['Lease']['id'])) {
|
||||
$this->Session->setFlash("REFUND FAILED", true);
|
||||
// REVISIT <AP> 20090706:
|
||||
// Until we can work out the session problems,
|
||||
// just die.
|
||||
die("<H1>REFUND FAILED</H1>");
|
||||
}
|
||||
|
||||
// Return to viewing the lease/customer
|
||||
if (empty($data['Lease']['id']))
|
||||
$this->redirect(array('controller' => 'customers',
|
||||
'action' => 'view',
|
||||
$data['Customer']['id']));
|
||||
else
|
||||
$this->redirect(array('controller' => 'leases',
|
||||
'action' => 'view',
|
||||
$data['Lease']['id']));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: destroy
|
||||
* - Deletes a transaction and associated entries
|
||||
* - !!WARNING!! This should be used with EXTREME caution, as it
|
||||
* irreversibly destroys the data. It is not for normal use.
|
||||
*/
|
||||
|
||||
function destroy($id = null) {
|
||||
$this->Transaction->destroy($id);
|
||||
//$this->redirect(array('action' => 'index'));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: view
|
||||
* - Displays information about a specific transaction
|
||||
*/
|
||||
|
||||
function view($id = null) {
|
||||
$transaction = $this->Transaction->find
|
||||
('first',
|
||||
array('contain' =>
|
||||
array(// Models
|
||||
'Account(id,name)',
|
||||
'Ledger(id,name)',
|
||||
'NsfTender(id,name)',
|
||||
),
|
||||
'conditions' => array(array('Transaction.id' => $id),
|
||||
// REVISIT <AP>: 20090811
|
||||
// No security issues have been worked out yet
|
||||
array('OR' =>
|
||||
array(array('Account.level >=' => 5),
|
||||
array('Account.id' => null))),
|
||||
),
|
||||
));
|
||||
|
||||
// REVISIT <AP>: 20090815
|
||||
// for debug purposes only (pr output)
|
||||
$this->Transaction->stats($id);
|
||||
|
||||
if (empty($transaction)) {
|
||||
$this->Session->setFlash(__('Invalid Item.', true));
|
||||
$this->redirect(array('action'=>'index'));
|
||||
}
|
||||
|
||||
if ($transaction['Transaction']['type'] === 'DEPOSIT' || $this->params['dev']) {
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'Operations', 'header' => true);
|
||||
|
||||
if ($transaction['Transaction']['type'] === 'DEPOSIT')
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'View Slip', 'url' => array('action' => 'deposit_slip', $id));
|
||||
if ($this->params['dev'])
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'Destroy', 'url' => array('action' => 'destroy', $id),
|
||||
'confirmMessage' => ("This may leave the database in an unstable state." .
|
||||
" Do NOT do this unless you know what you're doing." .
|
||||
" Proceed anyway?"));
|
||||
}
|
||||
|
||||
// OK, prepare to render.
|
||||
$title = 'Transaction #' . $transaction['Transaction']['id'];
|
||||
$this->set(compact('transaction', 'title'));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: deposit_slip
|
||||
* - Special presentation
|
||||
* Processes the user input and updates the database
|
||||
*/
|
||||
|
||||
function deposit_slip($id) {
|
||||
// Build a container for the deposit slip data
|
||||
$deposit = array('types' => array());
|
||||
|
||||
$this->id = $id;
|
||||
$deposit +=
|
||||
$this->Transaction->find('first', array('contain' => false));
|
||||
|
||||
// Get a summary of all forms of tender in the deposit
|
||||
$result = $this->Transaction->find
|
||||
('all',
|
||||
array('link' => array('DepositTender' =>
|
||||
array('fields' => array(),
|
||||
'TenderType',
|
||||
'LedgerEntry' =>
|
||||
array('fields' => array()))),
|
||||
'fields' => array(//'TenderType.id', 'TenderType.name',
|
||||
"COUNT(DepositTender.id) AS 'count'",
|
||||
"SUM(LedgerEntry.amount) AS 'total'"),
|
||||
//'conditions' => array(array('DepositTender.deposit_transaction_id' => $id)),
|
||||
'conditions' => array(array('Transaction.id' => $id)),
|
||||
'group' => 'TenderType.id',
|
||||
));
|
||||
|
||||
if (empty($result)) {
|
||||
die();
|
||||
$this->Session->setFlash(__('Invalid Deposit.', true));
|
||||
$this->redirect(array('action'=>'deposit'));
|
||||
}
|
||||
|
||||
// Add the summary to our deposit slip data container
|
||||
foreach ($result AS $type) {
|
||||
$deposit['types'][$type['TenderType']['id']] =
|
||||
$type['TenderType'] + $type[0];
|
||||
}
|
||||
|
||||
$deposit_total = 0;
|
||||
foreach ($deposit['types'] AS $type)
|
||||
$deposit_total += $type['total'];
|
||||
|
||||
if ($deposit['Transaction']['amount'] != $deposit_total)
|
||||
$this->INTERNAL_ERROR("Deposit items do not add up to deposit slip total");
|
||||
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'Operations', 'header' => true);
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'View Transaction', 'url' => array('action' => 'view', $id));
|
||||
|
||||
$title = 'Deposit Slip';
|
||||
$this->set(compact('title', 'deposit'));
|
||||
$this->render('deposit_slip');
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
336
controllers/units_controller.php
Normal file
336
controllers/units_controller.php
Normal file
@@ -0,0 +1,336 @@
|
||||
<?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->gridView('Unavailable Units'); }
|
||||
function vacant() { $this->gridView('Vacant Units'); }
|
||||
function occupied() { $this->gridView('Occupied Units'); }
|
||||
function all() { $this->gridView('All Units', 'all'); }
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* virtuals: gridData
|
||||
* - With the application controller handling the gridData action,
|
||||
* these virtual functions ensure that the correct data is passed
|
||||
* to jqGrid.
|
||||
*/
|
||||
|
||||
function gridDataSetup(&$params) {
|
||||
parent::gridDataSetup($params);
|
||||
if (!isset($params['action']))
|
||||
$params['action'] = 'all';
|
||||
}
|
||||
|
||||
function gridDataCountTables(&$params, &$model) {
|
||||
return array
|
||||
('link' => array('UnitSize' => array('fields' => array('id', 'name')),
|
||||
'CurrentLease' => array('fields' => array('id'))));
|
||||
|
||||
/* if ($params['action'] === 'occupied') */
|
||||
/* $link['Lease'] = array('fields' => array(), */
|
||||
/* // Models */
|
||||
/* 'Contact' => array('fields' => array('display_name'), */
|
||||
/* //'type' => 'LEFT', */
|
||||
/* ), */
|
||||
/* ); */
|
||||
|
||||
}
|
||||
|
||||
function gridDataTables(&$params, &$model) {
|
||||
$link = $this->gridDataCountTables($params, $model);
|
||||
$link['link']['CurrentLease']['StatementEntry'] = array('fields' => array());
|
||||
return $link;
|
||||
}
|
||||
|
||||
/* function gridDataTables(&$params, &$model) { */
|
||||
/* return array */
|
||||
/* ('link' => array('Unit' => array('fields' => array('Unit.id', 'Unit.name')), */
|
||||
/* 'Customer' => array('fields' => array('Customer.id', 'Customer.name')))); */
|
||||
/* } */
|
||||
|
||||
function gridDataFields(&$params, &$model) {
|
||||
$fields = parent::gridDataFields($params, $model);
|
||||
|
||||
return array_merge($fields,
|
||||
$this->Unit->Lease->StatementEntry->chargeDisbursementFields(true));
|
||||
}
|
||||
|
||||
function gridDataConditions(&$params, &$model) {
|
||||
$conditions = parent::gridDataConditions($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 gridDataOrder(&$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::gridDataOrder($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::gridDataOrder($params, $model,
|
||||
'Unit.sort_order', $direction);
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||
$links['Unit'] = array('name');
|
||||
$links['UnitSize'] = array('name');
|
||||
return parent::gridDataPostProcessLinks($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->securityDeposits($unit['CurrentLease']['id']);
|
||||
$outstanding_deposit = $this->Unit->Lease->securityDepositBalance($unit['CurrentLease']['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));
|
||||
|
||||
if (isset($unit['CurrentLease']['id']) &&
|
||||
!isset($unit['CurrentLease']['moveout_date'])) {
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'Move-Out', 'url' => array('action' => 'move_out',
|
||||
$id));
|
||||
} elseif ($this->Unit->available($unit['Unit']['status'])) {
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'Move-In', 'url' => array('action' => 'move_in',
|
||||
$id));
|
||||
} else {
|
||||
// Unit is unavailable (dirty, damaged, reserved, business-use, etc)
|
||||
}
|
||||
|
||||
if (isset($unit['CurrentLease']['id']) &&
|
||||
!isset($unit['CurrentLease']['close_date'])) {
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'New Invoice', 'url' => array('controller' => 'leases',
|
||||
'action' => 'invoice',
|
||||
$unit['CurrentLease']['id']));
|
||||
$this->sidemenu_links[] =
|
||||
array('name' => 'New Receipt', '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'));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* action: edit
|
||||
* - Edit unit information
|
||||
*/
|
||||
|
||||
function edit($id = null) {
|
||||
if (isset($this->data)) {
|
||||
// Check to see if the operation was cancelled.
|
||||
if (isset($this->params['form']['cancel'])) {
|
||||
if (empty($this->data['Unit']['id']))
|
||||
$this->redirect(array('action'=>'index'));
|
||||
|
||||
$this->redirect(array('action'=>'view', $this->data['Unit']['id']));
|
||||
}
|
||||
|
||||
// Make sure we have unit data
|
||||
if (empty($this->data['Unit']))
|
||||
$this->redirect(array('action'=>'index'));
|
||||
|
||||
// Make sure we have a rental rate
|
||||
if (empty($this->data['Unit']['rent']))
|
||||
$this->redirect(array('action'=>'view', $this->data['Unit']['id']));
|
||||
|
||||
// Save the unit and all associated data
|
||||
$this->Unit->create();
|
||||
$this->Unit->id = $this->data['Unit']['id'];
|
||||
if (!$this->Unit->save($this->data, false)) {
|
||||
$this->Session->setFlash("UNIT SAVE FAILED", true);
|
||||
pr("UNIT SAVE FAILED");
|
||||
}
|
||||
|
||||
$this->redirect(array('action'=>'view', $this->Unit->id));
|
||||
}
|
||||
|
||||
if ($id) {
|
||||
$this->data = $this->Unit->findById($id);
|
||||
$title = 'Unit ' . $this->data['Unit']['name'] . " : Edit";
|
||||
}
|
||||
else {
|
||||
$title = "Enter New Unit";
|
||||
$this->data = array();
|
||||
}
|
||||
|
||||
$statusEnums = $this->Unit->allowedStatusSet($id);
|
||||
$statusEnums = array_combine(array_keys($statusEnums),
|
||||
array_keys($statusEnums));
|
||||
$this->set(compact('statusEnums'));
|
||||
|
||||
$unit_sizes = $this->Unit->UnitSize->find
|
||||
('list', array('order' => array('unit_type_id', 'width', 'depth', 'id')));
|
||||
$this->set(compact('unit_sizes'));
|
||||
|
||||
// Prepare to render.
|
||||
pr($this->data);
|
||||
$this->set(compact('title'));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
24
index.php
Normal file
24
index.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id: index.php 7945 2008-12-19 02:16:01Z gwoo $ */
|
||||
/**
|
||||
* 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.app
|
||||
* @since CakePHP(tm) v 0.10.0.1076
|
||||
* @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
|
||||
*/
|
||||
require 'webroot' . DIRECTORY_SEPARATOR . 'index.php';
|
||||
?>
|
||||
389
models/account.php
Normal file
389
models/account.php
Normal file
@@ -0,0 +1,389 @@
|
||||
<?php
|
||||
class Account extends AppModel {
|
||||
|
||||
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(array('CurrentLedger.close_transaction_id' => null)),
|
||||
'conditions' => array('CurrentLedger.close_transaction_id IS NULL'),
|
||||
),
|
||||
);
|
||||
|
||||
var $hasMany = array(
|
||||
'Ledger',
|
||||
'LedgerEntry',
|
||||
);
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* 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 (strtolower($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: debitCreditFields
|
||||
* - Returns the fields necessary to determine whether the queried
|
||||
* entries are a debit, or a credit, and also the effect each have
|
||||
* on the overall balance of the account.
|
||||
*/
|
||||
|
||||
function debitCreditFields($sum = false, $balance = true,
|
||||
$entry_name = 'LedgerEntry', $account_name = 'Account') {
|
||||
return $this->LedgerEntry->debitCreditFields
|
||||
($sum, $balance, $entry_name, $account_name);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: Account IDs
|
||||
* - Returns the ID of the desired account
|
||||
*/
|
||||
|
||||
function lookup($name, $check = true) {
|
||||
$id = $this->nameToID($name);
|
||||
if (empty($id) && $check)
|
||||
$this->INTERNAL_ERROR("Missing Account '$name'");
|
||||
return $id;
|
||||
}
|
||||
|
||||
function securityDepositAccountID() { return $this->lookup('Security Deposit'); }
|
||||
function rentAccountID() { return $this->lookup('Rent'); }
|
||||
function lateChargeAccountID() { return $this->lookup('Late Charge'); }
|
||||
function nsfAccountID() { return $this->lookup('NSF'); }
|
||||
function nsfChargeAccountID() { return $this->lookup('NSF Charge'); }
|
||||
function taxAccountID() { return $this->lookup('Tax'); }
|
||||
function accountReceivableAccountID() { return $this->lookup('A/R'); }
|
||||
function accountPayableAccountID() { return $this->lookup('A/P'); }
|
||||
function cashAccountID() { return $this->lookup('Cash'); }
|
||||
function checkAccountID() { return $this->lookup('Check'); }
|
||||
function moneyOrderAccountID() { return $this->lookup('Money Order'); }
|
||||
function achAccountID() { return $this->lookup('ACH'); }
|
||||
function concessionAccountID() { return $this->lookup('Concession'); }
|
||||
function waiverAccountID() { return $this->lookup('Waiver'); }
|
||||
function pettyCashAccountID() { return $this->lookup('Petty Cash'); }
|
||||
function invoiceAccountID() { return $this->lookup('Invoice'); }
|
||||
function receiptAccountID() { return $this->lookup('Receipt'); }
|
||||
function badDebtAccountID() { return $this->lookup('Bad Debt'); }
|
||||
function customerCreditAccountID() { return $this->lookup(
|
||||
// REVISIT <AP>: 20090816
|
||||
// Use of A/R works, and saves an excess of accounts.
|
||||
// However, a dedicated account is nice, since it can
|
||||
// quickly be spotted how much is _really_ due, vs
|
||||
// how much has been pre-paid. Customer credits in
|
||||
// A/R is not as clear, although a report is an
|
||||
// obvious solution.
|
||||
//'A/R'
|
||||
'Credit'
|
||||
); }
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* 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;
|
||||
$accounts = $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;
|
||||
|
||||
// Rearrange to be of the form (id => name)
|
||||
$rel_accounts = array();
|
||||
foreach ($accounts AS $acct) {
|
||||
$rel_accounts[$acct['Account']['id']] = $acct['Account']['name'];
|
||||
}
|
||||
|
||||
return $rel_accounts;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: xxxAccounts
|
||||
* - Returns an array of accounts suitable for activity xxx
|
||||
*/
|
||||
|
||||
function invoiceAccounts() {
|
||||
return $this->relatedAccounts('invoices', array('order' => 'name'));
|
||||
}
|
||||
|
||||
function receiptAccounts() {
|
||||
return $this->relatedAccounts('receipts', array('order' => 'name'));
|
||||
}
|
||||
|
||||
function depositAccounts() {
|
||||
return $this->relatedAccounts('deposits', array('order' => 'name'));
|
||||
}
|
||||
|
||||
function refundAccounts() {
|
||||
return $this->relatedAccounts('refunds', array('order' => 'name'));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: collectableAccounts
|
||||
* - Returns an array of accounts suitable to show income collection
|
||||
*/
|
||||
|
||||
function collectableAccounts() {
|
||||
$accounts = $this->receiptAccounts();
|
||||
|
||||
foreach(array($this->customerCreditAccountID(),
|
||||
$this->securityDepositAccountID(),
|
||||
$this->nsfAccountID(),
|
||||
$this->waiverAccountID(),
|
||||
$this->badDebtAccountID(),
|
||||
//$this->lookup('Closing'),
|
||||
//$this->lookup('Equity'),
|
||||
)
|
||||
AS $account_id) {
|
||||
$accounts[$account_id] = $this->name($account_id);
|
||||
}
|
||||
|
||||
$accounts['all'] = $accounts['default'] = $accounts;
|
||||
|
||||
foreach(array($this->concessionAccountID(),
|
||||
$this->waiverAccountID(),
|
||||
$this->badDebtAccountID(),
|
||||
)
|
||||
AS $account_id) {
|
||||
unset($accounts['default'][$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 closeCurrentLedgers($ids = null) {
|
||||
|
||||
$this->cacheQueries = true;
|
||||
$account = $this->find('all', array
|
||||
('contain' => array('CurrentLedger.id'),
|
||||
'fields' => array(),
|
||||
'conditions' => (empty($ids)
|
||||
? array()
|
||||
: array(array('Account.id' => $ids)))
|
||||
));
|
||||
$this->cacheQueries = false;
|
||||
//pr(compact('id', 'account'));
|
||||
|
||||
$ledger_ids = array();
|
||||
foreach ($account AS $acct)
|
||||
$ledger_ids[] = $acct['CurrentLedger']['id'];
|
||||
|
||||
return $this->Ledger->closeLedgers($ledger_ids);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: ledgerEntries
|
||||
* - Returns an array of ledger entries that belong to the given
|
||||
* account, either just from the current ledger, or from all ledgers.
|
||||
*/
|
||||
function ledgerEntries($id, $all = false, $cond = null, $link = null) {
|
||||
$ledgers = $this->ledgers($id, $all);
|
||||
return $this->Ledger->ledgerEntries($ledgers, $cond, $link);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: stats
|
||||
* - Returns summary data from the requested account.
|
||||
*/
|
||||
|
||||
function stats($id = null, $all = false, $query = null) {
|
||||
if (!$id)
|
||||
return null;
|
||||
|
||||
$this->queryInit($query);
|
||||
$query['link'] = array('Account' => $query['link']);
|
||||
|
||||
$stats = array();
|
||||
foreach ($this->ledgers($id, $all) AS $ledger)
|
||||
$this->statsMerge($stats['Ledger'],
|
||||
$this->Ledger->stats($ledger, $query));
|
||||
|
||||
return $stats;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
486
models/behaviors/linkable.php
Normal file
486
models/behaviors/linkable.php
Normal file
@@ -0,0 +1,486 @@
|
||||
<?php
|
||||
/*
|
||||
* LinkableBehavior
|
||||
* Light-weight approach for data mining on deep relations between models.
|
||||
* Join tables based on model relations to easily enable right to left find operations.
|
||||
*
|
||||
* Can be used as a alternative to the ContainableBehavior:
|
||||
* - On data fetching only in right to left operations,
|
||||
* wich means that in "one to many" relations (hasMany, hasAndBelongsToMany)
|
||||
* should only be used from the "many to one" tables. i.e:
|
||||
* To fetch all Users assigneds to a Project with ProjectAssignment,
|
||||
* $Project->find('all', array('link' => 'User', 'conditions' => 'project_id = 1'))
|
||||
* - Won't produce the desired result as data came from users table will be lost.
|
||||
* $User->find('all', array('link' => 'Project', 'conditions' => 'project_id = 1'))
|
||||
* - Will fetch all users related to the specified project in one query
|
||||
*
|
||||
* - On data mining as a much lighter approach - can reduce 300+ query find operations
|
||||
* in one single query with joins; "or your money back!" ;-)
|
||||
*
|
||||
* - Has the 'fields' param enabled to make it easy to replace Containable usage,
|
||||
* only change the 'contain' param to 'link'.
|
||||
*
|
||||
* Linkable Behavior. Taking it easy in your DB.
|
||||
* RafaelBandeira <rafaelbandeira3(at)gmail(dot)com>
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @version 1.0;
|
||||
*/
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NOTE TO <AP> 20090615:
|
||||
* This structure should be linkable (it was my test case).
|
||||
|
||||
$entry = $this->LedgerEntry->find
|
||||
('first',
|
||||
array('link' => array('DebitLedger' =>
|
||||
array(
|
||||
'fields' => array('id'),
|
||||
'alias' => 'MyDebitLedger',
|
||||
'Account' =>
|
||||
array(
|
||||
'fields' => array('id'),
|
||||
'alias' => 'MyDebitAccount'),
|
||||
),
|
||||
|
||||
'MyCreditLedger' =>
|
||||
array(
|
||||
'fields' => array('id'),
|
||||
'class' => 'CreditLedger',
|
||||
'MyCreditAccount' =>
|
||||
array(
|
||||
'fields' => array('id'),
|
||||
'class' => 'Account'),
|
||||
),
|
||||
|
||||
'MyOtherLedger' =>
|
||||
array(
|
||||
'fields' => array('id'),
|
||||
'class' => 'Ledger',
|
||||
'alias' => 'AliasToMyOtherLedger',
|
||||
'Account' =>
|
||||
array(
|
||||
'fields' => array('id'),
|
||||
'alias' => 'AliasToMyOtherAccount'),
|
||||
),
|
||||
),
|
||||
|
||||
'conditions' => array('LedgerEntry.id' => $id),
|
||||
));
|
||||
**********************************************************************/
|
||||
|
||||
|
||||
class LinkableBehavior extends ModelBehavior {
|
||||
|
||||
protected $_key = 'link';
|
||||
|
||||
protected $_options = array(
|
||||
'type' => true, 'table' => true, 'alias' => true, 'joins' => true,
|
||||
'conditions' => true, 'fields' => true, 'reference' => true,
|
||||
'class' => true, 'defaults' => true, 'linkalias' => true,
|
||||
);
|
||||
|
||||
protected $_defaults = array('type' => 'LEFT');
|
||||
|
||||
function pr($lev, $mixed) {
|
||||
if ($lev >= 3)
|
||||
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
|
||||
* NOTE: The palacement of this function is terrible, but I don't
|
||||
* know if I really want to go down this path or not.
|
||||
*/
|
||||
function recursive_array_replace($find, $replace, &$data) {
|
||||
if (!isset($data))
|
||||
return;
|
||||
|
||||
if (is_array($data)) {
|
||||
foreach ($data as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$this->recursive_array_replace($find, $replace, $data[$key]);
|
||||
} else {
|
||||
$data[$key] = str_replace($find, $replace, $value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$data = str_replace($find, $replace, $data);
|
||||
}
|
||||
}
|
||||
|
||||
public function beforeFind(&$Model, $query) {
|
||||
if (!isset($query[$this->_key]))
|
||||
return $query;
|
||||
|
||||
if (!isset($query['fields']) || $query['fields'] === true) {
|
||||
$query['fields'] = $Model->getDataSource()->fields($Model);
|
||||
} elseif (!is_array($query['fields'])) {
|
||||
$query['fields'] = array($query['fields']);
|
||||
}
|
||||
$query = am(array('joins' => array()), $query, array('recursive' => -1));
|
||||
|
||||
$reference = array('class' => $Model->alias,
|
||||
'alias' => $Model->alias,
|
||||
);
|
||||
|
||||
$result = array_diff_key($query, array($this->_key => 1));
|
||||
$this->buildQuery($Model, $Model->alias, $Model->alias, $Model->findQueryType,
|
||||
$query[$this->_key], $result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
function buildQuery(&$Reference, $referenceClass, $referenceAlias, $query_type, $links, &$result) {
|
||||
if (empty($links))
|
||||
return;
|
||||
|
||||
$this->pr(10,
|
||||
array('begin' => 'Linkable::buildQuery',
|
||||
'args' => compact('referenceClass', 'referenceAlias', 'query_type', 'links'),
|
||||
));
|
||||
|
||||
//$defaults = $this->_defaults;// + array($this->_key => array());
|
||||
//$optionsKeys = $this->_options + array($this->_key => true);
|
||||
|
||||
$links = Set::normalize($links);
|
||||
$this->pr(24,
|
||||
array('checkpoint' => 'Normalized links',
|
||||
compact('links'),
|
||||
));
|
||||
foreach ($links as $alias => $options) {
|
||||
if (is_null($options)) {
|
||||
$options = array();
|
||||
}
|
||||
//$options = array_intersect_key($options, $optionsKeys);
|
||||
//$options = am($this->_defaults, compact('alias'), $options);
|
||||
|
||||
$options += compact('alias');
|
||||
$options += $this->_defaults;
|
||||
|
||||
if (empty($options['alias'])) {
|
||||
throw new InvalidArgumentException(sprintf('%s::%s must receive aliased links', get_class($this), __FUNCTION__));
|
||||
}
|
||||
|
||||
if (empty($options['class']))
|
||||
$options['class'] = $alias;
|
||||
|
||||
if (!isset($options['conditions']))
|
||||
$options['conditions'] = null;
|
||||
elseif (!is_array($options['conditions']))
|
||||
$options['conditions'] = array($options['conditions']);
|
||||
|
||||
$this->pr(20,
|
||||
array('checkpoint' => 'Begin Model Work',
|
||||
compact('referenceAlias', 'alias', 'options'),
|
||||
));
|
||||
|
||||
$modelClass = $options['class'];
|
||||
$modelAlias = $options['alias'];
|
||||
$Model =& ClassRegistry::init($modelClass); // the incoming model to be linked in query
|
||||
|
||||
$this->pr(12,
|
||||
array('checkpoint' => 'Model Established',
|
||||
'Reference' => ($referenceAlias .' : '. $referenceClass .
|
||||
' ('. $Reference->alias .' : '. $Reference->name .')'),
|
||||
'Model' => ($modelAlias .' : '. $modelClass .
|
||||
' ('. $Model->alias .' : '. $Model->name .')'),
|
||||
));
|
||||
|
||||
$db =& $Model->getDataSource();
|
||||
|
||||
$associatedThroughReference = 0;
|
||||
$association = null;
|
||||
|
||||
// Figure out how these two models are related, creating
|
||||
// a relationship if one doesn't otherwise already exists.
|
||||
if (($associations = $Reference->getAssociated()) &&
|
||||
isset($associations[$Model->alias])) {
|
||||
$this->pr(12, array('checkpoint' => "Reference ($referenceClass) defines association to Model ($modelClass)"));
|
||||
$associatedThroughReference = 1;
|
||||
$type = $associations[$Model->alias];
|
||||
$association = $Reference->{$type}[$Model->alias];
|
||||
}
|
||||
elseif (($associations = $Model->getAssociated()) &&
|
||||
isset($associations[$Reference->alias])) {
|
||||
$this->pr(12, array('checkpoint' => "Model ($modelClass) defines association to Reference ($referenceClass)"));
|
||||
$type = $associations[$Reference->alias];
|
||||
$association = $Model->{$type}[$Reference->alias];
|
||||
}
|
||||
else {
|
||||
// No relationship... make our best effort to create one.
|
||||
$this->pr(12, array('checkpoint' => "No assocation between Reference ($referenceClass) and Model ($modelClass)"));
|
||||
$type = 'belongsTo';
|
||||
$Model->bind($Reference->alias);
|
||||
// Grab the association now, since we'll unbind in a moment.
|
||||
$association = $Model->{$type}[$Reference->alias];
|
||||
$Model->unbindModel(array('belongsTo' => array($Reference->alias)));
|
||||
}
|
||||
|
||||
// Determine which model holds the foreign key
|
||||
if (($type === 'hasMany' || $type === 'hasOne') ^ $associatedThroughReference) {
|
||||
$primaryAlias = $referenceAlias;
|
||||
$foreignAlias = $modelAlias;
|
||||
$primaryModel = $Reference;
|
||||
$foreignModel = $Model;
|
||||
} else {
|
||||
$primaryAlias = $modelAlias;
|
||||
$foreignAlias = $referenceAlias;
|
||||
$primaryModel = $Model;
|
||||
$foreignModel = $Reference;
|
||||
}
|
||||
|
||||
if ($associatedThroughReference)
|
||||
$associationAlias = $referenceAlias;
|
||||
else
|
||||
$associationAlias = $modelAlias;
|
||||
|
||||
$this->pr(30,
|
||||
array('checkpoint' => 'Options/Association pre-merge',
|
||||
compact('association', 'options'),
|
||||
));
|
||||
|
||||
// A couple exceptions before performing a union of
|
||||
// options and association. Namely, most fields result
|
||||
// in either/or, but a couple should include BOTH the
|
||||
// options AND the association settings.
|
||||
foreach (array('fields', 'conditions') AS $fld) {
|
||||
$this->pr(31,
|
||||
array('checkpoint' => 'Options/Associations field original',
|
||||
compact('fld') +
|
||||
array("options[$fld]" =>
|
||||
array('value' => array_key_exists($fld, $options) ? (isset($options[$fld]) ? $options[$fld] : '-null-') : '-unset-',
|
||||
'type' => array_key_exists($fld, $options) ? (isset($options[$fld]) ? gettype($options[$fld]) : '-null-') : '-unset-'),
|
||||
"association[$fld]" =>
|
||||
array('value' => array_key_exists($fld, $association) ? (isset($association[$fld]) ? $association[$fld] : '-null-') : '-unset-',
|
||||
'type' => array_key_exists($fld, $association) ? (isset($association[$fld]) ? gettype($association[$fld]) : '-null-') : '-unset-'),
|
||||
)));
|
||||
|
||||
if (!isset($options[$fld]) ||
|
||||
(empty($options[$fld]) && !is_array($options[$fld])))
|
||||
unset($options[$fld]);
|
||||
elseif (!empty($options[$fld]) && !is_array($options[$fld]))
|
||||
$options[$fld] = array($options[$fld]);
|
||||
|
||||
if (!isset($association[$fld]) ||
|
||||
(empty($association[$fld]) && !is_array($association[$fld])))
|
||||
unset($association[$fld]);
|
||||
elseif (!empty($association[$fld]) && !is_array($association[$fld]))
|
||||
$association[$fld] = array($association[$fld]);
|
||||
|
||||
|
||||
$this->pr(31,
|
||||
array('checkpoint' => 'Options/Associations field normalize',
|
||||
compact('fld') +
|
||||
array("options[$fld]" =>
|
||||
array('value' => array_key_exists($fld, $options) ? (isset($options[$fld]) ? $options[$fld] : '-null-') : '-unset-',
|
||||
'type' => array_key_exists($fld, $options) ? (isset($options[$fld]) ? gettype($options[$fld]) : '-null-') : '-unset-'),
|
||||
"association[$fld]" =>
|
||||
array('value' => array_key_exists($fld, $association) ? (isset($association[$fld]) ? $association[$fld] : '-null-') : '-unset-',
|
||||
'type' => array_key_exists($fld, $association) ? (isset($association[$fld]) ? gettype($association[$fld]) : '-null-') : '-unset-'),
|
||||
)));
|
||||
|
||||
if (isset($options[$fld]) && isset($association[$fld]))
|
||||
$options[$fld] = array_merge($options[$fld],
|
||||
$association[$fld]);
|
||||
|
||||
$this->pr(31,
|
||||
array('checkpoint' => 'Options/Associations field merge complete',
|
||||
compact('fld') +
|
||||
array("options[$fld]" =>
|
||||
array('value' => array_key_exists($fld, $options) ? (isset($options[$fld]) ? $options[$fld] : '-null-') : '-unset-',
|
||||
'type' => array_key_exists($fld, $options) ? (isset($options[$fld]) ? gettype($options[$fld]) : '-null-') : '-unset-'),
|
||||
"association[$fld]" =>
|
||||
array('value' => array_key_exists($fld, $association) ? (isset($association[$fld]) ? $association[$fld] : '-null-') : '-unset-',
|
||||
'type' => array_key_exists($fld, $association) ? (isset($association[$fld]) ? gettype($association[$fld]) : '-null-') : '-unset-'),
|
||||
)));
|
||||
}
|
||||
|
||||
$this->pr(30,
|
||||
array('checkpoint' => 'Options/Association post-merge',
|
||||
compact('association', 'options'),
|
||||
));
|
||||
|
||||
// For any option that's not already set, use
|
||||
// whatever is specified by the assocation.
|
||||
$options += array_intersect_key($association, $this->_options);
|
||||
|
||||
// Replace all instances of the MODEL_ALIAS variable
|
||||
// tag with the correct model alias.
|
||||
$this->recursive_array_replace("%{MODEL_ALIAS}",
|
||||
$associationAlias,
|
||||
$options['conditions']);
|
||||
|
||||
$this->pr(15,
|
||||
array('checkpoint' => 'Models Established - Check Associations',
|
||||
'primaryModel' => $primaryAlias .' : '. $primaryModel->name,
|
||||
'foreignModel' => $foreignAlias .' : '. $foreignModel->name,
|
||||
compact('type', 'association', 'options'),
|
||||
));
|
||||
|
||||
if ($type === 'hasAndBelongsToMany') {
|
||||
if (isset($association['with']))
|
||||
$linkClass = $association['with'];
|
||||
else
|
||||
$linkClass = Inflector::classify($association['joinTable']);
|
||||
|
||||
$Link =& $Model->{$linkClass};
|
||||
|
||||
if (isset($options['linkalias']))
|
||||
$linkAlias = $options['linkalias'];
|
||||
else
|
||||
$linkAlias = $Link->alias;
|
||||
|
||||
// foreignKey and associationForeignKey can refer to either
|
||||
// the model or the reference, depending on which class
|
||||
// actually defines the association. Make sure to we're
|
||||
// using the foreign keys to point to the right class.
|
||||
if ($associatedThroughReference) {
|
||||
$modelAFK = 'associationForeignKey';
|
||||
$referenceAFK = 'foreignKey';
|
||||
} else {
|
||||
$modelAFK = 'foreignKey';
|
||||
$referenceAFK = 'associationForeignKey';
|
||||
}
|
||||
|
||||
$this->pr(17,
|
||||
array('checkpoint' => 'Linking HABTM',
|
||||
compact('linkClass', 'linkAlias',
|
||||
'modelAFK', 'referenceAFK'),
|
||||
));
|
||||
|
||||
// Get the foreign key fields (for the link table) directly from
|
||||
// the defined model associations, if they exists. This is the
|
||||
// users direct specification, and therefore definitive if present.
|
||||
$modelLink = $Link->escapeField($association[$modelAFK], $linkAlias);
|
||||
$referenceLink = $Link->escapeField($association[$referenceAFK], $linkAlias);
|
||||
|
||||
// If we haven't figured out the foreign keys, see if there is a
|
||||
// model for the link table, and if it has the appropriate
|
||||
// associations with the two tables we're trying to join.
|
||||
if (empty($modelLink) && isset($Link->belongsTo[$Model->alias]))
|
||||
$modelLink = $Link->escapeField($Link->belongsTo[$Model->alias]['foreignKey'], $linkAlias);
|
||||
if (empty($referenceLink) && isset($Link->belongsTo[$Reference->alias]))
|
||||
$referenceLink = $Link->escapeField($Link->belongsTo[$Reference->alias]['foreignKey'], $linkAlias);
|
||||
|
||||
// We're running quite thin here. None of the models spell
|
||||
// out the appropriate linkages. We'll have to SWAG it.
|
||||
if (empty($modelLink))
|
||||
$modelLink = $Link->escapeField(Inflector::underscore($Model->alias) . '_id', $linkAlias);
|
||||
if (empty($referenceLink))
|
||||
$referenceLink = $Link->escapeField(Inflector::underscore($Reference->alias) . '_id', $linkAlias);
|
||||
|
||||
// Get the primary key from the tables we're joining.
|
||||
$referenceKey = $Reference->escapeField(null, $referenceAlias);
|
||||
$modelKey = $Model->escapeField(null, $modelAlias);
|
||||
|
||||
$this->pr(21,
|
||||
array('checkpoint' => 'HABTM links/keys',
|
||||
array(compact('modelLink', 'modelKey'),
|
||||
compact('referenceLink', 'referenceKey')),
|
||||
));
|
||||
|
||||
// Join the linkage table to our model. We'll use an inner join,
|
||||
// as the whole purpose of the linkage table is to make this
|
||||
// connection. As we are embedding this join, the INNER will not
|
||||
// cause any problem with the overall query, should the user not
|
||||
// be concerned with whether or not the join has any results.
|
||||
// They control that with the 'type' parameter which will be at
|
||||
// the top level join.
|
||||
$options['joins'][] = array('type' => 'INNER',
|
||||
'alias' => $modelAlias,
|
||||
'conditions' => "{$modelKey} = {$modelLink}",
|
||||
'table' => $db->fullTableName($Model, true));
|
||||
|
||||
// Now for the top level join. This will be added into the list
|
||||
// of joins down below, outside of the HABTM specific code.
|
||||
$options['class'] = $linkClass;
|
||||
$options['alias'] = $linkAlias;
|
||||
$options['table'] = $Link->getDataSource()->fullTableName($Link);
|
||||
$options['conditions'][] = "{$referenceLink} = {$referenceKey}";
|
||||
}
|
||||
elseif (isset($association['foreignKey']) && $association['foreignKey']) {
|
||||
$foreignKey = $primaryModel->escapeField($association['foreignKey'], $primaryAlias);
|
||||
$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.
|
||||
// Either way works and this test can be tossed out
|
||||
if (($type === 'hasMany' || $type === 'hasOne') ^ $associatedThroughReference)
|
||||
$options['conditions'][] = "{$primaryKey} = {$foreignKey}";
|
||||
else
|
||||
$options['conditions'][] = "{$foreignKey} = {$primaryKey}";
|
||||
}
|
||||
else {
|
||||
$this->pr(17,
|
||||
array('checkpoint' => 'Linking with no logic (expecting user defined)',
|
||||
));
|
||||
|
||||
// No Foreign Key... nothing we can do.
|
||||
}
|
||||
|
||||
$this->pr(19,
|
||||
array('checkpoint' => 'Conditions',
|
||||
array('options[conditions]' => $options['conditions'],
|
||||
),
|
||||
));
|
||||
|
||||
if (empty($options['table'])) {
|
||||
$options['table'] = $db->fullTableName($Model, true);
|
||||
}
|
||||
|
||||
if (!isset($options['fields']) || !is_array($options['fields']))
|
||||
$options['fields'] = $db->fields($Model, $modelAlias);
|
||||
elseif (!empty($options['fields']))
|
||||
$options['fields'] = $db->fields($Model, $modelAlias, $options['fields']);
|
||||
|
||||
// When performing a count query, fields are useless.
|
||||
// For everything else, we need to add them into the set.
|
||||
if ($query_type !== 'count')
|
||||
$result['fields'] = array_merge($result['fields'], $options['fields']);
|
||||
|
||||
$result['joins'][] = array_intersect_key($options,
|
||||
array('type' => true,
|
||||
'alias' => true,
|
||||
'table' => true,
|
||||
'joins' => true,
|
||||
'conditions' => true));
|
||||
|
||||
$sublinks = array_diff_key($options, $this->_options);
|
||||
$this->buildQuery($Model, $modelClass, $modelAlias, $query_type, $sublinks, $result);
|
||||
|
||||
$this->pr(19,
|
||||
array('checkpoint' => 'Model Join Complete',
|
||||
compact('referenceAlias', 'modelAlias', 'options', 'result'),
|
||||
));
|
||||
}
|
||||
|
||||
$this->pr(20,
|
||||
array('return' => 'Linkable::buildQuery',
|
||||
compact('referenceAlias'),
|
||||
));
|
||||
}
|
||||
}
|
||||
129
models/contact.php
Normal file
129
models/contact.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
class Contact extends AppModel {
|
||||
|
||||
var $displayField = 'display_name';
|
||||
|
||||
var $hasMany = array(
|
||||
'ContactsMethod',
|
||||
'ContactsCustomer',
|
||||
);
|
||||
|
||||
var $hasAndBelongsToMany = array(
|
||||
'Customer',
|
||||
'ContactAddress' => array(
|
||||
'joinTable' => 'contacts_methods',
|
||||
'associationForeignKey' => 'method_id',
|
||||
'unique' => true,
|
||||
'conditions' => "method = 'ADDRESS'",
|
||||
),
|
||||
'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'",
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: saveContact
|
||||
* - Saves the contact and related data
|
||||
*/
|
||||
|
||||
function saveContact($id, $data) {
|
||||
|
||||
// Establish a display name if not already given
|
||||
if (!$data['Contact']['display_name'])
|
||||
$data['Contact']['display_name'] =
|
||||
(($data['Contact']['first_name'] &&
|
||||
$data['Contact']['last_name'])
|
||||
? $data['Contact']['last_name'] . ', ' . $data['Contact']['first_name']
|
||||
: ($data['Contact']['first_name']
|
||||
? $data['Contact']['first_name']
|
||||
: $data['Contact']['last_name']));
|
||||
|
||||
// Save the contact data
|
||||
$this->create();
|
||||
if ($id)
|
||||
$this->id = $id;
|
||||
if (!$this->save($data, false)) {
|
||||
return false;
|
||||
}
|
||||
$id = $this->id;
|
||||
|
||||
// Remove all associated ContactMethods, 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->ContactsMethod->deleteAll */
|
||||
/* (array('contact_id' => $id), false); */
|
||||
|
||||
// At this point, since we've saved data to contact,
|
||||
// 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;
|
||||
|
||||
// Iterate each type of contact method, adding them into
|
||||
// the database as needed and associating with this contact.
|
||||
foreach (array('phone', 'address', 'email') AS $type) {
|
||||
$class = 'Contact' . ucfirst($type);
|
||||
$enum = strtoupper($type);
|
||||
|
||||
// Nothing to do if this contact method isn't used
|
||||
if (!isset($data[$class]))
|
||||
continue;
|
||||
|
||||
// Go through each entry of this contact method
|
||||
foreach ($data[$class] AS &$item) {
|
||||
|
||||
// If the user has entered all new data, we need to
|
||||
// save that as a brand new entry.
|
||||
if (!isset($item['id'])) {
|
||||
$I = new $class();
|
||||
$I->create();
|
||||
if (!$I->save($item, false)) {
|
||||
$ret = false;
|
||||
continue;
|
||||
}
|
||||
$item['id'] = $I->id;
|
||||
}
|
||||
|
||||
// Update the ContactsMethod to reflect the appropriate IDs
|
||||
$item['ContactsMethod']['contact_id'] = $id;
|
||||
$item['ContactsMethod']['method_id'] = $item['id'];
|
||||
$item['ContactsMethod']['method'] = $enum;
|
||||
|
||||
// Save the relationship between contact and phone/email/address
|
||||
$CM = new ContactsMethod();
|
||||
if (!$CM->save($item['ContactsMethod'], false)) {
|
||||
$ret = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the result
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function contactList() {
|
||||
return $this->find('list',
|
||||
array('order' =>
|
||||
//array('last_name', 'first_name', 'middle_name'),
|
||||
array('display_name'),
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
46
models/contact_address.php
Normal file
46
models/contact_address.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
class ContactAddress extends AppModel {
|
||||
|
||||
var $name = 'ContactAddress';
|
||||
var $validate = array(
|
||||
'id' => array('numeric'),
|
||||
'postcode' => array('postal')
|
||||
);
|
||||
|
||||
var $hasMany = array(
|
||||
'ContactsMethod' => array(
|
||||
'foreignKey' => 'method_id',
|
||||
'conditions' => "method = 'ADDRESS'",
|
||||
)
|
||||
);
|
||||
|
||||
var $hasAndBelongsToMany = array(
|
||||
'Contact' => array(
|
||||
'className' => 'Contact',
|
||||
'joinTable' => 'contacts_methods',
|
||||
'foreignKey' => 'method_id',
|
||||
'associationForeignKey' => 'contact_id',
|
||||
'unique' => true,
|
||||
'conditions' => "method = 'ADDRESS'",
|
||||
)
|
||||
);
|
||||
|
||||
function addressList() {
|
||||
$results = $this->find('all',
|
||||
array('contain' => false,
|
||||
'fields' => array('id', 'address', 'city', 'state', 'postcode'),
|
||||
'order' => array('state', 'city', 'postcode', 'address')));
|
||||
|
||||
$list = array();
|
||||
foreach ($results as $key => $val) {
|
||||
$list[$val['ContactAddress']['id']]
|
||||
= preg_replace("/\n/", ", ", $val['ContactAddress']['address'])
|
||||
. ', ' . $val['ContactAddress']['city']
|
||||
. ', ' . $val['ContactAddress']['state']
|
||||
. ' ' . $val['ContactAddress']['postcode']
|
||||
;
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
?>
|
||||
27
models/contact_email.php
Normal file
27
models/contact_email.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
class ContactEmail extends AppModel {
|
||||
|
||||
var $name = 'ContactEmail';
|
||||
var $displayField = 'email';
|
||||
var $validate = array(
|
||||
'id' => array('numeric'),
|
||||
'email' => array('email')
|
||||
);
|
||||
|
||||
var $hasAndBelongsToMany = array(
|
||||
'Contact' => array(
|
||||
'className' => 'Contact',
|
||||
'joinTable' => 'contacts_methods',
|
||||
'foreignKey' => 'method_id',
|
||||
'associationForeignKey' => 'contact_id',
|
||||
'unique' => true,
|
||||
'conditions' => "method = 'EMAIL'",
|
||||
)
|
||||
);
|
||||
|
||||
function emailList() {
|
||||
return $this->find('list');
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
46
models/contact_phone.php
Normal file
46
models/contact_phone.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
class ContactPhone extends AppModel {
|
||||
|
||||
var $validate = array(
|
||||
'id' => array('numeric'),
|
||||
//'type' => array('inlist'),
|
||||
'phone' => array('phone'),
|
||||
'ext' => array('numeric')
|
||||
);
|
||||
|
||||
var $hasMany = array(
|
||||
'ContactsMethod' => array(
|
||||
'foreignKey' => 'method_id',
|
||||
'conditions' => "method = 'PHONE'",
|
||||
)
|
||||
);
|
||||
|
||||
var $hasAndBelongsToMany = array(
|
||||
'Contact' => array(
|
||||
'className' => 'Contact',
|
||||
'joinTable' => 'contacts_methods',
|
||||
'foreignKey' => 'method_id',
|
||||
'associationForeignKey' => 'contact_id',
|
||||
'unique' => true,
|
||||
'conditions' => "method = 'PHONE'",
|
||||
)
|
||||
);
|
||||
|
||||
function phoneList() {
|
||||
$results = $this->find('all',
|
||||
array('contain' => false,
|
||||
'fields' => array('id', 'phone', 'ext'),
|
||||
'order' => array('phone', 'ext')));
|
||||
|
||||
App::Import('Helper', 'Format');
|
||||
$list = array();
|
||||
foreach ($results as $key => $val) {
|
||||
$list[$val['ContactPhone']['id']]
|
||||
= FormatHelper::phone($val['ContactPhone']['phone'],
|
||||
$val['ContactPhone']['ext']);
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
11
models/contacts_customer.php
Normal file
11
models/contacts_customer.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
class ContactsCustomer extends AppModel {
|
||||
var $primaryKey = false;
|
||||
|
||||
var $belongsTo = array(
|
||||
'Contact',
|
||||
'Customer',
|
||||
);
|
||||
|
||||
}
|
||||
?>
|
||||
25
models/contacts_method.php
Normal file
25
models/contacts_method.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
class ContactsMethod extends AppModel {
|
||||
var $primaryKey = false;
|
||||
|
||||
var $belongsTo = array(
|
||||
'Contact',
|
||||
'ContactAddress' => array(
|
||||
'foreignKey' => 'method_id',
|
||||
'conditions' => "method = 'ADDRESS'",
|
||||
//'unique' => true,
|
||||
),
|
||||
'ContactPhone' => array(
|
||||
'foreignKey' => 'method_id',
|
||||
'conditions' => "method = 'PHONE'",
|
||||
//'unique' => true,
|
||||
),
|
||||
'ContactEmail' => array(
|
||||
'foreignKey' => 'method_id',
|
||||
'conditions' => "method = 'EMAIL'",
|
||||
//'unique' => true,
|
||||
),
|
||||
);
|
||||
|
||||
}
|
||||
?>
|
||||
377
models/customer.php
Normal file
377
models/customer.php
Normal file
@@ -0,0 +1,377 @@
|
||||
<?php
|
||||
class Customer extends AppModel {
|
||||
|
||||
var $name = 'Customer';
|
||||
var $validate = array(
|
||||
'id' => array('numeric'),
|
||||
'name' => array('notempty'),
|
||||
);
|
||||
|
||||
var $belongsTo = array(
|
||||
'PrimaryContact' => array(
|
||||
'className' => 'Contact',
|
||||
),
|
||||
);
|
||||
|
||||
var $hasMany = array(
|
||||
'CurrentLease' => array(
|
||||
'className' => 'Lease',
|
||||
'conditions' => 'CurrentLease.close_date IS NULL',
|
||||
),
|
||||
'Lease',
|
||||
'StatementEntry',
|
||||
'ContactsCustomer',
|
||||
|
||||
'Transaction',
|
||||
);
|
||||
|
||||
var $hasAndBelongsToMany = array(
|
||||
'Contact',
|
||||
);
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: accountId
|
||||
* - Returns the account ID for the given customer
|
||||
*/
|
||||
function accountId($id) {
|
||||
$this->cacheQueries = true;
|
||||
$customer = $this->find('first',
|
||||
array('contain' => false,
|
||||
'fields' => array('account_id'),
|
||||
'conditions' => array(array('Customer.id' => $id))));
|
||||
$this->cacheQueries = false;
|
||||
|
||||
return $customer['Customer']['account_id'];
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: leaseIds
|
||||
* - Returns the lease IDs for the given customer
|
||||
*/
|
||||
function leaseIds($id) {
|
||||
$this->cacheQueries = true;
|
||||
$customer = $this->find('first',
|
||||
array('contain' =>
|
||||
array('Lease' => array('fields' => array('id'))),
|
||||
'fields' => array(),
|
||||
'conditions' => array(array('Customer.id' => $id))));
|
||||
$this->cacheQueries = false;
|
||||
|
||||
$ids = array();
|
||||
foreach ($customer['Lease'] AS $lease)
|
||||
$ids[] = $lease['id'];
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: securityDeposits
|
||||
* - Returns an array of security deposit entries
|
||||
*/
|
||||
function securityDeposits($id, $query = null) {
|
||||
$this->prEnter(compact('id', 'query'));
|
||||
$this->queryInit($query);
|
||||
|
||||
$query['conditions'][] = array('StatementEntry.customer_id' => $id);
|
||||
$query['conditions'][] = array('StatementEntry.account_id' =>
|
||||
$this->StatementEntry->Account->securityDepositAccountID());
|
||||
|
||||
$set = $this->StatementEntry->reconciledSet('CHARGE', $query, false, true);
|
||||
return $this->prReturn($set);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: securityDepositBalance
|
||||
* - Returns the balance of the customer security deposit(s)
|
||||
*/
|
||||
|
||||
function securityDepositBalance($id, $query = null) {
|
||||
$this->prEnter(compact('id', 'query'));
|
||||
$this->queryInit($query);
|
||||
|
||||
$sd_account_id =
|
||||
$this->StatementEntry->Account->securityDepositAccountID();
|
||||
|
||||
$squery = $query;
|
||||
$squery['conditions'][] = array('StatementEntry.customer_id' => $id);
|
||||
$squery['conditions'][] = array('StatementEntry.account_id' => $sd_account_id);
|
||||
$stats = $this->StatementEntry->stats(null, $squery);
|
||||
$this->pr(26, compact('squery', 'stats'));
|
||||
|
||||
// OK, we know now how much we charged for a security
|
||||
// deposit, as well as how much we received to pay for it.
|
||||
// Now we need to know if any has been released.
|
||||
// Yes... this sucks.
|
||||
$lquery = $query;
|
||||
$lquery['link'] = array('Transaction' =>
|
||||
array('fields' => array(),
|
||||
'Customer' =>
|
||||
(empty($query['link'])
|
||||
? array('fields' => array())
|
||||
: $query['link'])));
|
||||
$lquery['conditions'][] = array('Transaction.customer_id' => $id);
|
||||
$lquery['conditions'][] = array('LedgerEntry.account_id' => $sd_account_id);
|
||||
$lquery['conditions'][] = array('LedgerEntry.crdr' => 'DEBIT');
|
||||
$lquery['fields'][] = 'SUM(LedgerEntry.amount) AS total';
|
||||
$released = $this->StatementEntry->Transaction->LedgerEntry->find
|
||||
('first', $lquery);
|
||||
$this->pr(26, compact('lquery', 'released'));
|
||||
|
||||
return $this->prReturn($stats['Charge']['disbursement'] - $released[0]['total']);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: unreconciledCharges
|
||||
* - Returns charges have not yet been fully paid
|
||||
*/
|
||||
|
||||
function unreconciledCharges($id, $query = null) {
|
||||
$this->prEnter(compact('id', 'query'));
|
||||
$this->queryInit($query);
|
||||
|
||||
$query['conditions'][] = array('StatementEntry.customer_id' => $id);
|
||||
$set = $this->StatementEntry->reconciledSet('CHARGE', $query, true);
|
||||
return $this->prReturn($set);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* 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();
|
||||
if (!$I->saveContact(null, array('Contact' => $contact)))
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: update
|
||||
* - Update any cached or calculated fields
|
||||
*/
|
||||
function update($id) {
|
||||
$this->prEnter(compact('id'));
|
||||
|
||||
if (empty($id)) {
|
||||
$customers = $this->find('all', array('contain' => false, 'fields' => array('id')));
|
||||
foreach ($customers AS $customer) {
|
||||
// This SHOULDN'T happen, but check to be sure
|
||||
// or we'll get infinite recursion.
|
||||
if (empty($customer['Customer']['id']))
|
||||
continue;
|
||||
$this->update($customer['Customer']['id']);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// REVISIT <AP>: 20090812
|
||||
// updateLeaseCount is handled directly when needed.
|
||||
// Should we simplify by just doing it anyway?
|
||||
//$this->updateLeaseCount($id);
|
||||
|
||||
$current_leases =
|
||||
$this->find('all',
|
||||
// REVISIT <AP>: 20090816
|
||||
// Do we need to update leases other than the current ones?
|
||||
// It may be necessary. For example, a non-current lease
|
||||
// can still be hit with an NSF item. In that case, it
|
||||
// could have stale data if we look only to current leases.
|
||||
//array('link' => array('CurrentLease' => array('type' => 'INNER')),
|
||||
array('link' => array('Lease' => array('type' => 'INNER')),
|
||||
'conditions' => array('Customer.id' => $id)));
|
||||
|
||||
foreach ($current_leases AS $lease) {
|
||||
if (!empty($lease['CurrentLease']['id']))
|
||||
$this->Lease->update($lease['CurrentLease']['id']);
|
||||
if (!empty($lease['Lease']['id']))
|
||||
$this->Lease->update($lease['Lease']['id']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: updateLeaseCount
|
||||
* - Updates the internal lease count
|
||||
*/
|
||||
|
||||
function updateLeaseCount($id) {
|
||||
$this->id = $id;
|
||||
|
||||
$lease_count =
|
||||
$this->find('count',
|
||||
array('link' => array('Lease' => array('type' => 'INNER')),
|
||||
'conditions' => array('Customer.id' => $id)));
|
||||
$current_count =
|
||||
$this->find('count',
|
||||
array('link' => array('CurrentLease' => array('type' => 'INNER')),
|
||||
'conditions' => array('Customer.id' => $id)));
|
||||
|
||||
$this->saveField('lease_count', $lease_count);
|
||||
$this->saveField('current_lease_count', $current_count);
|
||||
$this->saveField('past_lease_count', $lease_count - $current_count);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: balance
|
||||
* - Returns the balance of money owed on the lease
|
||||
*/
|
||||
|
||||
function balance($id) {
|
||||
$stats = $this->stats($id);
|
||||
return $stats['balance'];
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: stats
|
||||
* - Returns summary data from the requested customer.
|
||||
*/
|
||||
|
||||
function stats($id = null, $query = null) {
|
||||
//$this->prFunctionLevel(20);
|
||||
$this->prEnter(compact('id', 'query'));
|
||||
if (!$id)
|
||||
return $this->prExit(null);
|
||||
|
||||
$this->queryInit($query);
|
||||
|
||||
// REVISIT <AP>: 20090725
|
||||
// We'll need to go directly to the statement entries if
|
||||
// transactions are not always associated with the customer.
|
||||
// This could happen if either we remove the customer_id
|
||||
// field from Transaction, or we allow multiple customers
|
||||
// to be part of the same transaction (essentially making
|
||||
// the Transaction.customer_id meaningless).
|
||||
|
||||
/* $stats = $this->StatementEntry->find */
|
||||
/* ('first', array */
|
||||
/* ('contain' => false, */
|
||||
/* 'fields' => $this->StatementEntry->chargeDisbursementFields(true), */
|
||||
/* 'conditions' => array('StatementEntry.customer_id' => $id), */
|
||||
/* )); */
|
||||
|
||||
$find_stats = $this->StatementEntry->find
|
||||
('first', array
|
||||
('contain' => false,
|
||||
'fields' => $this->StatementEntry->chargeDisbursementFields(true),
|
||||
'conditions' => array('StatementEntry.customer_id' => $id),
|
||||
));
|
||||
$find_stats = $find_stats[0];
|
||||
$this->pr(17, compact('find_stats'));
|
||||
|
||||
$tquery = $query;
|
||||
$tquery['conditions'][] = array('StatementEntry.customer_id' => $id);
|
||||
$statement_stats = $this->StatementEntry->stats(null, $tquery);
|
||||
$statement_stats['balance'] = $statement_stats['Charge']['balance'];
|
||||
$this->pr(17, compact('statement_stats'));
|
||||
|
||||
$tquery = $query;
|
||||
//$tquery['conditions'][] = array('StatementEntry.customer_id' => $id);
|
||||
$tquery['conditions'][] = array('Transaction.customer_id' => $id);
|
||||
$transaction_stats = $this->Transaction->stats(null, $tquery);
|
||||
$transaction_stats += $transaction_stats['StatementEntry'];
|
||||
$this->pr(17, compact('transaction_stats'));
|
||||
|
||||
$tquery = $query;
|
||||
//$tquery['conditions'][] = array('StatementEntry.customer_id' => $id);
|
||||
$tquery['conditions'][] = array('Transaction.customer_id' => $id);
|
||||
$ar_transaction_stats = $this->Transaction->stats(null, $tquery,
|
||||
$this->Transaction->Account->accountReceivableAccountID());
|
||||
$ar_transaction_stats += $ar_transaction_stats['LedgerEntry'];
|
||||
$this->pr(17, compact('ar_transaction_stats'));
|
||||
|
||||
//$stats = $ar_transaction_stats;
|
||||
$stats = $find_stats;
|
||||
return $this->prReturn($stats);
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
109
models/double_entry.php
Normal file
109
models/double_entry.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
class DoubleEntry extends AppModel {
|
||||
|
||||
var $belongsTo = array(
|
||||
'DebitEntry' => array(
|
||||
'className' => 'LedgerEntry',
|
||||
),
|
||||
'CreditEntry' => array(
|
||||
'className' => 'LedgerEntry',
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: verifyDoubleEntry
|
||||
* - Verifies consistenty of new double entry data
|
||||
* (not in a pre-existing double entry)
|
||||
*/
|
||||
function verifyDoubleEntry($entry1, $entry2, $entry1_tender = null) {
|
||||
/* pr(array("DoubleEntry::verifyDoubleEntry()" */
|
||||
/* => compact('entry1', 'entry2', 'entry1_tender'))); */
|
||||
|
||||
$LE = new LedgerEntry();
|
||||
if (!$LE->verifyLedgerEntry($entry1, $entry1_tender)) {
|
||||
/* pr(array("DoubleEntry::verifyDoubleEntry()" */
|
||||
/* => "Entry1 verification failed")); */
|
||||
return false;
|
||||
}
|
||||
if (!$LE->verifyLedgerEntry($entry2)) {
|
||||
/* pr(array("DoubleEntry::verifyDoubleEntry()" */
|
||||
/* => "Entry2 verification failed")); */
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(($entry1['crdr'] === 'DEBIT' && $entry2['crdr'] === 'CREDIT') ||
|
||||
($entry1['crdr'] === 'CREDIT' && $entry2['crdr'] === 'DEBIT')) ||
|
||||
($entry1['amount'] != $entry2['amount'])) {
|
||||
/* pr(array("DoubleEntry::verifyDoubleEntry()" */
|
||||
/* => "Double Entry verification failed")); */
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: addDoubleEntry
|
||||
* - Inserts new Double Entry into the database
|
||||
*/
|
||||
|
||||
function addDoubleEntry($entry1, $entry2, $entry1_tender = null) {
|
||||
//$this->prFunctionLevel(16);
|
||||
$this->prEnter(compact('entry1', 'entry2', 'entry1_tender'));
|
||||
|
||||
$ret = array();
|
||||
if (!$this->verifyDoubleEntry($entry1, $entry2, $entry1_tender))
|
||||
return $this->prReturn(array('error' => true) + $ret);
|
||||
|
||||
// Handle the case where a double entry involves the same
|
||||
// exact ledger. This would not serve any useful purpose.
|
||||
// It is not, however, an error. It is semantically correct
|
||||
// just not really logically correct. To make this easier,
|
||||
// just ensure ledger_id is set for each entry, even though
|
||||
// it would be handled later by the LedgerEntry model.
|
||||
//array($entry1, $entry2) AS &$entry) {
|
||||
for ($i=1; $i <= 2; ++$i) {
|
||||
if (empty(${'entry'.$i}['ledger_id']))
|
||||
${'entry'.$i}['ledger_id'] =
|
||||
$this->DebitEntry->Account->currentLedgerID(${'entry'.$i}['account_id']);
|
||||
}
|
||||
if ($entry1['ledger_id'] == $entry2['ledger_id'])
|
||||
return $this->prReturn(array('error' => false));
|
||||
|
||||
// Since this model only relates to DebitEntry and CreditEntry...
|
||||
$LE = new LedgerEntry();
|
||||
|
||||
// Add the first ledger entry to the database
|
||||
$result = $LE->addLedgerEntry($entry1, $entry1_tender);
|
||||
$ret['Entry1'] = $result;
|
||||
if ($result['error'])
|
||||
return $this->prReturn(array('error' => true) + $ret);
|
||||
|
||||
// Add the second ledger entry to the database
|
||||
$result = $LE->addLedgerEntry($entry2);
|
||||
$ret['Entry2'] = $result;
|
||||
if ($result['error'])
|
||||
return $this->prReturn(array('error' => true) + $ret);
|
||||
|
||||
// Now link them as a double entry
|
||||
$double_entry = array();
|
||||
$double_entry['debit_entry_id'] =
|
||||
($entry1['crdr'] === 'DEBIT') ? $ret['Entry1']['ledger_entry_id'] : $ret['Entry2']['ledger_entry_id'];
|
||||
$double_entry['credit_entry_id'] =
|
||||
($entry1['crdr'] === 'CREDIT') ? $ret['Entry1']['ledger_entry_id'] : $ret['Entry2']['ledger_entry_id'];
|
||||
|
||||
$ret['data'] = $double_entry;
|
||||
|
||||
$this->create();
|
||||
if (!$this->save($double_entry))
|
||||
return $this->prReturn(array('error' => true) + $ret);
|
||||
|
||||
$ret['double_entry_id'] = $this->id;
|
||||
return $this->prReturn($ret + array('error' => false));
|
||||
}
|
||||
}
|
||||
849
models/lease.php
Normal file
849
models/lease.php
Normal file
@@ -0,0 +1,849 @@
|
||||
<?php
|
||||
class Lease extends AppModel {
|
||||
|
||||
var $belongsTo = array(
|
||||
'LeaseType',
|
||||
'Unit',
|
||||
'Customer',
|
||||
'LateSchedule',
|
||||
);
|
||||
|
||||
var $hasMany = array(
|
||||
'StatementEntry',
|
||||
);
|
||||
|
||||
//var $default_log_level = array('log' => 30, 'show' => 30);
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: securityDeposits
|
||||
* - Returns an array of security deposit entries
|
||||
*/
|
||||
function securityDeposits($id, $query = null) {
|
||||
$this->prEnter(compact('id', 'query'));
|
||||
$this->queryInit($query);
|
||||
|
||||
$query['conditions'][] = array('StatementEntry.lease_id' => $id);
|
||||
$query['conditions'][] = array('StatementEntry.account_id' =>
|
||||
$this->StatementEntry->Account->securityDepositAccountID());
|
||||
|
||||
$set = $this->StatementEntry->reconciledSet('CHARGE', $query, false, true);
|
||||
return $this->prReturn($set);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: securityDepositBalance
|
||||
* - Returns the balance of the lease security deposit(s)
|
||||
*/
|
||||
|
||||
function securityDepositBalance($id, $query = null) {
|
||||
$this->prEnter(compact('id', 'query'));
|
||||
$this->queryInit($query);
|
||||
|
||||
// REVISIT <AP>: 20090807
|
||||
// Let's try simplifying the security deposit issue.
|
||||
// Presume that security deposits are NOT used at all,
|
||||
// until the customer moves out of the unit. At that
|
||||
// time, the ENTIRE deposit is converted to customer
|
||||
// credit. Piece of cake.
|
||||
// For more information, see file revision history,
|
||||
// including the revision just before this, r503.
|
||||
|
||||
$this->id = $id;
|
||||
$moveout_date = $this->field('moveout_date');
|
||||
if (!empty($moveout_date))
|
||||
return $this->prReturn(0);
|
||||
|
||||
$query['conditions'][] = array('StatementEntry.lease_id' => $id);
|
||||
$query['conditions'][] = array('StatementEntry.account_id' =>
|
||||
$this->StatementEntry->Account->securityDepositAccountID());
|
||||
|
||||
$stats = $this->StatementEntry->stats(null, $query);
|
||||
return $this->prReturn($stats['Charge']['disbursement']);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: releaseSecurityDeposits
|
||||
* - Releases all security deposits associated with this lease.
|
||||
* That simply makes a disbursement out of them, which can be used
|
||||
* to pay outstanding customer charges, or simply to become
|
||||
* a customer surplus (customer credit).
|
||||
*/
|
||||
function releaseSecurityDeposits($id, $stamp = null, $query = null) {
|
||||
//$this->prFunctionLevel(30);
|
||||
$this->prEnter(compact('id', 'stamp', 'query'));
|
||||
|
||||
$secdeps = $this->securityDeposits($id, $query);
|
||||
$secdeps = $secdeps['entries'];
|
||||
$this->pr(20, compact('secdeps'));
|
||||
|
||||
// If there are no paid security deposits, then
|
||||
// we can consider all security deposits released.
|
||||
if (count($secdeps) == 0)
|
||||
return $this->prReturn(true);
|
||||
|
||||
// Build a transaction
|
||||
$release = array('Transaction' => array(), 'Entry' => array());
|
||||
$release['Transaction']['stamp'] = $stamp;
|
||||
$release['Transaction']['comment'] = "Security Deposit Release";
|
||||
foreach ($secdeps AS $charge) {
|
||||
if ($charge['StatementEntry']['type'] !== 'CHARGE')
|
||||
die("INTERNAL ERROR: SECURITY DEPOSIT IS NOT CHARGE");
|
||||
|
||||
// Since security deposits are being released, this also means
|
||||
// any unpaid (or only partially paid) security deposit should
|
||||
// have the remaining balance reversed.
|
||||
if ($charge['StatementEntry']['balance'] > 0)
|
||||
$this->StatementEntry->reverse($charge['StatementEntry']['id'], true, $stamp);
|
||||
|
||||
$release['Entry'][] =
|
||||
array('amount' => $charge['StatementEntry']['reconciled'],
|
||||
'account_id' => $this->StatementEntry->Account->securityDepositAccountID(),
|
||||
'comment' => "Released Security Deposit",
|
||||
);
|
||||
}
|
||||
|
||||
$customer_id = $secdeps[0]['StatementEntry']['customer_id'];
|
||||
$lease_id = $secdeps[0]['StatementEntry']['lease_id'];
|
||||
|
||||
// Add receipt of the security deposit funds. Do NOT
|
||||
// flag them as part of the lease, as all received funds
|
||||
// are only associated with the customer, for future
|
||||
// (or present) disbursement on any lease.
|
||||
$result = $this->StatementEntry->Transaction->addReceipt
|
||||
($release, $customer_id, null);
|
||||
|
||||
return $this->prReturn($result);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: rentLastCharges
|
||||
* - Returns a list of rent charges from this lease that
|
||||
* do not have sequential followup charges. Under normal
|
||||
* circumstances, there would only be one entry, which is
|
||||
* the most recent rent charge. However, it's possible
|
||||
* that there are several, indicating a problem with lease.
|
||||
*/
|
||||
|
||||
function rentLastCharges($id) {
|
||||
$this->prEnter(compact('id'));
|
||||
$rent_account_id = $this->StatementEntry->Account->rentAccountID();
|
||||
$entries = $this->find
|
||||
('all',
|
||||
array('link' =>
|
||||
array(// Models
|
||||
'StatementEntry',
|
||||
|
||||
'SEx' =>
|
||||
array('class' => 'StatementEntry',
|
||||
'fields' => array(),
|
||||
'conditions' => array
|
||||
('SEx.effective_date = DATE_ADD(StatementEntry.through_date, INTERVAL 1 day)',
|
||||
'SEx.lease_id = StatementEntry.lease_id',
|
||||
'SEx.reverse_transaction_id IS NULL',
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
//'fields' => array('id', 'amount', 'effective_date', 'through_date'),
|
||||
'fields' => array(),
|
||||
'conditions' => array(array('Lease.id' => $id),
|
||||
array('StatementEntry.type' => 'CHARGE'),
|
||||
array('StatementEntry.account_id' => $rent_account_id),
|
||||
array('StatementEntry.reverse_transaction_id IS NULL'),
|
||||
array('SEx.id' => null),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
return $this->prReturn($entries);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: lateCharges
|
||||
* - Returns a list of late charges from this lease
|
||||
*/
|
||||
|
||||
function lateCharges($id) {
|
||||
$this->prEnter(compact('id'));
|
||||
$late_account_id = $this->StatementEntry->Account->lateChargeAccountID();
|
||||
$entries = $this->StatementEntry->find
|
||||
('all',
|
||||
array('link' =>
|
||||
array(// Models
|
||||
'Lease',
|
||||
),
|
||||
|
||||
//'fields' => array('id', 'amount', 'effective_date', 'through_date'),
|
||||
'conditions' => array(array('Lease.id' => $id),
|
||||
array('StatementEntry.type' => 'CHARGE'),
|
||||
array('StatementEntry.account_id' => $late_account_id),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
return $this->prReturn($entries);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: rentChargeGaps
|
||||
* - Checks for gaps in rent charges
|
||||
*/
|
||||
|
||||
function rentChargeGaps($id) {
|
||||
$this->prEnter(compact('id'));
|
||||
$entries = $this->rentLastCharges($id);
|
||||
if ($entries && count($entries) > 1)
|
||||
return $this->prReturn(true);
|
||||
return $this->prReturn(false);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: rentChargeThrough
|
||||
* - Determines the date that rent has been charged through
|
||||
* Returns one of:
|
||||
* null: There are gaps in the charges
|
||||
* false: There are not yet any charges
|
||||
* date: The date rent has been charged through
|
||||
*/
|
||||
|
||||
function rentChargeThrough($id) {
|
||||
$this->prEnter(compact('id'));
|
||||
$entries = $this->rentLastCharges($id);
|
||||
if (!$entries)
|
||||
return $this->prReturn(false);
|
||||
if (count($entries) != 1)
|
||||
return $this->prReturn(null);
|
||||
return $this->prReturn($entries[0]['StatementEntry']['through_date']);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: rentPaidThrough
|
||||
* - Determines the date of the first unpaid rent
|
||||
*/
|
||||
|
||||
function rentPaidThrough($id) {
|
||||
$this->prEnter(compact('id'));
|
||||
$rent_account_id = $this->StatementEntry->Account->rentAccountID();
|
||||
|
||||
// First, see if we can find any unpaid entries. Of course,
|
||||
// the first unpaid entry gives us a very direct indication
|
||||
// of when the customer is paid up through, which is 1 day
|
||||
// prior to the effective date of that first unpaid charge.
|
||||
$rent = $this->StatementEntry->reconciledSet
|
||||
('CHARGE',
|
||||
array('fields' =>
|
||||
array('StatementEntry.*',
|
||||
'DATE_SUB(StatementEntry.effective_date, INTERVAL 1 DAY) AS paid_through',
|
||||
),
|
||||
|
||||
'conditions' =>
|
||||
array(array('StatementEntry.lease_id' => $id),
|
||||
array('StatementEntry.account_id' => $rent_account_id),
|
||||
array('StatementEntry.reverse_transaction_id IS NULL'),
|
||||
),
|
||||
|
||||
'order' => array('StatementEntry.effective_date'),
|
||||
),
|
||||
true);
|
||||
$this->pr(20, $rent, "Unpaid rent");
|
||||
|
||||
if ($rent['entries'])
|
||||
return $this->prReturn($rent['entries'][0]['StatementEntry']['paid_through']);
|
||||
|
||||
|
||||
// If we don't have any unpaid charges (great!), then the
|
||||
// customer is paid up through the last day of the last
|
||||
// charge. So, search for paid charges, which already
|
||||
// have the paid through date saved as part of the entry.
|
||||
$rent = $this->StatementEntry->reconciledSet
|
||||
('CHARGE',
|
||||
array('conditions' =>
|
||||
array(array('StatementEntry.lease_id' => $id),
|
||||
array('StatementEntry.account_id' => $rent_account_id),
|
||||
array('StatementEntry.reverse_transaction_id IS NULL'),
|
||||
),
|
||||
|
||||
'order' => array('StatementEntry.through_date DESC'),
|
||||
),
|
||||
false);
|
||||
$this->pr(20, $rent, "Paid rent");
|
||||
|
||||
if ($rent['entries'])
|
||||
return $this->prReturn($rent['entries'][0]['StatementEntry']['through_date']);
|
||||
|
||||
|
||||
// After all that, having found that there are no unpaid
|
||||
// charges, and in fact, no paid charges either, we cannot
|
||||
// possibly say when the customer is paid through.
|
||||
return $this->prReturn(null);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: assessMonthlyRent
|
||||
* - Charges rent for the month, if not already charged.
|
||||
*/
|
||||
|
||||
function assessMonthlyRent($id, $date = null) {
|
||||
$this->prEnter(compact('id', 'date'));
|
||||
$this->id = $id;
|
||||
|
||||
if (empty($date))
|
||||
$date = time();
|
||||
|
||||
if (is_string($date))
|
||||
$date = strtotime($date);
|
||||
|
||||
// REVISIT <AP>: 20090808
|
||||
// Anniversary Billing not supported
|
||||
$anniversary = 0 && $this->field('anniversary_billing');
|
||||
if (empty($anniversary)) {
|
||||
$date_parts = getdate($date);
|
||||
$date = mktime(0, 0, 0, $date_parts['mon'], 1, $date_parts['year']);
|
||||
}
|
||||
|
||||
// Make sure we're not trying to assess rent on a closed lease
|
||||
$close_date = $this->field('close_date');
|
||||
$this->pr(17, compact('close_date'));
|
||||
if (!empty($close_date))
|
||||
return $this->prReturn(null);
|
||||
|
||||
// Don't assess rent after customer has moved out
|
||||
$moveout_date = $this->field('moveout_date');
|
||||
$this->pr(17, compact('moveout_date'));
|
||||
if (!empty($moveout_date) && strtotime($moveout_date) < $date)
|
||||
return $this->prReturn(null);
|
||||
|
||||
// Determine when the customer has already been charged through
|
||||
// and, of course, don't charge them if they've already been.
|
||||
$charge_through_date = strtotime($this->rentChargeThrough($id));
|
||||
$this->pr(17, compact('date', 'charge_through_date')
|
||||
+ array('date_str' => date('Y-m-d', $date),
|
||||
'charge_through_date_str' => date('Y-m-d', $charge_through_date)));
|
||||
if ($charge_through_date >= $date)
|
||||
return $this->prReturn(null);
|
||||
|
||||
// OK, it seems we're going to go ahead and charge the customer
|
||||
// on this lease. Calculate the new charge through date, which
|
||||
// is 1 day shy of 1 month from $date. For example, if we're
|
||||
// charging for 8/1/09, charge through will be 8/31/09, and
|
||||
// charging for 8/15/09, charge through will be 9/14/09.
|
||||
$date_parts = getdate($date);
|
||||
$charge_through_date = mktime(0, 0, 0,
|
||||
$date_parts['mon']+1,
|
||||
$date_parts['mday']-1,
|
||||
$date_parts['year']);
|
||||
|
||||
// Build the invoice transaction
|
||||
$invoice = array('Transaction' => array(), 'Entry' => array());
|
||||
// REVISIT <AP>: 20090808
|
||||
// Keeping Transaction.stamp until the existing facility
|
||||
// is up to date. Then we want the stamp to be now()
|
||||
// (and so can just delete the next line).
|
||||
$invoice['Transaction']['stamp'] = date('Y-m-d', $date);
|
||||
$invoice['Entry'][] =
|
||||
array('effective_date' => date('Y-m-d', $date),
|
||||
'through_date' => date('Y-m-d', $charge_through_date),
|
||||
'amount' => $this->field('rent'),
|
||||
'account_id' => $this->StatementEntry->Account->rentAccountId(),
|
||||
);
|
||||
|
||||
// Record the invoice and return the result
|
||||
$this->pr(21, compact('invoice'));
|
||||
$result = $this->StatementEntry->Transaction->addInvoice
|
||||
($invoice, null, $id);
|
||||
return $this->prReturn($result);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: assessMonthlyRentAll
|
||||
* - Ensures rent has been charged on all open leases
|
||||
*/
|
||||
|
||||
function assessMonthlyRentAll($date = null) {
|
||||
$this->prEnter(compact('date'));
|
||||
$leases = $this->find
|
||||
('all', array('contain' => false,
|
||||
'conditions' => array('Lease.close_date' => null),
|
||||
));
|
||||
|
||||
$ret = array('Lease' => array());
|
||||
foreach ($leases AS $lease) {
|
||||
$result = $this->assessMonthlyRent($lease['Lease']['id'], $date);
|
||||
$ret['Lease'][$lease['Lease']['id']] = $result;
|
||||
if ($result['error'])
|
||||
$ret['error'] = true;
|
||||
}
|
||||
return $this->prReturn($ret + array('error' => false));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: assessMonthlyLate
|
||||
* - Assess late charges for the month, if not already charged.
|
||||
*/
|
||||
|
||||
function assessMonthlyLate($id, $date = null) {
|
||||
$this->prEnter(compact('id', 'date'));
|
||||
$this->id = $id;
|
||||
|
||||
if (empty($date))
|
||||
$date = time();
|
||||
|
||||
if (is_string($date))
|
||||
$date = strtotime($date);
|
||||
|
||||
// REVISIT <AP>: 20090808
|
||||
// Anniversary Billing not supported
|
||||
$anniversary = 0 && $this->field('anniversary_billing');
|
||||
if (empty($anniversary)) {
|
||||
$date_parts = getdate($date);
|
||||
$date = mktime(0, 0, 0, $date_parts['mon'], 11, $date_parts['year']);
|
||||
}
|
||||
|
||||
// Don't assess a late charge if the late charge date hasn't
|
||||
// even come yet. This is questionable whether we really
|
||||
// should restrict, since the user could know what they're
|
||||
// doing, and/or the server clock could be off (although that
|
||||
// would certainly have much larger ramifications). But, the
|
||||
// fact is that this check likely handles the vast majority
|
||||
// of the expected behavior, and presents an issue for very
|
||||
// few users, if any at all.
|
||||
if ($date > time())
|
||||
return $this->prReturn(null);
|
||||
|
||||
// Make sure we're not trying to assess late charges on a closed lease
|
||||
$close_date = $this->field('close_date');
|
||||
$this->pr(17, compact('close_date'));
|
||||
if (!empty($close_date))
|
||||
return $this->prReturn(null);
|
||||
|
||||
// Don't assess late charges after customer has moved out
|
||||
$moveout_date = $this->field('moveout_date');
|
||||
$this->pr(17, compact('moveout_date'));
|
||||
if (!empty($moveout_date) && strtotime($moveout_date) < $date)
|
||||
return $this->prReturn(null);
|
||||
|
||||
// Determine when the customer has been charged through for rent
|
||||
// and don't mark them as late if they haven't even been charged rent
|
||||
$charge_through_date = strtotime($this->rentChargeThrough($id));
|
||||
$this->pr(17, compact('date', 'charge_through_date')
|
||||
+ array('date_str' => date('Y-m-d', $date),
|
||||
'charge_through_date_str' => date('Y-m-d', $charge_through_date)));
|
||||
if ($charge_through_date <= $date)
|
||||
return $this->prReturn(null);
|
||||
|
||||
// Determine if the customer is actually late. This is based on
|
||||
// when they've paid through, plus 10 days before they're late.
|
||||
// REVISIT <AP>: 20090813
|
||||
// Of course, 10 days is a terrible hardcode. This should be
|
||||
// driven from the late schedule, saved as part of the lease
|
||||
// (when finally implemented).
|
||||
$paid_through_date = strtotime($this->rentPaidThrough($id));
|
||||
$this->pr(17, compact('date', 'paid_through_date')
|
||||
+ array('date_str' => date('Y-m-d', $date),
|
||||
'paid_through_date_str' => date('Y-m-d', $paid_through_date)));
|
||||
$date_parts = getdate($paid_through_date);
|
||||
$paid_through_date = mktime(0, 0, 0, $date_parts['mon'], $date_parts['mday']+10, $date_parts['year']);
|
||||
if ($paid_through_date >= $date)
|
||||
return $this->prReturn(null);
|
||||
|
||||
// Determine if the customer has already been charged a late fee
|
||||
// and, of course, don't charge them if they've already been.
|
||||
$late_charges = $this->lateCharges($id);
|
||||
foreach ($late_charges AS $late) {
|
||||
if (strtotime($late['StatementEntry']['effective_date']) == $date)
|
||||
return $this->prReturn(null);
|
||||
}
|
||||
|
||||
// Build the invoice transaction
|
||||
$invoice = array('Transaction' => array(), 'Entry' => array());
|
||||
// REVISIT <AP>: 20090808
|
||||
// Keeping Transaction.stamp until the existing facility
|
||||
// is up to date. Then we want the stamp to be now()
|
||||
// (and so can just delete the next line).
|
||||
$invoice['Transaction']['stamp'] = date('Y-m-d', $date);
|
||||
$invoice['Entry'][] =
|
||||
array('effective_date' => date('Y-m-d', $date),
|
||||
'amount' => 10,
|
||||
'account_id' => $this->StatementEntry->Account->lateChargeAccountId(),
|
||||
);
|
||||
|
||||
// Record the invoice and return the result
|
||||
$this->pr(21, compact('invoice'));
|
||||
$result = $this->StatementEntry->Transaction->addInvoice
|
||||
($invoice, null, $id);
|
||||
return $this->prReturn($result);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: assessMonthlyLateAll
|
||||
* - Ensures rent has been charged on all open leases
|
||||
*/
|
||||
|
||||
function assessMonthlyLateAll($date = null) {
|
||||
$this->prEnter(compact('date'));
|
||||
$leases = $this->find
|
||||
('all', array('contain' => false,
|
||||
'conditions' => array('Lease.close_date' => null),
|
||||
));
|
||||
|
||||
$ret = array('Lease' => array());
|
||||
foreach ($leases AS $lease) {
|
||||
$result = $this->assessMonthlyLate($lease['Lease']['id'], $date);
|
||||
$ret['Lease'][$lease['Lease']['id']] = $result;
|
||||
if ($result['error'])
|
||||
$ret['error'] = true;
|
||||
}
|
||||
return $this->prReturn($ret + array('error' => false));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* functions: delinquency
|
||||
* - SQL fragments to determine whether a lease is delinquent
|
||||
*/
|
||||
|
||||
function conditionDelinquent($table_name = 'Lease') {
|
||||
if (empty($table_name)) $t = ''; else $t = $table_name . '.';
|
||||
return ("({$t}close_date IS NULL AND" .
|
||||
" NOW() > DATE_ADD({$t}paid_through_date, INTERVAL 10 DAY))");
|
||||
}
|
||||
|
||||
function delinquentDaysSQL($table_name = 'Lease') {
|
||||
if (empty($table_name)) $t = ''; else $t = $table_name . '.';
|
||||
return ("IF(" . $this->conditionDelinquent($table_name) . "," .
|
||||
" DATEDIFF(NOW(), {$t}paid_through_date)-1," .
|
||||
" NULL)");
|
||||
}
|
||||
|
||||
function delinquentField($table_name = 'Lease') {
|
||||
return ($this->delinquentDaysSQL($table_name) . " AS 'delinquent'");
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: moveIn
|
||||
* - Moves the specified customer into the specified lease
|
||||
*/
|
||||
|
||||
function moveIn($customer_id, $unit_id,
|
||||
$deposit = null, $rent = null,
|
||||
$stamp = null, $comment = null)
|
||||
{
|
||||
$this->prEnter(compact('customer_id', 'unit_id',
|
||||
'deposit', 'rent', 'stamp', 'comment'));
|
||||
|
||||
$lt = $this->LeaseType->find('first',
|
||||
array('conditions' =>
|
||||
array('code' => 'SL')));
|
||||
|
||||
// Use NOW if not given a movein date
|
||||
if (!isset($stamp))
|
||||
$stamp = date('Y-m-d G:i:s');
|
||||
|
||||
if (!$comment)
|
||||
$comment = null;
|
||||
|
||||
if (!isset($deposit) || !isset($rent)) {
|
||||
$rates = $this->Unit->find
|
||||
('first',
|
||||
array('contain' =>
|
||||
array('UnitSize' =>
|
||||
array('deposit', 'rent'),
|
||||
),
|
||||
'fields' => array('deposit', 'rent'),
|
||||
'conditions' => array('Unit.id' => $unit_id),
|
||||
));
|
||||
|
||||
$deposit =
|
||||
(isset($deposit)
|
||||
? $deposit
|
||||
: (isset($rates['Unit']['deposit'])
|
||||
? $rates['Unit']['deposit']
|
||||
: (isset($rates['UnitSize']['deposit'])
|
||||
? $rates['UnitSize']['deposit']
|
||||
: 0)));
|
||||
|
||||
$rent =
|
||||
(isset($rent)
|
||||
? $rent
|
||||
: (isset($rates['Unit']['rent'])
|
||||
? $rates['Unit']['rent']
|
||||
: (isset($rates['UnitSize']['rent'])
|
||||
? $rates['UnitSize']['rent']
|
||||
: 0)));
|
||||
}
|
||||
|
||||
|
||||
// Save this new lease.
|
||||
$this->create();
|
||||
if (!$this->save(array('lease_type_id' => $lt['LeaseType']['id'],
|
||||
'unit_id' => $unit_id,
|
||||
'customer_id' => $customer_id,
|
||||
'lease_date' => $stamp,
|
||||
'movein_date' => $stamp,
|
||||
'deposit' => $deposit,
|
||||
'rent' => $rent,
|
||||
'comment' => $comment), false)) {
|
||||
return $this->prReturn(null);
|
||||
}
|
||||
|
||||
// Set the lease number to be the same as the lease ID
|
||||
$this->id;
|
||||
$this->saveField('number', $this->id);
|
||||
|
||||
// Update the current lease count for the customer
|
||||
$this->Customer->updateLeaseCount($customer_id);
|
||||
|
||||
// Update the unit status
|
||||
$this->Unit->updateStatus($unit_id, 'OCCUPIED');
|
||||
|
||||
// REVISIT <AP>: 20090702
|
||||
// We need to assess the security deposit charge,
|
||||
// and probably rent as well. Rent, however, will
|
||||
// require user parameters to indicate whether it
|
||||
// was waived, pro-rated, etc.
|
||||
|
||||
// Return the new lease ID
|
||||
return $this->prReturn($this->id);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: moveOut
|
||||
* - Moves the customer out of the specified lease
|
||||
*/
|
||||
|
||||
function moveOut($id, $status = 'VACANT',
|
||||
$stamp = null, $close = true)
|
||||
{
|
||||
$this->prEnter(compact('id', 'status', 'stamp', 'close'));
|
||||
|
||||
// Use NOW if not given a moveout date
|
||||
if (!isset($stamp))
|
||||
$stamp = date('Y-m-d G:i:s');
|
||||
|
||||
// Reset the data
|
||||
$this->create();
|
||||
$this->id = $id;
|
||||
|
||||
// Set the customer move-out date
|
||||
$this->data['Lease']['moveout_date'] = $stamp;
|
||||
|
||||
// Save it!
|
||||
$this->save($this->data, false);
|
||||
|
||||
// Release the security deposit(s)
|
||||
$this->releaseSecurityDeposits($id, $stamp);
|
||||
|
||||
// Close the lease, if so requested
|
||||
if ($close)
|
||||
$this->close($id, $stamp);
|
||||
|
||||
// Update the current lease count for the customer
|
||||
$this->Customer->updateLeaseCount($this->field('customer_id'));
|
||||
|
||||
// Finally, update the unit status
|
||||
$this->recursive = -1;
|
||||
$this->read();
|
||||
$this->Unit->updateStatus($this->data['Lease']['unit_id'], $status);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: close
|
||||
* - Closes the lease to further action
|
||||
*/
|
||||
|
||||
function close($id, $stamp = null) {
|
||||
$this->prEnter(compact('id', 'stamp'));
|
||||
|
||||
if (!$this->closeable($id))
|
||||
return $this->prReturn(false);
|
||||
|
||||
// Reset the data
|
||||
$this->create();
|
||||
$this->id = $id;
|
||||
|
||||
// Use NOW if not given a moveout date
|
||||
if (!isset($stamp))
|
||||
$stamp = date('Y-m-d G:i:s');
|
||||
|
||||
// Set the close date
|
||||
$this->data['Lease']['close_date'] = $stamp;
|
||||
|
||||
// Save it!
|
||||
$this->save($this->data, false);
|
||||
|
||||
// Update the current lease count for the customer
|
||||
$this->Customer->updateLeaseCount($this->field('customer_id'));
|
||||
|
||||
return $this->prReturn(true);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: closeable
|
||||
* - Indicates whether or not the lease can be closed
|
||||
*/
|
||||
|
||||
function closeable($id) {
|
||||
$this->prEnter(compact('id'));
|
||||
|
||||
$this->recursive = -1;
|
||||
$this->read(null, $id);
|
||||
|
||||
// We can't close a lease that's still in use
|
||||
if (!isset($this->data['Lease']['moveout_date']))
|
||||
return $this->prReturn(false);
|
||||
|
||||
// We can't close a lease that's already closed
|
||||
if (isset($this->data['Lease']['close_date']))
|
||||
return $this->prReturn(false);
|
||||
|
||||
// A lease can only be closed if there are no outstanding
|
||||
// security deposits ...
|
||||
if ($this->securityDepositBalance($id) != 0)
|
||||
return $this->prReturn(false);
|
||||
|
||||
// ... and if the account balance is zero.
|
||||
if ($this->balance($id) != 0)
|
||||
return $this->prReturn(false);
|
||||
|
||||
// Apparently this lease meets all the criteria!
|
||||
return $this->prReturn(true);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: refund
|
||||
* - Marks any lease balance as payable to the customer.
|
||||
*/
|
||||
|
||||
function refund($id, $stamp = null) {
|
||||
$this->prEnter(compact('id'));
|
||||
$balance = $this->balance($id);
|
||||
|
||||
if ($balance >= 0)
|
||||
return $this->prReturn(array('error' => true));
|
||||
|
||||
$balance *= -1;
|
||||
|
||||
// Build a transaction
|
||||
$refund = array('Transaction' => array(), 'Entry' => array());
|
||||
$refund['Transaction']['stamp'] = $stamp;
|
||||
$refund['Transaction']['comment'] = "Lease Refund";
|
||||
|
||||
$refund['Entry'][] =
|
||||
array('amount' => $balance);
|
||||
|
||||
$result = $this->StatementEntry->Transaction->addRefund
|
||||
($refund, null, $id);
|
||||
|
||||
return $this->prReturn($result);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: update
|
||||
* - Update any cached or calculated fields
|
||||
*/
|
||||
function update($id) {
|
||||
$this->prEnter(compact('id'));
|
||||
|
||||
$this->id = $id;
|
||||
$this->saveField('charge_through_date', $this->rentChargeThrough($id));
|
||||
$this->saveField('paid_through_date', $this->rentPaidThrough($id));
|
||||
|
||||
$moveout = $this->field('moveout_date');
|
||||
if (empty($moveout))
|
||||
$this->Unit->update($this->field('unit_id'));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: balance
|
||||
* - Returns the balance of money owed on the lease
|
||||
*/
|
||||
|
||||
function balance($id) {
|
||||
$this->prEnter(compact('id'));
|
||||
$stats = $this->stats($id);
|
||||
return $this->prReturn($stats['balance']);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: stats
|
||||
* - Returns summary data from the requested lease.
|
||||
*/
|
||||
|
||||
function stats($id = null, $query = null) {
|
||||
$this->prEnter(compact('id', 'query'));
|
||||
if (!$id)
|
||||
return $this->prReturn(null);
|
||||
|
||||
$find_stats = $this->StatementEntry->find
|
||||
('first', array
|
||||
('contain' => false,
|
||||
'fields' => $this->StatementEntry->chargeDisbursementFields(true),
|
||||
'conditions' => array('StatementEntry.lease_id' => $id),
|
||||
));
|
||||
$find_stats = $find_stats[0];
|
||||
return $this->prReturn($find_stats);
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
15
models/lease_type.php
Normal file
15
models/lease_type.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
class LeaseType extends AppModel {
|
||||
|
||||
var $name = 'LeaseType';
|
||||
var $validate = array(
|
||||
'id' => array('numeric'),
|
||||
'name' => array('notempty')
|
||||
);
|
||||
|
||||
var $hasMany = array(
|
||||
'Lease',
|
||||
);
|
||||
|
||||
}
|
||||
?>
|
||||
179
models/ledger.php
Normal file
179
models/ledger.php
Normal file
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
class Ledger extends AppModel {
|
||||
|
||||
var $belongsTo = array(
|
||||
'Account',
|
||||
'PriorLedger' => array('className' => 'Ledger'),
|
||||
'CloseTransaction' => array('className' => 'Transaction'),
|
||||
);
|
||||
|
||||
var $hasMany = array(
|
||||
'Transaction',
|
||||
'LedgerEntry',
|
||||
);
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: accountID
|
||||
* - Returns the account ID for the given ledger
|
||||
*/
|
||||
function accountID($id) {
|
||||
$this->cacheQueries = true;
|
||||
$item = $this->find('first', array
|
||||
('link' => array('Account'),
|
||||
'conditions' => array('Ledger.id' => $id),
|
||||
));
|
||||
$this->cacheQueries = false;
|
||||
//pr(compact('id', 'item'));
|
||||
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 closeLedgers($ids) {
|
||||
$ret = array('new_ledger_ids' => array());
|
||||
|
||||
$entries = array();
|
||||
foreach ($ids AS $id) {
|
||||
// Query stats to get the balance forward
|
||||
$stats = $this->stats($id);
|
||||
|
||||
// Populate fields from the current ledger
|
||||
$this->recursive = -1;
|
||||
$this->id = $id;
|
||||
$this->read();
|
||||
|
||||
// Build a new ledger to replace the current one
|
||||
$this->data['Ledger']['id'] = null;
|
||||
$this->data['Ledger']['close_transaction_id'] = null;
|
||||
$this->data['Ledger']['prior_ledger_id'] = $id;
|
||||
$this->data['Ledger']['comment'] = null;
|
||||
++$this->data['Ledger']['sequence'];
|
||||
$this->data['Ledger']['name'] =
|
||||
($this->data['Ledger']['account_id'] .
|
||||
'-' .
|
||||
$this->data['Ledger']['sequence']);
|
||||
|
||||
// Save the new ledger
|
||||
$this->id = null;
|
||||
if (!$this->save($this->data, false))
|
||||
return array('error' => true, 'new_ledger_data' => $this->data) + $ret;
|
||||
$ret['new_ledger_ids'][] = $this->id;
|
||||
|
||||
$entries[] = array('old_ledger_id' => $id,
|
||||
'new_ledger_id' => $this->id,
|
||||
'amount' => $stats['balance']);
|
||||
}
|
||||
|
||||
// Perform the close
|
||||
$result = $this->Transaction->addClose(array('Transaction' => array(),
|
||||
'Ledger' => $entries));
|
||||
$ret['Transaction'] = $result;
|
||||
if ($result['error'])
|
||||
return array('error' => true) + $ret;
|
||||
|
||||
return $ret + array('error' => false);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: debitCreditFields
|
||||
* - Returns the fields necessary to determine whether the queried
|
||||
* entries are a debit, or a credit, and also the effect each have
|
||||
* on the overall balance of the ledger.
|
||||
*/
|
||||
function debitCreditFields($sum = false, $balance = true,
|
||||
$entry_name = 'LedgerEntry', $account_name = 'Account') {
|
||||
return $this->LedgerEntry->debitCreditFields
|
||||
($sum, $balance, $entry_name, $account_name);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: ledgerEntries
|
||||
* - Returns an array of ledger entries that belong to a given
|
||||
* ledger. There is extra work done to establish debit/credit
|
||||
*/
|
||||
function ledgerEntries($ids, $query = null) {
|
||||
if (empty($ids))
|
||||
return null;
|
||||
|
||||
$entries = $this->LedgerEntry->find
|
||||
('all', array
|
||||
('link' => array('Ledger' => array('Account')),
|
||||
'fields' => array_merge(array("LedgerEntry.*"),
|
||||
$this->LedgerEntry->debitCreditFields()),
|
||||
'conditions' => array('LedgerEntry.ledger_id' => $ids),
|
||||
));
|
||||
|
||||
//pr(compact('entries'));
|
||||
return $entries;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: stats
|
||||
* - Returns summary data from the requested ledger.
|
||||
*/
|
||||
function stats($id, $query = null) {
|
||||
if (!$id)
|
||||
return null;
|
||||
|
||||
$this->queryInit($query);
|
||||
|
||||
if (!isset($query['link']['Account']))
|
||||
$query['link']['Account'] = array();
|
||||
if (!isset($query['link']['Account']['fields']))
|
||||
$query['link']['Account']['fields'] = array();
|
||||
if (!isset($query['fields']))
|
||||
$query['fields'] = array();
|
||||
|
||||
$query['fields'] = array_merge($query['fields'],
|
||||
$this->debitCreditFields(true));
|
||||
|
||||
$query['conditions'][] = array('LedgerEntry.ledger_id' => $id);
|
||||
$query['group'][] = 'LedgerEntry.ledger_id';
|
||||
|
||||
$stats = $this->LedgerEntry->find('first', $query);
|
||||
|
||||
// The fields are all tucked into the [0] index,
|
||||
// and the rest of the array is useless (empty).
|
||||
$stats = $stats[0];
|
||||
|
||||
// Make sure we have a member for debit/credit
|
||||
foreach(array('debits', 'credits') AS $crdr)
|
||||
if (!isset($stats[$crdr]))
|
||||
$stats[$crdr] = null;
|
||||
|
||||
// Make sure we have a non-null balance
|
||||
if (!isset($stats['balance']))
|
||||
$stats['balance'] = 0;
|
||||
|
||||
return $stats;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
177
models/ledger_entry.php
Normal file
177
models/ledger_entry.php
Normal file
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
class LedgerEntry extends AppModel {
|
||||
|
||||
var $belongsTo = array(
|
||||
'Transaction',
|
||||
'Account',
|
||||
'Ledger',
|
||||
);
|
||||
|
||||
var $hasOne = array(
|
||||
'Tender' => array(
|
||||
'dependent' => true,
|
||||
),
|
||||
'DebitDoubleEntry' => array(
|
||||
'className' => 'DoubleEntry',
|
||||
'foreignKey' => 'debit_entry_id',
|
||||
'dependent' => true,
|
||||
),
|
||||
'CreditDoubleEntry' => array(
|
||||
'className' => 'DoubleEntry',
|
||||
'foreignKey' => 'credit_entry_id',
|
||||
'dependent' => true,
|
||||
),
|
||||
'DoubleEntry' => array(
|
||||
'foreignKey' => false,
|
||||
),
|
||||
);
|
||||
|
||||
var $hasMany = array(
|
||||
);
|
||||
|
||||
var $hasAndBelongsToMany = array(
|
||||
// The Debit half of the double entry matching THIS Credit (if it is one)
|
||||
'DebitEntry' => array(
|
||||
'className' => 'LedgerEntry',
|
||||
'joinTable' => 'double_entries',
|
||||
'linkalias' => 'DDE',
|
||||
'foreignKey' => 'credit_entry_id',
|
||||
'associationForeignKey' => 'debit_entry_id',
|
||||
),
|
||||
|
||||
// The Credit half of the double entry matching THIS Debit (if it is one)
|
||||
'CreditEntry' => array(
|
||||
'className' => 'LedgerEntry',
|
||||
'joinTable' => 'double_entries',
|
||||
'linkalias' => 'CDE',
|
||||
'foreignKey' => 'debit_entry_id',
|
||||
'associationForeignKey' => 'credit_entry_id',
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: debitCreditFields
|
||||
* - Returns the fields necessary to determine whether the queried
|
||||
* entries are a debit, or a credit, and also the effect each have
|
||||
* on the overall balance of the account/ledger.
|
||||
*/
|
||||
|
||||
function debitCreditFields($sum = false, $balance = true,
|
||||
$entry_name = 'LedgerEntry', $account_name = 'Account') {
|
||||
$fields = array
|
||||
(
|
||||
($sum ? 'SUM(' : '') .
|
||||
"IF({$entry_name}.crdr = 'DEBIT'," .
|
||||
" {$entry_name}.amount, NULL)" .
|
||||
($sum ? ')' : '') . ' AS debit' . ($sum ? 's' : ''),
|
||||
|
||||
($sum ? 'SUM(' : '') .
|
||||
"IF({$entry_name}.crdr = 'CREDIT'," .
|
||||
" {$entry_name}.amount, NULL)" .
|
||||
($sum ? ')' : '') . ' AS credit' . ($sum ? 's' : ''),
|
||||
);
|
||||
|
||||
if ($balance)
|
||||
$fields[] =
|
||||
($sum ? 'SUM(' : '') .
|
||||
"IF(${account_name}.type IN ('ASSET', 'EXPENSE')," .
|
||||
" IF({$entry_name}.crdr = 'DEBIT', 1, -1)," .
|
||||
" IF({$entry_name}.crdr = 'CREDIT', 1, -1))" .
|
||||
" * IF({$entry_name}.amount, {$entry_name}.amount, 0)" .
|
||||
($sum ? ')' : '') . ' AS balance';
|
||||
|
||||
if ($sum)
|
||||
$fields[] = "COUNT({$entry_name}.id) AS entries";
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: verifyLedgerEntry
|
||||
* - Verifies consistenty of new ledger entry data
|
||||
* (not in a pre-existing ledger entry)
|
||||
*/
|
||||
function verifyLedgerEntry($entry, $tender = null) {
|
||||
/* pr(array("LedgerEntry::verifyLedgerEntry()" */
|
||||
/* => compact('entry', 'tender'))); */
|
||||
|
||||
if (empty($entry['account_id']) ||
|
||||
empty($entry['crdr']) ||
|
||||
empty($entry['amount'])
|
||||
) {
|
||||
/* pr(array("LedgerEntry::verifyLedgerEntry()" */
|
||||
/* => "Entry verification failed")); */
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($tender) && !$this->Tender->verifyTender($tender)) {
|
||||
/* pr(array("LedgerEntry::verifyLedgerEntry()" */
|
||||
/* => "Tender verification failed")); */
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: addLedgerEntry
|
||||
* - Inserts new Ledger Entry into the database
|
||||
*/
|
||||
function addLedgerEntry($entry, $tender = null) {
|
||||
//$this->prFunctionLevel(16);
|
||||
$this->prEnter(compact('entry', 'tender'));
|
||||
|
||||
$ret = array('data' => $entry);
|
||||
if (!$this->verifyLedgerEntry($entry, $tender))
|
||||
return $this->prReturn(array('error' => true) + $ret);
|
||||
|
||||
if (empty($entry['ledger_id']))
|
||||
$entry['ledger_id'] =
|
||||
$this->Account->currentLedgerID($entry['account_id']);
|
||||
|
||||
$this->create();
|
||||
if (!$this->save($entry))
|
||||
return $this->prReturn(array('error' => true) + $ret);
|
||||
|
||||
$ret['ledger_entry_id'] = $this->id;
|
||||
|
||||
if (isset($tender)) {
|
||||
$tender['account_id'] = $entry['account_id'];
|
||||
$tender['ledger_entry_id'] = $ret['ledger_entry_id'];
|
||||
$result = $this->Tender->addTender($tender);
|
||||
$ret['Tender'] = $result;
|
||||
if ($result['error'])
|
||||
return $this->prReturn(array('error' => true) + $ret);
|
||||
}
|
||||
|
||||
return $this->prReturn($ret + array('error' => false));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: stats
|
||||
* - Returns summary data from the requested ledger entry
|
||||
*/
|
||||
function stats($id = null, $query = null, $set = null) {
|
||||
$this->queryInit($query);
|
||||
|
||||
// REVISIT <AP>: 20090816
|
||||
// This function appeared to be dramatically broken,
|
||||
// a throwback to an earlier time. I deleted its
|
||||
// contents and added this error to ensure it does
|
||||
// not get used.
|
||||
$this->INTERNAL_ERROR('This function should not be used');
|
||||
}
|
||||
|
||||
}
|
||||
23
models/map.php
Normal file
23
models/map.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
class Map extends AppModel {
|
||||
|
||||
var $name = 'Map';
|
||||
var $validate = array(
|
||||
'id' => array('numeric'),
|
||||
'site_id' => array('numeric'),
|
||||
'site_area_id' => array('numeric'),
|
||||
'name' => array('notempty'),
|
||||
'width' => array('numeric'),
|
||||
'depth' => array('numeric')
|
||||
);
|
||||
|
||||
var $belongsTo = array(
|
||||
'SiteArea',
|
||||
);
|
||||
|
||||
var $hasAndBelongsToMany = array(
|
||||
'Unit',
|
||||
);
|
||||
|
||||
}
|
||||
?>
|
||||
16
models/site.php
Normal file
16
models/site.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
class Site extends AppModel {
|
||||
|
||||
var $name = 'Site';
|
||||
var $validate = array(
|
||||
'id' => array('numeric'),
|
||||
'name' => array('notempty')
|
||||
);
|
||||
|
||||
var $hasMany = array(
|
||||
'SiteArea',
|
||||
'SiteOption',
|
||||
);
|
||||
|
||||
}
|
||||
?>
|
||||
20
models/site_area.php
Normal file
20
models/site_area.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
class SiteArea extends AppModel {
|
||||
|
||||
var $name = 'SiteArea';
|
||||
var $validate = array(
|
||||
'id' => array('numeric'),
|
||||
'site_id' => array('numeric'),
|
||||
'name' => array('notempty')
|
||||
);
|
||||
|
||||
var $belongsTo = array(
|
||||
'Site',
|
||||
);
|
||||
|
||||
var $hasOne = array(
|
||||
'Map',
|
||||
);
|
||||
|
||||
}
|
||||
?>
|
||||
725
models/statement_entry.php
Normal file
725
models/statement_entry.php
Normal file
@@ -0,0 +1,725 @@
|
||||
<?php
|
||||
class StatementEntry extends AppModel {
|
||||
|
||||
var $belongsTo = array(
|
||||
'Transaction',
|
||||
'Customer',
|
||||
'Lease',
|
||||
'Account',
|
||||
|
||||
// The charge to which this disbursement applies (if it is one)
|
||||
'ChargeEntry' => array(
|
||||
'className' => 'StatementEntry',
|
||||
),
|
||||
);
|
||||
|
||||
var $hasMany = array(
|
||||
// The disbursements that apply to this charge (if it is one)
|
||||
'DisbursementEntry' => array(
|
||||
'className' => 'StatementEntry',
|
||||
'foreignKey' => 'charge_entry_id',
|
||||
'dependent' => true,
|
||||
),
|
||||
|
||||
);
|
||||
|
||||
//var $default_log_level = array('log' => 30, 'show' => 15);
|
||||
var $max_log_level = 19;
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: debit/creditTypes
|
||||
*/
|
||||
|
||||
function debitTypes() {
|
||||
return array('CHARGE', 'PAYMENT', 'REFUND');
|
||||
}
|
||||
|
||||
function creditTypes() {
|
||||
return array('DISBURSEMENT', 'WAIVER', 'REVERSAL', 'WRITEOFF', 'SURPLUS');
|
||||
}
|
||||
|
||||
function voidTypes() {
|
||||
return array('VOID');
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: chargeDisbursementFields
|
||||
*/
|
||||
|
||||
function chargeDisbursementFields($sum = false, $entry_name = 'StatementEntry') {
|
||||
$debits = $this->debitTypes();
|
||||
$credits = $this->creditTypes();
|
||||
$voids = $this->voidTypes();
|
||||
|
||||
foreach ($debits AS &$enum)
|
||||
$enum = "'" . $enum . "'";
|
||||
foreach ($credits AS &$enum)
|
||||
$enum = "'" . $enum . "'";
|
||||
foreach ($voids AS &$enum)
|
||||
$enum = "'" . $enum . "'";
|
||||
|
||||
$debit_set = implode(", ", $debits);
|
||||
$credit_set = implode(", ", $credits);
|
||||
$void_set = implode(", ", $voids);
|
||||
|
||||
$fields = array
|
||||
(
|
||||
($sum ? 'SUM(' : '') .
|
||||
"IF({$entry_name}.type IN ({$debit_set})," .
|
||||
" {$entry_name}.amount, NULL)" .
|
||||
($sum ? ')' : '') . ' AS charge' . ($sum ? 's' : ''),
|
||||
|
||||
($sum ? 'SUM(' : '') .
|
||||
"IF({$entry_name}.type IN({$credit_set})," .
|
||||
" {$entry_name}.amount, NULL)" .
|
||||
($sum ? ')' : '') . ' AS disbursement' . ($sum ? 's' : ''),
|
||||
|
||||
($sum ? 'SUM(' : '') .
|
||||
"IF({$entry_name}.type IN ({$debit_set}), 1," .
|
||||
" IF({$entry_name}.type IN ({$credit_set}), -1, 0))" .
|
||||
" * IF({$entry_name}.amount, {$entry_name}.amount, 0)" .
|
||||
($sum ? ')' : '') . ' AS balance',
|
||||
);
|
||||
|
||||
if ($sum)
|
||||
$fields[] = "COUNT({$entry_name}.id) AS entries";
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: verifyStatementEntry
|
||||
* - Verifies consistenty of new statement entry data
|
||||
* (not in a pre-existing statement entry)
|
||||
*/
|
||||
function verifyStatementEntry($entry) {
|
||||
$this->prFunctionLevel(10);
|
||||
$this->prEnter(compact('entry'));
|
||||
|
||||
if (empty($entry['type']) ||
|
||||
//empty($entry['effective_date']) ||
|
||||
empty($entry['account_id']) ||
|
||||
empty($entry['amount'])
|
||||
) {
|
||||
return $this->prReturn(false);
|
||||
}
|
||||
|
||||
return $this->prReturn(true);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: addStatementEntry
|
||||
* - Inserts new Statement Entry into the database
|
||||
*/
|
||||
function addStatementEntry($entry) {
|
||||
$this->prEnter(compact('entry'));
|
||||
|
||||
$ret = array('data' => $entry);
|
||||
if (!$this->verifyStatementEntry($entry))
|
||||
return $this->prReturn(array('error' => true, 'verify_data' => $entry) + $ret);
|
||||
|
||||
$this->create();
|
||||
if (!$this->save($entry))
|
||||
return $this->prReturn(array('error' => true, 'save_data' => $entry) + $ret);
|
||||
|
||||
$ret['statement_entry_id'] = $this->id;
|
||||
return $this->prReturn($ret + array('error' => false));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: waive
|
||||
* - Waives the charge balance
|
||||
*
|
||||
*/
|
||||
function waive($id, $stamp = null) {
|
||||
$this->prEnter(compact('id', 'stamp'));
|
||||
|
||||
// Get the basic information about the entry to be waived.
|
||||
$this->recursive = -1;
|
||||
$charge = $this->read(null, $id);
|
||||
$charge = $charge['StatementEntry'];
|
||||
|
||||
if ($charge['type'] !== 'CHARGE')
|
||||
$this->INTERNAL_ERROR("Waiver item is not CHARGE.");
|
||||
|
||||
// Query the stats to get the remaining balance
|
||||
$stats = $this->stats($id);
|
||||
|
||||
// Build a transaction
|
||||
$waiver = array('Transaction' => array(), 'Entry' => array());
|
||||
$waiver['Transaction']['stamp'] = $stamp;
|
||||
$waiver['Transaction']['comment'] = "Charge Waiver";
|
||||
|
||||
// Add the charge waiver
|
||||
$waiver['Entry'][] =
|
||||
array('amount' => $stats['Charge']['balance'],
|
||||
'comment' => null,
|
||||
);
|
||||
|
||||
// Record the waiver transaction
|
||||
return $this->prReturn($this->Transaction->addWaiver
|
||||
($waiver, $id, $charge['customer_id'], $charge['lease_id']));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: reversable
|
||||
* - Returns true if the charge can be reversed; false otherwise
|
||||
*/
|
||||
function reversable($id) {
|
||||
$this->prEnter(compact('id'));
|
||||
|
||||
if (empty($id))
|
||||
return $this->prReturn(false);
|
||||
|
||||
// Verify the item is an actual charge
|
||||
$this->id = $id;
|
||||
$charge_type = $this->field('type');
|
||||
if ($charge_type !== 'CHARGE')
|
||||
return $this->prReturn(false);
|
||||
|
||||
// Determine anything reconciled against the charge
|
||||
$reverse_transaction_id = $this->field('reverse_transaction_id');
|
||||
if (!empty($reverse_transaction_id))
|
||||
return $this->prReturn(false);
|
||||
|
||||
return $this->prReturn(true);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: reverse
|
||||
* - Reverses the charges
|
||||
*/
|
||||
function reverse($id, $stamp = null, $comment) {
|
||||
$this->prEnter(compact('id', 'stamp'));
|
||||
|
||||
// Verify the item can be reversed
|
||||
if (!$this->reversable($id))
|
||||
$this->INTERNAL_ERROR("Item is not reversable.");
|
||||
|
||||
// Get the basic information about this charge
|
||||
$charge = $this->find('first', array('contain' => true));
|
||||
//$charge = $charge['StatementEntry'];
|
||||
|
||||
// Query the stats to get the remaining balance
|
||||
$stats = $this->stats($id);
|
||||
$charge['paid'] = $stats['Charge']['disbursement'];
|
||||
|
||||
// Record the reversal transaction
|
||||
$result = $this->Transaction->addReversal
|
||||
($charge, $stamp, $comment ? $comment : 'Charge Reversal');
|
||||
|
||||
if (empty($result['error'])) {
|
||||
// Mark the charge as reversed
|
||||
$this->id = $id;
|
||||
$this->saveField('reverse_transaction_id', $result['transaction_id']);
|
||||
}
|
||||
|
||||
return $this->prReturn($result);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: reconciledSet
|
||||
* - Returns the set of entries satisfying the given conditions,
|
||||
* along with any entries that they reconcile
|
||||
*/
|
||||
function reconciledSetQuery($set, $query) {
|
||||
$this->queryInit($query);
|
||||
|
||||
if (in_array($set, $this->debitTypes()))
|
||||
$query['link']['DisbursementEntry'] = array('fields' => array("SUM(DisbursementEntry.amount) AS reconciled"));
|
||||
elseif (in_array($set, $this->creditTypes()))
|
||||
$query['link']['ChargeEntry'] = array('fields' => array("SUM(ChargeEntry.amount) AS reconciled"));
|
||||
else
|
||||
die("INVALID RECONCILE SET");
|
||||
|
||||
$query['conditions'][] = array('StatementEntry.type' => $set);
|
||||
$query['group'] = 'StatementEntry.id';
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
function reconciledSet($set, $query = null, $unrec = false, $if_rec_include_partial = false) {
|
||||
//$this->prFunctionLevel(array('log' => 16, 'show' => 10));
|
||||
$this->prEnter(compact('set', 'query', 'unrec', 'if_rec_include_partial'));
|
||||
$lquery = $this->reconciledSetQuery($set, $query);
|
||||
$result = $this->find('all', $lquery);
|
||||
|
||||
$this->pr(20, compact('lquery', 'result'));
|
||||
|
||||
$resultset = array();
|
||||
foreach ($result AS $i => $entry) {
|
||||
$this->pr(25, compact('entry'));
|
||||
if (!empty($entry[0]))
|
||||
$entry['StatementEntry'] = $entry[0] + $entry['StatementEntry'];
|
||||
unset($entry[0]);
|
||||
|
||||
$entry['StatementEntry']['balance'] =
|
||||
$entry['StatementEntry']['amount'] - $entry['StatementEntry']['reconciled'];
|
||||
|
||||
// Since HAVING isn't a builtin feature of CakePHP,
|
||||
// we'll have to post-process to get the desired entries
|
||||
|
||||
if ($entry['StatementEntry']['balance'] == 0)
|
||||
$reconciled = true;
|
||||
elseif ($entry['StatementEntry']['reconciled'] == 0)
|
||||
$reconciled = false;
|
||||
else // Partial disbursement; depends on unrec
|
||||
$reconciled = (!$unrec && $if_rec_include_partial);
|
||||
|
||||
// Add to the set, if it's been requested
|
||||
if ($reconciled == !$unrec)
|
||||
$resultset[] = $entry;
|
||||
}
|
||||
|
||||
return $this->prReturn(array('entries' => $resultset,
|
||||
'summary' => $this->stats(null, $query)));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: reconciledEntries
|
||||
* - Returns a list of entries that reconcile against the given entry.
|
||||
* (such as disbursements towards a charge).
|
||||
*/
|
||||
function reconciledEntriesQuery($id, $query = null) {
|
||||
$this->queryInit($query, false);
|
||||
|
||||
$this->id = $id;
|
||||
$this->recursive = -1;
|
||||
$this->read();
|
||||
|
||||
$query['conditions'][] = array('StatementEntry.id' => $id);
|
||||
|
||||
if (in_array($this->data['StatementEntry']['type'], $this->debitTypes())) {
|
||||
$query['link']['DisbursementEntry'] = array();
|
||||
$query['conditions'][] = array('DisbursementEntry.id !=' => null);
|
||||
}
|
||||
if (in_array($this->data['StatementEntry']['type'], $this->creditTypes())) {
|
||||
$query['link']['ChargeEntry'] = array();
|
||||
$query['conditions'][] = array('ChargeEntry.id !=' => null);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
function reconciledEntries($id, $query = null) {
|
||||
$this->prEnter(compact('id', 'query'));
|
||||
$lquery = $this->reconciledEntriesQuery($id, $query);
|
||||
|
||||
$result = $this->find('all', $lquery);
|
||||
foreach (array_keys($result) AS $i)
|
||||
unset($result[$i]['StatementEntry']);
|
||||
|
||||
return $this->prReturn(array('entries' => $result));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: assignCredits
|
||||
* - Assigns all credits to existing charges
|
||||
*
|
||||
* REVISIT <AP>: 20090726
|
||||
* This algorithm shouldn't be hardcoded. We need to allow
|
||||
* the user to specify how disbursements should be applied.
|
||||
*
|
||||
*/
|
||||
function assignCredits($query = null, $receipt_id = null,
|
||||
$charge_ids = null, $disbursement_type = null,
|
||||
$customer_id = null, $lease_id = null)
|
||||
{
|
||||
//$this->prFunctionLevel(25);
|
||||
$this->prEnter(compact('query', 'receipt_id',
|
||||
'charge_ids', 'disbursement_type',
|
||||
'customer_id', 'lease_id'));
|
||||
$this->queryInit($query);
|
||||
|
||||
if (!empty($customer_id))
|
||||
$query['conditions'][] = array('StatementEntry.customer_id' => $customer_id);
|
||||
|
||||
if (empty($disbursement_type))
|
||||
$disbursement_type = 'DISBURSEMENT';
|
||||
|
||||
$ret = array();
|
||||
|
||||
// First, find all known credits, unless this call is to make
|
||||
// credit adjustments to a specific charge
|
||||
if (empty($receipt_id)) {
|
||||
|
||||
if (!empty($charge_ids))
|
||||
$this->INTERNAL_ERROR("Charge IDs, yet no corresponding receipt");
|
||||
|
||||
$lquery = $query;
|
||||
$lquery['conditions'][] = array('StatementEntry.type' => 'SURPLUS');
|
||||
// REVISIT <AP>: 20090804
|
||||
// We need to ensure that we're using surplus credits ONLY from either
|
||||
// the given lease, or those that do not apply to any specific lease.
|
||||
// However, by doing this, it forces any lease surplus amounts to
|
||||
// remain frozen with that lease until either there is a lease charge,
|
||||
// we refund the money, or we "promote" that surplus to the customer
|
||||
// level and out of the leases direct control.
|
||||
// That seems like a pain. Perhaps we should allow any customer
|
||||
// surplus to be used on any customer charge.
|
||||
$lquery['conditions'][] =
|
||||
array('OR' =>
|
||||
array(array('StatementEntry.lease_id' => null),
|
||||
(!empty($lease_id)
|
||||
? array('StatementEntry.lease_id' => $lease_id)
|
||||
: array()),
|
||||
));
|
||||
$lquery['order'][] = 'StatementEntry.effective_date ASC';
|
||||
$credits = $this->find('all', $lquery);
|
||||
$this->pr(18, compact('credits'),
|
||||
"Credits Established");
|
||||
}
|
||||
else {
|
||||
// Establish credit from the (newly added) receipt
|
||||
$lquery =
|
||||
array('link' =>
|
||||
array('StatementEntry',
|
||||
'LedgerEntry' =>
|
||||
array('conditions' =>
|
||||
array('LedgerEntry.account_id <> Transaction.account_id')
|
||||
),
|
||||
),
|
||||
'conditions' => array('Transaction.id' => $receipt_id),
|
||||
'fields' => array('Transaction.id', 'Transaction.stamp', 'Transaction.amount'),
|
||||
);
|
||||
$receipt_credit = $this->Transaction->find('first', $lquery);
|
||||
if (!$receipt_credit)
|
||||
$this->INTERNAL_ERROR("Unable to locate receipt.");
|
||||
|
||||
$stats = $this->Transaction->stats($receipt_id);
|
||||
$receipt_credit['balance'] = $stats['undisbursed'];
|
||||
|
||||
$receipt_credit['receipt'] = true;
|
||||
$credits = array($receipt_credit);
|
||||
$this->pr(18, compact('credits'),
|
||||
"Receipt Credit Added");
|
||||
}
|
||||
|
||||
// Now find all unpaid charges
|
||||
if (isset($charge_ids)) {
|
||||
$lquery = array('contain' => false,
|
||||
'conditions' => array('StatementEntry.id' => $charge_ids));
|
||||
} else {
|
||||
$lquery = $query;
|
||||
// If we're working with a specific lease, then limit charges to it
|
||||
if (!empty($lease_id))
|
||||
$lquery['conditions'][] = array('StatementEntry.lease_id' => $lease_id);
|
||||
}
|
||||
$lquery['order'] = 'StatementEntry.effective_date ASC';
|
||||
$charges = array();
|
||||
foreach ($this->debitTypes() AS $dtype) {
|
||||
$rset = $this->reconciledSet($dtype, $lquery, true);
|
||||
$entries = $rset['entries'];
|
||||
$charges = array_merge($charges, $entries);
|
||||
$this->pr(18, compact('dtype', 'entries'), "Outstanding Debit Entries");
|
||||
}
|
||||
|
||||
// Work through all unpaid charges, applying disbursements as we go
|
||||
foreach ($charges AS $charge) {
|
||||
$this->pr(20, compact('charge'),
|
||||
'Process Charge');
|
||||
|
||||
$charge['balance'] = $charge['StatementEntry']['balance'];
|
||||
|
||||
// Use explicit credits before using the new receipt credit
|
||||
foreach ($credits AS &$credit) {
|
||||
if (empty($charge['balance']))
|
||||
break;
|
||||
if ($charge['balance'] < 0)
|
||||
$this->INTERNAL_ERROR("Negative Charge Balance");
|
||||
|
||||
if (!isset($credit['balance']))
|
||||
$credit['balance'] = $credit['StatementEntry']['amount'];
|
||||
|
||||
if (empty($credit['balance']))
|
||||
continue;
|
||||
if ($credit['balance'] < 0)
|
||||
$this->INTERNAL_ERROR("Negative Credit Balance");
|
||||
|
||||
$this->pr(20, compact('charge'),
|
||||
'Attempt Charge Reconciliation');
|
||||
|
||||
if (empty($credit['receipt']))
|
||||
$disbursement_account_id = $credit['StatementEntry']['account_id'];
|
||||
else
|
||||
$disbursement_account_id = $credit['LedgerEntry']['account_id'];
|
||||
|
||||
// REVISIT <AP>: 20090811
|
||||
// Need to come up with a better strategy for handling
|
||||
// concessions. For now, just restricting concessions
|
||||
// to apply only towards rent will resolve the most
|
||||
// predominant (or only) needed usage case.
|
||||
if ($disbursement_account_id == $this->Account->concessionAccountID() &&
|
||||
$charge['StatementEntry']['account_id'] != $this->Account->rentAccountID())
|
||||
continue;
|
||||
|
||||
// Set the disbursement amount to the maximum amount
|
||||
// possible without exceeding the charge or credit balance
|
||||
$disbursement_amount = min($charge['balance'], $credit['balance']);
|
||||
if (!isset($credit['applied']))
|
||||
$credit['applied'] = 0;
|
||||
|
||||
$credit['applied'] += $disbursement_amount;
|
||||
$credit['balance'] -= $disbursement_amount;
|
||||
|
||||
$this->pr(20, compact('credit'),
|
||||
($credit['balance'] > 0 ? 'Utilized' : 'Exhausted') .
|
||||
(empty($credit['receipt']) ? ' Credit' : ' Receipt'));
|
||||
|
||||
if (strtotime($charge['StatementEntry']['effective_date']) >
|
||||
strtotime($credit['StatementEntry']['effective_date']))
|
||||
$disbursement_edate = $charge['StatementEntry']['effective_date'];
|
||||
else
|
||||
$disbursement_edate = $credit['StatementEntry']['effective_date'];
|
||||
|
||||
if (empty($credit['receipt'])) {
|
||||
// Explicit Credit
|
||||
$result = $this->Transaction->addTransactionEntries
|
||||
(array('include_ledger_entry' => true,
|
||||
'include_statement_entry' => true),
|
||||
array('type' => 'INVOICE',
|
||||
'id' => $credit['StatementEntry']['transaction_id'],
|
||||
'account_id' => $this->Account->accountReceivableAccountID(),
|
||||
'crdr' => 'CREDIT',
|
||||
'customer_id' => $charge['StatementEntry']['customer_id'],
|
||||
'lease_id' => $charge['StatementEntry']['lease_id'],
|
||||
),
|
||||
array
|
||||
(array('type' => $disbursement_type,
|
||||
'effective_date' => $disbursement_edate,
|
||||
'account_id' => $credit['StatementEntry']['account_id'],
|
||||
'amount' => $disbursement_amount,
|
||||
'charge_entry_id' => $charge['StatementEntry']['id'],
|
||||
),
|
||||
));
|
||||
|
||||
$ret['Disbursement'][] = $result;
|
||||
if ($result['error'])
|
||||
$ret['error'] = true;
|
||||
}
|
||||
else {
|
||||
// Receipt Credit
|
||||
|
||||
if (strtotime($charge['StatementEntry']['effective_date']) >
|
||||
strtotime($credit['Transaction']['stamp']))
|
||||
$disbursement_edate = $charge['StatementEntry']['effective_date'];
|
||||
else
|
||||
$disbursement_edate = $credit['Transaction']['stamp'];
|
||||
|
||||
// Add a disbursement that uses the available credit to pay the charge
|
||||
$disbursement =
|
||||
array('type' => $disbursement_type,
|
||||
'effective_date' => $disbursement_edate,
|
||||
'amount' => $disbursement_amount,
|
||||
'account_id' => $credit['LedgerEntry']['account_id'],
|
||||
'transaction_id' => $credit['Transaction']['id'],
|
||||
'customer_id' => $charge['StatementEntry']['customer_id'],
|
||||
'lease_id' => $charge['StatementEntry']['lease_id'],
|
||||
'charge_entry_id' => $charge['StatementEntry']['id'],
|
||||
'comment' => null,
|
||||
);
|
||||
|
||||
$this->pr(20, compact('disbursement'), 'New Disbursement Entry');
|
||||
$result = $this->addStatementEntry($disbursement);
|
||||
$ret['Disbursement'][] = $result;
|
||||
if ($result['error'])
|
||||
$ret['error'] = true;
|
||||
}
|
||||
|
||||
// Adjust the charge balance to reflect the new disbursement
|
||||
$charge['balance'] -= $disbursement_amount;
|
||||
if ($charge['balance'] < 0)
|
||||
die("HOW DID WE GET A NEGATIVE CHARGE AMOUNT?");
|
||||
|
||||
if ($charge['balance'] <= 0)
|
||||
$this->pr(20, 'Fully Paid Charge');
|
||||
}
|
||||
// Break the $credit reference to avoid future problems
|
||||
unset($credit);
|
||||
}
|
||||
|
||||
$this->pr(18, compact('credits'),
|
||||
'Disbursements complete');
|
||||
|
||||
// Clean up any explicit credits that have been used
|
||||
foreach ($credits AS $credit) {
|
||||
if (!empty($credit['receipt']))
|
||||
continue;
|
||||
|
||||
if (empty($credit['applied']))
|
||||
continue;
|
||||
|
||||
if ($credit['balance'] > 0) {
|
||||
$this->pr(20, compact('credit'),
|
||||
'Update Credit Entry');
|
||||
|
||||
$this->id = $credit['StatementEntry']['id'];
|
||||
$this->saveField('amount', $credit['balance']);
|
||||
}
|
||||
else {
|
||||
$this->pr(20, compact('credit'),
|
||||
'Delete Exhausted Credit Entry');
|
||||
|
||||
$this->delete($credit['StatementEntry']['id'], false);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for any implicit receipt credits, converting
|
||||
// into explicit credits if there is a remaining balance.
|
||||
foreach ($credits AS $credit) {
|
||||
if (empty($credit['receipt']))
|
||||
continue;
|
||||
|
||||
if (empty($credit['balance']))
|
||||
continue;
|
||||
|
||||
// See if there is an existing explicit credit
|
||||
// for this transaction.
|
||||
$explicit_credit = $this->find
|
||||
('first', array('contain' => false,
|
||||
'conditions' =>
|
||||
array(array('transaction_id' => $credit['Transaction']['id']),
|
||||
array('type' => 'SURPLUS')),
|
||||
));
|
||||
|
||||
if (!empty($explicit_credit)) {
|
||||
// REVISIT <AP>: 20090815
|
||||
// Testing whether or not this case occurs
|
||||
$this->INTERNAL_ERROR('Existing explicit credit unexpected');
|
||||
|
||||
// Since there IS an existing explicit credit, we must update
|
||||
// its balance instead of creating a new one, since it has
|
||||
// already been incorporated in the overall credit balance.
|
||||
// If we were to create a new one, we would erroneously create
|
||||
// an excess of credit available.
|
||||
$this->pr(18, compact('explicit_credit', 'credit'),
|
||||
'Update existing explicit credit');
|
||||
$EC = new StatementEntry();
|
||||
$EC->id = $explicit_credit['StatementEntry']['id'];
|
||||
$EC->saveField('amount', $credit['balance']);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!empty($ret['receipt_balance']))
|
||||
$this->INTERNAL_ERROR('Only one receipt expected in assignCredits');
|
||||
|
||||
// Give caller the information necessary to create an explicit
|
||||
// credit from the passed receipt, which we've not exhausted.
|
||||
$this->pr(18, compact('credit'), 'Convert to explicit credit');
|
||||
$ret['receipt_balance'] = $credit['balance'];
|
||||
}
|
||||
|
||||
return $this->prReturn($ret + array('error' => false));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: stats
|
||||
* - Returns summary data from the requested statement entry
|
||||
*/
|
||||
function stats($id = null, $query = null) {
|
||||
//$this->prFunctionLevel(array('log' => 16, 'show' => 10));
|
||||
$this->prEnter(compact('id', 'query'));
|
||||
|
||||
$this->queryInit($query);
|
||||
unset($query['group']);
|
||||
|
||||
$stats = array();
|
||||
if (isset($id))
|
||||
$query['conditions'][] = array('StatementEntry.id' => $id);
|
||||
|
||||
$types = array('Charge', 'Disbursement');
|
||||
foreach ($types AS $type_index => $this_name) {
|
||||
$that_name = $types[($type_index + 1) % 2];
|
||||
if ($this_name === 'Charge') {
|
||||
$this_types = $this->debitTypes();
|
||||
$that_types = $this->creditTypes();
|
||||
} else {
|
||||
$this_types = $this->creditTypes();
|
||||
$that_types = $this->debitTypes();
|
||||
}
|
||||
|
||||
$this_query = $query;
|
||||
$this_query['fields'] = array();
|
||||
$this_query['fields'][] = "SUM(StatementEntry.amount) AS total";
|
||||
$this_query['conditions'][] = array('StatementEntry.type' => $this_types);
|
||||
$result = $this->find('first', $this_query);
|
||||
$stats[$this_name] = $result[0];
|
||||
|
||||
$this->pr(17, compact('this_query', 'result'), $this_name.'s');
|
||||
|
||||
// Tally the different types that result in credits towards the charges
|
||||
$stats[$this_name]['reconciled'] = 0;
|
||||
foreach ($that_types AS $that_type) {
|
||||
$lc_that_type = strtolower($that_type);
|
||||
$that_query = $this_query;
|
||||
$that_query['link']["{$that_name}Entry"] = array('fields' => array());
|
||||
$that_query['fields'] = array();
|
||||
if ($this_name == 'Charge')
|
||||
$that_query['fields'][] = "COALESCE(SUM(${that_name}Entry.amount),0) AS $lc_that_type";
|
||||
else
|
||||
$that_query['fields'][] = "COALESCE(SUM(StatementEntry.amount), 0) AS $lc_that_type";
|
||||
$that_query['conditions'][] = array("{$that_name}Entry.type" => $that_type);
|
||||
$result = $this->find('first', $that_query);
|
||||
$stats[$this_name] += $result[0];
|
||||
|
||||
$this->pr(17, compact('that_query', 'result'), "{$this_name}s: $that_type");
|
||||
$stats[$this_name]['reconciled'] += $stats[$this_name][$lc_that_type];
|
||||
}
|
||||
|
||||
// Compute balance information for charges
|
||||
$stats[$this_name]['balance'] =
|
||||
$stats[$this_name]['total'] - $stats[$this_name]['reconciled'];
|
||||
if (!isset($stats[$this_name]['balance']))
|
||||
$stats[$this_name]['balance'] = 0;
|
||||
}
|
||||
|
||||
// 'balance' is simply the difference between
|
||||
// the balances of charges and disbursements
|
||||
$stats['balance'] = $stats['Charge']['balance'] - $stats['Disbursement']['balance'];
|
||||
if (!isset($stats['balance']))
|
||||
$stats['balance'] = 0;
|
||||
|
||||
// 'account_balance' is really only relevant to
|
||||
// callers that have requested charge and disbursement
|
||||
// stats with respect to a particular account.
|
||||
// It represents the difference between inflow
|
||||
// and outflow from that account.
|
||||
$stats['account_balance'] = $stats['Charge']['reconciled'] - $stats['Disbursement']['total'];
|
||||
if (!isset($stats['account_balance']))
|
||||
$stats['account_balance'] = 0;
|
||||
|
||||
return $this->prReturn($stats);
|
||||
}
|
||||
|
||||
}
|
||||
166
models/tender.php
Normal file
166
models/tender.php
Normal file
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
class Tender extends AppModel {
|
||||
|
||||
var $belongsTo = array(
|
||||
'TenderType',
|
||||
'Customer',
|
||||
'LedgerEntry',
|
||||
'DepositTransaction' => array(
|
||||
'className' => 'Transaction',
|
||||
),
|
||||
'DepositLedgerEntry' => array(
|
||||
'className' => 'LedgerEntry',
|
||||
),
|
||||
'NsfTransaction' => array(
|
||||
'className' => 'Transaction',
|
||||
'dependent' => true,
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: afterSave
|
||||
* - Performs any work needed after the save occurs
|
||||
*/
|
||||
|
||||
function afterSave($created) {
|
||||
// Come up with a (not necessarily unique) name for the tender.
|
||||
// For checks & money orders, this will be based on the check
|
||||
// number. For other types of tender, we'll just use the
|
||||
// generic name of the tender type, and the tender ID
|
||||
|
||||
// Determine our tender type, and set the ID of that model
|
||||
$this->TenderType->id = $this->field('tender_type_id');
|
||||
|
||||
// REVISIT <AP>: 20090810
|
||||
// The only tender expected to have no tender type
|
||||
// is our special "Closing" tender.
|
||||
if (empty($this->TenderType->id))
|
||||
$newname = 'Closing';
|
||||
else {
|
||||
$newname = $this->TenderType->field('name');
|
||||
$naming_field = $this->TenderType->field('naming_field');
|
||||
if (!empty($naming_field))
|
||||
$newname .= ' #' . $this->field($naming_field);
|
||||
}
|
||||
|
||||
if ($newname !== $this->field('name'))
|
||||
$this->saveField('name', $newname);
|
||||
|
||||
return parent::afterSave($created);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: beforeDelete
|
||||
* - Performs any work needed before the delete occurs
|
||||
*/
|
||||
|
||||
function beforeDelete($cascade = true) {
|
||||
// REVISIT <AP>: 20090814
|
||||
// Experimental, and incomplete mechanism to protect
|
||||
// against trying to delete data that shouldn't be deleted.
|
||||
|
||||
$deposit_id = $this->field('deposit_transaction_id');
|
||||
pr(compact('deposit_id'));
|
||||
// If this tender has already been deposited, it would
|
||||
// be a rats nest to figure out how to delete this tender.
|
||||
if (!empty($deposit_id))
|
||||
return false;
|
||||
|
||||
return parent::beforeDelete($cascade);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: verifyTender
|
||||
* - Verifies consistenty of new tender data
|
||||
* (not in a pre-existing tender)
|
||||
*/
|
||||
function verifyTender($tender) {
|
||||
$this->prFunctionLevel(10);
|
||||
$this->prEnter(compact('tender'));
|
||||
|
||||
if (empty($tender['tender_type_id'])) {
|
||||
return $this->prReturn(false);
|
||||
}
|
||||
|
||||
return $this->prReturn(true);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: addTender
|
||||
* - Inserts new Tender into the database
|
||||
*/
|
||||
|
||||
function addTender($tender) {
|
||||
$this->prEnter(compact('tender'));
|
||||
|
||||
$ret = array('data' => $tender);
|
||||
if (!$this->verifyTender($tender))
|
||||
return $this->prReturn(array('error' => true) + $ret);
|
||||
|
||||
$this->create();
|
||||
if (!$this->save($tender))
|
||||
return $this->prReturn(array('error' => true) + $ret);
|
||||
|
||||
$ret['tender_id'] = $this->id;
|
||||
return $this->prReturn($ret + array('error' => false));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: nsf
|
||||
* - Flags the ledger entry as having insufficient funds
|
||||
*/
|
||||
|
||||
function nsf($id, $stamp = null, $comment = null) {
|
||||
$this->prEnter(compact('id', 'stamp', 'comment'));
|
||||
|
||||
// Get information about this NSF item.
|
||||
$this->id = $id;
|
||||
$tender = $this->find
|
||||
('first', array
|
||||
('contain' =>
|
||||
array('LedgerEntry',
|
||||
'DepositTransaction',
|
||||
'DepositLedgerEntry',
|
||||
'NsfTransaction'),
|
||||
));
|
||||
$this->pr(20, compact('tender'));
|
||||
|
||||
if (!empty($tender['NsfTransaction']['id']))
|
||||
die("Item has already been set as NSF");
|
||||
|
||||
if (empty($tender['DepositTransaction']['id']))
|
||||
die("Item has not been deposited yet");
|
||||
|
||||
$tender['Transaction'] = $tender['DepositTransaction'];
|
||||
unset($tender['DepositTransaction']);
|
||||
unset($tender['NsfTransaction']);
|
||||
|
||||
$T = new Transaction();
|
||||
$result = $T->addNsf($tender, $stamp, $comment);
|
||||
if (empty($result['error'])) {
|
||||
// Flag the tender as NSF, using the items created from addNsf
|
||||
$this->id = $id;
|
||||
$this->saveField('nsf_transaction_id', $result['nsf_transaction_id']);
|
||||
$this->saveField('nsf_ledger_entry_id', $result['nsf_ledger_entry_id']);
|
||||
}
|
||||
|
||||
return $this->prReturn($result);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
?>
|
||||
115
models/tender_type.php
Normal file
115
models/tender_type.php
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
class TenderType extends AppModel {
|
||||
|
||||
var $belongsTo = array(
|
||||
'Account',
|
||||
);
|
||||
|
||||
var $hasMany = array(
|
||||
'Tender',
|
||||
);
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: accountID
|
||||
* - Returns the intended account ID for receipt of the given tender
|
||||
*/
|
||||
|
||||
function accountID($id) {
|
||||
$this->cacheQueries = true;
|
||||
$item = $this->find('first', array
|
||||
('contain' => false,
|
||||
'conditions' => array('TenderType.id' => $id),
|
||||
));
|
||||
$this->cacheQueries = false;
|
||||
return $item['TenderType']['account_id'];
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: paymentTypes
|
||||
* - Returns an array of types that can be used for payments
|
||||
*/
|
||||
|
||||
function paymentTypes($query = null) {
|
||||
$this->queryInit($query);
|
||||
$query['order'][] = 'name';
|
||||
|
||||
$this->cacheQueries = true;
|
||||
$types = $this->find('all', $query);
|
||||
$this->cacheQueries = false;
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: paymentTypes
|
||||
* - Returns an array of types that can be deposited
|
||||
*/
|
||||
|
||||
function depositTypes($query = null) {
|
||||
$this->queryInit($query);
|
||||
$query['order'][] = 'name';
|
||||
$query['conditions'][] = array('tillable' => true);
|
||||
|
||||
$this->cacheQueries = true;
|
||||
$types = $this->find('all', $query);
|
||||
$this->cacheQueries = false;
|
||||
|
||||
// Rearrange to be of the form (id => name)
|
||||
$result = array();
|
||||
foreach ($types AS $type)
|
||||
$result[$type['TenderType']['id']] = $type['TenderType']['name'];
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: defaultPaymentType
|
||||
* - Returns the ID of the default payment type
|
||||
*/
|
||||
|
||||
function defaultPaymentType() {
|
||||
return $this->nameToID('Check');
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: stats
|
||||
* - Returns the stats for the given tender type
|
||||
*/
|
||||
|
||||
function stats($id = null, $query = null) {
|
||||
if (!$id)
|
||||
return null;
|
||||
|
||||
$this->queryInit($query);
|
||||
|
||||
if (!isset($query['link']['Tender']))
|
||||
$query['link']['Tender'] = array('fields' => array());
|
||||
if (!isset($query['link']['Tender']['LedgerEntry']))
|
||||
$query['link']['Tender']['LedgerEntry'] = array('fields' => array());
|
||||
|
||||
$query['fields'][] = "SUM(COALESCE(LedgerEntry.amount,0)) AS 'total'";
|
||||
$query['fields'][] = "SUM(IF(deposit_transaction_id IS NULL, COALESCE(LedgerEntry.amount,0), 0)) AS 'undeposited'";
|
||||
$query['fields'][] = "SUM(IF(deposit_transaction_id IS NULL, 0, COALESCE(LedgerEntry.amount,0))) AS 'deposited'";
|
||||
$query['fields'][] = "SUM(IF(nsf_transaction_id IS NULL, 0, COALESCE(LedgerEntry.amount,0))) AS 'nsf'";
|
||||
|
||||
$this->id = $id;
|
||||
$stats = $this->find('first', $query);
|
||||
return $stats[0];
|
||||
}
|
||||
|
||||
}
|
||||
1344
models/transaction.php
Normal file
1344
models/transaction.php
Normal file
File diff suppressed because it is too large
Load Diff
230
models/unit.php
Normal file
230
models/unit.php
Normal file
@@ -0,0 +1,230 @@
|
||||
<?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.moveout_date IS NULL',
|
||||
),
|
||||
);
|
||||
|
||||
var $hasMany = array(
|
||||
'Lease',
|
||||
);
|
||||
|
||||
//var $default_log_level = array('log' => 30, 'show' => 15);
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* helpers: status enumerations
|
||||
*/
|
||||
|
||||
function statusEnums() {
|
||||
static $status_enums;
|
||||
if (!isset($status_enums))
|
||||
$status_enums = $this->getEnumValues('status');
|
||||
return $status_enums;
|
||||
}
|
||||
|
||||
function activeStatusEnums() {
|
||||
return array_diff_key($this->statusEnums(), array(''=>1, 'DELETED'=>1));
|
||||
}
|
||||
|
||||
function statusValue($enum) {
|
||||
$enums = $this->statusEnums();
|
||||
return $enums[$enum];
|
||||
}
|
||||
|
||||
function occupiedEnumValue() {
|
||||
return $this->statusValue('OCCUPIED');
|
||||
}
|
||||
|
||||
function statusCheck($id_or_enum,
|
||||
$min = null, $min_strict = false,
|
||||
$max = null, $max_strict = false)
|
||||
{
|
||||
$this->prEnter(compact('id_or_enum', 'min', 'min_strict', 'max', 'max_strict'));
|
||||
|
||||
if (is_int($id_or_enum)) {
|
||||
$this->id = $id_or_enum;
|
||||
$id_or_enum = $this->field('status');
|
||||
}
|
||||
|
||||
$enum_val = $this->statusValue($id_or_enum);
|
||||
if (isset($min) && is_string($min))
|
||||
$min = $this->statusValue($min);
|
||||
if (isset($max) && is_string($max))
|
||||
$max = $this->statusValue($max);
|
||||
|
||||
$this->pr(17, compact('enum_val', 'min', 'min_strict', 'max', 'max_strict'));
|
||||
|
||||
if (isset($min) &&
|
||||
($enum_val < $min ||
|
||||
($min_strict && $enum_val == $min)))
|
||||
return $this->prReturn(false);
|
||||
|
||||
if (isset($max) &&
|
||||
($enum_val > $max ||
|
||||
($max_strict && $enum_val == $max)))
|
||||
return $this->prReturn(false);
|
||||
|
||||
return $this->prReturn(true);
|
||||
}
|
||||
|
||||
function occupied($enum) {
|
||||
return $this->statusCheck($enum, 'OCCUPIED', false, null, false);
|
||||
}
|
||||
|
||||
function conditionOccupied() {
|
||||
return ('Unit.status >= ' . $this->statusValue('OCCUPIED'));
|
||||
}
|
||||
|
||||
function vacant($enum) {
|
||||
return $this->statusCheck($enum, 'UNAVAILABLE', true, 'OCCUPIED', true);
|
||||
}
|
||||
|
||||
function conditionVacant() {
|
||||
return ('Unit.status BETWEEN ' .
|
||||
($this->statusValue('UNAVAILABLE')+1) .
|
||||
' AND ' .
|
||||
($this->statusValue('OCCUPIED')-1));
|
||||
}
|
||||
|
||||
function unavailable($enum) {
|
||||
return $this->statusCheck($enum, null, false, 'UNAVAILABLE', false);
|
||||
}
|
||||
|
||||
function conditionUnavailable() {
|
||||
return ('Unit.status <= ' . $this->statusValue('UNAVAILABLE'));
|
||||
}
|
||||
|
||||
function available($enum) { return $this->vacant($enum); }
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: allowedStatusSet
|
||||
* - Returns the status set allowed for the given unit
|
||||
*/
|
||||
function allowedStatusSet($id) {
|
||||
$this->prEnter(compact('id'));
|
||||
$this->id = $id;
|
||||
$old_status = $this->field('status');
|
||||
$old_val = $this->statusValue($old_status);
|
||||
$this->pr(17, compact('old_status', 'old_val'));
|
||||
|
||||
$enums = $this->activeStatusEnums();
|
||||
$this->pr(21, compact('enums'));
|
||||
|
||||
foreach ($enums AS $enum => $val) {
|
||||
if (($old_val < $this->occupiedEnumValue()) !=
|
||||
($val < $this->occupiedEnumValue())) {
|
||||
unset($enums[$enum]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->prReturn($enums);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: updateStatus
|
||||
* - Update the given unit to the given status
|
||||
*/
|
||||
function updateStatus($id, $status, $check = false) {
|
||||
$this->prEnter(compact('id', 'status', 'check'));
|
||||
|
||||
/* if ($check) { */
|
||||
/* $old_status = $this->field('status'); */
|
||||
/* $this->pr(17, compact('old_status')); */
|
||||
/* if ($this->statusValue($old_status) < $this->occupiedEnumValue() && */
|
||||
/* $this->statusValue($status) >= $this->occupiedEnumValue()) */
|
||||
/* { */
|
||||
/* die("Can't transition a unit from vacant to occupied"); */
|
||||
/* return $this->prReturn(false); */
|
||||
/* } */
|
||||
/* if ($this->statusValue($old_status) >= $this->occupiedEnumValue() && */
|
||||
/* $this->statusValue($status) < $this->occupiedEnumValue()) */
|
||||
/* { */
|
||||
/* die("Can't transition a unit from occupied to vacant"); */
|
||||
/* return $this->prReturn(false); */
|
||||
/* } */
|
||||
/* } */
|
||||
|
||||
if ($check) {
|
||||
if (!array_key_exists($status, $this->allowedStatusSet($id)))
|
||||
return $this->prReturn(false);
|
||||
}
|
||||
|
||||
$this->id = $id;
|
||||
$this->saveField('status', $status);
|
||||
return $this->prReturn(true);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* function: update
|
||||
* - Update any cached or calculated fields
|
||||
*/
|
||||
function update($id) {
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
**************************************************************************
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
25
models/unit_size.php
Normal file
25
models/unit_size.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
class UnitSize extends AppModel {
|
||||
|
||||
var $name = 'UnitSize';
|
||||
var $validate = array(
|
||||
'id' => array('numeric'),
|
||||
'unit_type_id' => array('numeric'),
|
||||
'code' => array('notempty'),
|
||||
'name' => array('notempty'),
|
||||
'width' => array('numeric'),
|
||||
'depth' => array('numeric'),
|
||||
'deposit' => array('money'),
|
||||
'amount' => array('money')
|
||||
);
|
||||
|
||||
var $belongsTo = array(
|
||||
'UnitType',
|
||||
);
|
||||
|
||||
var $hasMany = array(
|
||||
'Unit',
|
||||
);
|
||||
|
||||
}
|
||||
?>
|
||||
16
models/unit_type.php
Normal file
16
models/unit_type.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
class UnitType extends AppModel {
|
||||
|
||||
var $name = 'UnitType';
|
||||
var $validate = array(
|
||||
'id' => array('numeric'),
|
||||
'code' => array('notempty'),
|
||||
'name' => array('notempty')
|
||||
);
|
||||
|
||||
var $hasMany = array(
|
||||
'UnitSize',
|
||||
);
|
||||
|
||||
}
|
||||
?>
|
||||
5
plugins/debug_kit/README
Normal file
5
plugins/debug_kit/README
Normal file
@@ -0,0 +1,5 @@
|
||||
To install copy the debug_kit directory to the plugins folder and include the toolbar component in your app_controller.php:
|
||||
|
||||
$components = array('DebugKit.Toolbar');
|
||||
|
||||
+ Set debug mode to at least 1.
|
||||
0
plugins/debug_kit/controllers/components/empty
Normal file
0
plugins/debug_kit/controllers/components/empty
Normal file
471
plugins/debug_kit/controllers/components/toolbar.php
Normal file
471
plugins/debug_kit/controllers/components/toolbar.php
Normal file
@@ -0,0 +1,471 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* DebugKit DebugToolbar Component
|
||||
*
|
||||
*
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.
|
||||
* @since CakePHP v 1.2.0.4487
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
class ToolbarComponent extends Object {
|
||||
/**
|
||||
* Controller instance reference
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
var $controller;
|
||||
/**
|
||||
* Components used by DebugToolbar
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $components = array('RequestHandler');
|
||||
/**
|
||||
* The default panels the toolbar uses.
|
||||
* which panels are used can be configured when attaching the component
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $_defaultPanels = array('session', 'request', 'sqlLog', 'timer', 'log', 'memory', 'variables');
|
||||
/**
|
||||
* Loaded panel objects.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $panels = array();
|
||||
|
||||
/**
|
||||
* fallback for javascript settings
|
||||
*
|
||||
* @var array
|
||||
**/
|
||||
var $_defaultJavascript = array(
|
||||
'behavior' => '/debug_kit/js/js_debug_toolbar'
|
||||
);
|
||||
/**
|
||||
* javascript files component will be using.
|
||||
*
|
||||
* @var array
|
||||
**/
|
||||
var $javascript = array();
|
||||
/**
|
||||
* initialize
|
||||
*
|
||||
* If debug is off the component will be disabled and not do any further time tracking
|
||||
* or load the toolbar helper.
|
||||
*
|
||||
* @return bool
|
||||
**/
|
||||
function initialize(&$controller, $settings) {
|
||||
if (Configure::read('debug') == 0) {
|
||||
$this->enabled = false;
|
||||
return false;
|
||||
}
|
||||
App::import('Vendor', 'DebugKit.DebugKitDebugger');
|
||||
|
||||
DebugKitDebugger::startTimer('componentInit', __('Component initialization and startup', true));
|
||||
if (!isset($settings['panels'])) {
|
||||
$settings['panels'] = $this->_defaultPanels;
|
||||
}
|
||||
|
||||
if (isset($settings['javascript'])) {
|
||||
$settings['javascript'] = $this->_setJavascript($settings['javascript']);
|
||||
} else {
|
||||
$settings['javascript'] = $this->_defaultJavascript;
|
||||
}
|
||||
$this->_loadPanels($settings['panels']);
|
||||
unset($settings['panels']);
|
||||
|
||||
$this->_set($settings);
|
||||
$this->controller =& $controller;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component Startup
|
||||
*
|
||||
* @return bool
|
||||
**/
|
||||
function startup(&$controller) {
|
||||
$currentViewClass = $controller->view;
|
||||
$this->_makeViewClass($currentViewClass);
|
||||
$controller->view = 'DebugKit.Debug';
|
||||
if (!isset($controller->params['url']['ext']) || (isset($controller->params['url']['ext']) && $controller->params['url']['ext'] == 'html')) {
|
||||
$format = 'Html';
|
||||
} else {
|
||||
$format = 'FirePhp';
|
||||
}
|
||||
$controller->helpers['DebugKit.Toolbar'] = array('output' => sprintf('DebugKit.%sToolbar', $format));
|
||||
$panels = array_keys($this->panels);
|
||||
foreach ($panels as $panelName) {
|
||||
$this->panels[$panelName]->startup($controller);
|
||||
}
|
||||
DebugKitDebugger::stopTimer('componentInit');
|
||||
DebugKitDebugger::startTimer('controllerAction', __('Controller Action', true));
|
||||
}
|
||||
/**
|
||||
* beforeRender callback
|
||||
*
|
||||
* Calls beforeRender on all the panels and set the aggregate to the controller.
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function beforeRender(&$controller) {
|
||||
DebugKitDebugger::stopTimer('controllerAction');
|
||||
$vars = array();
|
||||
$panels = array_keys($this->panels);
|
||||
|
||||
foreach ($panels as $panelName) {
|
||||
$panel =& $this->panels[$panelName];
|
||||
$vars[$panelName]['content'] = $panel->beforeRender($controller);
|
||||
$elementName = Inflector::underscore($panelName) . '_panel';
|
||||
if (isset($panel->elementName)) {
|
||||
$elementName = $panel->elementName;
|
||||
}
|
||||
$vars[$panelName]['elementName'] = $elementName;
|
||||
$vars[$panelName]['plugin'] = $panel->plugin;
|
||||
$vars[$panelName]['disableTimer'] = true;
|
||||
}
|
||||
|
||||
$controller->set(array('debugToolbarPanels' => $vars, 'debugToolbarJavascript' => $this->javascript));
|
||||
DebugKitDebugger::startTimer('controllerRender', __('Render Controller Action', true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load Panels used in the debug toolbar
|
||||
*
|
||||
* @return void
|
||||
* @access protected
|
||||
**/
|
||||
function _loadPanels($panels) {
|
||||
foreach ($panels as $panel) {
|
||||
$className = $panel . 'Panel';
|
||||
if (!class_exists($className) && !App::import('Vendor', $className)) {
|
||||
trigger_error(sprintf(__('Could not load DebugToolbar panel %s', true), $panel), E_USER_WARNING);
|
||||
continue;
|
||||
}
|
||||
$panelObj =& new $className();
|
||||
if (is_subclass_of($panelObj, 'DebugPanel') || is_subclass_of($panelObj, 'debugpanel')) {
|
||||
$this->panels[$panel] =& $panelObj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the javascript to user scripts.
|
||||
*
|
||||
* Set either script key to false to exclude it from the rendered layout.
|
||||
*
|
||||
* @param array $scripts Javascript config information
|
||||
* @return array
|
||||
* @access protected
|
||||
**/
|
||||
function _setJavascript($scripts) {
|
||||
$behavior = false;
|
||||
if (!is_array($scripts)) {
|
||||
$scripts = (array)$scripts;
|
||||
}
|
||||
if (isset($scripts[0])) {
|
||||
$behavior = $scripts[0];
|
||||
}
|
||||
if (isset($scripts['behavior'])) {
|
||||
$behavior = $scripts['behavior'];
|
||||
}
|
||||
if (!$behavior) {
|
||||
return array();
|
||||
} elseif ($behavior === true) {
|
||||
$behavior = 'js';
|
||||
}
|
||||
if (strpos($behavior, '/') !== 0) {
|
||||
$behavior .= '_debug_toolbar';
|
||||
}
|
||||
$pluginFile = APP . 'plugins' . DS . 'debug_kit' . DS . 'vendors' . DS . 'js' . DS . $behavior . '.js';
|
||||
if (file_exists($pluginFile)) {
|
||||
$behavior = '/debug_kit/js/' . $behavior . '.js';
|
||||
}
|
||||
return compact('behavior');
|
||||
}
|
||||
/**
|
||||
* Makes the DoppleGangerView class if it doesn't already exist.
|
||||
* This allows DebugView to be compatible with all view classes.
|
||||
*
|
||||
* @param string $baseClassName
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
function _makeViewClass($baseClassName) {
|
||||
if (!class_exists('DoppelGangerView')) {
|
||||
App::import('View', $baseClassName);
|
||||
if (strpos('View', $baseClassName) === false) {
|
||||
$baseClassName .= 'View';
|
||||
}
|
||||
$class = "class DoppelGangerView extends $baseClassName {}";
|
||||
eval($class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug Panel
|
||||
*
|
||||
* Abstract class for debug panels.
|
||||
*
|
||||
* @package cake.debug_kit
|
||||
*/
|
||||
class DebugPanel extends Object {
|
||||
/**
|
||||
* Defines which plugin this panel is from so the element can be located.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
var $plugin = null;
|
||||
/**
|
||||
* startup the panel
|
||||
*
|
||||
* Pull information from the controller / request
|
||||
*
|
||||
* @param object $controller Controller reference.
|
||||
* @return void
|
||||
**/
|
||||
function startup(&$controller) { }
|
||||
|
||||
/**
|
||||
* Prepare output vars before Controller Rendering.
|
||||
*
|
||||
* @param object $controller Controller reference.
|
||||
* @return void
|
||||
**/
|
||||
function beforeRender(&$controller) { }
|
||||
}
|
||||
|
||||
/**
|
||||
* Variables Panel
|
||||
*
|
||||
* Provides debug information on the View variables.
|
||||
*
|
||||
* @package cake.debug_kit.panels
|
||||
**/
|
||||
class VariablesPanel extends DebugPanel {
|
||||
var $plugin = 'debug_kit';
|
||||
}
|
||||
|
||||
/**
|
||||
* Session Panel
|
||||
*
|
||||
* Provides debug information on the Session contents.
|
||||
*
|
||||
* @package cake.debug_kit.panels
|
||||
**/
|
||||
class SessionPanel extends DebugPanel {
|
||||
var $plugin = 'debug_kit';
|
||||
/**
|
||||
* beforeRender callback
|
||||
*
|
||||
* @param object $controller
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
function beforeRender(&$controller) {
|
||||
return $controller->Session->read();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request Panel
|
||||
*
|
||||
* Provides debug information on the Current request params.
|
||||
*
|
||||
* @package cake.debug_kit.panels
|
||||
**/
|
||||
class RequestPanel extends DebugPanel {
|
||||
var $plugin = 'debug_kit';
|
||||
/**
|
||||
* beforeRender callback - grabs request params
|
||||
*
|
||||
* @return array
|
||||
**/
|
||||
function beforeRender(&$controller) {
|
||||
$out = array();
|
||||
$out['params'] = $controller->params;
|
||||
if (isset($controller->Cookie)) {
|
||||
$out['cookie'] = $controller->Cookie->read();
|
||||
}
|
||||
$out['get'] = $_GET;
|
||||
$out['currentRoute'] = Router::currentRoute();
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Timer Panel
|
||||
*
|
||||
* Provides debug information on all timers used in a request.
|
||||
*
|
||||
* @package cake.debug_kit.panels
|
||||
**/
|
||||
class TimerPanel extends DebugPanel {
|
||||
var $plugin = 'debug_kit';
|
||||
/**
|
||||
* startup - add in necessary helpers
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function startup(&$controller) {
|
||||
if (!in_array('Number', $controller->helpers)) {
|
||||
$controller->helpers[] = 'Number';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Memory Panel
|
||||
*
|
||||
* Provides debug information on the memory consumption.
|
||||
*
|
||||
* @package cake.debug_kit.panels
|
||||
**/
|
||||
class MemoryPanel extends DebugPanel {
|
||||
var $plugin = 'debug_kit';
|
||||
/**
|
||||
* startup - add in necessary helpers
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function startup(&$controller) {
|
||||
if (!in_array('Number', $controller->helpers)) {
|
||||
$controller->helpers[] = 'Number';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sqlLog Panel
|
||||
*
|
||||
* Provides debug information on the SQL logs and provides links to an ajax explain interface.
|
||||
*
|
||||
* @package cake.debug_kit.panels
|
||||
**/
|
||||
class sqlLogPanel extends DebugPanel {
|
||||
var $plugin = 'debug_kit';
|
||||
|
||||
var $dbConfigs = array();
|
||||
/**
|
||||
* get db configs.
|
||||
*
|
||||
* @param string $controller
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function startUp(&$controller) {
|
||||
if (!class_exists('ConnectionManager')) {
|
||||
$this->dbConfigs = array();
|
||||
return false;
|
||||
}
|
||||
$this->dbConfigs = ConnectionManager::sourceList();
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Get Sql Logs for each DB config
|
||||
*
|
||||
* @param string $controller
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function beforeRender(&$controller) {
|
||||
$queryLogs = array();
|
||||
if (!class_exists('ConnectionManager')) {
|
||||
return array();
|
||||
}
|
||||
foreach ($this->dbConfigs as $configName) {
|
||||
$db =& ConnectionManager::getDataSource($configName);
|
||||
if ($db->isInterfaceSupported('showLog')) {
|
||||
ob_start();
|
||||
$db->showLog();
|
||||
$queryLogs[$configName] = ob_get_clean();
|
||||
}
|
||||
}
|
||||
return $queryLogs;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log Panel - Reads log entries made this request.
|
||||
*
|
||||
* @package cake.debug_kit.panels
|
||||
*/
|
||||
class LogPanel extends DebugPanel {
|
||||
var $plugin = 'debug_kit';
|
||||
/**
|
||||
* Log files to scan
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $logFiles = array('error.log', 'debug.log');
|
||||
/**
|
||||
* startup
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function startup(&$controller) {
|
||||
if (!class_exists('CakeLog')) {
|
||||
App::import('Core', 'Log');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* beforeRender Callback
|
||||
*
|
||||
* @return array
|
||||
**/
|
||||
function beforeRender(&$controller) {
|
||||
$this->startTime = DebugKitDebugger::requestStartTime();
|
||||
$this->currentTime = DebugKitDebugger::requestTime();
|
||||
$out = array();
|
||||
foreach ($this->logFiles as $log) {
|
||||
$file = LOGS . $log;
|
||||
if (!file_exists($file)) {
|
||||
continue;
|
||||
}
|
||||
$out[$log] = $this->_parseFile($file);
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
/**
|
||||
* parse a log file and find the relevant entries
|
||||
*
|
||||
* @param string $filename Name of file to read
|
||||
* @access protected
|
||||
* @return array
|
||||
*/
|
||||
function _parseFile($filename) {
|
||||
$file =& new File($filename);
|
||||
$contents = $file->read();
|
||||
$timePattern = '/(\d{4}-\d{2}\-\d{2}\s\d{1,2}\:\d{1,2}\:\d{1,2})/';
|
||||
$chunks = preg_split($timePattern, $contents, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
|
||||
for ($i = 0, $len = count($chunks); $i < $len; $i += 2) {
|
||||
if (strtotime($chunks[$i]) < $this->startTime) {
|
||||
unset($chunks[$i], $chunks[$i + 1]);
|
||||
}
|
||||
}
|
||||
return array_values($chunks);
|
||||
}
|
||||
}
|
||||
?>
|
||||
32
plugins/debug_kit/debug_kit_app_controller.php
Normal file
32
plugins/debug_kit/debug_kit_app_controller.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Debug Kit App Controller
|
||||
*
|
||||
*
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.
|
||||
* @since CakePHP v 1.2.0.4487
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
class DebugKitAppController extends AppController {
|
||||
|
||||
}
|
||||
?>
|
||||
32
plugins/debug_kit/debug_kit_app_model.php
Normal file
32
plugins/debug_kit/debug_kit_app_model.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Debug Kit App Model
|
||||
*
|
||||
*
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.
|
||||
* @since CakePHP v 1.2.0.4487
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
class DebugKitAppModel extends AppModel {
|
||||
|
||||
}
|
||||
?>
|
||||
0
plugins/debug_kit/models/empty
Normal file
0
plugins/debug_kit/models/empty
Normal file
@@ -0,0 +1,323 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* DebugToolbar Test
|
||||
*
|
||||
*
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.
|
||||
* @since CakePHP v 1.2.0.4487
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
App::import('Component', 'DebugKit.Toolbar');
|
||||
|
||||
class TestToolbarComponent extends ToolbarComponent {
|
||||
|
||||
function loadPanels($panels) {
|
||||
$this->_loadPanels($panels);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Mock::generate('DebugPanel');
|
||||
|
||||
/**
|
||||
* DebugToolbar Test case
|
||||
*/
|
||||
class DebugToolbarTestCase extends CakeTestCase {
|
||||
|
||||
function setUp() {
|
||||
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
|
||||
Router::parse('/');
|
||||
$this->Controller =& ClassRegistry::init('Controller');
|
||||
$this->Controller->Component =& ClassRegistry::init('Component');
|
||||
$this->Controller->Toolbar =& ClassRegistry::init('TestToolBarComponent', 'Component');
|
||||
}
|
||||
|
||||
/**
|
||||
* test Loading of panel classes
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testLoadPanels() {
|
||||
$this->Controller->Toolbar->loadPanels(array('session', 'request'));
|
||||
$this->assertTrue(is_a($this->Controller->Toolbar->panels['session'], 'SessionPanel'));
|
||||
$this->assertTrue(is_a($this->Controller->Toolbar->panels['request'], 'RequestPanel'));
|
||||
|
||||
$this->expectError();
|
||||
$this->Controller->Toolbar->loadPanels(array('randomNonExisting', 'request'));
|
||||
}
|
||||
|
||||
/**
|
||||
* test loading of vendor panels from test_app folder
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function testVendorPanels() {
|
||||
$_back = Configure::read('vendorPaths');
|
||||
Configure::write('vendorPaths', array(APP . 'plugins' . DS . 'debug_kit' . DS . 'tests' . DS . 'test_app' . DS . 'vendors' . DS));
|
||||
$this->Controller->components = array(
|
||||
'DebugKit.Toolbar' => array(
|
||||
'panels' => array('test'),
|
||||
)
|
||||
);
|
||||
$this->Controller->Component->init($this->Controller);
|
||||
$this->Controller->Component->initialize($this->Controller);
|
||||
$this->Controller->Component->startup($this->Controller);
|
||||
$this->assertTrue(isset($this->Controller->Toolbar->panels['test']));
|
||||
$this->assertTrue(is_a($this->Controller->Toolbar->panels['test'], 'TestPanel'));
|
||||
|
||||
Configure::write('vendorPaths', $_back);
|
||||
}
|
||||
|
||||
/**
|
||||
* test initialize
|
||||
*
|
||||
* @return void
|
||||
* @access public
|
||||
**/
|
||||
function testInitialize() {
|
||||
$this->Controller->components = array('DebugKit.Toolbar');
|
||||
$this->Controller->Component->init($this->Controller);
|
||||
$this->Controller->Component->initialize($this->Controller);
|
||||
|
||||
$this->assertFalse(empty($this->Controller->Toolbar->panels));
|
||||
|
||||
$timers = DebugKitDebugger::getTimers();
|
||||
$this->assertTrue(isset($timers['componentInit']));
|
||||
}
|
||||
|
||||
/**
|
||||
* test startup
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testStartup() {
|
||||
$this->Controller->components = array(
|
||||
'DebugKit.Toolbar' => array(
|
||||
'panels' => array('MockDebug')
|
||||
)
|
||||
);
|
||||
$this->Controller->Component->init($this->Controller);
|
||||
$this->Controller->Component->initialize($this->Controller);
|
||||
$this->Controller->Toolbar->panels['MockDebug']->expectOnce('startup');
|
||||
$this->Controller->Toolbar->startup($this->Controller);
|
||||
|
||||
$this->assertEqual(count($this->Controller->Toolbar->panels), 1);
|
||||
$this->assertTrue(isset($this->Controller->helpers['DebugKit.Toolbar']));
|
||||
$this->assertEqual($this->Controller->helpers['DebugKit.Toolbar'], array('output' => 'DebugKit.HtmlToolbar'));
|
||||
|
||||
$timers = DebugKitDebugger::getTimers();
|
||||
$this->assertTrue(isset($timers['controllerAction']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Before Render callback
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testBeforeRender() {
|
||||
$this->Controller->components = array(
|
||||
'DebugKit.Toolbar' => array(
|
||||
'panels' => array('MockDebug', 'session')
|
||||
)
|
||||
);
|
||||
$this->Controller->Component->init($this->Controller);
|
||||
$this->Controller->Component->initialize($this->Controller);
|
||||
$this->Controller->Toolbar->panels['MockDebug']->expectOnce('beforeRender');
|
||||
$this->Controller->Toolbar->beforeRender($this->Controller);
|
||||
|
||||
$this->assertTrue(isset($this->Controller->viewVars['debugToolbarPanels']));
|
||||
$vars = $this->Controller->viewVars['debugToolbarPanels'];
|
||||
|
||||
$expected = array(
|
||||
'plugin' => 'debug_kit',
|
||||
'elementName' => 'session_panel',
|
||||
'content' => $this->Controller->Session->read(),
|
||||
'disableTimer' => true,
|
||||
);
|
||||
$this->assertEqual($expected, $vars['session']);
|
||||
}
|
||||
|
||||
/**
|
||||
* test alternate javascript library use
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testAlternateJavascript() {
|
||||
$this->Controller->components = array(
|
||||
'DebugKit.Toolbar'
|
||||
);
|
||||
$this->Controller->Component->init($this->Controller);
|
||||
$this->Controller->Component->initialize($this->Controller);
|
||||
$this->Controller->Component->startup($this->Controller);
|
||||
$this->Controller->Component->beforeRender($this->Controller);
|
||||
$this->assertTrue(isset($this->Controller->viewVars['debugToolbarJavascript']));
|
||||
$expected = array(
|
||||
'behavior' => '/debug_kit/js/js_debug_toolbar',
|
||||
);
|
||||
$this->assertEqual($this->Controller->viewVars['debugToolbarJavascript'], $expected);
|
||||
|
||||
$this->Controller->components = array(
|
||||
'DebugKit.Toolbar' => array(
|
||||
'javascript' => 'jquery',
|
||||
),
|
||||
);
|
||||
$this->Controller->Component->init($this->Controller);
|
||||
$this->Controller->Component->initialize($this->Controller);
|
||||
$this->Controller->Component->startup($this->Controller);
|
||||
$this->Controller->Component->beforeRender($this->Controller);
|
||||
$this->assertTrue(isset($this->Controller->viewVars['debugToolbarJavascript']));
|
||||
$expected = array(
|
||||
'behavior' => '/debug_kit/js/jquery_debug_toolbar.js',
|
||||
);
|
||||
$this->assertEqual($this->Controller->viewVars['debugToolbarJavascript'], $expected);
|
||||
|
||||
|
||||
$this->Controller->components = array(
|
||||
'DebugKit.Toolbar' => array(
|
||||
'javascript' => false
|
||||
)
|
||||
);
|
||||
$this->Controller->Component->init($this->Controller);
|
||||
$this->Controller->Component->initialize($this->Controller);
|
||||
$this->Controller->Component->startup($this->Controller);
|
||||
$this->Controller->Component->beforeRender($this->Controller);
|
||||
$this->assertTrue(isset($this->Controller->viewVars['debugToolbarJavascript']));
|
||||
$expected = array();
|
||||
$this->assertEqual($this->Controller->viewVars['debugToolbarJavascript'], $expected);
|
||||
|
||||
|
||||
$this->Controller->components = array(
|
||||
'DebugKit.Toolbar' => array(
|
||||
'javascript' => array('my_library'),
|
||||
),
|
||||
);
|
||||
$this->Controller->Component->init($this->Controller);
|
||||
$this->Controller->Component->initialize($this->Controller);
|
||||
$this->Controller->Component->startup($this->Controller);
|
||||
$this->Controller->Component->beforeRender($this->Controller);
|
||||
$this->assertTrue(isset($this->Controller->viewVars['debugToolbarJavascript']));
|
||||
$expected = array(
|
||||
'behavior' => 'my_library_debug_toolbar'
|
||||
);
|
||||
$this->assertEqual($this->Controller->viewVars['debugToolbarJavascript'], $expected);
|
||||
|
||||
$this->Controller->components = array(
|
||||
'DebugKit.Toolbar' => array(
|
||||
'javascript' => array('/my/path/to/file')
|
||||
),
|
||||
);
|
||||
$this->Controller->Component->init($this->Controller);
|
||||
$this->Controller->Component->initialize($this->Controller);
|
||||
$this->Controller->Component->startup($this->Controller);
|
||||
$this->Controller->Component->beforeRender($this->Controller);
|
||||
$this->assertTrue(isset($this->Controller->viewVars['debugToolbarJavascript']));
|
||||
$expected = array(
|
||||
'behavior' => '/my/path/to/file',
|
||||
);
|
||||
$this->assertEqual($this->Controller->viewVars['debugToolbarJavascript'], $expected);
|
||||
|
||||
$this->Controller->components = array(
|
||||
'DebugKit.Toolbar' => array(
|
||||
'javascript' => '/js/custom_behavior',
|
||||
),
|
||||
);
|
||||
$this->Controller->Component->init($this->Controller);
|
||||
$this->Controller->Component->initialize($this->Controller);
|
||||
$this->Controller->Component->startup($this->Controller);
|
||||
$this->Controller->Component->beforeRender($this->Controller);
|
||||
$this->assertTrue(isset($this->Controller->viewVars['debugToolbarJavascript']));
|
||||
$expected = array(
|
||||
'behavior' => '/js/custom_behavior',
|
||||
);
|
||||
$this->assertEqual($this->Controller->viewVars['debugToolbarJavascript'], $expected);
|
||||
}
|
||||
/**
|
||||
* Test alternate javascript existing in the plugin.
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testExistingAlterateJavascript() {
|
||||
$filename = APP . 'plugins' . DS . 'debug_kit' . DS . 'vendors' . DS . 'js' . DS . 'test_alternate_debug_toolbar.js';
|
||||
$this->skipIf(!is_writable(dirname($filename)), 'Skipping existing javascript test, debug_kit/vendors/js must be writable');
|
||||
|
||||
@touch($filename);
|
||||
$this->Controller->components = array(
|
||||
'DebugKit.Toolbar' => array(
|
||||
'javascript' => 'test_alternate',
|
||||
),
|
||||
);
|
||||
$this->Controller->Component->init($this->Controller);
|
||||
$this->Controller->Component->initialize($this->Controller);
|
||||
$this->Controller->Component->startup($this->Controller);
|
||||
$this->Controller->Component->beforeRender($this->Controller);
|
||||
$this->assertTrue(isset($this->Controller->viewVars['debugToolbarJavascript']));
|
||||
$expected = array(
|
||||
'behavior' => '/debug_kit/js/test_alternate_debug_toolbar.js',
|
||||
);
|
||||
$this->assertEqual($this->Controller->viewVars['debugToolbarJavascript'], $expected);
|
||||
@unlink($filename);
|
||||
}
|
||||
/**
|
||||
* test the Log panel log reading.
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testLogPanel() {
|
||||
usleep(20);
|
||||
$this->Controller->log('This is a log I made this request');
|
||||
$this->Controller->log('This is the second log I made this request');
|
||||
$this->Controller->log('This time in the debug log!', LOG_DEBUG);
|
||||
|
||||
$this->Controller->components = array(
|
||||
'DebugKit.Toolbar' => array(
|
||||
'panels' => array('log', 'session')
|
||||
)
|
||||
);
|
||||
$this->Controller->Component->init($this->Controller);
|
||||
$this->Controller->Component->initialize($this->Controller);
|
||||
$this->Controller->Component->startup($this->Controller);
|
||||
$this->Controller->Component->beforeRender($this->Controller);
|
||||
$result = $this->Controller->viewVars['debugToolbarPanels']['log'];
|
||||
|
||||
$this->assertEqual(count($result['content']), 2);
|
||||
$this->assertEqual(count($result['content']['error.log']), 4);
|
||||
$this->assertEqual(count($result['content']['debug.log']), 2);
|
||||
|
||||
$this->assertEqual(trim($result['content']['debug.log'][1]), 'Debug: This time in the debug log!');
|
||||
$this->assertEqual(trim($result['content']['error.log'][1]), 'Error: This is a log I made this request');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* teardown
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function tearDown() {
|
||||
unset($this->Controller);
|
||||
if (class_exists('DebugKitDebugger')) {
|
||||
DebugKitDebugger::clearTimers();
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
0
plugins/debug_kit/tests/cases/empty
Normal file
0
plugins/debug_kit/tests/cases/empty
Normal file
62
plugins/debug_kit/tests/cases/test_objects.php
Normal file
62
plugins/debug_kit/tests/cases/test_objects.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Common test objects used in DebugKit tests
|
||||
*
|
||||
* Long description for file
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP(tm) Tests <https://trac.cakephp.org/wiki/Developement/TestSuite>
|
||||
* Copyright 2005-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The Open Group Test Suite License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2005-2008, Cake Software Foundation, Inc.
|
||||
* @link https://trac.cakephp.org/wiki/Developement/TestSuite CakePHP(tm) Tests
|
||||
* @package cake.tests
|
||||
* @subpackage cake.tests.cases.libs
|
||||
* @since CakePHP(tm) v 1.2.0.5432
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
|
||||
*/
|
||||
/**
|
||||
* TestFireCake class allows for testing of FireCake
|
||||
*
|
||||
* @package debug_kit.tests.
|
||||
*/
|
||||
class TestFireCake extends FireCake {
|
||||
var $sentHeaders = array();
|
||||
|
||||
function _sendHeader($name, $value) {
|
||||
$_this = FireCake::getInstance();
|
||||
$_this->sentHeaders[$name] = $value;
|
||||
}
|
||||
/**
|
||||
* skip client detection as headers are not being sent.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function detectClientExtension() {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Reset the fireCake
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function reset() {
|
||||
$_this = FireCake::getInstance();
|
||||
$_this->sentHeaders = array();
|
||||
$_this->_messageIndex = 1;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
157
plugins/debug_kit/tests/cases/vendors/debug_kit_debugger.test.php
vendored
Normal file
157
plugins/debug_kit/tests/cases/vendors/debug_kit_debugger.test.php
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* DebugKit Debugger Test Case File
|
||||
*
|
||||
* Long description for file
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP(tm) Tests <https://trac.cakephp.org/wiki/Developement/TestSuite>
|
||||
* Copyright 2005-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The Open Group Test Suite License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2005-2008, Cake Software Foundation, Inc.
|
||||
* @link https://trac.cakephp.org/wiki/Developement/TestSuite CakePHP(tm) Tests
|
||||
* @package cake.tests
|
||||
* @subpackage cake.tests.cases.libs
|
||||
* @since CakePHP(tm) v 1.2.0.5432
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/opengroup.php The Open Group Test Suite License
|
||||
*/
|
||||
App::import('Core', 'Debugger');
|
||||
App::import('Vendor', 'DebugKit.DebugKitDebugger');
|
||||
|
||||
require_once APP . 'plugins' . DS . 'debug_kit' . DS . 'tests' . DS . 'cases' . DS . 'test_objects.php';
|
||||
|
||||
/**
|
||||
* Short description for class.
|
||||
*
|
||||
* @package cake.tests
|
||||
* @subpackage cake.tests.cases.libs
|
||||
*/
|
||||
class DebugKitDebuggerTest extends CakeTestCase {
|
||||
/**
|
||||
* setUp method
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function setUp() {
|
||||
Configure::write('log', false);
|
||||
if (!defined('SIMPLETESTVENDORPATH')) {
|
||||
if (file_exists(APP . DS . 'vendors' . DS . 'simpletest' . DS . 'reporter.php')) {
|
||||
define('SIMPLETESTVENDORPATH', 'APP' . DS . 'vendors');
|
||||
} else {
|
||||
define('SIMPLETESTVENDORPATH', 'CORE' . DS . 'vendors');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start Timer test
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testTimers() {
|
||||
$this->assertTrue(DebugKitDebugger::startTimer('test1', 'this is my first test'));
|
||||
usleep(5000);
|
||||
$this->assertTrue(DebugKitDebugger::stopTimer('test1'));
|
||||
$elapsed = DebugKitDebugger::elapsedTime('test1');
|
||||
$this->assertTrue($elapsed > 0.0050);
|
||||
|
||||
$this->assertTrue(DebugKitDebugger::startTimer('test2', 'this is my second test'));
|
||||
sleep(1);
|
||||
$this->assertTrue(DebugKitDebugger::stopTimer('test2'));
|
||||
$elapsed = DebugKitDebugger::elapsedTime('test2');
|
||||
$this->assertTrue($elapsed > 1);
|
||||
|
||||
DebugKitDebugger::startTimer('test3');
|
||||
$this->assertFalse(DebugKitDebugger::elapsedTime('test3'));
|
||||
$this->assertFalse(DebugKitDebugger::stopTimer('wrong'));
|
||||
}
|
||||
|
||||
/**
|
||||
* testRequestTime
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function testRequestTime() {
|
||||
$result1 = DebugKitDebugger::requestTime();
|
||||
usleep(50);
|
||||
$result2 = DebugKitDebugger::requestTime();
|
||||
$this->assertTrue($result1 < $result2);
|
||||
}
|
||||
|
||||
/**
|
||||
* test getting all the set timers.
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testGetTimers() {
|
||||
DebugKitDebugger::clearTimers();
|
||||
DebugKitDebugger::startTimer('test1', 'this is my first test');
|
||||
DebugKitDebugger::stopTimer('test1');
|
||||
usleep(50);
|
||||
DebugKitDebugger::startTimer('test2');
|
||||
DebugKitDebugger::stopTimer('test2');
|
||||
$timers = DebugKitDebugger::getTimers();
|
||||
|
||||
$this->assertEqual(count($timers), 2);
|
||||
$this->assertTrue(is_float($timers['test1']['time']));
|
||||
$this->assertTrue(isset($timers['test1']['message']));
|
||||
$this->assertTrue(isset($timers['test2']['message']));
|
||||
}
|
||||
|
||||
/**
|
||||
* test memory usage
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testMemoryUsage() {
|
||||
$result = DebugKitDebugger::getMemoryUse();
|
||||
$this->assertTrue(is_int($result));
|
||||
|
||||
$result = DebugKitDebugger::getPeakMemoryUse();
|
||||
$this->assertTrue(is_int($result));
|
||||
}
|
||||
/**
|
||||
* test _output switch to firePHP
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function testOutput() {
|
||||
$firecake =& FireCake::getInstance('TestFireCake');
|
||||
Debugger::invoke(DebugKitDebugger::getInstance('DebugKitDebugger'));
|
||||
Debugger::output('fb');
|
||||
$foo .= '';
|
||||
$result = $firecake->sentHeaders;
|
||||
|
||||
$this->assertPattern('/GROUP_START/', $result['X-Wf-1-1-1-1']);
|
||||
$this->assertPattern('/ERROR/', $result['X-Wf-1-1-1-2']);
|
||||
$this->assertPattern('/GROUP_END/', $result['X-Wf-1-1-1-5']);
|
||||
|
||||
Debugger::invoke(Debugger::getInstance('Debugger'));
|
||||
Debugger::output();
|
||||
}
|
||||
|
||||
/**
|
||||
* tearDown method
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function tearDown() {
|
||||
Configure::write('log', true);
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
336
plugins/debug_kit/tests/cases/vendors/fire_cake.test.php
vendored
Normal file
336
plugins/debug_kit/tests/cases/vendors/fire_cake.test.php
vendored
Normal file
@@ -0,0 +1,336 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* CakeFirePHP test case
|
||||
*
|
||||
*
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package debug_kit
|
||||
* @subpackage cake.debug_kit.tests
|
||||
* @since CakePHP v 1.2.0.4487
|
||||
* @version
|
||||
* @modifiedby
|
||||
* @lastmodified
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
App::import('Vendor', 'DebugKit.FireCake');
|
||||
|
||||
require_once APP . 'plugins' . DS . 'debug_kit' . DS . 'tests' . DS . 'cases' . DS . 'test_objects.php';
|
||||
/**
|
||||
* Test Case For FireCake
|
||||
*
|
||||
* @package debug_kit.tests
|
||||
*/
|
||||
class FireCakeTestCase extends CakeTestCase {
|
||||
/**
|
||||
* setup test
|
||||
*
|
||||
* Fill FireCake with TestFireCake instance.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function setUp() {
|
||||
$this->firecake =& FireCake::getInstance('TestFireCake');
|
||||
}
|
||||
/**
|
||||
* test getInstance cheat.
|
||||
*
|
||||
* If this fails the rest of the test is going to fail too.
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testGetInstanceOverride() {
|
||||
$instance =& FireCake::getInstance();
|
||||
$instance2 =& FireCake::getInstance();
|
||||
$this->assertReference($instance, $instance2);
|
||||
$this->assertIsA($instance, 'FireCake');
|
||||
$this->assertIsA($instance, 'TestFireCake', 'Stored instance is not a copy of TestFireCake, test case is broken.');
|
||||
}
|
||||
/**
|
||||
* testsetoption
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testSetOptions() {
|
||||
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||
$this->assertEqual($this->firecake->options['includeLineNumbers'], false);
|
||||
}
|
||||
/**
|
||||
* test Log()
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function testLog() {
|
||||
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||
FireCake::log('Testing');
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-Protocol-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Plugin-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Structure-1']));
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-Index'], 1);
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '26|[{"Type":"LOG"},"Testing"]|');
|
||||
|
||||
FireCake::log('Testing', 'log-info');
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-2'], '45|[{"Type":"LOG","Label":"log-info"},"Testing"]|');
|
||||
}
|
||||
/**
|
||||
* test info()
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function testInfo() {
|
||||
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||
FireCake::info('I have information');
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-Protocol-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Plugin-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Structure-1']));
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-Index'], 1);
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '38|[{"Type":"INFO"},"I have information"]|');
|
||||
|
||||
FireCake::info('I have information', 'info-label');
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-2'], '59|[{"Type":"INFO","Label":"info-label"},"I have information"]|');
|
||||
}
|
||||
/**
|
||||
* test info()
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function testWarn() {
|
||||
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||
FireCake::warn('A Warning');
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-Protocol-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Plugin-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Structure-1']));
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-Index'], 1);
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '29|[{"Type":"WARN"},"A Warning"]|');
|
||||
|
||||
FireCake::warn('A Warning', 'Bzzz');
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-2'], '44|[{"Type":"WARN","Label":"Bzzz"},"A Warning"]|');
|
||||
}
|
||||
/**
|
||||
* test error()
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
**/
|
||||
function testError() {
|
||||
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||
FireCake::error('An error');
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-Protocol-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Plugin-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Structure-1']));
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-Index'], 1);
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '29|[{"Type":"ERROR"},"An error"]|');
|
||||
|
||||
FireCake::error('An error', 'wonky');
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-2'], '45|[{"Type":"ERROR","Label":"wonky"},"An error"]|');
|
||||
}
|
||||
/**
|
||||
* test dump()
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testDump() {
|
||||
FireCake::dump('mydump', array('one' => 1, 'two' => 2));
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-2-1-1'], '28|{"mydump":{"one":1,"two":2}}|');
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Structure-2']));
|
||||
}
|
||||
/**
|
||||
* test table() generation
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testTable() {
|
||||
$table[] = array('Col 1 Heading','Col 2 Heading');
|
||||
$table[] = array('Row 1 Col 1','Row 1 Col 2');
|
||||
$table[] = array('Row 2 Col 1','Row 2 Col 2');
|
||||
$table[] = array('Row 3 Col 1','Row 3 Col 2');
|
||||
FireCake::table('myTrace', $table);
|
||||
$expected = '162|[{"Type":"TABLE","Label":"myTrace"},[["Col 1 Heading","Col 2 Heading"],["Row 1 Col 1","Row 1 Col 2"],["Row 2 Col 1","Row 2 Col 2"],["Row 3 Col 1","Row 3 Col 2"]]]|';
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-1'], $expected);
|
||||
}
|
||||
/**
|
||||
* testStringEncoding
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testStringEncode() {
|
||||
$result = $this->firecake->stringEncode(array(1,2,3));
|
||||
$this->assertEqual($result, array(1,2,3));
|
||||
|
||||
$this->firecake->setOptions(array('maxArrayDepth' => 3));
|
||||
$deep = array(1 => array(2 => array(3)));
|
||||
$result = $this->firecake->stringEncode($deep);
|
||||
$this->assertEqual($result, array(1 => array(2 => '** Max Array Depth (3) **')));
|
||||
|
||||
$obj =& FireCake::getInstance();
|
||||
$result = $this->firecake->stringEncode($obj);
|
||||
$this->assertTrue(is_array($result));
|
||||
$this->assertEqual($result['_defaultOptions']['useNativeJsonEncode'], true);
|
||||
$this->assertEqual($result['_log'], null);
|
||||
$this->assertEqual($result['_encodedObjects'][0], '** Recursion (TestFireCake) **');
|
||||
}
|
||||
/**
|
||||
* test trace()
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testTrace() {
|
||||
FireCake::trace('myTrace');
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-Protocol-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Plugin-1']));
|
||||
$this->assertTrue(isset($this->firecake->sentHeaders['X-Wf-1-Structure-1']));
|
||||
$dump = $this->firecake->sentHeaders['X-Wf-1-1-1-1'];
|
||||
$this->assertPattern('/"Message":"myTrace"/', $dump);
|
||||
$this->assertPattern('/"Trace":\[/', $dump);
|
||||
}
|
||||
/**
|
||||
* test enabling and disabling of FireCake output
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testEnableDisable() {
|
||||
FireCake::disable();
|
||||
FireCake::trace('myTrace');
|
||||
$this->assertTrue(empty($this->firecake->sentHeaders));
|
||||
|
||||
FireCake::enable();
|
||||
FireCake::trace('myTrace');
|
||||
$this->assertFalse(empty($this->firecake->sentHeaders));
|
||||
}
|
||||
/**
|
||||
* test correct line continuation markers on multi line headers.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function testMultiLineOutput() {
|
||||
FireCake::trace('myTrace');
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-Index'], 3);
|
||||
$header = $this->firecake->sentHeaders['X-Wf-1-1-1-1'];
|
||||
$this->assertEqual(substr($header, -2), '|\\');
|
||||
|
||||
$header = $this->firecake->sentHeaders['X-Wf-1-1-1-2'];
|
||||
$this->assertEqual(substr($header, -2), '|\\');
|
||||
|
||||
$header = $this->firecake->sentHeaders['X-Wf-1-1-1-3'];
|
||||
$this->assertEqual(substr($header, -1), '|');
|
||||
}
|
||||
|
||||
/**
|
||||
* test inclusion of line numbers
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testIncludeLineNumbers() {
|
||||
FireCake::setOptions(array('includeLineNumbers' => true));
|
||||
FireCake::info('Testing');
|
||||
$result = $this->firecake->sentHeaders['X-Wf-1-1-1-1'];
|
||||
$this->assertPattern('/"File"\:"APP.*fire_cake.test.php/', $result);
|
||||
$this->assertPattern('/"Line"\:\d+/', $result);
|
||||
}
|
||||
/**
|
||||
* test Group messages
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testGroup() {
|
||||
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||
FireCake::group('test');
|
||||
FireCake::info('my info');
|
||||
FireCake::groupEnd();
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '44|[{"Type":"GROUP_START","Label":"test"},null]|');
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-3'], '27|[{"Type":"GROUP_END"},null]|');
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-Index'], 3);
|
||||
}
|
||||
/**
|
||||
* test fb() parameter parsing
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testFbParameterParsing() {
|
||||
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||
FireCake::fb('Test');
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '23|[{"Type":"LOG"},"Test"]|');
|
||||
|
||||
FireCake::fb('Test', 'warn');
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-2'], '24|[{"Type":"WARN"},"Test"]|');
|
||||
|
||||
FireCake::fb('Test', 'Custom label', 'warn');
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-3'], '47|[{"Type":"WARN","Label":"Custom label"},"Test"]|');
|
||||
|
||||
$this->expectError();
|
||||
$this->assertFalse(FireCake::fb('Test', 'Custom label', 'warn', 'more parameters'));
|
||||
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-Index'], 3);
|
||||
}
|
||||
/**
|
||||
* Test defaulting to log if incorrect message type is used
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testIncorrectMessageType() {
|
||||
FireCake::setOptions(array('includeLineNumbers' => false));
|
||||
FireCake::fb('Hello World', 'foobared');
|
||||
$this->assertEqual($this->firecake->sentHeaders['X-Wf-1-1-1-1'], '30|[{"Type":"LOG"},"Hello World"]|');
|
||||
}
|
||||
/**
|
||||
* testClientExtensionDetection.
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testDetectClientExtension() {
|
||||
$back = env('HTTP_USER_AGENT');
|
||||
$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.4) Gecko/2008102920 Firefox/3.0.4 FirePHP/0.2.1';
|
||||
$this->assertTrue(FireCake::detectClientExtension());
|
||||
|
||||
$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.4) Gecko/2008102920 Firefox/3.0.4 FirePHP/0.0.4';
|
||||
$this->assertFalse(FireCake::detectClientExtension());
|
||||
|
||||
$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.4) Gecko/2008102920 Firefox/3.0.4';
|
||||
$this->assertFalse(FireCake::detectClientExtension());
|
||||
$_SERVER['HTTP_USER_AGENT'] = $back;
|
||||
}
|
||||
/**
|
||||
* test of Non Native JSON encoding.
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testNonNativeEncoding() {
|
||||
FireCake::setOptions(array('useNativeJsonEncode' => false));
|
||||
$json = FireCake::jsonEncode(array('one' => 1, 'two' => 2));
|
||||
$this->assertEqual($json, '{"one":1,"two":2}');
|
||||
|
||||
$json = FireCake::jsonEncode(array(1,2,3));
|
||||
$this->assertEqual($json, '[1,2,3]');
|
||||
|
||||
$json = FireCake::jsonEncode(FireCake::getInstance());
|
||||
$this->assertPattern('/"options"\:\{"maxObjectDepth"\:\d*,/', $json);
|
||||
}
|
||||
/**
|
||||
* reset the FireCake counters and headers.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function tearDown() {
|
||||
TestFireCake::reset();
|
||||
}
|
||||
}
|
||||
?>
|
||||
144
plugins/debug_kit/tests/cases/views/debug.test.php
Normal file
144
plugins/debug_kit/tests/cases/views/debug.test.php
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* DebugView test Case
|
||||
*
|
||||
*
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.
|
||||
* @since CakePHP v 1.2.0.4487
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
App::import('Core', 'View');
|
||||
|
||||
if (!class_exists('DoppelGangerView')) {
|
||||
class DoppelGangerView extends View {}
|
||||
}
|
||||
|
||||
App::import('View', 'DebugKit.Debug');
|
||||
App::import('Vendor', 'DebugKit.DebugKitDebugger');
|
||||
/**
|
||||
* Debug View Test Case
|
||||
*
|
||||
* @package debug_kit.tests
|
||||
*/
|
||||
class DebugViewTestCase extends CakeTestCase {
|
||||
/**
|
||||
* set Up test case
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function setUp() {
|
||||
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
|
||||
Router::parse('/');
|
||||
$this->Controller =& ClassRegistry::init('Controller');
|
||||
$this->View =& new DebugView($this->Controller, false);
|
||||
$this->_debug = Configure::read('debug');
|
||||
}
|
||||
|
||||
/**
|
||||
* start Case - switch view paths
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function startCase() {
|
||||
$this->_viewPaths = Configure::read('viewPaths');
|
||||
Configure::write('viewPaths', array(
|
||||
TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'views'. DS,
|
||||
APP . 'plugins' . DS . 'debug_kit' . DS . 'views'. DS,
|
||||
ROOT . DS . LIBS . 'view' . DS
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* test that element timers are working
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testElementTimers() {
|
||||
$result = $this->View->element('test_element');
|
||||
$this->assertPattern('/^this is the test element$/', $result);
|
||||
|
||||
$result = DebugKitDebugger::getTimers();
|
||||
$this->assertTrue(isset($result['render_test_element.ctp']));
|
||||
}
|
||||
|
||||
/**
|
||||
* test rendering and ensure that timers are being set.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function testRenderTimers() {
|
||||
$this->Controller->viewPath = 'posts';
|
||||
$this->Controller->action = 'index';
|
||||
$this->Controller->params = array(
|
||||
'action' => 'index',
|
||||
'controller' => 'posts',
|
||||
'plugin' => null,
|
||||
'url' => array('url' => 'posts/index'),
|
||||
'base' => null,
|
||||
'here' => '/posts/index',
|
||||
);
|
||||
$this->Controller->layout = 'default';
|
||||
$View =& new DebugView($this->Controller, false);
|
||||
$View->render('index');
|
||||
|
||||
$result = DebugKitDebugger::getTimers();
|
||||
$this->assertEqual(count($result), 3);
|
||||
$this->assertTrue(isset($result['viewRender']));
|
||||
$this->assertTrue(isset($result['render_default.ctp']));
|
||||
$this->assertTrue(isset($result['render_index.ctp']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for correct loading of helpers into custom view
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function testLoadHelpers() {
|
||||
$loaded = array();
|
||||
$result = $this->View->_loadHelpers($loaded, array('Html', 'Javascript', 'Number'));
|
||||
$this->assertTrue(is_object($result['Html']));
|
||||
$this->assertTrue(is_object($result['Javascript']));
|
||||
$this->assertTrue(is_object($result['Number']));
|
||||
}
|
||||
|
||||
/**
|
||||
* reset the view paths
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function endCase() {
|
||||
Configure::write('viewPaths', $this->_viewPaths);
|
||||
}
|
||||
|
||||
/**
|
||||
* tear down function
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function tearDown() {
|
||||
unset($this->View, $this->Controller);
|
||||
DebugKitDebugger::clearTimers();
|
||||
Configure::write('debug', $this->_debug);
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Toolbar Abstract Helper Test Case
|
||||
*
|
||||
*
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage debug_kit.tests.views.helpers
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
App::import('Helper', 'DebugKit.FirePhpToolbar');
|
||||
App::import('Core', array('View', 'Controller'));
|
||||
require_once APP . 'plugins' . DS . 'debug_kit' . DS . 'tests' . DS . 'cases' . DS . 'test_objects.php';
|
||||
|
||||
FireCake::getInstance('TestFireCake');
|
||||
|
||||
class FirePhpToolbarHelperTestCase extends CakeTestCase {
|
||||
/**
|
||||
* setUp
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function setUp() {
|
||||
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
|
||||
Router::parse('/');
|
||||
|
||||
$this->Toolbar =& new ToolbarHelper(array('output' => 'DebugKit.FirePhpToolbar'));
|
||||
$this->Toolbar->FirePhpToolbar =& new FirePhpToolbarHelper();
|
||||
|
||||
$this->Controller =& ClassRegistry::init('Controller');
|
||||
if (isset($this->_debug)) {
|
||||
Configure::write('debug', $this->_debug);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* start Case - switch view paths
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function startCase() {
|
||||
$this->_viewPaths = Configure::read('viewPaths');
|
||||
Configure::write('viewPaths', array(
|
||||
TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'views'. DS,
|
||||
APP . 'plugins' . DS . 'debug_kit' . DS . 'views'. DS,
|
||||
ROOT . DS . LIBS . 'view' . DS
|
||||
));
|
||||
$this->_debug = Configure::read('debug');
|
||||
$this->firecake =& FireCake::getInstance();
|
||||
}
|
||||
/**
|
||||
* test neat array (dump)creation
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function testMakeNeatArray() {
|
||||
$this->Toolbar->makeNeatArray(array(1,2,3));
|
||||
$result = $this->firecake->sentHeaders;
|
||||
$this->assertTrue(isset($result['X-Wf-1-1-1-1']));
|
||||
$this->assertPattern('/\[1,2,3\]/', $result['X-Wf-1-1-1-1']);
|
||||
}
|
||||
/**
|
||||
* testAfterlayout element rendering
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function testAfterLayout(){
|
||||
$this->Controller->viewPath = 'posts';
|
||||
$this->Controller->action = 'index';
|
||||
$this->Controller->params = array(
|
||||
'action' => 'index',
|
||||
'controller' => 'posts',
|
||||
'plugin' => null,
|
||||
'url' => array('url' => 'posts/index', 'ext' => 'xml'),
|
||||
'base' => null,
|
||||
'here' => '/posts/index',
|
||||
);
|
||||
$this->Controller->layout = 'default';
|
||||
$this->Controller->uses = null;
|
||||
$this->Controller->components = array('DebugKit.Toolbar');
|
||||
$this->Controller->constructClasses();
|
||||
$this->Controller->Component->initialize($this->Controller);
|
||||
$this->Controller->Component->startup($this->Controller);
|
||||
$this->Controller->Component->beforeRender($this->Controller);
|
||||
$result = $this->Controller->render();
|
||||
$this->assertNoPattern('/debug-toolbar/', $result);
|
||||
$result = $this->firecake->sentHeaders;
|
||||
$this->assertTrue(is_array($result));
|
||||
|
||||
}
|
||||
/**
|
||||
* endTest()
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function endTest() {
|
||||
TestFireCake::reset();
|
||||
}
|
||||
/**
|
||||
* reset the view paths
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function endCase() {
|
||||
Configure::write('viewPaths', $this->_viewPaths);
|
||||
}
|
||||
|
||||
/**
|
||||
* tearDown
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function tearDown() {
|
||||
unset($this->Toolbar, $this->Controller);
|
||||
ClassRegistry::removeObject('view');
|
||||
ClassRegistry::flush();
|
||||
Router::reload();
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,358 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Toolbar HTML Helper Test Case
|
||||
*
|
||||
*
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage debug_kit.tests.views.helpers
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
App::import('Helper', array('DebugKit.HtmlToolbar', 'Html', 'Javascript'));
|
||||
App::import('Core', array('View', 'Controller'));
|
||||
|
||||
class HtmlToolbarHelperTestCase extends CakeTestCase {
|
||||
/**
|
||||
* setUp
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function setUp() {
|
||||
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
|
||||
Router::parse('/');
|
||||
|
||||
$this->Toolbar =& new ToolbarHelper(array('output' => 'DebugKit.HtmlToolbar'));
|
||||
$this->Toolbar->HtmlToolbar =& new HtmlToolbarHelper();
|
||||
$this->Toolbar->HtmlToolbar->Html =& new HtmlHelper();
|
||||
$this->Toolbar->HtmlToolbar->Javascript =& new JavascriptHelper();
|
||||
|
||||
$this->Controller =& ClassRegistry::init('Controller');
|
||||
if (isset($this->_debug)) {
|
||||
Configure::write('debug', $this->_debug);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* start Case - switch view paths
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function startCase() {
|
||||
$this->_viewPaths = Configure::read('viewPaths');
|
||||
Configure::write('viewPaths', array(
|
||||
TEST_CAKE_CORE_INCLUDE_PATH . 'tests' . DS . 'test_app' . DS . 'views'. DS,
|
||||
APP . 'plugins' . DS . 'debug_kit' . DS . 'views'. DS,
|
||||
ROOT . DS . LIBS . 'view' . DS
|
||||
));
|
||||
$this->_debug = Configure::read('debug');
|
||||
}
|
||||
|
||||
/**
|
||||
* test Neat Array formatting
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testMakeNeatArray() {
|
||||
$in = false;
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0'),
|
||||
'<li', '<strong', '0' , '/strong', '(false)', '/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$in = null;
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0'),
|
||||
'<li', '<strong', '0' , '/strong', '(null)', '/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$in = true;
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0'),
|
||||
'<li', '<strong', '0' , '/strong', '(true)', '/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$in = array('key' => 'value');
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0'),
|
||||
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$in = array('key' => null);
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0'),
|
||||
'<li', '<strong', 'key', '/strong', '(null)', '/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$in = array('key' => 'value', 'foo' => 'bar');
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0'),
|
||||
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||
'<li', '<strong', 'foo', '/strong', 'bar', '/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$in = array(
|
||||
'key' => 'value',
|
||||
'foo' => array(
|
||||
'this' => 'deep',
|
||||
'another' => 'value'
|
||||
)
|
||||
);
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0'),
|
||||
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||
'<li', '<strong', 'foo', '/strong',
|
||||
array('ul' => array('class' => 'neat-array depth-1')),
|
||||
'<li', '<strong', 'this', '/strong', 'deep', '/li',
|
||||
'<li', '<strong', 'another', '/strong', 'value', '/li',
|
||||
'/ul',
|
||||
'/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$in = array(
|
||||
'key' => 'value',
|
||||
'foo' => array(
|
||||
'this' => 'deep',
|
||||
'another' => 'value'
|
||||
),
|
||||
'lotr' => array(
|
||||
'gandalf' => 'wizard',
|
||||
'bilbo' => 'hobbit'
|
||||
)
|
||||
);
|
||||
$result = $this->Toolbar->makeNeatArray($in, 1);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0 expanded'),
|
||||
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||
'<li', '<strong', 'foo', '/strong',
|
||||
array('ul' => array('class' => 'neat-array depth-1')),
|
||||
'<li', '<strong', 'this', '/strong', 'deep', '/li',
|
||||
'<li', '<strong', 'another', '/strong', 'value', '/li',
|
||||
'/ul',
|
||||
'/li',
|
||||
'<li', '<strong', 'lotr', '/strong',
|
||||
array('ul' => array('class' => 'neat-array depth-1')),
|
||||
'<li', '<strong', 'gandalf', '/strong', 'wizard', '/li',
|
||||
'<li', '<strong', 'bilbo', '/strong', 'hobbit', '/li',
|
||||
'/ul',
|
||||
'/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$result = $this->Toolbar->makeNeatArray($in, 2);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0 expanded'),
|
||||
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||
'<li', '<strong', 'foo', '/strong',
|
||||
array('ul' => array('class' => 'neat-array depth-1 expanded')),
|
||||
'<li', '<strong', 'this', '/strong', 'deep', '/li',
|
||||
'<li', '<strong', 'another', '/strong', 'value', '/li',
|
||||
'/ul',
|
||||
'/li',
|
||||
'<li', '<strong', 'lotr', '/strong',
|
||||
array('ul' => array('class' => 'neat-array depth-1 expanded')),
|
||||
'<li', '<strong', 'gandalf', '/strong', 'wizard', '/li',
|
||||
'<li', '<strong', 'bilbo', '/strong', 'hobbit', '/li',
|
||||
'/ul',
|
||||
'/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
|
||||
$in = array('key' => 'value', 'array' => array());
|
||||
$result = $this->Toolbar->makeNeatArray($in);
|
||||
$expected = array(
|
||||
'ul' => array('class' => 'neat-array depth-0'),
|
||||
'<li', '<strong', 'key', '/strong', 'value', '/li',
|
||||
'<li', '<strong', 'array', '/strong', '(empty)', '/li',
|
||||
'/ul'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test injection of toolbar
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testInjectToolbar() {
|
||||
$this->Controller->viewPath = 'posts';
|
||||
$this->Controller->action = 'index';
|
||||
$this->Controller->params = array(
|
||||
'action' => 'index',
|
||||
'controller' => 'posts',
|
||||
'plugin' => null,
|
||||
'url' => array('url' => 'posts/index'),
|
||||
'base' => null,
|
||||
'here' => '/posts/index',
|
||||
);
|
||||
$this->Controller->helpers = array('Html', 'Javascript', 'DebugKit.Toolbar');
|
||||
$this->Controller->layout = 'default';
|
||||
$this->Controller->uses = null;
|
||||
$this->Controller->components = array('DebugKit.Toolbar');
|
||||
$this->Controller->constructClasses();
|
||||
$this->Controller->Component->initialize($this->Controller);
|
||||
$this->Controller->Component->startup($this->Controller);
|
||||
$this->Controller->Component->beforeRender($this->Controller);
|
||||
$result = $this->Controller->render();
|
||||
$result = str_replace(array("\n", "\r"), '', $result);
|
||||
$this->assertPattern('#<div id\="debug-kit-toolbar">.+</div></body>#', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* test injection of javascript
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testJavascriptInjection() {
|
||||
$this->Controller->viewPath = 'posts';
|
||||
$this->Controller->uses = null;
|
||||
$this->Controller->action = 'index';
|
||||
$this->Controller->params = array(
|
||||
'action' => 'index',
|
||||
'controller' => 'posts',
|
||||
'plugin' => null,
|
||||
'url' => array('url' => 'posts/index'),
|
||||
'base' => '/',
|
||||
'here' => '/posts/index',
|
||||
);
|
||||
$this->Controller->helpers = array('Javascript', 'Html');
|
||||
$this->Controller->components = array('DebugKit.Toolbar');
|
||||
$this->Controller->layout = 'default';
|
||||
$this->Controller->constructClasses();
|
||||
$this->Controller->Component->initialize($this->Controller);
|
||||
$this->Controller->Component->startup($this->Controller);
|
||||
$this->Controller->Component->beforeRender($this->Controller);
|
||||
$result = $this->Controller->render();
|
||||
$result = str_replace(array("\n", "\r"), '', $result);
|
||||
$this->assertPattern('#<script\s*type="text/javascript"\s*src="/debug_kit/js/js_debug_toolbar.js"\s*>\s?</script>#', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* test Injection of user defined javascript
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function testCustomJavascriptInjection() {
|
||||
$this->Controller->viewPath = 'posts';
|
||||
$this->Controller->uses = null;
|
||||
$this->Controller->action = 'index';
|
||||
$this->Controller->params = array(
|
||||
'action' => 'index',
|
||||
'controller' => 'posts',
|
||||
'plugin' => null,
|
||||
'url' => array('url' => 'posts/index'),
|
||||
'base' => '/',
|
||||
'here' => '/posts/index',
|
||||
);
|
||||
$this->Controller->helpers = array('Javascript', 'Html');
|
||||
$this->Controller->components = array('DebugKit.Toolbar' => array('javascript' => array('my_custom')));
|
||||
$this->Controller->layout = 'default';
|
||||
$this->Controller->constructClasses();
|
||||
$this->Controller->Component->initialize($this->Controller);
|
||||
$this->Controller->Component->startup($this->Controller);
|
||||
$this->Controller->Component->beforeRender($this->Controller);
|
||||
$result = $this->Controller->render();
|
||||
$result = str_replace(array("\n", "\r"), '', $result);
|
||||
$this->assertPattern('#<script\s*type="text/javascript"\s*src="js/my_custom_debug_toolbar.js"\s*>\s?</script>#', $result);
|
||||
}
|
||||
/**
|
||||
* test message creation
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function testMessage() {
|
||||
$result = $this->Toolbar->message('test', 'one, two');
|
||||
$expected = array(
|
||||
'<p',
|
||||
'<strong', 'test', '/strong',
|
||||
' one, two',
|
||||
'/p',
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
}
|
||||
/**
|
||||
* Test Table generation
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function testTable() {
|
||||
$rows = array(
|
||||
array(1,2),
|
||||
array(3,4),
|
||||
);
|
||||
$result = $this->Toolbar->table($rows);
|
||||
$expected = array(
|
||||
'table' => array('class' =>'debug-table'),
|
||||
array('tr' => array('class' => 'odd')),
|
||||
'<td', '1', '/td',
|
||||
'<td', '2', '/td',
|
||||
'/tr',
|
||||
array('tr' => array('class' => 'even')),
|
||||
'<td', '3', '/td',
|
||||
'<td', '4', '/td',
|
||||
'/tr',
|
||||
'/table'
|
||||
);
|
||||
$this->assertTags($result, $expected);
|
||||
}
|
||||
/**
|
||||
* reset the view paths
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function endCase() {
|
||||
Configure::write('viewPaths', $this->_viewPaths);
|
||||
}
|
||||
|
||||
/**
|
||||
* tearDown
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function tearDown() {
|
||||
unset($this->Toolbar, $this->Controller);
|
||||
ClassRegistry::removeObject('view');
|
||||
ClassRegistry::flush();
|
||||
}
|
||||
}
|
||||
?>
|
||||
0
plugins/debug_kit/tests/fixtures/empty
vendored
Normal file
0
plugins/debug_kit/tests/fixtures/empty
vendored
Normal file
0
plugins/debug_kit/tests/groups/empty
Normal file
0
plugins/debug_kit/tests/groups/empty
Normal file
33
plugins/debug_kit/tests/test_app/vendors/test_panel.php
vendored
Normal file
33
plugins/debug_kit/tests/test_app/vendors/test_panel.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Test Panel
|
||||
*
|
||||
*
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake.debug_kit
|
||||
* @subpackage cake.debug_kit.tests
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
class TestPanel extends DebugPanel {
|
||||
function startup(&$controller) {
|
||||
$controller->testPanel = true;
|
||||
}
|
||||
}
|
||||
?>
|
||||
165
plugins/debug_kit/vendors/css/debug_toolbar.css
vendored
Normal file
165
plugins/debug_kit/vendors/css/debug_toolbar.css
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
/* @override http://localhost/cake_debug_kit/debug_kit/css/debug_toolbar.css */
|
||||
#debug-kit-toolbar {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
right:0px;
|
||||
width: 100%;
|
||||
height: 1%;
|
||||
overflow: visible;
|
||||
z-index:10000;
|
||||
}
|
||||
/* panel tabs */
|
||||
#debug-kit-toolbar #panel-tabs {
|
||||
float: right;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
}
|
||||
#debug-kit-toolbar .panel-tab {
|
||||
clear: none;
|
||||
float: left;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
#debug-kit-toolbar .panel-tab a {
|
||||
float: left;
|
||||
clear: none;
|
||||
background: #efefef;
|
||||
color: #222;
|
||||
padding: 6px;
|
||||
border-right: 1px solid #ccc;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
margin: 0;
|
||||
display: block;
|
||||
}
|
||||
#debug-kit-toolbar .panel-tab .active,
|
||||
#debug-kit-toolbar .panel-tab a:hover {
|
||||
background: #fff;
|
||||
}
|
||||
#debug-kit-toolbar .panel-tab.icon a {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
/* Hovering over link shows tab, useful for no js */
|
||||
#debug-kit-toolbar .panel-tab a:hover + .panel-content,
|
||||
#debug-kit-toolbar .panel-tab a + .panel-content:hover {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* panel content */
|
||||
#debug-kit-toolbar .panel-content {
|
||||
position: absolute;
|
||||
text-align: left;
|
||||
width: auto;
|
||||
top:28px;
|
||||
right:0px;
|
||||
background: #fff;
|
||||
color: #000;
|
||||
width:96%;
|
||||
padding:20px 2%;
|
||||
max-height: 550px;
|
||||
overflow:auto;
|
||||
border-bottom: 3px solid #333;
|
||||
}
|
||||
|
||||
/* Hide panel content by default */
|
||||
.panel-content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.panel-content p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
.panel-content h2 {
|
||||
padding: 0;
|
||||
margin-top:0;
|
||||
}
|
||||
.panel-content h3 {
|
||||
padding: 0;
|
||||
margin-top: 1em;
|
||||
}
|
||||
.panel-content .info {
|
||||
padding: 4px;
|
||||
border-top: 1px dashed #6c6cff;
|
||||
border-bottom: 1px dashed #6c6cff;
|
||||
}
|
||||
|
||||
/* panel tables */
|
||||
table.debug-table {
|
||||
width: auto;
|
||||
border: 0;
|
||||
}
|
||||
table.debug-table td,
|
||||
table.debug-table th {
|
||||
text-align: left;
|
||||
border: 0;
|
||||
padding: 3px;
|
||||
}
|
||||
table.debug-table th {
|
||||
border-bottom: 1px solid #222;
|
||||
background: 0;;
|
||||
}
|
||||
table.debug-table tr.even td {
|
||||
background:#efefef;
|
||||
}
|
||||
|
||||
/** code tables **/
|
||||
#debug-kit-toolbar .code-table td {
|
||||
white-space: pre;
|
||||
font-family: monaco, corsiva, "courier new", courier, monospaced;
|
||||
}
|
||||
#debug-kit-toolbar .code-table td:first-child {
|
||||
width: 15%;
|
||||
}
|
||||
#debug-kit-toolbar .code-table td:last-child {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
|
||||
.panel-content.request {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
/** Neat Array styles **/
|
||||
.neat-array {
|
||||
padding: 1px 2px 1px 20px;
|
||||
background: #CE9E23;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
}
|
||||
.neat-array .neat-array {
|
||||
padding: 0 0 0 20px;
|
||||
}
|
||||
.neat-array li {
|
||||
background: #FEF6E5;
|
||||
border-top: 1px solid #CE9E23;
|
||||
border-bottom: 1px solid #CE9E23;
|
||||
margin: 0;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
.neat-array li:hover {
|
||||
background: #fff;
|
||||
}
|
||||
.neat-array li strong {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
/* expandable sections */
|
||||
.neat-array li.expandable {
|
||||
cursor: pointer;
|
||||
}
|
||||
.neat-array li.expandable.expanded > strong:before {
|
||||
content: 'v ';
|
||||
}
|
||||
.neat-array li.expandable.collapsed > strong:before,
|
||||
.neat-array li.expandable.expanded .expandable.collapsed > strong:before {
|
||||
content: '> ';
|
||||
}
|
||||
|
||||
.neat-array li {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
226
plugins/debug_kit/vendors/debug_kit_debugger.php
vendored
Normal file
226
plugins/debug_kit/vendors/debug_kit_debugger.php
vendored
Normal file
@@ -0,0 +1,226 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* DebugKit Debugger class. Extends and enhances core
|
||||
* debugger. Adds benchmarking and timing functionality.
|
||||
*
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.
|
||||
* @since CakePHP v 1.2.0.4487
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
App::import('Core', 'Debugger');
|
||||
App::import('Vendor', 'DebugKit.FireCake');
|
||||
/**
|
||||
* Debug Kit Temporary Debugger Class
|
||||
*
|
||||
* Provides the future features that are planned. Yet not implemented in the 1.2 code base
|
||||
*
|
||||
* This file will not be needed in future version of CakePHP.
|
||||
* @todo merge these changes with core Debugger
|
||||
*/
|
||||
class DebugKitDebugger extends Debugger {
|
||||
|
||||
/**
|
||||
* Start an benchmarking timer.
|
||||
*
|
||||
* @param string $name The name of the timer to start.
|
||||
* @param string $message A message for your timer
|
||||
* @return bool true
|
||||
* @static
|
||||
**/
|
||||
function startTimer($name = 'default', $message = '') {
|
||||
$now = getMicrotime();
|
||||
$_this = DebugKitDebugger::getInstance();
|
||||
$_this->__benchmarks[$name] = array(
|
||||
'start' => $now,
|
||||
'message' => $message,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop a benchmarking timer.
|
||||
*
|
||||
* $name should be the same as the $name used in startTimer().
|
||||
*
|
||||
* @param string $name The name of the timer to end.
|
||||
* @access public
|
||||
* @return boolean true if timer was ended, false if timer was not started.
|
||||
* @static
|
||||
*/
|
||||
function stopTimer($name = 'default') {
|
||||
$now = getMicrotime();
|
||||
$_this = DebugKitDebugger::getInstance();
|
||||
if (!isset($_this->__benchmarks[$name])) {
|
||||
return false;
|
||||
}
|
||||
$_this->__benchmarks[$name]['end'] = $now;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all timers that have been started and stopped.
|
||||
* Calculates elapsed time for each timer.
|
||||
*
|
||||
* @return array
|
||||
**/
|
||||
function getTimers() {
|
||||
$_this =& DebugKitDebugger::getInstance();
|
||||
$times = array();
|
||||
foreach ($_this->__benchmarks as $name => $timer) {
|
||||
$times[$name]['time'] = DebugKitDebugger::elapsedTime($name);
|
||||
$times[$name]['message'] = $timer['message'];
|
||||
}
|
||||
return $times;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all existing timers
|
||||
*
|
||||
* @return bool true
|
||||
**/
|
||||
function clearTimers() {
|
||||
$_this =& DebugKitDebugger::getInstance();
|
||||
$_this->__benchmarks = array();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the difference in time between the timer start and timer end.
|
||||
*
|
||||
* @param $name string the name of the timer you want elapsed time for.
|
||||
* @param $precision int the number of decimal places to return, defaults to 5.
|
||||
* @return float number of seconds elapsed for timer name, 0 on missing key
|
||||
* @static
|
||||
**/
|
||||
function elapsedTime($name = 'default', $precision = 5) {
|
||||
$_this =& DebugKitDebugger::getInstance();
|
||||
if (!isset($_this->__benchmarks[$name]['start']) || !isset($_this->__benchmarks[$name]['end'])) {
|
||||
return 0;
|
||||
}
|
||||
return round($_this->__benchmarks[$name]['end'] - $_this->__benchmarks[$name]['start'], $precision);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total execution time until this point
|
||||
*
|
||||
* @access public
|
||||
* @return float elapsed time in seconds since script start.
|
||||
* @static
|
||||
*/
|
||||
function requestTime() {
|
||||
$start = DebugKitDebugger::requestStartTime();
|
||||
$now = getMicroTime();
|
||||
return ($now - $start);
|
||||
}
|
||||
/**
|
||||
* get the time the current request started.
|
||||
*
|
||||
* @access public
|
||||
* @return float time of request start
|
||||
* @static
|
||||
*/
|
||||
function requestStartTime() {
|
||||
if (defined('TIME_START')) {
|
||||
$startTime = TIME_START;
|
||||
} else if (isset($_GLOBALS['TIME_START'])) {
|
||||
$startTime = $_GLOBALS['TIME_START'];
|
||||
} else {
|
||||
$startTime = env('REQUEST_TIME');
|
||||
}
|
||||
return $startTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* get current memory usage
|
||||
*
|
||||
* @return integer number of bytes ram currently in use. 0 if memory_get_usage() is not available.
|
||||
* @static
|
||||
**/
|
||||
function getMemoryUse() {
|
||||
if (!function_exists('memory_get_usage')) {
|
||||
return 0;
|
||||
}
|
||||
return memory_get_usage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get peak memory use
|
||||
*
|
||||
* @return integer peak memory use (in bytes). Returns 0 if memory_get_peak_usage() is not available
|
||||
* @static
|
||||
**/
|
||||
function getPeakMemoryUse() {
|
||||
if (!function_exists('memory_get_peak_usage')) {
|
||||
return 0;
|
||||
}
|
||||
return memory_get_peak_usage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles object conversion to debug string.
|
||||
*
|
||||
* @param string $var Object to convert
|
||||
* @access protected
|
||||
*/
|
||||
function _output($level, $error, $code, $helpCode, $description, $file, $line, $kontext) {
|
||||
$files = $this->trace(array('start' => 2, 'format' => 'points'));
|
||||
$listing = $this->excerpt($files[0]['file'], $files[0]['line'] - 1, 1);
|
||||
$trace = $this->trace(array('start' => 2, 'depth' => '20'));
|
||||
$context = array();
|
||||
|
||||
foreach ((array)$kontext as $var => $value) {
|
||||
$context[] = "\${$var}\t=\t" . $this->exportVar($value, 1);
|
||||
}
|
||||
if ($this->_outputFormat == 'fb') {
|
||||
$this->_fireError($error, $code, $description, $file, $line, $trace, $context);
|
||||
} else {
|
||||
echo parent::_output($level, $error, $code, $helpCode, $description, $file, $line, $kontext);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Create a FirePHP error message
|
||||
*
|
||||
* @param string $error Name of error
|
||||
* @param string $code Code of error
|
||||
* @param string $description Description of error
|
||||
* @param string $file File error occured in
|
||||
* @param string $line Line error occured on
|
||||
* @param string $trace Stack trace at time of error
|
||||
* @param string $context context of error
|
||||
* @return void
|
||||
* @access protected
|
||||
*/
|
||||
function _fireError($error, $code, $description, $file, $line, $trace, $context) {
|
||||
$name = $error . ' - ' . $description;
|
||||
$message = "$error $code $description on line: $line in file: $file";
|
||||
FireCake::group($name);
|
||||
FireCake::error($message, $name);
|
||||
FireCake::log($context, 'Context');
|
||||
FireCake::log($trace, 'Trace');
|
||||
FireCake::groupEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Debugger::invoke(DebugKitDebugger::getInstance());
|
||||
Debugger::getInstance('DebugKitDebugger');
|
||||
?>
|
||||
539
plugins/debug_kit/vendors/fire_cake.php
vendored
Normal file
539
plugins/debug_kit/vendors/fire_cake.php
vendored
Normal file
@@ -0,0 +1,539 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* FirePHP Class for CakePHP
|
||||
*
|
||||
* Provides most of the functionality offered by FirePHPCore
|
||||
* Interoperates with FirePHP extension for firefox
|
||||
*
|
||||
* For more information see: http://www.firephp.org/
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package debug_kit.
|
||||
* @subpackage debug_kit.vendors
|
||||
* @since
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
App::import('Core', 'Debugger');
|
||||
|
||||
class FireCake extends Object {
|
||||
/**
|
||||
* Options for FireCake.
|
||||
*
|
||||
* @see _defaultOptions and setOptions();
|
||||
* @var string
|
||||
*/
|
||||
var $options = array();
|
||||
/**
|
||||
* Default Options used in CakeFirePhp
|
||||
*
|
||||
* @var string
|
||||
* @access protected
|
||||
*/
|
||||
var $_defaultOptions = array(
|
||||
'maxObjectDepth' => 10,
|
||||
'maxArrayDepth' => 20,
|
||||
'useNativeJsonEncode' => true,
|
||||
'includeLineNumbers' => true,
|
||||
);
|
||||
/**
|
||||
* Message Levels for messages sent via FirePHP
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
var $_levels = array(
|
||||
'log' => 'LOG',
|
||||
'info' => 'INFO',
|
||||
'warn' => 'WARN',
|
||||
'error' => 'ERROR',
|
||||
'dump' => 'DUMP',
|
||||
'trace' => 'TRACE',
|
||||
'exception' => 'EXCEPTION',
|
||||
'table' => 'TABLE',
|
||||
'groupStart' => 'GROUP_START',
|
||||
'groupEnd' => 'GROUP_END',
|
||||
);
|
||||
|
||||
var $_version = '0.2.1';
|
||||
/**
|
||||
* internal messageIndex counter
|
||||
*
|
||||
* @var int
|
||||
* @access protected
|
||||
*/
|
||||
var $_messageIndex = 1;
|
||||
/**
|
||||
* stack of objects encoded by stringEncode()
|
||||
*
|
||||
* @var array
|
||||
**/
|
||||
var $_encodedObjects = array();
|
||||
/**
|
||||
* methodIndex to include in tracebacks when using includeLineNumbers
|
||||
*
|
||||
* @var array
|
||||
**/
|
||||
var $_methodIndex = array('info', 'log', 'warn', 'error', 'table', 'trace');
|
||||
/**
|
||||
* FireCake output status
|
||||
*
|
||||
* @var bool
|
||||
**/
|
||||
var $_enabled = true;
|
||||
/**
|
||||
* get Instance of the singleton
|
||||
*
|
||||
* @param string $class Class instance to store in the singleton. Used with subclasses and Tests.
|
||||
* @access public
|
||||
* @static
|
||||
* @return void
|
||||
*/
|
||||
function &getInstance($class = null) {
|
||||
static $instance = array();
|
||||
if (!empty($class)) {
|
||||
if (!$instance || strtolower($class) != strtolower(get_class($instance[0]))) {
|
||||
$instance[0] = new $class();
|
||||
$instance[0]->setOptions();
|
||||
}
|
||||
}
|
||||
if (!isset($instance[0]) || !$instance[0]) {
|
||||
$instance[0] = new FireCake();
|
||||
$instance[0]->setOptions();
|
||||
}
|
||||
return $instance[0];
|
||||
}
|
||||
/**
|
||||
* setOptions
|
||||
*
|
||||
* @param array $options Array of options to set.
|
||||
* @access public
|
||||
* @static
|
||||
* @return void
|
||||
*/
|
||||
function setOptions($options = array()) {
|
||||
$_this = FireCake::getInstance();
|
||||
if (empty($_this->options)) {
|
||||
$_this->options = array_merge($_this->_defaultOptions, $options);
|
||||
} else {
|
||||
$_this->options = array_merge($_this->options, $options);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Return boolean based on presence of FirePHP extension
|
||||
*
|
||||
* @access public
|
||||
* @return boolean
|
||||
**/
|
||||
function detectClientExtension() {
|
||||
$ua = FireCake::getUserAgent();
|
||||
if (!preg_match('/\sFirePHP\/([\.|\d]*)\s?/si', $ua, $match) || !version_compare($match[1], '0.0.6', '>=')) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Get the Current UserAgent
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
* @return string UserAgent string of active client connection
|
||||
**/
|
||||
function getUserAgent() {
|
||||
return env('HTTP_USER_AGENT');
|
||||
}
|
||||
/**
|
||||
* Disable FireCake output
|
||||
* All subsequent output calls will not be run.
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function disable() {
|
||||
$_this = FireCake::getInstance();
|
||||
$_this->_enabled = false;
|
||||
}
|
||||
/**
|
||||
* Enable FireCake output
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function enable() {
|
||||
$_this = FireCake::getInstance();
|
||||
$_this->_enabled = true;
|
||||
}
|
||||
/**
|
||||
* Convenience wrapper for LOG messages
|
||||
*
|
||||
* @param string $message Message to log
|
||||
* @param string $label Label for message (optional)
|
||||
* @access public
|
||||
* @static
|
||||
* @return void
|
||||
*/
|
||||
function log($message, $label = null) {
|
||||
FireCake::fb($message, $label, 'log');
|
||||
}
|
||||
/**
|
||||
* Convenience wrapper for WARN messages
|
||||
*
|
||||
* @param string $message Message to log
|
||||
* @param string $label Label for message (optional)
|
||||
* @access public
|
||||
* @static
|
||||
* @return void
|
||||
*/
|
||||
function warn($message, $label = null) {
|
||||
FireCake::fb($message, $label, 'warn');
|
||||
}
|
||||
/**
|
||||
* Convenience wrapper for INFO messages
|
||||
*
|
||||
* @param string $message Message to log
|
||||
* @param string $label Label for message (optional)
|
||||
* @access public
|
||||
* @static
|
||||
* @return void
|
||||
*/
|
||||
function info($message, $label = null) {
|
||||
FireCake::fb($message, $label, 'info');
|
||||
}
|
||||
/**
|
||||
* Convenience wrapper for ERROR messages
|
||||
*
|
||||
* @param string $message Message to log
|
||||
* @param string $label Label for message (optional)
|
||||
* @access public
|
||||
* @static
|
||||
* @return void
|
||||
*/
|
||||
function error($message, $label = null) {
|
||||
FireCake::fb($message, $label, 'error');
|
||||
}
|
||||
/**
|
||||
* Convenience wrapper for TABLE messages
|
||||
*
|
||||
* @param string $message Message to log
|
||||
* @param string $label Label for message (optional)
|
||||
* @access public
|
||||
* @static
|
||||
* @return void
|
||||
*/
|
||||
function table($label, $message) {
|
||||
FireCake::fb($message, $label, 'table');
|
||||
}
|
||||
/**
|
||||
* Convenience wrapper for DUMP messages
|
||||
*
|
||||
* @param string $message Message to log
|
||||
* @param string $label Unique label for message
|
||||
* @access public
|
||||
* @static
|
||||
* @return void
|
||||
*/
|
||||
function dump($label, $message) {
|
||||
FireCake::fb($message, $label, 'dump');
|
||||
}
|
||||
/**
|
||||
* Convenience wrapper for TRACE messages
|
||||
*
|
||||
* @param string $label Label for message (optional)
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function trace($label) {
|
||||
FireCake::fb($label, 'trace');
|
||||
}
|
||||
/**
|
||||
* Convenience wrapper for GROUP messages
|
||||
* Messages following the group call will be nested in a group block
|
||||
*
|
||||
* @param string $label Label for group (optional)
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function group($label) {
|
||||
FireCake::fb(null, $label, 'groupStart');
|
||||
}
|
||||
/**
|
||||
* Convenience wrapper for GROUPEND messages
|
||||
* Closes a group block
|
||||
*
|
||||
* @param string $label Label for group (optional)
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function groupEnd() {
|
||||
FireCake::fb(null, null, 'groupEnd');
|
||||
}
|
||||
/**
|
||||
* fb - Send messages with FireCake to FirePHP
|
||||
*
|
||||
* Much like FirePHP's fb() this method can be called with various parameter counts
|
||||
* fb($message) - Just send a message defaults to LOG type
|
||||
* fb($message, $type) - Send a message with a specific type
|
||||
* fb($message, $label, $type) - Send a message with a custom label and type.
|
||||
*
|
||||
* @param mixed $message Message to output. For other parameters see usage above.
|
||||
* @static
|
||||
* @return void
|
||||
**/
|
||||
function fb($message) {
|
||||
$_this = FireCake::getInstance();
|
||||
|
||||
if (headers_sent($filename, $linenum)) {
|
||||
trigger_error(sprintf(__('Headers already sent in %s on line %s. Cannot send log data to FirePHP.', true), $filename, $linenum), E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
if (!$_this->_enabled || !$_this->detectClientExtension()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$args = func_get_args();
|
||||
$type = $label = null;
|
||||
switch (count($args)) {
|
||||
case 1:
|
||||
$type = $_this->_levels['log'];
|
||||
break;
|
||||
case 2:
|
||||
$type = $args[1];
|
||||
break;
|
||||
case 3:
|
||||
$type = $args[2];
|
||||
$label = $args[1];
|
||||
break;
|
||||
default:
|
||||
trigger_error(__('Incorrect parameter count for FireCake::fb()', true), E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
if (isset($_this->_levels[$type])) {
|
||||
$type = $_this->_levels[$type];
|
||||
} else {
|
||||
$type = $_this->_levels['log'];
|
||||
}
|
||||
|
||||
$meta = array();
|
||||
$skipFinalObjectEncode = false;
|
||||
if ($type == $_this->_levels['trace']) {
|
||||
$trace = debug_backtrace();
|
||||
if (!$trace) {
|
||||
return false;
|
||||
}
|
||||
$message = $_this->_parseTrace($trace, $args[0]);
|
||||
$skipFinalObjectEncode = true;
|
||||
}
|
||||
|
||||
if ($_this->options['includeLineNumbers']) {
|
||||
if (!isset($meta['file']) || !isset($meta['line'])) {
|
||||
$trace = debug_backtrace();
|
||||
for ($i = 0, $len = count($trace); $i < $len ; $i++) {
|
||||
$keySet = (isset($trace[$i]['class']) && isset($trace[$i]['function']));
|
||||
$selfCall = ($keySet && $trace[$i]['class'] == 'FireCake' && in_array($trace[$i]['function'], $_this->_methodIndex));
|
||||
if ($selfCall) {
|
||||
$meta['File'] = isset($trace[$i]['file']) ? Debugger::trimPath($trace[$i]['file']) : '';
|
||||
$meta['Line'] = isset($trace[$i]['line']) ? $trace[$i]['line'] : '';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$structureIndex = 1;
|
||||
if ($type == $_this->_levels['dump']) {
|
||||
$structureIndex = 2;
|
||||
$_this->_sendHeader('X-Wf-1-Structure-2','http://meta.firephp.org/Wildfire/Structure/FirePHP/Dump/0.1');
|
||||
} else {
|
||||
$_this->_sendHeader('X-Wf-1-Structure-1','http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1');
|
||||
}
|
||||
|
||||
$_this->_sendHeader('X-Wf-Protocol-1', 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2');
|
||||
$_this->_sendHeader('X-Wf-1-Plugin-1', 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/'. $_this->_version);
|
||||
|
||||
if ($type == $_this->_levels['dump']) {
|
||||
$dump = $_this->jsonEncode($message);
|
||||
$msg = '{"' . $label .'":' . $dump .'}';
|
||||
} else {
|
||||
$meta['Type'] = $type;
|
||||
if ($label !== null) {
|
||||
$meta['Label'] = $label;
|
||||
}
|
||||
$msg = '[' . $_this->jsonEncode($meta) . ',' . $_this->jsonEncode($message, $skipFinalObjectEncode).']';
|
||||
}
|
||||
|
||||
$lines = explode("\n", chunk_split($msg, 5000, "\n"));
|
||||
foreach ($lines as $i => $line) {
|
||||
if (empty($line)) {
|
||||
continue;
|
||||
}
|
||||
$header = 'X-Wf-1-' . $structureIndex . '-1-' . $_this->_messageIndex;
|
||||
if (count($lines) > 2) {
|
||||
$first = ($i == 0) ? strlen($msg) : '';
|
||||
$end = ($i < count($lines) - 2) ? '\\' : '';
|
||||
$message = $first . '|' . $line . '|' . $end;
|
||||
$_this->_sendHeader($header, $message);
|
||||
} else {
|
||||
$_this->_sendHeader($header, strlen($line) . '|' . $line . '|');
|
||||
}
|
||||
$_this->_messageIndex++;
|
||||
if ($_this->_messageIndex > 99999) {
|
||||
trigger_error(__('Maximum number (99,999) of messages reached!', true), E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
$_this->_sendHeader('X-Wf-1-Index', $_this->_messageIndex - 1);
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Parse a debug backtrace
|
||||
*
|
||||
* @param array $trace Debug backtrace output
|
||||
* @access protected
|
||||
* @return array
|
||||
**/
|
||||
function _parseTrace($trace, $messageName) {
|
||||
$message = array();
|
||||
for ($i = 0, $len = count($trace); $i < $len ; $i++) {
|
||||
$keySet = (isset($trace[$i]['class']) && isset($trace[$i]['function']));
|
||||
$selfCall = ($keySet && $trace[$i]['class'] == 'FireCake');
|
||||
if (!$selfCall) {
|
||||
$message = array(
|
||||
'Class' => isset($trace[$i]['class']) ? $trace[$i]['class'] : '',
|
||||
'Type' => isset($trace[$i]['type']) ? $trace[$i]['type'] : '',
|
||||
'Function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : '',
|
||||
'Message' => $messageName,
|
||||
'File' => isset($trace[$i]['file']) ? Debugger::trimPath($trace[$i]['file']) : '',
|
||||
'Line' => isset($trace[$i]['line']) ? $trace[$i]['line'] : '',
|
||||
'Args' => isset($trace[$i]['args']) ? $this->stringEncode($trace[$i]['args']) : '',
|
||||
'Trace' => $this->_escapeTrace(array_splice($trace, $i + 1))
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $message;
|
||||
}
|
||||
/**
|
||||
* Fix a trace for use in output
|
||||
*
|
||||
* @param mixed $trace Trace to fix
|
||||
* @access protected
|
||||
* @static
|
||||
* @return string
|
||||
**/
|
||||
function _escapeTrace($trace) {
|
||||
for ($i = 0, $len = count($trace); $i < $len; $i++) {
|
||||
if (isset($trace[$i]['file'])) {
|
||||
$trace[$i]['file'] = Debugger::trimPath($trace[$i]['file']);
|
||||
}
|
||||
if (isset($trace[$i]['args'])) {
|
||||
$trace[$i]['args'] = $this->stringEncode($trace[$i]['args']);
|
||||
}
|
||||
}
|
||||
return $trace;
|
||||
}
|
||||
/**
|
||||
* Encode non string objects to string.
|
||||
* Filter out recursion, so no errors are raised by json_encode or $javascript->object()
|
||||
*
|
||||
* @param mixed $object Object or variable to encode to string.
|
||||
* @param int $objectDepth Current Depth in object chains.
|
||||
* @param int $arrayDepth Current Depth in array chains.
|
||||
* @static
|
||||
* @return void
|
||||
**/
|
||||
function stringEncode($object, $objectDepth = 1, $arrayDepth = 1) {
|
||||
$_this = FireCake::getInstance();
|
||||
$return = array();
|
||||
if (is_resource($object)) {
|
||||
return '** ' . (string)$object . '**';
|
||||
}
|
||||
if (is_object($object)) {
|
||||
if ($objectDepth == $_this->options['maxObjectDepth']) {
|
||||
return '** Max Object Depth (' . $_this->options['maxObjectDepth'] . ') **';
|
||||
}
|
||||
foreach ($_this->_encodedObjects as $encoded) {
|
||||
if ($encoded === $object) {
|
||||
return '** Recursion (' . get_class($object) . ') **';
|
||||
}
|
||||
}
|
||||
$_this->_encodedObjects[] = $object;
|
||||
|
||||
$return['__className'] = $class = get_class($object);
|
||||
$properties = (array) $object;
|
||||
foreach ($properties as $name => $property) {
|
||||
$return[$name] = FireCake::stringEncode($property, 1, $objectDepth + 1);
|
||||
}
|
||||
array_pop($_this->_encodedObjects);
|
||||
}
|
||||
if (is_array($object)) {
|
||||
if ($arrayDepth == $_this->options['maxArrayDepth']) {
|
||||
return '** Max Array Depth ('. $_this->options['maxArrayDepth'] . ') **';
|
||||
}
|
||||
foreach ($object as $key => $value) {
|
||||
$return[$key] = FireCake::stringEncode($value, 1, $arrayDepth + 1);
|
||||
}
|
||||
}
|
||||
if (is_string($object) || is_numeric($object) || is_bool($object) || is_null($object)) {
|
||||
return $object;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
/**
|
||||
* Encode an object into JSON
|
||||
*
|
||||
* @param mixed $object Object or array to json encode
|
||||
* @param boolean $doIt
|
||||
* @access public
|
||||
* @static
|
||||
* @return string
|
||||
**/
|
||||
function jsonEncode($object, $skipEncode = false) {
|
||||
$_this = FireCake::getInstance();
|
||||
if (!$skipEncode) {
|
||||
$object = FireCake::stringEncode($object);
|
||||
}
|
||||
|
||||
if (function_exists('json_encode') && $_this->options['useNativeJsonEncode']) {
|
||||
return json_encode($object);
|
||||
} else {
|
||||
return FireCake::_jsonEncode($object);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* jsonEncode Helper method for PHP4 compatibility
|
||||
*
|
||||
* @param mixed $object Something to encode
|
||||
* @access protected
|
||||
* @static
|
||||
* @return string
|
||||
**/
|
||||
function _jsonEncode($object) {
|
||||
if (!class_exists('JavascriptHelper')) {
|
||||
App::import('Helper', 'Javascript');
|
||||
}
|
||||
$javascript = new JavascriptHelper();
|
||||
$javascript->useNative = false;
|
||||
return $javascript->object($object);
|
||||
}
|
||||
/**
|
||||
* Send Headers - write headers.
|
||||
*
|
||||
* @access protected
|
||||
* @return void
|
||||
**/
|
||||
function _sendHeader($name, $value) {
|
||||
header($name . ': ' . $value);
|
||||
}
|
||||
}
|
||||
?>
|
||||
BIN
plugins/debug_kit/vendors/img/cake.icon.png
vendored
Normal file
BIN
plugins/debug_kit/vendors/img/cake.icon.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
84
plugins/debug_kit/vendors/js/jquery_debug_toolbar.js
vendored
Normal file
84
plugins/debug_kit/vendors/js/jquery_debug_toolbar.js
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Debug Toolbar Javascript. jQuery 1.2.x compatible.
|
||||
*
|
||||
* Long description here.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.
|
||||
* @since CakePHP v 1.2.0.4487
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
$(document).ready(function(){
|
||||
DebugKit.Toolbar();
|
||||
DebugKit.NeatArray();
|
||||
});
|
||||
|
||||
var DebugKit = {};
|
||||
/**
|
||||
* Create all behaviors for neat array elements
|
||||
*
|
||||
*/
|
||||
DebugKit.NeatArray = function() {
|
||||
$('.neat-array').find('li:has(ul)').toggle(
|
||||
function() {
|
||||
$(this).toggleClass('expanded').removeClass('collapsed').find('ul:first').show();
|
||||
},
|
||||
function() {
|
||||
$(this).toggleClass('expanded').addClass('collapsed').find('ul:first').hide();
|
||||
}
|
||||
).addClass('expandable').addClass('collapsed').find('ul').hide();
|
||||
}
|
||||
/**
|
||||
* Add behavior for toolbar buttons
|
||||
*
|
||||
*/
|
||||
DebugKit.Toolbar = function() {
|
||||
var tabCollection = $('#debug-kit-toolbar li > div');
|
||||
|
||||
$('#debug-kit-toolbar .panel-tab > a').click(
|
||||
function(e){
|
||||
e.preventDefault();
|
||||
var targetPanel = $(this.hash + '-tab');
|
||||
if (targetPanel.hasClass('active')) {
|
||||
tabCollection.hide().removeClass('active');
|
||||
} else {
|
||||
tabCollection
|
||||
.hide().removeClass('active')
|
||||
.filter(this.hash + '-tab').show().addClass('active');
|
||||
}
|
||||
$('#debug-kit-toolbar .panel-tab > a').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
}
|
||||
);
|
||||
|
||||
//enable hiding of toolbar.
|
||||
var panelButtons = $('#debug-kit-toolbar .panel-tab:not(.panel-tab.icon)');
|
||||
$('#debug-kit-toolbar #hide-toolbar').toggle(
|
||||
function() {
|
||||
panelButtons.hide();
|
||||
},
|
||||
function() {
|
||||
panelButtons.show();
|
||||
}
|
||||
);
|
||||
}
|
||||
})(jQuery);
|
||||
212
plugins/debug_kit/vendors/js/js_debug_toolbar.js
vendored
Normal file
212
plugins/debug_kit/vendors/js/js_debug_toolbar.js
vendored
Normal file
@@ -0,0 +1,212 @@
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Debug Toolbar Javascript.
|
||||
*
|
||||
* Long description here.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.
|
||||
* @since CakePHP v 1.2.0.4487
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
var DebugKit = function(id) {
|
||||
var undefined,
|
||||
elements = {},
|
||||
panels = {},
|
||||
hidden = false;
|
||||
|
||||
this.initialize = function(id) {
|
||||
elements.toolbar = document.getElementById(id || 'debug-kit-toolbar');
|
||||
|
||||
if (elements.toolbar === undefined) {
|
||||
throw new Exception('Toolbar not found, make sure you loaded it.');
|
||||
}
|
||||
|
||||
for (var i in elements.toolbar.childNodes) {
|
||||
var element = elements.toolbar.childNodes[i];
|
||||
if (element.nodeName && element.id === 'panel-tabs') {
|
||||
elements.panel = element;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i in elements.panel.childNodes) {
|
||||
var element = elements.panel.childNodes[i];
|
||||
if (element.className && element.className.match(/panel-tab/)) {
|
||||
this.addPanel(element);
|
||||
}
|
||||
}
|
||||
|
||||
var lists = document.getElementsByTagName('ul'), index = 0;
|
||||
while (lists[index] !== undefined) {
|
||||
var element = lists[index];
|
||||
if (element.className && element.className.match(/neat-array/)) {
|
||||
neatArray(element);
|
||||
}
|
||||
++index;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Add a panel to the toolbar
|
||||
*/
|
||||
this.addPanel = function(tab, callback) {
|
||||
if (!tab.nodeName || tab.nodeName.toUpperCase() !== 'LI') {
|
||||
throw new Exception('Toolbar not found, make sure you loaded it.');
|
||||
}
|
||||
var panel = {
|
||||
id : false,
|
||||
element : tab,
|
||||
callback : callback,
|
||||
button : undefined,
|
||||
content : undefined,
|
||||
active : false
|
||||
};
|
||||
for (var i in tab.childNodes) {
|
||||
var element = tab.childNodes[i],
|
||||
tag = element.nodeName? element.nodeName.toUpperCase(): false;
|
||||
if (tag === 'A') {
|
||||
panel.id = element.hash.replace(/^#/, '');
|
||||
panel.button = element;
|
||||
} else if (tag === 'DIV') {
|
||||
panel.content = element;
|
||||
}
|
||||
}
|
||||
if (!panel.id) {
|
||||
throw new Exception('invalid element');
|
||||
}
|
||||
|
||||
if (panel.button.id && panel.button.id === 'hide-toolbar') {
|
||||
panel.callback = this.toggleToolbar;
|
||||
}
|
||||
|
||||
if (panel.callback !== undefined) {
|
||||
panel.button.onclick = function() { return panel.callback(); };
|
||||
} else {
|
||||
panel.button.onclick = function() { return window.DebugKit.togglePanel(panel.id); };
|
||||
}
|
||||
|
||||
panels[panel.id] = panel;
|
||||
return panel.id;
|
||||
};
|
||||
/**
|
||||
* Hide/show the toolbar (minimize cake)
|
||||
*/
|
||||
this.toggleToolbar = function() {
|
||||
for (var i in panels) {
|
||||
var panel = panels[i],
|
||||
display = hidden? 'block': 'none';
|
||||
if (panel.content !== undefined) {
|
||||
panel.element.style.display = display;
|
||||
}
|
||||
}
|
||||
hidden = !hidden;
|
||||
return true;
|
||||
};
|
||||
/**
|
||||
* Toggle a panel
|
||||
*/
|
||||
this.togglePanel = function(id) {
|
||||
if (panels[id] && panels[id].active) {
|
||||
this.deactivatePanel(true);
|
||||
} else {
|
||||
this.deactivatePanel(true);
|
||||
this.activatePanel(id);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Make a panel active.
|
||||
*/
|
||||
this.activatePanel = function(id, unique) {
|
||||
if (panels[id] !== undefined && !panels[id].active) {
|
||||
var panel = panels[id];
|
||||
this.deactivatePanel(true);
|
||||
if (panel.content !== undefined) {
|
||||
panel.content.style.display = 'block';
|
||||
}
|
||||
panel.button.className = panel.button.className.replace(/^(.*)$/, '$1 active');
|
||||
panel.active = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
/**
|
||||
* Deactivate a panel. use true to hide all panels.
|
||||
*/
|
||||
this.deactivatePanel = function(id) {
|
||||
if (id === true) {
|
||||
for (var i in panels) {
|
||||
this.deactivatePanel(i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (panels[id] !== undefined && panels[id].active) {
|
||||
var panel = panels[id];
|
||||
if (panel.content !== undefined) {
|
||||
panel.content.style.display = 'none';
|
||||
}
|
||||
panel.button.className = panel.button.className.replace(/ ?(active) ?/, '');
|
||||
panel.active = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
/**
|
||||
* Add neat array functionality.
|
||||
*/
|
||||
function neatArray(list) {
|
||||
if (!list.className.match(/depth-0/)) {
|
||||
var item = list.parentNode;
|
||||
list.style.display = 'none';
|
||||
item.className = (item.className || '').replace(/^(.*)$/, '$1 expandable collapsed');
|
||||
item.onclick = function(event) {
|
||||
//var element = (event === undefined)? this: event.target;
|
||||
var element = this,
|
||||
event = event || window.event,
|
||||
act = Boolean(item === element),
|
||||
hide = Boolean(list.style.display === 'block');
|
||||
if (act && hide) {
|
||||
list.style.display = 'none';
|
||||
item.className = item.className.replace(/expanded|$/, 'collapsed');
|
||||
} else if (act) {
|
||||
list.style.display = 'block';
|
||||
item.className = item.className.replace('collapsed', 'expanded');
|
||||
}
|
||||
|
||||
if (event.cancelBubble !== undefined) {
|
||||
event.cancelBubble = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.initialize(id);
|
||||
}
|
||||
|
||||
DebugKit.install = function() {
|
||||
var initializer = window.onload || function() {};
|
||||
window.onload = function() {
|
||||
initializer();
|
||||
// makes DebugKit a singletone instance
|
||||
window.DebugKit = new DebugKit();
|
||||
}
|
||||
}
|
||||
|
||||
DebugKit.install();
|
||||
95
plugins/debug_kit/vendors/js/mootools_debug_toolbar.js
vendored
Normal file
95
plugins/debug_kit/vendors/js/mootools_debug_toolbar.js
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Debug Toolbar Javascript. Mootools 1.2 compatible.
|
||||
*
|
||||
* Requires Class, Event, Element, and Selectors
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.
|
||||
* @since CakePHP v 1.2.0.4487
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
window.addEvent('domready', function() {
|
||||
new DebugKit();
|
||||
});
|
||||
var DebugKit = new Class({
|
||||
initialize : function() {
|
||||
this.neatArray();
|
||||
this.toolbar();
|
||||
},
|
||||
/**
|
||||
* Create all behaviors for neat array elements
|
||||
*/
|
||||
neatArray : function() {
|
||||
$$('#debug-kit-toolbar .neat-array li').each(function(listItem) {
|
||||
var subUl = listItem.getElement('ul');
|
||||
if (subUl) {
|
||||
listItem.addClass('expandable').addClass('collapsed');
|
||||
subUl.setStyle('display', 'none').set('state', 'closed');
|
||||
listItem.addEvent('click', function(event) {
|
||||
event.stop();
|
||||
this.toggleClass('expanded').toggleClass('collapsed');
|
||||
if (subUl.get('state') == 'closed') {
|
||||
subUl.setStyle('display', 'block').set('state', 'open');
|
||||
} else {
|
||||
subUl.setStyle('display', 'none').set('state', 'closed');
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Add behavior for toolbar buttons
|
||||
*/
|
||||
toolbar : function() {
|
||||
var tabCollection = $$('#debug-kit-toolbar li > div');
|
||||
|
||||
$$('#debug-kit-toolbar .panel-tab > a').addEvent('click', function(event) {
|
||||
event.stop();
|
||||
var buttonId = this.hash.substring(1, this.hash.length) + '-tab';
|
||||
var targetPanel = $(buttonId);
|
||||
if (!targetPanel) return;
|
||||
$$('#debug-kit-toolbar .panel-tab > a').removeClass('active');
|
||||
if (targetPanel.hasClass('active')) {
|
||||
tabCollection.removeClass('active').setStyle('display', 'none');
|
||||
} else {
|
||||
tabCollection.setStyle('display', 'none').removeClass('active');
|
||||
targetPanel.addClass('active').setStyle('display', 'block');
|
||||
this.addClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
//enable hiding of toolbar.
|
||||
var panelButtons = $$('#debug-kit-toolbar .panel-tab:not(.panel-tab.icon)');
|
||||
var toolbarHide = $('hide-toolbar').set('state', 'open');
|
||||
toolbarHide.addEvent('click', function(event) {
|
||||
event.stop();
|
||||
var state = this.get('state');
|
||||
if (state == 'open') {
|
||||
panelButtons.setStyle('display', 'none');
|
||||
this.set('state', 'closed')
|
||||
} else {
|
||||
panelButtons.setStyle('display');
|
||||
this.set('state', 'open');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
95
plugins/debug_kit/vendors/js/prototype_debug_toolbar.js
vendored
Normal file
95
plugins/debug_kit/vendors/js/prototype_debug_toolbar.js
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Debug Toolbar Javascript. Prototype 1.6.x compatible.
|
||||
*
|
||||
* Long description here.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.
|
||||
* @since CakePHP v 1.2.0.4487
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
document.observe('dom:loaded', function() {
|
||||
new DebugKit();
|
||||
});
|
||||
|
||||
var DebugKit = Class.create({
|
||||
|
||||
initialize: function(){
|
||||
this.toolbar();
|
||||
this.neatArray();
|
||||
},
|
||||
|
||||
toolbar: function(){
|
||||
var tabCollection = $('debug-kit-toolbar').select('li > div');
|
||||
|
||||
$('debug-kit-toolbar').select('.panel-tab > a').invoke('observe', 'click', function(e){
|
||||
e.stop();
|
||||
var targetPanel = $(e.element().hash.replace(/#/, '') + '-tab');
|
||||
if (targetPanel.hasClassName('active')) {
|
||||
tabCollection.each(function(ele){
|
||||
ele.hide().removeClassName('active');
|
||||
});
|
||||
} else {
|
||||
tabCollection.each(function(ele){
|
||||
ele.hide().removeClassName('active');
|
||||
if (targetPanel.id == ele.id) {
|
||||
ele.setStyle({display: 'block'}).addClassName('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
$('debug-kit-toolbar').select('.panel-tab > a').invoke('removeClassName', 'active');
|
||||
e.element().addClassName('active');
|
||||
});
|
||||
|
||||
// enable hiding of toolbar.
|
||||
var panelButtons = $('debug-kit-toolbar').select('.panel-tab');
|
||||
$('hide-toolbar').observe('click', function(eve){
|
||||
eve.stop();
|
||||
panelButtons.each(function(panel){
|
||||
if (!panel.hasClassName('icon')) {
|
||||
panel.toggle();
|
||||
};
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Create all behaviors for neat array elements
|
||||
*/
|
||||
neatArray: function() {
|
||||
$('debug-kit-toolbar').select('.neat-array li').each(function(ele){
|
||||
var sub = ele.select('ul');
|
||||
if (sub.length > 0) {
|
||||
ele.addClassName('collapsed').addClassName('expandable');
|
||||
sub.invoke('hide');
|
||||
ele.observe('click', function(eve){
|
||||
if (eve.element() == ele || eve.element().up() == ele) {
|
||||
if (sub.length > 0) {
|
||||
ele.toggleClassName('expanded').toggleClassName('collapsed');
|
||||
sub[0].toggle();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
126
plugins/debug_kit/vendors/js/yui_debug_toolbar.js
vendored
Normal file
126
plugins/debug_kit/vendors/js/yui_debug_toolbar.js
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Debug Toolbar Javascript. YUI 2.6 compatible.
|
||||
*
|
||||
* Long description here.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.
|
||||
* @since CakePHP v 1.2.0.4487
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
|
||||
YAHOO.namespace('CakePHP.DebugKit');
|
||||
|
||||
YAHOO.CakePHP.DebugKit = function() {
|
||||
|
||||
var Event = YAHOO.util.Event;
|
||||
var Dom = YAHOO.util.Dom;
|
||||
var Selector = YAHOO.util.Selector;
|
||||
|
||||
|
||||
var toggle = function(el) {
|
||||
Dom.setStyle(el, 'display', ((Dom.getStyle(el, 'display') == 'none') ? '' : 'none'));
|
||||
};
|
||||
|
||||
var toggleClass = function(element, className) {
|
||||
(Dom.hasClass(element, className)) ? Dom.removeClass(element, className) : Dom.addClass(element, className);
|
||||
};
|
||||
|
||||
|
||||
|
||||
var toolbar = function() {
|
||||
var tabCollection = Selector.query('#debug-kit-toolbar li > div');
|
||||
|
||||
Dom.batch(Selector.query('#debug-kit-toolbar .panel-tab > a'), function(el) {
|
||||
Event.on(el, 'click', function(ev) {
|
||||
Event.preventDefault(ev);
|
||||
targetPanel =Dom.get(el.hash.replace(/#/, '') + '-tab');
|
||||
|
||||
if (Dom.hasClass(targetPanel, 'active')) {
|
||||
Dom.batch(tabCollection, function(ele) {
|
||||
toggle(ele);
|
||||
Dom.removeClass(ele, 'active');
|
||||
Dom.setStyle(ele, 'display', '');
|
||||
});
|
||||
} else {
|
||||
Dom.batch(tabCollection, function(ele) {
|
||||
toggle(ele);
|
||||
Dom.removeClass(ele, 'active');
|
||||
|
||||
if (targetPanel && targetPanel.id == ele.id) {
|
||||
Dom.setStyle(ele, 'display', 'block');
|
||||
Dom.addClass(ele, 'active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Dom.removeClass(Selector.query('#debug-kit-toolbar .panel-tab > a'), 'active');
|
||||
Dom.addClass(el, 'active');
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
var neatArray = function() {
|
||||
nodes = Selector.query('#debug-kit-toolbar .panel-content > ul.neat-array li > ul');
|
||||
|
||||
if (nodes.length > 0) {
|
||||
Dom.batch(nodes, function(el) {
|
||||
|
||||
var parent = el.parentNode;
|
||||
|
||||
Dom.addClass(parent, 'collapsed');
|
||||
Dom.addClass(parent, 'expandable');
|
||||
toggle(nodes);
|
||||
|
||||
Event.on(parent, 'click', function(ev) {
|
||||
sub = Selector.query('ul', parent);
|
||||
toggleClass(parent, 'expanded');
|
||||
toggleClass(parent, 'collapsed');
|
||||
toggle(sub);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var panelButtons = function() {
|
||||
Event.on('hide-toolbar', 'click', function(ev) {
|
||||
Event.preventDefault(ev);
|
||||
|
||||
Dom.getElementsByClassName('panel-tab', 'li', 'debug-kit-toolbar', function (el) {
|
||||
if (!Dom.hasClass(el, 'icon')) {
|
||||
toggle(el);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
initialize: function() {
|
||||
neatArray();
|
||||
toolbar();
|
||||
panelButtons();
|
||||
}
|
||||
};
|
||||
}(); // Execute annonymous closure & return results
|
||||
|
||||
YAHOO.util.Event.onDOMReady(YAHOO.CakePHP.DebugKit.initialize);
|
||||
79
plugins/debug_kit/vendors/shells/benchmark.php
vendored
Normal file
79
plugins/debug_kit/vendors/shells/benchmark.php
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Benchmark Shell.
|
||||
*
|
||||
* Provides basic benchmarking of application requests
|
||||
* functionally similar to Apache AB
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.debug_kit.vendors.shells
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
class BenchmarkShell extends Shell {
|
||||
function main() {
|
||||
$url = $this->args[0];
|
||||
$this->out(sprintf('-> Testing %s', $url));
|
||||
|
||||
$n = 100;
|
||||
$t = $i = 0;
|
||||
if (isset($this->params['n'])) {
|
||||
$n = $this->params['n'];
|
||||
}
|
||||
if (isset($this->params['t'])) {
|
||||
$t = $this->params['t'];
|
||||
}
|
||||
$start = microtime(true);
|
||||
while (true) {
|
||||
if ($t && $t <= floor(microtime(true) - $start)) {
|
||||
break;
|
||||
}
|
||||
if ($n <= $i) {
|
||||
break;
|
||||
}
|
||||
file_get_contents($url);
|
||||
$i++;
|
||||
}
|
||||
$duration = microtime(true) - $start;
|
||||
$this->out('Total Requests made: ' . $i);
|
||||
$this->out('Total Time elapsed: ' . $duration . '(s)');
|
||||
$this->out(round($n / $duration, 2).' req/sec');
|
||||
}
|
||||
|
||||
function help() {
|
||||
$out = <<<EOL
|
||||
DebugKit Benchmark Shell
|
||||
|
||||
Test a fully qualified url to get avg requests per second.
|
||||
By default it does 100 requests to the provided url.
|
||||
|
||||
Use:
|
||||
cake benchmark [params] [url]
|
||||
|
||||
Params
|
||||
-n The maximum number of iterations to do.
|
||||
|
||||
-t The maximum time to take. If a single request takes more
|
||||
than this time. Only one request will be made.
|
||||
EOL;
|
||||
$this->out($out);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
154
plugins/debug_kit/views/debug.php
Normal file
154
plugins/debug_kit/views/debug.php
Normal file
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Debug View
|
||||
*
|
||||
* Custom Debug View class, helps with development.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.cake.libs.
|
||||
* @since CakePHP v 1.2.0.4487
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
App::import('Vendor', 'DebugKit.DebugKitDebugger');
|
||||
App::import('Component', 'DebugKit.Toolbar');
|
||||
/**
|
||||
* DebugView used by DebugKit
|
||||
*
|
||||
* @package debug_kit.views
|
||||
* @todo Remove workarounds.
|
||||
*/
|
||||
class DebugView extends DoppelGangerView {
|
||||
/**
|
||||
* The old extension of the current template.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
var $_oldExtension = null;
|
||||
/**
|
||||
* Overload _render to capture filenames and time actual rendering of each view file
|
||||
*
|
||||
* @param string $___viewFn Filename of the view
|
||||
* @param array $___dataForView Data to include in rendered view
|
||||
* @return string Rendered output
|
||||
* @access protected
|
||||
*/
|
||||
function _render($___viewFn, $___dataForView, $loadHelpers = true, $cached = false) {
|
||||
/* pr(array('function' => 'DebugView::_render', */
|
||||
/* 'args' => compact('__viewFn', '__dataForView', 'loadHelpers'), */
|
||||
/* 'this-output-len' => strlen($this->output), */
|
||||
/* )); */
|
||||
if (isset($this->_oldExtension) && strstr($___viewFn, '.debug_view')) {
|
||||
$___viewFn = substr($___viewFn, 0, -10) . $this->_oldExtension;
|
||||
}
|
||||
if (!isset($___dataForView['disableTimer'])) {
|
||||
DebugKitDebugger::startTimer('render_' . basename($___viewFn), sprintf(__('Rendering %s', true), Debugger::trimPath($___viewFn)));
|
||||
}
|
||||
|
||||
$out = parent::_render($___viewFn, $___dataForView, $loadHelpers, $cached);
|
||||
|
||||
if (!isset($___dataForView['disableTimer'])) {
|
||||
DebugKitDebugger::stopTimer('render_' . basename($___viewFn));
|
||||
}
|
||||
/* pr(array('function' => 'DebugView::_render', */
|
||||
/* 'out-len' => strlen($out), */
|
||||
/* 'this-output-len' => strlen($this->output), */
|
||||
/* 'return' => $out ? 'not-empty' : 'empty')); */
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders view for given action and layout. If $file is given, that is used
|
||||
* for a view filename (e.g. customFunkyView.ctp).
|
||||
* Adds timers, for all subsequent rendering, and injects the debugKit toolbar.
|
||||
*
|
||||
* @param string $action Name of action to render for
|
||||
* @param string $layout Layout to use
|
||||
* @param string $file Custom filename for view
|
||||
* @return string Rendered Element
|
||||
*/
|
||||
function render($action = null, $layout = null, $file = null) {
|
||||
/* pr(array('function' => 'DebugView::render', */
|
||||
/* 'args' => compact('action', 'layout', 'file'), */
|
||||
/* 'this-output-len' => strlen($this->output), */
|
||||
/* )); */
|
||||
DebugKitDebugger::startTimer('viewRender', __('Rendering View', true));
|
||||
$out = parent::render($action, $layout, $file);
|
||||
/* pr(array('function' => 'DebugView::render', */
|
||||
/* 'checkpoint' => 'parent::render', */
|
||||
/* 'out' => $out ? 'not-empty' : 'empty')); */
|
||||
DebugKitDebugger::stopTimer('viewRender');
|
||||
DebugKitDebugger::stopTimer('controllerRender');
|
||||
|
||||
if (isset($this->loaded['toolbar'])) {
|
||||
/* pr(array('function' => 'DebugView::render', */
|
||||
/* 'checkpoint' => 'toolbarLoaded')); */
|
||||
$this->loaded['toolbar']->postRender();
|
||||
}
|
||||
//Temporary work around to hide the SQL dump at page bottom
|
||||
Configure::write('debug', 0);
|
||||
/* pr(array('function' => 'DebugView::render', */
|
||||
/* 'out-len' => strlen($out), */
|
||||
/* 'this-output-len' => strlen($this->output), */
|
||||
/* 'return' => $this->output ? 'not-empty' : 'empty')); */
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Workaround _render() limitation in core. Which forces View::_render() for .ctp and .thtml templates
|
||||
* Creates temporary extension to trick View::render() & View::renderLayout()
|
||||
*
|
||||
* @param string $name Action name.
|
||||
* @return string
|
||||
**/
|
||||
function _getViewFileName($name = null) {
|
||||
$filename = parent::_getViewFileName($name);
|
||||
return $this->_replaceExtension($filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Workaround _render() limitation in core. Which forces View::_render() for .ctp and .thtml templates
|
||||
* Creates temporary extension to trick View::render() & View::renderLayout()
|
||||
*
|
||||
* @param string $name Layout Name
|
||||
* @return string
|
||||
**/
|
||||
function _getLayoutFileName($name = null) {
|
||||
$filename = parent::_getLayoutFileName($name);
|
||||
return $this->_replaceExtension($filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* replace the Extension on a filename and set the temporary workaround extension.
|
||||
*
|
||||
* @param string $filename Filename to replace extension for.
|
||||
* @return string
|
||||
**/
|
||||
function _replaceExtension($filename) {
|
||||
if (substr($filename, -3) == 'ctp') {
|
||||
$this->_oldExtension = 'ctp';
|
||||
$filename = substr($filename, 0, strlen($filename) -3) . 'debug_view';
|
||||
} elseif (substr($filename, -5) == 'thtml') {
|
||||
$this->_oldExtension = 'thtml';
|
||||
$filename = substr($filename, 0, strlen($filename) -5) . 'debug_view';
|
||||
}
|
||||
return $filename;
|
||||
}
|
||||
}
|
||||
?>
|
||||
52
plugins/debug_kit/views/elements/debug_toolbar.ctp
Normal file
52
plugins/debug_kit/views/elements/debug_toolbar.ctp
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Debug Toolbar Element
|
||||
*
|
||||
* Renders all of the other panel elements.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.debug_kit.views.elements
|
||||
* @since
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
?>
|
||||
<div id="debug-kit-toolbar">
|
||||
<?php if (empty($debugToolbarPanels)) :?>
|
||||
<p class="warning"><?php __('There are no active panels. You must enable a panel to see its output.'); ?></p>
|
||||
<?php else: ?>
|
||||
<ul id="panel-tabs">
|
||||
<li class="panel-tab icon">
|
||||
<a href="#hide" id="hide-toolbar">
|
||||
<?php echo $html->image('/debug_kit/img/cake.icon.png', array('alt' => 'cakePHP')); ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php foreach ($debugToolbarPanels as $panelName => $panelInfo): ?>
|
||||
<li class="panel-tab">
|
||||
<a href="#<?php echo Inflector::underscore($panelName); ?>">
|
||||
<?php echo Inflector::humanize(Inflector::underscore($panelName)); ?>
|
||||
</a>
|
||||
<div class="panel-content" id="<?php echo Inflector::underscore($panelName); ?>-tab">
|
||||
<?php echo $this->element($panelInfo['elementName'], $panelInfo); ?>
|
||||
</div>
|
||||
</li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
0
plugins/debug_kit/views/elements/empty
Normal file
0
plugins/debug_kit/views/elements/empty
Normal file
48
plugins/debug_kit/views/elements/log_panel.ctp
Normal file
48
plugins/debug_kit/views/elements/log_panel.ctp
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Log Panel Element
|
||||
*
|
||||
*
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.debug_kit.views.elements
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
?>
|
||||
<h2><?php __('Logs') ?></h2>
|
||||
<div class="code-table">
|
||||
<?php foreach ($content as $logName => $logs): ?>
|
||||
<h3><?php echo $logName ?></h3>
|
||||
<?php
|
||||
$len = count($logs);
|
||||
if ($len > 0):
|
||||
$headers = array(__('Time', true), __('Message', true));
|
||||
$rows = array();
|
||||
for ($i = 0; $i < $len; $i += 2):
|
||||
$rows[] = array(
|
||||
$logs[$i], $logs[$i + 1]
|
||||
);
|
||||
endfor;
|
||||
echo $toolbar->table($rows, $headers, array('title' => $logName));
|
||||
else: ?>
|
||||
<p class="info"><?php __('There were no log entries made this request'); ?></p>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
43
plugins/debug_kit/views/elements/memory_panel.ctp
Normal file
43
plugins/debug_kit/views/elements/memory_panel.ctp
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Session Panel Element
|
||||
*
|
||||
*
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.debug_kit.views.elements
|
||||
* @since
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
?>
|
||||
<h2><?php __('Memory'); ?></h2>
|
||||
<div class="current-mem-use">
|
||||
<?php echo $toolbar->message(
|
||||
__('Current Memory Use',true),
|
||||
$number->toReadableSize(DebugKitDebugger::getMemoryUse())
|
||||
);?>
|
||||
</div>
|
||||
<div class="peak-mem-use">
|
||||
<?php
|
||||
echo $toolbar->message(
|
||||
__('Peak Memory Use', true),
|
||||
$number->toReadableSize(DebugKitDebugger::getPeakMemoryUse())
|
||||
);
|
||||
?></div>
|
||||
45
plugins/debug_kit/views/elements/request_panel.ctp
Normal file
45
plugins/debug_kit/views/elements/request_panel.ctp
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Request Panel Element
|
||||
*
|
||||
*
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.debug_kit.views.elements
|
||||
* @since
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
?>
|
||||
<h2> <?php __('Request'); ?></h2>
|
||||
<h4>Cake Params</h4>
|
||||
<?php echo $toolbar->makeNeatArray($content['params']); ?>
|
||||
|
||||
<h4>$_GET</h4>
|
||||
<?php echo $toolbar->makeNeatArray($content['get']); ?>
|
||||
|
||||
<h4>Cookie</h4>
|
||||
<?php if (isset($content['cookie'])): ?>
|
||||
<?php echo $toolbar->makeNeatArray($content['cookie']); ?>
|
||||
<?php else: ?>
|
||||
<p class="warning">To view Cookies, add CookieComponent to Controller
|
||||
<?php endif; ?>
|
||||
|
||||
<h4><?php __('Current Route') ?></h4>
|
||||
<?php echo $toolbar->makeNeatArray($content['currentRoute']); ?>
|
||||
31
plugins/debug_kit/views/elements/session_panel.ctp
Normal file
31
plugins/debug_kit/views/elements/session_panel.ctp
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Session Panel Element
|
||||
*
|
||||
*
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.debug_kit.views.elements
|
||||
* @since
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
?>
|
||||
<h2><?php __('Session'); ?></h2>
|
||||
<?php echo $toolbar->makeNeatArray($content); ?>
|
||||
40
plugins/debug_kit/views/elements/sql_log_panel.ctp
Normal file
40
plugins/debug_kit/views/elements/sql_log_panel.ctp
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Session Panel Element
|
||||
*
|
||||
*
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.debug_kit.views.elements
|
||||
* @since
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
?>
|
||||
<h2><?php __('Sql Logs')?></h2>
|
||||
<?php if (!empty($content)) : ?>
|
||||
<?php foreach ($content as $dbName => $queryLog) : ?>
|
||||
<div class="sql-log-panel-query-log">
|
||||
<h4><?php echo $dbName ?></h4>
|
||||
<?php echo $queryLog; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<p class="warning"><?php __('No active database connections'); ?>
|
||||
<?php endif; ?>
|
||||
44
plugins/debug_kit/views/elements/timer_panel.ctp
Normal file
44
plugins/debug_kit/views/elements/timer_panel.ctp
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Timer Panel Element
|
||||
*
|
||||
*
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.debug_kit.views.elements
|
||||
* @since
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
$timers = DebugKitDebugger::getTimers();
|
||||
?>
|
||||
<h2><?php __('Timers'); ?></h2>
|
||||
<p class="request-time">
|
||||
<?php $totalTime = sprintf(__('%s (seconds)', true), $number->precision(DebugKitDebugger::requestTime(), 6)); ?>
|
||||
<?php echo $toolbar->message(__('Total Request Time:', true), $totalTime)?>
|
||||
</p>
|
||||
|
||||
<?php foreach ($timers as $timerName => $timeInfo):
|
||||
$rows[] = array(
|
||||
$timeInfo['message'],
|
||||
$number->precision($timeInfo['time'], 6)
|
||||
);
|
||||
$headers = array(__('Message', true), __('time in seconds', true));
|
||||
endforeach;
|
||||
echo $toolbar->table($rows, $headers, array('title' => 'Timers')); ?>
|
||||
35
plugins/debug_kit/views/elements/variables_panel.ctp
Normal file
35
plugins/debug_kit/views/elements/variables_panel.ctp
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* View Variables Panel Element
|
||||
*
|
||||
*
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package cake
|
||||
* @subpackage cake.debug_kit.views.elements
|
||||
* @since
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
?>
|
||||
<h2> <?php __('View Variables'); ?></h2>
|
||||
<?php
|
||||
$vars = $this->viewVars;
|
||||
unset($vars['debugToolbarPanels'], $vars['debugToolbarJavascript']);
|
||||
?>
|
||||
<?php echo $toolbar->makeNeatArray($vars); ?>
|
||||
79
plugins/debug_kit/views/helpers/fire_php_toolbar.php
Normal file
79
plugins/debug_kit/views/helpers/fire_php_toolbar.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* FirePHP Toolbar Helper
|
||||
*
|
||||
* Injects the toolbar elements into non-HTML layouts via FireCake.
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package debug_kit
|
||||
* @subpackage debug_kit.views.helpers
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
App::import('helper', 'DebugKit.Toolbar');
|
||||
App::import('Vendor', 'DebugKit.FireCake');
|
||||
|
||||
class FirePhpToolbarHelper extends ToolbarHelper {
|
||||
/**
|
||||
* send method
|
||||
*
|
||||
* @return void
|
||||
* @access protected
|
||||
*/
|
||||
function _send() {
|
||||
$view =& ClassRegistry::getObject('view');
|
||||
$view->element('debug_toolbar', array('plugin' => 'debug_kit', 'disableTimer' => true));
|
||||
Configure::write('debug', 1);
|
||||
}
|
||||
/**
|
||||
* makeNeatArray.
|
||||
*
|
||||
* wraps FireCake::dump() allowing panel elements to continue functioning
|
||||
*
|
||||
* @param string $values
|
||||
* @return void
|
||||
*/
|
||||
function makeNeatArray($values) {
|
||||
FireCake::info($values);
|
||||
}
|
||||
/**
|
||||
* Create a simple message
|
||||
*
|
||||
* @param string $label Label of message
|
||||
* @param string $message Message content
|
||||
* @return void
|
||||
*/
|
||||
function message($label, $message) {
|
||||
FireCake::log($message, $label);
|
||||
}
|
||||
/**
|
||||
* Generate a table with FireCake
|
||||
*
|
||||
* @param array $rows Rows to print
|
||||
* @param array $headers Headers for table
|
||||
* @param array $options Additional options and params
|
||||
* @return void
|
||||
*/
|
||||
function table($rows, $headers, $options = array()) {
|
||||
$title = $headers[0];
|
||||
if (isset($options['title'])) {
|
||||
$title = $options['title'];
|
||||
}
|
||||
array_unshift($rows, $headers);
|
||||
FireCake::table($title, $rows);
|
||||
}
|
||||
}
|
||||
?>
|
||||
150
plugins/debug_kit/views/helpers/html_toolbar.php
Normal file
150
plugins/debug_kit/views/helpers/html_toolbar.php
Normal file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Html Toolbar Helper
|
||||
*
|
||||
* Injects the toolbar elements into HTML layouts.
|
||||
* Contains helper methods for
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* 1785 E. Sahara Avenue, Suite 490-204
|
||||
* Las Vegas, Nevada 89104
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package debug_kit
|
||||
* @subpackage debug_kit.views.helpers
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
App::import('helper', 'DebugKit.Toolbar');
|
||||
|
||||
class HtmlToolbarHelper extends ToolbarHelper {
|
||||
/**
|
||||
* helpers property
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $helpers = array('Html', 'Javascript');
|
||||
/**
|
||||
* settings property
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $settings = array('format' => 'html');
|
||||
/**
|
||||
* Recursively goes through an array and makes neat HTML out of it.
|
||||
*
|
||||
* @param mixed $values Array to make pretty.
|
||||
* @param int $openDepth Depth to add open class
|
||||
* @param int $currentDepth current depth.
|
||||
* @return string
|
||||
**/
|
||||
function makeNeatArray($values, $openDepth = 0, $currentDepth = 0) {
|
||||
$className ="neat-array depth-$currentDepth";
|
||||
if ($openDepth > $currentDepth) {
|
||||
$className .= ' expanded';
|
||||
}
|
||||
$nextDepth = $currentDepth + 1;
|
||||
$out = "<ul class=\"$className\">";
|
||||
if (!is_array($values)) {
|
||||
if (is_bool($values)) {
|
||||
$values = array($values);
|
||||
}
|
||||
if (is_null($values)) {
|
||||
$values = array(null);
|
||||
}
|
||||
}
|
||||
foreach ($values as $key => $value) {
|
||||
$out .= '<li><strong>' . $key . '</strong>';
|
||||
if ($value === null) {
|
||||
$value = '(null)';
|
||||
}
|
||||
if ($value === false) {
|
||||
$value = '(false)';
|
||||
}
|
||||
if ($value === true) {
|
||||
$value = '(true)';
|
||||
}
|
||||
if (empty($value) && $value != 0) {
|
||||
$value = '(empty)';
|
||||
}
|
||||
|
||||
if (is_object($value)) {
|
||||
$value = Set::reverse($value, true);
|
||||
}
|
||||
|
||||
if (is_array($value) && !empty($value)) {
|
||||
$out .= $this->makeNeatArray($value, $openDepth, $nextDepth);
|
||||
} else {
|
||||
$out .= $value;
|
||||
}
|
||||
$out .= '</li>';
|
||||
}
|
||||
$out .= '</ul>';
|
||||
return $out;
|
||||
}
|
||||
/**
|
||||
* Create an HTML message
|
||||
*
|
||||
* @param string $label label content
|
||||
* @param string $message message content
|
||||
* @return string
|
||||
*/
|
||||
function message($label, $message) {
|
||||
return sprintf('<p><strong>%s</strong> %s</p>', $label, $message);
|
||||
}
|
||||
/**
|
||||
* Create a table.
|
||||
*
|
||||
* @param array $rows Rows to make.
|
||||
* @param array $headers Optional header row.
|
||||
* @return string
|
||||
*/
|
||||
function table($rows, $headers = array()) {
|
||||
$out = '<table class="debug-table">';
|
||||
if (!empty($headers)) {
|
||||
$out .= $this->Html->tableHeaders($headers);
|
||||
}
|
||||
$out .= $this->Html->tableCells($rows, array('class' => 'odd'), array('class' => 'even'));
|
||||
$out .= '</table>';
|
||||
return $out;
|
||||
}
|
||||
/**
|
||||
* send method
|
||||
*
|
||||
* @return void
|
||||
* @access protected
|
||||
*/
|
||||
function _send() {
|
||||
if (Configure::read('debug') == 0) {
|
||||
return;
|
||||
}
|
||||
$view =& ClassRegistry::getObject('view');
|
||||
$head = $this->Html->css('/debug_kit/css/debug_toolbar');
|
||||
if (isset($view->viewVars['debugToolbarJavascript'])) {
|
||||
foreach ($view->viewVars['debugToolbarJavascript'] as $script) {
|
||||
if ($script) {
|
||||
$head .= $this->Javascript->link($script);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (preg_match('#</head>#', $view->output)) {
|
||||
$view->output = preg_replace('#</head>#', $head . "\n</head>", $view->output, 1);
|
||||
}
|
||||
$toolbar = $view->element('debug_toolbar', array('plugin' => 'debug_kit', 'disableTimer' => true));
|
||||
if (preg_match('#</body>#', $view->output)) {
|
||||
$view->output = preg_replace('#</body>#', $toolbar . "\n</body>", $view->output, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
90
plugins/debug_kit/views/helpers/toolbar.php
Normal file
90
plugins/debug_kit/views/helpers/toolbar.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/* SVN FILE: $Id$ */
|
||||
/**
|
||||
* Abstract Toolbar helper. Provides Base methods for content
|
||||
* specific debug toolbar helpers. Acts as a facade for other toolbars helpers as well.
|
||||
*
|
||||
* helps with development.
|
||||
*
|
||||
* PHP versions 4 and 5
|
||||
*
|
||||
* CakePHP : Rapid Development Framework <http://www.cakephp.org/>
|
||||
* Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @filesource
|
||||
* @copyright Copyright 2006-2008, Cake Software Foundation, Inc.
|
||||
* @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project
|
||||
* @package debug_kit
|
||||
* @subpackage debug_kit.views.helpers
|
||||
* @since v 1.0
|
||||
* @version $Revision$
|
||||
* @modifiedby $LastChangedBy$
|
||||
* @lastmodified $Date$
|
||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||
*/
|
||||
App::import('Vendor', 'DebugKit.DebugKitDebugger');
|
||||
|
||||
class ToolbarHelper extends AppHelper {
|
||||
/**
|
||||
* settings property to be overloaded. Subclasses should specify a format
|
||||
*
|
||||
* @var array
|
||||
* @access public
|
||||
*/
|
||||
var $settings = array();
|
||||
/**
|
||||
* Construct the helper and make the backend helper.
|
||||
*
|
||||
* @param string $options
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function __construct($options = array()) {
|
||||
$this->_myName = strtolower(get_class($this));
|
||||
if ($this->_myName !== 'toolbarhelper') {
|
||||
return;
|
||||
}
|
||||
if (!isset($options['output'])) {
|
||||
$options['output'] = 'DebugKit.HtmlToolbar';
|
||||
}
|
||||
App::import('Helper', $options['output']);
|
||||
$className = $options['output'];
|
||||
if (strpos($options['output'], '.') !== false) {
|
||||
list($plugin, $className) = explode('.', $options['output']);
|
||||
}
|
||||
$this->_backEndClassName = $className;
|
||||
$this->helpers = array($options['output']);
|
||||
}
|
||||
|
||||
/**
|
||||
* call__
|
||||
*
|
||||
* Allows method calls on backend helper
|
||||
*
|
||||
* @param string $method
|
||||
* @param mixed $params
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function call__($method, $params) {
|
||||
if (method_exists($this->{$this->_backEndClassName}, $method)) {
|
||||
return $this->{$this->_backEndClassName}->dispatchMethod($method, $params);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* postRender method
|
||||
*
|
||||
* Custom Callback defined in DebugView to allow helpers to modify
|
||||
* View output after all rendering is complete.
|
||||
*
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
function postRender() {
|
||||
$this->_send();
|
||||
}
|
||||
}
|
||||
207
views/accounts/collected.ctp
Normal file
207
views/accounts/collected.ctp
Normal file
@@ -0,0 +1,207 @@
|
||||
<?php /* -*- mode:PHP -*- */
|
||||
|
||||
echo '<div class="account collected">' . "\n";
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
* Javascript
|
||||
*/
|
||||
|
||||
?>
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
|
||||
// Reset the form
|
||||
function resetForm() {
|
||||
// Kick off the grid
|
||||
updateEntriesGrid();
|
||||
}
|
||||
|
||||
function onGridLoadComplete() {
|
||||
var userdata = $('#collected-entries-jqGrid').getGridParam('userData');
|
||||
$('#collected-total').html(fmtCurrency(userdata['total']));
|
||||
}
|
||||
|
||||
function updateEntriesGrid() {
|
||||
var account_ids = new Array();
|
||||
$("INPUT[type='checkbox']:checked").each(function(i) {
|
||||
account_ids.push($(this).val());
|
||||
});
|
||||
|
||||
var cust = new Array();
|
||||
cust['from_date'] = $('#TxFromDate').val();
|
||||
cust['through_date'] = $('#TxThroughDate').val();
|
||||
cust['account_id'] = account_ids;
|
||||
|
||||
var dynamic_post = new Array();
|
||||
dynamic_post['custom'] = cust;
|
||||
|
||||
$('#collected-total').html('Calculating...');
|
||||
$('#collected-entries-jqGrid').clearGridData();
|
||||
$('#collected-entries-jqGrid').setPostDataItem('dynamic_post_replace', serialize(dynamic_post));
|
||||
$('#collected-entries-jqGrid')
|
||||
.setGridParam({ page: 1 })
|
||||
.trigger("reloadGrid");
|
||||
|
||||
//$('#debug').html("<PRE>\n"+htmlEncode(dump($('#collected-entries-jqGrid').getGridParam()))+"\n</PRE>")
|
||||
var gridstate = $('#collected-entries-jqGrid').getGridParam('gridstate');
|
||||
if (gridstate == 'hidden')
|
||||
$('#collected-entries .HeaderButton').click();
|
||||
}
|
||||
|
||||
|
||||
--></script>
|
||||
|
||||
<?php
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
* Summary Info Box
|
||||
*/
|
||||
|
||||
echo '<div class="infobox">' . "\n";
|
||||
|
||||
$rows = array();
|
||||
$rows[] = array('Total:', '<SPAN id="collected-total"></SPAN>');
|
||||
echo $this->element('table',
|
||||
array('class' => 'summary',
|
||||
'rows' => $rows,
|
||||
'column_class' => array('field', 'value'),
|
||||
'suppress_alternate_rows' => true,
|
||||
));
|
||||
echo '</div>' . "\n";
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
* User Configuration
|
||||
*/
|
||||
|
||||
echo $form->create(null, array('id' => 'collected-form',
|
||||
'onsubmit' => 'return false',
|
||||
'url' => null));
|
||||
|
||||
echo $form->input("id",
|
||||
array('id' => 'account-id',
|
||||
'type' => 'hidden',
|
||||
'value' => 0));
|
||||
|
||||
/* echo '<fieldset class="account collected entry">'; */
|
||||
/* echo ' <legend>Payment Account</legend>'; */
|
||||
/* echo $form->input('Tx.account_id', */
|
||||
/* array(//'label' => 'Payment<BR>Account', */
|
||||
/* 'label' => false, */
|
||||
/* 'type' => 'select', */
|
||||
/* 'multiple' => 'checkbox', */
|
||||
/* 'options' => $paymentAccounts, */
|
||||
/* 'selected' => array_keys($defaultAccounts), */
|
||||
/* ) */
|
||||
/* ); */
|
||||
/* echo '</fieldset>'; */
|
||||
|
||||
echo $this->element('form_table',
|
||||
array('class' => "item account collected entry",
|
||||
//'with_name_after' => ':',
|
||||
'field_prefix' => 'Tx.',
|
||||
'fields' => array
|
||||
("account_id" => array('name' => 'Payment<BR>Account',
|
||||
'opts' =>
|
||||
array('type' => 'select',
|
||||
'multiple' => 'checkbox',
|
||||
'options' => $paymentAccounts,
|
||||
'selected' => array_keys($defaultAccounts),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
echo $this->element('form_table',
|
||||
array('class' => "item account collected entry",
|
||||
//'with_name_after' => ':',
|
||||
'field_prefix' => 'Tx.',
|
||||
'fields' => array
|
||||
("from_date" => array('opts' =>
|
||||
array('type' => 'text'),
|
||||
'between' => '<A HREF="#" ONCLICK="datepickerBOM(null,\'TxFromDate\'); return false;">BOM</A>',
|
||||
),
|
||||
"through_date" => array('opts' =>
|
||||
array('type' => 'text'),
|
||||
'between' => '<A HREF="#" ONCLICK="datepickerEOM(\'TxFromDate\',\'TxThroughDate\'); return false;">EOM</A>',
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
echo $form->button('Update',
|
||||
array('onclick' => 'updateEntriesGrid(); return false',
|
||||
));
|
||||
|
||||
echo $form->end();
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
* Supporting Elements Section
|
||||
*/
|
||||
|
||||
echo '<div CLASS="detail supporting">' . "\n";
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Entries
|
||||
*/
|
||||
|
||||
echo $this->element('statement_entries', array
|
||||
(// Grid configuration
|
||||
'config' => array
|
||||
(
|
||||
'grid_div_id' => 'collected-entries',
|
||||
'grid_div_class' => 'text-below',
|
||||
'grid_events' => array('loadComplete' => 'onGridLoadComplete()'),
|
||||
'grid_setup' => array('hiddengrid' => true),
|
||||
'caption' => 'Collected ' . Inflector::pluralize($account['name']),
|
||||
'action' => 'collected',
|
||||
'filter' => array('ChargeEntry.account_id' => $account['id']),
|
||||
'include' => array('Amount'),
|
||||
'exclude' => array(/*'Type',*/ 'Debit', 'Credit'),
|
||||
),
|
||||
));
|
||||
|
||||
?>
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
$(document).ready(function(){
|
||||
$("#TxFromDate")
|
||||
.attr('autocomplete', 'off')
|
||||
.datepicker({ constrainInput: true,
|
||||
numberOfMonths: [1, 1],
|
||||
showCurrentAtPos: 0,
|
||||
dateFormat: 'mm/dd/yy' });
|
||||
|
||||
$("#TxThroughDate")
|
||||
.attr('autocomplete', 'off')
|
||||
.datepicker({ constrainInput: true,
|
||||
numberOfMonths: [1, 1],
|
||||
showCurrentAtPos: 0,
|
||||
dateFormat: 'mm/dd/yy' });
|
||||
|
||||
resetForm();
|
||||
});
|
||||
--></script>
|
||||
|
||||
<?php
|
||||
|
||||
/* End "detail supporting" div */
|
||||
echo '</div>' . "\n";
|
||||
|
||||
/* End page div */
|
||||
echo '</div>' . "\n";
|
||||
|
||||
?>
|
||||
113
views/accounts/view.ctp
Normal file
113
views/accounts/view.ctp
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php /* -*- mode:PHP -*- */
|
||||
|
||||
echo '<div class="account view">' . "\n";
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
* Account Detail Main Section
|
||||
*/
|
||||
|
||||
$ledger = $account['Ledger'];
|
||||
$current_ledger = $account['CurrentLedger'];
|
||||
|
||||
if (isset($account['Account']))
|
||||
$account = $account['Account'];
|
||||
|
||||
$rows = array();
|
||||
$rows[] = array('ID', $account['id']);
|
||||
$rows[] = array('Name', $account['name']);
|
||||
$rows[] = array('Type', $account['type']);
|
||||
$rows[] = array('External Name', $account['external_name']);
|
||||
$rows[] = array('External Account', $account['external_account']);
|
||||
$rows[] = array('Comment', $account['comment']);
|
||||
|
||||
echo $this->element('table',
|
||||
array('class' => 'item account detail',
|
||||
'caption' => 'Account Detail',
|
||||
'rows' => $rows,
|
||||
'column_class' => array('field', 'value')));
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Account Info Box
|
||||
*/
|
||||
|
||||
echo '<div class="infobox">' . "\n";
|
||||
$rows = array();
|
||||
$rows[] = array('Debits:', FormatHelper::currency($stats['debits']));
|
||||
$rows[] = array('Credits:', FormatHelper::currency($stats['credits']));
|
||||
$rows[] = array('Account Balance:', FormatHelper::currency($stats['balance']));
|
||||
echo $this->element('table',
|
||||
array('class' => 'summary',
|
||||
'rows' => $rows,
|
||||
'column_class' => array('field', 'value'),
|
||||
'suppress_alternate_rows' => true,
|
||||
));
|
||||
echo '</div>' . "\n";
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
* Supporting Elements Section
|
||||
*/
|
||||
|
||||
echo '<div CLASS="detail supporting">' . "\n";
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Ledgers
|
||||
*/
|
||||
|
||||
echo $this->element('ledgers', array
|
||||
(// Grid configuration
|
||||
'config' => array
|
||||
('caption' => $account['name'] . " Ledgers",
|
||||
'filter' => array('Account.id' => $account['id']),
|
||||
)));
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Current Ledger
|
||||
*/
|
||||
|
||||
echo $this->element('ledger_entries', array
|
||||
(// Grid configuration
|
||||
'config' => array
|
||||
('grid_div_id' => 'ledger-ledger-entry-list',
|
||||
'caption' => ("Current Ledger: " .
|
||||
"(". $current_ledger['name'] .")"),
|
||||
'filter' => array('Ledger.id' => $current_ledger['id']),
|
||||
'exclude' => array('Account', 'Amount', 'Cr/Dr', 'Balance',
|
||||
empty($account['receipts']) ? 'Tender' : null),
|
||||
'include' => array('Debit', 'Credit', 'Sub-Total'),
|
||||
)));
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Entire Account
|
||||
*/
|
||||
|
||||
echo $this->element('ledger_entries', array
|
||||
(// Grid configuration
|
||||
'config' => array
|
||||
('grid_div_id' => 'account-ledger-entry-list',
|
||||
'grid_setup' => array('hiddengrid' => true),
|
||||
'caption' => "Entire Ledger",
|
||||
'filter' => array('Account.id' => $account['id']),
|
||||
'exclude' => array('Account', 'Amount', 'Cr/Dr', 'Balance',
|
||||
empty($account['receipts']) ? 'Tender' : null),
|
||||
'include' => array('Debit', 'Credit', 'Sub-Total'),
|
||||
)));
|
||||
|
||||
|
||||
|
||||
/* End "detail supporting" div */
|
||||
echo '</div>' . "\n";
|
||||
|
||||
/* End page div */
|
||||
echo '</div>' . "\n";
|
||||
403
views/contacts/edit.ctp
Normal file
403
views/contacts/edit.ctp
Normal file
@@ -0,0 +1,403 @@
|
||||
<?php /* -*- mode:PHP -*- */
|
||||
|
||||
/**********************************************************************
|
||||
* Because we make use of functions here,
|
||||
* we need to put our top level variables somewhere
|
||||
* we can access them.
|
||||
*/
|
||||
$this->varstore = compact('methodTypes', 'methodPreferences',
|
||||
'contactPhones', 'phoneTypes',
|
||||
'contactAddresses',
|
||||
'contactEmails');
|
||||
|
||||
//pr($this->data);
|
||||
/**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
* Javascript
|
||||
*/
|
||||
|
||||
function contactMethodDiv($obj, $type, $legend, $values = null) {
|
||||
|
||||
$div =
|
||||
// BEGIN type-div
|
||||
'<DIV>' . "\n" .
|
||||
// BEGIN type-fieldset
|
||||
'<FIELDSET CLASS="'.$type.' subset">' . "\n" .
|
||||
'<LEGEND>'.$legend.' #%{id} (%{remove})</LEGEND>' . "\n" .
|
||||
|
||||
// BEGIN source-div
|
||||
'<DIV ID="'.$type.'-%{id}-source-div">' . "\n" .
|
||||
// BEGIN source-fieldset
|
||||
'<FIELDSET>' . "\n" .
|
||||
//'<LEGEND>Source</LEGEND>' . "\n" .
|
||||
''
|
||||
;
|
||||
|
||||
if (!isset($values)) {
|
||||
foreach (array('Existing', 'New') AS $sname) {
|
||||
$stype = strtolower($sname);
|
||||
$div .=
|
||||
'<INPUT TYPE="radio" ' . "\n" .
|
||||
' NAME="data[Contact'.ucfirst($type).'][%{id}][source]"' . "\n" .
|
||||
' ONCLICK="switchMethodSource(%{id}, '."'{$type}', '{$stype}'".')"' . "\n" .
|
||||
' CLASS="'.$type.'-method-%{id}-source" ' . "\n" .
|
||||
' ID="'.$type.'-method-%{id}-source-'.$stype.'"' . "\n" .
|
||||
' VALUE="'.$stype.'"' . "\n" .
|
||||
' />' . "\n" .
|
||||
' <LABEL FOR="'.$type.'-method-%{id}-source-'.$stype.'">'.$sname.'</LABEL>' . "\n" .
|
||||
' ';
|
||||
}
|
||||
}
|
||||
$div .= "\n";
|
||||
|
||||
if (isset($values)) {
|
||||
$div .= contactMethodTypeDiv($obj, $type, 'show', $values);
|
||||
}
|
||||
else {
|
||||
$div .= contactMethodTypeDiv($obj, $type, 'existing');
|
||||
$div .= contactMethodTypeDiv($obj, $type, 'new');
|
||||
}
|
||||
|
||||
$div .=
|
||||
// END source-fieldset
|
||||
'</FIELDSET>' . "\n" .
|
||||
// END source-div
|
||||
'</DIV>' . "\n" .
|
||||
|
||||
// BEGIN method-div
|
||||
'<div id="'.$type.'-%{id}-method-div"' . "\n" .
|
||||
|
||||
$obj->element
|
||||
('form_table',
|
||||
array('class' => "item contact-{$type} entry",
|
||||
'field_prefix' => 'Contact'.ucfirst($type).'.%{id}.ContactsMethod',
|
||||
'fields' => array
|
||||
(
|
||||
'preference' => array
|
||||
('opts' => array
|
||||
('options' => $obj->varstore['methodPreferences'],
|
||||
'selected' => (isset($values) ? $values['ContactsMethod']['preference'] : null),
|
||||
)),
|
||||
|
||||
'type' => array
|
||||
('opts' => array
|
||||
('options' => $obj->varstore['methodTypes'],
|
||||
'selected' => (isset($values) ? $values['ContactsMethod']['type'] : null),
|
||||
)),
|
||||
|
||||
'comment' => array
|
||||
('opts' => array
|
||||
('value' => (isset($values) ? $values['ContactsMethod']['comment'] : null),
|
||||
)),
|
||||
|
||||
))) . "\n" .
|
||||
|
||||
// END method-div
|
||||
'</div>' . "\n" .
|
||||
|
||||
// END type-fieldset
|
||||
'</FIELDSET>' . "\n" .
|
||||
// END type-div
|
||||
'</DIV>'
|
||||
;
|
||||
|
||||
return $div;
|
||||
}
|
||||
|
||||
function contactMethodTypeDiv($obj, $type, $stype, $values = null) {
|
||||
|
||||
$element = 'form_table';
|
||||
|
||||
if ($type === 'phone') {
|
||||
if ($stype === 'existing') {
|
||||
$fields = array
|
||||
('id' => array('name' => 'Phone/Ext',
|
||||
'opts' => array('options' => $obj->varstore['contactPhones'])),
|
||||
);
|
||||
}
|
||||
elseif ($stype === 'new') {
|
||||
$fields = array
|
||||
('type' => array('opts' => array('options' => $obj->varstore['phoneTypes'])),
|
||||
'phone' => true,
|
||||
'ext' => array('name' => "Extension"),
|
||||
'comment' => true,
|
||||
);
|
||||
}
|
||||
elseif ($stype === 'show') {
|
||||
$element = 'table';
|
||||
$column_class = array('field', 'value');
|
||||
$rows = array
|
||||
(array('Type', $values['type']),
|
||||
array('Phone', $values['phone']),
|
||||
array('Extension', $values['ext']),
|
||||
array('Comment', $values['comment']),
|
||||
);
|
||||
}
|
||||
else {
|
||||
die("\n\nInvalid stype ($stype)\n\n");
|
||||
}
|
||||
|
||||
}
|
||||
elseif ($type === 'address') {
|
||||
if ($stype === 'existing') {
|
||||
$fields = array
|
||||
('id' => array('name' => 'Address',
|
||||
'opts' => array('options' => $obj->varstore['contactAddresses'])),
|
||||
);
|
||||
}
|
||||
elseif ($stype === 'new') {
|
||||
$fields = array
|
||||
('address' => true,
|
||||
'city' => true,
|
||||
'state' => true,
|
||||
'postcode' => array('name' => 'Zip Code'),
|
||||
'country' => true,
|
||||
'comment' => true,
|
||||
);
|
||||
}
|
||||
elseif ($stype === 'show') {
|
||||
$element = 'table';
|
||||
$column_class = array('field', 'value');
|
||||
$rows = array
|
||||
(array('Address', preg_replace("/\n/", "<BR>", $values['address'])),
|
||||
array('City', $values['city']),
|
||||
array('State', $values['state']),
|
||||
array('Zip Code', $values['postcode']),
|
||||
array('Country', $values['country']),
|
||||
array('Comment', $values['comment']),
|
||||
);
|
||||
}
|
||||
else {
|
||||
die("\n\nInvalid stype ($stype)\n\n");
|
||||
}
|
||||
}
|
||||
elseif ($type === 'email') {
|
||||
if ($stype === 'existing') {
|
||||
$fields = array
|
||||
('id' => array('name' => 'Email',
|
||||
'opts' => array('options' => $obj->varstore['contactEmails'])),
|
||||
);
|
||||
}
|
||||
elseif ($stype === 'new') {
|
||||
$fields = array
|
||||
('email' => true,
|
||||
'comment' => true,
|
||||
);
|
||||
}
|
||||
elseif ($stype === 'show') {
|
||||
$element = 'table';
|
||||
$column_class = array('field', 'value');
|
||||
$rows = array
|
||||
(array('Email', $values['email']),
|
||||
array('Comment', $values['comment']),
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
die("\n\nInvalid type ($type)\n\n");
|
||||
}
|
||||
|
||||
return
|
||||
// BEGIN sourcetype-div
|
||||
'<div ' . "\n" .
|
||||
' class="'.$type.'-%{id}-div"' . "\n" .
|
||||
' id="'.$type.'-%{id}-'.$stype.'-div"' . "\n" .
|
||||
(isset($values) ? '' : ' STYLE="display:none;"' . "\n") .
|
||||
'>' . "\n" .
|
||||
|
||||
$obj->element
|
||||
($element,
|
||||
array('class' => "item contact-{$type} {$stype}",
|
||||
'field_prefix' => 'Contact'.ucfirst($type).'.%{id}')
|
||||
+ compact('rows', 'fields', 'column_class')) .
|
||||
|
||||
($stype === 'show'
|
||||
? '<input type="hidden" name="data[Contact'.ucfirst($type).'][%{id}][id]" value="'.$values['id'].'"/>' . "\n"
|
||||
: '') .
|
||||
|
||||
// END sourcetype-div
|
||||
'</div>' . "\n" .
|
||||
'';
|
||||
}
|
||||
|
||||
|
||||
//pr($this->data);
|
||||
?>
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
|
||||
function addPhone(flash) {
|
||||
addDiv('phone-entry-id', 'phone', 'phones', flash, <?php
|
||||
echo FormatHelper::phpVarToJavascript(contactMethodDiv($this,
|
||||
'phone',
|
||||
'Phone Number'),
|
||||
null,
|
||||
' ');
|
||||
?>
|
||||
);
|
||||
}
|
||||
|
||||
function addAddress(flash) {
|
||||
addDiv('address-entry-id', 'address', 'addresses', flash, <?php
|
||||
echo FormatHelper::phpVarToJavascript(contactMethodDiv($this,
|
||||
'address',
|
||||
'Address'),
|
||||
null,
|
||||
' ');
|
||||
?>
|
||||
);
|
||||
}
|
||||
|
||||
function addEmail(flash) {
|
||||
addDiv('email-entry-id', 'email', 'emails', flash, <?php
|
||||
echo FormatHelper::phpVarToJavascript(contactMethodDiv($this,
|
||||
'email',
|
||||
'Email Address'),
|
||||
null,
|
||||
' ');
|
||||
?>
|
||||
);
|
||||
}
|
||||
|
||||
// Reset the form
|
||||
function resetForm() {
|
||||
$('#phones').html('');
|
||||
$('#addresses').html('');
|
||||
$('#emails').html('');
|
||||
$('#phone-entry-id').val(1);
|
||||
$('#address-entry-id').val(1);
|
||||
$('#email-entry-id').val(1);
|
||||
|
||||
<?php foreach ($this->data['ContactPhone'] AS $phone): ?>
|
||||
addDiv('phone-entry-id', 'phone', 'phones', false, <?php
|
||||
echo FormatHelper::phpVarToJavascript(contactMethodDiv($this,
|
||||
'phone',
|
||||
'Phone Number',
|
||||
$phone
|
||||
),
|
||||
null,
|
||||
' ');
|
||||
?>
|
||||
);
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php foreach ($this->data['ContactAddress'] AS $address): ?>
|
||||
addDiv('address-entry-id', 'address', 'addresses', false, <?php
|
||||
echo FormatHelper::phpVarToJavascript(contactMethodDiv($this,
|
||||
'address',
|
||||
'Address',
|
||||
$address
|
||||
),
|
||||
null,
|
||||
' ');
|
||||
?>
|
||||
);
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php foreach ($this->data['ContactEmail'] AS $email): ?>
|
||||
addDiv('email-entry-id', 'email', 'emails', false, <?php
|
||||
echo FormatHelper::phpVarToJavascript(contactMethodDiv($this,
|
||||
'email',
|
||||
'Email Address',
|
||||
$email
|
||||
),
|
||||
null,
|
||||
' ');
|
||||
?>
|
||||
);
|
||||
<?php endforeach; ?>
|
||||
|
||||
}
|
||||
|
||||
function switchMethodSource(id, type, source) {
|
||||
$("."+type+"-"+id+"-div")
|
||||
.slideUp();
|
||||
|
||||
$("#"+type+"-"+id+"-"+source+"-div")
|
||||
.slideDown();
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
resetForm();
|
||||
});
|
||||
|
||||
--></script>
|
||||
|
||||
<?php
|
||||
; // alignment
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
* Contact Edit
|
||||
*/
|
||||
|
||||
echo '<div class="contact edit">' . "\n";
|
||||
|
||||
echo $form->create('Contact', array('action' => 'edit')) . "\n";
|
||||
echo $form->input('id') . "\n";
|
||||
|
||||
echo($this->element
|
||||
('form_table',
|
||||
array('class' => 'item contact detail',
|
||||
'caption' => isset($this->data['Contact']) ? 'Edit Contact' : 'New Contact',
|
||||
'fields' => array
|
||||
('first_name' => true,
|
||||
'last_name' => true,
|
||||
'middle_name' => true,
|
||||
'display_name' => true,
|
||||
'company_name' => array('name' => 'Company'),
|
||||
'id_federal' => array('name' => 'SSN'),
|
||||
'id_local' => array('name' => 'ID #'),
|
||||
'id_local_state' => array('name' => 'ID State'),
|
||||
/* 'id_local_exp' => array('name' => 'ID Expiration', */
|
||||
/* 'opts' => array('empty' => true)), */
|
||||
'comment' => true,
|
||||
))) . "\n");
|
||||
|
||||
echo $form->submit('Update') . "\n";
|
||||
?>
|
||||
|
||||
<div CLASS="dynamic-set">
|
||||
<fieldset CLASS="phone superset">
|
||||
<legend>Phone Numbers</legend>
|
||||
<input type="hidden" id="phone-entry-id" value="0">
|
||||
<div id="phones"></div>
|
||||
<fieldset> <legend>
|
||||
<a href="#" onClick="addPhone(true); return false;">Add a Phone Number</a>
|
||||
</legend> </fieldset>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div CLASS="dynamic-set">
|
||||
<fieldset CLASS="address superset">
|
||||
<legend>Mailing Addresses</legend>
|
||||
<input type="hidden" id="address-entry-id" value="0">
|
||||
<div id="addresses"></div>
|
||||
<fieldset> <legend>
|
||||
<a href="#" onClick="addAddress(true); return false;">Add a Mailing Address</a>
|
||||
</legend> </fieldset>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div CLASS="dynamic-set">
|
||||
<fieldset CLASS="email superset">
|
||||
<legend>Email Addresses</legend>
|
||||
<input type="hidden" id="email-entry-id" value="0">
|
||||
<div id="emails"></div>
|
||||
<fieldset> <legend>
|
||||
<a href="#" onClick="addEmail(true); return false;">Add an Email Address</a>
|
||||
</legend> </fieldset>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
; // Alignment
|
||||
|
||||
echo $form->submit('Update') . "\n";
|
||||
echo $form->submit('Cancel', array('name' => 'cancel')) . "\n";
|
||||
echo $form->end() . "\n";
|
||||
echo '</div>' . "\n";
|
||||
145
views/contacts/view.ctp
Normal file
145
views/contacts/view.ctp
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php /* -*- mode:PHP -*- */
|
||||
|
||||
echo '<div class="contact view">' . "\n";
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
* Contact Detail Main Section
|
||||
*/
|
||||
|
||||
$phones = $contact['ContactPhone'];
|
||||
$addresses = $contact['ContactAddress'];
|
||||
$emails = $contact['ContactEmail'];
|
||||
|
||||
if (isset($contact['Contact']))
|
||||
$contact = $contact['Contact'];
|
||||
|
||||
$rows = array();
|
||||
$rows[] = array('First Name', $contact['first_name']);
|
||||
$rows[] = array('Middle Name', $contact['middle_name']);
|
||||
$rows[] = array('Last Name', $contact['last_name']);
|
||||
$rows[] = array('Company', $contact['company_name']);
|
||||
$rows[] = array('SSN', $contact['id_federal']);
|
||||
$rows[] = array('ID', ($contact['id_local']
|
||||
. ($contact['id_local']
|
||||
? " - ".$contact['id_local_state']
|
||||
: "")));
|
||||
$rows[] = array('Comment', $contact['comment']);
|
||||
|
||||
echo $this->element('table',
|
||||
array('class' => 'item contact detail',
|
||||
'caption' => 'Contact Details',
|
||||
'rows' => $rows,
|
||||
'column_class' => array('field', 'value')));
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Contact Info Box
|
||||
*/
|
||||
|
||||
echo '<div class="infobox">' . "\n";
|
||||
$rows = array();
|
||||
echo $this->element('table',
|
||||
array('class' => 'summary',
|
||||
'rows' => $rows,
|
||||
'column_class' => array('field', 'value'),
|
||||
'suppress_alternate_rows' => true,
|
||||
));
|
||||
echo '</div>' . "\n";
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
* Supporting Elements Section
|
||||
*/
|
||||
|
||||
echo '<div CLASS="detail supporting">' . "\n";
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Phones
|
||||
*/
|
||||
$headers = array('Phone', 'Preference', 'Comment');
|
||||
$rows = array();
|
||||
foreach($phones AS $phone) {
|
||||
$rows[] = array(FormatHelper::phone($phone['phone']) .
|
||||
($phone['ext'] ? " x".$phone['ext'] : ""),
|
||||
$phone['ContactsMethod']['preference'] . " / " .
|
||||
$phone['ContactsMethod']['type'] . " / " .
|
||||
$phone['type'],
|
||||
$phone['comment']);
|
||||
}
|
||||
|
||||
echo $this->element('table',
|
||||
array('class' => 'item phone list',
|
||||
'caption' => 'Phone',
|
||||
'headers' => $headers,
|
||||
'rows' => $rows,
|
||||
'column_class' => $headers));
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Addresses
|
||||
*/
|
||||
$headers = array('Address', 'Preference', 'Comment');
|
||||
$rows = array();
|
||||
foreach($addresses AS $address) {
|
||||
$rows[] = array(preg_replace("/\n/", "<BR>\n", $address['address']) . "<BR>\n" .
|
||||
$address['city'] . ", " .
|
||||
$address['state'] . " " .
|
||||
$address['postcode'],
|
||||
//. ? "<BR>\n" . $address['country'],
|
||||
$address['ContactsMethod']['preference'] . " / " .
|
||||
$address['ContactsMethod']['type'],
|
||||
$address['comment']);
|
||||
}
|
||||
|
||||
echo $this->element('table',
|
||||
array('class' => 'item address list',
|
||||
'caption' => 'Address',
|
||||
'headers' => $headers,
|
||||
'rows' => $rows,
|
||||
'column_class' => $headers));
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Emails
|
||||
*/
|
||||
$headers = array('Email', 'Preference', 'Comment');
|
||||
$rows = array();
|
||||
foreach($emails AS $email) {
|
||||
$rows[] = array($email['email'],
|
||||
$email['ContactsMethod']['preference'] . " / " .
|
||||
$email['ContactsMethod']['type'],
|
||||
$email['comment']);
|
||||
}
|
||||
|
||||
echo $this->element('table',
|
||||
array('class' => 'item email list',
|
||||
'caption' => 'Email',
|
||||
'headers' => $headers,
|
||||
'rows' => $rows,
|
||||
'column_class' => $headers));
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Customers
|
||||
*/
|
||||
|
||||
echo $this->element('customers', array
|
||||
(// Grid configuration
|
||||
'config' => array
|
||||
('caption' => 'Related Customers',
|
||||
'filter' => array('Contact.id' => $contact['id']),
|
||||
)));
|
||||
|
||||
|
||||
/* End "detail supporting" div */
|
||||
echo '</div>' . "\n";
|
||||
|
||||
/* End page div */
|
||||
echo '</div>' . "\n";
|
||||
274
views/customers/edit.ctp
Normal file
274
views/customers/edit.ctp
Normal file
@@ -0,0 +1,274 @@
|
||||
<?php /* -*- mode:PHP -*- */
|
||||
|
||||
/**********************************************************************
|
||||
* Because we make use of functions here,
|
||||
* we need to put our top level variables somewhere
|
||||
* we can access them.
|
||||
*/
|
||||
$this->varstore = compact('contactTypes', 'contacts');
|
||||
|
||||
//pr($this->data);
|
||||
/**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
* Javascript
|
||||
*/
|
||||
|
||||
function customerContactDiv($obj, $values = null, $primary = false) {
|
||||
|
||||
$div =
|
||||
// BEGIN type-div
|
||||
'<DIV>' . "\n" .
|
||||
// BEGIN type-fieldset
|
||||
'<FIELDSET CLASS="contact subset">' . "\n" .
|
||||
'<LEGEND>Contact #%{id} (%{remove})</LEGEND>' . "\n" .
|
||||
|
||||
// BEGIN source-div
|
||||
'<DIV ID="contact-%{id}-source-div">' . "\n" .
|
||||
// BEGIN source-fieldset
|
||||
'<FIELDSET>' . "\n" .
|
||||
//'<LEGEND>Source</LEGEND>' . "\n" .
|
||||
''
|
||||
;
|
||||
|
||||
if (!isset($values)) {
|
||||
foreach (array('Existing', 'New') AS $sname) {
|
||||
$stype = strtolower($sname);
|
||||
$div .=
|
||||
'<INPUT TYPE="radio" ' . "\n" .
|
||||
' NAME="data[Contact][%{id}][source]"' . "\n" .
|
||||
' ONCLICK="switchContactSource(%{id}, '."'{$stype}'".')"' . "\n" .
|
||||
' CLASS="contact-%{id}-source" ' . "\n" .
|
||||
' ID="contact-%{id}-source-'.$stype.'"' . "\n" .
|
||||
' VALUE="'.$stype.'"' . "\n" .
|
||||
//' CHECKED' . "\n" .
|
||||
' />' . "\n" .
|
||||
' <LABEL FOR="contact-%{id}-source-'.$stype.'">'.$sname.'</LABEL>' . "\n" .
|
||||
' ';
|
||||
}
|
||||
}
|
||||
$div .= "\n";
|
||||
|
||||
if (isset($values)) {
|
||||
$div .= customerContactTypeDiv($obj, 'show', $values);
|
||||
}
|
||||
else {
|
||||
$div .= customerContactTypeDiv($obj, 'existing');
|
||||
$div .= customerContactTypeDiv($obj, 'new');
|
||||
}
|
||||
|
||||
$div .=
|
||||
// END source-fieldset
|
||||
'</FIELDSET>' . "\n" .
|
||||
// END source-div
|
||||
'</DIV>' . "\n" .
|
||||
|
||||
// BEGIN contact-div
|
||||
'<div id="contact-%{id}-contact-div"' . "\n" .
|
||||
|
||||
$obj->element
|
||||
('form_table',
|
||||
array('class' => "item contact entry",
|
||||
'field_prefix' => 'Contact.%{id}.ContactsCustomer',
|
||||
'fields' => array
|
||||
(
|
||||
'Customer.primary_contact_entry' => array
|
||||
('name' => 'Primary Contact',
|
||||
'no_prefix' => true,
|
||||
'opts' => array
|
||||
('type' => 'radio',
|
||||
'options' => array('%{id}' => false),
|
||||
'value' => ($primary ? '%{id}' : 'bogus-value-to-suppress-hidden-input'),
|
||||
)),
|
||||
|
||||
'type' => array
|
||||
('opts' => array
|
||||
('options' => $obj->varstore['contactTypes'],
|
||||
'selected' => (isset($values) ? $values['ContactsCustomer']['type'] : null),
|
||||
)),
|
||||
|
||||
'comment' => array
|
||||
('opts' => array
|
||||
('value' => (isset($values) ? $values['ContactsCustomer']['comment'] : null),
|
||||
)),
|
||||
|
||||
))) . "\n" .
|
||||
|
||||
// END contact-div
|
||||
'</div>' . "\n" .
|
||||
|
||||
// END type-fieldset
|
||||
'</FIELDSET>' . "\n" .
|
||||
// END type-div
|
||||
'</DIV>'
|
||||
;
|
||||
|
||||
return $div;
|
||||
}
|
||||
|
||||
function customerContactTypeDiv($obj, $stype, $values = null) {
|
||||
|
||||
$element = 'form_table';
|
||||
$class = $stype;
|
||||
|
||||
if ($stype === 'existing') {
|
||||
$fields = array
|
||||
('id' => array('name' => 'Contact',
|
||||
'opts' => array('options' => $obj->varstore['contacts'])),
|
||||
);
|
||||
}
|
||||
elseif ($stype === 'new') {
|
||||
$fields = array
|
||||
('first_name' => true,
|
||||
'last_name' => true,
|
||||
'middle_name' => true,
|
||||
'display_name' => true,
|
||||
'company_name' => array('name' => 'Company'),
|
||||
'id_federal' => array('name' => 'SSN'),
|
||||
'id_local' => array('name' => 'ID #'),
|
||||
'id_local_state' => array('name' => 'ID State'),
|
||||
/* 'id_local_exp' => array('name' => 'ID Expiration', */
|
||||
/* 'opts' => array('empty' => true)), */
|
||||
'comment' => true,
|
||||
);
|
||||
}
|
||||
elseif ($stype === 'show') {
|
||||
$element = 'table';
|
||||
$class = 'detail';
|
||||
$column_class = array('field', 'value');
|
||||
$rows = array(array('First Name', $values['first_name']),
|
||||
array('Last Name', $values['last_name']),
|
||||
array('Company', $values['company_name']),
|
||||
array('Comment', $values['comment']));
|
||||
}
|
||||
else {
|
||||
die("\n\nInvalid stype ($stype)\n\n");
|
||||
}
|
||||
|
||||
return
|
||||
// BEGIN sourcetype-div
|
||||
'<div ' . "\n" .
|
||||
' class="contact-%{id}-div"' . "\n" .
|
||||
' id="contact-%{id}-'.$stype.'-div"' . "\n" .
|
||||
(isset($values) ? '' : ' STYLE="display:none;"' . "\n") .
|
||||
'>' . "\n" .
|
||||
|
||||
$obj->element
|
||||
($element,
|
||||
array('class' => "item contact {$class}",
|
||||
'field_prefix' => 'Contact.%{id}')
|
||||
+ compact('rows', 'fields', 'column_class')) .
|
||||
|
||||
($stype === 'show'
|
||||
? '<input type="hidden" name="data[Contact][%{id}][id]" value="'.$values['id'].'"/>' . "\n"
|
||||
: '') .
|
||||
|
||||
// END sourcetype-div
|
||||
'</div>' . "\n" .
|
||||
'';
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
|
||||
function addContact(flash) {
|
||||
addDiv('contact-entry-id', 'contact', 'contacts', flash, <?php
|
||||
echo FormatHelper::phpVarToJavascript
|
||||
(customerContactDiv($this),
|
||||
null,
|
||||
' ');
|
||||
?>
|
||||
);
|
||||
}
|
||||
|
||||
// Reset the form
|
||||
function resetForm() {
|
||||
$('#contacts').html('');
|
||||
$('#contact-entry-id').val(1);
|
||||
|
||||
<?php foreach ($this->data['Contact'] AS $contact): ?>
|
||||
addDiv('contact-entry-id', 'contact', 'contacts', false, <?php
|
||||
echo FormatHelper::phpVarToJavascript
|
||||
(customerContactDiv($this,
|
||||
$contact,
|
||||
$contact['id'] == $this->data['Customer']['primary_contact_id']
|
||||
),
|
||||
null,
|
||||
' ');
|
||||
?>
|
||||
);
|
||||
<?php endforeach; ?>
|
||||
|
||||
if ($("#contact-entry-id").val() == 1) {
|
||||
addDiv('contact-entry-id', 'contact', 'contacts', false, <?php
|
||||
echo FormatHelper::phpVarToJavascript
|
||||
(customerContactDiv($this, null, true),
|
||||
null,
|
||||
' ');
|
||||
?>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function switchContactSource(id, source) {
|
||||
$(".contact-"+id+"-div")
|
||||
.slideUp();
|
||||
|
||||
$("#contact-"+id+"-"+source+"-div")
|
||||
.slideDown();
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
resetForm();
|
||||
});
|
||||
|
||||
--></script>
|
||||
|
||||
<?php
|
||||
; // alignment
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
* Customer Edit
|
||||
*/
|
||||
|
||||
echo '<div class="customer edit">' . "\n";
|
||||
|
||||
echo $form->create('Customer', array('action' => 'edit')) . "\n";
|
||||
echo $form->input('id') . "\n";
|
||||
|
||||
echo($this->element
|
||||
('form_table',
|
||||
array('class' => 'item customer detail',
|
||||
'caption' => isset($this->data['Customer']) ? 'Edit Customer' : 'New Customer',
|
||||
'fields' => array
|
||||
('name' => true,
|
||||
'comment' => true,
|
||||
))) . "\n");
|
||||
|
||||
echo $form->submit(isset($this->data['Customer']) ? 'Update' : 'Add New Customer') . "\n";
|
||||
?>
|
||||
|
||||
<div CLASS="dynamic-set">
|
||||
<fieldset CLASS="contact superset">
|
||||
<legend>Contacts</legend>
|
||||
<input type="hidden" id="contact-entry-id" value="0">
|
||||
<div id="contacts"></div>
|
||||
<fieldset> <legend>
|
||||
<a href="#" onClick="addContact(true); return false;">Add a Contact</a>
|
||||
</legend> </fieldset>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
; // Alignment
|
||||
|
||||
echo $form->submit(isset($this->data['Customer']) ? 'Update' : 'Add New Customer') . "\n";
|
||||
echo $form->submit('Cancel', array('name' => 'cancel')) . "\n";
|
||||
echo $form->end() . "\n";
|
||||
echo '</div>' . "\n";
|
||||
421
views/customers/receipt.ctp
Normal file
421
views/customers/receipt.ctp
Normal file
@@ -0,0 +1,421 @@
|
||||
<?php /* -*- mode:PHP -*- */ ?>
|
||||
|
||||
<div class="receipt input">
|
||||
<?php
|
||||
; // Editor alignment
|
||||
|
||||
/**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
* Javascript
|
||||
*/
|
||||
|
||||
// Warnings _really_ screw up javascript
|
||||
$saved_debug_state = Configure::read('debug');
|
||||
Configure::write('debug', '0');
|
||||
?>
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
|
||||
// prepare the form when the DOM is ready
|
||||
$(document).ready(function() {
|
||||
var options = {
|
||||
target: '#output-debug', // target element(s) to be updated with server response
|
||||
beforeSubmit: verifyRequest, // pre-submit callback
|
||||
success: showResponse, // post-submit callback
|
||||
|
||||
// other available options:
|
||||
//clearForm: true, // clear all form fields after successful submit
|
||||
//resetForm: true, // reset the form after successful submit
|
||||
};
|
||||
|
||||
// bind form using 'ajaxForm'
|
||||
$('#receipt-form').ajaxForm(options);
|
||||
});
|
||||
|
||||
// pre-submit callback
|
||||
function verifyRequest(formData, jqForm, options) {
|
||||
$('#results').html('Working <BLINK>...</BLINK>');
|
||||
// here we could return false to prevent the form from being submitted;
|
||||
// returning anything other than false will allow the form submit to continue
|
||||
return true;
|
||||
}
|
||||
|
||||
// post-submit callback
|
||||
function showResponse(responseText, statusText) {
|
||||
if (statusText == 'success') {
|
||||
var amount = 0;
|
||||
$("input.payment.amount").each(function(i) {
|
||||
amount += $(this).val();
|
||||
});
|
||||
|
||||
$('#results').html('<H3>Receipt Saved<BR>' +
|
||||
$("#receipt-customer-name").html() +
|
||||
' : ' + fmtCurrency(amount) +
|
||||
'</H3>');
|
||||
|
||||
if (!$("#repeat").attr("checked")) {
|
||||
window.location.href =
|
||||
"<?php echo $html->url(array('controller' => 'customers',
|
||||
'action' => 'view')); ?>"
|
||||
+ "/" + $("#customer-id").val();
|
||||
return;
|
||||
}
|
||||
|
||||
// get a clean slate
|
||||
resetForm();
|
||||
}
|
||||
else {
|
||||
$('#results').html('<H2>Failed to save receipt!</H2>');
|
||||
alert('Failed to save receipt.');
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the form
|
||||
function resetForm() {
|
||||
$('#payment-entry-id').val(1);
|
||||
$('#payments').html('');
|
||||
|
||||
addPaymentSource(false);
|
||||
updateCharges($("#customer-id").val());
|
||||
}
|
||||
|
||||
function updateCharges(id) {
|
||||
$('#charge-entries-jqGrid').clearGridData();
|
||||
$("#receipt-balance").html("Calculating...");
|
||||
$("#receipt-charges-caption").html("Please Wait...");
|
||||
|
||||
var custom = new Array();
|
||||
custom['customer_id'] = id;
|
||||
|
||||
var dynamic_post = new Array();
|
||||
dynamic_post['custom'] = custom;
|
||||
|
||||
$('#charge-entries-jqGrid').setPostDataItem('dynamic_post_replace', serialize(dynamic_post));
|
||||
$('#charge-entries-jqGrid')
|
||||
.setGridParam({ page: 1 })
|
||||
.trigger("reloadGrid");
|
||||
|
||||
var gridstate = $('#charge-entries-jqGrid').getGridParam('gridstate');
|
||||
if (gridstate == 'hidden')
|
||||
$('#charge-entries .HeaderButton').click();
|
||||
}
|
||||
|
||||
function onGridLoadComplete() {
|
||||
var userdata = $('#charge-entries-jqGrid').getGridParam('userData');
|
||||
$('#receipt-balance').html(fmtCurrency(userdata['balance']));
|
||||
$("#receipt-charges-caption").html("Outstanding Charges");
|
||||
}
|
||||
|
||||
function onRowSelect(grid_id, customer_id) {
|
||||
// Set the customer id that will be returned with the form
|
||||
$("#customer-id").val(customer_id);
|
||||
|
||||
// Get the item names from the grid
|
||||
//$("#receipt-customer-id").html($(grid_id).getCell(customer_id, 'Customer-id'));
|
||||
// REVISIT <AP>: 20090708
|
||||
// This is not intended as a long term solution,
|
||||
// but I need a way to enter data and then view
|
||||
// the results. This link will help.
|
||||
$("#receipt-customer-id").html('<A HREF="' +
|
||||
"<?php echo $html->url(array('controller' => 'customers',
|
||||
'action' => 'view')); ?>"
|
||||
+ "/" +
|
||||
$(grid_id).getCell(customer_id, 'Customer-id').replace(/^#/,'') +
|
||||
'">' +
|
||||
$(grid_id).getCell(customer_id, 'Customer-id') +
|
||||
'</A>');
|
||||
$("#receipt-customer-name").html($(grid_id).getCell(customer_id, 'Customer-name'));
|
||||
|
||||
// Hide the "no customer" message and show the current customer
|
||||
$(".customer-selection-invalid").hide();
|
||||
$(".customer-selection-valid").show();
|
||||
|
||||
// Update the charges grid to reflect this customer
|
||||
updateCharges(customer_id);
|
||||
|
||||
// Collapse the grid now that the user has selected
|
||||
$("#customers-list .HeaderButton").click();
|
||||
}
|
||||
|
||||
function onGridState(grid_id, state) {
|
||||
if (state == 'visible') {
|
||||
$(".customer-selection-invalid").hide();
|
||||
$(".customer-selection-valid").hide();
|
||||
}
|
||||
else {
|
||||
if ($("#customer-id").val() > 0) {
|
||||
$(".customer-selection-valid").show();
|
||||
$(".customer-selection-invalid").hide();
|
||||
} else {
|
||||
$(".customer-selection-valid").hide();
|
||||
$(".customer-selection-invalid").show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addPaymentSource(flash) {
|
||||
addDiv('payment-entry-id', 'payment', 'payments', flash,
|
||||
// HTML section
|
||||
'<FIELDSET CLASS="payment subset">' +
|
||||
<?php /* '<LEGEND>Payment #%{id} (%{remove})</LEGEND>' + */ ?>
|
||||
'<LEGEND>Payment</LEGEND>' +
|
||||
|
||||
'<DIV ID="payment-div-%{id}">' +
|
||||
<?php
|
||||
// Rearrange to be of the form (id => name)
|
||||
$radioOptions = array();
|
||||
foreach ($paymentTypes AS $type)
|
||||
$radioOptions[$type['TenderType']['id']] = $type['TenderType']['name'];
|
||||
|
||||
echo FormatHelper::phpVarToJavascript
|
||||
($form->input('Entry.%{id}.tender_type_id',
|
||||
array('type' => 'radio',
|
||||
'separator' => '<BR>',
|
||||
'onclick' => ('switchPaymentType(' .
|
||||
'\\\'payment-type-div\\\', ' .
|
||||
'%{id}, ' .
|
||||
'$(this).attr("id")' .
|
||||
')' .
|
||||
//' return false;'
|
||||
''
|
||||
),
|
||||
'legend' => false,
|
||||
'value' => $defaultType,
|
||||
'options' => $radioOptions))) . "+\n";
|
||||
?>
|
||||
'</DIV>' +
|
||||
|
||||
'<DIV ID="payment-amount-div-%{id}" CLASS="input text required">' +
|
||||
' <INPUT TYPE="text" SIZE="20"' +
|
||||
' NAME="data[Entry][%{id}][amount]"' +
|
||||
' CLASS="payment amount"' +
|
||||
' ID="payment-amount-%{id}" />' +
|
||||
' <LABEL CLASS="payment" FOR="payment-amount-%{id}">Amount</LABEL>' +
|
||||
'</DIV>' +
|
||||
|
||||
<?php
|
||||
foreach ($paymentTypes AS $type) {
|
||||
$type = $type['TenderType'];
|
||||
$div = '<DIV';
|
||||
$div .= ' ID="payment-type-div-%{id}-'.$type['id'].'"';
|
||||
$div .= ' CLASS="payment-type-div-%{id}"';
|
||||
if ($type['id'] != $defaultType)
|
||||
$div .= ' STYLE="display:none;"';
|
||||
$div .= '>';
|
||||
|
||||
$div .= ' <INPUT TYPE="hidden"';
|
||||
$div .= ' NAME="data[Entry][%{id}][type]['.$type['id'].'][tender_type_id]"';
|
||||
$div .= ' VALUE="'.$type['id'].'"';
|
||||
$div .= '>';
|
||||
|
||||
for ($i=1; $i<=4; ++$i) {
|
||||
if (!empty($type["data{$i}_name"])) {
|
||||
$div .= '<DIV CLASS="input text required">';
|
||||
$div .= ' <INPUT TYPE="text" SIZE="20"';
|
||||
$div .= ' NAME="data[Entry][%{id}][type]['.$type['id'].'][data'.$i.']"';
|
||||
$div .= ' CLASS="payment"';
|
||||
$div .= ' ID="payment-data'.$i.'-%{id}" />';
|
||||
$div .= ' <LABEL';
|
||||
$div .= ' CLASS="payment"';
|
||||
$div .= ' FOR="payment-data'.$i.'-%{id}">';
|
||||
$div .= $type["data{$i}_name"];
|
||||
$div .= ' </LABEL>';
|
||||
$div .= '</DIV>';
|
||||
}
|
||||
}
|
||||
|
||||
$div .= '</DIV>';
|
||||
echo "'$div' +\n";
|
||||
}
|
||||
?>
|
||||
|
||||
'</FIELDSET>'
|
||||
);
|
||||
}
|
||||
|
||||
function switchPaymentType(paymentid_base, paymentid, radioid) {
|
||||
var type_id = $("#"+radioid).val();
|
||||
$("."+paymentid_base+"-"+paymentid+
|
||||
":not(" +
|
||||
"#"+paymentid_base+"-"+paymentid+"-"+type_id +
|
||||
")").slideUp();
|
||||
$("#"+paymentid_base+"-"+paymentid+"-"+type_id).slideDown();
|
||||
}
|
||||
|
||||
--></script>
|
||||
|
||||
<?php
|
||||
; // align
|
||||
// Re-Enable warnings
|
||||
Configure::write('debug', $saved_debug_state);
|
||||
|
||||
echo $this->element('customers', array
|
||||
('config' => array
|
||||
('grid_div_id' => 'customers-list',
|
||||
'grid_div_class' => 'text-below',
|
||||
'caption' => ('<A HREF="#" ONCLICK="$(\'#customers-list .HeaderButton\').click();'.
|
||||
' return false;">Select Customer</A>'),
|
||||
'grid_setup' => array('hiddengrid' => isset($customer['id'])),
|
||||
'grid_events' => array('onSelectRow' =>
|
||||
array('ids' =>
|
||||
'if (ids != null){onRowSelect("#"+$(this).attr("id"), ids);}'),
|
||||
'onHeaderClick' =>
|
||||
array('gridstate' =>
|
||||
'onGridState("#"+$(this).attr("id"), gridstate)'),
|
||||
),
|
||||
'action' => 'current',
|
||||
'nolinks' => true,
|
||||
'limit' => 10,
|
||||
)));
|
||||
|
||||
echo ('<DIV CLASS="receipt grid-selection-text">' .
|
||||
|
||||
'<DIV CLASS="customer-selection-valid" style="display:none">' .
|
||||
'Customer <SPAN id="receipt-customer-id"></SPAN>' .
|
||||
': <SPAN id="receipt-customer-name"></SPAN>' .
|
||||
|
||||
/* '<DIV CLASS="supporting">' . */
|
||||
/* '<TABLE>' . */
|
||||
/* '<TR><TD CLASS="field">Balance:</TD><TD CLASS="value"><SPAN id="receipt-balance"></SPAN></TD></TR>' . */
|
||||
/* '</TABLE>' . */
|
||||
/* '</DIV>' . */
|
||||
|
||||
'</DIV>' . // END customer-selection-valid
|
||||
|
||||
'<DIV CLASS="customer-selection-invalid" style="display:none">' .
|
||||
'Please select customer' .
|
||||
'</DIV>' .
|
||||
|
||||
'</DIV>' . "\n");
|
||||
|
||||
|
||||
echo $this->element('statement_entries', array
|
||||
(// Grid configuration
|
||||
'config' => array
|
||||
(
|
||||
'grid_div_id' => 'charge-entries',
|
||||
'grid_div_class' => 'text-below',
|
||||
'grid_events' => array('loadComplete' => 'onGridLoadComplete()'),
|
||||
'grid_setup' => array('hiddengrid' => true),
|
||||
'caption' => '<SPAN id="receipt-charges-caption"></SPAN>',
|
||||
'action' => 'unreconciled',
|
||||
'exclude' => array('Customer', 'Type', 'Debit', 'Credit'),
|
||||
'include' => array('Applied', 'Balance'),
|
||||
'remap' => array('Applied' => 'Paid'),
|
||||
'limit' => 8,
|
||||
),
|
||||
));
|
||||
|
||||
echo('<DIV CLASS="receipt grid-selection-text">' .
|
||||
'<DIV CLASS="customer-selection-valid" style="display:none">' .
|
||||
|
||||
//'<DIV CLASS="supporting">' .
|
||||
'<TABLE ID="supporting-table">' .
|
||||
'<TR><TD CLASS="field">Balance:</TD><TD CLASS="value"><SPAN id="receipt-balance"></SPAN></TD></TR>' .
|
||||
'</TABLE>' .
|
||||
//'</DIV>' .
|
||||
|
||||
'</DIV>' . // END customer-selection-valid
|
||||
'</DIV>' .
|
||||
"\n");
|
||||
|
||||
echo $form->create(null, array('id' => 'receipt-form',
|
||||
'url' => array('controller' => 'transactions',
|
||||
'action' => 'postReceipt')));
|
||||
|
||||
|
||||
echo $form->input("id",
|
||||
array('id' => 'customer-id',
|
||||
'type' => 'hidden',
|
||||
'value' => 0));
|
||||
|
||||
echo $this->element('form_table',
|
||||
array('class' => "item receipt transaction entry",
|
||||
//'with_name_after' => ':',
|
||||
'field_prefix' => 'Transaction',
|
||||
'fields' => array
|
||||
("stamp" => array('opts' => array('type' => 'text'),
|
||||
'between' => '<A HREF="#" ONCLICK="datepickerNow(\'TransactionStamp\'); return false;">Now</A>',
|
||||
),
|
||||
"comment" => array('opts' => array('size' => 50),
|
||||
),
|
||||
)));
|
||||
|
||||
echo "<BR>\n";
|
||||
echo $form->input('repeat', array('type' => 'checkbox',
|
||||
'id' => 'repeat',
|
||||
'label' => 'Enter Multiple Receipts')) . "\n";
|
||||
echo $form->submit('Generate Receipt') . "\n";
|
||||
?>
|
||||
|
||||
<?php /*
|
||||
<fieldset CLASS="payment superset">
|
||||
<legend>Payments</legend>
|
||||
*/ ?>
|
||||
<input type="hidden" id="payment-entry-id" value="0">
|
||||
<div id="payments"></div>
|
||||
<?php /*
|
||||
<fieldset> <legend>
|
||||
<a href="#" onClick="addPaymentSource(true); return false;">Add Another Payment</a>
|
||||
</legend> </fieldset>
|
||||
</fieldset>
|
||||
*/ ?>
|
||||
|
||||
<?php echo $form->end('Generate Receipt'); ?>
|
||||
|
||||
<?php /* echo '</DIV>' . "\n"; // End of the dialog DIV */ ?>
|
||||
|
||||
<div id="results"></div>
|
||||
<div id="output-debug" style="display:none"></div>
|
||||
|
||||
<?php
|
||||
// Warnings _really_ screw up javascript
|
||||
Configure::write('debug', '0');
|
||||
?>
|
||||
|
||||
<script type="text/javascript"><!--
|
||||
$(document).ready(function(){
|
||||
$("#TransactionStamp")
|
||||
.attr('autocomplete', 'off')
|
||||
.datepicker({ constrainInput: true,
|
||||
numberOfMonths: [1, 1],
|
||||
showCurrentAtPos: 0,
|
||||
dateFormat: 'mm/dd/yy' });
|
||||
|
||||
$("#receipt-customer-id").html("INTERNAL ERROR");
|
||||
$("#receipt-customer-name").html("INTERNAL ERROR");
|
||||
$("#receipt-balance").html("INTERNAL ERROR");
|
||||
$("#receipt-charges-caption").html("Outstanding Charges");
|
||||
|
||||
<?php if (isset($customer['id'])): ?>
|
||||
$("#customer-id").val(<?php echo $customer['id']; ?>);
|
||||
//$("#receipt-customer-id").html("<?php echo '#'.$customer['id']; ?>");
|
||||
$("#receipt-customer-id").html('<A HREF="' +
|
||||
"<?php echo $html->url(array('controller' => 'customers',
|
||||
'action' => 'view')); ?>"
|
||||
+ "/" +
|
||||
"<?php echo $customer['id']; ?>" +
|
||||
'">#' +
|
||||
"<?php echo $customer['id']; ?>" +
|
||||
'</A>');
|
||||
$("#receipt-customer-name").html("<?php echo $customer['name']; ?>");
|
||||
$("#receipt-balance").html(fmtCurrency("<?php echo $stats['balance']; ?>"));
|
||||
onGridState(null, 'hidden');
|
||||
<?php else: ?>
|
||||
onGridState(null, 'visible');
|
||||
<?php endif; ?>
|
||||
|
||||
resetForm();
|
||||
datepickerNow('TransactionStamp');
|
||||
|
||||
<?php if ($this->params['dev']): ?>
|
||||
$('#output-debug').html('Post Output');
|
||||
$('#output-debug').show();
|
||||
<?php endif; ?>
|
||||
|
||||
});
|
||||
--></script>
|
||||
|
||||
</div>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user