From c9f9d0867bdf1a7063c42e42d79dcc164e1676b0 Mon Sep 17 00:00:00 2001 From: Abijah Date: Wed, 27 May 2009 04:17:45 +0000 Subject: [PATCH 001/717] Added branch point for initial work. The site directory will be added using the svn_import script, and will represent the output of the command 'cake bake pmgr' git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@2 97e9348a-65ac-dc4b-aefc-98561f571b83 From 3251ba340df17c8d700840e518935fd929c919e3 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 27 May 2009 04:18:18 +0000 Subject: [PATCH 002/717] Create directories to load project into. * branches/initial_20090526/site: New directory. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@3 97e9348a-65ac-dc4b-aefc-98561f571b83 From 4502b73b2ed6c9c8729f293176866874266da9b0 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 27 May 2009 04:18:23 +0000 Subject: [PATCH 003/717] Load pmgr into branches/initial_20090526/site. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@4 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/.htaccess | 5 + site/app_controller.php | 39 ++ site/app_helper.php | 41 ++ site/app_model.php | 41 ++ site/config/acl.ini.php | 74 +++ site/config/bootstrap.php | 44 ++ site/config/core.php | 227 +++++++++ site/config/database.php | 14 + site/config/database.php.default | 101 ++++ site/config/inflections.php | 70 +++ site/config/routes.php | 39 ++ site/config/sql/db_acl.php | 79 +++ site/config/sql/db_acl.sql | 40 ++ site/config/sql/i18n.php | 56 ++ site/config/sql/i18n.sql | 26 + site/config/sql/sessions.php | 53 ++ site/config/sql/sessions.sql | 16 + site/controllers/pages_controller.php | 86 ++++ site/index.php | 24 + .../cache/models/cake_model_default_pmgr_list | 2 + .../tmp/cache/persistent/cake_core_core_paths | 2 + .../cache/persistent/cake_core_default_en_us | 2 + site/tmp/cache/persistent/cake_core_dir_map | 2 + site/tmp/cache/persistent/cake_core_file_map | 2 + site/views/elements/email/html/default.ctp | 31 ++ site/views/elements/email/text/default.ctp | 25 + site/views/layouts/ajax.ctp | 25 + site/views/layouts/default.ctp | 64 +++ site/views/layouts/email/html/default.ctp | 37 ++ site/views/layouts/email/text/default.ctp | 29 ++ site/views/layouts/flash.ctp | 44 ++ site/views/layouts/js/default.ctp | 2 + site/views/layouts/rss/default.ctp | 17 + site/views/layouts/xml/default.ctp | 2 + site/views/pages/home.ctp | 80 +++ site/webroot/.htaccess | 6 + site/webroot/css.php | 102 ++++ site/webroot/css/cake.generic.css | 480 ++++++++++++++++++ site/webroot/favicon.ico | Bin 0 -> 372 bytes site/webroot/img/cake.icon.gif | Bin 0 -> 233 bytes site/webroot/img/cake.power.gif | Bin 0 -> 201 bytes site/webroot/index.php | 93 ++++ site/webroot/js/vendors.php | 42 ++ site/webroot/test.php | 181 +++++++ 44 files changed, 2345 insertions(+) create mode 100644 site/.htaccess create mode 100644 site/app_controller.php create mode 100644 site/app_helper.php create mode 100644 site/app_model.php create mode 100644 site/config/acl.ini.php create mode 100644 site/config/bootstrap.php create mode 100644 site/config/core.php create mode 100644 site/config/database.php create mode 100644 site/config/database.php.default create mode 100644 site/config/inflections.php create mode 100644 site/config/routes.php create mode 100644 site/config/sql/db_acl.php create mode 100644 site/config/sql/db_acl.sql create mode 100644 site/config/sql/i18n.php create mode 100644 site/config/sql/i18n.sql create mode 100644 site/config/sql/sessions.php create mode 100644 site/config/sql/sessions.sql create mode 100644 site/controllers/pages_controller.php create mode 100644 site/index.php create mode 100644 site/tmp/cache/models/cake_model_default_pmgr_list create mode 100644 site/tmp/cache/persistent/cake_core_core_paths create mode 100644 site/tmp/cache/persistent/cake_core_default_en_us create mode 100644 site/tmp/cache/persistent/cake_core_dir_map create mode 100644 site/tmp/cache/persistent/cake_core_file_map create mode 100644 site/views/elements/email/html/default.ctp create mode 100644 site/views/elements/email/text/default.ctp create mode 100644 site/views/layouts/ajax.ctp create mode 100644 site/views/layouts/default.ctp create mode 100644 site/views/layouts/email/html/default.ctp create mode 100644 site/views/layouts/email/text/default.ctp create mode 100644 site/views/layouts/flash.ctp create mode 100644 site/views/layouts/js/default.ctp create mode 100644 site/views/layouts/rss/default.ctp create mode 100644 site/views/layouts/xml/default.ctp create mode 100644 site/views/pages/home.ctp create mode 100644 site/webroot/.htaccess create mode 100644 site/webroot/css.php create mode 100644 site/webroot/css/cake.generic.css create mode 100644 site/webroot/favicon.ico create mode 100644 site/webroot/img/cake.icon.gif create mode 100644 site/webroot/img/cake.power.gif create mode 100644 site/webroot/index.php create mode 100644 site/webroot/js/vendors.php create mode 100644 site/webroot/test.php diff --git a/site/.htaccess b/site/.htaccess new file mode 100644 index 0000000..0ed8662 --- /dev/null +++ b/site/.htaccess @@ -0,0 +1,5 @@ + + RewriteEngine on + RewriteRule ^$ webroot/ [L] + RewriteRule (.*) webroot/$1 [L] + \ No newline at end of file diff --git a/site/app_controller.php b/site/app_controller.php new file mode 100644 index 0000000..87357ed --- /dev/null +++ b/site/app_controller.php @@ -0,0 +1,39 @@ + \ No newline at end of file diff --git a/site/app_helper.php b/site/app_helper.php new file mode 100644 index 0000000..eb23db7 --- /dev/null +++ b/site/app_helper.php @@ -0,0 +1,41 @@ + \ No newline at end of file diff --git a/site/app_model.php b/site/app_model.php new file mode 100644 index 0000000..7d083b0 --- /dev/null +++ b/site/app_model.php @@ -0,0 +1,41 @@ + \ No newline at end of file diff --git a/site/config/acl.ini.php b/site/config/acl.ini.php new file mode 100644 index 0000000..94a9a9a --- /dev/null +++ b/site/config/acl.ini.php @@ -0,0 +1,74 @@ +; +; 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 \ No newline at end of file diff --git a/site/config/bootstrap.php b/site/config/bootstrap.php new file mode 100644 index 0000000..2c89c74 --- /dev/null +++ b/site/config/bootstrap.php @@ -0,0 +1,44 @@ + \ No newline at end of file diff --git a/site/config/core.php b/site/config/core.php new file mode 100644 index 0000000..3add95a --- /dev/null +++ b/site/config/core.php @@ -0,0 +1,227 @@ + 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/.php. + * Set the value of 'Session.save' to 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')); +?> \ No newline at end of file diff --git a/site/config/database.php b/site/config/database.php new file mode 100644 index 0000000..c875711 --- /dev/null +++ b/site/config/database.php @@ -0,0 +1,14 @@ + 'mysql', + 'persistent' => false, + 'host' => 'localhost', + 'login' => 'pmgr', + 'password' => 'pmgruser', + 'database' => 'pmgr', + 'prefix' => 'pmgr_', + ); +} +?> \ No newline at end of file diff --git a/site/config/database.php.default b/site/config/database.php.default new file mode 100644 index 0000000..c20fd5d --- /dev/null +++ b/site/config/database.php.default @@ -0,0 +1,101 @@ + 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' => '', + ); +} +?> \ No newline at end of file diff --git a/site/config/inflections.php b/site/config/inflections.php new file mode 100644 index 0000000..429c085 --- /dev/null +++ b/site/config/inflections.php @@ -0,0 +1,70 @@ + 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(); +/** + * 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); +?> \ No newline at end of file diff --git a/site/config/routes.php b/site/config/routes.php new file mode 100644 index 0000000..44e4c40 --- /dev/null +++ b/site/config/routes.php @@ -0,0 +1,39 @@ + 'pages', 'action' => 'display', 'home')); +/** + * ...and connect the rest of 'Pages' controller's urls. + */ + Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display')); +?> \ No newline at end of file diff --git a/site/config/sql/db_acl.php b/site/config/sql/db_acl.php new file mode 100644 index 0000000..5f24eab --- /dev/null +++ b/site/config/sql/db_acl.php @@ -0,0 +1,79 @@ + 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)) + ); + +} +?> \ No newline at end of file diff --git a/site/config/sql/db_acl.sql b/site/config/sql/db_acl.sql new file mode 100644 index 0000000..6d507fe --- /dev/null +++ b/site/config/sql/db_acl.sql @@ -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) +); \ No newline at end of file diff --git a/site/config/sql/i18n.php b/site/config/sql/i18n.php new file mode 100644 index 0000000..72233ff --- /dev/null +++ b/site/config/sql/i18n.php @@ -0,0 +1,56 @@ + 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)) + ); + +} +?> \ No newline at end of file diff --git a/site/config/sql/i18n.sql b/site/config/sql/i18n.sql new file mode 100644 index 0000000..484d8a2 --- /dev/null +++ b/site/config/sql/i18n.sql @@ -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) +); \ No newline at end of file diff --git a/site/config/sql/sessions.php b/site/config/sql/sessions.php new file mode 100644 index 0000000..7f00a26 --- /dev/null +++ b/site/config/sql/sessions.php @@ -0,0 +1,53 @@ + 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)) + ); + +} +?> \ No newline at end of file diff --git a/site/config/sql/sessions.sql b/site/config/sql/sessions.sql new file mode 100644 index 0000000..23a1925 --- /dev/null +++ b/site/config/sql/sessions.sql @@ -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) +); \ No newline at end of file diff --git a/site/controllers/pages_controller.php b/site/controllers/pages_controller.php new file mode 100644 index 0000000..0e17106 --- /dev/null +++ b/site/controllers/pages_controller.php @@ -0,0 +1,86 @@ +redirect('/'); + } + $page = $subpage = $title = null; + + if (!empty($path[0])) { + $page = $path[0]; + } + if (!empty($path[1])) { + $subpage = $path[1]; + } + if (!empty($path[$count - 1])) { + $title = Inflector::humanize($path[$count - 1]); + } + $this->set(compact('page', 'subpage', 'title')); + $this->render(join('/', $path)); + } +} + +?> \ No newline at end of file diff --git a/site/index.php b/site/index.php new file mode 100644 index 0000000..4e60b84 --- /dev/null +++ b/site/index.php @@ -0,0 +1,24 @@ + \ No newline at end of file diff --git a/site/tmp/cache/models/cake_model_default_pmgr_list b/site/tmp/cache/models/cake_model_default_pmgr_list new file mode 100644 index 0000000..fbaa15f --- /dev/null +++ b/site/tmp/cache/models/cake_model_default_pmgr_list @@ -0,0 +1,2 @@ +1243395559 +a:36:{i:0;s:12:"pmgr_actions";i:1;s:27:"pmgr_actions_late_schedules";i:2;s:17:"pmgr_charge_types";i:3;s:19:"pmgr_config_options";i:4;s:18:"pmgr_config_system";i:5;s:20:"pmgr_config_versions";i:6;s:22:"pmgr_contact_addresses";i:7;s:19:"pmgr_contact_emails";i:8;s:20:"pmgr_contact_methods";i:9;s:19:"pmgr_contact_phones";i:10;s:13:"pmgr_contacts";i:11;s:18:"pmgr_group_options";i:12;s:22:"pmgr_group_permissions";i:13;s:11:"pmgr_groups";i:14;s:19:"pmgr_late_schedules";i:15;s:19:"pmgr_lease_contacts";i:16;s:16:"pmgr_lease_types";i:17;s:11:"pmgr_leases";i:18;s:14:"pmgr_map_units";i:19;s:9:"pmgr_maps";i:20;s:10:"pmgr_notes";i:21;s:18:"pmgr_payment_types";i:22;s:15:"pmgr_site_areas";i:23;s:21:"pmgr_site_memberships";i:24;s:17:"pmgr_site_options";i:25;s:10:"pmgr_sites";i:26;s:24:"pmgr_transaction_charges";i:27;s:25:"pmgr_transaction_payments";i:28;s:25:"pmgr_transaction_receipts";i:29;s:32:"pmgr_transaction_reconciliations";i:30;s:15:"pmgr_unit_sizes";i:31;s:15:"pmgr_unit_types";i:32;s:10:"pmgr_units";i:33;s:17:"pmgr_user_options";i:34;s:10:"pmgr_users";i:35;s:5:"posts";} diff --git a/site/tmp/cache/persistent/cake_core_core_paths b/site/tmp/cache/persistent/cake_core_core_paths new file mode 100644 index 0000000..f13836c --- /dev/null +++ b/site/tmp/cache/persistent/cake_core_core_paths @@ -0,0 +1,2 @@ +1243395572 +a:10:{s:4:"libs";a:1:{i:0;s:39:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\";}s:5:"model";a:1:{i:0;s:45:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\";}s:8:"behavior";a:1:{i:0;s:55:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\behaviors\\\\";}s:10:"controller";a:1:{i:0;s:50:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\controller\\\\";}s:9:"component";a:1:{i:0;s:61:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\controller\\\\components\\\\";}s:4:"view";a:1:{i:0;s:44:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\";}s:6:"helper";a:1:{i:0;s:52:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\helpers\\\\";}s:4:"cake";a:1:{i:0;s:34:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\";}s:6:"vendor";a:1:{i:0;s:37:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\vendors\\\\";}s:5:"shell";a:1:{i:0;s:47:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\console\\\\libs\\\\";}} diff --git a/site/tmp/cache/persistent/cake_core_default_en_us b/site/tmp/cache/persistent/cake_core_default_en_us new file mode 100644 index 0000000..2c0aef8 --- /dev/null +++ b/site/tmp/cache/persistent/cake_core_default_en_us @@ -0,0 +1,2 @@ +1243395572 +a:1:{s:11:"LC_MESSAGES";a:1:{s:0:"";a:1:{s:7:"default";a:0:{}}}} diff --git a/site/tmp/cache/persistent/cake_core_dir_map b/site/tmp/cache/persistent/cake_core_dir_map new file mode 100644 index 0000000..1a91880 --- /dev/null +++ b/site/tmp/cache/persistent/cake_core_dir_map @@ -0,0 +1,2 @@ +1243395572 +a:3:{s:44:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model";a:4:{i:0;s:44:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model";i:1;s:56:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\datasources";i:2;s:60:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\datasources\\\\dbo";i:3;s:54:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\behaviors";}s:38:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs";a:24:{i:0;s:38:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs";i:1;s:43:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view";i:2;s:53:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\scaffolds";i:3;s:49:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\pages";i:4;s:51:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\layouts";i:5;s:55:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\layouts\\\\xml";i:6;s:55:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\layouts\\\\rss";i:7;s:54:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\layouts\\\\js";i:8;s:57:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\layouts\\\\email";i:9;s:62:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\layouts\\\\email\\\\text";i:10;s:62:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\layouts\\\\email\\\\html";i:11;s:51:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\helpers";i:12;s:50:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\errors";i:13;s:52:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\elements";i:14;s:58:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\elements\\\\email";i:15;s:63:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\elements\\\\email\\\\text";i:16;s:63:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\elements\\\\email\\\\html";i:17;s:44:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model";i:18;s:56:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\datasources";i:19;s:60:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\datasources\\\\dbo";i:20;s:54:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\behaviors";i:21;s:49:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\controller";i:22;s:60:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\controller\\\\components";i:23;s:44:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\cache";}s:44:"D:/Website/localhost/public_html\\\\pmgr\\\\models";a:3:{i:0;s:44:"D:/Website/localhost/public_html\\\\pmgr\\\\models";i:1;s:56:"D:\\\\Website\\\\localhost\\\\public_html\\\\pmgr\\\\models\\\\datasources";i:2;s:54:"D:\\\\Website\\\\localhost\\\\public_html\\\\pmgr\\\\models\\\\behaviors";}} diff --git a/site/tmp/cache/persistent/cake_core_file_map b/site/tmp/cache/persistent/cake_core_file_map new file mode 100644 index 0000000..e4a4928 --- /dev/null +++ b/site/tmp/cache/persistent/cake_core_file_map @@ -0,0 +1,2 @@ +1243395572 +a:2:{s:4:"Core";a:11:{s:12:"Overloadable";s:55:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\overloadable.php";s:10:"Validation";s:53:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\validation.php";s:8:"Behavior";s:57:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\behavior.php";s:17:"ConnectionManager";s:67:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\connection_manager.php";s:5:"Model";s:54:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\model.php";s:9:"Component";s:63:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\controller\\\\component.php";s:6:"Helper";s:54:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\helper.php";s:4:"View";s:52:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\view.php";s:10:"Controller";s:64:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\controller\\\\controller.php";s:4:"l10n";s:47:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\l10n.php";s:4:"i18n";s:47:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\i18n.php";}s:5:"Model";a:1:{s:8:"AppModel";s:51:"D:/Website/localhost/public_html\\\\pmgr\\\\app_model.php";}} diff --git a/site/views/elements/email/html/default.ctp b/site/views/elements/email/html/default.ctp new file mode 100644 index 0000000..a217c80 --- /dev/null +++ b/site/views/elements/email/html/default.ctp @@ -0,0 +1,31 @@ + + ' . $line . '

'; +endforeach; +?> \ No newline at end of file diff --git a/site/views/elements/email/text/default.ctp b/site/views/elements/email/text/default.ctp new file mode 100644 index 0000000..70e05eb --- /dev/null +++ b/site/views/elements/email/text/default.ctp @@ -0,0 +1,25 @@ + + \ No newline at end of file diff --git a/site/views/layouts/ajax.ctp b/site/views/layouts/ajax.ctp new file mode 100644 index 0000000..4857f18 --- /dev/null +++ b/site/views/layouts/ajax.ctp @@ -0,0 +1,25 @@ + + \ No newline at end of file diff --git a/site/views/layouts/default.ctp b/site/views/layouts/default.ctp new file mode 100644 index 0000000..db4d2aa --- /dev/null +++ b/site/views/layouts/default.ctp @@ -0,0 +1,64 @@ + + + + + charset(); ?> + + <?php __('CakePHP: the rapid development php framework:'); ?> + <?php echo $title_for_layout; ?> + + meta('icon'); + + echo $html->css('cake.generic'); + + echo $scripts_for_layout; + ?> + + +
+ +
+ + flash(); ?> + + + +
+ +
+ + + \ No newline at end of file diff --git a/site/views/layouts/email/html/default.ctp b/site/views/layouts/email/html/default.ctp new file mode 100644 index 0000000..72c5442 --- /dev/null +++ b/site/views/layouts/email/html/default.ctp @@ -0,0 +1,37 @@ + + + + + + <?php echo $title_for_layout;?> + + + + + +

This email was sent using the CakePHP Framework

+ + diff --git a/site/views/layouts/email/text/default.ctp b/site/views/layouts/email/text/default.ctp new file mode 100644 index 0000000..4c87cf7 --- /dev/null +++ b/site/views/layouts/email/text/default.ctp @@ -0,0 +1,29 @@ + + + + +This email was sent using the CakePHP Framework, http://cakephp.org. + diff --git a/site/views/layouts/flash.ctp b/site/views/layouts/flash.ctp new file mode 100644 index 0000000..a1b56d7 --- /dev/null +++ b/site/views/layouts/flash.ctp @@ -0,0 +1,44 @@ + + + + +charset(); ?> +<?php echo $page_title; ?> + + + + + + + + +

+ + \ No newline at end of file diff --git a/site/views/layouts/js/default.ctp b/site/views/layouts/js/default.ctp new file mode 100644 index 0000000..d94dc90 --- /dev/null +++ b/site/views/layouts/js/default.ctp @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/site/views/layouts/rss/default.ctp b/site/views/layouts/rss/default.ctp new file mode 100644 index 0000000..94067f2 --- /dev/null +++ b/site/views/layouts/rss/default.ctp @@ -0,0 +1,17 @@ +header(); + +if (!isset($channel)) { + $channel = array(); +} +if (!isset($channel['title'])) { + $channel['title'] = $title_for_layout; +} + +echo $rss->document( + $rss->channel( + array(), $channel, $content_for_layout + ) +); + +?> \ No newline at end of file diff --git a/site/views/layouts/xml/default.ctp b/site/views/layouts/xml/default.ctp new file mode 100644 index 0000000..c688702 --- /dev/null +++ b/site/views/layouts/xml/default.ctp @@ -0,0 +1,2 @@ +header()); ?> + \ No newline at end of file diff --git a/site/views/pages/home.ctp b/site/views/pages/home.ctp new file mode 100644 index 0000000..f19d628 --- /dev/null +++ b/site/views/pages/home.ctp @@ -0,0 +1,80 @@ +

Sweet, "Pmgr" got Baked by CakePHP!

+ + 0): + Debugger::checkSessionKey(); +endif; +?> +

+'; + __('Your tmp directory is writable.'); + echo ''; + else: + echo ''; + __('Your tmp directory is NOT writable.'); + echo ''; + endif; +?> +

+

+'; + echo sprintf(__('The %s is being used for caching. To change the config edit APP/config/core.php ', true), ''. $settings['engine'] . 'Engine'); + echo ''; + else: + echo ''; + __('Your cache is NOT working. Please check the settings in APP/config/core.php'); + echo ''; + endif; +?> +

+

+'; + __('Your database configuration file is present.'); + $filePresent = true; + echo ''; + else: + echo ''; + __('Your database configuration file is NOT present.'); + echo '
'; + __('Rename config/database.php.default to config/database.php'); + echo '
'; + endif; +?> +

+getDataSource('default'); +?> +

+isConnected()): + echo ''; + __('Cake is able to connect to the database.'); + echo ''; + else: + echo ''; + __('Cake is NOT able to connect to the database.'); + echo ''; + endif; +?> +

+ +

+

+', APP . 'views' . DS . 'layouts' . DS . 'default.ctp.
', APP . 'webroot' . DS . 'css'); +?> +

diff --git a/site/webroot/.htaccess b/site/webroot/.htaccess new file mode 100644 index 0000000..f9d8b93 --- /dev/null +++ b/site/webroot/.htaccess @@ -0,0 +1,6 @@ + + RewriteEngine On + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^(.*)$ index.php?url=$1 [QSA,L] + \ No newline at end of file diff --git a/site/webroot/css.php b/site/webroot/css.php new file mode 100644 index 0000000..eb9be9f --- /dev/null +++ b/site/webroot/css.php @@ -0,0 +1,102 @@ +compress($data); + $ratio = 100 - (round(strlen($output) / strlen($data), 3) * 100); + $output = " /* file: $name, ratio: $ratio% */ " . $output; + return $output; + } +/** + * Enter description here... + * + * @param unknown_type $path + * @param unknown_type $content + * @return unknown + */ + function write_css_cache($path, $content) { + if (!is_dir(dirname($path))) { + mkdir(dirname($path)); + } + $cache = new File($path); + return $cache->write($content); + } + + if (preg_match('|\.\.|', $url) || !preg_match('|^ccss/(.+)$|i', $url, $regs)) { + die('Wrong file name.'); + } + + $filename = 'css/' . $regs[1]; + $filepath = CSS . $regs[1]; + $cachepath = CACHE . 'css' . DS . str_replace(array('/','\\'), '-', $regs[1]); + + if (!file_exists($filepath)) { + die('Wrong file name.'); + } + + if (file_exists($cachepath)) { + $templateModified = filemtime($filepath); + $cacheModified = filemtime($cachepath); + + if ($templateModified > $cacheModified) { + $output = make_clean_css($filepath, $filename); + write_css_cache($cachepath, $output); + } else { + $output = file_get_contents($cachepath); + } + } else { + $output = make_clean_css($filepath, $filename); + write_css_cache($cachepath, $output); + $templateModified = time(); + } + + header("Date: " . date("D, j M Y G:i:s ", $templateModified) . 'GMT'); + header("Content-Type: text/css"); + header("Expires: " . gmdate("D, j M Y H:i:s", time() + DAY) . " GMT"); + header("Cache-Control: max-age=86400, must-revalidate"); // HTTP/1.1 + header("Pragma: cache"); // HTTP/1.0 + print $output; +?> \ No newline at end of file diff --git a/site/webroot/css/cake.generic.css b/site/webroot/css/cake.generic.css new file mode 100644 index 0000000..50ee79a --- /dev/null +++ b/site/webroot/css/cake.generic.css @@ -0,0 +1,480 @@ +/* SVN FILE: $Id: cake.generic.css 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.webroot.css + * @since CakePHP(tm) + * @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 + */ + + +* { + margin:0; + padding:0; +} + +/* General Style Info */ +body { + background: #003d4c; + color: #fff; + font-family:'lucida grande',verdana,helvetica,arial,sans-serif; + font-size:90%; + margin: 0; +} +a { + background:#fff; + color: #003d4c; + text-decoration: underline; + font-weight: bold; +} +a:hover { + background:#fff; + color: #003d4c; + text-decoration:none; +} +a img { + border:none; +} +h1, h2, h3, h4 { + font-weight: normal; +} +h1 { + background:#fff; + color: #003d4c; + font-size: 100%; + margin: 0.1em 0; +} +h2 { + background:#fff; + color: #e32; + font-family:'Gill Sans','lucida grande',helvetica, arial, sans-serif; + font-size: 190%; + margin: 0.3em 0; + padding-top: 0.8em; +} +h3 { + color: #993; + font-family:'Gill Sans','lucida grande',helvetica, arial, sans-serif; + font-size: 165%; + padding-top: 1.5em; +} +h4 { + color: #993; + font-weight: normal; + padding-top: 0.5em; +} +ul, li { + margin: 0 12px; +} + +/* Layout */ +#container { + text-align: left; +} + +#header{ + padding: 10px 20px; +} +#header h1 { + background: #003d4c url('../img/cake.icon.gif') no-repeat left; + color: #fff; + padding: 0px 30px; +} +#header h1 a { + color: #fff; + background: #003d4c; + font-weight: normal; + text-decoration: none; +} +#header h1 a:hover { + color: #fff; + background: #003d4c; + text-decoration: underline; +} +#content{ + background: #fff; + clear: both; + color: #333; + padding: 10px 20px 40px 20px; + overflow: auto; +} +#footer { + clear: both; + padding: 6px 10px; + text-align: right; +} + +/* Tables */ +table { + background: #fff; + border:1px solid #ccc; + border-right:0; + clear: both; + color: #333; + margin-bottom: 10px; + width: 100%; +} +th { + background: #f2f2f2; + border:1px solid #bbb; + border-top: 1px solid #fff; + border-left: 1px solid #fff; + text-align: center; +} +th a { + background:#f2f2f2; + display: block; + padding: 2px 4px; + text-decoration: none; +} +th a:hover { + background: #ccc; + color: #333; + text-decoration: none; +} +table tr td { + background: #fff; + border-right: 1px solid #ccc; + padding: 4px; + text-align: center; + vertical-align: top; +} +table tr.altrow td { + background: #f4f4f4; +} +td.actions { + text-align: center; + white-space: nowrap; +} +td.actions a { + margin: 0px 6px; +} +.cake-sql-log table { + background: #f4f4f4; +} +.cake-sql-log td { + padding: 4px 8px; + text-align: left; +} + +/* Paging */ +div.paging { + background:#fff; + color: #ccc; + margin-bottom: 2em; +} +div.paging div.disabled { + color: #ddd; + display: inline; +} +div.paging span { +} +div.paging span.current { + color: #000; +} +div.paging span a { +} + +/* Scaffold View */ +dl { + line-height: 2em; + margin: 0em 0em; + width: 60%; +} +dl.altrow { + background: #f4f4f4; +} +dt { + font-weight: bold; + padding-left: 4px; + vertical-align: top; +} +dd { + margin-left: 10em; + margin-top: -2em; + vertical-align: top; +} + +/* Forms */ +form { + clear: both; + margin-right: 20px; + padding: 0; + width: 80%; +} +fieldset { + border: 1px solid #ccc; + margin-top: 30px; + padding: 16px 20px; +} +fieldset legend { + background:#fff; + color: #e32; + font-size: 160%; + font-weight: bold; +} +fieldset fieldset { + margin-top: 0px; + margin-bottom: 20px; + padding: 16px 10px; +} +fieldset fieldset legend { + font-size: 120%; + font-weight: normal; +} +fieldset fieldset div { + clear: left; + margin: 0 20px; +} +form div { + clear: both; + margin-bottom: 1em; + padding: .5em; + vertical-align: text-top; +} +form div.input { + color: #444; +} +form div.required { + color: #333; + font-weight: bold; +} +form div.submit { + border: 0; + clear: both; + margin-top: 10px; + margin-left: 140px; +} +label { + display: block; + font-size: 110%; + padding-right: 20px; +} +input, textarea { + clear: both; + font-size: 140%; + font-family: "frutiger linotype", "lucida grande", "verdana", sans-serif; + padding: 2px; + width: 100%; +} +select { + clear: both; + font-size: 120%; + vertical-align: text-bottom; +} +select[multiple=multiple] { + width: 100%; +} +option { + font-size: 120%; + padding: 0 3px; +} +input[type=checkbox] { + clear: left; + float: left; + margin: 0px 6px 7px 2px; + width: auto; +} +input[type=radio] { + float:left; + width:auto; + margin: 0 3px 7px 0; +} +div.radio label { + margin: 0 0 6px 20px; +} +input[type=submit] { + display: inline; + font-size: 110%; + padding: 2px 5px; + width: auto; + vertical-align: bottom; +} + +/* Notices and Errors */ +div.message { + clear: both; + color: #900; + font-size: 140%; + font-weight: bold; + margin: 1em 0; +} +div.error-message { + clear: both; + color: #900; + font-weight: bold; +} +p.error { + background-color: #e32; + color: #fff; + font-family: Courier, monospace; + font-size: 120%; + line-height: 140%; + padding: 0.8em; + margin: 1em 0; +} +p.error em { + color: #000; + font-weight: normal; + line-height: 140%; +} +.notice { + background: #ffcc00; + color: #000; + display: block; + font-family: Courier, monospace; + font-size: 120%; + line-height: 140%; + padding: 0.8em; + margin: 1em 0; +} +.success { + background: green; + color: #fff; +} + +/* Actions */ +div.actions ul { + margin: 0px 0; + padding: 0; +} +div.actions li { + display: inline; + list-style-type: none; + line-height: 2em; + margin: 0 2em 0 0; + white-space: nowrap; +} +div.actions ul li a { + background:#fff; + color: #003d4c; + text-decoration: none; +} +div.actions ul li a:hover { + color: #333; + text-decoration: underline; +} + +/* Related */ +div.related { + clear: both; + display: block; +} + +/* Debugging */ +pre { + color: #000; + background: #f0f0f0; + padding: 1em; +} +pre.cake-debug { + background: #ffcc00; + font-size: 120%; + line-height: 140%; + margin-top: 1em; + overflow: auto; + position: relative; +} +div.cake-stack-trace { + background: #fff; + border: 4px dotted #ffcc00; + color: #333; + margin: 0px; + padding: 6px; + font-size: 120%; + line-height: 140%; + overflow: auto; + position: relative; +} +div.cake-code-dump pre { + position: relative; + overflow: auto; +} +div.cake-stack-trace pre, div.cake-code-dump pre { + color: #000; + background-color: #F0F0F0; + margin: 0px; + padding: 1em; + overflow: auto; +} +div.cake-code-dump pre, div.cake-code-dump pre code { + clear: both; + font-size: 12px; + line-height: 15px; + margin: 4px 2px; + padding: 4px; + overflow: auto; +} +div.cake-code-dump span.code-highlight { + background-color: #ff0; + padding: 4px; +} +div.code-coverage-results div.code-line { + padding-left:5px; + display:block; + margin-left:10px; +} +div.code-coverage-results div.uncovered span.content { + background:#ecc; +} +div.code-coverage-results div.covered span.content { + background:#cec; +} +div.code-coverage-results div.ignored span.content { + color:#aaa; +} +div.code-coverage-results span.line-num { + color:#666; + display:block; + float:left; + width:20px; + text-align:right; + margin-right:5px; +} +div.code-coverage-results span.line-num strong { + color:#666; +} +div.code-coverage-results div.start { + border:1px solid #aaa; + border-width:1px 1px 0px 1px; + margin-top:30px; + padding-top:5px; +} +div.code-coverage-results div.end { + border:1px solid #aaa; + border-width:0px 1px 1px 1px; + margin-bottom:30px; + padding-bottom:5px; +} +div.code-coverage-results div.realstart { + margin-top:0px; +} +div.code-coverage-results p.note { + color:#bbb; + padding:5px; + margin:5px 0 10px; + font-size:10px; +} +div.code-coverage-results span.result-bad { + color: #a00; +} +div.code-coverage-results span.result-ok { + color: #fa0; +} +div.code-coverage-results span.result-good { + color: #0a0; +} \ No newline at end of file diff --git a/site/webroot/favicon.ico b/site/webroot/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b36e81f2f35133dede48dc18f78d3e1a3353f7bc GIT binary patch literal 372 zcmV-)0gL{LP)Ce4&o}{bgKX)=r-B_#-Qs`WM)Da5Prgl zsZ%T@FChJjuHh1`0m$SsVlk8KBKw^@522Z3S}fqzqUy4nLhVp$W)@MMy#WF!pk3U7 zB65kQi)kZ#rBYK5tRifZI?>XjFU4<@lsph9Z1>blC@{qW13mof`13?K&cOa zOrfx~(a*Br=IF!2lMFyj!pzT(o0Foa zdn-*>Om~4(V_pR~MF2EGA^8La000jFEC2ui02BZe000D*@X1N5t>>`K@|6NJ6h&YL z1u`%~wUB3glC5+ga)976a!3oFOhFu(2DMubr5G5VhQ{x4NGt;hD1iW&9tgW!0iZB! z6O)6HG-waF&;)>@C@r&FLW6?XF3Wfe6jmrIZUbdo27(g_16K`ZTZ}-3IRcmfa});+ jCL}5ZNSK%y0t-u|r5FwZRfnys7YD7i0<9mpxe)+6uKiOz literal 0 HcmV?d00001 diff --git a/site/webroot/img/cake.power.gif b/site/webroot/img/cake.power.gif new file mode 100644 index 0000000000000000000000000000000000000000..8f8d570a2e24d86f0ad7730ee8f2435fd49f152c GIT binary patch literal 201 zcmV;)05<&ZTq0L2I(c1A@d@rg`ENj#vn zcl`yi#iKX*jb2F7vd0WQgUq5Tw}Jp}g+ZnCeBY3dYNI+m71%bHRfx4UCkD2th(Q*@ zmd5r+MJNYn7dispatch($url); + } + if (Configure::read() > 0) { + echo ""; + } +?> \ No newline at end of file diff --git a/site/webroot/js/vendors.php b/site/webroot/js/vendors.php new file mode 100644 index 0000000..a6fcf32 --- /dev/null +++ b/site/webroot/js/vendors.php @@ -0,0 +1,42 @@ + \ No newline at end of file diff --git a/site/webroot/test.php b/site/webroot/test.php new file mode 100644 index 0000000..485a68b --- /dev/null +++ b/site/webroot/test.php @@ -0,0 +1,181 @@ + + * Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org) + * + * 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. (http://www.cakefoundation.org) + * @link https://trac.cakephp.org/wiki/Developement/TestSuite CakePHP(tm) Tests + * @package cake + * @subpackage cake.cake.tests.libs + * @since CakePHP(tm) v 1.2.0.4433 + * @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/opengroup.php The Open Group Test Suite License + */ +error_reporting(E_ALL); +set_time_limit(0); +ini_set('memory_limit','128M'); +ini_set('display_errors', 1); +/** + * Use the DS to separate the directories in other defines + */ + if (!defined('DS')) { + define('DS', DIRECTORY_SEPARATOR); + } +/** + * These defines should only be edited if you have cake installed in + * a directory layout other than the way it is distributed. + * When using custom settings be sure to use the DS and do not add a trailing DS. + */ + +/** + * The full path to the directory which holds "app", WITHOUT a trailing DS. + * + */ + if (!defined('ROOT')) { + define('ROOT', dirname(dirname(dirname(__FILE__)))); + } +/** + * The actual directory name for the "app". + * + */ + if (!defined('APP_DIR')) { + define('APP_DIR', basename(dirname(dirname(__FILE__)))); + } +/** + * The absolute path to the "cake" directory, WITHOUT a trailing DS. + * + */ + if (!defined('CAKE_CORE_INCLUDE_PATH')) { + define('CAKE_CORE_INCLUDE_PATH', 'D:\Website\localhost\CakePHP'); + } + +/** + * Editing below this line should not be necessary. + * Change at your own risk. + * + */ +if (!defined('WEBROOT_DIR')) { + define('WEBROOT_DIR', basename(dirname(__FILE__))); +} +if (!defined('WWW_ROOT')) { + define('WWW_ROOT', dirname(__FILE__) . DS); +} +if (!defined('CORE_PATH')) { + if (function_exists('ini_set') && ini_set('include_path', CAKE_CORE_INCLUDE_PATH . PATH_SEPARATOR . ROOT . DS . APP_DIR . DS . PATH_SEPARATOR . ini_get('include_path'))) { + define('APP_PATH', null); + define('CORE_PATH', null); + } else { + define('APP_PATH', ROOT . DS . APP_DIR . DS); + define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS); + } +} +if (!include(CORE_PATH . 'cake' . DS . 'bootstrap.php')) { + trigger_error("CakePHP core could not be found. Check the value of CAKE_CORE_INCLUDE_PATH in APP/webroot/index.php. It should point to the directory containing your " . DS . "cake core directory and your " . DS . "vendors root directory.", E_USER_ERROR); +} + +$corePath = Configure::corePaths('cake'); +if (isset($corePath[0])) { + define('TEST_CAKE_CORE_INCLUDE_PATH', rtrim($corePath[0], DS) . DS); +} else { + define('TEST_CAKE_CORE_INCLUDE_PATH', CAKE_CORE_INCLUDE_PATH); +} + +require_once CAKE_TESTS_LIB . 'test_manager.php'; + +if (Configure::read('debug') < 1) { + die(__('Debug setting does not allow access to this url.', true)); +} + +if (!isset($_SERVER['SERVER_NAME'])) { + $_SERVER['SERVER_NAME'] = ''; +} +if (empty( $_GET['output'])) { + $_GET['output'] = 'html'; +} +/** + * + * Used to determine output to display + */ +define('CAKE_TEST_OUTPUT_HTML', 1); +define('CAKE_TEST_OUTPUT_TEXT', 2); + +if (isset($_GET['output']) && $_GET['output'] == 'html') { + define('CAKE_TEST_OUTPUT', CAKE_TEST_OUTPUT_HTML); +} else { + Debugger::output('txt'); + define('CAKE_TEST_OUTPUT', CAKE_TEST_OUTPUT_TEXT); +} + +if (!App::import('Vendor', 'simpletest' . DS . 'reporter')) { + CakePHPTestHeader(); + include CAKE_TESTS_LIB . 'simpletest.php'; + CakePHPTestSuiteFooter(); + exit(); +} + +$analyzeCodeCoverage = false; +if (isset($_GET['code_coverage'])) { + $analyzeCodeCoverage = true; + require_once CAKE_TESTS_LIB . 'code_coverage_manager.php'; + if (!extension_loaded('xdebug')) { + CakePHPTestHeader(); + include CAKE_TESTS_LIB . 'xdebug.php'; + CakePHPTestSuiteFooter(); + exit(); + } +} + +CakePHPTestHeader(); +CakePHPTestSuiteHeader(); +define('RUN_TEST_LINK', $_SERVER['PHP_SELF']); + +if (isset($_GET['group'])) { + if ('all' == $_GET['group']) { + TestManager::runAllTests(CakeTestsGetReporter()); + } else { + if ($analyzeCodeCoverage) { + CodeCoverageManager::start($_GET['group'], CakeTestsGetReporter()); + } + TestManager::runGroupTest(ucfirst($_GET['group']), CakeTestsGetReporter()); + if ($analyzeCodeCoverage) { + CodeCoverageManager::report(); + } + } + + CakePHPTestRunMore(); + CakePHPTestAnalyzeCodeCoverage(); +} elseif (isset($_GET['case'])) { + if ($analyzeCodeCoverage) { + CodeCoverageManager::start($_GET['case'], CakeTestsGetReporter()); + } + + TestManager::runTestCase($_GET['case'], CakeTestsGetReporter()); + + if ($analyzeCodeCoverage) { + CodeCoverageManager::report(); + } + + CakePHPTestRunMore(); + CakePHPTestAnalyzeCodeCoverage(); +} elseif (isset($_GET['show']) && $_GET['show'] == 'cases') { + CakePHPTestCaseList(); +} else { + CakePHPTestGroupTestList(); +} +CakePHPTestSuiteFooter(); +$output = ob_get_clean(); +echo $output; +?> \ No newline at end of file From 220284d20f1cb20523b22105e81562b9effe6abc Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 27 May 2009 04:24:45 +0000 Subject: [PATCH 004/717] Added svn:ignore for all of the tmp directories git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@5 97e9348a-65ac-dc4b-aefc-98561f571b83 From c22be388cf249e7e473f1dc3d38fcc32012d3aa0 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 27 May 2009 04:35:43 +0000 Subject: [PATCH 005/717] Fixed the stupid svn:ignore properties, which all had a trailing space (doh!) git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@6 97e9348a-65ac-dc4b-aefc-98561f571b83 From c5d5e2c6511a973db740dac709c243782e87e80e Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 27 May 2009 19:23:05 +0000 Subject: [PATCH 006/717] Removed the cache files from the repository git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@7 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/tmp/cache/persistent/cake_core_core_paths | 2 -- site/tmp/cache/persistent/cake_core_default_en_us | 2 -- site/tmp/cache/persistent/cake_core_dir_map | 2 -- site/tmp/cache/persistent/cake_core_file_map | 2 -- 4 files changed, 8 deletions(-) delete mode 100644 site/tmp/cache/persistent/cake_core_core_paths delete mode 100644 site/tmp/cache/persistent/cake_core_default_en_us delete mode 100644 site/tmp/cache/persistent/cake_core_dir_map delete mode 100644 site/tmp/cache/persistent/cake_core_file_map diff --git a/site/tmp/cache/persistent/cake_core_core_paths b/site/tmp/cache/persistent/cake_core_core_paths deleted file mode 100644 index f13836c..0000000 --- a/site/tmp/cache/persistent/cake_core_core_paths +++ /dev/null @@ -1,2 +0,0 @@ -1243395572 -a:10:{s:4:"libs";a:1:{i:0;s:39:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\";}s:5:"model";a:1:{i:0;s:45:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\";}s:8:"behavior";a:1:{i:0;s:55:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\behaviors\\\\";}s:10:"controller";a:1:{i:0;s:50:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\controller\\\\";}s:9:"component";a:1:{i:0;s:61:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\controller\\\\components\\\\";}s:4:"view";a:1:{i:0;s:44:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\";}s:6:"helper";a:1:{i:0;s:52:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\helpers\\\\";}s:4:"cake";a:1:{i:0;s:34:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\";}s:6:"vendor";a:1:{i:0;s:37:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\vendors\\\\";}s:5:"shell";a:1:{i:0;s:47:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\console\\\\libs\\\\";}} diff --git a/site/tmp/cache/persistent/cake_core_default_en_us b/site/tmp/cache/persistent/cake_core_default_en_us deleted file mode 100644 index 2c0aef8..0000000 --- a/site/tmp/cache/persistent/cake_core_default_en_us +++ /dev/null @@ -1,2 +0,0 @@ -1243395572 -a:1:{s:11:"LC_MESSAGES";a:1:{s:0:"";a:1:{s:7:"default";a:0:{}}}} diff --git a/site/tmp/cache/persistent/cake_core_dir_map b/site/tmp/cache/persistent/cake_core_dir_map deleted file mode 100644 index 1a91880..0000000 --- a/site/tmp/cache/persistent/cake_core_dir_map +++ /dev/null @@ -1,2 +0,0 @@ -1243395572 -a:3:{s:44:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model";a:4:{i:0;s:44:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model";i:1;s:56:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\datasources";i:2;s:60:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\datasources\\\\dbo";i:3;s:54:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\behaviors";}s:38:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs";a:24:{i:0;s:38:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs";i:1;s:43:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view";i:2;s:53:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\scaffolds";i:3;s:49:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\pages";i:4;s:51:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\layouts";i:5;s:55:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\layouts\\\\xml";i:6;s:55:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\layouts\\\\rss";i:7;s:54:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\layouts\\\\js";i:8;s:57:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\layouts\\\\email";i:9;s:62:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\layouts\\\\email\\\\text";i:10;s:62:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\layouts\\\\email\\\\html";i:11;s:51:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\helpers";i:12;s:50:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\errors";i:13;s:52:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\elements";i:14;s:58:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\elements\\\\email";i:15;s:63:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\elements\\\\email\\\\text";i:16;s:63:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\elements\\\\email\\\\html";i:17;s:44:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model";i:18;s:56:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\datasources";i:19;s:60:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\datasources\\\\dbo";i:20;s:54:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\behaviors";i:21;s:49:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\controller";i:22;s:60:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\controller\\\\components";i:23;s:44:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\cache";}s:44:"D:/Website/localhost/public_html\\\\pmgr\\\\models";a:3:{i:0;s:44:"D:/Website/localhost/public_html\\\\pmgr\\\\models";i:1;s:56:"D:\\\\Website\\\\localhost\\\\public_html\\\\pmgr\\\\models\\\\datasources";i:2;s:54:"D:\\\\Website\\\\localhost\\\\public_html\\\\pmgr\\\\models\\\\behaviors";}} diff --git a/site/tmp/cache/persistent/cake_core_file_map b/site/tmp/cache/persistent/cake_core_file_map deleted file mode 100644 index e4a4928..0000000 --- a/site/tmp/cache/persistent/cake_core_file_map +++ /dev/null @@ -1,2 +0,0 @@ -1243395572 -a:2:{s:4:"Core";a:11:{s:12:"Overloadable";s:55:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\overloadable.php";s:10:"Validation";s:53:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\validation.php";s:8:"Behavior";s:57:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\behavior.php";s:17:"ConnectionManager";s:67:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\connection_manager.php";s:5:"Model";s:54:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\model\\\\model.php";s:9:"Component";s:63:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\controller\\\\component.php";s:6:"Helper";s:54:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\helper.php";s:4:"View";s:52:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\view\\\\view.php";s:10:"Controller";s:64:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\controller\\\\controller.php";s:4:"l10n";s:47:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\l10n.php";s:4:"i18n";s:47:"D:\\\\Website\\\\localhost\\\\CakePHP\\\\cake\\\\libs\\\\i18n.php";}s:5:"Model";a:1:{s:8:"AppModel";s:51:"D:/Website/localhost/public_html\\\\pmgr\\\\app_model.php";}} From 2665d012c2a38ceeab336f2be105ed3ed6554b3f Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 27 May 2009 19:26:04 +0000 Subject: [PATCH 007/717] Added a scripts directory and the latest copy of our sitelink conversion script. For the complete revision history of sitelink2pmgr.pl, see branches/rent_manager_20090510 path of the 'domain' repository git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@8 97e9348a-65ac-dc4b-aefc-98561f571b83 --- scripts/sitelink2rmgr.pl | 796 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 796 insertions(+) create mode 100644 scripts/sitelink2rmgr.pl diff --git a/scripts/sitelink2rmgr.pl b/scripts/sitelink2rmgr.pl new file mode 100644 index 0000000..67b6863 --- /dev/null +++ b/scripts/sitelink2rmgr.pl @@ -0,0 +1,796 @@ +#perl -w +use strict; +use DBI; +use Data::Dumper; +use File::Copy; + +# Internally adjust all numbers coming from the database to +# be in inches. Not necessary to go to this detail, but the +# actual units used is irrelevant, provided everything is to +# scale, and this factor ensures that any fractional units +# become whole (e.g. 7.5 "feet" becomes 90 "units") +my $internal_adjustment_factor = 12; + +my $schema_file = shift || die("Must specify schema file\n"); +my $slink_file = shift || die("Must specify sitelink file\n"); + +my $slink_file = ";Data Source=$slink_file"; +my $slink_pass = ";Jet OLEDB:Database Password=2web"; +my $sdsn="Provider=Microsoft.Jet.OLEDB.4.0$slink_pass$slink_file"; +my $sdbh = DBI->connect("dbi:ADO:$sdsn", undef, undef, {PrintError => 1, + RaiseError => 1}); + +# Connect to the database. +my($hostname, $database, $user, $password) = ('localhost', 'rentmgr', 'root', 'mysql97312519'); +my $db_handle = DBI->connect("DBI:mysql:database=$database;host=$hostname", + $user, $password, + {'RaiseError' => 1}); + + +my ($query, $result, $nrows, $row); +my ($aicur_c_id, $aicur_ca_id, $aicur_cp_id, $aicur_ce_id) = (0, 0, 0, 0); +my ($aicur_g_id, $aicur_gp_id, $aicur_user_id) = (0, 0, 0); +my ($aicur_type_id, $aicur_size_id, $aicur_unit_id) = (0, 0, 0); +my ($aicur_site_id, $aicur_area_id) = (0, 0); +my ($aicur_lease_type_id, $aicur_lease_id) = (0, 0); +my ($aicur_charge_id, $aicur_receipt_id, $aicur_payment_id) = (0, 0, 0); + +open(SCHEMA, "<$schema_file") || die ("Can't open schema ($!)\n"); +my $schema_query = ""; +while () { + next if /^\s*-- /; + $schema_query .= $_; + query($db_handle, $schema_query), $schema_query = "" + if /;\s*$/; +} +close(SCHEMA); + +++$aicur_c_id; +$query = "INSERT INTO rmgr_contacts + (`id`, `first_name`, `middle_name`, `last_name`, `display_name`) VALUES + ($aicur_c_id, 'Abijah', 'M', 'Perkins', 'Perkins, Abijah')"; + query($db_handle, $query) || die("Unable to insert"); + +++$aicur_ca_id; +$query = "INSERT INTO rmgr_contactAddresses + (`id`, `address`, `city`, `state`, `postcode`, `country`) VALUES + ($aicur_ca_id, '1324 N Liberty Lake Rd\nPMB 263', 'Liberty Lake', 'WA', '99019', 'USA')"; + query($db_handle, $query) || die("Unable to insert"); +$query = "INSERT INTO rmgr_contactMethods + (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES + ($aicur_c_id, 'POST', $aicur_ca_id, 'MAIN', 'PRIMARY')"; + query($db_handle, $query) || die("Unable to insert"); + +++$aicur_ca_id; +$query = "INSERT INTO rmgr_contactAddresses + (`id`, `address`, `city`, `state`, `postcode`, `country`) VALUES + ($aicur_ca_id, '5221 W Myrtlewood Ct', 'Spokane', 'WA', '99208', 'USA')"; + query($db_handle, $query) || die("Unable to insert"); +$query = "INSERT INTO rmgr_contactMethods + (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES + ($aicur_c_id, 'POST', $aicur_ca_id, 'HOME', 'ALTERNATE')"; + query($db_handle, $query) || die("Unable to insert"); + +++$aicur_ca_id; +$query = "INSERT INTO rmgr_contactAddresses + (`id`, `address`, `city`, `state`, `postcode`, `country`) VALUES + ($aicur_ca_id, 'PO Box 69', 'Granger', 'WA', '98932', 'USA')"; + query($db_handle, $query) || die("Unable to insert"); +$query = "INSERT INTO rmgr_contactMethods + (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES + ($aicur_c_id, 'POST', $aicur_ca_id, 'HOME', 'ALTERNATE')"; + query($db_handle, $query) || die("Unable to insert"); + +++$aicur_cp_id; +$query = "INSERT INTO rmgr_contactPhones + (`id`, `type`, `phone`) VALUES + ($aicur_cp_id, 'MOBILE', '5098445573')"; + query($db_handle, $query) || die("Unable to insert"); +$query = "INSERT INTO rmgr_contactMethods + (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES + ($aicur_c_id, 'PHONE', $aicur_cp_id, 'MAIN', 'PRIMARY')"; + query($db_handle, $query) || die("Unable to insert"); + +++$aicur_cp_id; +$query = "INSERT INTO rmgr_contactPhones + (`id`, `type`, `phone`) VALUES + ($aicur_cp_id, 'MOBILE', '5098445973')"; + query($db_handle, $query) || die("Unable to insert"); +$query = "INSERT INTO rmgr_contactMethods + (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES + ($aicur_c_id, 'PHONE', $aicur_cp_id, 'MAIN', 'ALTERNATE')"; + query($db_handle, $query) || die("Unable to insert"); + +++$aicur_cp_id; +$query = "INSERT INTO rmgr_contactPhones + (`id`, `type`, `phone`) VALUES + ($aicur_cp_id, 'VIRTUAL', '5095901112')"; + query($db_handle, $query) || die("Unable to insert"); +$query = "INSERT INTO rmgr_contactMethods + (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES + ($aicur_c_id, 'PHONE', $aicur_cp_id, 'BUSINESS', 'WORK')"; + query($db_handle, $query) || die("Unable to insert"); + +++$aicur_cp_id; +$query = "INSERT INTO rmgr_contactPhones + (`id`, `type`, `phone`) VALUES + ($aicur_cp_id, 'LANDLINE', '5098541491')"; + query($db_handle, $query) || die("Unable to insert"); +$query = "INSERT INTO rmgr_contactMethods + (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES + ($aicur_c_id, 'PHONE', $aicur_cp_id, 'HOME', 'ALTERNATE')"; + query($db_handle, $query) || die("Unable to insert"); + +++$aicur_cp_id; +$query = "INSERT INTO rmgr_contactPhones + (`id`, `type`, `phone`) VALUES + ($aicur_cp_id, 'VIRTUAL', '8774488664')"; + query($db_handle, $query) || die("Unable to insert"); +$query = "INSERT INTO rmgr_contactMethods + (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES + ($aicur_c_id, 'PHONE', $aicur_cp_id, 'BUSINESS', 'WORK')"; + query($db_handle, $query) || die("Unable to insert"); + +++$aicur_cp_id; +$query = "INSERT INTO rmgr_contactPhones + (`id`, `type`, `phone`) VALUES + ($aicur_cp_id, 'FAX', '8662960131')"; + query($db_handle, $query) || die("Unable to insert"); +$query = "INSERT INTO rmgr_contactMethods + (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES + ($aicur_c_id, 'PHONE', $aicur_cp_id, 'BUSINESS', 'WORK')"; + query($db_handle, $query) || die("Unable to insert"); + +++$aicur_ce_id; +$query = "INSERT INTO rmgr_contactEmails + (`id`, `email`) VALUES + ($aicur_ce_id, 'abijah\@PerkinsHouse.com')"; + query($db_handle, $query) || die("Unable to insert"); +$query = "INSERT INTO rmgr_contactMethods + (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES + ($aicur_c_id, 'EMAIL', $aicur_ce_id, 'HOME', 'PRIMARY')"; + query($db_handle, $query) || die("Unable to insert"); + +++$aicur_ce_id; +$query = "INSERT INTO rmgr_contactEmails + (`id`, `email`) VALUES + ($aicur_ce_id, 'abijah\@PerkinsREI.com')"; + query($db_handle, $query) || die("Unable to insert"); +$query = "INSERT INTO rmgr_contactMethods + (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES + ($aicur_c_id, 'EMAIL', $aicur_ce_id, 'HOME', 'WORK')"; + query($db_handle, $query) || die("Unable to insert"); + +++$aicur_ce_id; +$query = "INSERT INTO rmgr_contactEmails + (`id`, `email`) VALUES + ($aicur_ce_id, 'abijah\@ValleyStorage.com')"; + query($db_handle, $query) || die("Unable to insert"); +$query = "INSERT INTO rmgr_contactMethods + (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES + ($aicur_c_id, 'EMAIL', $aicur_ce_id, 'BUSINESS', 'WORK')"; + query($db_handle, $query) || die("Unable to insert"); + +++$aicur_g_id; +$query = "INSERT INTO rmgr_groups + (`id`, `code`, `name`) + VALUES + ($aicur_g_id, 'Owner', 'Owner Group')"; + query($db_handle, $query) || die("Unable to insert"); + +++$aicur_gp_id; +$query = "INSERT INTO rmgr_groupPermissions + (`group_id`, `name`, `access`) + VALUES + ($aicur_gp_id, 'EVERYTHING', 'FORCED')"; + query($db_handle, $query) || die("Unable to insert"); + + +++$aicur_user_id; +$query = "INSERT INTO rmgr_users + (`id`, `code`, `login`, `contact_id`) + VALUES + ($aicur_user_id, 'AP', 'abijah', $aicur_c_id)"; + query($db_handle, $query) || die("Unable to insert"); + + +++$aicur_site_id; +$query = "INSERT INTO rmgr_sites + (`id`, `code`, `name`) + VALUES + ($aicur_site_id, 'VSS', 'Valley Storage')"; + query($db_handle, $query) || die("Unable to insert"); + +$query = "INSERT INTO rmgr_siteMemberships + (`site_id`, `user_id`, `group_id`) + VALUES + ($aicur_site_id, $aicur_user_id, $aicur_g_id)"; + query($db_handle, $query) || die("Unable to insert"); + +++$aicur_area_id; +$query = "INSERT INTO rmgr_siteAreas + (`id`, `site_id`, `code`, `name`) + VALUES + ($aicur_area_id, $aicur_site_id, 'Main', 'Main Facility Area')"; + query($db_handle, $query) || die("Unable to insert"); + +++$aicur_lease_type_id; +$query = "INSERT INTO rmgr_leaseTypes + (`id`, `code`, `name`) + VALUES + ($aicur_lease_type_id, 'SL', 'Storage Lease')"; + query($db_handle, $query) || die("Unable to insert"); + + + + +###################################################################### +###################################################################### +## query + +sub query { + my ($dbh, $sql) = @_; + #print("$sql\n\n"); #return [ { 'id' => 7 } ]; + #print("$sql\n\n") if $sql =~ /^\s*UPDATE/i; + #return 1 unless $sql =~ /^\s*SELECT/i; + + my ($sth, $result); + if ($sql =~ /^\s*SELECT/i) { + $sth = $dbh->prepare($sql); + $sth->execute(); + $result = $sth->fetchall_arrayref({}); + } else { + $result = $dbh->do($sql); + } + + #print("sth = " . Dumper($sth) . "\n"); + #print("result = " . Dumper($result) . "\n"); + return ($sth, $result); +} + + +sub sizeCode { + my ($width, $depth) = @_; + return "YARD" + if ($width == 12 && $depth == 40); + return "APARTMENT" + if ($width == 20 && $depth == 30); + return sprintf("%02dx%02d", $width, $depth); +} + +sub datefmt { + my ($dt) = @_; + return undef unless $dt; + my @dt = split(/\/|\s/, $dt); + #print("$dt : " . sprintf("%04d-%02d-%02d", $dt[2], $dt[0], $dt[1]) . "\n"); + return sprintf("%04d-%02d-%02d%s", $dt[2], $dt[0], $dt[1], $dt[3] ? ' '.$dt[3] : ""); +} + +###################################################################### +###################################################################### +###################################################################### +###################################################################### +###################################################################### +###################################################################### +## +## UNITS +## + + +###################################################################### +## Unit Types + +$query = "SELECT * FROM UnitType ORDER BY TypeID"; +$result = query($sdbh, $query); +$nrows = @$result; +print(" $nrows Unit Types\n"); + +foreach $row (@$result) { + $query = "INSERT INTO rmgr_unitTypes + (`id`, `code`, `name`) + VALUES + ($row->{'TypeID'}, 'xxx', '$row->{'UnitType'}')"; + query($db_handle, $query) || die("Unable to insert"); +} + + +###################################################################### +## Unit Sizes + +$query = "SELECT * FROM UnitInfo WHERE UnitID <> 'POS\$' ORDER BY UnitID"; +$result = query($sdbh, $query); +$nrows = @$result; +print(" $nrows Units\n"); + +my (%unit_size_map); +foreach $row (@$result) { + my $sz = sizeCode($row->{'Width'}, $row->{'Depth'}); + next if defined $unit_size_map{$sz}; + $unit_size_map{$sz} = { 'id' => ++$aicur_size_id }; + $unit_size_map{$sz}{'rent'} = $row->{'StdRent'}; + $unit_size_map{$sz}{'dep'} = $row->{'StdSecDep'}; + my $szid = $unit_size_map{$sz}{'id'}; + + $query = "INSERT INTO rmgr_unitSizes + (`id`, `type_id`, `code`, `name`, `width`, `depth`, + `deposit`, `amount`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($szid, $row->{'Type'}, $sz, $sz, + $internal_adjustment_factor * $row->{'Width'}, + $internal_adjustment_factor * $row->{'Depth'}, + $row->{'StdSecDep'}, $row->{'StdRent'}) + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); +} + + +###################################################################### +## Units + +my (%unit_map); +foreach $row (@$result) { + my $sz = sizeCode($row->{'Width'}, $row->{'Depth'}); + my $szid = $unit_size_map{$sz}{'id'}; + $unit_map{$row->{'UnitID'}} = ++$aicur_unit_id; + my $uid = $unit_map{$row->{'UnitID'}}; + + $query = "INSERT INTO rmgr_units + (`id`, `size_id`, `code`, `name`, + `status`, + `sort_order`, `walk_order`, `deposit`, `amount`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($uid, $szid, $row->{'UnitID'}, $row->{'UnitID'}, + $row->{'Rented'} ?'OCCUPIED' :($row->{'Rentable'} ?'VACANT' :'UNAVAILABLE'), + $uid, $uid, $row->{'StdSecDep'}, $row->{'StdRent'}) + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); +} + + +###################################################################### +## Map + +my %info = ('extents' => {}, 'units' => {}); + +# Get the overall site limits +$query = "SELECT MIN(M.Top) AS mintop, MIN(M.Left) AS minlft,"; +$query .= " MAX(M.Top + IIF(M.reverseWL, U.Width, U.Depth)) AS bot,"; +$query .= " MAX(M.Left + IIF(M.reverseWL, U.Depth, U.Width)) AS rgt"; +$query .= ' FROM UnitInfo U INNER JOIN mapUnitsV2 M ON M.unitID = U.UnitID'; +$result = query($sdbh, $query); + +# Fetch and verify the result +my $row = shift(@$result); +die("MIN query failed!") unless $row; + +# Compute the actual boundaries, adjusting for a (0,0) origin +my $top_adjustment = 0 - $row->{'mintop'}; +my $left_adjustment = 0 - $row->{'minlft'}; +$info{'extents'}{'top'} = 0; +$info{'extents'}{'left'} = 0; +$info{'extents'}{'bottom'} = $internal_adjustment_factor * ($top_adjustment + $row->{'bot'} + 0); +$info{'extents'}{'right'} = $internal_adjustment_factor * ($left_adjustment + $row->{'rgt'} + 0); + +$query = + "INSERT INTO rmgr_maps (id, site_id, area_id, width, depth) VALUES\n" . + " (1, $aicur_site_id, $aicur_area_id," . + ($info{'extents'}{'right'} - $info{'extents'}{'left'}) . ", " . + ($info{'extents'}{'bottom'} - $info{'extents'}{'top'}) . ")"; +query($db_handle, $query) || die("Unable to insert"); + +# Get list of units and positions +$query = "SELECT U.UnitID, U.UnitID as name,"; +$query .= " ($top_adjustment + M.Top) AS pt_t,"; +$query .= " ($left_adjustment + M.Left) AS pt_l,"; +$query .= " IIF(M.reverseWL, U.Depth, U.Width) AS Width,"; +$query .= " IIF(M.reverseWL, U.Width, U.Depth) AS Depth,"; +$query .= " M.reverseWL, U.Rented, U.Rentable"; +$query .= " FROM UnitInfo U INNER JOIN mapUnitsV2 M ON M.unitID = U.UnitID"; +$result = query($sdbh, $query); + +# Go through each one, calculating the map location +foreach $row (@$result) { + my $uid = $unit_map{$row->{'UnitID'}}; + + $query = # pt_bottom, pt_right, + "INSERT INTO rmgr_mapUnits (map_id, unit_id, + pt_top, pt_left, + transpose) VALUES + (" . join(", ", + 1, $uid, + $internal_adjustment_factor * ($row->{'pt_t'}), + $internal_adjustment_factor * ($row->{'pt_l'}), + $row->{'reverseWL'}) . ")"; + query($db_handle, $query) || die("Unable to insert"); +} + + +###################################################################### +###################################################################### +###################################################################### +###################################################################### +###################################################################### +###################################################################### +## +## TENANTS +## + + +###################################################################### +## Tenants + +$query = "SELECT * FROM TenantInfo WHERE FirstName <> 'POS' ORDER BY TenantID"; +$result = query($sdbh, $query); +$nrows = @$result; +print(" $nrows Tenants\n"); + +my %stmap = ( 1=>'AK', 14=>'ID', 48=>'WA' ); +my (%tenant_map); +foreach $row (@$result) { + $tenant_map{$row->{'TenantID'}} = { 'id' => ++$aicur_c_id }; + my $cid = $tenant_map{$row->{'TenantID'}}{'id'}; + + $query = "INSERT INTO rmgr_contacts + (`id`, `first_name`, `middle_name`, `last_name`, `display_name`, `id_num`, `id_state`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($cid, $row->{'FirstName'}, $row->{'MiddleName'}, $row->{'LastName'}, + "$row->{'LastName'}, $row->{'FirstName'}", + $row->{'IDNum'} || undef, $row->{'IDNum'} ? $stmap{$row->{'DLStateID'}} : undef) + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + if ($row->{'City'}) { + $query = "INSERT INTO rmgr_contactAddresses + (`id`, `address`, `city`, `state`, `postcode`, `country`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (++$aicur_ca_id, + #$row->{'HomeAddress'} + $row->{'HomeAddress'} . ($row->{'HomeAddr2'} ? "\n".$row->{'HomeAddr2'} : "") || undef, + $row->{'City'}, $stmap{$row->{'StateID'}}, $row->{'Zip'} || undef, 'USA') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO rmgr_contactMethods + (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES + ($cid, 'POST', $aicur_ca_id, 'HOME', 'PRIMARY')"; + query($db_handle, $query) || die("Unable to insert"); + } + + foreach ({'type' => 'LANDLINE', 'preference' => 'PRIMARY', 'phone' => $row->{'Phone'}}, + {'type' => 'LANDLINE', 'preference' => 'WORK', + 'phone' => $row->{'BusinessPhone'}, 'ext' => $row->{'BusinessExt'}}, + {'type' => 'FAX', 'preference' => 'PRIMARY', 'phone' => $row->{'FAX'}}, + {'type' => 'PAGER', 'preference' => 'PRIMARY', 'phone' => $row->{'Pager'}}, + {'type' => 'MOBILE', 'preference' => 'ALTERNATE', 'phone' => $row->{'CellPhone'}}) + { + if ($_->{'phone'}) { + $query = "INSERT INTO rmgr_contactPhones + (`id`, `type`, `phone`, `ext`) VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (++$aicur_cp_id, $_->{'type'}, $_->{'phone'}, $_->{'ext'}))) + . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO rmgr_contactMethods + (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($cid, 'PHONE', $aicur_cp_id, 'MAIN', $_->{'preference'}))) + . ")"; + query($db_handle, $query) || die("Unable to insert"); + } + } + + if ($row->{'Email'}) { + $query = "INSERT INTO rmgr_contactEmails + (`id`, `email`) VALUES + (".++$aicur_ce_id.", '$row->{'Email'}')"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO rmgr_contactMethods + (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUE + ($cid, 'EMAIL', $aicur_ce_id, 'MAIN', 'PRIMARY')"; + query($db_handle, $query) || die("Unable to insert"); + } + + next unless $row->{'AltFirstName'} || $row->{'AltLastName'} || $row->{'AltAddress'} || $row->{'AltPhone'}; + + $tenant_map{$row->{'TenantID'}}{'alt'} = ++$aicur_c_id; + $cid = $tenant_map{$row->{'TenantID'}}{'alt'}; + + $query = "INSERT INTO rmgr_contacts + (`id`, `first_name`, `middle_name`, `last_name`, `display_name`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($cid, + $row->{'AltFirstName'} || undef, + $row->{'AltMI'} || undef, + $row->{'AltLastName'} || undef, + ($row->{'AltLastName'} && $row->{'AltFirstName'} + ? "$row->{'AltLastName'}, $row->{'AltFirstName'}" + : ($row->{'AltLastName'} || $row->{'AltFirstName'} || ''))) + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + if ($row->{'AltCity'}) { + $query = "INSERT INTO rmgr_contactAddresses + (`id`, `address`, `city`, `state`, `postcode`, `country`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (++$aicur_ca_id, + $row->{'AltAddress'} . ($row->{'AltAddr2'} ? "\n".$row->{'AltAddr2'} : ""), + $row->{'AltCity'}, $stmap{$row->{'AltStateID'}}, $row->{'AltZip'}, 'USA') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO rmgr_contactMethods + (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES + ($cid, 'POST', $aicur_ca_id, 'MAIN', 'PRIMARY')"; + query($db_handle, $query) || die("Unable to insert"); + } + + if ($row->{'AltPhone'}) { + $query = "INSERT INTO rmgr_contactPhones + (`id`, `type`, `phone`, `ext`) VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (++$aicur_cp_id, 'LANDLINE', $row->{'AltPhone'}, undef) + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO rmgr_contactMethods + (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES + ($cid, 'PHONE', $aicur_cp_id, 'MAIN', 'PRIMARY')"; + query($db_handle, $query) || die("Unable to insert"); + } +} + + +###################################################################### +## Tenant Leases + +$query = "SELECT L.*, A.TenantID FROM TenantLedger L LEFT JOIN `Access` A ON A.LedgerID = L.LedgerID WHERE L.UnitID <> 'POS\$' ORDER BY L.LedgerID"; +$result = query($sdbh, $query); +$nrows = @$result; +print(" $nrows Tenant Ledgers\n"); +my (%ledger_map); +foreach $row (@$result) { + $ledger_map{$row->{'LedgerID'}} = ++$aicur_lease_id; + my $cid = $tenant_map{$row->{'TenantID'}}{'id'}; + my $uid = $unit_map{$row->{'UnitID'}}; + my $lid = $ledger_map{$row->{'LedgerID'}}; + + $query = "INSERT INTO rmgr_leases + (`id`, `number`, `lease_type_id`, `unit_id`, + `lease_date`, `movein_date`, + `moveout_date`, `close_date`, + `amount`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($lid, $row->{'LedgerID'}, $aicur_lease_type_id, $uid, + datefmt($row->{'DateIn'}), datefmt($row->{'DateIn'}), + datefmt($row->{'DateOut'}), datefmt($row->{'DateClosed'}), + $row->{'Rent'}) + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO rmgr_leaseContacts + (`lease_id`, `contact_id`, `type`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($lid, $cid, 'TENANT') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $cid = $tenant_map{$row->{'TenantID'}}{'alt'}; + next unless $cid; + + $query = "INSERT INTO rmgr_leaseContacts + (`lease_id`, `contact_id`, `type`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($lid, $cid, 'ALTERNATE') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); +} + + +###################################################################### +## Security Deposits + +$query = "SELECT L.LedgerID, L.UnitID, C.ChargeAmount FROM TenantLedger L INNER JOIN Charges C ON C.LedgerID = L.LedgerID WHERE L.UnitID <> 'POS\$' AND C.ChargeDescription = 'Security Deposit' ORDER BY UnitID"; +$result = query($sdbh, $query); +$nrows = @$result; +print(" $nrows Security Deposits\n"); + +foreach $row (@$result) { + my $uid = $unit_map{$row->{'UnitID'}}; + $query = "UPDATE rmgr_leases + SET deposit = $row->{'ChargeAmount'} + WHERE `number` = '$row->{'LedgerID'}'"; + query($db_handle, $query) || die("Unable to update"); +} + + +###################################################################### +###################################################################### +###################################################################### +###################################################################### +###################################################################### +###################################################################### +## +## TRANSACTIONS +## + +###################################################################### +## Charges + +$query = "SELECT * FROM Charges ORDER BY ChargeID"; +$result = query($sdbh, $query); +$nrows = @$result; +print(" $nrows Charges\n"); + +my %charge_type_map = ('Rent' => 2, 'Security Deposit' => 1, 'Late Fee' => 3); +my %charge_map; +foreach $row (@$result) { + $charge_map{$row->{'ChargeID'}} = ++$aicur_charge_id; + my $lid = $ledger_map{$row->{'LedgerID'}}; + my $chid = $charge_map{$row->{'ChargeID'}}; + + $query = "INSERT INTO rmgr_transactionCharges + (`id`, `type_id`, `lease_id`, + `charge_date`, `charge_to_date`, + `amount`, `tax`, `total`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($chid, $charge_type_map{$row->{'ChargeDescription'}}, $lid, + datefmt($row->{'ChargeDate'}), datefmt($row->{'EndDate'}), + $row->{'ChargeAmount'}, $row->{'TaxAmount'}, + $row->{'ChargeAmount'} + $row->{'TaxAmount'}, + "ChargeID #".$row->{'ChargeID'}) + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "UPDATE rmgr_transactionCharges"; + $query .= " SET due_date = DATE_ADD(charge_date, INTERVAL IF(type_id=2,10,0) DAY)"; + query($db_handle, $query) || die("Unable to update"); +} + + +###################################################################### +## Receipts + +$query = "SELECT * FROM Receipts ORDER BY ReceiptNum"; +$result = query($sdbh, $query); +$nrows = @$result; +print(" $nrows Receipts\n"); + +my %receipt_map; +foreach $row (@$result) { + $receipt_map{$row->{'ReceiptNum'}} = ++$aicur_receipt_id; + my $lid = $ledger_map{$row->{'LedgerID'}}; + my $rid = $receipt_map{$row->{'ReceiptNum'}}; + + $query = "INSERT INTO rmgr_transactionReceipts + (`id`, `stamp`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($rid, datefmt($row->{'ReceiptDate'}), + "ReceiptNum #".$row->{'ReceiptNum'}) + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); +} + +# $query = "SELECT * FROM Receipts R INNER JOIN Payments P ON P.ReceiptNum = R.ReceiptNum" . +# " WHERE P.PaymentDate <> R.ReceiptDate"; +# $result = query($sdbh, $query); +# $nrows = @$result; +# print(" $nrows Mismatches\n"); + +# foreach $row (@$result) { +# my @keys = qw(PaymentID P.ReceiptNum PaymentDate ReceiptDate); +# print("Payment Date Mismatch:\n"); +# print(" ", +# join("\n ", map({sprintf("%-12s => %s", $_, $row->{$_})} @keys)), +# "\n"); +# } + +###################################################################### +## Payments + +$query = "SELECT * FROM Payments ORDER BY PaymentID"; +$result = query($sdbh, $query); +$nrows = @$result; +print(" $nrows Payments\n"); + +my %payment_map; +foreach $row (@$result) { + $payment_map{$row->{'PaymentID'}} = ++$aicur_payment_id; + my $pid = $payment_map{$row->{'PaymentID'}}; + my $rid = $receipt_map{$row->{'ReceiptNum'}}; + my $chid = $charge_map{$row->{'ChargeID'}}; + + $query = "INSERT INTO rmgr_transactionPayments + (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($pid, $rid, + $row->{'PaymentDate'} =~ m%3/25/2009% ? 8 : $row->{'PaymentType'}, + $row->{'PaymentAmount'}, + "PaymentID #".$row->{'PaymentID'} . ($row->{'Memo'} ? "; ".$row->{'Memo'} : "")) + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO rmgr_transactionReconciliations + (`charge_id`, `receipt_id`, `amount`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($chid, $rid, $row->{'PaymentAmount'}) + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); +} + +__END__ + +###################################################################### +## Reconciliations + +# $query = "SELECT ReceiptNum, SUM(PaymentAmount) AS 'rTot'"; +# $query .= " FROM Payments GROUP BY ReceiptNum, ORDER BY ReceiptNum"; +$query = "SELECT ChargeID, ReceiptNum"; +$query .= " FROM Payments GROUP BY ChargeID, ReceiptNum ORDER BY ChargeID, ReceiptNum"; +$result = query($sdbh, $query); +$nrows = @$result; +print(" $nrows Reconciliations\n"); + +foreach $row (@$result) { + my $chid = $charge_map{$row->{'ChargeID'}}; + my $rid = $receipt_map{$row->{'ReceiptNum'}}; + + $query = "INSERT INTO rmgr_transactionReconciliations + (`charge_id`, `receipt_id`, `amount`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($chid, $rid, 0) + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); +} + +$query ="UPDATE rmgr_transactionReconciliations R + JOIN (SELECT P.receipt_id AS rid, + IF(COALESCE(Ch.total, 0)disconnect(); + From 0da1080b86437973717f53b462cb808a3b15be15 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 27 May 2009 19:47:48 +0000 Subject: [PATCH 008/717] Added database schema file. For the complete revision history of schema.sql, see branches/rent_manager_20090510/db path of the 'domain' repository git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@9 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 985 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 985 insertions(+) create mode 100644 db/schema.sql diff --git a/db/schema.sql b/db/schema.sql new file mode 100644 index 0000000..f38e1d9 --- /dev/null +++ b/db/schema.sql @@ -0,0 +1,985 @@ +-- +-- Database 'rentmgr' + +-- REVISIT : 20090511 +-- Perhaps "Rent Master" instead of "Rent Manager" ? +-- Perhaps "Property Master" ? +-- Perhaps better to market under several names: +-- "Self Storage Master", "Apartment Master", etc. + + +-- AP: +-- Originally authored for MySQL. +-- However, requirements to consider / keep in mind: +-- PostgreSQL: Don't want to be tied to ONLY MySQL. +-- SQLite: Will likely require a standalone option. + +-- REVISIT : 20090511 +-- I would like timestamps to note when things change, but +-- I don't think we can rely on the magic of MySQL to update +-- them, since we may be required to use other engines. +-- At the moment, I'll keep the MySQL statements, but we +-- may have to move this logic into the application :-/ + + +DROP DATABASE IF EXISTS `rentmgr`; +CREATE DATABASE `rentmgr`; +USE `rentmgr`; + + +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ## +-- ## SOFTWARE CONFIGURATION +-- ## + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_configSystem + +DROP TABLE IF EXISTS `rmgr_configSystem`; +CREATE TABLE `rmgr_configSystem` ( + `version_id` INT(10) UNSIGNED NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +LOCK TABLES `rmgr_configSystem` WRITE; +INSERT INTO `rmgr_configSystem` (`version_id`) + VALUES + (1); +UNLOCK TABLES; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_configVersions + +DROP TABLE IF EXISTS `rmgr_configVersions`; +CREATE TABLE `rmgr_configVersions` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `schema` INT UNSIGNED NOT NULL DEFAULT 1, -- DB REVISION + `major` INT UNSIGNED NOT NULL, + `minor` INT UNSIGNED NOT NULL, + `bugfix` INT UNSIGNED NOT NULL DEFAULT 0, + + -- REVISIT : 20090511 + -- Should we just use the 'notes' table instead? + `comment` VARCHAR(255) DEFAULT NULL, + `stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +LOCK TABLES `rmgr_configVersions` WRITE; +INSERT INTO `rmgr_configVersions` (`id`, `schema`, `major`, `minor`, `bugfix`, `stamp`, `comment`) + VALUES + (1, 1, 0, 1, 0, '2009-05-11 06:00', 'First revision'); +UNLOCK TABLES; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_configOptions + +DROP TABLE IF EXISTS `rmgr_configOptions`; +CREATE TABLE `rmgr_configOptions` ( + `name` VARCHAR(50) NOT NULL, + `value` VARCHAR(255) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + + +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ## +-- ## CONTACTS (PEOPLE and COMPANIES) +-- ## + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_contacts + +DROP TABLE IF EXISTS `rmgr_contacts`; +CREATE TABLE `rmgr_contacts` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `first_name` VARCHAR(255) DEFAULT NULL, + `middle_name` VARCHAR(255) DEFAULT NULL, + `last_name` VARCHAR(255) DEFAULT NULL, + `company_name` VARCHAR(255) DEFAULT NULL, + `display_name` VARCHAR(512) NOT NULL, + + -- FEDERAL ID, e.g. SSN or EIN + `id_federal` VARCHAR(16) DEFAULT NULL, + + -- STATE ID, e.g. drivers license + `id_num` VARCHAR(16) DEFAULT NULL, + `id_state` CHAR(2) DEFAULT NULL, + `id_exp` DATE DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_contactAddress + +DROP TABLE IF EXISTS `rmgr_contactAddresses`; +CREATE TABLE `rmgr_contactAddresses` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `address` VARCHAR(255) DEFAULT NULL, + `city` VARCHAR(255) DEFAULT NULL, + `state` CHAR(2) DEFAULT NULL, -- REVISIT : Convert to ENUM + `postcode` VARCHAR(12) DEFAULT NULL, + `country` VARCHAR(128) DEFAULT NULL, -- REVISIT : Convert to ENUM + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_contactPhones + +DROP TABLE IF EXISTS `rmgr_contactPhones`; +CREATE TABLE `rmgr_contactPhones` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `type` ENUM('LANDLINE', + 'MOBILE', + 'VIRTUAL', + 'PAGER', + 'FAX') + NOT NULL DEFAULT 'LANDLINE', + `phone` VARCHAR(18) NOT NULL, + `ext` VARCHAR(6) DEFAULT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + KEY `number_key` (`phone`), + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_contactEmails + +DROP TABLE IF EXISTS `rmgr_contactEmails`; +CREATE TABLE `rmgr_contactEmails` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `email` VARCHAR(128) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + KEY `email_key` (`email`), + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_contactMethods + +DROP TABLE IF EXISTS `rmgr_contactMethods`; +CREATE TABLE `rmgr_contactMethods` ( + `contact_id` INT(10) UNSIGNED NOT NULL, + `method` ENUM('POST', + 'PHONE', + 'EMAIL') + NOT NULL, + `method_id` INT(10) UNSIGNED NOT NULL, + `type` ENUM('MAIN', + 'HOME', + 'BUSINESS', + 'OTHER') + NOT NULL DEFAULT 'MAIN', + `preference` ENUM('PRIMARY', + 'WORK', + 'ALTERNATE', + 'EMERGENCY') + NOT NULL DEFAULT 'PRIMARY', +-- `position` TINYINT UNSIGNED NOT NULL DEFAULT 1, + + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`contact_id`, `method`, `method_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ## +-- ## GROUPS +-- ## + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_groups + +DROP TABLE IF EXISTS `rmgr_groups`; +CREATE TABLE `rmgr_groups` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + -- REVISIT : 20090511 + -- code may not be userful + `code` VARCHAR(12) NOT NULL, -- User style "id" + `name` VARCHAR(80) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_groupOptions + +DROP TABLE IF EXISTS `rmgr_groupOptions`; +CREATE TABLE `rmgr_groupOptions` ( + `group_id` INT(10) UNSIGNED NOT NULL, + `name` VARCHAR(50) NOT NULL, + `value` VARCHAR(255) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`group_id`, `name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_groupPermissions + +DROP TABLE IF EXISTS `rmgr_groupPermissions`; +CREATE TABLE `rmgr_groupPermissions` ( + `group_id` INT(10) UNSIGNED NOT NULL, + `name` CHAR(30) NOT NULL, + `access` ENUM('ALLOWED', + 'DENIED', + 'FORCED') + NOT NULL DEFAULT 'ALLOWED', + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`group_id`, `name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ## +-- ## USERS +-- ## + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_users + +DROP TABLE IF EXISTS `rmgr_users`; +CREATE TABLE `rmgr_users` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `code` VARCHAR(12) NOT NULL, -- User style "id" + + -- Login details. Passwords are not yet used (and so NULL). + `login` VARCHAR(30) NOT NULL, + `salt` CHAR(12) DEFAULT NULL, + `passhash` VARCHAR(255) DEFAULT NULL, + + -- Contact information for this user + `contact_id` INT(10) UNSIGNED NOT NULL, + + -- Specific comments + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_userOptions + +DROP TABLE IF EXISTS `rmgr_userOptions`; +CREATE TABLE `rmgr_userOptions` ( + `user_id` INT(10) UNSIGNED NOT NULL, + `name` VARCHAR(50) NOT NULL, + `value` VARCHAR(255) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`user_id`, `name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ## +-- ## SITES +-- ## + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_sites + +DROP TABLE IF EXISTS `rmgr_sites`; +CREATE TABLE `rmgr_sites` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `code` VARCHAR(12) NOT NULL, -- User style "id" + `name` VARCHAR(80) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + UNIQUE KEY `site_code` (`code`), + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_siteOptions + +DROP TABLE IF EXISTS `rmgr_siteOptions`; +CREATE TABLE `rmgr_siteOptions` ( + `site_id` INT(10) UNSIGNED NOT NULL, + `name` VARCHAR(50) NOT NULL, + `value` VARCHAR(255) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`site_id`, `name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_siteMemberships +-- +-- Which users are allowed to access which sites, +-- and under which set of group permissions (possibly multiple) + +-- SELECT U.id, P.name, MAX(P.access) +-- FROM rmgr_users U +-- LEFT JOIN rmgr_siteMembership M ON M.user_id = U.id +-- LEFT JOIN rmgr_groups G ON G.id = M.group_id +-- LEFT JOIN rmgr_groupPermissions P ON P.group_id = G.id +-- GROUP BY U.id, P.name + +DROP TABLE IF EXISTS `rmgr_siteMemberships`; +CREATE TABLE `rmgr_siteMemberships` ( + `site_id` INT(10) UNSIGNED NOT NULL, + `user_id` INT(10) UNSIGNED NOT NULL, + `group_id` INT(10) UNSIGNED NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`site_id`, `user_id`, `group_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_siteAreas + +DROP TABLE IF EXISTS `rmgr_siteAreas`; +CREATE TABLE `rmgr_siteAreas` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `site_id` INT(10) UNSIGNED NOT NULL, + `code` VARCHAR(12) NOT NULL, -- User style "id" + `name` VARCHAR(80) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ## +-- ## UNITS +-- ## + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_unitTypes + +DROP TABLE IF EXISTS `rmgr_unitTypes`; +CREATE TABLE `rmgr_unitTypes` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `code` VARCHAR(12) NOT NULL, -- User style "id" + `name` VARCHAR(80) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_unitSizes + +DROP TABLE IF EXISTS `rmgr_unitSizes`; +CREATE TABLE `rmgr_unitSizes` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `type_id` INT(10) UNSIGNED NOT NULL, + `code` VARCHAR(12) NOT NULL, -- User style "id" + `name` VARCHAR(80) NOT NULL, + `width` SMALLINT UNSIGNED NOT NULL, -- inches + `depth` SMALLINT UNSIGNED NOT NULL, -- inches + `height` SMALLINT UNSIGNED DEFAULT NULL, -- inches + `comment` VARCHAR(255) DEFAULT NULL, + + `deposit` FLOAT(12,2) DEFAULT NULL, + `amount` FLOAT(12,2) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_units + + +DROP TABLE IF EXISTS `rmgr_units`; +CREATE TABLE `rmgr_units` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `size_id` INT(10) UNSIGNED NOT NULL, + `code` VARCHAR(12) NOT NULL, -- User style "id" + `name` VARCHAR(80) NOT NULL, + + `status` ENUM('DELETED', + 'DAMAGED', + 'COMPANY', + 'UNAVAILABLE', + 'RESERVED', + 'DIRTY', + 'VACANT', + 'OCCUPIED', + 'LATE', -- NOT SURE + 'LOCKED', + 'LIENED') + NOT NULL DEFAULT 'VACANT', + + `sort_order` MEDIUMINT UNSIGNED NOT NULL, + `walk_order` MEDIUMINT UNSIGNED NOT NULL, + + `deposit` FLOAT(12,2) DEFAULT NULL, + `amount` FLOAT(12,2) DEFAULT NULL, + + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ## +-- ## ACTIONS +-- ## + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_actions + +DROP TABLE IF EXISTS `rmgr_actions`; +CREATE TABLE `rmgr_actions` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + `action` ENUM('LETTER', + 'GATELOCK', + 'OVERLOCK', + 'LIEN', + 'AUCTION') + NOT NULL, + + -- Which letter, or other specific action? + -- REVISIT : Are there other specific actions? + `item_id` INT(10) UNSIGNED DEFAULT NULL, + + `name` VARCHAR(80) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_lateSchedules + +DROP TABLE IF EXISTS `rmgr_lateSchedules`; +CREATE TABLE `rmgr_lateSchedules` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `code` VARCHAR(12) NOT NULL, -- User style "id" + + `name` VARCHAR(80) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_lateScheduleActions + +DROP TABLE IF EXISTS `rmgr_lateScheduleActions`; +CREATE TABLE `rmgr_lateScheduleActions` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + `late_schedule_id` INT(10) UNSIGNED DEFAULT NULL, + `days_past_due` SMALLINT NOT NULL, + `recurring` TINYINT DEFAULT 0, + `action_id` INT(10) UNSIGNED DEFAULT NULL, +-- REVISIT : 20090513 +-- Should we have a specific fee list, or just use account +-- `fee_id` INT(10) UNSIGNED DEFAULT NULL, + `account_id` INT(10) UNSIGNED DEFAULT NULL, + `amount` FLOAT(12,2) DEFAULT NULL, + `tax` FLOAT(12,2) DEFAULT NULL, + `name` VARCHAR(80) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ## +-- ## LEASES +-- ## + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_leaseTypes + +DROP TABLE IF EXISTS `rmgr_leaseTypes`; +CREATE TABLE `rmgr_leaseTypes` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `code` VARCHAR(12) NOT NULL, -- User style "id" + `name` VARCHAR(80) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_leases + +DROP TABLE IF EXISTS `rmgr_leases`; +CREATE TABLE `rmgr_leases` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + -- Allow user to specify their own lease numbers + -- If NULL, `id` will be used + `number` VARCHAR(20) DEFAULT NULL, + + `lease_type_id` INT(10) UNSIGNED NOT NULL, + `unit_id` INT(10) UNSIGNED NOT NULL, + `late_schedule_id` INT(10) UNSIGNED DEFAULT NULL, + + `lease_date` DATE NOT NULL, + `movein_planed_date` DATE DEFAULT NULL, + `movein_date` DATE DEFAULT NULL, + `moveout_date` DATE DEFAULT NULL, + `moveout_planed_date` DATE DEFAULT NULL, + `notice_given_date` DATE DEFAULT NULL, + `notice_received_date` DATE DEFAULT NULL, + `close_date` DATE DEFAULT NULL, + + `deposit` FLOAT(12,2) DEFAULT NULL, + `amount` FLOAT(12,2) DEFAULT NULL, + + `next_amount` FLOAT(12,2) DEFAULT NULL, + `next_amount_date` DATE DEFAULT NULL, + + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_leaseAltContacts + +DROP TABLE IF EXISTS `rmgr_leaseContacts`; +CREATE TABLE `rmgr_leaseContacts` ( + `lease_id` INT(10) UNSIGNED NOT NULL, + `contact_id` INT(10) UNSIGNED NOT NULL, + + -- What type of contact is this for the lease? + `type` ENUM('TENANT', -- PRIMARY TENANT + 'COTENANT', -- ADDITIONAL TENANT + 'ALTERNATE') -- ALTERNATE CONTACT ONLY + NOT NULL DEFAULT 'TENANT', + + -- If the tenant is removed as part of the lease + `active` TINYINT DEFAULT 1, + + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`lease_id`, `contact_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ## +-- ## TRANSACTIONS +-- ## + +-- # Charge +-- # - Issued against customer lease +-- # - associated with account (i.e. QuickBooks account / category) +-- # Receipt +-- # - Collections of payments paid at one time +-- # Payment +-- # - Credited towards customer (or lease?) +-- # - may be more than customer owes +-- # - cash/check/charge/ach/etc +-- # Reconciliation +-- # - Associates a payment with the charge +-- # - Indicates amount of credit towards charge +-- # - Payments may cover several charges +-- # - Several payments may cover the same charge + + +-- Which charges haven not been paid? +-- SELECT C.id AS cid, C.total AS total, COALESCE(SUM(R.amount),0) AS paid +-- FROM rmgr_transactionCharges C +-- LEFT JOIN rmgr_transactionReconciliations R ON R.charge_id = C.id +-- GROUP BY C.id +-- HAVING paid < C.total + +-- SELECT ChL.lid AS lid, U.name, C.display_name, +-- SUM(ChL.total) AS total, SUM(ChL.paid) AS paid, +-- SUM(ChL.total) - SUM(ChL.paid) AS owing +-- FROM (SELECT Ch.lease_id AS lid, Ch.total AS total, COALESCE(SUM(R.amount),0) AS paid +-- FROM rmgr_transactionCharges Ch +-- LEFT JOIN rmgr_transactionReconciliations R ON R.charge_id = Ch.id +-- WHERE Ch.due_date < NOW() +-- GROUP BY Ch.id +-- HAVING paid < Ch.total) ChL +-- LEFT JOIN rmgr_leases L ON L.id = ChL.lid +-- LEFT JOIN rmgr_leaseContacts Lc ON Lc.lease_id = L.id AND Lc.type = 'TENANT' +-- LEFT JOIN rmgr_contacts C ON C.id = Lc.contact_id +-- LEFT JOIN rmgr_units U ON U.id = L.unit_id + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_chargeTypes + +DROP TABLE IF EXISTS `rmgr_chargeTypes`; +CREATE TABLE `rmgr_chargeTypes` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + `name` VARCHAR(80) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + `account_id` INT(10) UNSIGNED NOT NULL, -- quickbooks tracking + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +LOCK TABLES `rmgr_chargeTypes` WRITE; +INSERT INTO `rmgr_chargeTypes` (`id`, `name`, `account_id`) + VALUES + (1, 'Security Deposit', 0), + (2, 'Rent', 0), + (3, 'Late Charge', 0); +UNLOCK TABLES; + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_paymentTypes + +DROP TABLE IF EXISTS `rmgr_paymentTypes`; +CREATE TABLE `rmgr_paymentTypes` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + `name` VARCHAR(80) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + `tillable` TINYINT(1) NOT NULL DEFAULT 1, -- Does manager collect by hand? + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +LOCK TABLES `rmgr_paymentTypes` WRITE; +INSERT INTO `rmgr_paymentTypes` (`id`, `name`, `tillable`) + VALUES + (1, 'Cash', 1), + (2, 'Check', 1), + (3, 'Money Order', 1), + (4, 'ACH', 0), + (5, 'Debit Card', 0), + (6, 'Credit Card', 0), + (7, 'Other Tillable', 1), + (8, 'Other Non-Tillable', 0); +UNLOCK TABLES; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_transactionCharges + +DROP TABLE IF EXISTS `rmgr_transactionCharges`; +CREATE TABLE `rmgr_transactionCharges` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + `type_id` INT(10) UNSIGNED NOT NULL, + `lease_id` INT(10) UNSIGNED NOT NULL, + `charge_date` DATE NOT NULL, + `charge_to_date` DATE NOT NULL, + `due_date` DATE DEFAULT NULL, + `amount` FLOAT(12,2) NOT NULL, + `tax` FLOAT(12,2) NOT NULL, + `total` FLOAT(12,2) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_transactionReceipts + +DROP TABLE IF EXISTS `rmgr_transactionReceipts`; +CREATE TABLE `rmgr_transactionReceipts` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + `stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_transactionPayments + +DROP TABLE IF EXISTS `rmgr_transactionPayments`; +CREATE TABLE `rmgr_transactionPayments` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + `receipt_id` INT(10) UNSIGNED NOT NULL, + `payment_type_id` INT(10) UNSIGNED NOT NULL, + `amount` FLOAT(12,2) NOT NULL, + + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_transactionReconciliations + +DROP TABLE IF EXISTS `rmgr_transactionReconciliations`; +CREATE TABLE `rmgr_transactionReconciliations` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `charge_id` INT(10) UNSIGNED NOT NULL, + -- REVISIT : 20090514 + -- THIS SHOULD BE RECEIPT_ID, NOT PAYMENT_ID, RIGHT?? + `receipt_id` INT(10) UNSIGNED NOT NULL, + `amount` FLOAT(12,2) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ## +-- ## SITE MAPS +-- ## + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_maps + + +DROP TABLE IF EXISTS `rmgr_maps`; +CREATE TABLE `rmgr_maps` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `site_id` INT(10) UNSIGNED NOT NULL, + `area_id` INT(10) UNSIGNED NOT NULL, + `name` VARCHAR(80) DEFAULT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + `width` SMALLINT UNSIGNED NOT NULL, -- inches + `depth` SMALLINT UNSIGNED NOT NULL, -- inches + + UNIQUE KEY `map_key` (`site_id`, `area_id`), + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_mapUnits + + +DROP TABLE IF EXISTS `rmgr_mapUnits`; +CREATE TABLE `rmgr_mapUnits` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `map_id` INT(10) UNSIGNED NOT NULL, + `unit_id` INT(10) UNSIGNED NOT NULL, + `pt_top` SMALLINT UNSIGNED NOT NULL, -- inches + `pt_left` SMALLINT UNSIGNED NOT NULL, -- inches +-- `pt_bottom` SMALLINT UNSIGNED NOT NULL, -- inches +-- `pt_right` SMALLINT UNSIGNED NOT NULL, -- inches + `transpose` SMALLINT UNSIGNED NOT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + + +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ## +-- ## NOTES +-- ## + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE rmgr_notes + +DROP TABLE IF EXISTS `rmgr_notes`; +CREATE TABLE `rmgr_notes` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + -- HISTORY is a note created by the system, when the + -- user changes a setting or field that has been + -- flagged for tracking. + -- USER is a manually entered note. + `type` ENUM('HISTORY', + 'USER') + NOT NULL DEFAULT 'USER', + + -- `item` references the object type, and `item_id` denotes + -- the specific object to which this note is attached + `item_id` INT(10) UNSIGNED NOT NULL, + `item` ENUM('OPTION', + 'UNIT_TYPE', + 'UNIT_SIZE', + 'UNIT', + 'CUSTOMER', + 'SITE', + 'SITE_AREA', + 'USER') -- etc, etc + NOT NULL, + + -- Text of the recorded note + `note` TEXT, + + -- User that made this note, or if HISTORY, made the change + `user_id` INT(10) UNSIGNED NOT NULL, + `stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + From 2d9a85ad82b163363eee8ab2dd97f4b8979ebdc4 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 27 May 2009 20:25:00 +0000 Subject: [PATCH 009/717] Changed table naming convention git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@10 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 258 +++++++++++++++++++++++++------------------------- 1 file changed, 129 insertions(+), 129 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index f38e1d9..f51eac3 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -1,5 +1,5 @@ -- --- Database 'rentmgr' +-- Database 'property_manager' -- REVISIT : 20090511 -- Perhaps "Rent Master" instead of "Rent Manager" ? @@ -22,9 +22,9 @@ -- may have to move this logic into the application :-/ -DROP DATABASE IF EXISTS `rentmgr`; -CREATE DATABASE `rentmgr`; -USE `rentmgr`; +DROP DATABASE IF EXISTS `property_manager`; +CREATE DATABASE `property_manager`; +USE `property_manager`; -- ###################################################################### @@ -43,16 +43,16 @@ USE `rentmgr`; -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_configSystem +-- TABLE pmgr_config_system -DROP TABLE IF EXISTS `rmgr_configSystem`; -CREATE TABLE `rmgr_configSystem` ( +DROP TABLE IF EXISTS `pmgr_config_system`; +CREATE TABLE `pmgr_config_system` ( `version_id` INT(10) UNSIGNED NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -LOCK TABLES `rmgr_configSystem` WRITE; -INSERT INTO `rmgr_configSystem` (`version_id`) +LOCK TABLES `pmgr_config_system` WRITE; +INSERT INTO `pmgr_config_system` (`version_id`) VALUES (1); UNLOCK TABLES; @@ -60,10 +60,10 @@ UNLOCK TABLES; -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_configVersions +-- TABLE pmgr_config_versions -DROP TABLE IF EXISTS `rmgr_configVersions`; -CREATE TABLE `rmgr_configVersions` ( +DROP TABLE IF EXISTS `pmgr_config_versions`; +CREATE TABLE `pmgr_config_versions` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `schema` INT UNSIGNED NOT NULL DEFAULT 1, -- DB REVISION `major` INT UNSIGNED NOT NULL, @@ -79,8 +79,8 @@ CREATE TABLE `rmgr_configVersions` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -LOCK TABLES `rmgr_configVersions` WRITE; -INSERT INTO `rmgr_configVersions` (`id`, `schema`, `major`, `minor`, `bugfix`, `stamp`, `comment`) +LOCK TABLES `pmgr_config_versions` WRITE; +INSERT INTO `pmgr_config_versions` (`id`, `schema`, `major`, `minor`, `bugfix`, `stamp`, `comment`) VALUES (1, 1, 0, 1, 0, '2009-05-11 06:00', 'First revision'); UNLOCK TABLES; @@ -88,10 +88,10 @@ UNLOCK TABLES; -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_configOptions +-- TABLE pmgr_config_options -DROP TABLE IF EXISTS `rmgr_configOptions`; -CREATE TABLE `rmgr_configOptions` ( +DROP TABLE IF EXISTS `pmgr_config_options`; +CREATE TABLE `pmgr_config_options` ( `name` VARCHAR(50) NOT NULL, `value` VARCHAR(255) NOT NULL, `comment` VARCHAR(255) DEFAULT NULL, @@ -118,10 +118,10 @@ CREATE TABLE `rmgr_configOptions` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_contacts +-- TABLE pmgr_contacts -DROP TABLE IF EXISTS `rmgr_contacts`; -CREATE TABLE `rmgr_contacts` ( +DROP TABLE IF EXISTS `pmgr_contacts`; +CREATE TABLE `pmgr_contacts` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `first_name` VARCHAR(255) DEFAULT NULL, `middle_name` VARCHAR(255) DEFAULT NULL, @@ -143,10 +143,10 @@ CREATE TABLE `rmgr_contacts` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_contactAddress +-- TABLE pmgr_contact_addresses -DROP TABLE IF EXISTS `rmgr_contactAddresses`; -CREATE TABLE `rmgr_contactAddresses` ( +DROP TABLE IF EXISTS `pmgr_contact_addresses`; +CREATE TABLE `pmgr_contact_addresses` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `address` VARCHAR(255) DEFAULT NULL, `city` VARCHAR(255) DEFAULT NULL, @@ -160,10 +160,10 @@ CREATE TABLE `rmgr_contactAddresses` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_contactPhones +-- TABLE pmgr_contact_phones -DROP TABLE IF EXISTS `rmgr_contactPhones`; -CREATE TABLE `rmgr_contactPhones` ( +DROP TABLE IF EXISTS `pmgr_contact_phones`; +CREATE TABLE `pmgr_contact_phones` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `type` ENUM('LANDLINE', 'MOBILE', @@ -182,10 +182,10 @@ CREATE TABLE `rmgr_contactPhones` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_contactEmails +-- TABLE pmgr_contact_emails -DROP TABLE IF EXISTS `rmgr_contactEmails`; -CREATE TABLE `rmgr_contactEmails` ( +DROP TABLE IF EXISTS `pmgr_contact_emails`; +CREATE TABLE `pmgr_contact_emails` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `email` VARCHAR(128) NOT NULL, `comment` VARCHAR(255) DEFAULT NULL, @@ -197,10 +197,10 @@ CREATE TABLE `rmgr_contactEmails` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_contactMethods +-- TABLE pmgr_contact_methods -DROP TABLE IF EXISTS `rmgr_contactMethods`; -CREATE TABLE `rmgr_contactMethods` ( +DROP TABLE IF EXISTS `pmgr_contact_methods`; +CREATE TABLE `pmgr_contact_methods` ( `contact_id` INT(10) UNSIGNED NOT NULL, `method` ENUM('POST', 'PHONE', @@ -242,10 +242,10 @@ CREATE TABLE `rmgr_contactMethods` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_groups +-- TABLE pmgr_groups -DROP TABLE IF EXISTS `rmgr_groups`; -CREATE TABLE `rmgr_groups` ( +DROP TABLE IF EXISTS `pmgr_groups`; +CREATE TABLE `pmgr_groups` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, -- REVISIT : 20090511 -- code may not be userful @@ -259,10 +259,10 @@ CREATE TABLE `rmgr_groups` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_groupOptions +-- TABLE pmgr_group_options -DROP TABLE IF EXISTS `rmgr_groupOptions`; -CREATE TABLE `rmgr_groupOptions` ( +DROP TABLE IF EXISTS `pmgr_group_options`; +CREATE TABLE `pmgr_group_options` ( `group_id` INT(10) UNSIGNED NOT NULL, `name` VARCHAR(50) NOT NULL, `value` VARCHAR(255) NOT NULL, @@ -274,10 +274,10 @@ CREATE TABLE `rmgr_groupOptions` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_groupPermissions +-- TABLE pmgr_group_permissions -DROP TABLE IF EXISTS `rmgr_groupPermissions`; -CREATE TABLE `rmgr_groupPermissions` ( +DROP TABLE IF EXISTS `pmgr_group_permissions`; +CREATE TABLE `pmgr_group_permissions` ( `group_id` INT(10) UNSIGNED NOT NULL, `name` CHAR(30) NOT NULL, `access` ENUM('ALLOWED', @@ -307,10 +307,10 @@ CREATE TABLE `rmgr_groupPermissions` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_users +-- TABLE pmgr_users -DROP TABLE IF EXISTS `rmgr_users`; -CREATE TABLE `rmgr_users` ( +DROP TABLE IF EXISTS `pmgr_users`; +CREATE TABLE `pmgr_users` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `code` VARCHAR(12) NOT NULL, -- User style "id" @@ -331,10 +331,10 @@ CREATE TABLE `rmgr_users` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_userOptions +-- TABLE pmgr_user_options -DROP TABLE IF EXISTS `rmgr_userOptions`; -CREATE TABLE `rmgr_userOptions` ( +DROP TABLE IF EXISTS `pmgr_user_options`; +CREATE TABLE `pmgr_user_options` ( `user_id` INT(10) UNSIGNED NOT NULL, `name` VARCHAR(50) NOT NULL, `value` VARCHAR(255) NOT NULL, @@ -361,10 +361,10 @@ CREATE TABLE `rmgr_userOptions` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_sites +-- TABLE pmgr_sites -DROP TABLE IF EXISTS `rmgr_sites`; -CREATE TABLE `rmgr_sites` ( +DROP TABLE IF EXISTS `pmgr_sites`; +CREATE TABLE `pmgr_sites` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `code` VARCHAR(12) NOT NULL, -- User style "id" `name` VARCHAR(80) NOT NULL, @@ -377,10 +377,10 @@ CREATE TABLE `rmgr_sites` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_siteOptions +-- TABLE pmgr_site_options -DROP TABLE IF EXISTS `rmgr_siteOptions`; -CREATE TABLE `rmgr_siteOptions` ( +DROP TABLE IF EXISTS `pmgr_site_options`; +CREATE TABLE `pmgr_site_options` ( `site_id` INT(10) UNSIGNED NOT NULL, `name` VARCHAR(50) NOT NULL, `value` VARCHAR(255) NOT NULL, @@ -392,20 +392,20 @@ CREATE TABLE `rmgr_siteOptions` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_siteMemberships +-- TABLE pmgr_site_memberships -- -- Which users are allowed to access which sites, -- and under which set of group permissions (possibly multiple) -- SELECT U.id, P.name, MAX(P.access) --- FROM rmgr_users U --- LEFT JOIN rmgr_siteMembership M ON M.user_id = U.id --- LEFT JOIN rmgr_groups G ON G.id = M.group_id --- LEFT JOIN rmgr_groupPermissions P ON P.group_id = G.id +-- FROM pmgr_users U +-- LEFT JOIN pmgr_site_membership M ON M.user_id = U.id +-- LEFT JOIN pmgr_groups G ON G.id = M.group_id +-- LEFT JOIN pmgr_group_permissions P ON P.group_id = G.id -- GROUP BY U.id, P.name -DROP TABLE IF EXISTS `rmgr_siteMemberships`; -CREATE TABLE `rmgr_siteMemberships` ( +DROP TABLE IF EXISTS `pmgr_site_memberships`; +CREATE TABLE `pmgr_site_memberships` ( `site_id` INT(10) UNSIGNED NOT NULL, `user_id` INT(10) UNSIGNED NOT NULL, `group_id` INT(10) UNSIGNED NOT NULL, @@ -417,10 +417,10 @@ CREATE TABLE `rmgr_siteMemberships` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_siteAreas +-- TABLE pmgr_site_areas -DROP TABLE IF EXISTS `rmgr_siteAreas`; -CREATE TABLE `rmgr_siteAreas` ( +DROP TABLE IF EXISTS `pmgr_site_areas`; +CREATE TABLE `pmgr_site_areas` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `site_id` INT(10) UNSIGNED NOT NULL, `code` VARCHAR(12) NOT NULL, -- User style "id" @@ -448,10 +448,10 @@ CREATE TABLE `rmgr_siteAreas` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_unitTypes +-- TABLE pmgr_unit_types -DROP TABLE IF EXISTS `rmgr_unitTypes`; -CREATE TABLE `rmgr_unitTypes` ( +DROP TABLE IF EXISTS `pmgr_unit_types`; +CREATE TABLE `pmgr_unit_types` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `code` VARCHAR(12) NOT NULL, -- User style "id" `name` VARCHAR(80) NOT NULL, @@ -464,10 +464,10 @@ CREATE TABLE `rmgr_unitTypes` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_unitSizes +-- TABLE pmgr_unit_sizes -DROP TABLE IF EXISTS `rmgr_unitSizes`; -CREATE TABLE `rmgr_unitSizes` ( +DROP TABLE IF EXISTS `pmgr_unit_sizes`; +CREATE TABLE `pmgr_unit_sizes` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `type_id` INT(10) UNSIGNED NOT NULL, `code` VARCHAR(12) NOT NULL, -- User style "id" @@ -486,11 +486,11 @@ CREATE TABLE `rmgr_unitSizes` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_units +-- TABLE pmgr_units -DROP TABLE IF EXISTS `rmgr_units`; -CREATE TABLE `rmgr_units` ( +DROP TABLE IF EXISTS `pmgr_units`; +CREATE TABLE `pmgr_units` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `size_id` INT(10) UNSIGNED NOT NULL, `code` VARCHAR(12) NOT NULL, -- User style "id" @@ -537,10 +537,10 @@ CREATE TABLE `rmgr_units` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_actions +-- TABLE pmgr_actions -DROP TABLE IF EXISTS `rmgr_actions`; -CREATE TABLE `rmgr_actions` ( +DROP TABLE IF EXISTS `pmgr_actions`; +CREATE TABLE `pmgr_actions` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `action` ENUM('LETTER', @@ -563,10 +563,10 @@ CREATE TABLE `rmgr_actions` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_lateSchedules +-- TABLE pmgr_late_schedules -DROP TABLE IF EXISTS `rmgr_lateSchedules`; -CREATE TABLE `rmgr_lateSchedules` ( +DROP TABLE IF EXISTS `pmgr_late_schedules`; +CREATE TABLE `pmgr_late_schedules` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `code` VARCHAR(12) NOT NULL, -- User style "id" @@ -581,10 +581,10 @@ CREATE TABLE `rmgr_lateSchedules` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_lateScheduleActions +-- TABLE pmgr_late_schedule_actions -DROP TABLE IF EXISTS `rmgr_lateScheduleActions`; -CREATE TABLE `rmgr_lateScheduleActions` ( +DROP TABLE IF EXISTS `pmgr_late_schedule_actions`; +CREATE TABLE `pmgr_late_schedule_actions` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `late_schedule_id` INT(10) UNSIGNED DEFAULT NULL, @@ -621,10 +621,10 @@ CREATE TABLE `rmgr_lateScheduleActions` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_leaseTypes +-- TABLE pmgr_lease_types -DROP TABLE IF EXISTS `rmgr_leaseTypes`; -CREATE TABLE `rmgr_leaseTypes` ( +DROP TABLE IF EXISTS `pmgr_lease_types`; +CREATE TABLE `pmgr_lease_types` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `code` VARCHAR(12) NOT NULL, -- User style "id" `name` VARCHAR(80) NOT NULL, @@ -636,10 +636,10 @@ CREATE TABLE `rmgr_leaseTypes` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_leases +-- TABLE pmgr_leases -DROP TABLE IF EXISTS `rmgr_leases`; -CREATE TABLE `rmgr_leases` ( +DROP TABLE IF EXISTS `pmgr_leases`; +CREATE TABLE `pmgr_leases` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, -- Allow user to specify their own lease numbers @@ -673,10 +673,10 @@ CREATE TABLE `rmgr_leases` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_leaseAltContacts +-- TABLE pmgr_lease_contacts -DROP TABLE IF EXISTS `rmgr_leaseContacts`; -CREATE TABLE `rmgr_leaseContacts` ( +DROP TABLE IF EXISTS `pmgr_lease_contacts`; +CREATE TABLE `pmgr_lease_contacts` ( `lease_id` INT(10) UNSIGNED NOT NULL, `contact_id` INT(10) UNSIGNED NOT NULL, @@ -727,8 +727,8 @@ CREATE TABLE `rmgr_leaseContacts` ( -- Which charges haven not been paid? -- SELECT C.id AS cid, C.total AS total, COALESCE(SUM(R.amount),0) AS paid --- FROM rmgr_transactionCharges C --- LEFT JOIN rmgr_transactionReconciliations R ON R.charge_id = C.id +-- FROM pmgr_transaction_charges C +-- LEFT JOIN pmgr_transaction_reconciliations R ON R.charge_id = C.id -- GROUP BY C.id -- HAVING paid < C.total @@ -736,23 +736,23 @@ CREATE TABLE `rmgr_leaseContacts` ( -- SUM(ChL.total) AS total, SUM(ChL.paid) AS paid, -- SUM(ChL.total) - SUM(ChL.paid) AS owing -- FROM (SELECT Ch.lease_id AS lid, Ch.total AS total, COALESCE(SUM(R.amount),0) AS paid --- FROM rmgr_transactionCharges Ch --- LEFT JOIN rmgr_transactionReconciliations R ON R.charge_id = Ch.id +-- FROM pmgr_transaction_charges Ch +-- LEFT JOIN pmgr_transaction_reconciliations R ON R.charge_id = Ch.id -- WHERE Ch.due_date < NOW() -- GROUP BY Ch.id -- HAVING paid < Ch.total) ChL --- LEFT JOIN rmgr_leases L ON L.id = ChL.lid --- LEFT JOIN rmgr_leaseContacts Lc ON Lc.lease_id = L.id AND Lc.type = 'TENANT' --- LEFT JOIN rmgr_contacts C ON C.id = Lc.contact_id --- LEFT JOIN rmgr_units U ON U.id = L.unit_id +-- LEFT JOIN pmgr_leases L ON L.id = ChL.lid +-- LEFT JOIN pmgr_lease_contacts Lc ON Lc.lease_id = L.id AND Lc.type = 'TENANT' +-- LEFT JOIN pmgr_contacts C ON C.id = Lc.contact_id +-- LEFT JOIN pmgr_units U ON U.id = L.unit_id -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_chargeTypes +-- TABLE pmgr_charge_types -DROP TABLE IF EXISTS `rmgr_chargeTypes`; -CREATE TABLE `rmgr_chargeTypes` ( +DROP TABLE IF EXISTS `pmgr_charge_types`; +CREATE TABLE `pmgr_charge_types` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `name` VARCHAR(80) NOT NULL, @@ -762,8 +762,8 @@ CREATE TABLE `rmgr_chargeTypes` ( PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -LOCK TABLES `rmgr_chargeTypes` WRITE; -INSERT INTO `rmgr_chargeTypes` (`id`, `name`, `account_id`) +LOCK TABLES `pmgr_charge_types` WRITE; +INSERT INTO `pmgr_charge_types` (`id`, `name`, `account_id`) VALUES (1, 'Security Deposit', 0), (2, 'Rent', 0), @@ -772,10 +772,10 @@ UNLOCK TABLES; -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_paymentTypes +-- TABLE pmgr_payment_types -DROP TABLE IF EXISTS `rmgr_paymentTypes`; -CREATE TABLE `rmgr_paymentTypes` ( +DROP TABLE IF EXISTS `pmgr_payment_types`; +CREATE TABLE `pmgr_payment_types` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `name` VARCHAR(80) NOT NULL, @@ -785,8 +785,8 @@ CREATE TABLE `rmgr_paymentTypes` ( PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -LOCK TABLES `rmgr_paymentTypes` WRITE; -INSERT INTO `rmgr_paymentTypes` (`id`, `name`, `tillable`) +LOCK TABLES `pmgr_payment_types` WRITE; +INSERT INTO `pmgr_payment_types` (`id`, `name`, `tillable`) VALUES (1, 'Cash', 1), (2, 'Check', 1), @@ -801,10 +801,10 @@ UNLOCK TABLES; -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_transactionCharges +-- TABLE pmgr_transaction_charges -DROP TABLE IF EXISTS `rmgr_transactionCharges`; -CREATE TABLE `rmgr_transactionCharges` ( +DROP TABLE IF EXISTS `pmgr_transaction_charges`; +CREATE TABLE `pmgr_transaction_charges` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `type_id` INT(10) UNSIGNED NOT NULL, @@ -823,10 +823,10 @@ CREATE TABLE `rmgr_transactionCharges` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_transactionReceipts +-- TABLE pmgr_transaction_receipts -DROP TABLE IF EXISTS `rmgr_transactionReceipts`; -CREATE TABLE `rmgr_transactionReceipts` ( +DROP TABLE IF EXISTS `pmgr_transaction_receipts`; +CREATE TABLE `pmgr_transaction_receipts` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, @@ -839,10 +839,10 @@ CREATE TABLE `rmgr_transactionReceipts` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_transactionPayments +-- TABLE pmgr_transaction_payments -DROP TABLE IF EXISTS `rmgr_transactionPayments`; -CREATE TABLE `rmgr_transactionPayments` ( +DROP TABLE IF EXISTS `pmgr_transaction_payments`; +CREATE TABLE `pmgr_transaction_payments` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `receipt_id` INT(10) UNSIGNED NOT NULL, @@ -857,10 +857,10 @@ CREATE TABLE `rmgr_transactionPayments` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_transactionReconciliations +-- TABLE pmgr_transaction_reconciliations -DROP TABLE IF EXISTS `rmgr_transactionReconciliations`; -CREATE TABLE `rmgr_transactionReconciliations` ( +DROP TABLE IF EXISTS `pmgr_transaction_reconciliations`; +CREATE TABLE `pmgr_transaction_reconciliations` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `charge_id` INT(10) UNSIGNED NOT NULL, -- REVISIT : 20090514 @@ -887,11 +887,11 @@ CREATE TABLE `rmgr_transactionReconciliations` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_maps +-- TABLE pmgr_maps -DROP TABLE IF EXISTS `rmgr_maps`; -CREATE TABLE `rmgr_maps` ( +DROP TABLE IF EXISTS `pmgr_maps`; +CREATE TABLE `pmgr_maps` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `site_id` INT(10) UNSIGNED NOT NULL, `area_id` INT(10) UNSIGNED NOT NULL, @@ -908,11 +908,11 @@ CREATE TABLE `rmgr_maps` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_mapUnits +-- TABLE pmgr_map_units -DROP TABLE IF EXISTS `rmgr_mapUnits`; -CREATE TABLE `rmgr_mapUnits` ( +DROP TABLE IF EXISTS `pmgr_map_units`; +CREATE TABLE `pmgr_map_units` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `map_id` INT(10) UNSIGNED NOT NULL, `unit_id` INT(10) UNSIGNED NOT NULL, @@ -944,10 +944,10 @@ CREATE TABLE `rmgr_mapUnits` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE rmgr_notes +-- TABLE pmgr_notes -DROP TABLE IF EXISTS `rmgr_notes`; -CREATE TABLE `rmgr_notes` ( +DROP TABLE IF EXISTS `pmgr_notes`; +CREATE TABLE `pmgr_notes` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, -- HISTORY is a note created by the system, when the From eeb87758208738d09720587ad0559ff3d537238e Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 27 May 2009 20:32:31 +0000 Subject: [PATCH 010/717] Further changes to the table naming conventions to match expectations of CakePHP git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@11 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 58 +++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index f51eac3..1a636dd 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -197,10 +197,10 @@ CREATE TABLE `pmgr_contact_emails` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE pmgr_contact_methods +-- TABLE pmgr_contacts_methods -DROP TABLE IF EXISTS `pmgr_contact_methods`; -CREATE TABLE `pmgr_contact_methods` ( +DROP TABLE IF EXISTS `pmgr_contacts_methods`; +CREATE TABLE `pmgr_contacts_methods` ( `contact_id` INT(10) UNSIGNED NOT NULL, `method` ENUM('POST', 'PHONE', @@ -400,7 +400,7 @@ CREATE TABLE `pmgr_site_options` ( -- SELECT U.id, P.name, MAX(P.access) -- FROM pmgr_users U -- LEFT JOIN pmgr_site_membership M ON M.user_id = U.id --- LEFT JOIN pmgr_groups G ON G.id = M.group_id +-- LEFT JOIN pmgr_groups G ON G.id = M.group_id -- LEFT JOIN pmgr_group_permissions P ON P.group_id = G.id -- GROUP BY U.id, P.name @@ -581,10 +581,10 @@ CREATE TABLE `pmgr_late_schedules` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE pmgr_late_schedule_actions +-- TABLE pmgr_actions_late_schedules -DROP TABLE IF EXISTS `pmgr_late_schedule_actions`; -CREATE TABLE `pmgr_late_schedule_actions` ( +DROP TABLE IF EXISTS `pmgr_actions_late_schedules`; +CREATE TABLE `pmgr_actions_late_schedules` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `late_schedule_id` INT(10) UNSIGNED DEFAULT NULL, @@ -673,10 +673,10 @@ CREATE TABLE `pmgr_leases` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE pmgr_lease_contacts +-- TABLE pmgr_contacts_leases -DROP TABLE IF EXISTS `pmgr_lease_contacts`; -CREATE TABLE `pmgr_lease_contacts` ( +DROP TABLE IF EXISTS `pmgr_contacts_leases`; +CREATE TABLE `pmgr_contacts_leases` ( `lease_id` INT(10) UNSIGNED NOT NULL, `contact_id` INT(10) UNSIGNED NOT NULL, @@ -727,8 +727,8 @@ CREATE TABLE `pmgr_lease_contacts` ( -- Which charges haven not been paid? -- SELECT C.id AS cid, C.total AS total, COALESCE(SUM(R.amount),0) AS paid --- FROM pmgr_transaction_charges C --- LEFT JOIN pmgr_transaction_reconciliations R ON R.charge_id = C.id +-- FROM pmgr_charges C +-- LEFT JOIN pmgr_charges_receipts R ON R.charge_id = C.id -- GROUP BY C.id -- HAVING paid < C.total @@ -736,8 +736,8 @@ CREATE TABLE `pmgr_lease_contacts` ( -- SUM(ChL.total) AS total, SUM(ChL.paid) AS paid, -- SUM(ChL.total) - SUM(ChL.paid) AS owing -- FROM (SELECT Ch.lease_id AS lid, Ch.total AS total, COALESCE(SUM(R.amount),0) AS paid --- FROM pmgr_transaction_charges Ch --- LEFT JOIN pmgr_transaction_reconciliations R ON R.charge_id = Ch.id +-- FROM pmgr_charges Ch +-- LEFT JOIN pmgr_charges_receipts R ON R.charge_id = Ch.id -- WHERE Ch.due_date < NOW() -- GROUP BY Ch.id -- HAVING paid < Ch.total) ChL @@ -801,10 +801,10 @@ UNLOCK TABLES; -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE pmgr_transaction_charges +-- TABLE pmgr_charges -DROP TABLE IF EXISTS `pmgr_transaction_charges`; -CREATE TABLE `pmgr_transaction_charges` ( +DROP TABLE IF EXISTS `pmgr_charges`; +CREATE TABLE `pmgr_charges` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `type_id` INT(10) UNSIGNED NOT NULL, @@ -823,10 +823,10 @@ CREATE TABLE `pmgr_transaction_charges` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE pmgr_transaction_receipts +-- TABLE pmgr_receipts -DROP TABLE IF EXISTS `pmgr_transaction_receipts`; -CREATE TABLE `pmgr_transaction_receipts` ( +DROP TABLE IF EXISTS `pmgr_receipts`; +CREATE TABLE `pmgr_receipts` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, @@ -839,10 +839,10 @@ CREATE TABLE `pmgr_transaction_receipts` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE pmgr_transaction_payments +-- TABLE pmgr_payments -DROP TABLE IF EXISTS `pmgr_transaction_payments`; -CREATE TABLE `pmgr_transaction_payments` ( +DROP TABLE IF EXISTS `pmgr_payments`; +CREATE TABLE `pmgr_payments` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `receipt_id` INT(10) UNSIGNED NOT NULL, @@ -857,10 +857,10 @@ CREATE TABLE `pmgr_transaction_payments` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE pmgr_transaction_reconciliations +-- TABLE pmgr_charges_receipts -DROP TABLE IF EXISTS `pmgr_transaction_reconciliations`; -CREATE TABLE `pmgr_transaction_reconciliations` ( +DROP TABLE IF EXISTS `pmgr_charges_receipts`; +CREATE TABLE `pmgr_charges_receipts` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `charge_id` INT(10) UNSIGNED NOT NULL, -- REVISIT : 20090514 @@ -908,11 +908,11 @@ CREATE TABLE `pmgr_maps` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE pmgr_map_units +-- TABLE pmgr_maps_units -DROP TABLE IF EXISTS `pmgr_map_units`; -CREATE TABLE `pmgr_map_units` ( +DROP TABLE IF EXISTS `pmgr_maps_units`; +CREATE TABLE `pmgr_maps_units` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `map_id` INT(10) UNSIGNED NOT NULL, `unit_id` INT(10) UNSIGNED NOT NULL, From 76a06d165511470ab6b8de40397ef98afe43af00 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 27 May 2009 20:49:54 +0000 Subject: [PATCH 011/717] Further naming conventions to match CakePHP git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@12 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index 1a636dd..75fecfc 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -47,7 +47,7 @@ USE `property_manager`; DROP TABLE IF EXISTS `pmgr_config_system`; CREATE TABLE `pmgr_config_system` ( - `version_id` INT(10) UNSIGNED NOT NULL + `config_version_id` INT(10) UNSIGNED NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8; @@ -469,7 +469,7 @@ CREATE TABLE `pmgr_unit_types` ( DROP TABLE IF EXISTS `pmgr_unit_sizes`; CREATE TABLE `pmgr_unit_sizes` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `type_id` INT(10) UNSIGNED NOT NULL, + `unit_type_id` INT(10) UNSIGNED NOT NULL, `code` VARCHAR(12) NOT NULL, -- User style "id" `name` VARCHAR(80) NOT NULL, `width` SMALLINT UNSIGNED NOT NULL, -- inches @@ -492,7 +492,7 @@ CREATE TABLE `pmgr_unit_sizes` ( DROP TABLE IF EXISTS `pmgr_units`; CREATE TABLE `pmgr_units` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `size_id` INT(10) UNSIGNED NOT NULL, + `unit_size_id` INT(10) UNSIGNED NOT NULL, `code` VARCHAR(12) NOT NULL, -- User style "id" `name` VARCHAR(80) NOT NULL, @@ -807,7 +807,7 @@ DROP TABLE IF EXISTS `pmgr_charges`; CREATE TABLE `pmgr_charges` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `type_id` INT(10) UNSIGNED NOT NULL, + `charge_type_id` INT(10) UNSIGNED NOT NULL, `lease_id` INT(10) UNSIGNED NOT NULL, `charge_date` DATE NOT NULL, `charge_to_date` DATE NOT NULL, @@ -894,14 +894,14 @@ DROP TABLE IF EXISTS `pmgr_maps`; CREATE TABLE `pmgr_maps` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `site_id` INT(10) UNSIGNED NOT NULL, - `area_id` INT(10) UNSIGNED NOT NULL, + `site_area_id` INT(10) UNSIGNED NOT NULL, `name` VARCHAR(80) DEFAULT NULL, `comment` VARCHAR(255) DEFAULT NULL, `width` SMALLINT UNSIGNED NOT NULL, -- inches `depth` SMALLINT UNSIGNED NOT NULL, -- inches - UNIQUE KEY `map_key` (`site_id`, `area_id`), + UNIQUE KEY `map_key` (`site_id`, `site_area_id`), PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; From 6b53d8a25aa0079f12645fbb045e9cce95c447fe Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 27 May 2009 20:52:32 +0000 Subject: [PATCH 012/717] Omission bug on last checkin git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@13 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/schema.sql b/db/schema.sql index 75fecfc..3b710be 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -52,7 +52,7 @@ CREATE TABLE `pmgr_config_system` ( LOCK TABLES `pmgr_config_system` WRITE; -INSERT INTO `pmgr_config_system` (`version_id`) +INSERT INTO `pmgr_config_system` (`config_version_id`) VALUES (1); UNLOCK TABLES; From f4007a026957b6cf5c737c9938719489f12964a4 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 27 May 2009 20:54:14 +0000 Subject: [PATCH 013/717] Adjusted database details and sitelink conversion script to go along with new schema naming convention changes git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@14 97e9348a-65ac-dc4b-aefc-98561f571b83 --- .../{sitelink2rmgr.pl => sitelink2pmgr.pl} | 152 +++++++++--------- site/config/database.php | 2 +- 2 files changed, 78 insertions(+), 76 deletions(-) rename scripts/{sitelink2rmgr.pl => sitelink2pmgr.pl} (86%) diff --git a/scripts/sitelink2rmgr.pl b/scripts/sitelink2pmgr.pl similarity index 86% rename from scripts/sitelink2rmgr.pl rename to scripts/sitelink2pmgr.pl index 67b6863..0a435a1 100644 --- a/scripts/sitelink2rmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -21,7 +21,9 @@ my $sdbh = DBI->connect("dbi:ADO:$sdsn", undef, undef, {PrintError => 1, RaiseError => 1}); # Connect to the database. -my($hostname, $database, $user, $password) = ('localhost', 'rentmgr', 'root', 'mysql97312519'); +my($hostname, $database, $user, $password) = ('localhost', + 'property_manager', + 'pmgr', 'pmgruser'); my $db_handle = DBI->connect("DBI:mysql:database=$database;host=$hostname", $user, $password, {'RaiseError' => 1}); @@ -46,140 +48,140 @@ while () { close(SCHEMA); ++$aicur_c_id; -$query = "INSERT INTO rmgr_contacts +$query = "INSERT INTO pmgr_contacts (`id`, `first_name`, `middle_name`, `last_name`, `display_name`) VALUES ($aicur_c_id, 'Abijah', 'M', 'Perkins', 'Perkins, Abijah')"; query($db_handle, $query) || die("Unable to insert"); ++$aicur_ca_id; -$query = "INSERT INTO rmgr_contactAddresses +$query = "INSERT INTO pmgr_contact_addresses (`id`, `address`, `city`, `state`, `postcode`, `country`) VALUES ($aicur_ca_id, '1324 N Liberty Lake Rd\nPMB 263', 'Liberty Lake', 'WA', '99019', 'USA')"; query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO rmgr_contactMethods +$query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES ($aicur_c_id, 'POST', $aicur_ca_id, 'MAIN', 'PRIMARY')"; query($db_handle, $query) || die("Unable to insert"); ++$aicur_ca_id; -$query = "INSERT INTO rmgr_contactAddresses +$query = "INSERT INTO pmgr_contact_addresses (`id`, `address`, `city`, `state`, `postcode`, `country`) VALUES ($aicur_ca_id, '5221 W Myrtlewood Ct', 'Spokane', 'WA', '99208', 'USA')"; query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO rmgr_contactMethods +$query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES ($aicur_c_id, 'POST', $aicur_ca_id, 'HOME', 'ALTERNATE')"; query($db_handle, $query) || die("Unable to insert"); ++$aicur_ca_id; -$query = "INSERT INTO rmgr_contactAddresses +$query = "INSERT INTO pmgr_contact_addresses (`id`, `address`, `city`, `state`, `postcode`, `country`) VALUES ($aicur_ca_id, 'PO Box 69', 'Granger', 'WA', '98932', 'USA')"; query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO rmgr_contactMethods +$query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES ($aicur_c_id, 'POST', $aicur_ca_id, 'HOME', 'ALTERNATE')"; query($db_handle, $query) || die("Unable to insert"); ++$aicur_cp_id; -$query = "INSERT INTO rmgr_contactPhones +$query = "INSERT INTO pmgr_contact_phones (`id`, `type`, `phone`) VALUES ($aicur_cp_id, 'MOBILE', '5098445573')"; query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO rmgr_contactMethods +$query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES ($aicur_c_id, 'PHONE', $aicur_cp_id, 'MAIN', 'PRIMARY')"; query($db_handle, $query) || die("Unable to insert"); ++$aicur_cp_id; -$query = "INSERT INTO rmgr_contactPhones +$query = "INSERT INTO pmgr_contact_phones (`id`, `type`, `phone`) VALUES ($aicur_cp_id, 'MOBILE', '5098445973')"; query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO rmgr_contactMethods +$query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES ($aicur_c_id, 'PHONE', $aicur_cp_id, 'MAIN', 'ALTERNATE')"; query($db_handle, $query) || die("Unable to insert"); ++$aicur_cp_id; -$query = "INSERT INTO rmgr_contactPhones +$query = "INSERT INTO pmgr_contact_phones (`id`, `type`, `phone`) VALUES ($aicur_cp_id, 'VIRTUAL', '5095901112')"; query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO rmgr_contactMethods +$query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES ($aicur_c_id, 'PHONE', $aicur_cp_id, 'BUSINESS', 'WORK')"; query($db_handle, $query) || die("Unable to insert"); ++$aicur_cp_id; -$query = "INSERT INTO rmgr_contactPhones +$query = "INSERT INTO pmgr_contact_phones (`id`, `type`, `phone`) VALUES ($aicur_cp_id, 'LANDLINE', '5098541491')"; query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO rmgr_contactMethods +$query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES ($aicur_c_id, 'PHONE', $aicur_cp_id, 'HOME', 'ALTERNATE')"; query($db_handle, $query) || die("Unable to insert"); ++$aicur_cp_id; -$query = "INSERT INTO rmgr_contactPhones +$query = "INSERT INTO pmgr_contact_phones (`id`, `type`, `phone`) VALUES ($aicur_cp_id, 'VIRTUAL', '8774488664')"; query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO rmgr_contactMethods +$query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES ($aicur_c_id, 'PHONE', $aicur_cp_id, 'BUSINESS', 'WORK')"; query($db_handle, $query) || die("Unable to insert"); ++$aicur_cp_id; -$query = "INSERT INTO rmgr_contactPhones +$query = "INSERT INTO pmgr_contact_phones (`id`, `type`, `phone`) VALUES ($aicur_cp_id, 'FAX', '8662960131')"; query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO rmgr_contactMethods +$query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES ($aicur_c_id, 'PHONE', $aicur_cp_id, 'BUSINESS', 'WORK')"; query($db_handle, $query) || die("Unable to insert"); ++$aicur_ce_id; -$query = "INSERT INTO rmgr_contactEmails +$query = "INSERT INTO pmgr_contact_emails (`id`, `email`) VALUES ($aicur_ce_id, 'abijah\@PerkinsHouse.com')"; query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO rmgr_contactMethods +$query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES ($aicur_c_id, 'EMAIL', $aicur_ce_id, 'HOME', 'PRIMARY')"; query($db_handle, $query) || die("Unable to insert"); ++$aicur_ce_id; -$query = "INSERT INTO rmgr_contactEmails +$query = "INSERT INTO pmgr_contact_emails (`id`, `email`) VALUES ($aicur_ce_id, 'abijah\@PerkinsREI.com')"; query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO rmgr_contactMethods +$query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES ($aicur_c_id, 'EMAIL', $aicur_ce_id, 'HOME', 'WORK')"; query($db_handle, $query) || die("Unable to insert"); ++$aicur_ce_id; -$query = "INSERT INTO rmgr_contactEmails +$query = "INSERT INTO pmgr_contact_emails (`id`, `email`) VALUES ($aicur_ce_id, 'abijah\@ValleyStorage.com')"; query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO rmgr_contactMethods +$query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES ($aicur_c_id, 'EMAIL', $aicur_ce_id, 'BUSINESS', 'WORK')"; query($db_handle, $query) || die("Unable to insert"); ++$aicur_g_id; -$query = "INSERT INTO rmgr_groups +$query = "INSERT INTO pmgr_groups (`id`, `code`, `name`) VALUES ($aicur_g_id, 'Owner', 'Owner Group')"; query($db_handle, $query) || die("Unable to insert"); ++$aicur_gp_id; -$query = "INSERT INTO rmgr_groupPermissions +$query = "INSERT INTO pmgr_group_permissions (`group_id`, `name`, `access`) VALUES ($aicur_gp_id, 'EVERYTHING', 'FORCED')"; @@ -187,7 +189,7 @@ $query = "INSERT INTO rmgr_groupPermissions ++$aicur_user_id; -$query = "INSERT INTO rmgr_users +$query = "INSERT INTO pmgr_users (`id`, `code`, `login`, `contact_id`) VALUES ($aicur_user_id, 'AP', 'abijah', $aicur_c_id)"; @@ -195,27 +197,27 @@ $query = "INSERT INTO rmgr_users ++$aicur_site_id; -$query = "INSERT INTO rmgr_sites +$query = "INSERT INTO pmgr_sites (`id`, `code`, `name`) VALUES ($aicur_site_id, 'VSS', 'Valley Storage')"; query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO rmgr_siteMemberships +$query = "INSERT INTO pmgr_site_memberships (`site_id`, `user_id`, `group_id`) VALUES ($aicur_site_id, $aicur_user_id, $aicur_g_id)"; query($db_handle, $query) || die("Unable to insert"); ++$aicur_area_id; -$query = "INSERT INTO rmgr_siteAreas +$query = "INSERT INTO pmgr_site_areas (`id`, `site_id`, `code`, `name`) VALUES ($aicur_area_id, $aicur_site_id, 'Main', 'Main Facility Area')"; query($db_handle, $query) || die("Unable to insert"); ++$aicur_lease_type_id; -$query = "INSERT INTO rmgr_leaseTypes +$query = "INSERT INTO pmgr_lease_types (`id`, `code`, `name`) VALUES ($aicur_lease_type_id, 'SL', 'Storage Lease')"; @@ -286,7 +288,7 @@ $nrows = @$result; print(" $nrows Unit Types\n"); foreach $row (@$result) { - $query = "INSERT INTO rmgr_unitTypes + $query = "INSERT INTO pmgr_unit_types (`id`, `code`, `name`) VALUES ($row->{'TypeID'}, 'xxx', '$row->{'UnitType'}')"; @@ -311,8 +313,8 @@ foreach $row (@$result) { $unit_size_map{$sz}{'dep'} = $row->{'StdSecDep'}; my $szid = $unit_size_map{$sz}{'id'}; - $query = "INSERT INTO rmgr_unitSizes - (`id`, `type_id`, `code`, `name`, `width`, `depth`, + $query = "INSERT INTO pmgr_unit_sizes + (`id`, `unit_type_id`, `code`, `name`, `width`, `depth`, `deposit`, `amount`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} @@ -335,8 +337,8 @@ foreach $row (@$result) { $unit_map{$row->{'UnitID'}} = ++$aicur_unit_id; my $uid = $unit_map{$row->{'UnitID'}}; - $query = "INSERT INTO rmgr_units - (`id`, `size_id`, `code`, `name`, + $query = "INSERT INTO pmgr_units + (`id`, `unit_size_id`, `code`, `name`, `status`, `sort_order`, `walk_order`, `deposit`, `amount`) VALUES (" . @@ -374,7 +376,7 @@ $info{'extents'}{'bottom'} = $internal_adjustment_factor * ($top_adjustment + $ $info{'extents'}{'right'} = $internal_adjustment_factor * ($left_adjustment + $row->{'rgt'} + 0); $query = - "INSERT INTO rmgr_maps (id, site_id, area_id, width, depth) VALUES\n" . + "INSERT INTO pmgr_maps (id, site_id, site_area_id, width, depth) VALUES\n" . " (1, $aicur_site_id, $aicur_area_id," . ($info{'extents'}{'right'} - $info{'extents'}{'left'}) . ", " . ($info{'extents'}{'bottom'} - $info{'extents'}{'top'}) . ")"; @@ -395,9 +397,9 @@ foreach $row (@$result) { my $uid = $unit_map{$row->{'UnitID'}}; $query = # pt_bottom, pt_right, - "INSERT INTO rmgr_mapUnits (map_id, unit_id, - pt_top, pt_left, - transpose) VALUES + "INSERT INTO pmgr_maps_units (map_id, unit_id, + pt_top, pt_left, + transpose) VALUES (" . join(", ", 1, $uid, $internal_adjustment_factor * ($row->{'pt_t'}), @@ -432,7 +434,7 @@ foreach $row (@$result) { $tenant_map{$row->{'TenantID'}} = { 'id' => ++$aicur_c_id }; my $cid = $tenant_map{$row->{'TenantID'}}{'id'}; - $query = "INSERT INTO rmgr_contacts + $query = "INSERT INTO pmgr_contacts (`id`, `first_name`, `middle_name`, `last_name`, `display_name`, `id_num`, `id_state`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} @@ -443,7 +445,7 @@ foreach $row (@$result) { query($db_handle, $query) || die("Unable to insert"); if ($row->{'City'}) { - $query = "INSERT INTO rmgr_contactAddresses + $query = "INSERT INTO pmgr_contact_addresses (`id`, `address`, `city`, `state`, `postcode`, `country`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} @@ -454,7 +456,7 @@ foreach $row (@$result) { )) . ")"; query($db_handle, $query) || die("Unable to insert"); - $query = "INSERT INTO rmgr_contactMethods + $query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES ($cid, 'POST', $aicur_ca_id, 'HOME', 'PRIMARY')"; query($db_handle, $query) || die("Unable to insert"); @@ -468,14 +470,14 @@ foreach $row (@$result) { {'type' => 'MOBILE', 'preference' => 'ALTERNATE', 'phone' => $row->{'CellPhone'}}) { if ($_->{'phone'}) { - $query = "INSERT INTO rmgr_contactPhones + $query = "INSERT INTO pmgr_contact_phones (`id`, `type`, `phone`, `ext`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} (++$aicur_cp_id, $_->{'type'}, $_->{'phone'}, $_->{'ext'}))) . ")"; query($db_handle, $query) || die("Unable to insert"); - $query = "INSERT INTO rmgr_contactMethods + $query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} ($cid, 'PHONE', $aicur_cp_id, 'MAIN', $_->{'preference'}))) @@ -485,12 +487,12 @@ foreach $row (@$result) { } if ($row->{'Email'}) { - $query = "INSERT INTO rmgr_contactEmails + $query = "INSERT INTO pmgr_contact_emails (`id`, `email`) VALUES (".++$aicur_ce_id.", '$row->{'Email'}')"; query($db_handle, $query) || die("Unable to insert"); - $query = "INSERT INTO rmgr_contactMethods + $query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUE ($cid, 'EMAIL', $aicur_ce_id, 'MAIN', 'PRIMARY')"; query($db_handle, $query) || die("Unable to insert"); @@ -501,7 +503,7 @@ foreach $row (@$result) { $tenant_map{$row->{'TenantID'}}{'alt'} = ++$aicur_c_id; $cid = $tenant_map{$row->{'TenantID'}}{'alt'}; - $query = "INSERT INTO rmgr_contacts + $query = "INSERT INTO pmgr_contacts (`id`, `first_name`, `middle_name`, `last_name`, `display_name`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} @@ -516,7 +518,7 @@ foreach $row (@$result) { query($db_handle, $query) || die("Unable to insert"); if ($row->{'AltCity'}) { - $query = "INSERT INTO rmgr_contactAddresses + $query = "INSERT INTO pmgr_contact_addresses (`id`, `address`, `city`, `state`, `postcode`, `country`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} @@ -526,21 +528,21 @@ foreach $row (@$result) { )) . ")"; query($db_handle, $query) || die("Unable to insert"); - $query = "INSERT INTO rmgr_contactMethods + $query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES ($cid, 'POST', $aicur_ca_id, 'MAIN', 'PRIMARY')"; query($db_handle, $query) || die("Unable to insert"); } if ($row->{'AltPhone'}) { - $query = "INSERT INTO rmgr_contactPhones + $query = "INSERT INTO pmgr_contact_phones (`id`, `type`, `phone`, `ext`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} (++$aicur_cp_id, 'LANDLINE', $row->{'AltPhone'}, undef) )) . ")"; query($db_handle, $query) || die("Unable to insert"); - $query = "INSERT INTO rmgr_contactMethods + $query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES ($cid, 'PHONE', $aicur_cp_id, 'MAIN', 'PRIMARY')"; query($db_handle, $query) || die("Unable to insert"); @@ -562,7 +564,7 @@ foreach $row (@$result) { my $uid = $unit_map{$row->{'UnitID'}}; my $lid = $ledger_map{$row->{'LedgerID'}}; - $query = "INSERT INTO rmgr_leases + $query = "INSERT INTO pmgr_leases (`id`, `number`, `lease_type_id`, `unit_id`, `lease_date`, `movein_date`, `moveout_date`, `close_date`, @@ -576,7 +578,7 @@ foreach $row (@$result) { )) . ")"; query($db_handle, $query) || die("Unable to insert"); - $query = "INSERT INTO rmgr_leaseContacts + $query = "INSERT INTO pmgr_contacts_leases (`lease_id`, `contact_id`, `type`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} @@ -587,7 +589,7 @@ foreach $row (@$result) { $cid = $tenant_map{$row->{'TenantID'}}{'alt'}; next unless $cid; - $query = "INSERT INTO rmgr_leaseContacts + $query = "INSERT INTO pmgr_contacts_leases (`lease_id`, `contact_id`, `type`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} @@ -607,7 +609,7 @@ print(" $nrows Security Deposits\n"); foreach $row (@$result) { my $uid = $unit_map{$row->{'UnitID'}}; - $query = "UPDATE rmgr_leases + $query = "UPDATE pmgr_leases SET deposit = $row->{'ChargeAmount'} WHERE `number` = '$row->{'LedgerID'}'"; query($db_handle, $query) || die("Unable to update"); @@ -639,8 +641,8 @@ foreach $row (@$result) { my $lid = $ledger_map{$row->{'LedgerID'}}; my $chid = $charge_map{$row->{'ChargeID'}}; - $query = "INSERT INTO rmgr_transactionCharges - (`id`, `type_id`, `lease_id`, + $query = "INSERT INTO pmgr_charges + (`id`, `charge_type_id`, `lease_id`, `charge_date`, `charge_to_date`, `amount`, `tax`, `total`, `comment`) VALUES (" . @@ -653,8 +655,8 @@ foreach $row (@$result) { )) . ")"; query($db_handle, $query) || die("Unable to insert"); - $query = "UPDATE rmgr_transactionCharges"; - $query .= " SET due_date = DATE_ADD(charge_date, INTERVAL IF(type_id=2,10,0) DAY)"; + $query = "UPDATE pmgr_charges"; + $query .= " SET due_date = DATE_ADD(charge_date, INTERVAL IF(charge_type_id=2,10,0) DAY)"; query($db_handle, $query) || die("Unable to update"); } @@ -673,7 +675,7 @@ foreach $row (@$result) { my $lid = $ledger_map{$row->{'LedgerID'}}; my $rid = $receipt_map{$row->{'ReceiptNum'}}; - $query = "INSERT INTO rmgr_transactionReceipts + $query = "INSERT INTO pmgr_receipts (`id`, `stamp`, `comment`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} @@ -712,7 +714,7 @@ foreach $row (@$result) { my $rid = $receipt_map{$row->{'ReceiptNum'}}; my $chid = $charge_map{$row->{'ChargeID'}}; - $query = "INSERT INTO rmgr_transactionPayments + $query = "INSERT INTO pmgr_payments (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} @@ -723,7 +725,7 @@ foreach $row (@$result) { )) . ")"; query($db_handle, $query) || die("Unable to insert"); - $query = "INSERT INTO rmgr_transactionReconciliations + $query = "INSERT INTO pmgr_charges_receipts (`charge_id`, `receipt_id`, `amount`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} @@ -749,7 +751,7 @@ foreach $row (@$result) { my $chid = $charge_map{$row->{'ChargeID'}}; my $rid = $receipt_map{$row->{'ReceiptNum'}}; - $query = "INSERT INTO rmgr_transactionReconciliations + $query = "INSERT INTO pmgr_charges_receipts (`charge_id`, `receipt_id`, `amount`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} @@ -758,22 +760,22 @@ foreach $row (@$result) { query($db_handle, $query) || die("Unable to insert"); } -$query ="UPDATE rmgr_transactionReconciliations R +$query ="UPDATE pmgr_charges_receipts R JOIN (SELECT P.receipt_id AS rid, IF(COALESCE(Ch.total, 0) 'localhost', 'login' => 'pmgr', 'password' => 'pmgruser', - 'database' => 'pmgr', + 'database' => 'property_manager', 'prefix' => 'pmgr_', ); } From df846f99638d6b375448cde87219e1e5e7f45eed Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 28 May 2009 05:49:03 +0000 Subject: [PATCH 014/717] Very, very early snapshot. Some models are working, and I have a controller for testing. Everything is subject to change. I _do_ have a working tenant ledger though, so it's worth a snapshot. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@15 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/transactions_controller.php | 36 +++++++++ site/models/charge.php | 53 ++++++++++++ site/models/charge_type.php | 39 +++++++++ site/models/contact.php | 46 +++++++++++ site/models/contact_email.php | 30 +++++++ site/models/lease.php | 85 ++++++++++++++++++++ site/models/lease_type.php | 28 +++++++ site/models/payment.php | 31 +++++++ site/models/payment_type.php | 29 +++++++ site/models/receipt.php | 46 +++++++++++ site/views/transactions/contact.ctp | 66 +++++++++++++++ site/views/transactions/ledger.ctp | 53 ++++++++++++ site/views/transactions/ledger_1.ctp | 58 +++++++++++++ 13 files changed, 600 insertions(+) create mode 100644 site/controllers/transactions_controller.php create mode 100644 site/models/charge.php create mode 100644 site/models/charge_type.php create mode 100644 site/models/contact.php create mode 100644 site/models/contact_email.php create mode 100644 site/models/lease.php create mode 100644 site/models/lease_type.php create mode 100644 site/models/payment.php create mode 100644 site/models/payment_type.php create mode 100644 site/models/receipt.php create mode 100644 site/views/transactions/contact.ctp create mode 100644 site/views/transactions/ledger.ctp create mode 100644 site/views/transactions/ledger_1.ctp diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php new file mode 100644 index 0000000..f4501ef --- /dev/null +++ b/site/controllers/transactions_controller.php @@ -0,0 +1,36 @@ +Session->setFlash(__('Invalid Item.', true)); + $this->redirect(array('action'=>'')); + } + $this->Charge->recursive = 0; + //$ledgers = array($this->Charge->read(null, $id)); + $this->set('ledgers', $this->Charge->find('all')); + //$this->set(compact('ledgers', 'tables')); + } + + function contact($id = null) { + if (!$id) { + $this->Session->setFlash(__('Invalid Item.', true)); + $this->redirect(array('action'=>'')); + } + $this->Contact->recursive = 4; + $this->Contact->Lease->LeaseType->unbindModel(array('hasMany' => array('Lease'))); + $this->Contact->Lease->Charge->unbindModel(array('belongsTo' => array('Lease'))); + $this->Contact->Lease->Charge->ChargeType->unbindModel(array('hasMany' => array('Charge'))); + $this->Contact->Lease->Charge->Receipt->unbindModel(array('hasMany' => array('ChargesReceipt'))); + + //$ledgers = array($this->Charge->read(null, $id)); + //$this->set('ledgers', $this->Contact->Lease->Charge->find('all')); + //$this->set(compact('ledgers', 'tables')); + $this->set('tenant', $this->Contact->read(null, $id)); + } +} + +?> \ No newline at end of file diff --git a/site/models/charge.php b/site/models/charge.php new file mode 100644 index 0000000..e37a8e9 --- /dev/null +++ b/site/models/charge.php @@ -0,0 +1,53 @@ + array('numeric'), + 'charge_type_id' => array('numeric'), + 'lease_id' => array('numeric'), + 'charge_date' => array('date'), + 'charge_to_date' => array('date'), + 'due_date' => array('date'), + 'amount' => array('money'), + 'tax' => array('money'), + 'total' => array('money') + ); + + var $belongsTo = array( + 'ChargeType' => array( + 'className' => 'ChargeType', + 'foreignKey' => 'charge_type_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ), + 'Lease' => array( + 'className' => 'Lease', + 'foreignKey' => 'lease_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ) + ); + + var $hasAndBelongsToMany = array( + 'Receipt' => array( + 'className' => 'Receipt', + 'joinTable' => 'charges_receipts', + 'foreignKey' => 'charge_id', + 'associationForeignKey' => 'receipt_id', + 'unique' => true, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'finderQuery' => '', + 'deleteQuery' => '', + 'insertQuery' => '' + ) + ); + +} +?> \ No newline at end of file diff --git a/site/models/charge_type.php b/site/models/charge_type.php new file mode 100644 index 0000000..fe42c68 --- /dev/null +++ b/site/models/charge_type.php @@ -0,0 +1,39 @@ + array('numeric'), + 'name' => array('notempty'), + 'account_id' => array('numeric') + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed +/* var $belongsTo = array( */ +/* 'Account' => array( */ +/* 'className' => 'Account', */ +/* 'foreignKey' => 'account_id', */ +/* 'conditions' => '', */ +/* 'fields' => '', */ +/* 'order' => '' */ +/* ) */ +/* ); */ + + var $hasMany = array( + 'Charge' => array( + 'className' => 'Charge', + 'foreignKey' => 'charge_type_id', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); + +} +?> \ No newline at end of file diff --git a/site/models/contact.php b/site/models/contact.php new file mode 100644 index 0000000..2584571 --- /dev/null +++ b/site/models/contact.php @@ -0,0 +1,46 @@ + array('numeric'), + 'display_name' => array('notempty'), + 'id_federal' => array('ssn'), + 'id_exp' => array('date') + ); + + var $hasAndBelongsToMany = array( + 'Lease' => array( + 'className' => 'Lease', + 'joinTable' => 'contacts_leases', + 'foreignKey' => 'contact_id', + 'associationForeignKey' => 'lease_id', + 'unique' => true, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'finderQuery' => '', + 'deleteQuery' => '', + 'insertQuery' => '' + ), + 'ContactEmail' => array( + 'className' => 'ContactEmail', + 'joinTable' => 'contacts_methods', + 'foreignKey' => 'contact_id', + 'associationForeignKey' => 'method_id', + 'unique' => true, + 'conditions' => "ContactsMethod.method = 'EMAIL'", + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'finderQuery' => '', + 'deleteQuery' => '', + 'insertQuery' => '' + ) + ); + +} +?> \ No newline at end of file diff --git a/site/models/contact_email.php b/site/models/contact_email.php new file mode 100644 index 0000000..3f4a7e9 --- /dev/null +++ b/site/models/contact_email.php @@ -0,0 +1,30 @@ + array('numeric'), + 'email' => array('email') + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + var $hasAndBelongsToMany = array( + 'Contact' => array( + 'className' => 'Contact', + 'joinTable' => 'contacts_methods', + 'foreignKey' => 'method_id', + 'associationForeignKey' => 'contact_id', + 'unique' => true, + 'conditions' => "ContactsMethod.method = 'EMAIL'", + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'finderQuery' => '', + 'deleteQuery' => '', + 'insertQuery' => '' + ) + ); + +} +?> \ No newline at end of file diff --git a/site/models/lease.php b/site/models/lease.php new file mode 100644 index 0000000..509b333 --- /dev/null +++ b/site/models/lease.php @@ -0,0 +1,85 @@ + array('numeric'), + 'number' => array('alphanumeric'), + 'lease_type_id' => array('numeric'), + 'unit_id' => array('numeric'), + 'late_schedule_id' => array('numeric'), + 'lease_date' => array('date'), + 'movein_planed_date' => array('date'), + 'movein_date' => array('date'), + 'moveout_date' => array('date'), + 'moveout_planed_date' => array('date'), + 'notice_given_date' => array('date'), + 'notice_received_date' => array('date'), + 'close_date' => array('date'), + 'deposit' => array('money'), + 'amount' => array('money'), + 'next_amount' => array('money'), + 'next_amount_date' => array('date') + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + var $belongsTo = array( + 'LeaseType' => array( + 'className' => 'LeaseType', + 'foreignKey' => 'lease_type_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ), + 'Unit' => array( + 'className' => 'Unit', + 'foreignKey' => 'unit_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ), + 'LateSchedule' => array( + 'className' => 'LateSchedule', + 'foreignKey' => 'late_schedule_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ) + ); + + var $hasMany = array( + 'Charge' => array( + 'className' => 'Charge', + 'foreignKey' => 'lease_id', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); + + var $hasAndBelongsToMany = array( + 'Contact' => array( + 'className' => 'Contact', + 'joinTable' => 'contacts_leases', + 'foreignKey' => 'lease_id', + 'associationForeignKey' => 'contact_id', + 'unique' => true, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'finderQuery' => '', + 'deleteQuery' => '', + 'insertQuery' => '' + ) + ); + +} +?> \ No newline at end of file diff --git a/site/models/lease_type.php b/site/models/lease_type.php new file mode 100644 index 0000000..f4a5208 --- /dev/null +++ b/site/models/lease_type.php @@ -0,0 +1,28 @@ + array('numeric'), + 'name' => array('notempty') + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + var $hasMany = array( + 'Lease' => array( + 'className' => 'Lease', + 'foreignKey' => 'lease_type_id', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); + +} +?> \ No newline at end of file diff --git a/site/models/payment.php b/site/models/payment.php new file mode 100644 index 0000000..e3b2fc8 --- /dev/null +++ b/site/models/payment.php @@ -0,0 +1,31 @@ + array('numeric'), + 'receipt_id' => array('numeric'), + 'payment_type_id' => array('numeric'), + 'amount' => array('money') + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + var $belongsTo = array( + 'Receipt' => array( + 'className' => 'Receipt', + 'foreignKey' => 'receipt_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ), + 'PaymentType' => array( + 'className' => 'PaymentType', + 'foreignKey' => 'payment_type_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ) + ); + +} +?> \ No newline at end of file diff --git a/site/models/payment_type.php b/site/models/payment_type.php new file mode 100644 index 0000000..45f5881 --- /dev/null +++ b/site/models/payment_type.php @@ -0,0 +1,29 @@ + array('numeric'), + 'name' => array('notempty'), + 'tillable' => array('boolean') + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + var $hasMany = array( + 'Payment' => array( + 'className' => 'Payment', + 'foreignKey' => 'payment_type_id', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); + +} +?> \ No newline at end of file diff --git a/site/models/receipt.php b/site/models/receipt.php new file mode 100644 index 0000000..66a2164 --- /dev/null +++ b/site/models/receipt.php @@ -0,0 +1,46 @@ + array('numeric'), + 'stamp' => array('time') + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + var $hasMany = array( + 'Payment' => array( + 'className' => 'Payment', + 'foreignKey' => 'receipt_id', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); + + var $hasAndBelongsToMany = array( + 'Charge' => array( + 'className' => 'Charge', + 'joinTable' => 'charges_receipts', + 'foreignKey' => 'receipt_id', + 'associationForeignKey' => 'charge_id', + 'unique' => true, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'finderQuery' => '', + 'deleteQuery' => '', + 'insertQuery' => '' + ) + ); + +} +?> \ No newline at end of file diff --git a/site/views/transactions/contact.ctp b/site/views/transactions/contact.ctp new file mode 100644 index 0000000..18d6021 --- /dev/null +++ b/site/views/transactions/contact.ctp @@ -0,0 +1,66 @@ + + +
+

+ + $val) { + $rows[] = array(array($col, 'width=1%'), $val); +} +echo('' . "\n"); +echo(' ' . "\n"); +echo $html->tableCells($rows, null, array('class' => "altrow")); +echo('
Tenant Info
' . "\n"); + +$grand_total = 0; +foreach($tenant['Lease'] AS $lease) { + $headers = array('Date', /*'Through',*/ /*'Charge/Receipt'*/'ID', 'Type', 'Comment', 'Amount', 'Total'); + + $rows = array(); + $running_total = 0; + foreach($lease['Charge'] AS $charge) { + $amount = $charge['total']; + $running_total += $amount; + $rows[] = array(date_format(date_create($charge['charge_date']), 'm-d-Y') . ' - ' . + date_format(date_create($charge['charge_to_date']), 'm-d-Y'), + '#'.$charge['id'], + $charge['ChargeType']['name'], + $charge['comment'], + currency($amount), + currency($running_total)); + + foreach ($charge['Receipt'] AS $receipt) { + $amount = -1 * $receipt['ChargesReceipt']['amount']; + $running_total += $amount; + $rows[] = array(' -- ' .date_format(date_create($receipt['stamp']), 'm-d-Y'), + //null, + '#'.$receipt['id'], + 'Receipt', + $receipt['comment'], + currency($amount), + currency($running_total)); + } + } + $grand_total += $running_total; + + echo('' . "\n"); + echo(' ' . "\n"); + echo $html->tableHeaders($headers); + echo $html->tableCells($rows, null, array('class' => "altrow")); + echo('
Lease #'.$lease['number'].' (Unit '.$lease['Unit']['name'].')
' . "\n"); + +} +?> + +

Grand Total:

+
diff --git a/site/views/transactions/ledger.ctp b/site/views/transactions/ledger.ctp new file mode 100644 index 0000000..fd59df5 --- /dev/null +++ b/site/views/transactions/ledger.ctp @@ -0,0 +1,53 @@ + + +
+

+ + $table) { + + if (array_key_exists(0, $table)) { + // Horizontal table (multiple items) + $headers = array_keys($table[0]); + + //$rows = array_map('array_values', $table); + $rows = array(); + //echo("
table:\n"); print_r($table); echo("
\n"); + foreach ($table as $row) { + //echo("
row:\n"); print_r($row); echo("
\n"); + $rows[] = array_values($row); + } + } + else { + // Vertical table (one item) + $headers = array('Field', 'Value'); + + $rows = array(); + foreach ($table as $col => $val) { + $rows[] = array($col, $val); + } + } + + foreach($rows AS &$row) { + foreach ($row AS &$cell) { + if (is_array($cell)) + $cell = "<ARRAY>"; + } + } + //echo("
headers:\n"); print_r($headers); echo("
\n"); + //echo("
rows:\n"); print_r($rows); echo("
\n"); + ?> + + + tableHeaders($headers); + echo $html->tableCells($rows, null, array('class' => "altrow")); + ?> +
+ + +
\ No newline at end of file diff --git a/site/views/transactions/ledger_1.ctp b/site/views/transactions/ledger_1.ctp new file mode 100644 index 0000000..316e24a --- /dev/null +++ b/site/views/transactions/ledger_1.ctp @@ -0,0 +1,58 @@ +
+

+ + +counter(array( + 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); + + $cells = array($paginator->sort('id'), + $paginator->sort('charge_type_id'), + $paginator->sort('lease_id'), + $paginator->sort('charge_date'), + $paginator->sort('charge_to_date'), + $paginator->sort('due_date'), + $paginator->sort('amount'), + $paginator->sort('tax'), + $paginator->sort('total'), + $paginator->sort('comment')); +} else { + $cells = array('Id', 'Type', 'Lease', 'Date', 'Through', 'Due', 'Amount', 'Tax', 'Total', 'Comment'); +} +echo $html->tableHeaders($cells); + +$cells = array(); +foreach ($ledgers as $ledger) { + $cells[] = array($html->link($ledger['Charge']['id'], + array('controller' => 'transactions', + 'action' => 'view', + $ledger['Charge']['id'])), + $ledger['Charge']['charge_type_id'], + $ledger['Charge']['lease_id'], + $ledger['Charge']['charge_date'], + $ledger['Charge']['charge_to_date'], + $ledger['Charge']['due_date'], + $ledger['Charge']['amount'], + $ledger['Charge']['tax'], + $ledger['Charge']['total'], + $ledger['Charge']['comment']); +} +echo $html->tableCells($cells, null, array('class' => "altrow")); +?> +
+ +' . "\n"); + echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); + echo(' | '); + echo $paginator->numbers(); + echo(' | '); + echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); + echo('
' . "\n"); + } +?> + + + \ No newline at end of file From 28bf192853bba8571e508e19c322b6b7b09c036f Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 28 May 2009 06:31:07 +0000 Subject: [PATCH 015/717] Added phone and address models as well as outputing them to the view. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@16 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/contact.php | 32 +++++++- site/models/contact_address.php | 28 +++++++ site/models/contact_email.php | 1 - site/models/contact_phone.php | 31 ++++++++ site/views/transactions/contact.ctp | 114 +++++++++++++++++++++++++--- 5 files changed, 194 insertions(+), 12 deletions(-) create mode 100644 site/models/contact_address.php create mode 100644 site/models/contact_phone.php diff --git a/site/models/contact.php b/site/models/contact.php index 2584571..5aab7f3 100644 --- a/site/models/contact.php +++ b/site/models/contact.php @@ -25,6 +25,36 @@ class Contact extends AppModel { 'deleteQuery' => '', 'insertQuery' => '' ), + 'ContactAddress' => array( + 'className' => 'ContactAddress', + 'joinTable' => 'contacts_methods', + 'foreignKey' => 'contact_id', + 'associationForeignKey' => 'method_id', + 'unique' => true, + 'conditions' => "ContactsMethod.method = 'POST'", + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'finderQuery' => '', + 'deleteQuery' => '', + 'insertQuery' => '' + ), + 'ContactPhone' => array( + 'className' => 'ContactPhone', + 'joinTable' => 'contacts_methods', + 'foreignKey' => 'contact_id', + 'associationForeignKey' => 'method_id', + 'unique' => true, + 'conditions' => "ContactsMethod.method = 'PHONE'", + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'finderQuery' => '', + 'deleteQuery' => '', + 'insertQuery' => '' + ), 'ContactEmail' => array( 'className' => 'ContactEmail', 'joinTable' => 'contacts_methods', @@ -39,7 +69,7 @@ class Contact extends AppModel { 'finderQuery' => '', 'deleteQuery' => '', 'insertQuery' => '' - ) + ), ); } diff --git a/site/models/contact_address.php b/site/models/contact_address.php new file mode 100644 index 0000000..d808b41 --- /dev/null +++ b/site/models/contact_address.php @@ -0,0 +1,28 @@ + array('numeric'), + 'postcode' => array('postal') + ); + + var $hasAndBelongsToMany = array( + 'Contact' => array( + 'className' => 'Contact', + 'joinTable' => 'contacts_methods', + 'foreignKey' => 'method_id', + 'associationForeignKey' => 'contact_id', + 'unique' => true, + 'conditions' => "ContactsMethod.method = 'POST'", + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'finderQuery' => '', + 'deleteQuery' => '', + 'insertQuery' => '' + ) + ); +} +?> \ No newline at end of file diff --git a/site/models/contact_email.php b/site/models/contact_email.php index 3f4a7e9..c9b59dd 100644 --- a/site/models/contact_email.php +++ b/site/models/contact_email.php @@ -7,7 +7,6 @@ class ContactEmail extends AppModel { 'email' => array('email') ); - //The Associations below have been created with all possible keys, those that are not needed can be removed var $hasAndBelongsToMany = array( 'Contact' => array( 'className' => 'Contact', diff --git a/site/models/contact_phone.php b/site/models/contact_phone.php new file mode 100644 index 0000000..79b9807 --- /dev/null +++ b/site/models/contact_phone.php @@ -0,0 +1,31 @@ + array('numeric'), + //'type' => array('inlist'), + 'phone' => array('phone'), + 'ext' => array('numeric') + ); + + var $hasAndBelongsToMany = array( + 'Contact' => array( + 'className' => 'Contact', + 'joinTable' => 'contacts_methods', + 'foreignKey' => 'method_id', + 'associationForeignKey' => 'contact_id', + 'unique' => true, + 'conditions' => "ContactsMethod.method = 'PHONE'", + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'finderQuery' => '', + 'deleteQuery' => '', + 'insertQuery' => '' + ) + ); + +} +?> \ No newline at end of file diff --git a/site/views/transactions/contact.ctp b/site/views/transactions/contact.ctp index 18d6021..8ea105c 100644 --- a/site/views/transactions/contact.ctp +++ b/site/views/transactions/contact.ctp @@ -5,23 +5,117 @@ $val) { $rows[] = array(array($col, 'width=1%'), $val); } + echo('' . "\n"); echo(' ' . "\n"); -echo $html->tableCells($rows, null, array('class' => "altrow")); +echo $html->tableCells(array(array('Name', $tenant['Contact']['display_name']), + array('Company', $tenant['Contact']['company_name']), + array('SSN', $tenant['Contact']['id_federal']), + array('ID', $tenant['Contact']['id_num'] + . ($tenant['Contact']['id_state'] + ? " - ".$tenant['Contact']['id_state'] + : ""))), + null, array('class' => "altrow"), false, false); echo('
Tenant Info
' . "\n"); + +/********************************************************************** + * Phones + */ +$headers = array('Location', 'Preference', 'Type', 'Phone', 'Extension', 'Comment'); +$rows = array(); +foreach($tenant['ContactPhone'] AS $phone) { + $rows[] = array($phone['ContactsMethod']['type'], + $phone['ContactsMethod']['preference'], + $phone['type'], + phone($phone['phone']), + $phone['ext'], + $phone['comment']); +} + +if (count($rows)) { + echo('' . "\n"); + echo(' ' . "\n"); + echo $html->tableHeaders($headers); + echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); + echo('
Phone
' . "\n"); +} + + +/********************************************************************** + * Emails + */ +$headers = array('Location', 'Preference', 'Email', 'Comment'); +$rows = array(); +foreach($tenant['ContactEmail'] AS $email) { + $rows[] = array($email['ContactsMethod']['type'], + $email['ContactsMethod']['preference'], + $email['email'], + $email['comment']); +} + +if (count($rows)) { + echo('' . "\n"); + echo(' ' . "\n"); + echo $html->tableHeaders($headers); + echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); + echo('
Email
' . "\n"); +} + + +/********************************************************************** + * Addresses + */ +$headers = array('Location', 'Preference', 'Address', 'City', 'State', 'Zip', 'Country', 'Comment'); +$rows = array(); +foreach($tenant['ContactAddress'] AS $address) { + $rows[] = array($address['ContactsMethod']['type'], + $address['ContactsMethod']['preference'], + $address['address'], + $address['city'], + $address['state'], + $address['postcode'], + $address['country'], + $address['comment']); +} + +if (count($rows)) { + echo('' . "\n"); + echo(' ' . "\n"); + echo $html->tableHeaders($headers); + echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); + echo('
Address
' . "\n"); +} + + +/********************************************************************** + * Ledger History + */ $grand_total = 0; foreach($tenant['Lease'] AS $lease) { $headers = array('Date', /*'Through',*/ /*'Charge/Receipt'*/'ID', 'Type', 'Comment', 'Amount', 'Total'); @@ -31,8 +125,8 @@ foreach($tenant['Lease'] AS $lease) { foreach($lease['Charge'] AS $charge) { $amount = $charge['total']; $running_total += $amount; - $rows[] = array(date_format(date_create($charge['charge_date']), 'm-d-Y') . ' - ' . - date_format(date_create($charge['charge_to_date']), 'm-d-Y'), + $rows[] = array(date_format(date_create($charge['charge_date']), $date_fmt) . ' - ' . + date_format(date_create($charge['charge_to_date']), $date_fmt), '#'.$charge['id'], $charge['ChargeType']['name'], $charge['comment'], @@ -42,10 +136,10 @@ foreach($tenant['Lease'] AS $lease) { foreach ($charge['Receipt'] AS $receipt) { $amount = -1 * $receipt['ChargesReceipt']['amount']; $running_total += $amount; - $rows[] = array(' -- ' .date_format(date_create($receipt['stamp']), 'm-d-Y'), + $rows[] = array(' -- ' .date_format(date_create($receipt['stamp']), $date_fmt), //null, '#'.$receipt['id'], - 'Receipt', + 'Payment/Receipt', $receipt['comment'], currency($amount), currency($running_total)); @@ -56,11 +150,11 @@ foreach($tenant['Lease'] AS $lease) { echo('' . "\n"); echo(' ' . "\n"); echo $html->tableHeaders($headers); - echo $html->tableCells($rows, null, array('class' => "altrow")); + echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); echo('
Lease #'.$lease['number'].' (Unit '.$lease['Unit']['name'].')
' . "\n"); } ?> -

Grand Total:

+

Outstanding Balance:

From 0ef51ee30fa9fb9e00302bf587f6c073794a1821 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 28 May 2009 06:40:40 +0000 Subject: [PATCH 016/717] Added a Financial Accounts table, for allowing transactions to be exported to financial software (definition is presently incomplete). Rearranged the table definitions a bit as well. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@17 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 248 +++++++++++++++++++++++++++++++------------------- 1 file changed, 155 insertions(+), 93 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index 3b710be..a014c03 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -706,7 +706,161 @@ CREATE TABLE `pmgr_contacts_leases` ( -- ###################################################################### -- ###################################################################### -- ## --- ## TRANSACTIONS +-- ## FINANCIAL ACCOUNTS +-- ## + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE pmgr_accounts + +DROP TABLE IF EXISTS `pmgr_accounts`; +CREATE TABLE `pmgr_accounts` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + `name` VARCHAR(80) NOT NULL, + `external_name` VARCHAR(80) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ## +-- ## CHARGES +-- ## + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE pmgr_charge_types + +DROP TABLE IF EXISTS `pmgr_charge_types`; +CREATE TABLE `pmgr_charge_types` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + `name` VARCHAR(80) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + `account_id` INT(10) UNSIGNED NOT NULL, -- quickbooks tracking + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +LOCK TABLES `pmgr_charge_types` WRITE; +INSERT INTO `pmgr_charge_types` (`id`, `name`, `account_id`) + VALUES + (1, 'Security Deposit', 0), + (2, 'Rent', 0), + (3, 'Late Charge', 0); +UNLOCK TABLES; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE pmgr_charges + +DROP TABLE IF EXISTS `pmgr_charges`; +CREATE TABLE `pmgr_charges` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + `charge_type_id` INT(10) UNSIGNED NOT NULL, + `lease_id` INT(10) UNSIGNED NOT NULL, + `charge_date` DATE NOT NULL, + `charge_to_date` DATE NOT NULL, + `due_date` DATE DEFAULT NULL, + `amount` FLOAT(12,2) NOT NULL, + `tax` FLOAT(12,2) NOT NULL, + `total` FLOAT(12,2) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ## +-- ## PAYMENTS +-- ## + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE pmgr_payment_types + +DROP TABLE IF EXISTS `pmgr_payment_types`; +CREATE TABLE `pmgr_payment_types` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + `name` VARCHAR(80) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + `tillable` TINYINT(1) NOT NULL DEFAULT 1, -- Does manager collect by hand? + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +LOCK TABLES `pmgr_payment_types` WRITE; +INSERT INTO `pmgr_payment_types` (`id`, `name`, `tillable`) + VALUES + (1, 'Cash', 1), + (2, 'Check', 1), + (3, 'Money Order', 1), + (4, 'ACH', 0), + (5, 'Debit Card', 0), + (6, 'Credit Card', 0), + (7, 'Other Tillable', 1), + (8, 'Other Non-Tillable', 0); +UNLOCK TABLES; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE pmgr_payments + +DROP TABLE IF EXISTS `pmgr_payments`; +CREATE TABLE `pmgr_payments` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + `receipt_id` INT(10) UNSIGNED NOT NULL, + `payment_type_id` INT(10) UNSIGNED NOT NULL, + `amount` FLOAT(12,2) NOT NULL, + + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ## +-- ## RECEIPTS -- ## -- # Charge @@ -747,80 +901,6 @@ CREATE TABLE `pmgr_contacts_leases` ( -- LEFT JOIN pmgr_units U ON U.id = L.unit_id --- ---------------------------------------------------------------------- --- ---------------------------------------------------------------------- --- TABLE pmgr_charge_types - -DROP TABLE IF EXISTS `pmgr_charge_types`; -CREATE TABLE `pmgr_charge_types` ( - `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - - `name` VARCHAR(80) NOT NULL, - `comment` VARCHAR(255) DEFAULT NULL, - `account_id` INT(10) UNSIGNED NOT NULL, -- quickbooks tracking - - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -LOCK TABLES `pmgr_charge_types` WRITE; -INSERT INTO `pmgr_charge_types` (`id`, `name`, `account_id`) - VALUES - (1, 'Security Deposit', 0), - (2, 'Rent', 0), - (3, 'Late Charge', 0); -UNLOCK TABLES; - --- ---------------------------------------------------------------------- --- ---------------------------------------------------------------------- --- TABLE pmgr_payment_types - -DROP TABLE IF EXISTS `pmgr_payment_types`; -CREATE TABLE `pmgr_payment_types` ( - `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - - `name` VARCHAR(80) NOT NULL, - `comment` VARCHAR(255) DEFAULT NULL, - `tillable` TINYINT(1) NOT NULL DEFAULT 1, -- Does manager collect by hand? - - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -LOCK TABLES `pmgr_payment_types` WRITE; -INSERT INTO `pmgr_payment_types` (`id`, `name`, `tillable`) - VALUES - (1, 'Cash', 1), - (2, 'Check', 1), - (3, 'Money Order', 1), - (4, 'ACH', 0), - (5, 'Debit Card', 0), - (6, 'Credit Card', 0), - (7, 'Other Tillable', 1), - (8, 'Other Non-Tillable', 0); -UNLOCK TABLES; - - --- ---------------------------------------------------------------------- --- ---------------------------------------------------------------------- --- TABLE pmgr_charges - -DROP TABLE IF EXISTS `pmgr_charges`; -CREATE TABLE `pmgr_charges` ( - `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - - `charge_type_id` INT(10) UNSIGNED NOT NULL, - `lease_id` INT(10) UNSIGNED NOT NULL, - `charge_date` DATE NOT NULL, - `charge_to_date` DATE NOT NULL, - `due_date` DATE DEFAULT NULL, - `amount` FLOAT(12,2) NOT NULL, - `tax` FLOAT(12,2) NOT NULL, - `total` FLOAT(12,2) NOT NULL, - `comment` VARCHAR(255) DEFAULT NULL, - - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - - -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- -- TABLE pmgr_receipts @@ -837,24 +917,6 @@ CREATE TABLE `pmgr_receipts` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8; --- ---------------------------------------------------------------------- --- ---------------------------------------------------------------------- --- TABLE pmgr_payments - -DROP TABLE IF EXISTS `pmgr_payments`; -CREATE TABLE `pmgr_payments` ( - `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - - `receipt_id` INT(10) UNSIGNED NOT NULL, - `payment_type_id` INT(10) UNSIGNED NOT NULL, - `amount` FLOAT(12,2) NOT NULL, - - `comment` VARCHAR(255) DEFAULT NULL, - - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - - -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- -- TABLE pmgr_charges_receipts From 0021eb176843a9c3a12d009d0925d80a7cfb54c4 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 28 May 2009 06:42:20 +0000 Subject: [PATCH 017/717] Changed the charge/receipt comments slightly to help clarify the intent. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@18 97e9348a-65ac-dc4b-aefc-98561f571b83 --- scripts/sitelink2pmgr.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 0a435a1..5d95b4f 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -651,7 +651,7 @@ foreach $row (@$result) { datefmt($row->{'ChargeDate'}), datefmt($row->{'EndDate'}), $row->{'ChargeAmount'}, $row->{'TaxAmount'}, $row->{'ChargeAmount'} + $row->{'TaxAmount'}, - "ChargeID #".$row->{'ChargeID'}) + "SiteLink Charges.ChargeID #".$row->{'ChargeID'}) )) . ")"; query($db_handle, $query) || die("Unable to insert"); @@ -680,7 +680,7 @@ foreach $row (@$result) { VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} ($rid, datefmt($row->{'ReceiptDate'}), - "ReceiptNum #".$row->{'ReceiptNum'}) + "SiteLink Receipts.ReceiptNum #".$row->{'ReceiptNum'}) )) . ")"; query($db_handle, $query) || die("Unable to insert"); } From ffe04ed6fdc67538b2fe49ed805918b119524c4b Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 28 May 2009 07:05:05 +0000 Subject: [PATCH 018/717] Added Lease History and security deposit tracking. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@19 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/transactions/contact.ctp | 45 +++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/site/views/transactions/contact.ctp b/site/views/transactions/contact.ctp index 8ea105c..631e709 100644 --- a/site/views/transactions/contact.ctp +++ b/site/views/transactions/contact.ctp @@ -5,7 +5,6 @@ ' . "\n"); +echo(' Lease History' . "\n"); +echo $html->tableHeaders($headers); +echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); +echo('' . "\n"); + + /********************************************************************** * Ledger History */ +$security_deposit = 0; $grand_total = 0; foreach($tenant['Lease'] AS $lease) { $headers = array('Date', /*'Through',*/ /*'Charge/Receipt'*/'ID', 'Type', 'Comment', 'Amount', 'Total'); @@ -125,8 +155,7 @@ foreach($tenant['Lease'] AS $lease) { foreach($lease['Charge'] AS $charge) { $amount = $charge['total']; $running_total += $amount; - $rows[] = array(date_format(date_create($charge['charge_date']), $date_fmt) . ' - ' . - date_format(date_create($charge['charge_to_date']), $date_fmt), + $rows[] = array(datefmt($charge['charge_date']) .' - '. datefmt($charge['charge_to_date']), '#'.$charge['id'], $charge['ChargeType']['name'], $charge['comment'], @@ -136,8 +165,11 @@ foreach($tenant['Lease'] AS $lease) { foreach ($charge['Receipt'] AS $receipt) { $amount = -1 * $receipt['ChargesReceipt']['amount']; $running_total += $amount; - $rows[] = array(' -- ' .date_format(date_create($receipt['stamp']), $date_fmt), - //null, + // REVISIT 20090527: + // Using hardcoded value for security deposit... can't be good! + if ($charge['charge_type_id'] == 1) + $security_deposit += $receipt['ChargesReceipt']['amount']; + $rows[] = array(' -- ' . datefmt($receipt['stamp']), '#'.$receipt['id'], 'Payment/Receipt', $receipt['comment'], @@ -148,7 +180,7 @@ foreach($tenant['Lease'] AS $lease) { $grand_total += $running_total; echo('' . "\n"); - echo(' ' . "\n"); + echo(' ' . "\n"); echo $html->tableHeaders($headers); echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); echo('
Lease #'.$lease['number'].' (Unit '.$lease['Unit']['name'].')Lease #'.$lease['number'].' ('.$lease['Unit']['name'].')
' . "\n"); @@ -156,5 +188,6 @@ foreach($tenant['Lease'] AS $lease) { } ?> +

Total Security Deposit:

Outstanding Balance:

From 49237122380ebd8469731799a36d784e70db35b4 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 28 May 2009 07:12:32 +0000 Subject: [PATCH 019/717] Moved the contact info into the contacts controller. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@20 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/contacts_controller.php | 21 ++ site/controllers/transactions_controller.php | 36 ---- site/views/contacts/view.ctp | 66 +++++++ site/views/transactions/contact.ctp | 193 ------------------- site/views/transactions/ledger.ctp | 53 ----- site/views/transactions/ledger_1.ctp | 58 ------ 6 files changed, 87 insertions(+), 340 deletions(-) create mode 100644 site/controllers/contacts_controller.php delete mode 100644 site/controllers/transactions_controller.php create mode 100644 site/views/contacts/view.ctp delete mode 100644 site/views/transactions/contact.ctp delete mode 100644 site/views/transactions/ledger.ctp delete mode 100644 site/views/transactions/ledger_1.ctp diff --git a/site/controllers/contacts_controller.php b/site/controllers/contacts_controller.php new file mode 100644 index 0000000..f372274 --- /dev/null +++ b/site/controllers/contacts_controller.php @@ -0,0 +1,21 @@ +Session->setFlash(__('Invalid Item.', true)); + $this->redirect(array('action'=>'')); + } + $this->Contact->recursive = 4; + $this->Contact->Lease->LeaseType->unbindModel(array('hasMany' => array('Lease'))); + $this->Contact->Lease->Charge->unbindModel(array('belongsTo' => array('Lease'))); + $this->Contact->Lease->Charge->ChargeType->unbindModel(array('hasMany' => array('Charge'))); + $this->Contact->Lease->Charge->Receipt->unbindModel(array('hasMany' => array('ChargesReceipt'))); + + $this->set('tenant', $this->Contact->read(null, $id)); + } +} + +?> \ No newline at end of file diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php deleted file mode 100644 index f4501ef..0000000 --- a/site/controllers/transactions_controller.php +++ /dev/null @@ -1,36 +0,0 @@ -Session->setFlash(__('Invalid Item.', true)); - $this->redirect(array('action'=>'')); - } - $this->Charge->recursive = 0; - //$ledgers = array($this->Charge->read(null, $id)); - $this->set('ledgers', $this->Charge->find('all')); - //$this->set(compact('ledgers', 'tables')); - } - - function contact($id = null) { - if (!$id) { - $this->Session->setFlash(__('Invalid Item.', true)); - $this->redirect(array('action'=>'')); - } - $this->Contact->recursive = 4; - $this->Contact->Lease->LeaseType->unbindModel(array('hasMany' => array('Lease'))); - $this->Contact->Lease->Charge->unbindModel(array('belongsTo' => array('Lease'))); - $this->Contact->Lease->Charge->ChargeType->unbindModel(array('hasMany' => array('Charge'))); - $this->Contact->Lease->Charge->Receipt->unbindModel(array('hasMany' => array('ChargesReceipt'))); - - //$ledgers = array($this->Charge->read(null, $id)); - //$this->set('ledgers', $this->Contact->Lease->Charge->find('all')); - //$this->set(compact('ledgers', 'tables')); - $this->set('tenant', $this->Contact->read(null, $id)); - } -} - -?> \ No newline at end of file diff --git a/site/views/contacts/view.ctp b/site/views/contacts/view.ctp new file mode 100644 index 0000000..18d6021 --- /dev/null +++ b/site/views/contacts/view.ctp @@ -0,0 +1,66 @@ + + +
+

+ + $val) { + $rows[] = array(array($col, 'width=1%'), $val); +} +echo('' . "\n"); +echo(' ' . "\n"); +echo $html->tableCells($rows, null, array('class' => "altrow")); +echo('
Tenant Info
' . "\n"); + +$grand_total = 0; +foreach($tenant['Lease'] AS $lease) { + $headers = array('Date', /*'Through',*/ /*'Charge/Receipt'*/'ID', 'Type', 'Comment', 'Amount', 'Total'); + + $rows = array(); + $running_total = 0; + foreach($lease['Charge'] AS $charge) { + $amount = $charge['total']; + $running_total += $amount; + $rows[] = array(date_format(date_create($charge['charge_date']), 'm-d-Y') . ' - ' . + date_format(date_create($charge['charge_to_date']), 'm-d-Y'), + '#'.$charge['id'], + $charge['ChargeType']['name'], + $charge['comment'], + currency($amount), + currency($running_total)); + + foreach ($charge['Receipt'] AS $receipt) { + $amount = -1 * $receipt['ChargesReceipt']['amount']; + $running_total += $amount; + $rows[] = array(' -- ' .date_format(date_create($receipt['stamp']), 'm-d-Y'), + //null, + '#'.$receipt['id'], + 'Receipt', + $receipt['comment'], + currency($amount), + currency($running_total)); + } + } + $grand_total += $running_total; + + echo('' . "\n"); + echo(' ' . "\n"); + echo $html->tableHeaders($headers); + echo $html->tableCells($rows, null, array('class' => "altrow")); + echo('
Lease #'.$lease['number'].' (Unit '.$lease['Unit']['name'].')
' . "\n"); + +} +?> + +

Grand Total:

+
diff --git a/site/views/transactions/contact.ctp b/site/views/transactions/contact.ctp deleted file mode 100644 index 631e709..0000000 --- a/site/views/transactions/contact.ctp +++ /dev/null @@ -1,193 +0,0 @@ - - -
-

- - $val) { - $rows[] = array(array($col, 'width=1%'), $val); -} - -echo('' . "\n"); -echo(' ' . "\n"); -echo $html->tableCells(array(array('Name', $tenant['Contact']['display_name']), - array('Company', $tenant['Contact']['company_name']), - array('SSN', $tenant['Contact']['id_federal']), - array('ID', $tenant['Contact']['id_num'] - . ($tenant['Contact']['id_state'] - ? " - ".$tenant['Contact']['id_state'] - : ""))), - null, array('class' => "altrow"), false, false); -echo('
Tenant Info
' . "\n"); - - -/********************************************************************** - * Phones - */ -$headers = array('Location', 'Preference', 'Type', 'Phone', 'Extension', 'Comment'); -$rows = array(); -foreach($tenant['ContactPhone'] AS $phone) { - $rows[] = array($phone['ContactsMethod']['type'], - $phone['ContactsMethod']['preference'], - $phone['type'], - phone($phone['phone']), - $phone['ext'], - $phone['comment']); -} - -if (count($rows)) { - echo('' . "\n"); - echo(' ' . "\n"); - echo $html->tableHeaders($headers); - echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); - echo('
Phone
' . "\n"); -} - - -/********************************************************************** - * Emails - */ -$headers = array('Location', 'Preference', 'Email', 'Comment'); -$rows = array(); -foreach($tenant['ContactEmail'] AS $email) { - $rows[] = array($email['ContactsMethod']['type'], - $email['ContactsMethod']['preference'], - $email['email'], - $email['comment']); -} - -if (count($rows)) { - echo('' . "\n"); - echo(' ' . "\n"); - echo $html->tableHeaders($headers); - echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); - echo('
Email
' . "\n"); -} - - -/********************************************************************** - * Addresses - */ -$headers = array('Location', 'Preference', 'Address', 'City', 'State', 'Zip', 'Country', 'Comment'); -$rows = array(); -foreach($tenant['ContactAddress'] AS $address) { - $rows[] = array($address['ContactsMethod']['type'], - $address['ContactsMethod']['preference'], - $address['address'], - $address['city'], - $address['state'], - $address['postcode'], - $address['country'], - $address['comment']); -} - -if (count($rows)) { - echo('' . "\n"); - echo(' ' . "\n"); - echo $html->tableHeaders($headers); - echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); - echo('
Address
' . "\n"); -} - - -/********************************************************************** - * Lease History - */ -$headers = array('Lease', 'Unit', 'Signed', 'Move-In', 'Move-Out', 'Rent', 'Deposit', 'Comment'); -$rows = array(); -foreach($tenant['Lease'] AS $lease) { - $rows[] = array('#'.$lease['id'], - $lease['Unit']['name'], - datefmt($lease['lease_date']), - datefmt($lease['movein_date']), - datefmt($lease['moveout_date']), - $lease['amount'], - $lease['deposit'], - $lease['comment']); -} - -echo('' . "\n"); -echo(' ' . "\n"); -echo $html->tableHeaders($headers); -echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); -echo('
Lease History
' . "\n"); - - -/********************************************************************** - * Ledger History - */ -$security_deposit = 0; -$grand_total = 0; -foreach($tenant['Lease'] AS $lease) { - $headers = array('Date', /*'Through',*/ /*'Charge/Receipt'*/'ID', 'Type', 'Comment', 'Amount', 'Total'); - - $rows = array(); - $running_total = 0; - foreach($lease['Charge'] AS $charge) { - $amount = $charge['total']; - $running_total += $amount; - $rows[] = array(datefmt($charge['charge_date']) .' - '. datefmt($charge['charge_to_date']), - '#'.$charge['id'], - $charge['ChargeType']['name'], - $charge['comment'], - currency($amount), - currency($running_total)); - - foreach ($charge['Receipt'] AS $receipt) { - $amount = -1 * $receipt['ChargesReceipt']['amount']; - $running_total += $amount; - // REVISIT 20090527: - // Using hardcoded value for security deposit... can't be good! - if ($charge['charge_type_id'] == 1) - $security_deposit += $receipt['ChargesReceipt']['amount']; - $rows[] = array(' -- ' . datefmt($receipt['stamp']), - '#'.$receipt['id'], - 'Payment/Receipt', - $receipt['comment'], - currency($amount), - currency($running_total)); - } - } - $grand_total += $running_total; - - echo('' . "\n"); - echo(' ' . "\n"); - echo $html->tableHeaders($headers); - echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); - echo('
Lease #'.$lease['number'].' ('.$lease['Unit']['name'].')
' . "\n"); - -} -?> - -

Total Security Deposit:

-

Outstanding Balance:

-
diff --git a/site/views/transactions/ledger.ctp b/site/views/transactions/ledger.ctp deleted file mode 100644 index fd59df5..0000000 --- a/site/views/transactions/ledger.ctp +++ /dev/null @@ -1,53 +0,0 @@ - - -
-

- - $table) { - - if (array_key_exists(0, $table)) { - // Horizontal table (multiple items) - $headers = array_keys($table[0]); - - //$rows = array_map('array_values', $table); - $rows = array(); - //echo("
table:\n"); print_r($table); echo("
\n"); - foreach ($table as $row) { - //echo("
row:\n"); print_r($row); echo("
\n"); - $rows[] = array_values($row); - } - } - else { - // Vertical table (one item) - $headers = array('Field', 'Value'); - - $rows = array(); - foreach ($table as $col => $val) { - $rows[] = array($col, $val); - } - } - - foreach($rows AS &$row) { - foreach ($row AS &$cell) { - if (is_array($cell)) - $cell = "<ARRAY>"; - } - } - //echo("
headers:\n"); print_r($headers); echo("
\n"); - //echo("
rows:\n"); print_r($rows); echo("
\n"); - ?> - - - tableHeaders($headers); - echo $html->tableCells($rows, null, array('class' => "altrow")); - ?> -
- - -
\ No newline at end of file diff --git a/site/views/transactions/ledger_1.ctp b/site/views/transactions/ledger_1.ctp deleted file mode 100644 index 316e24a..0000000 --- a/site/views/transactions/ledger_1.ctp +++ /dev/null @@ -1,58 +0,0 @@ -
-

- - -counter(array( - 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); - - $cells = array($paginator->sort('id'), - $paginator->sort('charge_type_id'), - $paginator->sort('lease_id'), - $paginator->sort('charge_date'), - $paginator->sort('charge_to_date'), - $paginator->sort('due_date'), - $paginator->sort('amount'), - $paginator->sort('tax'), - $paginator->sort('total'), - $paginator->sort('comment')); -} else { - $cells = array('Id', 'Type', 'Lease', 'Date', 'Through', 'Due', 'Amount', 'Tax', 'Total', 'Comment'); -} -echo $html->tableHeaders($cells); - -$cells = array(); -foreach ($ledgers as $ledger) { - $cells[] = array($html->link($ledger['Charge']['id'], - array('controller' => 'transactions', - 'action' => 'view', - $ledger['Charge']['id'])), - $ledger['Charge']['charge_type_id'], - $ledger['Charge']['lease_id'], - $ledger['Charge']['charge_date'], - $ledger['Charge']['charge_to_date'], - $ledger['Charge']['due_date'], - $ledger['Charge']['amount'], - $ledger['Charge']['tax'], - $ledger['Charge']['total'], - $ledger['Charge']['comment']); -} -echo $html->tableCells($cells, null, array('class' => "altrow")); -?> -
- -' . "\n"); - echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); - echo(' | '); - echo $paginator->numbers(); - echo(' | '); - echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); - echo('
' . "\n"); - } -?> - - - \ No newline at end of file From ed04f81dda882563016a1aad357f7034425c8cc1 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 28 May 2009 08:03:12 +0000 Subject: [PATCH 020/717] Modified to allow the display_name to be NULL git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@21 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 4 +++- scripts/sitelink2pmgr.pl | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index a014c03..fb9cc13 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -127,7 +127,7 @@ CREATE TABLE `pmgr_contacts` ( `middle_name` VARCHAR(255) DEFAULT NULL, `last_name` VARCHAR(255) DEFAULT NULL, `company_name` VARCHAR(255) DEFAULT NULL, - `display_name` VARCHAR(512) NOT NULL, + `display_name` VARCHAR(512) DEFAULT NULL, -- FEDERAL ID, e.g. SSN or EIN `id_federal` VARCHAR(16) DEFAULT NULL, @@ -137,6 +137,8 @@ CREATE TABLE `pmgr_contacts` ( `id_state` CHAR(2) DEFAULT NULL, `id_exp` DATE DEFAULT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 5d95b4f..dd3ce4c 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -513,7 +513,7 @@ foreach $row (@$result) { $row->{'AltLastName'} || undef, ($row->{'AltLastName'} && $row->{'AltFirstName'} ? "$row->{'AltLastName'}, $row->{'AltFirstName'}" - : ($row->{'AltLastName'} || $row->{'AltFirstName'} || ''))) + : ($row->{'AltLastName'} || $row->{'AltFirstName'} || undef))) )) . ")"; query($db_handle, $query) || die("Unable to insert"); From 839340344325a33f88c99c2abe0437b0f201026e Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 28 May 2009 08:04:22 +0000 Subject: [PATCH 021/717] First pass at listing the customers. Need to figure out how to paginate based on a HABTM relationship. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@22 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/contacts_controller.php | 26 ++++++++- site/views/contacts/index.ctp | 3 + site/views/elements/contacts.ctp | 74 ++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 site/views/contacts/index.ctp create mode 100644 site/views/elements/contacts.ctp diff --git a/site/controllers/contacts_controller.php b/site/controllers/contacts_controller.php index f372274..a8e789a 100644 --- a/site/controllers/contacts_controller.php +++ b/site/controllers/contacts_controller.php @@ -2,7 +2,31 @@ class ContactsController extends AppController { var $helpers = array('Html'); - + + var $paginate = array('limit' => 100, + 'order' => array('Contact.last_name' => 'ASC', + 'Contact.first_name' => 'ASC')); + + function index() { + $this->all(); + } + + function current() { + $this->Contact->recursive = 0; + $this->set('contacts', $this->paginate(array('Lease.closed_date IS NULL', + //'Contact.' + ))); + $this->render('index'); + } + + function all() { + $this->Contact->recursive = 2; + + //$contacts = $this->paginate(); + $this->set('contacts', $this->paginate()); + $this->render('index'); + } + function view($id = null) { if (!$id) { $this->Session->setFlash(__('Invalid Item.', true)); diff --git a/site/views/contacts/index.ctp b/site/views/contacts/index.ctp new file mode 100644 index 0000000..15d92e7 --- /dev/null +++ b/site/views/contacts/index.ctp @@ -0,0 +1,3 @@ +
+element('contacts') ?> +
diff --git a/site/views/elements/contacts.ctp b/site/views/elements/contacts.ctp new file mode 100644 index 0000000..041d428 --- /dev/null +++ b/site/views/elements/contacts.ctp @@ -0,0 +1,74 @@ + + +

+'.__('Contacts',true).''; +?> +

+ + + + counter(array( + 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); + + $rows = array($paginator->sort('id'), + $paginator->sort('last_name'), + $paginator->sort('first_name'), + $paginator->sort('company_name'), + //$paginator->sort('unit_id'), + $paginator->sort('comment')); + } else { + $rows = array('Id', 'Last Name', 'First Name', 'Company', 'Comment'); + } + echo $html->tableHeaders($rows); + + $rows = array(); + foreach ($contacts as $contact) { +/* // REVISIT 20090528: */ +/* // The controller really should handle this, but at the moment */ +/* // it's not clear how. So, let's just cheat. */ +/* $primary = 0; */ +/* foreach ($contact['Lease'] AS $lease) { */ +/* if ($lease['ContactsLease']['type'] != 'ALTERNATE') */ +/* $primary = 1; */ +/* } */ +/* if (!$primary) */ +/* continue; */ + + $rows[] = array($html->link($contact['Contact']['id'], + array('controller' => 'contacts', + 'action' => 'view', + $contact['Contact']['id'])), + $html->link($contact['Contact']['last_name'], + array('controller' => 'contacts', + 'action' => 'view', + $contact['Contact']['id'])), + $html->link($contact['Contact']['first_name'], + array('controller' => 'contacts', + 'action' => 'view', + $contact['Contact']['id'])), + $contact['Contact']['company_name'], + $contact['Contact']['comment']); + } + echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); + } +?> +
+ +' . "\n"); + echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); + echo(' | '); + echo $paginator->numbers(); + echo(' | '); + echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); + echo('' . "\n"); + } +?> From 7433e6868c6053412fa389a75d74e50647b8958e Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 28 May 2009 09:07:53 +0000 Subject: [PATCH 022/717] Fixed duplicate row entries and other paginate issues. The fix might be a hack, but it works for now. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@23 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/contacts_controller.php | 21 ++++++++++++++------- site/models/contact.php | 13 +++++++++++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/site/controllers/contacts_controller.php b/site/controllers/contacts_controller.php index a8e789a..eaf90df 100644 --- a/site/controllers/contacts_controller.php +++ b/site/controllers/contacts_controller.php @@ -13,17 +13,24 @@ class ContactsController extends AppController { function current() { $this->Contact->recursive = 0; - $this->set('contacts', $this->paginate(array('Lease.closed_date IS NULL', - //'Contact.' - ))); + $this->Contact->bindModel(array('hasOne' => array('ContactsLease', + 'Lease' => array( + 'foreignKey' => false, + 'conditions' => array('Lease.id = ContactsLease.lease_id') + ))), + false); + + $this->set('contacts', $this->paginate(array('Lease.close_date IS NULL', + 'ContactsLease.type != "ALTERNATE"'))); $this->render('index'); } function all() { - $this->Contact->recursive = 2; - - //$contacts = $this->paginate(); - $this->set('contacts', $this->paginate()); + $this->Contact->recursive = 0; + $this->Contact->bindModel(array('hasOne' => array('ContactsLease')), + false); + + $this->set('contacts', $this->paginate(array('ContactsLease.type != "ALTERNATE"'))); $this->render('index'); } diff --git a/site/models/contact.php b/site/models/contact.php index 5aab7f3..96d12bb 100644 --- a/site/models/contact.php +++ b/site/models/contact.php @@ -72,5 +72,18 @@ class Contact extends AppModel { ), ); + // Overriding pagination, since the controller using HABTM joins that + // result in duplicate rows. This may not be the best way to handle + // things (especially if the query return a really large number of rows, + // but it does seem to work. + function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null) { + $conditions[] ="1=1 GROUP BY Contact.id"; + return $this->findAll($conditions, $fields, $order, $limit, $page, $recursive); + } + function paginateCount($conditions = null, $recursive = 0) { + $rows = $this->paginate($conditions, null, null, null, null, $recursive); + return count($rows); + } + } ?> \ No newline at end of file From aed2c6912cbd9425cf3309fe395d69cd332a62fa Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 28 May 2009 09:27:29 +0000 Subject: [PATCH 023/717] Added more models git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@24 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/account.php | 29 +++++++++++++++++++++++ site/models/map.php | 44 +++++++++++++++++++++++++++++++++++ site/models/maps_unit.php | 15 ++++++++++++ site/models/site.php | 41 ++++++++++++++++++++++++++++++++ site/models/site_area.php | 34 +++++++++++++++++++++++++++ site/models/unit.php | 49 +++++++++++++++++++++++++++++++++++++++ site/models/unit_size.php | 44 +++++++++++++++++++++++++++++++++++ site/models/unit_type.php | 29 +++++++++++++++++++++++ 8 files changed, 285 insertions(+) create mode 100644 site/models/account.php create mode 100644 site/models/map.php create mode 100644 site/models/maps_unit.php create mode 100644 site/models/site.php create mode 100644 site/models/site_area.php create mode 100644 site/models/unit.php create mode 100644 site/models/unit_size.php create mode 100644 site/models/unit_type.php diff --git a/site/models/account.php b/site/models/account.php new file mode 100644 index 0000000..35eeca0 --- /dev/null +++ b/site/models/account.php @@ -0,0 +1,29 @@ + array('numeric'), + 'name' => array('notempty'), + 'external_name' => array('notempty') + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + var $hasMany = array( + 'ChargeType' => array( + 'className' => 'ChargeType', + 'foreignKey' => 'account_id', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); + +} +?> \ No newline at end of file diff --git a/site/models/map.php b/site/models/map.php new file mode 100644 index 0000000..c9c2c2e --- /dev/null +++ b/site/models/map.php @@ -0,0 +1,44 @@ + array('numeric'), + 'site_id' => array('numeric'), + 'site_area_id' => array('numeric'), + 'name' => array('notempty'), + 'width' => array('numeric'), + 'depth' => array('numeric') + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + var $belongsTo = array( + 'SiteArea' => array( + 'className' => 'SiteArea', + 'foreignKey' => 'site_area_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ) + ); + + var $hasAndBelongsToMany = array( + 'Unit' => array( + 'className' => 'Unit', + 'joinTable' => 'maps_units', + 'foreignKey' => 'map_id', + 'associationForeignKey' => 'unit_id', + 'unique' => true, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'finderQuery' => '', + 'deleteQuery' => '', + 'insertQuery' => '' + ) + ); + +} +?> \ No newline at end of file diff --git a/site/models/maps_unit.php b/site/models/maps_unit.php new file mode 100644 index 0000000..4486e27 --- /dev/null +++ b/site/models/maps_unit.php @@ -0,0 +1,15 @@ + array('numeric'), + 'map_id' => array('numeric'), + 'unit_id' => array('numeric'), + 'pt_top' => array('numeric'), + 'pt_left' => array('numeric'), + 'transpose' => array('boolean') + ); + +} +?> \ No newline at end of file diff --git a/site/models/site.php b/site/models/site.php new file mode 100644 index 0000000..d2882df --- /dev/null +++ b/site/models/site.php @@ -0,0 +1,41 @@ + array('numeric'), + 'name' => array('notempty') + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + var $hasMany = array( + 'SiteArea' => array( + 'className' => 'SiteArea', + 'foreignKey' => 'site_id', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ), + 'SiteOption' => array( + 'className' => 'SiteOption', + 'foreignKey' => 'site_id', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); + +} +?> \ No newline at end of file diff --git a/site/models/site_area.php b/site/models/site_area.php new file mode 100644 index 0000000..1aec59f --- /dev/null +++ b/site/models/site_area.php @@ -0,0 +1,34 @@ + array('numeric'), + 'site_id' => array('numeric'), + 'name' => array('notempty') + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + var $belongsTo = array( + 'Site' => array( + 'className' => 'Site', + 'foreignKey' => 'site_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ) + ); + + var $hasOne = array( + 'Map' => array( + 'className' => 'Map', + 'foreignKey' => 'site_area_id', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '' + ) + ); + +} +?> \ No newline at end of file diff --git a/site/models/unit.php b/site/models/unit.php new file mode 100644 index 0000000..643065a --- /dev/null +++ b/site/models/unit.php @@ -0,0 +1,49 @@ + 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' => array( + 'className' => 'UnitSize', + 'foreignKey' => 'unit_size_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ), +/* 'Map' => array( */ +/* 'className' => 'MapsUnit', */ +/* 'foreignKey' => 'unit_id', */ +/* 'conditions' => '', */ +/* 'fields' => '', */ +/* 'order' => '' */ +/* ) */ + ); + + var $hasMany = array( + 'Lease' => array( + 'className' => 'Lease', + 'foreignKey' => 'unit_id', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); + +} +?> \ No newline at end of file diff --git a/site/models/unit_size.php b/site/models/unit_size.php new file mode 100644 index 0000000..5bb39f8 --- /dev/null +++ b/site/models/unit_size.php @@ -0,0 +1,44 @@ + 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') + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + var $belongsTo = array( + 'UnitType' => array( + 'className' => 'UnitType', + 'foreignKey' => 'unit_type_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ) + ); + + var $hasMany = array( + 'Unit' => array( + 'className' => 'Unit', + 'foreignKey' => 'unit_size_id', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); + +} +?> \ No newline at end of file diff --git a/site/models/unit_type.php b/site/models/unit_type.php new file mode 100644 index 0000000..06f59e4 --- /dev/null +++ b/site/models/unit_type.php @@ -0,0 +1,29 @@ + array('numeric'), + 'code' => array('notempty'), + 'name' => array('notempty') + ); + + //The Associations below have been created with all possible keys, those that are not needed can be removed + var $hasMany = array( + 'UnitSize' => array( + 'className' => 'UnitSize', + 'foreignKey' => 'unit_type_id', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); + +} +?> \ No newline at end of file From e38e99c94e95c0e3e486a839b300c66a52a5d070 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 28 May 2009 09:36:58 +0000 Subject: [PATCH 024/717] Removed the revisit code, as use of it would only screw up pagination anyway. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@25 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/contacts.ctp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/site/views/elements/contacts.ctp b/site/views/elements/contacts.ctp index 041d428..f28baa3 100644 --- a/site/views/elements/contacts.ctp +++ b/site/views/elements/contacts.ctp @@ -30,17 +30,6 @@ $rows = array(); foreach ($contacts as $contact) { -/* // REVISIT 20090528: */ -/* // The controller really should handle this, but at the moment */ -/* // it's not clear how. So, let's just cheat. */ -/* $primary = 0; */ -/* foreach ($contact['Lease'] AS $lease) { */ -/* if ($lease['ContactsLease']['type'] != 'ALTERNATE') */ -/* $primary = 1; */ -/* } */ -/* if (!$primary) */ -/* continue; */ - $rows[] = array($html->link($contact['Contact']['id'], array('controller' => 'contacts', 'action' => 'view', From ec3d986c783b9e8001a793f4d3e873a262cab39a Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 28 May 2009 11:09:19 +0000 Subject: [PATCH 025/717] Removed site_id from the maps table, since the it already references site_area_id which fully qualifies the site anyway. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@26 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 2 -- 1 file changed, 2 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index fb9cc13..d78adee 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -957,7 +957,6 @@ CREATE TABLE `pmgr_charges_receipts` ( DROP TABLE IF EXISTS `pmgr_maps`; CREATE TABLE `pmgr_maps` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `site_id` INT(10) UNSIGNED NOT NULL, `site_area_id` INT(10) UNSIGNED NOT NULL, `name` VARCHAR(80) DEFAULT NULL, `comment` VARCHAR(255) DEFAULT NULL, @@ -965,7 +964,6 @@ CREATE TABLE `pmgr_maps` ( `width` SMALLINT UNSIGNED NOT NULL, -- inches `depth` SMALLINT UNSIGNED NOT NULL, -- inches - UNIQUE KEY `map_key` (`site_id`, `site_area_id`), PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; From 4a86d3dda0e58014dfc1cd992794fd5618da586d Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 28 May 2009 11:09:56 +0000 Subject: [PATCH 026/717] Removal of site_id from the maps table, corresponding with the last checkin git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@27 97e9348a-65ac-dc4b-aefc-98561f571b83 --- scripts/sitelink2pmgr.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index dd3ce4c..63ef777 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -376,8 +376,8 @@ $info{'extents'}{'bottom'} = $internal_adjustment_factor * ($top_adjustment + $ $info{'extents'}{'right'} = $internal_adjustment_factor * ($left_adjustment + $row->{'rgt'} + 0); $query = - "INSERT INTO pmgr_maps (id, site_id, site_area_id, width, depth) VALUES\n" . - " (1, $aicur_site_id, $aicur_area_id," . + "INSERT INTO pmgr_maps (id, site_area_id, width, depth) VALUES\n" . + " (1, $aicur_area_id," . ($info{'extents'}{'right'} - $info{'extents'}{'left'}) . ", " . ($info{'extents'}{'bottom'} - $info{'extents'}{'top'}) . ")"; query($db_handle, $query) || die("Unable to insert"); From 5c6189cdefb9204f6ba0d7e71bbcc600f032a71d Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 28 May 2009 11:26:09 +0000 Subject: [PATCH 027/717] Added preliminary support for units. The queries are giving me a heck of a time, so I've cheated in some places. For the most part though, it's working. Also, something went wrong with svn, and view/contacts/view.ctp was not right (a checkin seems to have been omitted on it). This checking brings it up to date. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@28 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/units_controller.php | 123 ++++++++++++++++++++ site/models/unit_size.php | 1 - site/models/unit_type.php | 1 - site/views/contacts/view.ctp | 156 +++++++++++++++++++++++--- site/views/elements/units.ctp | 59 ++++++++++ site/views/units/index.ctp | 3 + site/views/units/view.ctp | 113 +++++++++++++++++++ 7 files changed, 439 insertions(+), 17 deletions(-) create mode 100644 site/controllers/units_controller.php create mode 100644 site/views/elements/units.ctp create mode 100644 site/views/units/index.ctp create mode 100644 site/views/units/view.ctp diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php new file mode 100644 index 0000000..fe21434 --- /dev/null +++ b/site/controllers/units_controller.php @@ -0,0 +1,123 @@ + 100, + 'order' => array('Unit.sort_order' => 'ASC')); + + function index() { + $this->all(); + } + + function vacant() { + $this->Unit->recursive = 0; + $this->Unit->bindModel(array('hasOne' => array('UnitsLease', + 'Lease' => array( + 'foreignKey' => false, + 'conditions' => array('Lease.id = UnitsLease.lease_id') + ))), + false); + + $this->set('units', $this->paginate(array('Lease.close_date IS NULL', + 'UnitsLease.type != "ALTERNATE"'))); + $this->render('index'); + } + + function occupied() { + $this->Unit->recursive = 0; + $this->Unit->bindModel(array('hasOne' => array('UnitsLease', + 'Lease' => array( + 'foreignKey' => false, + 'conditions' => array('Lease.id = UnitsLease.lease_id') + ))), + false); + + $this->set('units', $this->paginate(array('Lease.close_date IS NULL', + 'UnitsLease.type != "ALTERNATE"'))); + $this->render('index'); + } + + function all() { + $this->Unit->recursive = 2; +/* $this->Unit->UnitSize->unbindModel(array('hasMany' => array('Unit'))); */ +/* $this->Unit->UnitSize->UnitType->unbindModel(array('hasMany' => array('UnitSize'))); */ + //$this->Unit->bindModel(array('hasOne' => array('UnitType'))); + //function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null) { + $this->set('units', $this->paginate(null, null, null, null, null, 2)); + $this->render('index'); + } + + function view($id = null) { + if (!$id) { + $this->Session->setFlash(__('Invalid Item.', true)); + $this->redirect(array('action'=>'')); + } + $this->Unit->recursive = 4; + $this->Unit->UnitSize->unbindModel(array('hasMany' => array('Unit'))); + $this->Unit->UnitSize->UnitType->unbindModel(array('hasMany' => array('UnitSize'))); + $this->Unit->Lease->unbindModel(array('belongsTo' => array('Unit'))); + $this->Unit->Lease->LeaseType->unbindModel(array('hasMany' => array('Lease'))); + $this->Unit->Lease->Charge->unbindModel(array('belongsTo' => array('Lease'))); + $this->Unit->Lease->Charge->ChargeType->unbindModel(array('hasMany' => array('Charge'))); + $this->Unit->Lease->Charge->Receipt->unbindModel(array('hasMany' => array('ChargesReceipt'))); + +/* //$this->Unit->Lease->unbindModel(array('hasMany' => array('Contact'))); */ +/* $this->Unit->Lease->unbindModel(array('hasAndBelongsToMany' => array('Contact'))); */ +/* //$this->Unit->Lease->unbindModel(array('hasOne' => array('Contact'))); */ +/* //$this->Unit->Lease->unbindModel(array('belongsTo' => array('Contact'))); */ +/* //$this->Unit->Lease->bindModel(array('hasOne' => array('ContactsLease'))); */ +/* //$this->Unit->Lease->bindModel(array('hasOne' => array('Contact'))); */ +/* /\* $this->Unit->Lease->bindModel(array('hasOne' => array('ContactsLease', *\/ */ +/* /\* 'Contact' => array( *\/ */ +/* /\* 'foreignKey' => false, *\/ */ +/* /\* 'conditions' => *\/ */ +/* /\* array('Contact.id = ContactsLease.contact_id', *\/ */ +/* /\* //'ContactsLease.type = "TENANT"' *\/ */ +/* /\* ))))); *\/ */ + +/* $this->Unit->bindModel(array('hasOne' => array('Lease' => array( */ +/* 'foreignKey' => false, */ +/* 'conditions' => array('Lease.unit_id = Unit.id') */ +/* ), */ +/* 'ContactsLease' => array( */ +/* 'foreignKey' => false, */ +/* 'conditions' => array('ContactsLease.lease_id = Lease.id') */ +/* ), */ +/* 'Contact' => array( */ +/* 'foreignKey' => false, */ +/* 'conditions' => array('Contact.id = ContactsLease.contact_id') */ +/* ))), */ +/* false); */ + + +/* $this->Unit->Lease->bindModel(array('hasOne' => array('Contact' => array( */ +/* 'className' => 'ContactsLease', */ +/* 'foreignKey' => false, */ +/* 'conditions' => */ +/* array('ContactsLease.lease_id = Lease.id', */ +/* 'ContactsLease.type = "TENANT"'))))); */ + +/* # 'hasOne' => array( */ +/* # 'RecipesTag', */ +/* # 'FilterTag' => array( */ +/* # 'className' => 'Tag', */ +/* # 'foreignKey' => false, */ +/* # 'conditions' => array('FilterTag.id = RecipesTag.tag_id') */ +/* # )))); */ + + $this->set('unit', $this->Unit->read(null, $id)); +/* $this->Unit->id = $id; */ +/* if ($id !== null && $id !== false) { */ +/* $this->Unit->data = $this->Unit->find('first', */ +/* array('conditions' => array( */ +/* $this->Unit->alias . '.' . $this->Unit->primaryKey => $id, */ +/* 'ContactsLease.type = "TENANT"' */ +/* ) */ +/* )); */ +/* $this->set('unit', $this->Unit->data); */ +/* } */ + } +} + +?> \ No newline at end of file diff --git a/site/models/unit_size.php b/site/models/unit_size.php index 5bb39f8..29d1a2f 100644 --- a/site/models/unit_size.php +++ b/site/models/unit_size.php @@ -13,7 +13,6 @@ class UnitSize extends AppModel { 'amount' => array('money') ); - //The Associations below have been created with all possible keys, those that are not needed can be removed var $belongsTo = array( 'UnitType' => array( 'className' => 'UnitType', diff --git a/site/models/unit_type.php b/site/models/unit_type.php index 06f59e4..8488ca0 100644 --- a/site/models/unit_type.php +++ b/site/models/unit_type.php @@ -8,7 +8,6 @@ class UnitType extends AppModel { 'name' => array('notempty') ); - //The Associations below have been created with all possible keys, those that are not needed can be removed var $hasMany = array( 'UnitSize' => array( 'className' => 'UnitSize', diff --git a/site/views/contacts/view.ctp b/site/views/contacts/view.ctp index 18d6021..5d6e968 100644 --- a/site/views/contacts/view.ctp +++ b/site/views/contacts/view.ctp @@ -6,22 +6,145 @@ $val) { - $rows[] = array(array($col, 'width=1%'), $val); +function phone($phone) { + $phone = preg_replace("/\D/", "", $phone); + if(strlen($phone) == 7) + return preg_replace("/(\d{3})(\d{4})/", "$1-$2", $phone); + elseif(strlen($phone) == 10) + return preg_replace("/(\d{3})(\d{3})(\d{4})/", "$1-$2-$3", $phone); + else + return $phone; } + +function datefmt($date) { + $date_fmt = 'm/d/Y'; + return ($date + ? date_format(date_create($date), $date_fmt) + : null); +} + +/********************************************************************** + * Tenant Info + */ echo('' . "\n"); echo(' ' . "\n"); -echo $html->tableCells($rows, null, array('class' => "altrow")); +echo $html->tableCells(array(array('Name', $tenant['Contact']['display_name']), + array('Company', $tenant['Contact']['company_name']), + array('SSN', $tenant['Contact']['id_federal']), + array('ID', $tenant['Contact']['id_num'] + . ($tenant['Contact']['id_state'] + ? " - ".$tenant['Contact']['id_state'] + : "")), + array('Comment', $tenant['Contact']['comment'])), + null, array('class' => "altrow"), false, false); echo('
Tenant Info
' . "\n"); + +/********************************************************************** + * Phones + */ +$headers = array('Location', 'Preference', 'Type', 'Phone', 'Extension', 'Comment'); +$rows = array(); +foreach($tenant['ContactPhone'] AS $phone) { + $rows[] = array($phone['ContactsMethod']['type'], + $phone['ContactsMethod']['preference'], + $phone['type'], + phone($phone['phone']), + $phone['ext'], + $phone['comment']); +} + +if (count($rows)) { + echo('' . "\n"); + echo(' ' . "\n"); + echo $html->tableHeaders($headers); + echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); + echo('
Phone
' . "\n"); +} + + +/********************************************************************** + * Emails + */ +$headers = array('Location', 'Preference', 'Email', 'Comment'); +$rows = array(); +foreach($tenant['ContactEmail'] AS $email) { + $rows[] = array($email['ContactsMethod']['type'], + $email['ContactsMethod']['preference'], + $email['email'], + $email['comment']); +} + +if (count($rows)) { + echo('' . "\n"); + echo(' ' . "\n"); + echo $html->tableHeaders($headers); + echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); + echo('
Email
' . "\n"); +} + + +/********************************************************************** + * Addresses + */ +$headers = array('Location', 'Preference', 'Address', 'City', 'State', 'Zip', 'Country', 'Comment'); +$rows = array(); +foreach($tenant['ContactAddress'] AS $address) { + $rows[] = array($address['ContactsMethod']['type'], + $address['ContactsMethod']['preference'], + $address['address'], + $address['city'], + $address['state'], + $address['postcode'], + $address['country'], + $address['comment']); +} + +if (count($rows)) { + echo('' . "\n"); + echo(' ' . "\n"); + echo $html->tableHeaders($headers); + echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); + echo('
Address
' . "\n"); +} + + +/********************************************************************** + * Lease History + */ +$headers = array('Lease', 'Unit', 'Signed', 'Move-In', 'Move-Out', 'Rent', 'Deposit', 'Comment'); +$rows = array(); +foreach($tenant['Lease'] AS $lease) { + $rows[] = array('#'.$lease['id'], + $html->link($lease['Unit']['name'], + array('controller' => 'units', + 'action' => 'view', + $lease['Unit']['id'])), + datefmt($lease['lease_date']), + datefmt($lease['movein_date']), + datefmt($lease['moveout_date']), + $lease['amount'], + $lease['deposit'], + $lease['comment']); +} + +echo('' . "\n"); +echo(' ' . "\n"); +echo $html->tableHeaders($headers); +echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); +echo('
Lease History
' . "\n"); + + +/********************************************************************** + * Ledger History + */ +$security_deposit = 0; $grand_total = 0; foreach($tenant['Lease'] AS $lease) { $headers = array('Date', /*'Through',*/ /*'Charge/Receipt'*/'ID', 'Type', 'Comment', 'Amount', 'Total'); @@ -31,8 +154,7 @@ foreach($tenant['Lease'] AS $lease) { foreach($lease['Charge'] AS $charge) { $amount = $charge['total']; $running_total += $amount; - $rows[] = array(date_format(date_create($charge['charge_date']), 'm-d-Y') . ' - ' . - date_format(date_create($charge['charge_to_date']), 'm-d-Y'), + $rows[] = array(datefmt($charge['charge_date']) .' - '. datefmt($charge['charge_to_date']), '#'.$charge['id'], $charge['ChargeType']['name'], $charge['comment'], @@ -42,10 +164,13 @@ foreach($tenant['Lease'] AS $lease) { foreach ($charge['Receipt'] AS $receipt) { $amount = -1 * $receipt['ChargesReceipt']['amount']; $running_total += $amount; - $rows[] = array(' -- ' .date_format(date_create($receipt['stamp']), 'm-d-Y'), - //null, + // REVISIT 20090527: + // Using hardcoded value for security deposit... can't be good! + if ($charge['charge_type_id'] == 1) + $security_deposit += $receipt['ChargesReceipt']['amount']; + $rows[] = array(' -- ' . datefmt($receipt['stamp']), '#'.$receipt['id'], - 'Receipt', + 'Payment/Receipt', $receipt['comment'], currency($amount), currency($running_total)); @@ -54,13 +179,14 @@ foreach($tenant['Lease'] AS $lease) { $grand_total += $running_total; echo('' . "\n"); - echo(' ' . "\n"); + echo(' ' . "\n"); echo $html->tableHeaders($headers); - echo $html->tableCells($rows, null, array('class' => "altrow")); + echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); echo('
Lease #'.$lease['number'].' (Unit '.$lease['Unit']['name'].')Lease #'.$lease['number'].' ('.$lease['Unit']['name'].')
' . "\n"); } ?> -

Grand Total:

+

Total Security Deposit:

+

Outstanding Balance:

diff --git a/site/views/elements/units.ctp b/site/views/elements/units.ctp new file mode 100644 index 0000000..ca3b714 --- /dev/null +++ b/site/views/elements/units.ctp @@ -0,0 +1,59 @@ + + +

+'.__('Units',true).''; +?> +

+ + + + counter(array( + 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); + + $rows = array($paginator->sort('id'), + $paginator->sort('name'), + $paginator->sort('unit_size_id'), + $paginator->sort('status'), + $paginator->sort('comment')); + } else { + $rows = array('Id', 'Name', 'Size', 'Status', 'Comment'); + } + echo $html->tableHeaders($rows); + + $rows = array(); + foreach ($units as $unit) { + $rows[] = array($html->link($unit['Unit']['id'], + array('controller' => 'units', + 'action' => 'view', + $unit['Unit']['id'])), + $html->link($unit['Unit']['name'], + array('controller' => 'units', + 'action' => 'view', + $unit['Unit']['id'])), + $unit['UnitSize']['name'], + $unit['Unit']['status'], + $unit['Unit']['comment']); + } + echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); + } +?> +
+ +' . "\n"); + echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); + echo(' | '); + echo $paginator->numbers(); + echo(' | '); + echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); + echo('' . "\n"); + } +?> diff --git a/site/views/units/index.ctp b/site/views/units/index.ctp new file mode 100644 index 0000000..df3021c --- /dev/null +++ b/site/views/units/index.ctp @@ -0,0 +1,3 @@ +
+element('units') ?> +
diff --git a/site/views/units/view.ctp b/site/views/units/view.ctp new file mode 100644 index 0000000..6e2c113 --- /dev/null +++ b/site/views/units/view.ctp @@ -0,0 +1,113 @@ + + +
+

+ + $val) { + $rows[] = array(array($col, 'width=1%'), $val); +} + +echo('' . "\n"); +echo(' ' . "\n"); +echo $html->tableCells(array(array('Name', $unit['Unit']['name']), + array('Status', $unit['Unit']['status']), + array('Comment', $unit['Unit']['comment'])), + null, array('class' => "altrow"), false, false); +echo('
Unit Info
' . "\n"); + + +/********************************************************************** + * Lease History + */ +$headers = array('Lease', 'Tenant', 'Signed', 'Move-In', 'Move-Out', 'Rent', 'Deposit', 'Comment'); +$rows = array(); +foreach($unit['Lease'] AS $lease) { + $rows[] = array('#'.$lease['id'], + $html->link($lease['Contact'][0]['display_name'], + array('controller' => 'contacts', + 'action' => 'view', + $lease['Contact'][0]['id'])), + datefmt($lease['lease_date']), + datefmt($lease['movein_date']), + datefmt($lease['moveout_date']), + $lease['amount'], + $lease['deposit'], + $lease['comment']); +} + +echo('' . "\n"); +echo(' ' . "\n"); +echo $html->tableHeaders($headers); +echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); +echo('
Lease History
' . "\n"); + + +/********************************************************************** + * Ledger History + */ +$security_deposit = 0; +$grand_total = 0; +foreach($unit['Lease'] AS $lease) { + $headers = array('Date', /*'Through',*/ /*'Charge/Receipt'*/'ID', 'Type', 'Comment', 'Amount', 'Total'); + + $rows = array(); + $running_total = 0; + foreach($lease['Charge'] AS $charge) { + $amount = $charge['total']; + $running_total += $amount; + $rows[] = array(datefmt($charge['charge_date']) .' - '. datefmt($charge['charge_to_date']), + '#'.$charge['id'], + $charge['ChargeType']['name'], + $charge['comment'], + currency($amount), + currency($running_total)); + + foreach ($charge['Receipt'] AS $receipt) { + $amount = -1 * $receipt['ChargesReceipt']['amount']; + $running_total += $amount; + // REVISIT 20090527: + // Using hardcoded value for security deposit... can't be good! + if ($charge['charge_type_id'] == 1) + $security_deposit += $receipt['ChargesReceipt']['amount']; + $rows[] = array(' -- ' . datefmt($receipt['stamp']), + '#'.$receipt['id'], + 'Payment/Receipt', + $receipt['comment'], + currency($amount), + currency($running_total)); + } + } + $grand_total += $running_total; + + echo('' . "\n"); + echo(' ' . "\n"); + echo $html->tableHeaders($headers); + echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); + echo('
Lease #'.$lease['number'].' ('.$lease['Contact'][0]['display_name'].')
' . "\n"); + +} +?> + +

Total Security Deposit:

+

Outstanding Balance:

+
From dbe037fee8d978d65c53f33fb81e09e317c48dc9 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 28 May 2009 21:52:14 +0000 Subject: [PATCH 028/717] Added support for querying only occupied or vacant units. It's working at the moment, but I'll probably move some more logic to the controller next. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@29 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_model.php | 39 ++++++++++++++++++++++++++- site/controllers/units_controller.php | 20 ++------------ site/models/unit.php | 5 +++- site/views/elements/units.ctp | 4 +-- 4 files changed, 46 insertions(+), 22 deletions(-) diff --git a/site/app_model.php b/site/app_model.php index 7d083b0..a4e1079 100644 --- a/site/app_model.php +++ b/site/app_model.php @@ -37,5 +37,42 @@ * @subpackage cake.app */ class AppModel extends Model { + + + /** + * 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, $respectDefault=false) + { + if ($columnName==null) { return array(); } //no field specified + + //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("','", preg_replace("/(enum)\('(.+?)'\)/","\\2", $types)) + )); + } //end getEnumValues + } -?> \ No newline at end of file diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index fe21434..e6569b3 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -12,29 +12,13 @@ class UnitsController extends AppController { function vacant() { $this->Unit->recursive = 0; - $this->Unit->bindModel(array('hasOne' => array('UnitsLease', - 'Lease' => array( - 'foreignKey' => false, - 'conditions' => array('Lease.id = UnitsLease.lease_id') - ))), - false); - - $this->set('units', $this->paginate(array('Lease.close_date IS NULL', - 'UnitsLease.type != "ALTERNATE"'))); + $this->set('units', $this->paginate(array('Unit.status < ' . $this->Unit->occupiedEnumValue()))); $this->render('index'); } function occupied() { $this->Unit->recursive = 0; - $this->Unit->bindModel(array('hasOne' => array('UnitsLease', - 'Lease' => array( - 'foreignKey' => false, - 'conditions' => array('Lease.id = UnitsLease.lease_id') - ))), - false); - - $this->set('units', $this->paginate(array('Lease.close_date IS NULL', - 'UnitsLease.type != "ALTERNATE"'))); + $this->set('units', $this->paginate(array('Unit.status >= ' . $this->Unit->occupiedEnumValue()))); $this->render('index'); } diff --git a/site/models/unit.php b/site/models/unit.php index 643065a..72c1af9 100644 --- a/site/models/unit.php +++ b/site/models/unit.php @@ -45,5 +45,8 @@ class Unit extends AppModel { ) ); + function occupiedEnumValue() { + $enums = $this->getEnumValues('status'); + return $enums['OCCUPIED']; + } } -?> \ No newline at end of file diff --git a/site/views/elements/units.ctp b/site/views/elements/units.ctp index ca3b714..ee19ea9 100644 --- a/site/views/elements/units.ctp +++ b/site/views/elements/units.ctp @@ -18,12 +18,12 @@ 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); $rows = array($paginator->sort('id'), - $paginator->sort('name'), + $paginator->sort('Unit', 'name'), $paginator->sort('unit_size_id'), $paginator->sort('status'), $paginator->sort('comment')); } else { - $rows = array('Id', 'Name', 'Size', 'Status', 'Comment'); + $rows = array('Id', 'Unit', 'Size', 'Status', 'Comment'); } echo $html->tableHeaders($rows); From 15930fae30f329a863f37f2b946de5ca82bda664 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 28 May 2009 22:09:04 +0000 Subject: [PATCH 029/717] Moved the unit status logic into the model where it belongs. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@30 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/units_controller.php | 10 ++++++-- site/models/unit.php | 33 ++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index e6569b3..6e0e931 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -10,15 +10,21 @@ class UnitsController extends AppController { $this->all(); } + function unavailable() { + $this->Unit->recursive = 0; + $this->set('units', $this->paginate(array($this->Unit->conditionUnavailable()))); + $this->render('index'); + } + function vacant() { $this->Unit->recursive = 0; - $this->set('units', $this->paginate(array('Unit.status < ' . $this->Unit->occupiedEnumValue()))); + $this->set('units', $this->paginate(array($this->Unit->conditionVacant()))); $this->render('index'); } function occupied() { $this->Unit->recursive = 0; - $this->set('units', $this->paginate(array('Unit.status >= ' . $this->Unit->occupiedEnumValue()))); + $this->set('units', $this->paginate(array($this->Unit->conditionOccupied()))); $this->render('index'); } diff --git a/site/models/unit.php b/site/models/unit.php index 72c1af9..fb0b173 100644 --- a/site/models/unit.php +++ b/site/models/unit.php @@ -45,8 +45,35 @@ class Unit extends AppModel { ) ); - function occupiedEnumValue() { - $enums = $this->getEnumValues('status'); - return $enums['OCCUPIED']; + function statusEnums() { + static $status_enums; + if (!isset($status_enums)) + $status_enums = $this->getEnumValues('status'); + return $status_enums; } + + function statusValue($enum) { + $enums = $this->statusEnums(); + return $enums[$enum]; + } + + function occupiedEnumValue() { + return statusValue('OCCUPIED'); + } + + function conditionOccupied() { + return ('Unit.status >= ' . $this->statusValue('OCCUPIED')); + } + + function conditionVacant() { + return ('Unit.status BETWEEN ' . + ($this->statusValue('UNAVAILABLE')+1) . + ' AND ' . + ($this->statusValue('OCCUPIED')-1)); + } + + function conditionUnavailable() { + return ('Unit.status <= ' . $this->statusValue('UNAVAILABLE')); + } + } From 3cc8e95ff49015e92c1bc3548407734e02d86f93 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 28 May 2009 23:18:20 +0000 Subject: [PATCH 030/717] Added a name for our lone map git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@31 97e9348a-65ac-dc4b-aefc-98561f571b83 --- scripts/sitelink2pmgr.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 63ef777..ea0db31 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -376,8 +376,8 @@ $info{'extents'}{'bottom'} = $internal_adjustment_factor * ($top_adjustment + $ $info{'extents'}{'right'} = $internal_adjustment_factor * ($left_adjustment + $row->{'rgt'} + 0); $query = - "INSERT INTO pmgr_maps (id, site_area_id, width, depth) VALUES\n" . - " (1, $aicur_area_id," . + "INSERT INTO pmgr_maps (id, name, site_area_id, width, depth) VALUES\n" . + " (1, 'Main Facility Map', $aicur_area_id," . ($info{'extents'}{'right'} - $info{'extents'}{'left'}) . ", " . ($info{'extents'}{'bottom'} - $info{'extents'}{'top'}) . ")"; query($db_handle, $query) || die("Unable to insert"); From 9fc5562dd82ca2ceb6603b72aa579e5b7421267f Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 29 May 2009 01:47:12 +0000 Subject: [PATCH 031/717] Adding mapping ability. Incomplete as of yet, but coming along nicely. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@32 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/maps_controller.php | 308 +++++++++++++++++++++++++++ site/views/elements/maps.ctp | 61 ++++++ site/views/maps/image.ctp | 95 +++++++++ site/views/maps/index.ctp | 3 + site/views/maps/view.ctp | 25 +++ 5 files changed, 492 insertions(+) create mode 100644 site/controllers/maps_controller.php create mode 100644 site/views/elements/maps.ctp create mode 100644 site/views/maps/image.ctp create mode 100644 site/views/maps/index.ctp create mode 100644 site/views/maps/view.ctp diff --git a/site/controllers/maps_controller.php b/site/controllers/maps_controller.php new file mode 100644 index 0000000..fe97ee7 --- /dev/null +++ b/site/controllers/maps_controller.php @@ -0,0 +1,308 @@ +Map->recursive = 0; +/* $this->Map->MapSize->unbindModel(array('hasMany' => array('Map'))); */ +/* $this->Map->MapSize->MapType->unbindModel(array('hasMany' => array('MapSize'))); */ + //$this->Map->bindModel(array('hasOne' => array('MapType'))); + //function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null) { + $this->set('maps', $this->paginate(null, null, null, null, null, 0)); + } + + function view($id = null) { + if (!$id) { + $this->Session->setFlash(__('Invalid Item.', true)); + $this->redirect(array('action'=>'index')); + } + $this->Map->recursive = 0; + $this->set('map', $this->Map->read(null, $id)); + +/* $this->Map->MapSize->unbindModel(array('hasMany' => array('Map'))); */ +/* $this->Map->MapSize->MapType->unbindModel(array('hasMany' => array('MapSize'))); */ +/* $this->Map->Lease->unbindModel(array('belongsTo' => array('Map'))); */ +/* $this->Map->Lease->LeaseType->unbindModel(array('hasMany' => array('Lease'))); */ +/* $this->Map->Lease->Charge->unbindModel(array('belongsTo' => array('Lease'))); */ +/* $this->Map->Lease->Charge->ChargeType->unbindModel(array('hasMany' => array('Charge'))); */ +/* $this->Map->Lease->Charge->Receipt->unbindModel(array('hasMany' => array('ChargesReceipt'))); */ + +/* //$this->Map->Lease->unbindModel(array('hasMany' => array('Contact'))); */ +/* $this->Map->Lease->unbindModel(array('hasAndBelongsToMany' => array('Contact'))); */ +/* //$this->Map->Lease->unbindModel(array('hasOne' => array('Contact'))); */ +/* //$this->Map->Lease->unbindModel(array('belongsTo' => array('Contact'))); */ +/* //$this->Map->Lease->bindModel(array('hasOne' => array('ContactsLease'))); */ +/* //$this->Map->Lease->bindModel(array('hasOne' => array('Contact'))); */ +/* /\* $this->Map->Lease->bindModel(array('hasOne' => array('ContactsLease', *\/ */ +/* /\* 'Contact' => array( *\/ */ +/* /\* 'foreignKey' => false, *\/ */ +/* /\* 'conditions' => *\/ */ +/* /\* array('Contact.id = ContactsLease.contact_id', *\/ */ +/* /\* //'ContactsLease.type = "TENANT"' *\/ */ +/* /\* ))))); *\/ */ + +/* $this->Map->bindModel(array('hasOne' => array('Lease' => array( */ +/* 'foreignKey' => false, */ +/* 'conditions' => array('Lease.map_id = Map.id') */ +/* ), */ +/* 'ContactsLease' => array( */ +/* 'foreignKey' => false, */ +/* 'conditions' => array('ContactsLease.lease_id = Lease.id') */ +/* ), */ +/* 'Contact' => array( */ +/* 'foreignKey' => false, */ +/* 'conditions' => array('Contact.id = ContactsLease.contact_id') */ +/* ))), */ +/* false); */ + + +/* $this->Map->Lease->bindModel(array('hasOne' => array('Contact' => array( */ +/* 'className' => 'ContactsLease', */ +/* 'foreignKey' => false, */ +/* 'conditions' => */ +/* array('ContactsLease.lease_id = Lease.id', */ +/* 'ContactsLease.type = "TENANT"'))))); */ + +/* # 'hasOne' => array( */ +/* # 'RecipesTag', */ +/* # 'FilterTag' => array( */ +/* # 'className' => 'Tag', */ +/* # 'foreignKey' => false, */ +/* # 'conditions' => array('FilterTag.id = RecipesTag.tag_id') */ +/* # )))); */ + +/* $this->Map->id = $id; */ +/* if ($id !== null && $id !== false) { */ +/* $this->Map->data = $this->Map->find('first', */ +/* array('conditions' => array( */ +/* $this->Map->alias . '.' . $this->Map->primaryKey => $id, */ +/* 'ContactsLease.type = "TENANT"' */ +/* ) */ +/* )); */ +/* $this->set('map', $this->Map->data); */ +/* } */ + } + + + // Temporary function + function unitStatusList() { + return + array('DELETED' => array(), + 'DAMAGED' => array(), + 'COMPANY' => array(), + 'UNAVAILABLE' => array(), + 'RESERVED' => array(), + 'DIRTY' => array(), + 'VACANT' => array(), + 'OCCUPIED' => array(), + 'LATE' => array(), + 'LOCKED' => array(), + 'LIENED' => array(), + ); + } + + function map($id = null, $requested_width = 600) { + $info = $this->mapInfo($id); + $info['border'] = true; + $info['clickable'] = true; + $this->image($info, $requested_width); + } + + function legend($id = null, $requested_width = 400) { + $status = $this->unitStatusList(); + $cols = 6; + $rows = (int)((count($status) + $cols - 1) / $cols); + + $info = array('extents' => array(), 'units' => array(), 'legend' => array()); + $info['legend']['width'] = 360; + $info['legend']['depth'] = 120; + + $info['extents']['right'] = $info['legend']['width'] * $cols; + $info['extents']['bottom'] = $info['legend']['depth'] * $rows; + + $top = $lft = 0; + foreach ($status AS $code => $color) { + $info['units'][] = array('name' => $code, + 'status' => $code, + 'width' => $info['legend']['width'], + 'depth' => $info['legend']['depth'], + 'left' => $lft, + 'right' => $lft + $info['legend']['width'], + 'top' => $top, + 'bottom' => $top + $info['legend']['depth']); + $top += $info['legend']['depth']; + if ($top >= $info['legend']['depth'] * $rows) { + $top = 0; $lft += $info['legend']['width']; + } + } + + $this->image($info, $requested_width, true); + } + + function image($info, $requested_width, $legend = false) { + //var $helpers = array('Html', 'Form', 'Javascript', 'Graph'); + $this->layout = null; + $this->autoLayout = false; + Configure::write('debug', '0'); + + // Define our color palate + // REVISIT : 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' => 64, 'blue' => 64); + $info['palate']['unit']['LOCKED']['bg'] = array('red' => 255, 'green' => 128, 'blue' => 128); + $info['palate']['unit']['LIENED']['bg'] = array('red' => 255, 'green' => 192, 'blue' => 192); + + // 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; + } + + //pr($info); + + /***** + * 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. + *****/ + + // Scale things according to desired display width + $screen_adjustment_factor = $requested_width / $info['extents']['right'];; + + // Define image size + $info['width'] = $info['extents']['right'] * $screen_adjustment_factor; + $info['depth'] = $info['extents']['bottom'] * $screen_adjustment_factor; + + // Go through each unit, adjusting map locations + foreach ($info['units'] AS $unit) { + $unit['left'] *= $screen_adjustment_factor; + $unit['right'] *= $screen_adjustment_factor; + $unit['top'] *= $screen_adjustment_factor; + $unit['bottom'] *= $screen_adjustment_factor; + } + + $this->set(compact('info')); + $this->render('image'); + } + + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * mapInfo + */ + + function mapInfo($site_area_id) { + // Set up array to hold the map information + $info = array('extents' => array(), 'units' => array()); + + $map = $this->Map->SiteArea->read(null, $site_area_id); + //pr($map); + + $top_adjustment = 5; + $left_adjustment = 5; + $info['extents']['top'] = 0; + $info['extents']['left'] = 0; + $info['extents']['bottom'] = $top_adjustment + $map['Map']['depth'] + 5; + $info['extents']['right'] = $left_adjustment + $map['Map']['width'] + 5; + return $info; + + // Get the overall site limits + $query = "SELECT M.id, M.width, M.depth"; + $query .= " FROM pmgr_maps M"; + $query .= " WHERE site_area_id = $site_area_id"; + $result = $this->Map->query($query); + + //pr($result); + $info['extents']['top'] = 0; + $info['extents']['left'] = 0; + $info['extents']['bottom'] = 360; + $info['extents']['right'] = 480; + $info['map_id'] = 1; + return $info; + + /* // Fetch and verify the result */ + /* $row = mysql_fetch_array($result); */ + /* if (!$row) die("Site map query failed!"); */ + /* mysql_free_result($result); */ + + /* // Compute the actual boundaries, adjusting for a border */ + /* $top_adjustment = 5; */ + /* $left_adjustment = 5; */ + /* $info['extents']['top'] = 0; */ + /* $info['extents']['left'] = 0; */ + /* $info['extents']['bottom'] = $top_adjustment + $row['depth'] + 5; */ + /* $info['extents']['right'] = $left_adjustment + $row['width'] + 5; */ + /* $info['map_id'] = $row['id']; */ + + /* // Get list of units and positions */ + /* $query = "SELECT U.id, U.name, U.status,"; */ + /* $query .= " ($top_adjustment + Mu.pt_top) AS pt_top,"; */ + /* $query .= " ($left_adjustment + Mu.pt_left) AS pt_left,"; */ + /* //$query .= " ($top_adjustment + Mu.pt_bottom) AS pt_bottom,"; */ + /* //$query .= " ($left_adjustment + Mu.pt_right) AS pt_right,"; */ + /* $query .= " IF(Mu.transpose, S.depth, S.width) AS width,"; */ + /* $query .= " IF(Mu.transpose, S.width, S.depth) AS depth"; */ + /* //$query .= " Mu.transpose"; */ + /* $query .= " FROM pmgr_maps_units Mu"; */ + /* $query .= " JOIN pmgr_units U ON U.id = Mu.unit_id"; */ + /* $query .= " JOIN pmgr_unit_sizes S ON S.id = U.size_id"; */ + /* $query .= " WHERE Mu.map_id = $info[map_id]"; */ + /* $result = sql_query($query); */ + + /* // Go through each one, calculating the map location */ + /* while ($row = mysql_fetch_array($result)) { */ + /* $info['units'][$row['id']] = */ + /* array( 'id' => $row['id'], */ + /* 'name' => $row['name'], */ + /* 'left' => $row['pt_left'], */ + /* 'right' => $row['pt_left'] + $row['width'], */ + /* 'top' => $row['pt_top'], */ + /* 'bottom' => $row['pt_top'] + $row['depth'], */ + /* 'width' => $row['width'], */ + /* 'depth' => $row['depth'], */ + /* 'n-s' => $row['reverseWL'], */ + /* 'status' => $row['status'] */ + /* ); */ + /* } */ + + /* // Free the result */ + /* mysql_free_result($result); */ + + /* return $info; */ + } + +} + +?> \ No newline at end of file diff --git a/site/views/elements/maps.ctp b/site/views/elements/maps.ctp new file mode 100644 index 0000000..a62fcaa --- /dev/null +++ b/site/views/elements/maps.ctp @@ -0,0 +1,61 @@ + + +

+'.__('Maps',true).''; +?> +

+ + + + counter(array( + 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); + + $rows = array($paginator->sort('id'), + $paginator->sort('name'), + $paginator->sort('site_area_id'), + $paginator->sort('width'), + $paginator->sort('depth'), + $paginator->sort('comment')); + } else { + $rows = array('Id', 'Name', 'Area', 'Width', 'Depth', 'Comment'); + } + echo $html->tableHeaders($rows); + + $rows = array(); + foreach ($maps as $map) { + $rows[] = array($html->link($map['Map']['id'], + array('controller' => 'maps', + 'action' => 'view', + $map['Map']['id'])), + $html->link($map['Map']['name'], + array('controller' => 'maps', + 'action' => 'view', + $map['Map']['id'])), + $map['SiteArea']['name'], + $map['Map']['width'] / 12, + $map['Map']['depth'] / 12, + $map['Map']['comment']); + } + echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); + } +?> +
+ +' . "\n"); + echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); + echo(' | '); + echo $paginator->numbers(); + echo(' | '); + echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); + echo('' . "\n"); + } +?> diff --git a/site/views/maps/image.ctp b/site/views/maps/image.ctp new file mode 100644 index 0000000..0d910b2 --- /dev/null +++ b/site/views/maps/image.ctp @@ -0,0 +1,95 @@ + 100) { + imagestring($image, 1, + $unit['left']+3, $unit['top']+3, + $unit['name'], + $info['palate']['unit'][$unit['status']]['fg']['color']); + } + else { + imagestringup($image, 1, + $unit['left']+3, $unit['bottom']-3, + $unit['name'], + $info['palate']['unit'][$unit['status']]['fg']['color']); + } + +} + + +header("Content-type: image/png"); +if (! imagepng($image)) { + die("Couldn't output image!"); +} + +// Clear image from memory +imagedestroy($image); + +// Closing PHP tag intentionally omitted diff --git a/site/views/maps/index.ctp b/site/views/maps/index.ctp new file mode 100644 index 0000000..8660dda --- /dev/null +++ b/site/views/maps/index.ctp @@ -0,0 +1,3 @@ +
+element('maps') ?> +
diff --git a/site/views/maps/view.ctp b/site/views/maps/view.ctp new file mode 100644 index 0000000..bc90c4a --- /dev/null +++ b/site/views/maps/view.ctp @@ -0,0 +1,25 @@ + + +
+image(array('controller' => 'maps', + 'action' => 'map', + $map['Map']['id']), + array('alt' => 'Site Map', + 'class' => 'imagemap', + 'usemap' => '#mapimg')); +?> +
+ +
+image(array('controller' => 'maps', + 'action' => 'legend', + $map['Map']['id']), + array('alt' => 'Site Map Legend')); + */ +?> +
+ + From 4e33c582466f6ea4eab47c13f8a0cb45cdfc2bd8 Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 29 May 2009 02:45:23 +0000 Subject: [PATCH 032/717] Further progress on the site map. The scale is off at the moment, but it's working well enough that it's worth a snapshot. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@33 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/maps_controller.php | 275 +++++++++++---------------- site/views/maps/view.ctp | 4 +- 2 files changed, 116 insertions(+), 163 deletions(-) diff --git a/site/controllers/maps_controller.php b/site/controllers/maps_controller.php index fe97ee7..088c8cf 100644 --- a/site/controllers/maps_controller.php +++ b/site/controllers/maps_controller.php @@ -3,88 +3,118 @@ class MapsController extends AppController { var $helpers = array('Html'); + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: index + * - Generates a list of all site maps + * + * REVISIT 20090528: + * We'll need to present only those site area maps that correspond + * to the users particular site. + */ + function index() { $this->Map->recursive = 0; -/* $this->Map->MapSize->unbindModel(array('hasMany' => array('Map'))); */ -/* $this->Map->MapSize->MapType->unbindModel(array('hasMany' => array('MapSize'))); */ - //$this->Map->bindModel(array('hasOne' => array('MapType'))); - //function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null) { - $this->set('maps', $this->paginate(null, null, null, null, null, 0)); + $this->set('maps', $this->paginate()); } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: view + * - Generates a site map page + */ + function view($id = null) { if (!$id) { $this->Session->setFlash(__('Invalid Item.', true)); $this->redirect(array('action'=>'index')); } - $this->Map->recursive = 0; - $this->set('map', $this->Map->read(null, $id)); - -/* $this->Map->MapSize->unbindModel(array('hasMany' => array('Map'))); */ -/* $this->Map->MapSize->MapType->unbindModel(array('hasMany' => array('MapSize'))); */ -/* $this->Map->Lease->unbindModel(array('belongsTo' => array('Map'))); */ -/* $this->Map->Lease->LeaseType->unbindModel(array('hasMany' => array('Lease'))); */ -/* $this->Map->Lease->Charge->unbindModel(array('belongsTo' => array('Lease'))); */ -/* $this->Map->Lease->Charge->ChargeType->unbindModel(array('hasMany' => array('Charge'))); */ -/* $this->Map->Lease->Charge->Receipt->unbindModel(array('hasMany' => array('ChargesReceipt'))); */ - -/* //$this->Map->Lease->unbindModel(array('hasMany' => array('Contact'))); */ -/* $this->Map->Lease->unbindModel(array('hasAndBelongsToMany' => array('Contact'))); */ -/* //$this->Map->Lease->unbindModel(array('hasOne' => array('Contact'))); */ -/* //$this->Map->Lease->unbindModel(array('belongsTo' => array('Contact'))); */ -/* //$this->Map->Lease->bindModel(array('hasOne' => array('ContactsLease'))); */ -/* //$this->Map->Lease->bindModel(array('hasOne' => array('Contact'))); */ -/* /\* $this->Map->Lease->bindModel(array('hasOne' => array('ContactsLease', *\/ */ -/* /\* 'Contact' => array( *\/ */ -/* /\* 'foreignKey' => false, *\/ */ -/* /\* 'conditions' => *\/ */ -/* /\* array('Contact.id = ContactsLease.contact_id', *\/ */ -/* /\* //'ContactsLease.type = "TENANT"' *\/ */ -/* /\* ))))); *\/ */ - -/* $this->Map->bindModel(array('hasOne' => array('Lease' => array( */ -/* 'foreignKey' => false, */ -/* 'conditions' => array('Lease.map_id = Map.id') */ -/* ), */ -/* 'ContactsLease' => array( */ -/* 'foreignKey' => false, */ -/* 'conditions' => array('ContactsLease.lease_id = Lease.id') */ -/* ), */ -/* 'Contact' => array( */ -/* 'foreignKey' => false, */ -/* 'conditions' => array('Contact.id = ContactsLease.contact_id') */ -/* ))), */ -/* false); */ - - -/* $this->Map->Lease->bindModel(array('hasOne' => array('Contact' => array( */ -/* 'className' => 'ContactsLease', */ -/* 'foreignKey' => false, */ -/* 'conditions' => */ -/* array('ContactsLease.lease_id = Lease.id', */ -/* 'ContactsLease.type = "TENANT"'))))); */ - -/* # 'hasOne' => array( */ -/* # 'RecipesTag', */ -/* # 'FilterTag' => array( */ -/* # 'className' => 'Tag', */ -/* # 'foreignKey' => false, */ -/* # 'conditions' => array('FilterTag.id = RecipesTag.tag_id') */ -/* # )))); */ - -/* $this->Map->id = $id; */ -/* if ($id !== null && $id !== false) { */ -/* $this->Map->data = $this->Map->find('first', */ -/* array('conditions' => array( */ -/* $this->Map->alias . '.' . $this->Map->primaryKey => $id, */ -/* 'ContactsLease.type = "TENANT"' */ -/* ) */ -/* )); */ -/* $this->set('map', $this->Map->data); */ -/* } */ + $this->set('info', $this->mapInfo($id)); } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: map + * - Produces a PNG site map image + */ + + function map($id = null, $requested_width = 600) { + if (!$id) { + $this->Session->setFlash(__('Invalid Item.', true)); + $this->redirect(array('action'=>'index')); + } + $this->image($this->mapInfo($id), $requested_width); + } + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * mapInfo + */ + + function mapInfo($id) { + // Set up array to hold the map information + $info = array('extents' => array(), 'units' => array(), + 'map_id' => $id, 'border' => true); + +/* // Find all of the map/unit information from this SiteArea */ +/* $this->Map->SiteArea->recursive = 3; */ +/* $this->Map->SiteArea->Site->unbindModel(array('hasMany' => array('SiteArea'))); */ +/* $this->Map->unbindModel(array('belongsTo' => array('SiteArea'))); */ +/* $map = $this->Map->SiteArea->read(null, $site_area_id); */ + + // Find all of the map/unit information from this SiteArea + $this->Map->recursive = 2; + $this->Map->SiteArea->unbindModel(array('hasOne' => array('Map'))); + $map = $this->Map->read(null, $id); + //pr($map); + + // Get the overall site limits, and then compute the + // actual boundary extents, adjusting for a border + $top_adjustment = 5; + $left_adjustment = 5; + $info['extents']['top'] = 0; + $info['extents']['left'] = 0; + $info['extents']['bottom'] = $top_adjustment + $map['Map']['depth'] + 5; + $info['extents']['right'] = $left_adjustment + $map['Map']['width'] + 5; + + // Go through each unit in the map, calculating the map location + foreach ($map['Unit'] AS $unit) { + $lft = $unit['MapsUnit']['pt_left'] + $left_adjustment; + $top = $unit['MapsUnit']['pt_top'] + $top_adjustment; + + $width = + $unit['MapsUnit']['transpose'] + ? $unit['UnitSize']['depth'] + : $unit['UnitSize']['width']; + + $depth = + $unit['MapsUnit']['transpose'] + ? $unit['UnitSize']['width'] + : $unit['UnitSize']['depth']; + + $info['units'][$unit['id']] = + array( 'id' => $unit['id'], + 'name' => $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['status'] + ); + } + + //pr($info); + return $info; + } + // Temporary function function unitStatusList() { return @@ -102,12 +132,12 @@ class MapsController extends AppController { ); } - function map($id = null, $requested_width = 600) { - $info = $this->mapInfo($id); - $info['border'] = true; - $info['clickable'] = true; - $this->image($info, $requested_width); - } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: legend + * - Produces a PNG color legend image + */ function legend($id = null, $requested_width = 400) { $status = $this->unitStatusList(); @@ -140,6 +170,14 @@ class MapsController extends AppController { $this->image($info, $requested_width, true); } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * helper: image + * - used by actions map & legend to set up unit information and + * color palates before rendering the PNG image. + */ + function image($info, $requested_width, $legend = false) { //var $helpers = array('Html', 'Form', 'Javascript', 'Graph'); $this->layout = null; @@ -217,91 +255,6 @@ class MapsController extends AppController { - /************************************************************************** - ************************************************************************** - ************************************************************************** - * mapInfo - */ - - function mapInfo($site_area_id) { - // Set up array to hold the map information - $info = array('extents' => array(), 'units' => array()); - - $map = $this->Map->SiteArea->read(null, $site_area_id); - //pr($map); - - $top_adjustment = 5; - $left_adjustment = 5; - $info['extents']['top'] = 0; - $info['extents']['left'] = 0; - $info['extents']['bottom'] = $top_adjustment + $map['Map']['depth'] + 5; - $info['extents']['right'] = $left_adjustment + $map['Map']['width'] + 5; - return $info; - - // Get the overall site limits - $query = "SELECT M.id, M.width, M.depth"; - $query .= " FROM pmgr_maps M"; - $query .= " WHERE site_area_id = $site_area_id"; - $result = $this->Map->query($query); - - //pr($result); - $info['extents']['top'] = 0; - $info['extents']['left'] = 0; - $info['extents']['bottom'] = 360; - $info['extents']['right'] = 480; - $info['map_id'] = 1; - return $info; - - /* // Fetch and verify the result */ - /* $row = mysql_fetch_array($result); */ - /* if (!$row) die("Site map query failed!"); */ - /* mysql_free_result($result); */ - - /* // Compute the actual boundaries, adjusting for a border */ - /* $top_adjustment = 5; */ - /* $left_adjustment = 5; */ - /* $info['extents']['top'] = 0; */ - /* $info['extents']['left'] = 0; */ - /* $info['extents']['bottom'] = $top_adjustment + $row['depth'] + 5; */ - /* $info['extents']['right'] = $left_adjustment + $row['width'] + 5; */ - /* $info['map_id'] = $row['id']; */ - - /* // Get list of units and positions */ - /* $query = "SELECT U.id, U.name, U.status,"; */ - /* $query .= " ($top_adjustment + Mu.pt_top) AS pt_top,"; */ - /* $query .= " ($left_adjustment + Mu.pt_left) AS pt_left,"; */ - /* //$query .= " ($top_adjustment + Mu.pt_bottom) AS pt_bottom,"; */ - /* //$query .= " ($left_adjustment + Mu.pt_right) AS pt_right,"; */ - /* $query .= " IF(Mu.transpose, S.depth, S.width) AS width,"; */ - /* $query .= " IF(Mu.transpose, S.width, S.depth) AS depth"; */ - /* //$query .= " Mu.transpose"; */ - /* $query .= " FROM pmgr_maps_units Mu"; */ - /* $query .= " JOIN pmgr_units U ON U.id = Mu.unit_id"; */ - /* $query .= " JOIN pmgr_unit_sizes S ON S.id = U.size_id"; */ - /* $query .= " WHERE Mu.map_id = $info[map_id]"; */ - /* $result = sql_query($query); */ - - /* // Go through each one, calculating the map location */ - /* while ($row = mysql_fetch_array($result)) { */ - /* $info['units'][$row['id']] = */ - /* array( 'id' => $row['id'], */ - /* 'name' => $row['name'], */ - /* 'left' => $row['pt_left'], */ - /* 'right' => $row['pt_left'] + $row['width'], */ - /* 'top' => $row['pt_top'], */ - /* 'bottom' => $row['pt_top'] + $row['depth'], */ - /* 'width' => $row['width'], */ - /* 'depth' => $row['depth'], */ - /* 'n-s' => $row['reverseWL'], */ - /* 'status' => $row['status'] */ - /* ); */ - /* } */ - - /* // Free the result */ - /* mysql_free_result($result); */ - - /* return $info; */ - } } diff --git a/site/views/maps/view.ctp b/site/views/maps/view.ctp index bc90c4a..7eeeb50 100644 --- a/site/views/maps/view.ctp +++ b/site/views/maps/view.ctp @@ -3,8 +3,8 @@
image(array('controller' => 'maps', - 'action' => 'map', - $map['Map']['id']), + 'action' => 'map', + $info['map_id']), array('alt' => 'Site Map', 'class' => 'imagemap', 'usemap' => '#mapimg')); From 684f02ebc57c3fe3d989668dcf05e1fc8b6a734d Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 29 May 2009 03:36:28 +0000 Subject: [PATCH 033/717] More tweaks to get the map working. At the moment, the clickable area is off because it's not scaled like the actual image is. I'll have to work on that next. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@34 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/maps_controller.php | 7 ++-- site/views/maps/view.ctp | 54 +++++++++++++++++++--------- 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/site/controllers/maps_controller.php b/site/controllers/maps_controller.php index 088c8cf..bab9533 100644 --- a/site/controllers/maps_controller.php +++ b/site/controllers/maps_controller.php @@ -42,7 +42,7 @@ class MapsController extends AppController { * - Produces a PNG site map image */ - function map($id = null, $requested_width = 600) { + function map($id = null, $requested_width = 800) { if (!$id) { $this->Session->setFlash(__('Invalid Item.', true)); $this->redirect(array('action'=>'index')); @@ -235,14 +235,14 @@ class MapsController extends AppController { *****/ // Scale things according to desired display width - $screen_adjustment_factor = $requested_width / $info['extents']['right'];; + $screen_adjustment_factor = $requested_width / $info['extents']['right']; // Define image size $info['width'] = $info['extents']['right'] * $screen_adjustment_factor; $info['depth'] = $info['extents']['bottom'] * $screen_adjustment_factor; // Go through each unit, adjusting map locations - foreach ($info['units'] AS $unit) { + foreach ($info['units'] AS &$unit) { $unit['left'] *= $screen_adjustment_factor; $unit['right'] *= $screen_adjustment_factor; $unit['top'] *= $screen_adjustment_factor; @@ -255,7 +255,6 @@ class MapsController extends AppController { - } ?> \ No newline at end of file diff --git a/site/views/maps/view.ctp b/site/views/maps/view.ctp index 7eeeb50..a6d5ef6 100644 --- a/site/views/maps/view.ctp +++ b/site/views/maps/view.ctp @@ -1,24 +1,46 @@ -
-image(array('controller' => 'maps', - 'action' => 'map', - $info['map_id']), - array('alt' => 'Site Map', - 'class' => 'imagemap', - 'usemap' => '#mapimg')); -?> +
+ url(array('controller' => 'units', + 'action' => 'view', + $unit['id'])) . + '" alt="' . + $unit['name'] . + '">' . "\n"); + } + }// for indentation purposes + ?> + + + image(array('controller' => 'maps', + 'action' => 'map', + $info['map_id']), + array('alt' => 'Site Map', + 'class' => 'map', + 'usemap' => '#mapzones')); + ?> +
-
+
image(array('controller' => 'maps', - 'action' => 'legend', - $map['Map']['id']), - array('alt' => 'Site Map Legend')); - */ + echo $html->image(array('controller' => 'maps', + 'action' => 'legend', + $info['map_id']), + array('alt' => 'Site Map Legend', + 'class' => 'map')); ?>
From db03c73b599aafc6bc1dfbd28cc3a34a4b227d1e Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 29 May 2009 04:37:24 +0000 Subject: [PATCH 034/717] Fixed the underlying hotlink map to match the coordinates of the actual image. Also fixed a few issues with requested_width propogation, although there may still be some bugs. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@35 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/maps_controller.php | 106 +++++++++++++-------------- site/views/maps/view.ctp | 11 ++- 2 files changed, 59 insertions(+), 58 deletions(-) diff --git a/site/controllers/maps_controller.php b/site/controllers/maps_controller.php index bab9533..88140c0 100644 --- a/site/controllers/maps_controller.php +++ b/site/controllers/maps_controller.php @@ -26,12 +26,12 @@ class MapsController extends AppController { * - Generates a site map page */ - function view($id = null) { + 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)); + $this->set('info', $this->mapInfo($id, $requested_width)); } @@ -47,7 +47,7 @@ class MapsController extends AppController { $this->Session->setFlash(__('Invalid Item.', true)); $this->redirect(array('action'=>'index')); } - $this->image($this->mapInfo($id), $requested_width); + $this->image($this->mapInfo($id, $requested_width)); } /************************************************************************** @@ -56,16 +56,11 @@ class MapsController extends AppController { * mapInfo */ - function mapInfo($id) { + function mapInfo($id, $requested_width) { // Set up array to hold the map information - $info = array('extents' => array(), 'units' => array(), - 'map_id' => $id, 'border' => true); - -/* // Find all of the map/unit information from this SiteArea */ -/* $this->Map->SiteArea->recursive = 3; */ -/* $this->Map->SiteArea->Site->unbindModel(array('hasMany' => array('SiteArea'))); */ -/* $this->Map->unbindModel(array('belongsTo' => array('SiteArea'))); */ -/* $map = $this->Map->SiteArea->read(null, $site_area_id); */ + $info = array('map_id' => $id, + 'border' => true, + 'units' => array()); // Find all of the map/unit information from this SiteArea $this->Map->recursive = 2; @@ -73,19 +68,32 @@ class MapsController extends AppController { $map = $this->Map->read(null, $id); //pr($map); + /***** + * 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 - $top_adjustment = 5; - $left_adjustment = 5; - $info['extents']['top'] = 0; - $info['extents']['left'] = 0; - $info['extents']['bottom'] = $top_adjustment + $map['Map']['depth'] + 5; - $info['extents']['right'] = $left_adjustment + $map['Map']['width'] + 5; + $boundary_adjustment = 5; + $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 ($map['Unit'] AS $unit) { - $lft = $unit['MapsUnit']['pt_left'] + $left_adjustment; - $top = $unit['MapsUnit']['pt_top'] + $top_adjustment; + $lft = $unit['MapsUnit']['pt_left'] + $boundary_adjustment; + $top = $unit['MapsUnit']['pt_top'] + $boundary_adjustment; $width = $unit['MapsUnit']['transpose'] @@ -97,7 +105,13 @@ class MapsController extends AppController { ? $unit['UnitSize']['width'] : $unit['UnitSize']['depth']; - $info['units'][$unit['id']] = + $lft *= $screen_adjustment_factor; + $top *= $screen_adjustment_factor; + $width *= $screen_adjustment_factor; + $depth *= $screen_adjustment_factor; + + //$info['units'][$unit['id']] = + $info['units'][] = array( 'id' => $unit['id'], 'name' => $unit['name'], 'left' => $lft, @@ -144,14 +158,22 @@ class MapsController extends AppController { $cols = 6; $rows = (int)((count($status) + $cols - 1) / $cols); - $info = array('extents' => array(), 'units' => array(), 'legend' => array()); - $info['legend']['width'] = 360; - $info['legend']['depth'] = 120; + $info = array('units' => array(), 'legend' => array()); - $info['extents']['right'] = $info['legend']['width'] * $cols; - $info['extents']['bottom'] = $info['legend']['depth'] * $rows; + // Get the overall site limits, and then compute the + // actual boundary extents, adjusting for a border + $boundary_adjustment = 2; + $bottom = 2*$boundary_adjustment + $cols*360; + $right = 2*$boundary_adjustment + $rows*120; - $top = $lft = 0; + // 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; + + $top = $lft = $boundary_adjustment; foreach ($status AS $code => $color) { $info['units'][] = array('name' => $code, 'status' => $code, @@ -163,11 +185,11 @@ class MapsController extends AppController { 'bottom' => $top + $info['legend']['depth']); $top += $info['legend']['depth']; if ($top >= $info['legend']['depth'] * $rows) { - $top = 0; $lft += $info['legend']['width']; + $top = $boundary_adjustment; $lft += $info['legend']['width']; } } - $this->image($info, $requested_width, true); + $this->image($info, true); } /************************************************************************** @@ -178,7 +200,7 @@ class MapsController extends AppController { * color palates before rendering the PNG image. */ - function image($info, $requested_width, $legend = false) { + function image($info, $legend = false) { //var $helpers = array('Html', 'Form', 'Javascript', 'Graph'); $this->layout = null; $this->autoLayout = false; @@ -225,30 +247,6 @@ class MapsController extends AppController { //pr($info); - /***** - * 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. - *****/ - - // Scale things according to desired display width - $screen_adjustment_factor = $requested_width / $info['extents']['right']; - - // Define image size - $info['width'] = $info['extents']['right'] * $screen_adjustment_factor; - $info['depth'] = $info['extents']['bottom'] * $screen_adjustment_factor; - - // Go through each unit, adjusting map locations - foreach ($info['units'] AS &$unit) { - $unit['left'] *= $screen_adjustment_factor; - $unit['right'] *= $screen_adjustment_factor; - $unit['top'] *= $screen_adjustment_factor; - $unit['bottom'] *= $screen_adjustment_factor; - } - $this->set(compact('info')); $this->render('image'); } diff --git a/site/views/maps/view.ctp b/site/views/maps/view.ctp index a6d5ef6..e6324df 100644 --- a/site/views/maps/view.ctp +++ b/site/views/maps/view.ctp @@ -1,15 +1,16 @@
- +url(array('controller' => 'units', @@ -26,7 +27,8 @@ image(array('controller' => 'maps', 'action' => 'map', - $info['map_id']), + $info['map_id'], + $info['width']), array('alt' => 'Site Map', 'class' => 'map', 'usemap' => '#mapzones')); @@ -38,7 +40,8 @@ image(array('controller' => 'maps', 'action' => 'legend', - $info['map_id']), + $info['map_id'], + $info['width']), array('alt' => 'Site Map Legend', 'class' => 'map')); ?> From 2c85566ffc1e1b4f2a0c3df01a58968f9c8efabf Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 29 May 2009 05:10:46 +0000 Subject: [PATCH 035/717] The map is working quite well now, including the legend. Next steps will be to add the sidemenu. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@36 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/maps_controller.php | 35 ++++++++++++++++++---------- site/views/maps/image.ctp | 8 +++---- site/views/maps/view.ctp | 5 ++-- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/site/controllers/maps_controller.php b/site/controllers/maps_controller.php index 88140c0..02fe130 100644 --- a/site/controllers/maps_controller.php +++ b/site/controllers/maps_controller.php @@ -79,7 +79,7 @@ class MapsController extends AppController { // Get the overall site limits, and then compute the // actual boundary extents, adjusting for a border - $boundary_adjustment = 5; + $boundary_adjustment = 12; $bottom = 2*$boundary_adjustment + $map['Map']['depth']; $right = 2*$boundary_adjustment + $map['Map']['width']; @@ -158,13 +158,15 @@ class MapsController extends AppController { $cols = 6; $rows = (int)((count($status) + $cols - 1) / $cols); - $info = array('units' => array(), 'legend' => array()); + $info = array('units' => array()); // Get the overall site limits, and then compute the // actual boundary extents, adjusting for a border - $boundary_adjustment = 2; - $bottom = 2*$boundary_adjustment + $cols*360; - $right = 2*$boundary_adjustment + $rows*120; + $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; @@ -173,19 +175,28 @@ class MapsController extends AppController { $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 => $color) { $info['units'][] = array('name' => $code, 'status' => $code, - 'width' => $info['legend']['width'], - 'depth' => $info['legend']['depth'], + 'width' => $item_width, + 'depth' => $item_depth, 'left' => $lft, - 'right' => $lft + $info['legend']['width'], + 'right' => $lft + $item_width, 'top' => $top, - 'bottom' => $top + $info['legend']['depth']); - $top += $info['legend']['depth']; - if ($top >= $info['legend']['depth'] * $rows) { - $top = $boundary_adjustment; $lft += $info['legend']['width']; + 'bottom' => $top + $item_depth); + $top += $item_depth; + if ($top >= $item_depth * $rows) { + $top = $boundary_adjustment * $screen_adjustment_factor; + $lft += $item_width; } } diff --git a/site/views/maps/image.ctp b/site/views/maps/image.ctp index 0d910b2..0a68c25 100644 --- a/site/views/maps/image.ctp +++ b/site/views/maps/image.ctp @@ -21,7 +21,7 @@ foreach ($info['palate'] AS &$area) { } } -if ($info['border']) { +if (isset($info['border'])) { // Create border around image imageline($image, 0, 0, @@ -68,14 +68,14 @@ foreach ($info['units'] AS $unit) { // If the unit is wide enough, run the text horizontal, // otherwise, we'll have to run it vertical. - if ($unit['width'] > 100) { - imagestring($image, 1, + if ($unit['width'] > 40 || ($unit['width'] >= $unit['depth'])) { + imagestring($image, $unit['width']/25, $unit['left']+3, $unit['top']+3, $unit['name'], $info['palate']['unit'][$unit['status']]['fg']['color']); } else { - imagestringup($image, 1, + imagestringup($image, $unit['depth']/25, $unit['left']+3, $unit['bottom']-3, $unit['name'], $info['palate']['unit'][$unit['status']]['fg']['color']); diff --git a/site/views/maps/view.ctp b/site/views/maps/view.ctp index e6324df..1966ff9 100644 --- a/site/views/maps/view.ctp +++ b/site/views/maps/view.ctp @@ -31,6 +31,7 @@ $info['width']), array('alt' => 'Site Map', 'class' => 'map', + 'border' => 0, 'usemap' => '#mapzones')); ?> @@ -41,9 +42,9 @@ echo $html->image(array('controller' => 'maps', 'action' => 'legend', $info['map_id'], - $info['width']), + $info['width']/2), array('alt' => 'Site Map Legend', - 'class' => 'map')); + 'class' => 'legend')); ?>
From 2da7b6b2c04d4556a64b58c15f814ae1cf199dcc Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 29 May 2009 06:57:22 +0000 Subject: [PATCH 036/717] Added a higher preference for horizontal unit names git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@37 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/maps/image.ctp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/views/maps/image.ctp b/site/views/maps/image.ctp index 0a68c25..9d789e5 100644 --- a/site/views/maps/image.ctp +++ b/site/views/maps/image.ctp @@ -68,7 +68,7 @@ foreach ($info['units'] AS $unit) { // If the unit is wide enough, run the text horizontal, // otherwise, we'll have to run it vertical. - if ($unit['width'] > 40 || ($unit['width'] >= $unit['depth'])) { + if ($unit['width'] > 20 || ($unit['width'] >= $unit['depth'])) { imagestring($image, $unit['width']/25, $unit['left']+3, $unit['top']+3, $unit['name'], From f384e051bfbc2a5f02d837635a828e60b16936fd Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 29 May 2009 14:49:11 +0000 Subject: [PATCH 037/717] Initial working version ofa consistent layout with side menu git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@38 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 19 ++++ site/views/contacts/view.ctp | 1 - site/views/elements/contacts.ctp | 13 ++- site/views/elements/maps.ctp | 13 ++- site/views/elements/sidemenu.ctp | 24 +++++ site/views/elements/units.ctp | 13 ++- site/views/layouts/default.ctp | 50 +++++++---- site/views/units/view.ctp | 1 - site/webroot/css/cake.generic.css | 5 +- site/webroot/css/sidemenu.css | 140 ++++++++++++++++++++++++++++++ 10 files changed, 234 insertions(+), 45 deletions(-) create mode 100644 site/views/elements/sidemenu.ctp create mode 100644 site/webroot/css/sidemenu.css diff --git a/site/app_controller.php b/site/app_controller.php index 87357ed..ae6a785 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -35,5 +35,24 @@ * @subpackage cake.app */ class AppController extends Controller { + + function sideMenuStandardLinks() { + return array( + array('name' => 'Standard Menu', 'header' => true), + array('name' => 'Site Map', 'url' => array('controller' => 'maps', 'action' => 'view', 1)), + array('hr' => true), + array('name' => 'Tenants', 'url' => array('controller' => 'contacts', 'action' => 'index')), + array('name' => 'Units', 'url' => array('controller' => 'units', 'action' => 'index')), + ); + } + + function sideMenuLinks() { + return $this->sideMenuStandardLinks(); + } + + function beforeRender() { + $this->set('sidemenu', $this->sideMenuLinks()); + } + } ?> \ No newline at end of file diff --git a/site/views/contacts/view.ctp b/site/views/contacts/view.ctp index 5d6e968..d2823c9 100644 --- a/site/views/contacts/view.ctp +++ b/site/views/contacts/view.ctp @@ -1,7 +1,6 @@
-

+ -'.__('Contacts',true).''; +if (isset($heading)) + echo $heading; +else + echo '

'.__('Contacts',true).'

'; ?> -

diff --git a/site/views/elements/maps.ctp b/site/views/elements/maps.ctp index a62fcaa..0de3f45 100644 --- a/site/views/elements/maps.ctp +++ b/site/views/elements/maps.ctp @@ -1,13 +1,10 @@ - + -'.__('Maps',true).''; +if (isset($heading)) + echo $heading; +else + echo '

'.__('Maps',true).'

'; ?> -

diff --git a/site/views/elements/sidemenu.ctp b/site/views/elements/sidemenu.ctp new file mode 100644 index 0000000..c1e8958 --- /dev/null +++ b/site/views/elements/sidemenu.ctp @@ -0,0 +1,24 @@ +' . $item['name'] . '' . "\n"); + elseif (isset($item['hr'])) + echo('
' . "\n"); + elseif (isset($item['url'])) + echo('
' + . $html->link($item['name'], $item['url'], + isset($item['htmlAttributes']) ? $item['htmlAttributes'] : null, + isset($item['confirmMessage']) ? $item['confirmMessage'] : null, + isset($item['escapeTitle']) ? $item['escapeTitle'] : null) + + . '
' . "\n"); +} diff --git a/site/views/elements/units.ctp b/site/views/elements/units.ctp index ee19ea9..8d504c0 100644 --- a/site/views/elements/units.ctp +++ b/site/views/elements/units.ctp @@ -1,13 +1,10 @@ - + -'.__('Units',true).''; +if (isset($heading)) + echo $heading; +else + echo '

'.__('Units',true).'

'; ?> -

diff --git a/site/views/layouts/default.ctp b/site/views/layouts/default.ctp index db4d2aa..a703388 100644 --- a/site/views/layouts/default.ctp +++ b/site/views/layouts/default.ctp @@ -27,38 +27,56 @@ charset(); ?> - <?php __('CakePHP: the rapid development php framework:'); ?> - <?php echo $title_for_layout; ?> + Property Manager: <?php echo $title_for_layout; ?> meta('icon'); - echo $html->css('cake.generic'); - echo $scripts_for_layout; ?> + + + +
+ + + + + + + + + + + + +
+ + + element('sidemenu', array('menu' => $sidemenu)); ?> + + + + +
-
flash(); ?> -
- + + +
+ + + + - \ No newline at end of file + diff --git a/site/views/units/view.ctp b/site/views/units/view.ctp index 6e2c113..307f380 100644 --- a/site/views/units/view.ctp +++ b/site/views/units/view.ctp @@ -1,7 +1,6 @@
-

Date: Fri, 29 May 2009 15:54:33 +0000 Subject: [PATCH 038/717] Minor CSS layout tweak git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@39 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/webroot/css/sidemenu.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/site/webroot/css/sidemenu.css b/site/webroot/css/sidemenu.css index af9a415..94f29cf 100644 --- a/site/webroot/css/sidemenu.css +++ b/site/webroot/css/sidemenu.css @@ -11,11 +11,12 @@ */ table#layout { width: 100% } -td#sidecolumn { width: 1%; background: lightblue; text-align: left; } +td#sidecolumn { width: 10em; background: lightblue; text-align: left; } td#pagecolumn { padding-left: 4mm; } td#sidecolumn , td#pagecolumn { vertical-align: top; } +td#sidecolumn .header { margin-top: 0.4em; } td#sidecolumn .header , td#sidecolumn .item { white-space : nowrap; } td#sidecolumn .item { padding-left: 0.6em; } From 79bcf99fc519bb8b91d39551cf4162cf6de2c40d Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 29 May 2009 15:55:50 +0000 Subject: [PATCH 039/717] Removed unnecessary sidemenu links function, as the overriding class can just call the parent to get the standard links. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@40 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/site/app_controller.php b/site/app_controller.php index ae6a785..408afec 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -36,20 +36,15 @@ */ class AppController extends Controller { - function sideMenuStandardLinks() { + function sideMenuLinks() { return array( - array('name' => 'Standard Menu', 'header' => true), + array('name' => 'Common', 'header' => true), array('name' => 'Site Map', 'url' => array('controller' => 'maps', 'action' => 'view', 1)), - array('hr' => true), array('name' => 'Tenants', 'url' => array('controller' => 'contacts', 'action' => 'index')), array('name' => 'Units', 'url' => array('controller' => 'units', 'action' => 'index')), ); } - function sideMenuLinks() { - return $this->sideMenuStandardLinks(); - } - function beforeRender() { $this->set('sidemenu', $this->sideMenuLinks()); } From 2a4b8079fb060e804de83098c41e8a968a2a3634 Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 29 May 2009 16:01:47 +0000 Subject: [PATCH 040/717] Added comment blocks and context specific side menu link items. Also tweaked the Page titles and headings for the table listings. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@41 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/contacts_controller.php | 111 +++++++++++++++++-- site/controllers/units_controller.php | 130 ++++++++++++++--------- site/views/contacts/index.ctp | 2 +- site/views/contacts/view.ctp | 24 ++--- site/views/units/index.ctp | 2 +- 5 files changed, 198 insertions(+), 71 deletions(-) diff --git a/site/controllers/contacts_controller.php b/site/controllers/contacts_controller.php index eaf90df..5e1ccdc 100644 --- a/site/controllers/contacts_controller.php +++ b/site/controllers/contacts_controller.php @@ -7,10 +7,64 @@ class ContactsController extends AppController { 'order' => array('Contact.last_name' => 'ASC', 'Contact.first_name' => 'ASC')); - function index() { - $this->all(); + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * override: sideMenuLinks + * - Generates controller specific links for the side menu + */ + function sideMenuLinks() { + $menu = parent::sideMenuLinks(); + //$menu[] = array('hr' => true); + $menu[] = array('name' => 'Tenants', 'header' => true); + $menu[] = array('name' => 'Current', 'url' => array('controller' => 'contacts', 'action' => 'current')); + $menu[] = array('name' => 'Past', 'url' => array('controller' => 'contacts', 'action' => 'past')); + $menu[] = array('name' => 'All Tenants', 'url' => array('controller' => 'contacts', 'action' => 'tenants')); + $menu[] = array('name' => 'All Contacts', 'url' => array('controller' => 'contacts', 'action' => 'all')); + + return $menu; } + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: index + * - Lists all current tenants + */ + + function index() { + $this->current(); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: past + * - Lists all tenants, past and present + */ + + function tenants() { + $this->Contact->recursive = 0; + $this->Contact->bindModel(array('hasOne' => array('ContactsLease')), + false); + + $title = 'All Tenants'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('contacts', $this->paginate(array('ContactsLease.type != "ALTERNATE"'))); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: current + * - Lists all current tenants + */ + function current() { $this->Contact->recursive = 0; $this->Contact->bindModel(array('hasOne' => array('ContactsLease', @@ -19,21 +73,62 @@ class ContactsController extends AppController { 'conditions' => array('Lease.id = ContactsLease.lease_id') ))), false); - + + $title = 'Current Tenants'; + $this->set('title', $title); $this->set('heading', $title); $this->set('contacts', $this->paginate(array('Lease.close_date IS NULL', 'ContactsLease.type != "ALTERNATE"'))); $this->render('index'); } - function all() { + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: past + * - Lists all past tenants + */ + + function past() { $this->Contact->recursive = 0; - $this->Contact->bindModel(array('hasOne' => array('ContactsLease')), + $this->Contact->bindModel(array('hasOne' => array('ContactsLease', + 'Lease' => array( + 'foreignKey' => false, + 'conditions' => array('Lease.id = ContactsLease.lease_id') + ))), false); - $this->set('contacts', $this->paginate(array('ContactsLease.type != "ALTERNATE"'))); + $title = 'Past Tenants'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('contacts', $this->paginate(array('Lease.close_date IS NOT NULL', + 'ContactsLease.type != "ALTERNATE"'))); $this->render('index'); } + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: all + * - Lists all contacts, including non-tenants + */ + + function all() { + $this->Contact->recursive = 0; + $title = 'All Contacts'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('contacts', $this->paginate()); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: view + * - Displays information about a specific contact + */ + function view($id = null) { if (!$id) { $this->Session->setFlash(__('Invalid Item.', true)); @@ -45,7 +140,9 @@ class ContactsController extends AppController { $this->Contact->Lease->Charge->ChargeType->unbindModel(array('hasMany' => array('Charge'))); $this->Contact->Lease->Charge->Receipt->unbindModel(array('hasMany' => array('ChargesReceipt'))); - $this->set('tenant', $this->Contact->read(null, $id)); + $contact = $this->Contact->read(null, $id); + $title = $contact['Contact']['display_name']; + $this->set(compact('contact', 'title')); } } diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index 6e0e931..63fe664 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -6,38 +6,109 @@ class UnitsController extends AppController { var $paginate = array('limit' => 100, 'order' => array('Unit.sort_order' => 'ASC')); + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * override: sideMenuLinks + * - Generates controller specific links for the side menu + */ + function sideMenuLinks() { + $menu = parent::sideMenuLinks(); + //$menu[] = array('hr' => true); + $menu[] = array('name' => 'Units', 'header' => true); + $menu[] = array('name' => 'Occupied', 'url' => array('controller' => 'units', 'action' => 'occupied')); + $menu[] = array('name' => 'Vacant', 'url' => array('controller' => 'units', 'action' => 'vacant')); + $menu[] = array('name' => 'Unavailable', 'url' => array('controller' => 'units', 'action' => 'unavailable')); + $menu[] = array('name' => 'All', 'url' => array('controller' => 'units', 'action' => 'all')); + + return $menu; + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: index + * - Lists all units + */ + function index() { $this->all(); } + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: unavailable + * - Lists unavailable units + */ + function unavailable() { $this->Unit->recursive = 0; + $title = 'Unavailable Units'; + $this->set('title', $title); $this->set('heading', $title); $this->set('units', $this->paginate(array($this->Unit->conditionUnavailable()))); $this->render('index'); } + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: vacant + * - Lists vacant units + */ + function vacant() { $this->Unit->recursive = 0; + $title = 'Vacant Units'; + $this->set('title', $title); $this->set('heading', $title); $this->set('units', $this->paginate(array($this->Unit->conditionVacant()))); $this->render('index'); } + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: occupied + * - Lists occupied units + */ + function occupied() { $this->Unit->recursive = 0; + $title = 'Occupied Units'; + $this->set('title', $title); $this->set('heading', $title); $this->set('units', $this->paginate(array($this->Unit->conditionOccupied()))); $this->render('index'); } + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: all + * - Lists all units + */ + function all() { - $this->Unit->recursive = 2; -/* $this->Unit->UnitSize->unbindModel(array('hasMany' => array('Unit'))); */ -/* $this->Unit->UnitSize->UnitType->unbindModel(array('hasMany' => array('UnitSize'))); */ - //$this->Unit->bindModel(array('hasOne' => array('UnitType'))); - //function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null) { - $this->set('units', $this->paginate(null, null, null, null, null, 2)); + $this->Unit->recursive = 0; + $title = 'All Units'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('units', $this->paginate()); $this->render('index'); } + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: view + * - Displays information about a specific unit + */ + function view($id = null) { if (!$id) { $this->Session->setFlash(__('Invalid Item.', true)); @@ -52,51 +123,10 @@ class UnitsController extends AppController { $this->Unit->Lease->Charge->ChargeType->unbindModel(array('hasMany' => array('Charge'))); $this->Unit->Lease->Charge->Receipt->unbindModel(array('hasMany' => array('ChargesReceipt'))); -/* //$this->Unit->Lease->unbindModel(array('hasMany' => array('Contact'))); */ -/* $this->Unit->Lease->unbindModel(array('hasAndBelongsToMany' => array('Contact'))); */ -/* //$this->Unit->Lease->unbindModel(array('hasOne' => array('Contact'))); */ -/* //$this->Unit->Lease->unbindModel(array('belongsTo' => array('Contact'))); */ -/* //$this->Unit->Lease->bindModel(array('hasOne' => array('ContactsLease'))); */ -/* //$this->Unit->Lease->bindModel(array('hasOne' => array('Contact'))); */ -/* /\* $this->Unit->Lease->bindModel(array('hasOne' => array('ContactsLease', *\/ */ -/* /\* 'Contact' => array( *\/ */ -/* /\* 'foreignKey' => false, *\/ */ -/* /\* 'conditions' => *\/ */ -/* /\* array('Contact.id = ContactsLease.contact_id', *\/ */ -/* /\* //'ContactsLease.type = "TENANT"' *\/ */ -/* /\* ))))); *\/ */ + $unit = $this->Unit->read(null, $id); + $title = 'Unit ' . $unit['Unit']['name']; + $this->set(compact('unit', 'title')); -/* $this->Unit->bindModel(array('hasOne' => array('Lease' => array( */ -/* 'foreignKey' => false, */ -/* 'conditions' => array('Lease.unit_id = Unit.id') */ -/* ), */ -/* 'ContactsLease' => array( */ -/* 'foreignKey' => false, */ -/* 'conditions' => array('ContactsLease.lease_id = Lease.id') */ -/* ), */ -/* 'Contact' => array( */ -/* 'foreignKey' => false, */ -/* 'conditions' => array('Contact.id = ContactsLease.contact_id') */ -/* ))), */ -/* false); */ - - -/* $this->Unit->Lease->bindModel(array('hasOne' => array('Contact' => array( */ -/* 'className' => 'ContactsLease', */ -/* 'foreignKey' => false, */ -/* 'conditions' => */ -/* array('ContactsLease.lease_id = Lease.id', */ -/* 'ContactsLease.type = "TENANT"'))))); */ - -/* # 'hasOne' => array( */ -/* # 'RecipesTag', */ -/* # 'FilterTag' => array( */ -/* # 'className' => 'Tag', */ -/* # 'foreignKey' => false, */ -/* # 'conditions' => array('FilterTag.id = RecipesTag.tag_id') */ -/* # )))); */ - - $this->set('unit', $this->Unit->read(null, $id)); /* $this->Unit->id = $id; */ /* if ($id !== null && $id !== false) { */ /* $this->Unit->data = $this->Unit->find('first', */ diff --git a/site/views/contacts/index.ctp b/site/views/contacts/index.ctp index 15d92e7..6fb4277 100644 --- a/site/views/contacts/index.ctp +++ b/site/views/contacts/index.ctp @@ -1,3 +1,3 @@
-element('contacts') ?> +element('contacts', array('heading' => '

'.$heading.'

')) ?>
diff --git a/site/views/contacts/view.ctp b/site/views/contacts/view.ctp index d2823c9..28aac21 100644 --- a/site/views/contacts/view.ctp +++ b/site/views/contacts/view.ctp @@ -33,14 +33,14 @@ function datefmt($date) { */ echo('' . "\n"); echo(' ' . "\n"); -echo $html->tableCells(array(array('Name', $tenant['Contact']['display_name']), - array('Company', $tenant['Contact']['company_name']), - array('SSN', $tenant['Contact']['id_federal']), - array('ID', $tenant['Contact']['id_num'] - . ($tenant['Contact']['id_state'] - ? " - ".$tenant['Contact']['id_state'] +echo $html->tableCells(array(array('Name', $contact['Contact']['display_name']), + array('Company', $contact['Contact']['company_name']), + array('SSN', $contact['Contact']['id_federal']), + array('ID', $contact['Contact']['id_num'] + . ($contact['Contact']['id_state'] + ? " - ".$contact['Contact']['id_state'] : "")), - array('Comment', $tenant['Contact']['comment'])), + array('Comment', $contact['Contact']['comment'])), null, array('class' => "altrow"), false, false); echo('
Tenant Info
' . "\n"); @@ -50,7 +50,7 @@ echo('' . "\n"); */ $headers = array('Location', 'Preference', 'Type', 'Phone', 'Extension', 'Comment'); $rows = array(); -foreach($tenant['ContactPhone'] AS $phone) { +foreach($contact['ContactPhone'] AS $phone) { $rows[] = array($phone['ContactsMethod']['type'], $phone['ContactsMethod']['preference'], $phone['type'], @@ -73,7 +73,7 @@ if (count($rows)) { */ $headers = array('Location', 'Preference', 'Email', 'Comment'); $rows = array(); -foreach($tenant['ContactEmail'] AS $email) { +foreach($contact['ContactEmail'] AS $email) { $rows[] = array($email['ContactsMethod']['type'], $email['ContactsMethod']['preference'], $email['email'], @@ -94,7 +94,7 @@ if (count($rows)) { */ $headers = array('Location', 'Preference', 'Address', 'City', 'State', 'Zip', 'Country', 'Comment'); $rows = array(); -foreach($tenant['ContactAddress'] AS $address) { +foreach($contact['ContactAddress'] AS $address) { $rows[] = array($address['ContactsMethod']['type'], $address['ContactsMethod']['preference'], $address['address'], @@ -119,7 +119,7 @@ if (count($rows)) { */ $headers = array('Lease', 'Unit', 'Signed', 'Move-In', 'Move-Out', 'Rent', 'Deposit', 'Comment'); $rows = array(); -foreach($tenant['Lease'] AS $lease) { +foreach($contact['Lease'] AS $lease) { $rows[] = array('#'.$lease['id'], $html->link($lease['Unit']['name'], array('controller' => 'units', @@ -145,7 +145,7 @@ echo('' . "\n"); */ $security_deposit = 0; $grand_total = 0; -foreach($tenant['Lease'] AS $lease) { +foreach($contact['Lease'] AS $lease) { $headers = array('Date', /*'Through',*/ /*'Charge/Receipt'*/'ID', 'Type', 'Comment', 'Amount', 'Total'); $rows = array(); diff --git a/site/views/units/index.ctp b/site/views/units/index.ctp index df3021c..d6ae893 100644 --- a/site/views/units/index.ctp +++ b/site/views/units/index.ctp @@ -1,3 +1,3 @@
-element('units') ?> +element('units', array('heading' => '

'.$heading.'

')) ?>
From c041174b0c1d6da11c3b52da9e41c1373a15a317 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 30 May 2009 15:56:41 +0000 Subject: [PATCH 041/717] Changed how tables are layed out (since I was repeatedly duplicating code in many places) by adding a table element to be used wherever we need a table. This could probably have been a helper instead of an element, but it's not clear to me why one should be chosen over the other, and I already know how to quickly add an element (I think the real choice resides in whether you need a collection of helper functions, or you just want to drop in a chunk of html, i.e. a helper element). Also, a major revamp to the style sheets as well, although more work is clearly needed. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@42 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/contacts/view.ctp | 126 ++++++++++--------- site/views/elements/contacts.ctp | 85 ++++++------- site/views/elements/maps.ctp | 81 ++++++------ site/views/elements/table.ctp | 59 +++++++++ site/views/elements/units.ctp | 79 ++++++------ site/views/layouts/default.ctp | 10 +- site/views/units/view.ctp | 43 ++++--- site/webroot/css/cake.generic.css | 203 ++---------------------------- site/webroot/css/layout.css | 154 +++++++++++++++++++++++ site/webroot/css/sidemenu.css | 147 ++++------------------ 10 files changed, 452 insertions(+), 535 deletions(-) create mode 100644 site/views/elements/table.ctp create mode 100644 site/webroot/css/layout.css diff --git a/site/views/contacts/view.ctp b/site/views/contacts/view.ctp index 28aac21..d91fdd2 100644 --- a/site/views/contacts/view.ctp +++ b/site/views/contacts/view.ctp @@ -31,87 +31,88 @@ function datefmt($date) { /********************************************************************** * Tenant Info */ -echo('' . "\n"); -echo(' ' . "\n"); -echo $html->tableCells(array(array('Name', $contact['Contact']['display_name']), - array('Company', $contact['Contact']['company_name']), - array('SSN', $contact['Contact']['id_federal']), - array('ID', $contact['Contact']['id_num'] - . ($contact['Contact']['id_state'] - ? " - ".$contact['Contact']['id_state'] - : "")), - array('Comment', $contact['Contact']['comment'])), - null, array('class' => "altrow"), false, false); -echo('
Tenant Info
' . "\n"); + +$rows = array(array('Name', $contact['Contact']['display_name']), + array('Company', $contact['Contact']['company_name']), + array('SSN', $contact['Contact']['id_federal']), + array('ID', ($contact['Contact']['id_num'] + . ($contact['Contact']['id_state'] + ? " - ".$contact['Contact']['id_state'] + : ""))), + array('Comment', $contact['Contact']['comment'])); + +echo $this->element('table', + array('class' => 'item contact detail', + 'caption' => 'Tenant Info', + 'rows' => $rows, + 'column_class' => array('field', 'value'))); /********************************************************************** * Phones */ -$headers = array('Location', 'Preference', 'Type', 'Phone', 'Extension', 'Comment'); +$headers = array('Preference', 'Phone', 'Comment'); $rows = array(); foreach($contact['ContactPhone'] AS $phone) { - $rows[] = array($phone['ContactsMethod']['type'], - $phone['ContactsMethod']['preference'], + $rows[] = array($phone['ContactsMethod']['preference'] . " / " . + $phone['ContactsMethod']['type'] . " / " . $phone['type'], - phone($phone['phone']), - $phone['ext'], + phone($phone['phone']) . + ($phone['ext'] ? " x".$phone['ext'] : ""), $phone['comment']); } -if (count($rows)) { - echo('' . "\n"); - echo(' ' . "\n"); - echo $html->tableHeaders($headers); - echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); - echo('
Phone
' . "\n"); -} +echo $this->element('table', + array('class' => 'item phone list', + 'caption' => 'Phone', + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $headers)); /********************************************************************** * Emails */ -$headers = array('Location', 'Preference', 'Email', 'Comment'); +$headers = array('Preference', 'Email', 'Comment'); $rows = array(); foreach($contact['ContactEmail'] AS $email) { - $rows[] = array($email['ContactsMethod']['type'], - $email['ContactsMethod']['preference'], + $rows[] = array($email['ContactsMethod']['preference'] . " / " . + $email['ContactsMethod']['type'], $email['email'], $email['comment']); } -if (count($rows)) { - echo('' . "\n"); - echo(' ' . "\n"); - echo $html->tableHeaders($headers); - echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); - echo('
Email
' . "\n"); -} +echo $this->element('table', + array('class' => 'item email list', + 'caption' => 'Email', + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $headers)); /********************************************************************** * Addresses */ -$headers = array('Location', 'Preference', 'Address', 'City', 'State', 'Zip', 'Country', 'Comment'); +$headers = array('Preference', 'Address', 'Comment'); $rows = array(); foreach($contact['ContactAddress'] AS $address) { - $rows[] = array($address['ContactsMethod']['type'], - $address['ContactsMethod']['preference'], - $address['address'], - $address['city'], - $address['state'], - $address['postcode'], - $address['country'], + $rows[] = array($address['ContactsMethod']['preference'] . " / " . + $address['ContactsMethod']['type'], + preg_replace("/\n/", "
\n", $address['address']) . "
\n" . + $address['city'] . ", " . + $address['state'] . " " . + $address['postcode'] + . "
\n" . $address['country'] + , $address['comment']); } -if (count($rows)) { - echo('' . "\n"); - echo(' ' . "\n"); - echo $html->tableHeaders($headers); - echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); - echo('
Address
' . "\n"); -} +echo $this->element('table', + array('class' => 'item address list', + 'caption' => 'Address', + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $headers)); /********************************************************************** @@ -133,11 +134,12 @@ foreach($contact['Lease'] AS $lease) { $lease['comment']); } -echo('' . "\n"); -echo(' ' . "\n"); -echo $html->tableHeaders($headers); -echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); -echo('
Lease History
' . "\n"); +echo $this->element('table', + array('class' => 'item lease list', + 'caption' => 'Lease History', + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $headers)); /********************************************************************** @@ -149,6 +151,7 @@ foreach($contact['Lease'] AS $lease) { $headers = array('Date', /*'Through',*/ /*'Charge/Receipt'*/'ID', 'Type', 'Comment', 'Amount', 'Total'); $rows = array(); + $row_class = array(); $running_total = 0; foreach($lease['Charge'] AS $charge) { $amount = $charge['total']; @@ -159,6 +162,7 @@ foreach($contact['Lease'] AS $lease) { $charge['comment'], currency($amount), currency($running_total)); + $row_class[] = 'charge'; foreach ($charge['Receipt'] AS $receipt) { $amount = -1 * $receipt['ChargesReceipt']['amount']; @@ -173,16 +177,18 @@ foreach($contact['Lease'] AS $lease) { $receipt['comment'], currency($amount), currency($running_total)); + $row_class[] = 'receipt'; } } $grand_total += $running_total; - echo('' . "\n"); - echo(' ' . "\n"); - echo $html->tableHeaders($headers); - echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); - echo('
Lease #'.$lease['number'].' ('.$lease['Unit']['name'].')
' . "\n"); - + echo $this->element('table', + array('class' => 'item ledger list', + 'caption' => 'Lease #'.$lease['number'].' ('.$lease['Unit']['name'].')', + 'headers' => $headers, + 'rows' => $rows, + 'row_class' => $row_class, + 'column_class' => $headers)); } ?> diff --git a/site/views/elements/contacts.ctp b/site/views/elements/contacts.ctp index 6b51553..fca941d 100644 --- a/site/views/elements/contacts.ctp +++ b/site/views/elements/contacts.ctp @@ -4,57 +4,52 @@ if (isset($heading)) echo $heading; else echo '

'.__('Contacts',true).'

'; -?> - +$headers_manual = array('Id', 'Last Name', 'First Name', 'Company', 'Comment'); +if (isset($paginator)) { + echo $paginator->counter(array( + 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); - counter(array( - 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); - - $rows = array($paginator->sort('id'), + $headers = array($paginator->sort('id'), $paginator->sort('last_name'), $paginator->sort('first_name'), $paginator->sort('company_name'), //$paginator->sort('unit_id'), $paginator->sort('comment')); - } else { - $rows = array('Id', 'Last Name', 'First Name', 'Company', 'Comment'); - } - echo $html->tableHeaders($rows); +} else { + $headers = $headers_manual; +} - $rows = array(); - foreach ($contacts as $contact) { - $rows[] = array($html->link($contact['Contact']['id'], - array('controller' => 'contacts', - 'action' => 'view', - $contact['Contact']['id'])), - $html->link($contact['Contact']['last_name'], - array('controller' => 'contacts', - 'action' => 'view', - $contact['Contact']['id'])), - $html->link($contact['Contact']['first_name'], - array('controller' => 'contacts', - 'action' => 'view', - $contact['Contact']['id'])), - $contact['Contact']['company_name'], - $contact['Contact']['comment']); - } - echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); - } -?> -
+$rows = array(); +foreach ($contacts as $contact) { + $rows[] = array($html->link($contact['Contact']['id'], + array('controller' => 'contacts', + 'action' => 'view', + $contact['Contact']['id'])), + $html->link($contact['Contact']['last_name'], + array('controller' => 'contacts', + 'action' => 'view', + $contact['Contact']['id'])), + $html->link($contact['Contact']['first_name'], + array('controller' => 'contacts', + 'action' => 'view', + $contact['Contact']['id'])), + $contact['Contact']['company_name'], + $contact['Contact']['comment']); +} -' . "\n"); - echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); - echo(' | '); - echo $paginator->numbers(); - echo(' | '); - echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); - echo('
' . "\n"); - } -?> +echo $this->element('table', + array('class' => 'item contact list', + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $headers_manual)); + +if (isset($paginator)) { + echo('
' . "\n"); + echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); + echo(' | '); + echo $paginator->numbers(); + echo(' | '); + echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); + echo('
' . "\n"); +} diff --git a/site/views/elements/maps.ctp b/site/views/elements/maps.ctp index 0de3f45..ee148c9 100644 --- a/site/views/elements/maps.ctp +++ b/site/views/elements/maps.ctp @@ -4,55 +4,50 @@ if (isset($heading)) echo $heading; else echo '

'.__('Maps',true).'

'; -?> - +$headers_manual = array('Id', 'Name', 'Area', 'Width', 'Depth', 'Comment'); +if (isset($paginator)) { + echo $paginator->counter(array( + 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); - counter(array( - 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); - - $rows = array($paginator->sort('id'), + $headers = array($paginator->sort('id'), $paginator->sort('name'), $paginator->sort('site_area_id'), $paginator->sort('width'), $paginator->sort('depth'), $paginator->sort('comment')); - } else { - $rows = array('Id', 'Name', 'Area', 'Width', 'Depth', 'Comment'); - } - echo $html->tableHeaders($rows); +} else { + $headers = $headers_manual; +} - $rows = array(); - foreach ($maps as $map) { - $rows[] = array($html->link($map['Map']['id'], - array('controller' => 'maps', - 'action' => 'view', - $map['Map']['id'])), - $html->link($map['Map']['name'], - array('controller' => 'maps', - 'action' => 'view', - $map['Map']['id'])), - $map['SiteArea']['name'], - $map['Map']['width'] / 12, - $map['Map']['depth'] / 12, - $map['Map']['comment']); - } - echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); - } -?> -
+$rows = array(); +foreach ($maps as $map) { + $rows[] = array($html->link($map['Map']['id'], + array('controller' => 'maps', + 'action' => 'view', + $map['Map']['id'])), + $html->link($map['Map']['name'], + array('controller' => 'maps', + 'action' => 'view', + $map['Map']['id'])), + $map['SiteArea']['name'], + $map['Map']['width'] / 12, + $map['Map']['depth'] / 12, + $map['Map']['comment']); +} -' . "\n"); - echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); - echo(' | '); - echo $paginator->numbers(); - echo(' | '); - echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); - echo('
' . "\n"); - } -?> +echo $this->element('table', + array('class' => 'item map list', + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $headers_manual)); + +if (isset($paginator)) { + echo('
' . "\n"); + echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); + echo(' | '); + echo $paginator->numbers(); + echo(' | '); + echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); + echo('
' . "\n"); +} diff --git a/site/views/elements/table.ctp b/site/views/elements/table.ctp new file mode 100644 index 0000000..31fb7fd --- /dev/null +++ b/site/views/elements/table.ctp @@ -0,0 +1,59 @@ +' . "\n"); + if (isset($caption)) + echo(' ' . $caption . '' . "\n"); + + if (isset($row_class) && is_array($row_class)) { + foreach ($row_class AS &$rc) + $rc = preg_replace("/ /", "-", strtolower($rc)); + } + + if (isset($column_class) && is_array($column_class)) { + foreach ($column_class AS &$cc) + $cc = preg_replace("/ /", "-", strtolower($cc)); + } + +/* if (isset($headers) && is_array($headers)) { */ +/* foreach ($headers AS $i => $col) { */ +/* if (!isset($column_class[$i])) */ +/* continue; */ +/* $headers[$i] = array($col, array('class' => $column_class[$i])); */ +/* } */ +/* } */ + + // Very kludgy. + // I want the row_class to affix to the tag. + // tableCells, however, does not have such ability :-/ + foreach ($rows AS $r => &$row) { + foreach ($row AS $c => $col) { + $colclass = (isset($column_class) && is_array($column_class)) ? $column_class[$c] : '';; + $rowclass = (isset($row_class) && is_array($row_class)) ? $row_class[$r] : ''; + $class = $rowclass . ($colclass ? " " . $colclass : ''); + if (!$class) + continue; + $row[$c] = array($col, array('class' => $class)); + } + } + + echo("\n"); + if (isset($headers) && is_array($headers)) + echo $html->tableHeaders($headers); + + echo("\n"); + echo $html->tableCells($rows, + array('class' => "oddrow"), + array('class' => "evnrow"), + false, false); + echo("\n"); + echo('' . "\n"); +} diff --git a/site/views/elements/units.ctp b/site/views/elements/units.ctp index 8d504c0..d0f90ee 100644 --- a/site/views/elements/units.ctp +++ b/site/views/elements/units.ctp @@ -4,53 +4,48 @@ if (isset($heading)) echo $heading; else echo '

'.__('Units',true).'

'; -?> - +$headers_manual = array('Id', 'Unit', 'Size', 'Status', 'Comment'); +if (isset($paginator)) { + echo $paginator->counter(array( + 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); - counter(array( - 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); - - $rows = array($paginator->sort('id'), + $headers = array($paginator->sort('id'), $paginator->sort('Unit', 'name'), $paginator->sort('unit_size_id'), $paginator->sort('status'), $paginator->sort('comment')); - } else { - $rows = array('Id', 'Unit', 'Size', 'Status', 'Comment'); - } - echo $html->tableHeaders($rows); +} else { + $headers = $headers_manual; +} - $rows = array(); - foreach ($units as $unit) { - $rows[] = array($html->link($unit['Unit']['id'], - array('controller' => 'units', - 'action' => 'view', - $unit['Unit']['id'])), - $html->link($unit['Unit']['name'], - array('controller' => 'units', - 'action' => 'view', - $unit['Unit']['id'])), - $unit['UnitSize']['name'], - $unit['Unit']['status'], - $unit['Unit']['comment']); - } - echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); - } -?> -
+$rows = array(); +foreach ($units as $unit) { + $rows[] = array($html->link($unit['Unit']['id'], + array('controller' => 'units', + 'action' => 'view', + $unit['Unit']['id'])), + $html->link($unit['Unit']['name'], + array('controller' => 'units', + 'action' => 'view', + $unit['Unit']['id'])), + $unit['UnitSize']['name'], + $unit['Unit']['status'], + $unit['Unit']['comment']); +} -' . "\n"); - echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); - echo(' | '); - echo $paginator->numbers(); - echo(' | '); - echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); - echo('
' . "\n"); - } -?> +echo $this->element('table', + array('class' => 'item unit list', + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $headers_manual)); + +if (isset($paginator)) { + echo('
' . "\n"); + echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); + echo(' | '); + echo $paginator->numbers(); + echo(' | '); + echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); + echo('
' . "\n"); +} diff --git a/site/views/layouts/default.ctp b/site/views/layouts/default.ctp index a703388..f6ff58d 100644 --- a/site/views/layouts/default.ctp +++ b/site/views/layouts/default.ctp @@ -30,12 +30,12 @@ Property Manager: meta('icon'); - echo $html->css('cake.generic'); - echo $scripts_for_layout; + echo $html->meta('icon') . "\n"; + echo $html->css('cake.generic') . "\n"; + echo $html->css('layout') . "\n"; + echo $html->css('sidemenu') . "\n"; + echo $scripts_for_layout . "\n"; ?> - - diff --git a/site/views/units/view.ctp b/site/views/units/view.ctp index 307f380..f9cf7d7 100644 --- a/site/views/units/view.ctp +++ b/site/views/units/view.ctp @@ -21,18 +21,16 @@ function datefmt($date) { /********************************************************************** * Unit Info */ -$rows = array(); -foreach($unit['Unit'] AS $col => $val) { - $rows[] = array(array($col, 'width=1%'), $val); -} -echo('' . "\n"); -echo(' ' . "\n"); -echo $html->tableCells(array(array('Name', $unit['Unit']['name']), - array('Status', $unit['Unit']['status']), - array('Comment', $unit['Unit']['comment'])), - null, array('class' => "altrow"), false, false); -echo('
Unit Info
' . "\n"); +$rows = array(array('Name', $unit['Unit']['name']), + array('Status', $unit['Unit']['status']), + array('Comment', $unit['Unit']['comment'])); + +echo $this->element('table', + array('class' => 'item unit detail', + 'caption' => 'Unit Info', + 'rows' => $rows, + 'column_class' => array('field', 'value'))); /********************************************************************** @@ -54,11 +52,12 @@ foreach($unit['Lease'] AS $lease) { $lease['comment']); } -echo('' . "\n"); -echo(' ' . "\n"); -echo $html->tableHeaders($headers); -echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); -echo('
Lease History
' . "\n"); +echo $this->element('table', + array('class' => 'item lease list', + 'caption' => 'Lease History', + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $headers)); /********************************************************************** @@ -98,12 +97,12 @@ foreach($unit['Lease'] AS $lease) { } $grand_total += $running_total; - echo('' . "\n"); - echo(' ' . "\n"); - echo $html->tableHeaders($headers); - echo $html->tableCells($rows, null, array('class' => "altrow"), false, false); - echo('
Lease #'.$lease['number'].' ('.$lease['Contact'][0]['display_name'].')
' . "\n"); - + echo $this->element('table', + array('class' => 'item ledger list', + 'caption' => 'Lease #'.$lease['number'].' ('.$lease['Contact'][0]['display_name'].')', + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $headers)); } ?> diff --git a/site/webroot/css/cake.generic.css b/site/webroot/css/cake.generic.css index 8fc98f4..a6d84f3 100644 --- a/site/webroot/css/cake.generic.css +++ b/site/webroot/css/cake.generic.css @@ -27,59 +27,6 @@ padding:0; } -/* General Style Info */ -body { - background: #003d4c; - color: #fff; - font-family:'lucida grande',verdana,helvetica,arial,sans-serif; - font-size:90%; - margin: 0; -} -a { - background:#fff; - color: #003d4c; - text-decoration: underline; - font-weight: bold; -} -a:hover { - background:#fff; - color: #003d4c; - text-decoration:none; -} -a img { - border:none; -} -h1, h2, h3, h4 { - font-weight: normal; -} -h1 { - background:#fff; - color: #003d4c; - font-size: 100%; - margin: 0.1em 0; -} -h2 { - background:#fff; - color: #e32; - font-family:'Gill Sans','lucida grande',helvetica, arial, sans-serif; - font-size: 190%; - margin-bottom: 0.3em; -} -h3 { - color: #993; - font-family:'Gill Sans','lucida grande',helvetica, arial, sans-serif; - font-size: 165%; - padding-top: 1.5em; -} -h4 { - color: #993; - font-weight: normal; - padding-top: 0.5em; -} -ul, li { - margin: 0 12px; -} - /* Layout */ #container { text-align: left; @@ -117,51 +64,7 @@ ul, li { text-align: right; } -/* Tables */ -table { - background: #fff; - border:1px solid #ccc; - border-right:0; - clear: both; - color: #333; - margin-bottom: 10px; - width: 100%; -} -th { - background: #f2f2f2; - border:1px solid #bbb; - border-top: 1px solid #fff; - border-left: 1px solid #fff; - text-align: center; -} -th a { - background:#f2f2f2; - display: block; - padding: 2px 4px; - text-decoration: none; -} -th a:hover { - background: #ccc; - color: #333; - text-decoration: none; -} -table tr td { - background: #fff; - border-right: 1px solid #ccc; - padding: 4px; - text-align: center; - vertical-align: top; -} -table tr.altrow td { - background: #f4f4f4; -} -td.actions { - text-align: center; - white-space: nowrap; -} -td.actions a { - margin: 0px 6px; -} + .cake-sql-log table { background: #f4f4f4; } @@ -208,102 +111,6 @@ dd { vertical-align: top; } -/* Forms */ -form { - clear: both; - margin-right: 20px; - padding: 0; - width: 80%; -} -fieldset { - border: 1px solid #ccc; - margin-top: 30px; - padding: 16px 20px; -} -fieldset legend { - background:#fff; - color: #e32; - font-size: 160%; - font-weight: bold; -} -fieldset fieldset { - margin-top: 0px; - margin-bottom: 20px; - padding: 16px 10px; -} -fieldset fieldset legend { - font-size: 120%; - font-weight: normal; -} -fieldset fieldset div { - clear: left; - margin: 0 20px; -} -form div { - clear: both; - margin-bottom: 1em; - padding: .5em; - vertical-align: text-top; -} -form div.input { - color: #444; -} -form div.required { - color: #333; - font-weight: bold; -} -form div.submit { - border: 0; - clear: both; - margin-top: 10px; - margin-left: 140px; -} -label { - display: block; - font-size: 110%; - padding-right: 20px; -} -input, textarea { - clear: both; - font-size: 140%; - font-family: "frutiger linotype", "lucida grande", "verdana", sans-serif; - padding: 2px; - width: 100%; -} -select { - clear: both; - font-size: 120%; - vertical-align: text-bottom; -} -select[multiple=multiple] { - width: 100%; -} -option { - font-size: 120%; - padding: 0 3px; -} -input[type=checkbox] { - clear: left; - float: left; - margin: 0px 6px 7px 2px; - width: auto; -} -input[type=radio] { - float:left; - width:auto; - margin: 0 3px 7px 0; -} -div.radio label { - margin: 0 0 6px 20px; -} -input[type=submit] { - display: inline; - font-size: 110%; - padding: 2px 5px; - width: auto; - vertical-align: bottom; -} - /* Notices and Errors */ div.message { clear: both; @@ -347,6 +154,14 @@ p.error em { } /* Actions */ +td.actions { + text-align: center; + white-space: nowrap; +} +td.actions a { + margin: 0px 6px; +} + div.actions ul { margin: 0px 0; padding: 0; diff --git a/site/webroot/css/layout.css b/site/webroot/css/layout.css new file mode 100644 index 0000000..e4a6999 --- /dev/null +++ b/site/webroot/css/layout.css @@ -0,0 +1,154 @@ +/************************************************************ + ************************************************************ + * Debug table margin/padding helper + */ + +/* table th, td { border: dashed 1px; } */ + +/************************************************************ + ************************************************************ + * Overall page layout + */ + +table#layout { width: 100% } +td#sidecolumn , +td#pagecolumn { vertical-align: top; } +td#pagecolumn { padding-left: 4mm; } + + +/************************************************************ + ************************************************************ + * Panel captions + */ + +table caption { text-align: left; + font-size: 120%; + font-weight: bold; + margin-bottom: 0.5em; + } + +table.item caption { margin-top: 1em; } +table.detail caption { margin-top: 0; } + + +/************************************************************ + ************************************************************ + * Cell configuration + */ + +table.item th , +table.item td { padding: 0.1em 0.4em 0.1em 0.4em; } +table.item { white-space: nowrap; } +/* table.item { border-spacing: 0 0; /\*IE*\/border-collapse: collapse; empty-cells: show } */ +table.item { border-spacing: 0 0; empty-cells: show } +table.item { border:1px solid #ccc; + border-bottom:2px solid #ccc; + } + +table.item th { background: #f2f2f2; + border-top: 1px solid #fff; + border-left: 1px solid #fff; + border-right: 1px solid #ccc; +/* text-align: center; */ + } +table.item td { border-right: 1px solid #ccc; } + +tr.evnrow { background: #f4f4f4; } + + +/************************************************************ + ************************************************************ + * Formatting for item listings + */ + +/** Item listing width and borders **/ +table.list { width : 100%; } +table.detail { width : 60%; } + +/** Column to which any extra real estate should be allocated **/ +/* table.list.view td#referer , */ +/* table.list.browser td#web_browser , */ +/* table.list.tracker td#url , */ +table.list td.comment { width: 99%; } +table.detail td.field { width: 10em } + +/** Text alignment exceptions **/ +table.list td.id { text-align: center; } + +/** White spacing exceptions **/ +table.list td.comment { white-space: normal; } + +/* table.detail td {word-wrap : normal} */ + +table.list.ledger td.date.receipt { padding-left: 1em } + + +/************************************************************ + ************************************************************ + * General Style Info + */ + +body { +/* background: #003d4c; */ +/* color: #fff; */ + font-family:'lucida grande',verdana,helvetica,arial,sans-serif; + font-size:90%; + margin: 0; +} +a { + color: #003d4c; + text-decoration: underline; + font-weight: bold; +} +a:hover { + color: #f00; + text-decoration:none; +} +a img { + border:none; +} + +h1, h2, h3, h4 { + font-weight: normal; +} + +h1 { + background:#fff; + color: #003d4c; + font-size: 100%; + margin: 0.1em 0; +} +h2 { + background:#fff; + color: #e32; + font-family:'Gill Sans','lucida grande',helvetica, arial, sans-serif; + font-size: 190%; + margin-bottom: 0.3em; +} +h3 { + color: #993; + font-family:'Gill Sans','lucida grande',helvetica, arial, sans-serif; + font-size: 165%; + padding-top: 1.5em; +} +h4 { + color: #993; + font-weight: normal; + padding-top: 0.5em; +} + + + +/* Forms */ +} +input[type=checkbox] { + clear: left; + float: left; + margin: 0px 6px 7px 2px; + width: auto; +} +input[type=radio] { + float:left; + width:auto; + margin: 0 3px 7px 0; +} diff --git a/site/webroot/css/sidemenu.css b/site/webroot/css/sidemenu.css index 94f29cf..c141e61 100644 --- a/site/webroot/css/sidemenu.css +++ b/site/webroot/css/sidemenu.css @@ -1,141 +1,40 @@ /************************************************************ ************************************************************ - * Debug table margin/padding helper + * Side Menu Layout */ -/* table th, td { border: dashed 1px; } */ +td#sidecolumn { width: 10em; background: lightblue; text-align: left; } -/************************************************************ - ************************************************************ - * Overall page layout - */ - -table#layout { width: 100% } -td#sidecolumn { width: 10em; background: lightblue; text-align: left; } -td#pagecolumn { padding-left: 4mm; } -td#sidecolumn , -td#pagecolumn { vertical-align: top; } - -td#sidecolumn .header { margin-top: 0.4em; } td#sidecolumn .header , td#sidecolumn .item { white-space : nowrap; } -td#sidecolumn .item { padding-left: 0.6em; } -td#sidecolumn .item a { background: lightblue; } + + +/************************************************************ + ************************************************************ + * Menu Headers + */ + +td#sidecolumn .header { margin-top: 0.4em; + background: blue; + color: white; + font-weight: bold; + } + + + +/************************************************************ + ************************************************************ + * Menu Separators + */ td#sidecolumn hr { margin-top: 0.4em; margin-bottom: 0.3em; } -/************************************************************ - ************************************************************ - * Panel captions - */ - -table caption { text-align: left; - font-size: 120%; - font-weight: bold; - margin-bottom: 0.5em; - } - /************************************************************ ************************************************************ - * Panel headers + * Menu Items */ -td#sidecolumn .header , -table.list th , -table.edit td.name { background: blue; - color: white; - font-weight: bold; - } +td#sidecolumn .item { padding-left: 0.6em; } - -/************************************************************ - ************************************************************ - * Cell configuration - */ - -th, td { padding: 0.1em 0.4em 0.1em 0.4em; } -table.item { border-spacing: 0 0; /*IE*/border-collapse: collapse; empty-cells: show } - - -/************************************************************ - ************************************************************ - * Overall text alignment - */ - -th, td { text-align: left; } - - -/************************************************************ - ************************************************************ - * Formatting for item listings - */ - -/** Item listing width and borders **/ -table.list { width: 100%; } -table.list td { border: 1px solid #000; } - -/* IE doesn't seem to work with first-child. this combination of - * rules works for both IE and Firefox */ -table.list th { border-left: 1px solid #fff; border-top: 1px solid #000; } -table.list th:first-child { border-left: 1px solid #000 } -table.list { border: 1px solid #000; } - -/** Column to which any extra real estate should be allocated **/ -table.list.view td#referer , -table.list.browser td#web_browser , -table.list.tracker td#url , -table.list.category td#comment { width: 99%; } - -/** Text alignment exceptions **/ -table.list td#id , -table.list td#operation , -table.list td#browser , -table.list td#views , -table.list td#uniques { text-align: center; } - -/** White spacing exceptions **/ -table.list { white-space : nowrap } -table.list.browser td#web_browser , -table.list.category td#comment { white-space: normal; } - - -/************************************************************ - ************************************************************ - * Format for item editing - */ - -/** Item editing width and borders **/ -table.edit tr:first-child td.name { border-top: none } -table.edit td.name { border-top: 1px solid #fff; width:1% } - -/** Text alignment exceptions **/ -table.edit td.name { text-align: right } -table.edit td.value { text-align: left } - - -/************************************************************ - ************************************************************ - * Form submission buttons after item tables - */ - -div.opbuttons { margin-top: 1.0em; text-align: left } - - - - -/* table#unitinfo, table#tenantinfo { width: 60% } */ -/* table#unitinfo td:first-child, table#tenantinfo td:first-child { width: 30% } */ -/* table#unitinfo td, table#tenanatinfo td { width: 70% } */ -/* /\*table.detail td:first-child { width: 30% }*\/ */ -/* /\*table.detail td { width: 1% }*\/ */ -/* #unitinfo caption, #tenantinfo caption { margin-top: 0px; } */ -/* table.detail caption { margin-top: 1.5em; text-align: left; font-size: 14pt; font-weight: bold } */ -/* table.detail {width: 80% } */ -/* table.detail {border-spacing: 0 0} */ -/* table.detail {border-left: 1px solid #000; border-top: 1px solid #000} */ -/* table.detail {empty-cells: show} */ -/* table.detail td, table.detail th {padding: 0.1em 0.2em 0.1em 0.2em } */ -/* table.detail td, table.detail th {border-right: 1px solid #000; border-bottom: 1px solid #000} */ -/* table.detail td {word-wrap : normal} */ From 7fae1bcaad9aa0edb5ca84e7712b4eb279bbaeb9 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 30 May 2009 20:07:24 +0000 Subject: [PATCH 042/717] Modified table element algorithm to be cleaner and to handle multiple class types. Modified ledger listings to group the charges and associated payment rows with one color. Fixed summary balance data to come from the controller instead of being created in the view. Created an infobox to carry pertinent info in the top right of the view pages. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@43 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/contacts_controller.php | 21 +++++- site/controllers/units_controller.php | 30 +++++--- site/views/contacts/view.ctp | 56 +++++++------- site/views/elements/table.ctp | 96 ++++++++++++++---------- site/views/units/view.ctp | 28 ++++--- site/webroot/css/layout.css | 90 +++++++++++++++------- 6 files changed, 207 insertions(+), 114 deletions(-) diff --git a/site/controllers/contacts_controller.php b/site/controllers/contacts_controller.php index 5e1ccdc..a721839 100644 --- a/site/controllers/contacts_controller.php +++ b/site/controllers/contacts_controller.php @@ -142,7 +142,26 @@ class ContactsController extends AppController { $contact = $this->Contact->read(null, $id); $title = $contact['Contact']['display_name']; - $this->set(compact('contact', 'title')); + + $outstanding_deposit = 0; + $outstanding_balance = 0; + foreach($contact['Lease'] AS $lease) { + foreach($lease['Charge'] AS $charge) { + $outstanding_balance += $charge['total']; + foreach ($charge['Receipt'] AS $receipt) { + $outstanding_balance -= $receipt['ChargesReceipt']['amount']; + // REVISIT 20090530: + // Using hardcoded value for security deposit... + // That can't be good! + if ($charge['charge_type_id'] == 1) + $outstanding_deposit += $receipt['ChargesReceipt']['amount']; + } + } + } + + $this->set(compact('contact', 'title', 'mytstval', + 'outstanding_balance', + 'outstanding_deposit')); } } diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index 63fe664..a184efa 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -125,18 +125,26 @@ class UnitsController extends AppController { $unit = $this->Unit->read(null, $id); $title = 'Unit ' . $unit['Unit']['name']; - $this->set(compact('unit', 'title')); -/* $this->Unit->id = $id; */ -/* if ($id !== null && $id !== false) { */ -/* $this->Unit->data = $this->Unit->find('first', */ -/* array('conditions' => array( */ -/* $this->Unit->alias . '.' . $this->Unit->primaryKey => $id, */ -/* 'ContactsLease.type = "TENANT"' */ -/* ) */ -/* )); */ -/* $this->set('unit', $this->Unit->data); */ -/* } */ + $outstanding_deposit = 0; + $outstanding_balance = 0; + foreach($unit['Lease'] AS $lease) { + foreach($lease['Charge'] AS $charge) { + $outstanding_balance += $charge['total']; + foreach ($charge['Receipt'] AS $receipt) { + $outstanding_balance -= $receipt['ChargesReceipt']['amount']; + // REVISIT 20090530: + // Using hardcoded value for security deposit... + // That can't be good! + if ($charge['charge_type_id'] == 1) + $outstanding_deposit += $receipt['ChargesReceipt']['amount']; + } + } + } + + $this->set(compact('unit', 'title', + 'outstanding_balance', + 'outstanding_deposit')); } } diff --git a/site/views/contacts/view.ctp b/site/views/contacts/view.ctp index d91fdd2..9209167 100644 --- a/site/views/contacts/view.ctp +++ b/site/views/contacts/view.ctp @@ -48,17 +48,29 @@ echo $this->element('table', 'column_class' => array('field', 'value'))); +?> +
+
+ Security Deposit: +
+
+ Balance: +
+
+element('table', /********************************************************************** * Emails */ -$headers = array('Preference', 'Email', 'Comment'); +$headers = array('Email', 'Preference', 'Comment'); $rows = array(); foreach($contact['ContactEmail'] AS $email) { - $rows[] = array($email['ContactsMethod']['preference'] . " / " . + $rows[] = array($email['email'], + $email['ContactsMethod']['preference'] . " / " . $email['ContactsMethod']['type'], - $email['email'], $email['comment']); } @@ -93,17 +105,16 @@ echo $this->element('table', /********************************************************************** * Addresses */ -$headers = array('Preference', 'Address', 'Comment'); +$headers = array('Address', 'Preference', 'Comment'); $rows = array(); foreach($contact['ContactAddress'] AS $address) { - $rows[] = array($address['ContactsMethod']['preference'] . " / " . - $address['ContactsMethod']['type'], - preg_replace("/\n/", "
\n", $address['address']) . "
\n" . + $rows[] = array(preg_replace("/\n/", "
\n", $address['address']) . "
\n" . $address['city'] . ", " . $address['state'] . " " . - $address['postcode'] - . "
\n" . $address['country'] - , + $address['postcode'], + //. ? "
\n" . $address['country'], + $address['ContactsMethod']['preference'] . " / " . + $address['ContactsMethod']['type'], $address['comment']); } @@ -121,7 +132,7 @@ echo $this->element('table', $headers = array('Lease', 'Unit', 'Signed', 'Move-In', 'Move-Out', 'Rent', 'Deposit', 'Comment'); $rows = array(); foreach($contact['Lease'] AS $lease) { - $rows[] = array('#'.$lease['id'], + $rows[] = array('#'.$lease['number'], $html->link($lease['Unit']['name'], array('controller' => 'units', 'action' => 'view', @@ -145,14 +156,13 @@ echo $this->element('table', /********************************************************************** * Ledger History */ -$security_deposit = 0; -$grand_total = 0; foreach($contact['Lease'] AS $lease) { $headers = array('Date', /*'Through',*/ /*'Charge/Receipt'*/'ID', 'Type', 'Comment', 'Amount', 'Total'); $rows = array(); $row_class = array(); $running_total = 0; + $odd = 0; foreach($lease['Charge'] AS $charge) { $amount = $charge['total']; $running_total += $amount; @@ -162,29 +172,25 @@ foreach($contact['Lease'] AS $lease) { $charge['comment'], currency($amount), currency($running_total)); - $row_class[] = 'charge'; + $row_class[] = array('charge', (++$odd % 2) ? 'oddrow' : 'evnrow'); foreach ($charge['Receipt'] AS $receipt) { $amount = -1 * $receipt['ChargesReceipt']['amount']; $running_total += $amount; - // REVISIT 20090527: - // Using hardcoded value for security deposit... can't be good! - if ($charge['charge_type_id'] == 1) - $security_deposit += $receipt['ChargesReceipt']['amount']; $rows[] = array(' -- ' . datefmt($receipt['stamp']), '#'.$receipt['id'], 'Payment/Receipt', $receipt['comment'], currency($amount), currency($running_total)); - $row_class[] = 'receipt'; + $row_class[] = array('receipt', ($odd % 2) ? 'oddrow' : 'evnrow'); } } - $grand_total += $running_total; echo $this->element('table', array('class' => 'item ledger list', 'caption' => 'Lease #'.$lease['number'].' ('.$lease['Unit']['name'].')', + 'suppress_alternate_rows' => true, 'headers' => $headers, 'rows' => $rows, 'row_class' => $row_class, @@ -192,6 +198,4 @@ foreach($contact['Lease'] AS $lease) { } ?> -

Total Security Deposit:

-

Outstanding Balance:

diff --git a/site/views/elements/table.ctp b/site/views/elements/table.ctp index 31fb7fd..fdb973f 100644 --- a/site/views/elements/table.ctp +++ b/site/views/elements/table.ctp @@ -8,52 +8,70 @@ * @package pmgr */ + +// The caller may not have given us a row_class, or may have given +// it as a non-array. Ultimately, we want it to be an array with +// an entry for each row, where each entry is an array of classes. +if (!isset($row_class) || !is_array($row_class)) + $row_class = array(); + +// Same for the column_class, except columns instead of rows. +if (!isset($column_class) || !is_array($column_class)) + $column_class = array(); + +// Give a default if not caller supplied. +if (!isset($suppress_alternate_rows)) + $suppress_alternate_rows = false; + +// If we have rows, then we have a table... go to work if (isset($rows) && is_array($rows) && count($rows)) { + + // Prework to get each element of row_class as an + // array of classes, lowercased and whitespace free. + foreach ($row_class AS &$rca) { + if (!is_array($rca)) + $rca = array($rca); + foreach ($rca AS &$rc) + $rc = preg_replace("/ /", "-", strtolower($rc)); + } + + // Same prework for column_class + foreach ($column_class AS &$cca) { + if (!is_array($cca)) + $cca = array($cca); + foreach ($cca AS &$cc) + $cc = preg_replace("/ /", "-", strtolower($cc)); + } + + // Associate each cell with the appropriate class(es). + // NOTE: Very kludgy solution on the row class(es). + // I want the row_class to affix to the tag. + // tableCells, however, does not have such ability :-/ + // Therefore, the row class(es) get replicated to each + // cell within the row. + + foreach ($rows AS $r => &$row) { + foreach ($row AS $c => $col) { + $cell_class = implode(" ", array_merge(isset( $row_class[$r]) ? $row_class[$r] : array(), + isset($column_class[$c]) ? $column_class[$c] : array())); + if ($cell_class) + $row[$c] = array($col, array('class' => $cell_class)); + } + } + echo('
' . "\n"); if (isset($caption)) echo(' ' . $caption . '' . "\n"); - if (isset($row_class) && is_array($row_class)) { - foreach ($row_class AS &$rc) - $rc = preg_replace("/ /", "-", strtolower($rc)); - } - - if (isset($column_class) && is_array($column_class)) { - foreach ($column_class AS &$cc) - $cc = preg_replace("/ /", "-", strtolower($cc)); - } - -/* if (isset($headers) && is_array($headers)) { */ -/* foreach ($headers AS $i => $col) { */ -/* if (!isset($column_class[$i])) */ -/* continue; */ -/* $headers[$i] = array($col, array('class' => $column_class[$i])); */ -/* } */ -/* } */ - - // Very kludgy. - // I want the row_class to affix to the tag. - // tableCells, however, does not have such ability :-/ - foreach ($rows AS $r => &$row) { - foreach ($row AS $c => $col) { - $colclass = (isset($column_class) && is_array($column_class)) ? $column_class[$c] : '';; - $rowclass = (isset($row_class) && is_array($row_class)) ? $row_class[$r] : ''; - $class = $rowclass . ($colclass ? " " . $colclass : ''); - if (!$class) - continue; - $row[$c] = array($col, array('class' => $class)); - } - } - - echo("\n"); if (isset($headers) && is_array($headers)) - echo $html->tableHeaders($headers); + echo $html->tableHeaders($headers) . "\n"; - echo("\n"); echo $html->tableCells($rows, - array('class' => "oddrow"), - array('class' => "evnrow"), - false, false); - echo("\n"); + $suppress_alternate_rows ? null : array('class' => "oddrow"), + $suppress_alternate_rows ? null : array('class' => "evnrow"), + false, false) . "\n"; + echo('' . "\n"); + echo('element('table', 'column_class' => array('field', 'value'))); +?> +
+
+ Security Deposit: +
+
+ Balance: +
+
+link($lease['Contact'][0]['display_name'], array('controller' => 'contacts', 'action' => 'view', @@ -63,13 +75,12 @@ echo $this->element('table', /********************************************************************** * Ledger History */ -$security_deposit = 0; -$grand_total = 0; foreach($unit['Lease'] AS $lease) { $headers = array('Date', /*'Through',*/ /*'Charge/Receipt'*/'ID', 'Type', 'Comment', 'Amount', 'Total'); $rows = array(); $running_total = 0; + $odd = 0; foreach($lease['Charge'] AS $charge) { $amount = $charge['total']; $running_total += $amount; @@ -79,33 +90,30 @@ foreach($unit['Lease'] AS $lease) { $charge['comment'], currency($amount), currency($running_total)); + $row_class[] = array('charge', (++$odd % 2) ? 'oddrow' : 'evnrow'); foreach ($charge['Receipt'] AS $receipt) { $amount = -1 * $receipt['ChargesReceipt']['amount']; $running_total += $amount; - // REVISIT 20090527: - // Using hardcoded value for security deposit... can't be good! - if ($charge['charge_type_id'] == 1) - $security_deposit += $receipt['ChargesReceipt']['amount']; $rows[] = array(' -- ' . datefmt($receipt['stamp']), '#'.$receipt['id'], 'Payment/Receipt', $receipt['comment'], currency($amount), currency($running_total)); + $row_class[] = array('receipt', ($odd % 2) ? 'oddrow' : 'evnrow'); } } - $grand_total += $running_total; echo $this->element('table', array('class' => 'item ledger list', 'caption' => 'Lease #'.$lease['number'].' ('.$lease['Contact'][0]['display_name'].')', + 'suppress_alternate_rows' => true, 'headers' => $headers, 'rows' => $rows, + 'row_class' => $row_class, 'column_class' => $headers)); } ?> -

Total Security Deposit:

-

Outstanding Balance:

diff --git a/site/webroot/css/layout.css b/site/webroot/css/layout.css index e4a6999..7574d43 100644 --- a/site/webroot/css/layout.css +++ b/site/webroot/css/layout.css @@ -24,11 +24,12 @@ td#pagecolumn { padding-left: 4mm; } table caption { text-align: left; font-size: 120%; font-weight: bold; - margin-bottom: 0.5em; + padding-bottom: 0.5em; } -table.item caption { margin-top: 1em; } -table.detail caption { margin-top: 0; } +table.item { margin-bottom: 1.5em; } +/* table.item caption { margin-top: 1em; } */ +/* table.detail caption { margin-top: 0; } */ /************************************************************ @@ -38,7 +39,7 @@ table.detail caption { margin-top: 0; } table.item th , table.item td { padding: 0.1em 0.4em 0.1em 0.4em; } -table.item { white-space: nowrap; } +table.item td { white-space: nowrap; } /* table.item { border-spacing: 0 0; /\*IE*\/border-collapse: collapse; empty-cells: show } */ table.item { border-spacing: 0 0; empty-cells: show } table.item { border:1px solid #ccc; @@ -49,7 +50,7 @@ table.item th { background: #f2f2f2; border-top: 1px solid #fff; border-left: 1px solid #fff; border-right: 1px solid #ccc; -/* text-align: center; */ + text-align: center; } table.item td { border-right: 1px solid #ccc; } @@ -58,29 +59,66 @@ tr.evnrow { background: #f4f4f4; } /************************************************************ ************************************************************ - * Formatting for item listings + * Item table formats */ -/** Item listing width and borders **/ -table.list { width : 100%; } -table.detail { width : 60%; } +/* Item listing width and borders */ +table.detail { width : 60%; } +table.list { width : 100%; } -/** Column to which any extra real estate should be allocated **/ -/* table.list.view td#referer , */ -/* table.list.browser td#web_browser , */ -/* table.list.tracker td#url , */ -table.list td.comment { width: 99%; } -table.detail td.field { width: 10em } +/* Text alignment exceptions */ +table.list td.id { text-align: center; } -/** Text alignment exceptions **/ -table.list td.id { text-align: center; } +/* White spacing exceptions */ +td.comment { white-space: normal; } -/** White spacing exceptions **/ -table.list td.comment { white-space: normal; } +/* Detail Tables (such as Tenant Info, Unit Info, etc) */ +table.detail { float: left; } +table.detail td.field { width: 10em; } -/* table.detail td {word-wrap : normal} */ +/* List Tables (listing multiple items of one type) */ +table.list { clear: both; } -table.list.ledger td.date.receipt { padding-left: 1em } +/* Contact methods */ +table.list.phone td.preference , +table.list.email td.preference , +table.list.address td.preference { width: 18em; } +table.list.phone td.phone , +table.list.email td.email , +table.list.address td.address { width: 15em; } +table.list.phone td.comment , +table.list.email td.comment , +table.list.address td.comment { width: auto; } + +/* Leases */ +table.list.lease td.comment { width : 99%; } + +/* Ledger Entries */ +table.list.ledger td { border-top : 1px dashed #ccc; } +table.list.ledger td.date.receipt { padding-left: 1em; } +table.list.ledger td.evnrow { background: #f4f4f4; } +table.list.ledger td.comment { width : 99%; } + + +/************************************************************ + ************************************************************ + * Pertinent Information Box + * These floating boxes appear on the detail pages, + * providing the most pertinent / important information + * for the given view. + */ + +div.infobox { float: right; + width: 39%; + margin-top: 1.5em; + } + +div.summary { color: #993; + font-family:'Gill Sans','lucida grande',helvetica, arial, sans-serif; + font-size: 125%; + text-align: right; + margin-bottom: 0.2em; + } /************************************************************ @@ -101,7 +139,7 @@ a { font-weight: bold; } a:hover { - color: #f00; + color: #00f; text-decoration:none; } a img { @@ -113,14 +151,13 @@ h1, h2, h3, h4 { } h1 { - background:#fff; color: #003d4c; font-size: 100%; margin: 0.1em 0; } h2 { - background:#fff; - color: #e32; +/* color: #e32; */ + color: #993; font-family:'Gill Sans','lucida grande',helvetica, arial, sans-serif; font-size: 190%; margin-bottom: 0.3em; @@ -128,8 +165,7 @@ h2 { h3 { color: #993; font-family:'Gill Sans','lucida grande',helvetica, arial, sans-serif; - font-size: 165%; - padding-top: 1.5em; +/* font-size: 165%; */ } h4 { color: #993; From 70812e0a0ce21b598adacdbe68d23c520db9e96d Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 30 May 2009 20:51:07 +0000 Subject: [PATCH 043/717] Getting sidemenu ready for more dynamic actions based on context. Couple minor tweaks to layout. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@44 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/contacts_controller.php | 22 +++++++++++++--------- site/controllers/units_controller.php | 23 ++++++++++++++--------- site/views/contacts/view.ctp | 2 +- site/views/units/view.ctp | 2 +- site/webroot/css/layout.css | 1 + 5 files changed, 30 insertions(+), 20 deletions(-) diff --git a/site/controllers/contacts_controller.php b/site/controllers/contacts_controller.php index a721839..acf3eb0 100644 --- a/site/controllers/contacts_controller.php +++ b/site/controllers/contacts_controller.php @@ -7,6 +7,13 @@ class ContactsController extends AppController { 'order' => array('Contact.last_name' => 'ASC', 'Contact.first_name' => 'ASC')); + var $sidemenu_links = + array(array('name' => 'Tenants', 'header' => true), + array('name' => 'Current', 'url' => array('controller' => 'contacts', 'action' => 'current')), + array('name' => 'Past', 'url' => array('controller' => 'contacts', 'action' => 'past')), + array('name' => 'All Tenants', 'url' => array('controller' => 'contacts', 'action' => 'tenants')), + array('name' => 'All Contacts', 'url' => array('controller' => 'contacts', 'action' => 'all')), + ); /************************************************************************** ************************************************************************** @@ -15,15 +22,7 @@ class ContactsController extends AppController { * - Generates controller specific links for the side menu */ function sideMenuLinks() { - $menu = parent::sideMenuLinks(); - //$menu[] = array('hr' => true); - $menu[] = array('name' => 'Tenants', 'header' => true); - $menu[] = array('name' => 'Current', 'url' => array('controller' => 'contacts', 'action' => 'current')); - $menu[] = array('name' => 'Past', 'url' => array('controller' => 'contacts', 'action' => 'past')); - $menu[] = array('name' => 'All Tenants', 'url' => array('controller' => 'contacts', 'action' => 'tenants')); - $menu[] = array('name' => 'All Contacts', 'url' => array('controller' => 'contacts', 'action' => 'all')); - - return $menu; + return array_merge(parent::sideMenuLinks(), $this->sidemenu_links); } @@ -159,6 +158,11 @@ class ContactsController extends AppController { } } + $this->sidemenu_links[] = + array('name' => 'Operations', 'header' => true); + $this->sidemenu_links[] = + array('name' => 'Move-Out', 'url' => array('controller' => 'units', 'action' => 'move-out')); + $this->set(compact('contact', 'title', 'mytstval', 'outstanding_balance', 'outstanding_deposit')); diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index a184efa..43a15ca 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -6,6 +6,14 @@ class UnitsController extends AppController { var $paginate = array('limit' => 100, 'order' => array('Unit.sort_order' => 'ASC')); + 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')), + ); + /************************************************************************** ************************************************************************** @@ -14,15 +22,7 @@ class UnitsController extends AppController { * - Generates controller specific links for the side menu */ function sideMenuLinks() { - $menu = parent::sideMenuLinks(); - //$menu[] = array('hr' => true); - $menu[] = array('name' => 'Units', 'header' => true); - $menu[] = array('name' => 'Occupied', 'url' => array('controller' => 'units', 'action' => 'occupied')); - $menu[] = array('name' => 'Vacant', 'url' => array('controller' => 'units', 'action' => 'vacant')); - $menu[] = array('name' => 'Unavailable', 'url' => array('controller' => 'units', 'action' => 'unavailable')); - $menu[] = array('name' => 'All', 'url' => array('controller' => 'units', 'action' => 'all')); - - return $menu; + return array_merge(parent::sideMenuLinks(), $this->sidemenu_links); } @@ -142,6 +142,11 @@ class UnitsController extends AppController { } } + $this->sidemenu_links[] = + array('name' => 'Operations', 'header' => true); + $this->sidemenu_links[] = + array('name' => 'Move-Out', 'url' => array('controller' => 'units', 'action' => 'move-out')); + $this->set(compact('unit', 'title', 'outstanding_balance', 'outstanding_deposit')); diff --git a/site/views/contacts/view.ctp b/site/views/contacts/view.ctp index 9209167..facd250 100644 --- a/site/views/contacts/view.ctp +++ b/site/views/contacts/view.ctp @@ -189,7 +189,7 @@ foreach($contact['Lease'] AS $lease) { echo $this->element('table', array('class' => 'item ledger list', - 'caption' => 'Lease #'.$lease['number'].' ('.$lease['Unit']['name'].')', + 'caption' => 'Lease #'.$lease['number'].' (Unit: '.$lease['Unit']['name'].')', 'suppress_alternate_rows' => true, 'headers' => $headers, 'rows' => $rows, diff --git a/site/views/units/view.ctp b/site/views/units/view.ctp index 59b0a1d..07c9cf8 100644 --- a/site/views/units/view.ctp +++ b/site/views/units/view.ctp @@ -107,7 +107,7 @@ foreach($unit['Lease'] AS $lease) { echo $this->element('table', array('class' => 'item ledger list', - 'caption' => 'Lease #'.$lease['number'].' ('.$lease['Contact'][0]['display_name'].')', + 'caption' => 'Lease #'.$lease['number'].' (Tenant: '.$lease['Contact'][0]['display_name'].')', 'suppress_alternate_rows' => true, 'headers' => $headers, 'rows' => $rows, diff --git a/site/webroot/css/layout.css b/site/webroot/css/layout.css index 7574d43..1c6e5ab 100644 --- a/site/webroot/css/layout.css +++ b/site/webroot/css/layout.css @@ -111,6 +111,7 @@ table.list.ledger td.comment { width : 99%; } div.infobox { float: right; width: 39%; margin-top: 1.5em; + margin-right: 0.5em; } div.summary { color: #993; From 387c1ae87bf4a22654684a15eb972872fce8f09e Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 31 May 2009 17:02:41 +0000 Subject: [PATCH 044/717] Testing out a possible model behavior called linkable. I may not go this route, but I'll just delete it if not. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@45 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/behaviors/linkable.php | 152 +++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 site/models/behaviors/linkable.php diff --git a/site/models/behaviors/linkable.php b/site/models/behaviors/linkable.php new file mode 100644 index 0000000..32b28bb --- /dev/null +++ b/site/models/behaviors/linkable.php @@ -0,0 +1,152 @@ +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 + * + * Licensed under The MIT License + * Redistributions of files must retain the above copyright notice. + * + * @version 1.0; + */ + +class LinkableBehavior extends ModelBehavior { + + protected $_key = 'link'; + + protected $_options = array( + 'type' => true, 'table' => true, 'alias' => true, + 'conditions' => true, 'fields' => true, 'reference' => true, + 'class' => true, 'defaults' => true + ); + + protected $_defaults = array('type' => 'LEFT'); + + public function beforeFind(&$Model, $query) { + if (isset($query[$this->_key])) { + $optionsDefaults = $this->_defaults + array('reference' => $Model->alias, $this->_key => array()); + $optionsKeys = $this->_options + array($this->_key => true); + $query = am(array('joins' => array()), $query, array('recursive' => -1)); + $iterators[] = $query[$this->_key]; + $cont = 0; + do { + $iterator = $iterators[$cont]; + $defaults = $optionsDefaults; + if (isset($iterator['defaults'])) { + $defaults = array_merge($defaults, $iterator['defaults']); + unset($iterator['defaults']); + } + $iterations = Set::normalize($iterator); + foreach ($iterations as $alias => $options) { + if (is_null($options)) { + $options = array(); + } + $options = am($defaults, compact('alias'), $options); + if (empty($options['alias'])) { + throw new InvalidArgumentException(sprintf('%s::%s must receive aliased links', get_class($this), __FUNCTION__)); + } + + if (empty($options['table']) && empty($options['class'])) { + $options['class'] = $options['alias']; + } elseif (!empty($options['table']) && empty($options['class'])) { + $options['class'] = Inflector::classify($options['table']); + } + $_Model =& ClassRegistry::init($options['class']); // the incoming model to be linked in query + $Reference =& ClassRegistry::init($options['reference']); // the already in query model that links to $_Model + $db =& $_Model->getDataSource(); + $associations = $_Model->getAssociated(); + if (isset($associations[$Reference->alias])) { + $type = $associations[$Reference->alias]; + $association = $_Model->{$type}[$Reference->alias]; + } else { + $_Model->bind($Reference->alias); + $type = 'belongsTo'; + $association = $_Model->{$type}[$Reference->alias]; + $_Model->unbindModel(array('belongsTo' => array($Reference->alias))); + } + + if (empty($options['conditions'])) { + if ($type === 'belongsTo') { + $modelKey = $_Model->escapeField($association['foreignKey']); + $referenceKey = $Reference->escapeField($Reference->primaryKey); + $options['conditions'] = "{$referenceKey} = {$modelKey}"; + } elseif ($type === 'hasAndBelongsToMany') { + if (isset($association['with'])) { + $Link =& $_Model->{$association['with']}; + if (isset($Link->belongsTo[$_Model->alias])) { + $modelLink = $Link->escapeField($Link->belongsTo[$_Model->alias]['foreignKey']); + } + if (isset($Link->belongsTo[$Reference->alias])) { + $referenceLink = $Link->escapeField($Link->belongsTo[$Reference->alias]['foreignKey']); + } + } else { + $Link =& $_Model->{Inflector::classify($association['joinTable'])}; + } + if (empty($modelLink)) { + $modelLink = $Link->escapeField(Inflector::underscore($_Model->alias) . '_id'); + } + if (empty($referenceLink)) { + $referenceLink = $Link->escapeField(Inflector::underscore($Reference->alias) . '_id'); + } + $referenceKey = $Reference->escapeField(); + $query['joins'][] = array( + 'alias' => $Link->alias, + 'table' => $Link->getDataSource()->fullTableName($Link), + 'conditions' => "{$referenceLink} = {$referenceKey}", + 'type' => 'LEFT' + ); + $modelKey = $_Model->escapeField(); + $options['conditions'] = "{$modelLink} = {$modelKey}"; + } else { + $referenceKey = $Reference->escapeField($association['foreignKey']); + $modelKey = $_Model->escapeField($_Model->primaryKey); + $options['conditions'] = "{$modelKey} = {$referenceKey}"; + } + } + if (empty($options['table'])) { + $options['table'] = $db->fullTableName($_Model, true); + } + if (!empty($options['fields'])) { + if ($options['fields'] === true && !empty($association['fields'])) { + $options['fields'] = $db->fields($_Model, null, $association['fields']); + } elseif ($options['fields'] === true) { + $options['fields'] = $db->fields($_Model); + } else { + $options['fields'] = $db->fields($_Model, null, $options['fields']); + } + $query['fields'] = array_merge($query['fields'], $options['fields']); + } + + $options[$this->_key] = am($options[$this->_key], array_diff_key($options, $optionsKeys)); + $options = array_intersect_key($options, $optionsKeys); + if (!empty($options[$this->_key])) { + $iterators[] = $options[$this->_key] + array('defaults' => array_merge($defaults, array('reference' => $options['class']))); + } + $query['joins'][] = array_intersect_key($options, array('type' => true, 'alias' => true, 'table' => true, 'conditions' => true)); + } + ++$cont; + $notDone = isset($iterators[$cont]); + } while ($notDone); + } + return $query; + } +} \ No newline at end of file From 6bf06a3a3ce48a5d9620236b594e8749ff8778a9 Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 31 May 2009 18:27:21 +0000 Subject: [PATCH 045/717] Changed how fields are handled, so that they are all included by default and the user is not forced to specify them. This works with paginate, but the additional fields are requested in the count query. Would like to resolve this, but it doesn't seem to be confusing paginate. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@46 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/behaviors/linkable.php | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/site/models/behaviors/linkable.php b/site/models/behaviors/linkable.php index 32b28bb..428fc9b 100644 --- a/site/models/behaviors/linkable.php +++ b/site/models/behaviors/linkable.php @@ -42,9 +42,16 @@ class LinkableBehavior extends ModelBehavior { protected $_defaults = array('type' => 'LEFT'); public function beforeFind(&$Model, $query) { + //pr("Linkable::beforeFind() begin"); pr($query); if (isset($query[$this->_key])) { $optionsDefaults = $this->_defaults + array('reference' => $Model->alias, $this->_key => array()); $optionsKeys = $this->_options + array($this->_key => true); + if (!isset($query['fields']) || $query['fields'] === true) { + //$query['fields'] = array_keys($Model->_schema); + $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)); $iterators[] = $query[$this->_key]; $cont = 0; @@ -125,16 +132,16 @@ class LinkableBehavior extends ModelBehavior { if (empty($options['table'])) { $options['table'] = $db->fullTableName($_Model, true); } - if (!empty($options['fields'])) { - if ($options['fields'] === true && !empty($association['fields'])) { - $options['fields'] = $db->fields($_Model, null, $association['fields']); - } elseif ($options['fields'] === true) { - $options['fields'] = $db->fields($_Model); - } else { - $options['fields'] = $db->fields($_Model, null, $options['fields']); - } - $query['fields'] = array_merge($query['fields'], $options['fields']); - } + + if (!isset($options['fields']) || !is_array($options['fields'])) + $options['fields'] = $db->fields($_Model); + elseif (!empty($options['fields'])) + $options['fields'] = $db->fields($_Model, null, $options['fields']); + + $query['fields'] = array_merge($query['fields'], $options['fields'], + (empty($association['fields']) + ? array() : $db->fields($_Model, null, $association['fields']))); + $options[$this->_key] = am($options[$this->_key], array_diff_key($options, $optionsKeys)); $options = array_intersect_key($options, $optionsKeys); @@ -147,6 +154,7 @@ class LinkableBehavior extends ModelBehavior { $notDone = isset($iterators[$cont]); } while ($notDone); } + //pr("Linkable::beforeFind() end"); pr($query); return $query; } } \ No newline at end of file From 52528f1c0ea129ef803bb786dd153a9d2065782b Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 1 Jun 2009 02:11:14 +0000 Subject: [PATCH 046/717] Minor tweak to the table headers git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@47 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/webroot/css/layout.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/site/webroot/css/layout.css b/site/webroot/css/layout.css index 1c6e5ab..b814585 100644 --- a/site/webroot/css/layout.css +++ b/site/webroot/css/layout.css @@ -46,9 +46,10 @@ table.item { border:1px solid #ccc; border-bottom:2px solid #ccc; } -table.item th { background: #f2f2f2; +table.list th { background: #dcdcdc; border-top: 1px solid #fff; border-left: 1px solid #fff; + border-bottom: 2px solid #aaa; border-right: 1px solid #ccc; text-align: center; } From 9db4dd737d167c27f8c091914b5231dc1dc7475e Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 1 Jun 2009 02:11:48 +0000 Subject: [PATCH 047/717] Added some of the original formatting back into the sql log table. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@48 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/webroot/css/cake.generic.css | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/site/webroot/css/cake.generic.css b/site/webroot/css/cake.generic.css index a6d84f3..6a5579f 100644 --- a/site/webroot/css/cake.generic.css +++ b/site/webroot/css/cake.generic.css @@ -65,13 +65,31 @@ } -.cake-sql-log table { +table.cake-sql-log { background: #f4f4f4; + border:1px solid #ccc; + border-right:0; + clear: both; + color: #333; + margin-bottom: 10px; + width: 100%; } .cake-sql-log td { + background: #fff; + border-right: 1px solid #ccc; + border-bottom: 1px solid #ccc; + vertical-align: top; padding: 4px 8px; text-align: left; } +.cake-sql-log th { + background: #f2f2f2; + border:1px solid #bbb; + border-top: 1px solid #fff; + border-left: 1px solid #fff; + text-align: center; +} + /* Paging */ div.paging { From 23a81ae9247aa1d9c6c75dc734516bb9bd41f66c Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 1 Jun 2009 02:36:26 +0000 Subject: [PATCH 048/717] I've been around and around with paging. I started using the Containable behavior, which is fantastic for something like 'view', but is highly problematic for listings, especially with pagination. I discovered the Linkable behavior, and it's much more database efficient, and I actually can get it to work with pagination (except when using GROUP BY). I did have to tweak it though, to handle some of the more complex queries that I intend. This checkin includes a bunch of garbage, but given the amount of time I've spent on this crap, I'm afraid to lose anything that might later be useful information. I'll clean up on the next checkin. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@49 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_model.php | 61 ++++++++ site/controllers/contacts_controller.php | 188 ++++++++++++++++++++--- site/controllers/units_controller.php | 88 ++++++++++- site/models/behaviors/linkable.php | 125 ++++++++++++--- site/models/contact.php | 13 -- 5 files changed, 419 insertions(+), 56 deletions(-) diff --git a/site/app_model.php b/site/app_model.php index a4e1079..b4cc264 100644 --- a/site/app_model.php +++ b/site/app_model.php @@ -38,6 +38,8 @@ */ class AppModel extends Model { + //var $actsAs = array('Containable'); + var $actsAs = array('Linkable'); /** * Get Enum Values @@ -75,4 +77,63 @@ class AppModel extends Model { )); } //end getEnumValues + + // Overriding pagination, since the stupid count mechanism blows. + // This is also a crappy solution, especially if the query returns + // a really large number of rows. However, trying to untagle this + // without changing a bunch of core code is near impossible. + + var $paginate_rows_save; + function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null) { +/* pr("paginate"); */ +/* pr(array_merge(compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive'))); */ + if ($page > 1 && isset($limit)) + $offset = ($page - 1) * $limit; + else + $offset = 0; + return array_slice($this->paginate_rows_save, $offset, $limit); + } + function paginateCount($conditions = null, $recursive = null, $extra = null) { +/* pr("paginateCount"); */ + + if (!isset($recursive)) + $recursive = $this->recursive; + $parameters = array_merge(compact('conditions', 'recursive'), $extra); + $results = $this->find('all', $parameters); + + $this->paginate_rows_save = $results; + return count($this->paginate_rows_save); + } + +// Code as found in the controller +/* function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null) { */ +/* pr("paginate"); */ +/* pr(array_merge(compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive'))); */ + +/* $parameters = compact('conditions', 'fields', 'order', 'limit', 'page'); */ +/* if ($recursive != $this->recursive) { */ +/* $parameters['recursive'] = $recursive; */ +/* } */ + +/* $results = $this->find($type, array_merge($parameters, $extra)); */ +/* pr("paginate end"); */ +/* pr($results); */ +/* } */ + +/* function paginateCount($conditions = null, $recursive = null, $extra = null) { */ +/* pr("paginateCount"); */ +/* pr(array_merge(compact('conditions', 'recursive'), $extra)); */ + +/* $parameters = compact('conditions'); */ +/* if ($recursive != $this->recursive) { */ +/* $parameters['recursive'] = $recursive; */ +/* } */ +/* $count = $this->find('count', array_merge($parameters, $extra)); */ + +/* pr("paginateCount end: $count"); */ +/* return $count; */ +/* } */ + + + } diff --git a/site/controllers/contacts_controller.php b/site/controllers/contacts_controller.php index acf3eb0..2ef5300 100644 --- a/site/controllers/contacts_controller.php +++ b/site/controllers/contacts_controller.php @@ -89,18 +89,124 @@ class ContactsController extends AppController { */ function past() { - $this->Contact->recursive = 0; - $this->Contact->bindModel(array('hasOne' => array('ContactsLease', - 'Lease' => array( - 'foreignKey' => false, - 'conditions' => array('Lease.id = ContactsLease.lease_id') - ))), - false); - +/* $this->Contact->contain */ +/* (array(// Models */ +/* 'ContactPhone', */ +/* 'ContactEmail', */ +/* 'ContactAddress', */ +/* 'Lease' => */ +/* array('order' => 'movein_date', */ +/* 'conditions' => array('Lease.close_date IS NOT NULL', */ +/* 'ContactsLease.type !=' => 'ALTERNATE'), */ +/* // Models */ +/* 'Unit' => */ +/* array('order' => array('sort_order'), */ +/* 'fields' => array('id', 'name'), */ +/* ), */ +/* /\* 'Charge' => *\/ */ +/* /\* array('order' => array('charge_date'), *\/ */ +/* /\* // Models *\/ */ +/* /\* 'ChargeType', *\/ */ +/* /\* 'Receipt', *\/ */ +/* /\* ) *\/ */ +/* ) */ +/* ) */ +/* ); */ + +/* $contact = $this->Contact->find('all', */ +/* array('order' => 'id DESC', */ +/* 'conditions' => array('Lease.id IS NOT NULL'), */ +/* 'contain' => */ +/* array( */ +/* // Models */ +/* 'Lease' => */ +/* array('order' => 'movein_date', */ +/* 'conditions' => array('Lease.lease_date IS NOT NULL', */ +/* 'Lease.close_date IS NOT NULL', */ +/* 'ContactsLease.type !=' => 'ALTERNATE'), */ +/* ) */ +/* ) */ +/* )); */ + +/* $contacts = $this->Contact->find */ +/* ('all', array */ +/* ('contain' => array */ +/* ('Lease' => array */ +/* ('conditions' => array('lease_date >' => "2009-04-01"), */ +/* ) */ +/* ), */ +/* 'order' => 'id DESC', */ +/* 'conditions' => array('Lease.id IS NOT NULL') */ +/* )); */ + +/* $contacts = $this->Contact->find('all', */ +/* array('order' => 'id DESC', */ +/* 'contain' => 'Lease.lease_date > "2009-04-01"' */ +/* )); */ +/* pr($contacts); */ +/* $this->set('contacts', $contacts); */ + +/* $this->Contact->Behaviors->attach('Containable'); */ +/* $this->Contact->contain */ +/* (array(// Models */ +/* 'ContactPhone', */ +/* 'ContactEmail', */ +/* 'ContactAddress', */ +/* 'Lease' => */ +/* array('order' => 'movein_date', */ +/* 'conditions' => array('Lease.close_date IS NOT NULL', */ +/* 'ContactsLease.type !=' => 'ALTERNATE'), */ +/* // Models */ +/* 'Unit' => */ +/* array('order' => array('sort_order'), */ +/* 'fields' => array('id', 'name'), */ +/* ), */ +/* /\* 'Charge' => *\/ */ +/* /\* array('order' => array('charge_date'), *\/ */ +/* /\* // Models *\/ */ +/* /\* 'ChargeType', *\/ */ +/* /\* 'Receipt', *\/ */ +/* /\* ) *\/ */ +/* ) */ +/* ) */ +/* ); */ + + + $this->paginate = + array('link' => + array(// Models + 'ContactPhone' => array('fields' => array('phone'), + //'type' => 'INNER' + ), + //'ContactEmail', + //'ContactAddress', + 'Lease' => + array('fields' => array(), + 'type' => 'LEFT', + // Models + 'Unit' => array('fields' => array('name'), + //'type' => 'INNER', + ), + ) + ), + 'order' => 'Contact.last_name, Contact.first_name', + 'conditions' => array(//'ContactsLease.type !=' => 'ALTERNATE', + //'Lease.id IS NOT NULL', + //'Lease.lease_date IS NOT NULL', + //'Lease.close_date IS NOT NULL' + ), + 'group' => 'Contact.id', + 'fields' => array('id', 'first_name', 'last_name', 'company_name', 'comment'), + ); + + $title = 'Past Tenants'; $this->set('title', $title); $this->set('heading', $title); - $this->set('contacts', $this->paginate(array('Lease.close_date IS NOT NULL', - 'ContactsLease.type != "ALTERNATE"'))); + $this->set('contacts', $this->paginate()); + //$this->set('contacts', $this->Contact->find('all', array('order' => 'id DESC'))); + //$this->set('contacts', $this->Contact->find('all')); +/* $this->set('contacts', $this->Contact->find('all')); */ +/* $this->set('contacts', $this->Contact->find('all')); */ $this->render('index'); } @@ -131,15 +237,61 @@ class ContactsController extends AppController { function view($id = null) { if (!$id) { $this->Session->setFlash(__('Invalid Item.', true)); - $this->redirect(array('action'=>'')); + $this->redirect(array('action'=>'index')); } - $this->Contact->recursive = 4; - $this->Contact->Lease->LeaseType->unbindModel(array('hasMany' => array('Lease'))); - $this->Contact->Lease->Charge->unbindModel(array('belongsTo' => array('Lease'))); - $this->Contact->Lease->Charge->ChargeType->unbindModel(array('hasMany' => array('Charge'))); - $this->Contact->Lease->Charge->Receipt->unbindModel(array('hasMany' => array('ChargesReceipt'))); - $contact = $this->Contact->read(null, $id); + //pr($this->Contact); + //pr($this->Contact->ContactPhone); + + $this->Contact->Behaviors->attach('Containable'); + $this->Contact->contain + (array(// Models + 'ContactPhone', + 'ContactEmail', + 'ContactAddress', + 'Lease' => + array('order' => 'movein_date', + 'conditions' => array('Lease.lease_date IS NOT NULL', + 'ContactsLease.type !=' => 'ALTERNATE'), + // Models + 'Unit' => + array('order' => array('sort_order'), + 'fields' => array('id', 'name'), + ), + 'Charge' => + array('order' => array('charge_date'), + // Models + 'ChargeType', + 'Receipt', + ) + ) + ) + ); + $contact = $this->Contact->read(null, $id); + +/* $contact = $this->Contact->find */ +/* ('first', */ +/* array('link' => array */ +/* (// Models */ +/* 'ContactPhone', */ +/* 'ContactEmail', */ +/* 'ContactAddress', */ +/* 'Lease' => */ +/* array(// Models */ +/* 'Unit' => array('fields' => array('id', 'name')), */ +/* 'Charge' => array(// Models */ +/* 'ChargeType', */ +/* 'Receipt', */ +/* ) */ +/* ) */ +/* ), */ +/* 'order' => 'Lease.movein_date, Unit.sort_order, Charge.charge_date', */ +/* 'conditions' => array('Lease.lease_date IS NOT NULL', */ +/* 'ContactsLease.type !=' => 'ALTERNATE'), */ +/* )); */ + +/* pr($contact); */ + $title = $contact['Contact']['display_name']; $outstanding_deposit = 0; @@ -163,7 +315,7 @@ class ContactsController extends AppController { $this->sidemenu_links[] = array('name' => 'Move-Out', 'url' => array('controller' => 'units', 'action' => 'move-out')); - $this->set(compact('contact', 'title', 'mytstval', + $this->set(compact('contact', 'title', 'outstanding_balance', 'outstanding_deposit')); } diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index 43a15ca..60a6b20 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -34,7 +34,93 @@ class UnitsController extends AppController { */ function index() { - $this->all(); + //$this->Unit->recursive = 0; + + // $units = $this->Unit->find + // ('all', + $this->paginate = + array( + 'link' => array + ('UnitSize' //=> array('fields' => array('name')), + //=> array('fields' => true), + => array('fields' => array('name')), + //=> array('fields' => array()), + //=> array(), + + //'Lease', + ), + 'conditions' => array('UnitSize.name =' => "10x30", + 'UnitSize.id IS NOT NULL'), + //'fields' => true + 'fields' => array('id', 'name', 'status', 'comment') +// ) + ); + + $units = $this->paginate(); + + +/* Array */ +/* ( */ +/* [joins] => Array */ +/* ( */ +/* [0] => Array */ +/* ( */ +/* [type] => LEFT */ +/* [alias] => UnitSize */ +/* [conditions] => `UnitSize`.`id` = `Unit`.`unit_size_id` */ +/* [table] => `pmgr_unit_sizes` */ +/* ) */ + +/* ) */ + +/* [conditions] => Array */ +/* ( */ +/* [UnitSize.name =] => 10x30 */ +/* [0] => UnitSize.id IS NOT NULL */ +/* ) */ + +/* [fields] => Array */ +/* ( */ +/* [0] => id */ +/* [1] => name */ +/* [2] => status */ +/* [3] => comment */ +/* [4] => `UnitSize`.`name` */ +/* ) */ + +/* [limit] => */ +/* [offset] => */ +/* [order] => Array */ +/* ( */ +/* [0] => */ +/* ) */ + +/* [page] => 1 */ +/* [group] => */ +/* [callbacks] => 1 */ +/* [link] => Array */ +/* ( */ +/* [UnitSize] => Array */ +/* ( */ +/* [fields] => Array */ +/* ( */ +/* [0] => name */ +/* ) */ + +/* ) */ + +/* ) */ + +/* [recursive] => -1 */ +/* ) */ + + + pr($units); + $title = 'Index Units'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('units', $units); + + //$this->all(); } diff --git a/site/models/behaviors/linkable.php b/site/models/behaviors/linkable.php index 428fc9b..8b6c306 100644 --- a/site/models/behaviors/linkable.php +++ b/site/models/behaviors/linkable.php @@ -34,7 +34,7 @@ class LinkableBehavior extends ModelBehavior { protected $_key = 'link'; protected $_options = array( - 'type' => true, 'table' => true, 'alias' => true, + 'type' => true, 'table' => true, 'alias' => true, 'joins' => true, 'conditions' => true, 'fields' => true, 'reference' => true, 'class' => true, 'defaults' => true ); @@ -42,7 +42,7 @@ class LinkableBehavior extends ModelBehavior { protected $_defaults = array('type' => 'LEFT'); public function beforeFind(&$Model, $query) { - //pr("Linkable::beforeFind() begin"); pr($query); +/* pr("Linkable::beforeFind() begin"); pr($query); */ if (isset($query[$this->_key])) { $optionsDefaults = $this->_defaults + array('reference' => $Model->alias, $this->_key => array()); $optionsKeys = $this->_options + array($this->_key => true); @@ -79,8 +79,12 @@ class LinkableBehavior extends ModelBehavior { } $_Model =& ClassRegistry::init($options['class']); // the incoming model to be linked in query $Reference =& ClassRegistry::init($options['reference']); // the already in query model that links to $_Model +/* pr("_Model: $options[class] : $_Model->name ($_Model->alias)"); */ +/* pr("Reference: $options[reference] : $Reference->name ($Reference->alias)"); */ $db =& $_Model->getDataSource(); $associations = $_Model->getAssociated(); +/* pr("Assocations of $_Model->name"); */ +/* pr($associations); */ if (isset($associations[$Reference->alias])) { $type = $associations[$Reference->alias]; $association = $_Model->{$type}[$Reference->alias]; @@ -97,32 +101,94 @@ class LinkableBehavior extends ModelBehavior { $referenceKey = $Reference->escapeField($Reference->primaryKey); $options['conditions'] = "{$referenceKey} = {$modelKey}"; } elseif ($type === 'hasAndBelongsToMany') { - if (isset($association['with'])) { +/* pr("Association"); */ +/* pr($association); */ + if (isset($association['with'])) $Link =& $_Model->{$association['with']}; - if (isset($Link->belongsTo[$_Model->alias])) { - $modelLink = $Link->escapeField($Link->belongsTo[$_Model->alias]['foreignKey']); - } - if (isset($Link->belongsTo[$Reference->alias])) { - $referenceLink = $Link->escapeField($Link->belongsTo[$Reference->alias]['foreignKey']); - } - } else { + else $Link =& $_Model->{Inflector::classify($association['joinTable'])}; - } - if (empty($modelLink)) { + + // 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['foreignKey']); + $referenceLink = $Link->escapeField($association['associationForeignKey']); + + // 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']); + if (empty($referenceLink) && isset($Link->belongsTo[$Reference->alias])) + $referenceLink = $Link->escapeField($Link->belongsTo[$Reference->alias]['foreignKey']); + + // 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'); - } - if (empty($referenceLink)) { + if (empty($referenceLink)) $referenceLink = $Link->escapeField(Inflector::underscore($Reference->alias) . '_id'); - } + + // Get the primary key from the tables we're joining. $referenceKey = $Reference->escapeField(); - $query['joins'][] = array( - 'alias' => $Link->alias, - 'table' => $Link->getDataSource()->fullTableName($Link), - 'conditions' => "{$referenceLink} = {$referenceKey}", - 'type' => 'LEFT' - ); $modelKey = $_Model->escapeField(); - $options['conditions'] = "{$modelLink} = {$modelKey}"; + +/* pr("bf pre options:"); */ +/* pr($options); */ + +/* [joins] => Array */ +/* ( */ +/* [0] => Array */ +/* ( */ +/* [type] => LEFT */ +/* [table] => `pmgr_contacts_leases` */ +/* [alias] => ContactsLease */ +/* [joins] => Array */ +/* ( */ +/* [0] => Array */ +/* ( */ +/* [type] => INNER */ +/* [table] => `pmgr_leases` */ +/* [alias] => Lease */ +/* [conditions] => `Lease`.`id` = `ContactsLease`.`lease_id` */ +/* ) */ +/* ) */ +/* [conditions] => `ContactsLease`.`contact_id` = `Contact`.`id` */ +/* ) */ +/* ) */ +/* LEFT JOIN (`pmgr_contacts_leases` AS `ContactsLease` */ +/* INNER JOIN `pmgr_leases` AS `Lease` */ +/* ON (`Lease`.`id` = `ContactsLease`.`lease_id`) */ +/* ) ON (`ContactsLease`.`contact_id` = `Contact`.`id`) */ + + + // 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' => $options['alias'], + 'conditions' => "{$modelKey} = {$modelLink}", + 'table' => $db->fullTableName($_Model, true)); + + // The user may have specified conditions directly in the model + // for this join. Make sure to adhere to those conditions. + if (isset($association['conditions']) && is_array($association['conditions'])) + $options['conditions'] = $association['conditions']; + elseif (!empty($association['conditions'])) + $options['conditions'] = array($association['conditions']); + + // Now for the top level join. This will be added into the list + // of joins down below, outside of the HABTM specific code. + $options['alias'] = $Link->alias; + $options['table'] = $Link->getDataSource()->fullTableName($Link); + $options['conditions'][] = "{$referenceLink} = {$referenceKey}"; + +/* pr("bf post options:"); */ +/* pr($options); */ } else { $referenceKey = $Reference->escapeField($association['foreignKey']); $modelKey = $_Model->escapeField($_Model->primaryKey); @@ -148,13 +214,24 @@ class LinkableBehavior extends ModelBehavior { if (!empty($options[$this->_key])) { $iterators[] = $options[$this->_key] + array('defaults' => array_merge($defaults, array('reference' => $options['class']))); } - $query['joins'][] = array_intersect_key($options, array('type' => true, 'alias' => true, 'table' => true, 'conditions' => true)); +/* pr("bf pre query:"); */ +/* pr($query); */ +/* $aik = array('type' => true, 'alias' => true, 'table' => true, 'joins' => true, 'conditions' => true); */ +/* pr("aik"); */ +/* pr($aik); */ +/* $ojoin = array_intersect_key($options, $aik); */ +/* pr("ojoin"); */ +/* pr($ojoin); */ +/* $query['joins'][] = $ojoin; */ +/* pr("bf post query:"); */ +/* pr($query); */ + $query['joins'][] = array_intersect_key($options, array('type' => true, 'alias' => true, 'table' => true, 'joins' => true, 'conditions' => true)); } ++$cont; $notDone = isset($iterators[$cont]); } while ($notDone); } - //pr("Linkable::beforeFind() end"); pr($query); +/* pr("Linkable::beforeFind() end"); pr($query); */ return $query; } } \ No newline at end of file diff --git a/site/models/contact.php b/site/models/contact.php index 96d12bb..5aab7f3 100644 --- a/site/models/contact.php +++ b/site/models/contact.php @@ -72,18 +72,5 @@ class Contact extends AppModel { ), ); - // Overriding pagination, since the controller using HABTM joins that - // result in duplicate rows. This may not be the best way to handle - // things (especially if the query return a really large number of rows, - // but it does seem to work. - function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null) { - $conditions[] ="1=1 GROUP BY Contact.id"; - return $this->findAll($conditions, $fields, $order, $limit, $page, $recursive); - } - function paginateCount($conditions = null, $recursive = 0) { - $rows = $this->paginate($conditions, null, null, null, null, $recursive); - return count($rows); - } - } ?> \ No newline at end of file From 903209a47e0b3e625813f9621b318e7d88a7ea84 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 1 Jun 2009 04:27:34 +0000 Subject: [PATCH 049/717] Performed cleanup, and started the thought process of figuring out how to use one link table multiple times in the same query. My changes worked actually, but I want to wait on this to see if I can figure out if there is already a core solution (since it seems likely that things behaving like a tree would have one table used multiple times in the same query... although they probably get around that by running 100 different queries come to think of it). git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@50 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/behaviors/linkable.php | 64 +++++------------------------- 1 file changed, 10 insertions(+), 54 deletions(-) diff --git a/site/models/behaviors/linkable.php b/site/models/behaviors/linkable.php index 8b6c306..f38c7da 100644 --- a/site/models/behaviors/linkable.php +++ b/site/models/behaviors/linkable.php @@ -83,8 +83,6 @@ class LinkableBehavior extends ModelBehavior { /* pr("Reference: $options[reference] : $Reference->name ($Reference->alias)"); */ $db =& $_Model->getDataSource(); $associations = $_Model->getAssociated(); -/* pr("Assocations of $_Model->name"); */ -/* pr($associations); */ if (isset($associations[$Reference->alias])) { $type = $associations[$Reference->alias]; $association = $_Model->{$type}[$Reference->alias]; @@ -101,67 +99,39 @@ class LinkableBehavior extends ModelBehavior { $referenceKey = $Reference->escapeField($Reference->primaryKey); $options['conditions'] = "{$referenceKey} = {$modelKey}"; } elseif ($type === 'hasAndBelongsToMany') { -/* pr("Association"); */ -/* pr($association); */ if (isset($association['with'])) $Link =& $_Model->{$association['with']}; else $Link =& $_Model->{Inflector::classify($association['joinTable'])}; + $linkAlias = $Link->alias; + //$linkAlias = $Link->alias . $options['alias']; + // 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['foreignKey']); - $referenceLink = $Link->escapeField($association['associationForeignKey']); + $modelLink = $Link->escapeField($association['foreignKey'], $linkAlias); + $referenceLink = $Link->escapeField($association['associationForeignKey'], $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']); + $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']); + $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'); + $modelLink = $Link->escapeField(Inflector::underscore($_Model->alias) . '_id', $linkAlias); if (empty($referenceLink)) - $referenceLink = $Link->escapeField(Inflector::underscore($Reference->alias) . '_id'); + $referenceLink = $Link->escapeField(Inflector::underscore($Reference->alias) . '_id', $linkAlias); // Get the primary key from the tables we're joining. $referenceKey = $Reference->escapeField(); $modelKey = $_Model->escapeField(); -/* pr("bf pre options:"); */ -/* pr($options); */ - -/* [joins] => Array */ -/* ( */ -/* [0] => Array */ -/* ( */ -/* [type] => LEFT */ -/* [table] => `pmgr_contacts_leases` */ -/* [alias] => ContactsLease */ -/* [joins] => Array */ -/* ( */ -/* [0] => Array */ -/* ( */ -/* [type] => INNER */ -/* [table] => `pmgr_leases` */ -/* [alias] => Lease */ -/* [conditions] => `Lease`.`id` = `ContactsLease`.`lease_id` */ -/* ) */ -/* ) */ -/* [conditions] => `ContactsLease`.`contact_id` = `Contact`.`id` */ -/* ) */ -/* ) */ -/* LEFT JOIN (`pmgr_contacts_leases` AS `ContactsLease` */ -/* INNER JOIN `pmgr_leases` AS `Lease` */ -/* ON (`Lease`.`id` = `ContactsLease`.`lease_id`) */ -/* ) ON (`ContactsLease`.`contact_id` = `Contact`.`id`) */ - - // 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 @@ -183,12 +153,9 @@ class LinkableBehavior extends ModelBehavior { // Now for the top level join. This will be added into the list // of joins down below, outside of the HABTM specific code. - $options['alias'] = $Link->alias; + $options['alias'] = $linkAlias; $options['table'] = $Link->getDataSource()->fullTableName($Link); $options['conditions'][] = "{$referenceLink} = {$referenceKey}"; - -/* pr("bf post options:"); */ -/* pr($options); */ } else { $referenceKey = $Reference->escapeField($association['foreignKey']); $modelKey = $_Model->escapeField($_Model->primaryKey); @@ -214,17 +181,6 @@ class LinkableBehavior extends ModelBehavior { if (!empty($options[$this->_key])) { $iterators[] = $options[$this->_key] + array('defaults' => array_merge($defaults, array('reference' => $options['class']))); } -/* pr("bf pre query:"); */ -/* pr($query); */ -/* $aik = array('type' => true, 'alias' => true, 'table' => true, 'joins' => true, 'conditions' => true); */ -/* pr("aik"); */ -/* pr($aik); */ -/* $ojoin = array_intersect_key($options, $aik); */ -/* pr("ojoin"); */ -/* pr($ojoin); */ -/* $query['joins'][] = $ojoin; */ -/* pr("bf post query:"); */ -/* pr($query); */ $query['joins'][] = array_intersect_key($options, array('type' => true, 'alias' => true, 'table' => true, 'joins' => true, 'conditions' => true)); } ++$cont; From 3f6c526718b8bb024dfe7e69079e20ec80fc78b1 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 1 Jun 2009 04:29:26 +0000 Subject: [PATCH 050/717] Removed the named table alias from each of the HABTM joins, since we don't know in advance what name will be used in the actual join git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@51 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/contact.php | 6 +++--- site/models/contact_address.php | 2 +- site/models/contact_email.php | 2 +- site/models/contact_phone.php | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/site/models/contact.php b/site/models/contact.php index 5aab7f3..c3d834a 100644 --- a/site/models/contact.php +++ b/site/models/contact.php @@ -31,7 +31,7 @@ class Contact extends AppModel { 'foreignKey' => 'contact_id', 'associationForeignKey' => 'method_id', 'unique' => true, - 'conditions' => "ContactsMethod.method = 'POST'", + 'conditions' => "method = 'POST'", 'fields' => '', 'order' => '', 'limit' => '', @@ -46,7 +46,7 @@ class Contact extends AppModel { 'foreignKey' => 'contact_id', 'associationForeignKey' => 'method_id', 'unique' => true, - 'conditions' => "ContactsMethod.method = 'PHONE'", + 'conditions' => "method = 'PHONE'", 'fields' => '', 'order' => '', 'limit' => '', @@ -61,7 +61,7 @@ class Contact extends AppModel { 'foreignKey' => 'contact_id', 'associationForeignKey' => 'method_id', 'unique' => true, - 'conditions' => "ContactsMethod.method = 'EMAIL'", + 'conditions' => "method = 'EMAIL'", 'fields' => '', 'order' => '', 'limit' => '', diff --git a/site/models/contact_address.php b/site/models/contact_address.php index d808b41..5503268 100644 --- a/site/models/contact_address.php +++ b/site/models/contact_address.php @@ -14,7 +14,7 @@ class ContactAddress extends AppModel { 'foreignKey' => 'method_id', 'associationForeignKey' => 'contact_id', 'unique' => true, - 'conditions' => "ContactsMethod.method = 'POST'", + 'conditions' => "method = 'POST'", 'fields' => '', 'order' => '', 'limit' => '', diff --git a/site/models/contact_email.php b/site/models/contact_email.php index c9b59dd..474e2b2 100644 --- a/site/models/contact_email.php +++ b/site/models/contact_email.php @@ -14,7 +14,7 @@ class ContactEmail extends AppModel { 'foreignKey' => 'method_id', 'associationForeignKey' => 'contact_id', 'unique' => true, - 'conditions' => "ContactsMethod.method = 'EMAIL'", + 'conditions' => "method = 'EMAIL'", 'fields' => '', 'order' => '', 'limit' => '', diff --git a/site/models/contact_phone.php b/site/models/contact_phone.php index 79b9807..8569c89 100644 --- a/site/models/contact_phone.php +++ b/site/models/contact_phone.php @@ -16,7 +16,7 @@ class ContactPhone extends AppModel { 'foreignKey' => 'method_id', 'associationForeignKey' => 'contact_id', 'unique' => true, - 'conditions' => "ContactsMethod.method = 'PHONE'", + 'conditions' => "method = 'PHONE'", 'fields' => '', 'order' => '', 'limit' => '', From f74073a2e14c85b249ff27faf510e078e3fc03da Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 1 Jun 2009 04:30:32 +0000 Subject: [PATCH 051/717] Cleaned up the paginate comment remnants and added the undocumented 'extra' parameter to paginate git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@52 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_model.php | 36 +++--------------------------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/site/app_model.php b/site/app_model.php index b4cc264..8914138 100644 --- a/site/app_model.php +++ b/site/app_model.php @@ -84,9 +84,9 @@ class AppModel extends Model { // without changing a bunch of core code is near impossible. var $paginate_rows_save; - function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null) { + function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null, $extra = null) { /* pr("paginate"); */ -/* pr(array_merge(compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive'))); */ +/* pr(array_merge(compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive', 'extra'))); */ if ($page > 1 && isset($limit)) $offset = ($page - 1) * $limit; else @@ -95,6 +95,7 @@ class AppModel extends Model { } function paginateCount($conditions = null, $recursive = null, $extra = null) { /* pr("paginateCount"); */ +/* pr(array_merge(compact('conditions', 'recursive', 'extra'))); */ if (!isset($recursive)) $recursive = $this->recursive; @@ -105,35 +106,4 @@ class AppModel extends Model { return count($this->paginate_rows_save); } -// Code as found in the controller -/* function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null) { */ -/* pr("paginate"); */ -/* pr(array_merge(compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive'))); */ - -/* $parameters = compact('conditions', 'fields', 'order', 'limit', 'page'); */ -/* if ($recursive != $this->recursive) { */ -/* $parameters['recursive'] = $recursive; */ -/* } */ - -/* $results = $this->find($type, array_merge($parameters, $extra)); */ -/* pr("paginate end"); */ -/* pr($results); */ -/* } */ - -/* function paginateCount($conditions = null, $recursive = null, $extra = null) { */ -/* pr("paginateCount"); */ -/* pr(array_merge(compact('conditions', 'recursive'), $extra)); */ - -/* $parameters = compact('conditions'); */ -/* if ($recursive != $this->recursive) { */ -/* $parameters['recursive'] = $recursive; */ -/* } */ -/* $count = $this->find('count', array_merge($parameters, $extra)); */ - -/* pr("paginateCount end: $count"); */ -/* return $count; */ -/* } */ - - - } From 4ebe1db2ccac3d99b506375dbba83a695022a1dd Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 1 Jun 2009 04:36:28 +0000 Subject: [PATCH 052/717] Cleaned up the controllers and now make use of the Linkable behavior for listing out items. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@53 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/contacts_controller.php | 201 +++++------------------ site/controllers/units_controller.php | 143 ++++++---------- 2 files changed, 88 insertions(+), 256 deletions(-) diff --git a/site/controllers/contacts_controller.php b/site/controllers/contacts_controller.php index 2ef5300..e2d2905 100644 --- a/site/controllers/contacts_controller.php +++ b/site/controllers/contacts_controller.php @@ -4,6 +4,7 @@ class ContactsController extends AppController { var $helpers = array('Html'); var $paginate = array('limit' => 100, + 'group' => 'Contact.id', 'order' => array('Contact.last_name' => 'ASC', 'Contact.first_name' => 'ASC')); @@ -46,13 +47,21 @@ class ContactsController extends AppController { */ function tenants() { - $this->Contact->recursive = 0; - $this->Contact->bindModel(array('hasOne' => array('ContactsLease')), - false); - + $this->paginate = array_merge + ($this->paginate, + array('link' => + array(// Models + 'Lease' => + array('fields' => array(), + 'type' => 'INNER', + ), + ), + 'conditions' => array('ContactsLease.type !=' => 'ALTERNATE') + )); + $title = 'All Tenants'; $this->set('title', $title); $this->set('heading', $title); - $this->set('contacts', $this->paginate(array('ContactsLease.type != "ALTERNATE"'))); + $this->set('contacts', $this->paginate()); $this->render('index'); } @@ -65,18 +74,22 @@ class ContactsController extends AppController { */ function current() { - $this->Contact->recursive = 0; - $this->Contact->bindModel(array('hasOne' => array('ContactsLease', - 'Lease' => array( - 'foreignKey' => false, - 'conditions' => array('Lease.id = ContactsLease.lease_id') - ))), - false); + $this->paginate = array_merge + ($this->paginate, + array('link' => + array(// Models + 'Lease' => + array('fields' => array(), + 'type' => 'INNER', + ), + ), + 'conditions' => array('ContactsLease.type !=' => 'ALTERNATE', + 'Lease.close_date IS NULL') + )); $title = 'Current Tenants'; $this->set('title', $title); $this->set('heading', $title); - $this->set('contacts', $this->paginate(array('Lease.close_date IS NULL', - 'ContactsLease.type != "ALTERNATE"'))); + $this->set('contacts', $this->paginate()); $this->render('index'); } @@ -89,124 +102,22 @@ class ContactsController extends AppController { */ function past() { -/* $this->Contact->contain */ -/* (array(// Models */ -/* 'ContactPhone', */ -/* 'ContactEmail', */ -/* 'ContactAddress', */ -/* 'Lease' => */ -/* array('order' => 'movein_date', */ -/* 'conditions' => array('Lease.close_date IS NOT NULL', */ -/* 'ContactsLease.type !=' => 'ALTERNATE'), */ -/* // Models */ -/* 'Unit' => */ -/* array('order' => array('sort_order'), */ -/* 'fields' => array('id', 'name'), */ -/* ), */ -/* /\* 'Charge' => *\/ */ -/* /\* array('order' => array('charge_date'), *\/ */ -/* /\* // Models *\/ */ -/* /\* 'ChargeType', *\/ */ -/* /\* 'Receipt', *\/ */ -/* /\* ) *\/ */ -/* ) */ -/* ) */ -/* ); */ - -/* $contact = $this->Contact->find('all', */ -/* array('order' => 'id DESC', */ -/* 'conditions' => array('Lease.id IS NOT NULL'), */ -/* 'contain' => */ -/* array( */ -/* // Models */ -/* 'Lease' => */ -/* array('order' => 'movein_date', */ -/* 'conditions' => array('Lease.lease_date IS NOT NULL', */ -/* 'Lease.close_date IS NOT NULL', */ -/* 'ContactsLease.type !=' => 'ALTERNATE'), */ -/* ) */ -/* ) */ -/* )); */ - -/* $contacts = $this->Contact->find */ -/* ('all', array */ -/* ('contain' => array */ -/* ('Lease' => array */ -/* ('conditions' => array('lease_date >' => "2009-04-01"), */ -/* ) */ -/* ), */ -/* 'order' => 'id DESC', */ -/* 'conditions' => array('Lease.id IS NOT NULL') */ -/* )); */ - -/* $contacts = $this->Contact->find('all', */ -/* array('order' => 'id DESC', */ -/* 'contain' => 'Lease.lease_date > "2009-04-01"' */ -/* )); */ -/* pr($contacts); */ -/* $this->set('contacts', $contacts); */ - -/* $this->Contact->Behaviors->attach('Containable'); */ -/* $this->Contact->contain */ -/* (array(// Models */ -/* 'ContactPhone', */ -/* 'ContactEmail', */ -/* 'ContactAddress', */ -/* 'Lease' => */ -/* array('order' => 'movein_date', */ -/* 'conditions' => array('Lease.close_date IS NOT NULL', */ -/* 'ContactsLease.type !=' => 'ALTERNATE'), */ -/* // Models */ -/* 'Unit' => */ -/* array('order' => array('sort_order'), */ -/* 'fields' => array('id', 'name'), */ -/* ), */ -/* /\* 'Charge' => *\/ */ -/* /\* array('order' => array('charge_date'), *\/ */ -/* /\* // Models *\/ */ -/* /\* 'ChargeType', *\/ */ -/* /\* 'Receipt', *\/ */ -/* /\* ) *\/ */ -/* ) */ -/* ) */ -/* ); */ - - - $this->paginate = - array('link' => - array(// Models - 'ContactPhone' => array('fields' => array('phone'), - //'type' => 'INNER' - ), - //'ContactEmail', - //'ContactAddress', - 'Lease' => - array('fields' => array(), - 'type' => 'LEFT', - // Models - 'Unit' => array('fields' => array('name'), - //'type' => 'INNER', - ), - ) - ), - 'order' => 'Contact.last_name, Contact.first_name', - 'conditions' => array(//'ContactsLease.type !=' => 'ALTERNATE', - //'Lease.id IS NOT NULL', - //'Lease.lease_date IS NOT NULL', - //'Lease.close_date IS NOT NULL' - ), - 'group' => 'Contact.id', - 'fields' => array('id', 'first_name', 'last_name', 'company_name', 'comment'), - ); - + $this->paginate = array_merge + ($this->paginate, + array('link' => + array(// Models + 'Lease' => + array('fields' => array(), + 'type' => 'INNER', + ), + ), + 'conditions' => array('ContactsLease.type !=' => 'ALTERNATE', + 'Lease.close_date IS NOT NULL') + )); $title = 'Past Tenants'; $this->set('title', $title); $this->set('heading', $title); $this->set('contacts', $this->paginate()); - //$this->set('contacts', $this->Contact->find('all', array('order' => 'id DESC'))); - //$this->set('contacts', $this->Contact->find('all')); -/* $this->set('contacts', $this->Contact->find('all')); */ -/* $this->set('contacts', $this->Contact->find('all')); */ $this->render('index'); } @@ -219,7 +130,6 @@ class ContactsController extends AppController { */ function all() { - $this->Contact->recursive = 0; $title = 'All Contacts'; $this->set('title', $title); $this->set('heading', $title); $this->set('contacts', $this->paginate()); @@ -240,9 +150,6 @@ class ContactsController extends AppController { $this->redirect(array('action'=>'index')); } - //pr($this->Contact); - //pr($this->Contact->ContactPhone); - $this->Contact->Behaviors->attach('Containable'); $this->Contact->contain (array(// Models @@ -267,32 +174,7 @@ class ContactsController extends AppController { ) ) ); - $contact = $this->Contact->read(null, $id); - -/* $contact = $this->Contact->find */ -/* ('first', */ -/* array('link' => array */ -/* (// Models */ -/* 'ContactPhone', */ -/* 'ContactEmail', */ -/* 'ContactAddress', */ -/* 'Lease' => */ -/* array(// Models */ -/* 'Unit' => array('fields' => array('id', 'name')), */ -/* 'Charge' => array(// Models */ -/* 'ChargeType', */ -/* 'Receipt', */ -/* ) */ -/* ) */ -/* ), */ -/* 'order' => 'Lease.movein_date, Unit.sort_order, Charge.charge_date', */ -/* 'conditions' => array('Lease.lease_date IS NOT NULL', */ -/* 'ContactsLease.type !=' => 'ALTERNATE'), */ -/* )); */ - -/* pr($contact); */ - - $title = $contact['Contact']['display_name']; + $contact = $this->Contact->read(null, $id); $outstanding_deposit = 0; $outstanding_balance = 0; @@ -315,10 +197,9 @@ class ContactsController extends AppController { $this->sidemenu_links[] = array('name' => 'Move-Out', 'url' => array('controller' => 'units', 'action' => 'move-out')); + $title = $contact['Contact']['display_name']; $this->set(compact('contact', 'title', 'outstanding_balance', 'outstanding_deposit')); } } - -?> \ No newline at end of file diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index 60a6b20..2e2fc84 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -4,6 +4,7 @@ class UnitsController extends AppController { var $helpers = array('Html'); var $paginate = array('limit' => 100, + 'group' => 'Unit.id', 'order' => array('Unit.sort_order' => 'ASC')); var $sidemenu_links = @@ -34,93 +35,7 @@ class UnitsController extends AppController { */ function index() { - //$this->Unit->recursive = 0; - - // $units = $this->Unit->find - // ('all', - $this->paginate = - array( - 'link' => array - ('UnitSize' //=> array('fields' => array('name')), - //=> array('fields' => true), - => array('fields' => array('name')), - //=> array('fields' => array()), - //=> array(), - - //'Lease', - ), - 'conditions' => array('UnitSize.name =' => "10x30", - 'UnitSize.id IS NOT NULL'), - //'fields' => true - 'fields' => array('id', 'name', 'status', 'comment') -// ) - ); - - $units = $this->paginate(); - - -/* Array */ -/* ( */ -/* [joins] => Array */ -/* ( */ -/* [0] => Array */ -/* ( */ -/* [type] => LEFT */ -/* [alias] => UnitSize */ -/* [conditions] => `UnitSize`.`id` = `Unit`.`unit_size_id` */ -/* [table] => `pmgr_unit_sizes` */ -/* ) */ - -/* ) */ - -/* [conditions] => Array */ -/* ( */ -/* [UnitSize.name =] => 10x30 */ -/* [0] => UnitSize.id IS NOT NULL */ -/* ) */ - -/* [fields] => Array */ -/* ( */ -/* [0] => id */ -/* [1] => name */ -/* [2] => status */ -/* [3] => comment */ -/* [4] => `UnitSize`.`name` */ -/* ) */ - -/* [limit] => */ -/* [offset] => */ -/* [order] => Array */ -/* ( */ -/* [0] => */ -/* ) */ - -/* [page] => 1 */ -/* [group] => */ -/* [callbacks] => 1 */ -/* [link] => Array */ -/* ( */ -/* [UnitSize] => Array */ -/* ( */ -/* [fields] => Array */ -/* ( */ -/* [0] => name */ -/* ) */ - -/* ) */ - -/* ) */ - -/* [recursive] => -1 */ -/* ) */ - - - pr($units); - $title = 'Index Units'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('units', $units); - - //$this->all(); + $this->all(); } @@ -132,10 +47,18 @@ class UnitsController extends AppController { */ function unavailable() { - $this->Unit->recursive = 0; + $this->paginate = array_merge + ($this->paginate, + array('link' => + array(// Models + 'UnitSize' => array('fields' => array('name')), + ), + 'conditions' => $this->Unit->conditionUnavailable() + )); + $title = 'Unavailable Units'; $this->set('title', $title); $this->set('heading', $title); - $this->set('units', $this->paginate(array($this->Unit->conditionUnavailable()))); + $this->set('units', $this->paginate()); $this->render('index'); } @@ -148,10 +71,18 @@ class UnitsController extends AppController { */ function vacant() { - $this->Unit->recursive = 0; + $this->paginate = array_merge + ($this->paginate, + array('link' => + array(// Models + 'UnitSize' => array('fields' => array('name')), + ), + 'conditions' => $this->Unit->conditionVacant() + )); + $title = 'Vacant Units'; $this->set('title', $title); $this->set('heading', $title); - $this->set('units', $this->paginate(array($this->Unit->conditionVacant()))); + $this->set('units', $this->paginate()); $this->render('index'); } @@ -164,10 +95,25 @@ class UnitsController extends AppController { */ function occupied() { - $this->Unit->recursive = 0; + $this->paginate = array_merge + ($this->paginate, + array('link' => + array(// Models + 'UnitSize' => array('fields' => array('name')), + 'Lease' => array('fields' => array(), + + // Models + 'Contact' => array('fields' => array('display_name'), + //'type' => 'LEFT', + ), + ), + ), + 'conditions' => $this->Unit->conditionOccupied() + )); + $title = 'Occupied Units'; $this->set('title', $title); $this->set('heading', $title); - $this->set('units', $this->paginate(array($this->Unit->conditionOccupied()))); + $this->set('units', $this->paginate()); $this->render('index'); } @@ -180,7 +126,14 @@ class UnitsController extends AppController { */ function all() { - $this->Unit->recursive = 0; + $this->paginate = array_merge + ($this->paginate, + array('link' => + array(// Models + 'UnitSize' => array('fields' => array('name')), + ), + )); + $title = 'All Units'; $this->set('title', $title); $this->set('heading', $title); $this->set('units', $this->paginate()); @@ -238,5 +191,3 @@ class UnitsController extends AppController { 'outstanding_deposit')); } } - -?> \ No newline at end of file From 1db887cf38238f8e22a36d72b92f8212c11a5618 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 1 Jun 2009 05:44:44 +0000 Subject: [PATCH 053/717] Removed the debug comments that were helping me with the sitelink migration, and added in the actual comments that were entered in sitelink. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@54 97e9348a-65ac-dc4b-aefc-98561f571b83 --- scripts/sitelink2pmgr.pl | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index ea0db31..f52a1d3 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -651,7 +651,7 @@ foreach $row (@$result) { datefmt($row->{'ChargeDate'}), datefmt($row->{'EndDate'}), $row->{'ChargeAmount'}, $row->{'TaxAmount'}, $row->{'ChargeAmount'} + $row->{'TaxAmount'}, - "SiteLink Charges.ChargeID #".$row->{'ChargeID'}) + undef) )) . ")"; query($db_handle, $query) || die("Unable to insert"); @@ -679,8 +679,7 @@ foreach $row (@$result) { (`id`, `stamp`, `comment`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($rid, datefmt($row->{'ReceiptDate'}), - "SiteLink Receipts.ReceiptNum #".$row->{'ReceiptNum'}) + ($rid, datefmt($row->{'ReceiptDate'}), undef) )) . ")"; query($db_handle, $query) || die("Unable to insert"); } @@ -720,8 +719,7 @@ foreach $row (@$result) { join(", ", map({defined $_ ? "'$_'" : "NULL"} ($pid, $rid, $row->{'PaymentDate'} =~ m%3/25/2009% ? 8 : $row->{'PaymentType'}, - $row->{'PaymentAmount'}, - "PaymentID #".$row->{'PaymentID'} . ($row->{'Memo'} ? "; ".$row->{'Memo'} : "")) + $row->{'PaymentAmount'}, undef) )) . ")"; query($db_handle, $query) || die("Unable to insert"); @@ -732,6 +730,13 @@ foreach $row (@$result) { ($chid, $rid, $row->{'PaymentAmount'}) )) . ")"; query($db_handle, $query) || die("Unable to insert"); + + if ($row->{'Memo'}) { + $query = + "UPDATE pmgr_receipts SET `comment` = '$row->{'Memo'}'" . + " WHERE `id` = $rid"; + query($db_handle, $query) || die("Unable to update"); + } } __END__ From 603a08393e7089c8848b4ca77477f735d29bdc7c Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 1 Jun 2009 06:17:49 +0000 Subject: [PATCH 054/717] Moved the view action to use the Containable behavior instead of the convoluted bind/unbind git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@55 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/units_controller.php | 35 +++++++++++++++++++-------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index 2e2fc84..af1f27c 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -153,17 +153,31 @@ class UnitsController extends AppController { $this->Session->setFlash(__('Invalid Item.', true)); $this->redirect(array('action'=>'')); } - $this->Unit->recursive = 4; - $this->Unit->UnitSize->unbindModel(array('hasMany' => array('Unit'))); - $this->Unit->UnitSize->UnitType->unbindModel(array('hasMany' => array('UnitSize'))); - $this->Unit->Lease->unbindModel(array('belongsTo' => array('Unit'))); - $this->Unit->Lease->LeaseType->unbindModel(array('hasMany' => array('Lease'))); - $this->Unit->Lease->Charge->unbindModel(array('belongsTo' => array('Lease'))); - $this->Unit->Lease->Charge->ChargeType->unbindModel(array('hasMany' => array('Charge'))); - $this->Unit->Lease->Charge->Receipt->unbindModel(array('hasMany' => array('ChargesReceipt'))); - $unit = $this->Unit->read(null, $id); - $title = 'Unit ' . $unit['Unit']['name']; + $this->Unit->Behaviors->attach('Containable'); + $this->Unit->contain + (array(// Models + 'UnitSize', + 'Lease' => + array('order' => 'movein_date', + 'conditions' => array('Lease.lease_date IS NOT NULL', + ), + // Models + 'Contact' => + array(//'order' => array('sort_order'), + 'fields' => array('id', 'display_name'), + ), + 'Charge' => + array('order' => array('charge_date'), + // Models + 'ChargeType', + 'Receipt' + //=> array('Payment'), + ) + ) + ) + ); + $unit = $this->Unit->read(null, $id); $outstanding_deposit = 0; $outstanding_balance = 0; @@ -186,6 +200,7 @@ class UnitsController extends AppController { $this->sidemenu_links[] = array('name' => 'Move-Out', 'url' => array('controller' => 'units', 'action' => 'move-out')); + $title = 'Unit ' . $unit['Unit']['name']; $this->set(compact('unit', 'title', 'outstanding_balance', 'outstanding_deposit')); From 59b549955ed33fe6707cc088dba5ef92f38c52dd Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 1 Jun 2009 06:25:59 +0000 Subject: [PATCH 055/717] Added payments under each receipt in the ledger. This isn't something I really want, just something I was testing. Snapshotting before I delete it, since it did work correctly git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@56 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/units_controller.php | 2 +- site/views/units/view.ctp | 13 ++++++++++++- site/webroot/css/layout.css | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index af1f27c..79f37ce 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -172,7 +172,7 @@ class UnitsController extends AppController { // Models 'ChargeType', 'Receipt' - //=> array('Payment'), + => array('Payment'), ) ) ) diff --git a/site/views/units/view.ctp b/site/views/units/view.ctp index 07c9cf8..84329e5 100644 --- a/site/views/units/view.ctp +++ b/site/views/units/view.ctp @@ -97,11 +97,22 @@ foreach($unit['Lease'] AS $lease) { $running_total += $amount; $rows[] = array(' -- ' . datefmt($receipt['stamp']), '#'.$receipt['id'], - 'Payment/Receipt', + 'Receipt', $receipt['comment'], currency($amount), currency($running_total)); $row_class[] = array('receipt', ($odd % 2) ? 'oddrow' : 'evnrow'); + + foreach ($receipt['Payment'] AS $payment) { + $amount = -1 * $payment['amount']; + $rows[] = array(' -- ', + '#'.$payment['id'], + 'Payment', + $payment['comment'], + currency($amount), + ''); + $row_class[] = array('payment', ($odd % 2) ? 'oddrow' : 'evnrow'); + } } } diff --git a/site/webroot/css/layout.css b/site/webroot/css/layout.css index b814585..a657efa 100644 --- a/site/webroot/css/layout.css +++ b/site/webroot/css/layout.css @@ -97,6 +97,7 @@ table.list.lease td.comment { width : 99%; } /* Ledger Entries */ table.list.ledger td { border-top : 1px dashed #ccc; } table.list.ledger td.date.receipt { padding-left: 1em; } +table.list.ledger td.date.payment { padding-left: 2em; } table.list.ledger td.evnrow { background: #f4f4f4; } table.list.ledger td.comment { width : 99%; } From e65db5c75994a1e0e9cf8dd3f3ae16c688d15c67 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 1 Jun 2009 06:28:56 +0000 Subject: [PATCH 056/717] Rolled back the last changes, which were checked in for documentation only. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@57 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/units_controller.php | 1 - site/views/units/view.ctp | 13 +------------ site/webroot/css/layout.css | 1 - 3 files changed, 1 insertion(+), 14 deletions(-) diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index 79f37ce..eb50b36 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -172,7 +172,6 @@ class UnitsController extends AppController { // Models 'ChargeType', 'Receipt' - => array('Payment'), ) ) ) diff --git a/site/views/units/view.ctp b/site/views/units/view.ctp index 84329e5..1956d15 100644 --- a/site/views/units/view.ctp +++ b/site/views/units/view.ctp @@ -97,22 +97,11 @@ foreach($unit['Lease'] AS $lease) { $running_total += $amount; $rows[] = array(' -- ' . datefmt($receipt['stamp']), '#'.$receipt['id'], - 'Receipt', + 'Payment Applied', $receipt['comment'], currency($amount), currency($running_total)); $row_class[] = array('receipt', ($odd % 2) ? 'oddrow' : 'evnrow'); - - foreach ($receipt['Payment'] AS $payment) { - $amount = -1 * $payment['amount']; - $rows[] = array(' -- ', - '#'.$payment['id'], - 'Payment', - $payment['comment'], - currency($amount), - ''); - $row_class[] = array('payment', ($odd % 2) ? 'oddrow' : 'evnrow'); - } } } diff --git a/site/webroot/css/layout.css b/site/webroot/css/layout.css index a657efa..b814585 100644 --- a/site/webroot/css/layout.css +++ b/site/webroot/css/layout.css @@ -97,7 +97,6 @@ table.list.lease td.comment { width : 99%; } /* Ledger Entries */ table.list.ledger td { border-top : 1px dashed #ccc; } table.list.ledger td.date.receipt { padding-left: 1em; } -table.list.ledger td.date.payment { padding-left: 2em; } table.list.ledger td.evnrow { background: #f4f4f4; } table.list.ledger td.comment { width : 99%; } From 0c43a0f884c7a9ebad2157466c8909aeeaf81603 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 1 Jun 2009 07:23:05 +0000 Subject: [PATCH 057/717] Fixed copy/paste error git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@58 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/units/view.ctp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/views/units/view.ctp b/site/views/units/view.ctp index 1956d15..ccc2baf 100644 --- a/site/views/units/view.ctp +++ b/site/views/units/view.ctp @@ -34,7 +34,7 @@ echo $this->element('table', ?> -
+
Security Deposit:
From 4aa59a40a2466f55da94e330c97a1d34940e2df1 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 1 Jun 2009 07:23:42 +0000 Subject: [PATCH 058/717] Removed the test code I'd forgot and left in the table element git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@59 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/table.ctp | 2 -- 1 file changed, 2 deletions(-) diff --git a/site/views/elements/table.ctp b/site/views/elements/table.ctp index fdb973f..de95c71 100644 --- a/site/views/elements/table.ctp +++ b/site/views/elements/table.ctp @@ -58,7 +58,6 @@ if (isset($rows) && is_array($rows) && count($rows)) { $row[$c] = array($col, array('class' => $cell_class)); } } - echo('
' . "\n"); if (isset($caption)) @@ -73,5 +72,4 @@ if (isset($rows) && is_array($rows) && count($rows)) { false, false) . "\n"; echo('' . "\n"); - echo(' Date: Mon, 1 Jun 2009 07:24:51 +0000 Subject: [PATCH 059/717] Added a receipt controller to verify receipt data git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@60 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/receipts_controller.php | 133 +++++++++++++++++++++++ site/views/elements/receipts.ctp | 44 ++++++++ site/views/receipts/index.ctp | 3 + site/views/receipts/view.ctp | 109 +++++++++++++++++++ 4 files changed, 289 insertions(+) create mode 100644 site/controllers/receipts_controller.php create mode 100644 site/views/elements/receipts.ctp create mode 100644 site/views/receipts/index.ctp create mode 100644 site/views/receipts/view.ctp diff --git a/site/controllers/receipts_controller.php b/site/controllers/receipts_controller.php new file mode 100644 index 0000000..a78764f --- /dev/null +++ b/site/controllers/receipts_controller.php @@ -0,0 +1,133 @@ + 100, + 'group' => 'Receipt.id', + 'order' => array('Receipt.stamp' => 'ASC')); + + var $sidemenu_links = + array(array('name' => 'Receipts', 'header' => true), + array('name' => 'Cleared', 'url' => array('controller' => 'receipts', 'action' => 'cleared')), + array('name' => 'Unresolved', 'url' => array('controller' => 'receipts', 'action' => 'unresolved')), + ); + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * override: sideMenuLinks + * - Generates controller specific links for the side menu + */ + function sideMenuLinks() { + return array_merge(parent::sideMenuLinks(), $this->sidemenu_links); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: index + * - Lists all receipts + */ + + function index() { + $this->all(); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: cleared + * - Lists cleared receipts + */ + + function cleared() { + $this->all(); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: unresolved + * - Lists unresolved receipts + */ + + function unresolved() { + $this->all(); + } + + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: all + * - Lists all receipts + */ + + function all() { + $this->paginate = array_merge + ($this->paginate, + array('link' => + array(// Models + 'Charge', + 'Payment' + ), + )); + + $title = 'All Receipts'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('receipts', $this->paginate()); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: view + * - Displays information about a specific receipt + */ + + function view($id = null) { + if (!$id) { + $this->Session->setFlash(__('Invalid Item.', true)); + $this->redirect(array('action'=>'index')); + } + + $this->Receipt->Behaviors->attach('Containable'); + $this->Receipt->contain + (array(// Models + 'Charge' => array(// Models + 'Lease' => array('fields' => array('number')), + 'ChargesReceipt', + 'ChargeType'), + 'Payment' => array(// Models + 'PaymentType'), + ) + ); + $receipt = $this->Receipt->read(null, $id); + //pr($receipt); + + $charge_amount = 0; + $payment_amount = 0; + foreach($receipt['Charge'] AS $charge) + $charge_amount += $charge['ChargesReceipt']['amount']; + foreach($receipt['Payment'] AS $payment) + $payment_amount += $payment['amount']; + +/* $this->sidemenu_links[] = */ +/* array('name' => 'Operations', 'header' => true); */ +/* $this->sidemenu_links[] = */ +/* array('name' => 'Move-Out', 'url' => array('controller' => 'receipts', 'action' => 'move-out')); */ + + $title = 'Receipt #' . $receipt['Receipt']['id']; + $this->set(compact('receipt', 'title', + 'charge_amount', + 'payment_amount')); + } +} diff --git a/site/views/elements/receipts.ctp b/site/views/elements/receipts.ctp new file mode 100644 index 0000000..169d702 --- /dev/null +++ b/site/views/elements/receipts.ctp @@ -0,0 +1,44 @@ +'.__('Receipts',true).''; + +$headers_manual = array('Id', 'Timestamp', 'Comment'); +if (isset($paginator)) { + echo $paginator->counter(array( + 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); + + $headers = array($paginator->sort('id'), + $paginator->sort('Timestamp', 'stamp'), + $paginator->sort('comment')); +} else { + $headers = $headers_manual; +} + +$rows = array(); +foreach ($receipts as $receipt) { + $rows[] = array($html->link($receipt['Receipt']['id'], + array('controller' => 'receipts', + 'action' => 'view', + $receipt['Receipt']['id'])), + $receipt['Receipt']['stamp'], + $receipt['Receipt']['comment']); +} + +echo $this->element('table', + array('class' => 'item receipt list', + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $headers_manual)); + +if (isset($paginator)) { + echo('
' . "\n"); + echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); + echo(' | '); + echo $paginator->numbers(); + echo(' | '); + echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); + echo('
' . "\n"); +} diff --git a/site/views/receipts/index.ctp b/site/views/receipts/index.ctp new file mode 100644 index 0000000..e6ce32d --- /dev/null +++ b/site/views/receipts/index.ctp @@ -0,0 +1,3 @@ +
+element('receipts', array('heading' => '

'.$heading.'

')) ?> +
diff --git a/site/views/receipts/view.ctp b/site/views/receipts/view.ctp new file mode 100644 index 0000000..27f14a3 --- /dev/null +++ b/site/views/receipts/view.ctp @@ -0,0 +1,109 @@ + + +
+ +element('table', + array('class' => 'item receipt detail', + 'caption' => 'Receipt Info', + 'rows' => $rows, + 'column_class' => array('field', 'value'))); + + +?> +
+
+ Amount Received: +
+
+ Amount Applied: +
+
+element('table', + array('class' => 'item payment list', + 'caption' => 'Payments in Receipt', + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $headers)); + + +/********************************************************************** + * Charges + */ + +$headers = array('Date', 'ID', /*'Due',*/ 'Type', 'Lease', 'Comment', 'Amount' /*, 'Tax', 'Subtotal'*/, 'Applied', /*'Total'*/); +$rows = array(); +$running_total = 0; +foreach($receipt['Charge'] AS $charge) { + $amount = $charge['total']; + $running_total += $amount; + $rows[] = array(datefmt($charge['charge_date']) .' - '. datefmt($charge['charge_to_date']), + '#'.$charge['id'], + //datefmt($charge['due_date']), + $charge['ChargeType']['name'], + '#'.$charge['Lease']['number'], + $charge['comment'], + //currency($charge['amount']), + //currency($charge['tax']), + currency($charge['total']), + currency($charge['ChargesReceipt']['amount']), + //currency($running_total) + ); +} + +echo $this->element('table', + array('class' => 'item charge list', + 'caption' => 'Charges Applied Towards', + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $headers)); + + + +?> + +
From f42ce65768c14d7f6bd35f7657133e5b2e8205ad Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 1 Jun 2009 07:26:00 +0000 Subject: [PATCH 060/717] Changed the charge_to date to allow NULL, since not all charges cover a time period (security deposits, some late charges, POS, etc) git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@61 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/schema.sql b/db/schema.sql index d78adee..0baef5a 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -778,7 +778,7 @@ CREATE TABLE `pmgr_charges` ( `charge_type_id` INT(10) UNSIGNED NOT NULL, `lease_id` INT(10) UNSIGNED NOT NULL, `charge_date` DATE NOT NULL, - `charge_to_date` DATE NOT NULL, + `charge_to_date` DATE DEFAULT NULL, `due_date` DATE DEFAULT NULL, `amount` FLOAT(12,2) NOT NULL, `tax` FLOAT(12,2) NOT NULL, From b6a0809350703594a8de152cedb8fa68e6595506 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 1 Jun 2009 08:05:53 +0000 Subject: [PATCH 061/717] Added the charges controller and views. Fixed a couple minor bugs found with receipts. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@62 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/charges_controller.php | 129 ++++++++++++++++++++++++ site/views/charges/index.ctp | 3 + site/views/charges/view.ctp | 84 +++++++++++++++ site/views/elements/charges.ctp | 68 +++++++++++++ site/views/elements/receipts.ctp | 16 ++- site/views/receipts/view.ctp | 3 +- 6 files changed, 301 insertions(+), 2 deletions(-) create mode 100644 site/controllers/charges_controller.php create mode 100644 site/views/charges/index.ctp create mode 100644 site/views/charges/view.ctp create mode 100644 site/views/elements/charges.ctp diff --git a/site/controllers/charges_controller.php b/site/controllers/charges_controller.php new file mode 100644 index 0000000..8458124 --- /dev/null +++ b/site/controllers/charges_controller.php @@ -0,0 +1,129 @@ + 100, + 'group' => 'Charge.id', + 'order' => array('Charge.charge_date' => 'ASC')); + + var $sidemenu_links = + array(array('name' => 'Charges', 'header' => true), + array('name' => 'Cleared', 'url' => array('controller' => 'charges', 'action' => 'cleared')), + array('name' => 'Unresolved', 'url' => array('controller' => 'charges', 'action' => 'unresolved')), + ); + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * override: sideMenuLinks + * - Generates controller specific links for the side menu + */ + function sideMenuLinks() { + return array_merge(parent::sideMenuLinks(), $this->sidemenu_links); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: index + * - Lists all charges + */ + + function index() { + $this->all(); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: cleared + * - Lists cleared charges + */ + + function cleared() { + $this->all(); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: unresolved + * - Lists unresolved charges + */ + + function unresolved() { + $this->all(); + } + + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: all + * - Lists all charges + */ + + function all() { + $this->paginate = array_merge + ($this->paginate, + array('link' => + array(// Models + 'ChargeType', + 'Receipt', + 'Lease' => array('fields' => array('number')) + ), + )); + + $title = 'All Charges'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('charges', $this->paginate()); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: view + * - Displays information about a specific charge + */ + + function view($id = null) { + if (!$id) { + $this->Session->setFlash(__('Invalid Item.', true)); + $this->redirect(array('action'=>'index')); + } + + $this->Charge->Behaviors->attach('Containable'); + $this->Charge->contain + (array(// Models + 'ChargeType', + 'Receipt', + 'Lease' => array('fields' => array('number')), + ) + ); + $charge = $this->Charge->read(null, $id); + //pr($charge); + + $payment_amount = 0; + foreach($charge['Receipt'] AS $receipt) + $payment_amount += $receipt['ChargesReceipt']['amount']; + $balance_amount = $charge['Charge']['total'] - $payment_amount; + +/* $this->sidemenu_links[] = */ +/* array('name' => 'Operations', 'header' => true); */ +/* $this->sidemenu_links[] = */ +/* array('name' => 'Move-Out', 'url' => array('controller' => 'charges', 'action' => 'move-out')); */ + + $title = 'Charge #' . $charge['Charge']['id']; + $this->set(compact('charge', 'title', + 'payment_amount', + 'balance_amount')); + } +} diff --git a/site/views/charges/index.ctp b/site/views/charges/index.ctp new file mode 100644 index 0000000..1d4e8e3 --- /dev/null +++ b/site/views/charges/index.ctp @@ -0,0 +1,3 @@ +
+element('charges', array('heading' => '

'.$heading.'

')) ?> +
diff --git a/site/views/charges/view.ctp b/site/views/charges/view.ctp new file mode 100644 index 0000000..3672c01 --- /dev/null +++ b/site/views/charges/view.ctp @@ -0,0 +1,84 @@ + + +
+ +element('table', + array('class' => 'item charge detail', + 'caption' => 'Charge Info', + 'rows' => $rows, + 'column_class' => array('field', 'value'))); + + +?> +
+
+ Amount Received: +
+
+ Amount Owing: +
+
+element('table', + array('class' => 'item receipt list', + 'caption' => 'Receipts towards Charge', + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $headers)); + + +?> + +
diff --git a/site/views/elements/charges.ctp b/site/views/elements/charges.ctp new file mode 100644 index 0000000..461da13 --- /dev/null +++ b/site/views/elements/charges.ctp @@ -0,0 +1,68 @@ +'.__('Charges',true).''; + +function currency($number) { + if ($number < 0) + return "($ " . number_format(-1*$number, 2) . ")"; + else + return "$ " . number_format($number, 2); +} + +function datefmt($date) { + $date_fmt = 'm/d/Y'; + return ($date + ? date_format(date_create($date), $date_fmt) + : null); +} + +$headers_manual = array('ID', 'Date', 'Due', 'Type', 'Lease', 'Amount', 'Comment'); +if (isset($paginator)) { + echo $paginator->counter(array( + 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); + + $headers = array($paginator->sort('id'), + $paginator->sort('Date', 'charge_date'), + $paginator->sort('Due', 'due_date'), + $paginator->sort('Type', 'charge_type'), + $paginator->sort('Lease', 'number'), + $paginator->sort('total'), + $paginator->sort('comment')); +} else { + $headers = $headers_manual; +} + + +$rows = array(); +foreach ($charges as $charge) { + $rows[] = array($html->link($charge['Charge']['id'], + array('controller' => 'charges', + 'action' => 'view', + $charge['Charge']['id'])), + datefmt($charge['Charge']['charge_date']), + datefmt($charge['Charge']['due_date']), + $charge['ChargeType']['name'], + '#'.$charge['Lease']['number'], + currency($charge['Charge']['total']), + $charge['Charge']['comment'], + ); +} + +echo $this->element('table', + array('class' => 'item charge list', + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $headers_manual)); + +if (isset($paginator)) { + echo('
' . "\n"); + echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); + echo(' | '); + echo $paginator->numbers(); + echo(' | '); + echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); + echo('
' . "\n"); +} diff --git a/site/views/elements/receipts.ctp b/site/views/elements/receipts.ctp index 169d702..e89adbd 100644 --- a/site/views/elements/receipts.ctp +++ b/site/views/elements/receipts.ctp @@ -5,6 +5,20 @@ if (isset($heading)) else echo '

'.__('Receipts',true).'

'; +function currency($number) { + if ($number < 0) + return "($ " . number_format(-1*$number, 2) . ")"; + else + return "$ " . number_format($number, 2); +} + +function datefmt($date) { + $date_fmt = 'm/d/Y'; + return ($date + ? date_format(date_create($date), $date_fmt) + : null); +} + $headers_manual = array('Id', 'Timestamp', 'Comment'); if (isset($paginator)) { echo $paginator->counter(array( @@ -23,7 +37,7 @@ foreach ($receipts as $receipt) { array('controller' => 'receipts', 'action' => 'view', $receipt['Receipt']['id'])), - $receipt['Receipt']['stamp'], + datefmt($receipt['Receipt']['stamp']), $receipt['Receipt']['comment']); } diff --git a/site/views/receipts/view.ctp b/site/views/receipts/view.ctp index 27f14a3..6cceba9 100644 --- a/site/views/receipts/view.ctp +++ b/site/views/receipts/view.ctp @@ -22,7 +22,8 @@ function datefmt($date) { * Receipt Info */ -$rows = array(array('Timestamp', $receipt['Receipt']['stamp']), +$rows = array(array('ID', $receipt['Receipt']['id']), + array('Timestamp', datefmt($receipt['Receipt']['stamp'])), array('Comment', $receipt['Receipt']['comment'])); echo $this->element('table', From b6ec85205dda34873416be2d4bad6e5b7e024d0c Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 1 Jun 2009 08:15:51 +0000 Subject: [PATCH 062/717] Added the payments controller and views. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@63 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/payments_controller.php | 120 +++++++++++++++++++++++ site/views/elements/payments.ctp | 64 ++++++++++++ site/views/payments/index.ctp | 3 + site/views/payments/view.ctp | 40 ++++++++ 4 files changed, 227 insertions(+) create mode 100644 site/controllers/payments_controller.php create mode 100644 site/views/elements/payments.ctp create mode 100644 site/views/payments/index.ctp create mode 100644 site/views/payments/view.ctp diff --git a/site/controllers/payments_controller.php b/site/controllers/payments_controller.php new file mode 100644 index 0000000..f567bea --- /dev/null +++ b/site/controllers/payments_controller.php @@ -0,0 +1,120 @@ + 100, + 'group' => 'Payment.id', + 'order' => array('Payment.id' => 'ASC')); + + var $sidemenu_links = + array(array('name' => 'Payments', 'header' => true), + array('name' => 'Cleared', 'url' => array('controller' => 'payments', 'action' => 'cleared')), + array('name' => 'Unresolved', 'url' => array('controller' => 'payments', 'action' => 'unresolved')), + ); + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * override: sideMenuLinks + * - Generates controller specific links for the side menu + */ + function sideMenuLinks() { + return array_merge(parent::sideMenuLinks(), $this->sidemenu_links); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: index + * - Lists all payments + */ + + function index() { + $this->all(); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: cleared + * - Lists cleared payments + */ + + function cleared() { + $this->all(); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: unresolved + * - Lists unresolved payments + */ + + function unresolved() { + $this->all(); + } + + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: all + * - Lists all payments + */ + + function all() { + $this->paginate = array_merge + ($this->paginate, + array('link' => + array(// Models + 'PaymentType', + 'Receipt', + ), + )); + + $title = 'All Payments'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('payments', $this->paginate()); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: view + * - Displays information about a specific payment + */ + + function view($id = null) { + if (!$id) { + $this->Session->setFlash(__('Invalid Item.', true)); + $this->redirect(array('action'=>'index')); + } + + $this->Payment->Behaviors->attach('Containable'); + $this->Payment->contain + (array(// Models + 'PaymentType', + 'Receipt', + ) + ); + $payment = $this->Payment->read(null, $id); + //pr($payment); + +/* $this->sidemenu_links[] = */ +/* array('name' => 'Operations', 'header' => true); */ +/* $this->sidemenu_links[] = */ +/* array('name' => 'Move-Out', 'url' => array('controller' => 'payments', 'action' => 'move-out')); */ + + $title = 'Payment #' . $payment['Payment']['id']; + $this->set(compact('payment', 'title')); + } +} diff --git a/site/views/elements/payments.ctp b/site/views/elements/payments.ctp new file mode 100644 index 0000000..78e7d22 --- /dev/null +++ b/site/views/elements/payments.ctp @@ -0,0 +1,64 @@ +'.__('Payments',true).''; + +function currency($number) { + if ($number < 0) + return "($ " . number_format(-1*$number, 2) . ")"; + else + return "$ " . number_format($number, 2); +} + +function datefmt($date) { + $date_fmt = 'm/d/Y'; + return ($date + ? date_format(date_create($date), $date_fmt) + : null); +} + +$headers_manual = array('ID', 'Type', 'Receipt', 'Amount', 'Comment'); +if (isset($paginator)) { + echo $paginator->counter(array( + 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); + + $headers = array($paginator->sort('id'), + $paginator->sort('Type', 'payment_type'), + $paginator->sort('Receipt', 'receipt_id'), + $paginator->sort('amount'), + $paginator->sort('comment')); +} else { + $headers = $headers_manual; +} + + +$rows = array(); +foreach ($payments as $payment) { + $rows[] = array($html->link($payment['Payment']['id'], + array('controller' => 'payments', + 'action' => 'view', + $payment['Payment']['id'])), + $payment['PaymentType']['name'], + '#'.$payment['Receipt']['id'], + currency($payment['Payment']['amount']), + $payment['Payment']['comment'], + ); +} + +echo $this->element('table', + array('class' => 'item payment list', + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $headers_manual)); + +if (isset($paginator)) { + echo('
' . "\n"); + echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); + echo(' | '); + echo $paginator->numbers(); + echo(' | '); + echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); + echo('
' . "\n"); +} diff --git a/site/views/payments/index.ctp b/site/views/payments/index.ctp new file mode 100644 index 0000000..4258e83 --- /dev/null +++ b/site/views/payments/index.ctp @@ -0,0 +1,3 @@ +
+element('payments', array('heading' => '

'.$heading.'

')) ?> +
diff --git a/site/views/payments/view.ctp b/site/views/payments/view.ctp new file mode 100644 index 0000000..08db77b --- /dev/null +++ b/site/views/payments/view.ctp @@ -0,0 +1,40 @@ + + +
+ +element('table', + array('class' => 'item payment detail', + 'caption' => 'Payment Info', + 'rows' => $rows, + 'column_class' => array('field', 'value'))); + + +?> + +
From 24730fda1be6aff4a6ef7bbb23fdb7c5829c8f9d Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 1 Jun 2009 08:39:33 +0000 Subject: [PATCH 063/717] Added links everywhere for charge/payment/receipt. Also, minor tweaking to the views in a couple places. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@64 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/charges/view.ctp | 13 ++++++++----- site/views/contacts/view.ctp | 18 ++++++++++++------ site/views/elements/payments.ctp | 5 ++++- site/views/payments/view.ctp | 5 ++++- site/views/receipts/view.ctp | 18 ++++++++++++------ site/views/units/view.ctp | 16 +++++++++++----- 6 files changed, 51 insertions(+), 24 deletions(-) diff --git a/site/views/charges/view.ctp b/site/views/charges/view.ctp index 3672c01..ab4d948 100644 --- a/site/views/charges/view.ctp +++ b/site/views/charges/view.ctp @@ -57,17 +57,20 @@ echo $this->element('table', * Receipts */ -$headers = array('ID', 'Timestamp', 'Comment', 'Applied'); +$headers = array('ID', 'Timestamp', 'Comment', 'Applied', 'Balance'); $rows = array(); -$running_total = 0; +$running_total = $charge['Charge']['total']; foreach($charge['Receipt'] AS $receipt) { $amount = $receipt['ChargesReceipt']['amount']; - $running_total += $amount; - $rows[] = array('#'.$receipt['id'], + $running_total -= $amount; + $rows[] = array($html->link('#'.$receipt['id'], + array('controller' => 'receipts', + 'action' => 'view', + $receipt['id'])), datefmt($receipt['stamp']), $receipt['comment'], currency($receipt['ChargesReceipt']['amount']), - //currency($running_total) + currency($running_total) ); } diff --git a/site/views/contacts/view.ctp b/site/views/contacts/view.ctp index facd250..28dcc0a 100644 --- a/site/views/contacts/view.ctp +++ b/site/views/contacts/view.ctp @@ -157,7 +157,7 @@ echo $this->element('table', * Ledger History */ foreach($contact['Lease'] AS $lease) { - $headers = array('Date', /*'Through',*/ /*'Charge/Receipt'*/'ID', 'Type', 'Comment', 'Amount', 'Total'); + $headers = array(/*'Charge/Receipt'*/'ID', 'Date', /*'Through',*/ 'Type', 'Comment', 'Amount', 'Total'); $rows = array(); $row_class = array(); @@ -166,8 +166,11 @@ foreach($contact['Lease'] AS $lease) { foreach($lease['Charge'] AS $charge) { $amount = $charge['total']; $running_total += $amount; - $rows[] = array(datefmt($charge['charge_date']) .' - '. datefmt($charge['charge_to_date']), - '#'.$charge['id'], + $rows[] = array($html->link('#'.$charge['id'], + array('controller' => 'charges', + 'action' => 'view', + $charge['id'])), + datefmt($charge['charge_date']) .' - '. datefmt($charge['charge_to_date']), $charge['ChargeType']['name'], $charge['comment'], currency($amount), @@ -177,9 +180,12 @@ foreach($contact['Lease'] AS $lease) { foreach ($charge['Receipt'] AS $receipt) { $amount = -1 * $receipt['ChargesReceipt']['amount']; $running_total += $amount; - $rows[] = array(' -- ' . datefmt($receipt['stamp']), - '#'.$receipt['id'], - 'Payment/Receipt', + $rows[] = array($html->link('#'.$receipt['id'], + array('controller' => 'receipts', + 'action' => 'view', + $receipt['id'])), + ' -- ' . datefmt($receipt['stamp']), + 'Payment Applied', $receipt['comment'], currency($amount), currency($running_total)); diff --git a/site/views/elements/payments.ctp b/site/views/elements/payments.ctp index 78e7d22..6a8818c 100644 --- a/site/views/elements/payments.ctp +++ b/site/views/elements/payments.ctp @@ -41,7 +41,10 @@ foreach ($payments as $payment) { 'action' => 'view', $payment['Payment']['id'])), $payment['PaymentType']['name'], - '#'.$payment['Receipt']['id'], + $html->link('#'.$payment['Receipt']['id'], + array('controller' => 'receipts', + 'action' => 'view', + $payment['Receipt']['id'])), currency($payment['Payment']['amount']), $payment['Payment']['comment'], ); diff --git a/site/views/payments/view.ctp b/site/views/payments/view.ctp index 08db77b..7bca3fd 100644 --- a/site/views/payments/view.ctp +++ b/site/views/payments/view.ctp @@ -24,7 +24,10 @@ function datefmt($date) { $rows = array(array('ID', $payment['Payment']['id']), array('Type', $payment['PaymentType']['name']), - array('Receipt', '#'.$payment['Receipt']['id']), + array('Receipt', $html->link('#'.$payment['Receipt']['id'], + array('controller' => 'receipts', + 'action' => 'view', + $payment['Receipt']['id']))), array('Amount', currency($payment['Payment']['amount'])), array('Comment', $payment['Payment']['comment'])); diff --git a/site/views/receipts/view.ctp b/site/views/receipts/view.ctp index 6cceba9..3b4c42f 100644 --- a/site/views/receipts/view.ctp +++ b/site/views/receipts/view.ctp @@ -50,17 +50,20 @@ echo $this->element('table', * Payments */ -$headers = array('ID', 'Type', 'Comment', 'Amount', /*'Total'*/); +$headers = array('ID', 'Type', 'Comment', 'Amount', 'Total'); $rows = array(); $running_total = 0; foreach($receipt['Payment'] AS $payment) { $amount = $payment['amount']; $running_total += $amount; - $rows[] = array('#'.$payment['id'], + $rows[] = array($html->link('#'.$payment['id'], + array('controller' => 'payments', + 'action' => 'view', + $payment['id'])), $payment['PaymentType']['name'], $payment['comment'], currency($payment['amount']), - //currency($running_total) + currency($running_total) ); } @@ -76,14 +79,17 @@ echo $this->element('table', * Charges */ -$headers = array('Date', 'ID', /*'Due',*/ 'Type', 'Lease', 'Comment', 'Amount' /*, 'Tax', 'Subtotal'*/, 'Applied', /*'Total'*/); +$headers = array('ID', 'Date', /*'Due',*/ 'Type', 'Lease', 'Comment', 'Amount' /*, 'Tax', 'Subtotal'*/, 'Applied', /*'Total'*/); $rows = array(); $running_total = 0; foreach($receipt['Charge'] AS $charge) { $amount = $charge['total']; $running_total += $amount; - $rows[] = array(datefmt($charge['charge_date']) .' - '. datefmt($charge['charge_to_date']), - '#'.$charge['id'], + $rows[] = array($html->link('#'.$charge['id'], + array('controller' => 'charges', + 'action' => 'view', + $charge['id'])), + datefmt($charge['charge_date']) .' - '. datefmt($charge['charge_to_date']), //datefmt($charge['due_date']), $charge['ChargeType']['name'], '#'.$charge['Lease']['number'], diff --git a/site/views/units/view.ctp b/site/views/units/view.ctp index ccc2baf..70555de 100644 --- a/site/views/units/view.ctp +++ b/site/views/units/view.ctp @@ -76,7 +76,7 @@ echo $this->element('table', * Ledger History */ foreach($unit['Lease'] AS $lease) { - $headers = array('Date', /*'Through',*/ /*'Charge/Receipt'*/'ID', 'Type', 'Comment', 'Amount', 'Total'); + $headers = array(/*'Charge/Receipt'*/'ID', 'Date', /*'Through',*/ 'Type', 'Comment', 'Amount', 'Total'); $rows = array(); $running_total = 0; @@ -84,8 +84,11 @@ foreach($unit['Lease'] AS $lease) { foreach($lease['Charge'] AS $charge) { $amount = $charge['total']; $running_total += $amount; - $rows[] = array(datefmt($charge['charge_date']) .' - '. datefmt($charge['charge_to_date']), - '#'.$charge['id'], + $rows[] = array($html->link('#'.$charge['id'], + array('controller' => 'charges', + 'action' => 'view', + $charge['id'])), + datefmt($charge['charge_date']) .' - '. datefmt($charge['charge_to_date']), $charge['ChargeType']['name'], $charge['comment'], currency($amount), @@ -95,8 +98,11 @@ foreach($unit['Lease'] AS $lease) { foreach ($charge['Receipt'] AS $receipt) { $amount = -1 * $receipt['ChargesReceipt']['amount']; $running_total += $amount; - $rows[] = array(' -- ' . datefmt($receipt['stamp']), - '#'.$receipt['id'], + $rows[] = array($html->link('#'.$receipt['id'], + array('controller' => 'receipts', + 'action' => 'view', + $receipt['id'])), + ' -- ' . datefmt($receipt['stamp']), 'Payment Applied', $receipt['comment'], currency($amount), From e586268deeaf69cd62f31f901fe6d6a06b041966 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 3 Jun 2009 22:33:03 +0000 Subject: [PATCH 064/717] Added a couple helpers, including Html, to our app controller and removed Html from each individual controller git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@65 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 1 + site/controllers/charges_controller.php | 2 -- site/controllers/contacts_controller.php | 2 -- site/controllers/maps_controller.php | 2 -- site/controllers/payments_controller.php | 2 -- site/controllers/receipts_controller.php | 2 -- site/controllers/units_controller.php | 2 -- 7 files changed, 1 insertion(+), 12 deletions(-) diff --git a/site/app_controller.php b/site/app_controller.php index 408afec..6557f34 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -35,6 +35,7 @@ * @subpackage cake.app */ class AppController extends Controller { + var $helpers = array('Html', 'Number', 'Time'); function sideMenuLinks() { return array( diff --git a/site/controllers/charges_controller.php b/site/controllers/charges_controller.php index 8458124..d1b890c 100644 --- a/site/controllers/charges_controller.php +++ b/site/controllers/charges_controller.php @@ -1,8 +1,6 @@ 100, 'group' => 'Charge.id', 'order' => array('Charge.charge_date' => 'ASC')); diff --git a/site/controllers/contacts_controller.php b/site/controllers/contacts_controller.php index e2d2905..f3aae03 100644 --- a/site/controllers/contacts_controller.php +++ b/site/controllers/contacts_controller.php @@ -1,8 +1,6 @@ 100, 'group' => 'Contact.id', 'order' => array('Contact.last_name' => 'ASC', diff --git a/site/controllers/maps_controller.php b/site/controllers/maps_controller.php index 02fe130..3e38fd4 100644 --- a/site/controllers/maps_controller.php +++ b/site/controllers/maps_controller.php @@ -1,7 +1,6 @@ layout = null; $this->autoLayout = false; Configure::write('debug', '0'); diff --git a/site/controllers/payments_controller.php b/site/controllers/payments_controller.php index f567bea..63e1a41 100644 --- a/site/controllers/payments_controller.php +++ b/site/controllers/payments_controller.php @@ -1,8 +1,6 @@ 100, 'group' => 'Payment.id', 'order' => array('Payment.id' => 'ASC')); diff --git a/site/controllers/receipts_controller.php b/site/controllers/receipts_controller.php index a78764f..77215dd 100644 --- a/site/controllers/receipts_controller.php +++ b/site/controllers/receipts_controller.php @@ -1,8 +1,6 @@ 100, 'group' => 'Receipt.id', 'order' => array('Receipt.stamp' => 'ASC')); diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index eb50b36..8ee4fc6 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -1,8 +1,6 @@ 100, 'group' => 'Unit.id', 'order' => array('Unit.sort_order' => 'ASC')); From e1671a9fca7c37fb17ff2c884d3de611dd0ca5d8 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 4 Jun 2009 01:54:15 +0000 Subject: [PATCH 065/717] Additional work on generating ledger information. I've been reading up on accounting basics though, and I feel I'm just not going in the right direction. I'm checking this in, since it works somewhat, and will probably try to head in a different direction. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@66 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/units_controller.php | 9 +- site/views/contacts/view.ctp | 30 ++- site/views/elements/ledger.ctp | 321 ++++++++++++++++++++++++++ site/views/units/view.ctp | 68 ++---- 4 files changed, 357 insertions(+), 71 deletions(-) create mode 100644 site/views/elements/ledger.ctp diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index 8ee4fc6..453097a 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -169,12 +169,15 @@ class UnitsController extends AppController { array('order' => array('charge_date'), // Models 'ChargeType', - 'Receipt' + 'Receipt' => array(// Models + 'Payment' + ), ) ) ) ); $unit = $this->Unit->read(null, $id); + //pr($unit); $outstanding_deposit = 0; $outstanding_balance = 0; @@ -183,6 +186,10 @@ class UnitsController extends AppController { $outstanding_balance += $charge['total']; foreach ($charge['Receipt'] AS $receipt) { $outstanding_balance -= $receipt['ChargesReceipt']['amount']; + +/* foreach($receipt['Payment'] AS $payment) */ +/* $outstanding_balance -= $payment['amount']; */ + // REVISIT 20090530: // Using hardcoded value for security deposit... // That can't be good! diff --git a/site/views/contacts/view.ctp b/site/views/contacts/view.ctp index 28dcc0a..7d7f48c 100644 --- a/site/views/contacts/view.ctp +++ b/site/views/contacts/view.ctp @@ -157,7 +157,7 @@ echo $this->element('table', * Ledger History */ foreach($contact['Lease'] AS $lease) { - $headers = array(/*'Charge/Receipt'*/'ID', 'Date', /*'Through',*/ 'Type', 'Comment', 'Amount', 'Total'); + $headers = array(/*'Charge/Receipt'*/'Charge', 'Date', 'Through', 'Type', 'Comment', 'Amount', 'Balance', 'Total'); $rows = array(); $row_class = array(); @@ -165,32 +165,28 @@ foreach($contact['Lease'] AS $lease) { $odd = 0; foreach($lease['Charge'] AS $charge) { $amount = $charge['total']; - $running_total += $amount; + + $balance = $amount; + foreach ($charge['Receipt'] AS $receipt) + $balance -= $receipt['ChargesReceipt']['amount']; + + $running_total += $balance; + $rows[] = array($html->link('#'.$charge['id'], array('controller' => 'charges', 'action' => 'view', $charge['id'])), - datefmt($charge['charge_date']) .' - '. datefmt($charge['charge_to_date']), + datefmt($charge['charge_date']), + datefmt($charge['charge_to_date']), $charge['ChargeType']['name'], $charge['comment'], currency($amount), + currency($balance), + //currency($amount - $paid)); currency($running_total)); + $row_class[] = array('charge', (++$odd % 2) ? 'oddrow' : 'evnrow'); - foreach ($charge['Receipt'] AS $receipt) { - $amount = -1 * $receipt['ChargesReceipt']['amount']; - $running_total += $amount; - $rows[] = array($html->link('#'.$receipt['id'], - array('controller' => 'receipts', - 'action' => 'view', - $receipt['id'])), - ' -- ' . datefmt($receipt['stamp']), - 'Payment Applied', - $receipt['comment'], - currency($amount), - currency($running_total)); - $row_class[] = array('receipt', ($odd % 2) ? 'oddrow' : 'evnrow'); - } } echo $this->element('table', diff --git a/site/views/elements/ledger.ctp b/site/views/elements/ledger.ctp new file mode 100644 index 0000000..3e16b9a --- /dev/null +++ b/site/views/elements/ledger.ctp @@ -0,0 +1,321 @@ +'.__('Payments',true).''; */ + +?> + +
+ + +link('#'.$charge['id'], + array('controller' => 'charges', + 'action' => 'view', + $charge['id'])), + datefmt($charge['charge_date']), + datefmt($charge['charge_to_date']), + $charge['ChargeType']['name'], + $charge['comment'], + currency($amount), + currency($balance), + //currency($amount - $paid)); + currency($running_total)); + + $row_class[] = 'charge'; + } + + echo ('
' . "\n"); + echo $this->element('table', + array('class' => 'item ledger list', + 'caption' => $caption, + 'headers' => $headers, + 'rows' => $rows, + 'row_class' => $row_class, + 'column_class' => $headers)); + echo ('
' . "\n"); +} + + +/********************************************************************** + * Receipts Only + */ + +if (isset($ledger['receipts'])) { + $headers = array('Receipt', 'Date', 'Comment', 'Amount', 'Balance', 'Total'); + + $receipts = array(); + foreach ($lease['Charge'] AS $charge) { + foreach($charge['Receipt'] AS $receipt) { + if (!isset($receipts[$receipt['id']])) { + $receipts[$receipt['id']] = $receipt; + $receipts[$receipt['id']]['amount'] = 0; + $receipts[$receipt['id']]['charge'] = 0; + foreach($receipt['Payment'] AS $payment) + $receipts[$receipt['id']]['amount'] += $payment['amount']; + unset($receipts[$receipt['id']]['ChargesReceipt']); + unset($receipts[$receipt['id']]['Payment']); + } + $receipts[$receipt['id']]['charge'] += $receipt['ChargesReceipt']['amount']; + } + } + + usort($receipts, + create_function('$a, $b', + '$adate = TimeHelper::toUnix(isset($a["charge_date"]) ? $a["charge_date"] : $a["stamp"]); ' . + '$bdate = TimeHelper::toUnix(isset($b["charge_date"]) ? $b["charge_date"] : $b["stamp"]); ' . + 'return strcmp($adate, $bdate);') + ); + + $rows = array(); + $row_class = array(); + $running_total = 0; + + foreach ($receipts AS $receipt) { + $amount = $receipt['amount']; + $balance = $amount - $receipt['charge']; + $running_total += $balance; + + $rows[] = array($html->link('#'.$receipt['id'], + array('controller' => 'receipts', + 'action' => 'view', + $receipt['id'])), + datefmt($receipt['stamp']), + $receipt['comment'], + currency($amount), + currency($balance), + currency($running_total)); + + $row_class[] = 'receipt'; + } + + echo ('
' . "\n"); + echo $this->element('table', + array('class' => 'item ledger list', + 'caption' => $caption, + 'headers' => $headers, + 'rows' => $rows, + 'row_class' => $row_class, + 'column_class' => $headers)); + echo ('
' . "\n"); +} + +/* $headers = array('Receipt', 'Date', 'Comment', 'Amount', 'Balance', 'Total'); */ + +/* $rows = array(); */ +/* $row_class = array(); */ +/* $running_total = 0; */ +/* $odd = 0; */ +/* foreach($lease['Receipt'] AS $charge) { */ +/* $amount = $charge['total']; */ + +/* $balance = $amount; */ +/* foreach ($charge['Receipt'] AS $receipt) */ +/* $balance -= $receipt['ChargesReceipt']['amount']; */ + +/* $running_total += $balance; */ + + +/* $charge_amount = 0; */ +/* $payment_amount = 0; */ +/* foreach($receipt['Charge'] AS $charge) */ +/* $charge_amount += $charge['ChargesReceipt']['amount']; */ +/* foreach($receipt['Payment'] AS $payment) */ +/* $payment_amount += $payment['amount']; */ + +/* foreach ($charge['Receipt'] AS $receipt) { */ +/* $amount = -1 * $receipt['ChargesReceipt']['amount']; */ +/* $running_total += $amount; */ +/* $rows[] = array($html->link('#'.$receipt['id'], */ +/* array('controller' => 'receipts', */ +/* 'action' => 'view', */ +/* $receipt['id'])), */ +/* datefmt($receipt['stamp']), */ +/* $receipt['comment'], */ +/* currency($amount), */ +/* currency($running_total)); */ +/* $row_class[] = array('receipt', ($odd % 2) ? 'oddrow' : 'evnrow'); */ +/* } */ + +/* $rows[] = array($html->link('#'.$charge['id'], */ +/* array('controller' => 'charges', */ +/* 'action' => 'view', */ +/* $charge['id'])), */ +/* datefmt($charge['charge_date']), */ +/* datefmt($charge['charge_to_date']), */ +/* $charge['ChargeType']['name'], */ +/* $charge['comment'], */ +/* currency($amount), */ +/* currency($balance), */ +/* //currency($amount - $paid)); */ +/* currency($running_total)); */ + +/* $row_class[] = array('charge', (++$odd % 2) ? 'oddrow' : 'evnrow'); */ +/* } */ + +/* echo ('
' . "\n"); */ +/* echo $this->element('table', */ +/* array('class' => 'item ledger list', */ +/* 'caption' => $caption */ +/* 'suppress_alternate_rows' => true, */ +/* 'headers' => $headers, */ +/* 'rows' => $rows, */ +/* 'row_class' => $row_class, */ +/* 'column_class' => $headers)); */ +/* echo ('
' . "\n"); */ + + +/********************************************************************** + * Mixture + */ + +if (isset($ledger['mix'])) { + $headers = array(/*'Charge/Receipt'*/'ID', 'Date', /*'Through',*/ 'Type', 'Comment', 'Amount', 'Total'); + + $receipts = array(); + foreach ($lease['Charge'] AS $charge) { + foreach($charge['Receipt'] AS $receipt) { + if (!isset($receipts[$receipt['id']])) { + $receipts[$receipt['id']] = $receipt; + $receipts[$receipt['id']]['amount'] = 0; + unset($receipts[$receipt['id']]['ChargesReceipt']); + unset($receipts[$receipt['id']]['Payment']); + } + $receipts[$receipt['id']]['amount'] += $receipt['ChargesReceipt']['amount']; + } + } + + $mix = array_merge($lease['Charge'], $receipts); + usort($mix, + create_function('$a, $b', + '$adate = TimeHelper::toUnix(isset($a["charge_date"]) ? $a["charge_date"] : $a["stamp"]); ' . + '$bdate = TimeHelper::toUnix(isset($b["charge_date"]) ? $b["charge_date"] : $b["stamp"]); ' . + 'return strcmp($adate, $bdate);') + ); + + $rows = array(); + $row_class = array(); + $running_total = 0; + + foreach ($mix AS $row) { + if (isset($row['charge_date'])) { + $controller = 'charges'; + $class = 'charge'; + $rowdate = datefmt($row['charge_date']) .' - '. datefmt($row['charge_to_date']); + $name = $row['ChargeType']['name']; + $amount = $row['total']; + } + else { + $controller = 'receipts'; + $class = 'receipt'; + $rowdate = ' -- ' . datefmt($row['stamp']); + $name = 'Payment Applied'; + $amount = -1 * $row['amount']; + } + + $running_total += $amount; + $rows[] = array($html->link('#'.$row['id'], + array('controller' => $controller, + 'action' => 'view', + $row['id'])), + $rowdate, + $name, + $row['comment'], + currency($amount), + currency($running_total)); + $row_class[] = $class; + } + + echo ('
' . "\n"); + echo $this->element('table', + array('class' => 'item ledger list', + 'caption' => $caption, + //'suppress_alternate_rows' => true, + 'headers' => $headers, + 'rows' => $rows, + 'row_class' => $row_class, + 'column_class' => $headers)); + echo ('
' . "\n"); +} + +/********************************************************************** + * Match + */ + +if (isset($ledger['match'])) { + $headers = array(/*'Charge/Receipt'*/'ID', 'Date', /*'Through',*/ 'Type', 'Comment', 'Amount', 'Total'); + + $rows = array(); + $row_class = array(); + $running_total = 0; + $odd = 0; + foreach($lease['Charge'] AS $charge) { + $amount = $charge['total']; + $running_total += $amount; + $rows[] = array($html->link('#'.$charge['id'], + array('controller' => 'charges', + 'action' => 'view', + $charge['id'])), + datefmt($charge['charge_date']) .' - '. datefmt($charge['charge_to_date']), + $charge['ChargeType']['name'], + $charge['comment'], + currency($amount), + currency($running_total)); + $row_class[] = array('charge', (++$odd % 2) ? 'oddrow' : 'evnrow'); + + foreach ($charge['Receipt'] AS $receipt) { + $amount = -1 * $receipt['ChargesReceipt']['amount']; + $running_total += $amount; + $rows[] = array($html->link('#'.$receipt['id'], + array('controller' => 'receipts', + 'action' => 'view', + $receipt['id'])), + ' -- ' . datefmt($receipt['stamp']), + 'Payment Applied', + $receipt['comment'], + currency($amount), + currency($running_total)); + $row_class[] = array('receipt', ($odd % 2) ? 'oddrow' : 'evnrow'); + } + } + + echo ('
' . "\n"); + echo $this->element('table', + array('class' => 'item ledger list', + 'caption' => $caption, + 'suppress_alternate_rows' => true, + 'headers' => $headers, + 'rows' => $rows, + 'row_class' => $row_class, + 'column_class' => $headers)); + echo ('
' . "\n"); +} \ No newline at end of file diff --git a/site/views/units/view.ctp b/site/views/units/view.ctp index 70555de..04a84a8 100644 --- a/site/views/units/view.ctp +++ b/site/views/units/view.ctp @@ -4,20 +4,20 @@ element('table', * Ledger History */ foreach($unit['Lease'] AS $lease) { - $headers = array(/*'Charge/Receipt'*/'ID', 'Date', /*'Through',*/ 'Type', 'Comment', 'Amount', 'Total'); - - $rows = array(); - $running_total = 0; - $odd = 0; - foreach($lease['Charge'] AS $charge) { - $amount = $charge['total']; - $running_total += $amount; - $rows[] = array($html->link('#'.$charge['id'], - array('controller' => 'charges', - 'action' => 'view', - $charge['id'])), - datefmt($charge['charge_date']) .' - '. datefmt($charge['charge_to_date']), - $charge['ChargeType']['name'], - $charge['comment'], - currency($amount), - currency($running_total)); - $row_class[] = array('charge', (++$odd % 2) ? 'oddrow' : 'evnrow'); - - foreach ($charge['Receipt'] AS $receipt) { - $amount = -1 * $receipt['ChargesReceipt']['amount']; - $running_total += $amount; - $rows[] = array($html->link('#'.$receipt['id'], - array('controller' => 'receipts', - 'action' => 'view', - $receipt['id'])), - ' -- ' . datefmt($receipt['stamp']), - 'Payment Applied', - $receipt['comment'], - currency($amount), - currency($running_total)); - $row_class[] = array('receipt', ($odd % 2) ? 'oddrow' : 'evnrow'); - } - } - - echo $this->element('table', - array('class' => 'item ledger list', - 'caption' => 'Lease #'.$lease['number'].' (Tenant: '.$lease['Contact'][0]['display_name'].')', - 'suppress_alternate_rows' => true, - 'headers' => $headers, - 'rows' => $rows, - 'row_class' => $row_class, - 'column_class' => $headers)); + $caption = 'Lease #'.$lease['number'].' (Tenant: '.$lease['Contact'][0]['display_name'].')'; + echo $this->element('ledger', + array('lease' => $lease, + 'caption' => $caption, + 'ledger' => array('charges'=>1, 'receipts'=>1, 'match'=>1, 'zmix'=>1))); } ?> From 46e3316ce12f12ebc63a96a184db2ced35c649c1 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 4 Jun 2009 01:56:09 +0000 Subject: [PATCH 066/717] Added some changes to try and resolve some accounting problems. However, I may be about to redo the accounting stuff altogether. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@67 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 110 +++++++++++++++++++++-- scripts/sitelink2pmgr.pl | 182 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 282 insertions(+), 10 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index 0baef5a..d32a099 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -132,10 +132,10 @@ CREATE TABLE `pmgr_contacts` ( -- FEDERAL ID, e.g. SSN or EIN `id_federal` VARCHAR(16) DEFAULT NULL, - -- STATE ID, e.g. drivers license - `id_num` VARCHAR(16) DEFAULT NULL, - `id_state` CHAR(2) DEFAULT NULL, - `id_exp` DATE DEFAULT NULL, + -- LOCAL ID, e.g. drivers license + `id_local` VARCHAR(16) DEFAULT NULL, + `id_local_state` CHAR(2) DEFAULT NULL, + `id_local_exp` DATE DEFAULT NULL, `comment` VARCHAR(255) DEFAULT NULL, @@ -511,6 +511,8 @@ CREATE TABLE `pmgr_units` ( 'LIENED') NOT NULL DEFAULT 'VACANT', + `current_lease_id` INT(10) UNSIGNED DEFAULT NULL, + `sort_order` MEDIUMINT UNSIGNED NOT NULL, `walk_order` MEDIUMINT UNSIGNED NOT NULL, @@ -650,6 +652,7 @@ CREATE TABLE `pmgr_leases` ( `lease_type_id` INT(10) UNSIGNED NOT NULL, `unit_id` INT(10) UNSIGNED NOT NULL, + `primary_contact_id` INT(10) UNSIGNED DEFAULT NULL, -- NOT NULL, `late_schedule_id` INT(10) UNSIGNED DEFAULT NULL, `lease_date` DATE NOT NULL, @@ -683,12 +686,11 @@ CREATE TABLE `pmgr_contacts_leases` ( `contact_id` INT(10) UNSIGNED NOT NULL, -- What type of contact is this for the lease? - `type` ENUM('TENANT', -- PRIMARY TENANT - 'COTENANT', -- ADDITIONAL TENANT + `type` ENUM('TENANT', -- TENANT 'ALTERNATE') -- ALTERNATE CONTACT ONLY NOT NULL DEFAULT 'TENANT', - -- If the tenant is removed as part of the lease + -- If the tenant is active as part of the lease `active` TINYINT DEFAULT 1, `comment` VARCHAR(255) DEFAULT NULL, @@ -698,6 +700,68 @@ CREATE TABLE `pmgr_contacts_leases` ( +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ## +-- ## RESERVATIONS +-- ## + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE pmgr_reservations + +DROP TABLE IF EXISTS `pmgr_reservations`; +CREATE TABLE `pmgr_reservations` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + -- Allow user to specify their own reservation numbers + -- If NULL, `id` will be used + `number` VARCHAR(20) DEFAULT NULL, + + `contact_id` INT(10) UNSIGNED NOT NULL, + `deposit` FLOAT(12,2) DEFAULT NULL, + + `reservation_date` DATE NOT NULL, + `expiration_date` DATE DEFAULT NULL, + `fulfilled_date` DATE DEFAULT NULL, + `lease_id` INT(10) UNSIGNED NOT NULL, + + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE pmgr_reservations_units + +DROP TABLE IF EXISTS `pmgr_reservations_units`; +CREATE TABLE `pmgr_reservations_units` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + `reservation_id` INT(10) UNSIGNED NOT NULL, + + `requested_id` INT(10) UNSIGNED DEFAULT NULL, + `type` ENUM('UNIT', + 'UNIT_SIZE', + 'UNIT_TYPE') + NOT NULL DEFAULT 'UNIT', + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + + -- ###################################################################### -- ###################################################################### -- ###################################################################### @@ -721,7 +785,8 @@ CREATE TABLE `pmgr_accounts` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `name` VARCHAR(80) NOT NULL, - `external_name` VARCHAR(80) NOT NULL, + `external_account` INT(10) UNSIGNED DEFAULT NULL, + `external_name` VARCHAR(80) DEFAULT NULL, `comment` VARCHAR(255) DEFAULT NULL, PRIMARY KEY (`id`) @@ -789,6 +854,34 @@ CREATE TABLE `pmgr_charges` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8; +-- -- ---------------------------------------------------------------------- +-- -- ---------------------------------------------------------------------- +-- -- TABLE pmgr_invoices + +-- DROP TABLE IF EXISTS `pmgr_invoices`; +-- CREATE TABLE `pmgr_invoices` ( +-- `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, +-- `stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + +-- `comment` VARCHAR(255) DEFAULT NULL, + +-- PRIMARY KEY (`id`) +-- ) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- -- ---------------------------------------------------------------------- +-- -- ---------------------------------------------------------------------- +-- -- TABLE pmgr_charges_invoices + +-- DROP TABLE IF EXISTS `pmgr_charges_invoices`; +-- CREATE TABLE `pmgr_charges_invoices` ( +-- `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, +-- `charge_id` INT(10) UNSIGNED NOT NULL, +-- `invoice_id` INT(10) UNSIGNED NOT NULL, +-- `amount` FLOAT(12,2) NOT NULL, +-- PRIMARY KEY (`id`) +-- ) ENGINE=MyISAM DEFAULT CHARSET=utf8; + -- ###################################################################### -- ###################################################################### @@ -910,7 +1003,6 @@ CREATE TABLE `pmgr_payments` ( DROP TABLE IF EXISTS `pmgr_receipts`; CREATE TABLE `pmgr_receipts` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `comment` VARCHAR(255) DEFAULT NULL, diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index f52a1d3..3d331b5 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -435,7 +435,7 @@ foreach $row (@$result) { my $cid = $tenant_map{$row->{'TenantID'}}{'id'}; $query = "INSERT INTO pmgr_contacts - (`id`, `first_name`, `middle_name`, `last_name`, `display_name`, `id_num`, `id_state`) + (`id`, `first_name`, `middle_name`, `last_name`, `display_name`, `id_local`, `id_local_state`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} ($cid, $row->{'FirstName'}, $row->{'MiddleName'}, $row->{'LastName'}, @@ -739,6 +739,186 @@ foreach $row (@$result) { } } + + + $query = "INSERT INTO pmgr_charges + (`id`, `charge_type_id`, `lease_id`, + `charge_date`, `charge_to_date`, + `amount`, `tax`, `total`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (1000, $charge_type_map{'Security Deposit'}, 17, + '2009-05-05', undef, + 10, 0, 10, + 'Fake security deposit for testing purposes') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO pmgr_charges + (`id`, `charge_type_id`, `lease_id`, + `charge_date`, `charge_to_date`, + `amount`, `tax`, `total`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (1001, $charge_type_map{'Rent'}, 17, + '2009-05-01', '2009-05-31', + 100, 5, 105, + 'Fake charge for testing purposes') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO pmgr_charges + (`id`, `charge_type_id`, `lease_id`, + `charge_date`, `charge_to_date`, + `amount`, `tax`, `total`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (1002, $charge_type_map{'Late Fee'}, 17, + '2009-05-11', undef, + 25, 0, 25, + 'Fake late charge for testing purposes') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO pmgr_receipts + (`id`, `stamp`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (2000, '2009-05-15', 'Fake receipt #1') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO pmgr_payments + (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (3000, 2000, 1, 15, 'Fake receipt #1 payment #1') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO pmgr_payments + (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (3001, 2000, 2, 10, 'Fake receipt #1 payment #2') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO pmgr_payments + (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (3002, 2000, 3, 5, 'Fake receipt #1 payment #3') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO pmgr_charges_receipts + (`charge_id`, `receipt_id`, `amount`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (1000, 2000, 10) + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO pmgr_charges_receipts + (`charge_id`, `receipt_id`, `amount`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (1001, 2000, 20) + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + + $query = "INSERT INTO pmgr_receipts + (`id`, `stamp`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (2100, '2009-05-18', 'Fake receipt #2') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO pmgr_payments + (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (3100, 2100, 5, 30, 'Fake receipt #2 payment #1') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO pmgr_payments + (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (3101, 2100, 6, 20, 'Fake receipt #2 payment #2') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO pmgr_charges_receipts + (`charge_id`, `receipt_id`, `amount`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (1001, 2100, 50) + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + + $query = "INSERT INTO pmgr_receipts + (`id`, `stamp`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (2200, '2009-05-22', 'Fake receipt #3') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO pmgr_payments + (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (3200, 2200, 1, 10, 'Fake receipt #3 payment #1') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO pmgr_payments + (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (3201, 2200, 2, 5, 'Fake receipt #3 payment #2') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO pmgr_payments + (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (3202, 2200, 7, 20, 'Fake receipt #3 payment #3') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO pmgr_payments + (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (3203, 2200, 8, 15, 'Fake receipt #3 payment #4') + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO pmgr_charges_receipts + (`charge_id`, `receipt_id`, `amount`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (1001, 2200, 35) + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + $query = "INSERT INTO pmgr_charges_receipts + (`charge_id`, `receipt_id`, `amount`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (1002, 2200, 15) + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + + __END__ ###################################################################### From 30c6e0b0f46447766e5924489d247db889b397ed Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 4 Jun 2009 03:48:35 +0000 Subject: [PATCH 067/717] Forgot to save the file before the last checkin. Added the possibility of a 'credits' table, but I'll probably be wiping this out moving forward. git-svn-id: file:///svn-source/pmgr/branches/initial_20090526@68 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/db/schema.sql b/db/schema.sql index d32a099..52d4f6b 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -945,6 +945,66 @@ CREATE TABLE `pmgr_payments` ( +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ## +-- ## CREDITS +-- ## + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE pmgr_credit_types + +-- DROP TABLE IF EXISTS `pmgr_credit_types`; +-- CREATE TABLE `pmgr_credit_types` ( +-- `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + +-- `name` VARCHAR(80) NOT NULL, +-- `comment` VARCHAR(255) DEFAULT NULL, +-- `account_id` INT(10) UNSIGNED NOT NULL, -- quickbooks tracking + +-- PRIMARY KEY (`id`) +-- ) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- LOCK TABLES `pmgr_credit_types` WRITE; +-- INSERT INTO `pmgr_credit_types` (`id`, `name`, `account_id`) +-- VALUES +-- (1, 'Security Deposit', 0), +-- (2, 'Rent', 0), +-- (3, 'Late Credit', 0); +-- UNLOCK TABLES; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE pmgr_credits + +DROP TABLE IF EXISTS `pmgr_credits`; +CREATE TABLE `pmgr_credits` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + -- `credit_type_id` INT(10) UNSIGNED NOT NULL, + `lease_id` INT(10) UNSIGNED NOT NULL, + `credit_date` DATE NOT NULL, + `credit_to_date` DATE DEFAULT NULL, + `due_date` DATE DEFAULT NULL, + `amount` FLOAT(12,2) NOT NULL, + `tax` FLOAT(12,2) NOT NULL, + `total` FLOAT(12,2) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + -- ###################################################################### -- ###################################################################### -- ###################################################################### From 948ae286165acfe3b09292ea82eb9b8c7e99bf0d Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 6 Jun 2009 05:22:11 +0000 Subject: [PATCH 068/717] Branching to change the accounting mechanism from the broken charge/receipt/payment to simple, double entry accounting ledgers. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@69 97e9348a-65ac-dc4b-aefc-98561f571b83 From 30b934823c7dba7770650363a9dfa361101497cb Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 6 Jun 2009 07:57:41 +0000 Subject: [PATCH 069/717] Snapshot of some partial work done with ledger.ctp. There was only a slight change to just the 'mix' ledger, in order to get it working with the new ledger tables. This checkin leaves the codebase in an inconsistent state. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@70 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/ledger.ctp | 85 ++++++++++++++++------------------ 1 file changed, 39 insertions(+), 46 deletions(-) diff --git a/site/views/elements/ledger.ctp b/site/views/elements/ledger.ctp index 3e16b9a..7e7cf04 100644 --- a/site/views/elements/ledger.ctp +++ b/site/views/elements/ledger.ctp @@ -201,58 +201,51 @@ if (isset($ledger['receipts'])) { if (isset($ledger['mix'])) { $headers = array(/*'Charge/Receipt'*/'ID', 'Date', /*'Through',*/ 'Type', 'Comment', 'Amount', 'Total'); - $receipts = array(); - foreach ($lease['Charge'] AS $charge) { - foreach($charge['Receipt'] AS $receipt) { - if (!isset($receipts[$receipt['id']])) { - $receipts[$receipt['id']] = $receipt; - $receipts[$receipt['id']]['amount'] = 0; - unset($receipts[$receipt['id']]['ChargesReceipt']); - unset($receipts[$receipt['id']]['Payment']); - } - $receipts[$receipt['id']]['amount'] += $receipt['ChargesReceipt']['amount']; - } - } - - $mix = array_merge($lease['Charge'], $receipts); - usort($mix, - create_function('$a, $b', - '$adate = TimeHelper::toUnix(isset($a["charge_date"]) ? $a["charge_date"] : $a["stamp"]); ' . - '$bdate = TimeHelper::toUnix(isset($b["charge_date"]) ? $b["charge_date"] : $b["stamp"]); ' . - 'return strcmp($adate, $bdate);') - ); +/* $mix = array_merge($lease['Charge'], $receipts); */ +/* usort($mix, */ +/* create_function('$a, $b', */ +/* '$adate = TimeHelper::toUnix(isset($a["charge_date"]) ? $a["charge_date"] : $a["stamp"]); ' . */ +/* '$bdate = TimeHelper::toUnix(isset($b["charge_date"]) ? $b["charge_date"] : $b["stamp"]); ' . */ +/* 'return strcmp($adate, $bdate);') */ +/* ); */ $rows = array(); $row_class = array(); $running_total = 0; - foreach ($mix AS $row) { - if (isset($row['charge_date'])) { - $controller = 'charges'; - $class = 'charge'; - $rowdate = datefmt($row['charge_date']) .' - '. datefmt($row['charge_to_date']); - $name = $row['ChargeType']['name']; - $amount = $row['total']; - } - else { - $controller = 'receipts'; - $class = 'receipt'; - $rowdate = ' -- ' . datefmt($row['stamp']); - $name = 'Payment Applied'; - $amount = -1 * $row['amount']; - } + foreach ($transactions AS $transaction) { + $transaction_date = datefmt($transaction['stamp']); + if (isset($transaction['through_date'])) + $transaction_date .= ' - '. datefmt($transaction['through_date']); - $running_total += $amount; - $rows[] = array($html->link('#'.$row['id'], - array('controller' => $controller, - 'action' => 'view', - $row['id'])), - $rowdate, - $name, - $row['comment'], - currency($amount), - currency($running_total)); - $row_class[] = $class; + $comment = $transaction['comment']; + + foreach ($transaction['Entry'] AS $entry) { + if ($entry['DebitAccount']['name'] === 'A/R') { + $name = $entry['CreditAccount']['name']; + $amount = $entry['amount']; + $class = 'charge'; + } + elseif ($entry['CreditAccount']['name'] === 'A/R') { + $name = 'Payment'; + $amount = -1 * $entry['amount']; + $class = 'payment'; + } + else + continue; + + $running_total += $amount; + $rows[] = array($html->link('#'.$transaction['id'], + array('controller' => 'transactions', + 'action' => 'view', + $transaction['id'])), + $transaction_date, + $name, + $comment, + currency($amount), + currency($running_total)); + $row_class[] = $class; + } } echo ('
' . "\n"); From f3ffa3c079dedd31077a9fb3cd3f00e4e6f9ade1 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 6 Jun 2009 20:18:56 +0000 Subject: [PATCH 070/717] I'm still in the middle of moving onto a ledger based system. However, I'm am now changing how transactions and entries relate back to the customer. I'll be using a ledger for each lease (for rent, late charges, security deposits, etc), and a ledger for each customer (for POS, non-specific deposits such as reservations or covering mulitple units, bad debt writeoff, and possibly customer credits, when not obviously lease specific). This coming change might not be in the right direction, so I want to capture the work as is right now. This change set is not fully functional. Many operations do work, but there are obviously transaction problems with units and customers. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@71 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 546 +++++------- scripts/sitelink2pmgr.pl | 809 ++++++++++-------- site/app_model.php | 46 +- site/controllers/accounts_controller.php | 265 ++++++ site/controllers/accounts_controller.php.bak | 244 ++++++ site/controllers/contacts_controller.php | 52 +- site/controllers/customers_controller.php | 177 ++++ .../controllers/ledger_entries_controller.php | 55 ++ site/controllers/ledgers_controller.php | 188 ++++ site/controllers/payments_controller.php | 118 --- site/controllers/receipts_controller.php | 131 --- ...roller.php => transactions_controller.php} | 66 +- site/controllers/units_controller.php | 81 +- site/models/account.php | 23 +- site/models/behaviors/linkable.php | 85 +- site/models/charge.php | 53 -- site/models/charge_type.php | 39 - site/models/contact.php | 8 +- site/models/customer.php | 58 ++ site/models/lease.php | 39 +- site/models/ledger.php | 65 ++ site/models/ledger_entry.php | 43 + site/models/monetary_source.php | 28 + .../{payment_type.php => monetary_type.php} | 11 +- site/models/payment.php | 31 - site/models/receipt.php | 46 - site/models/transaction.php | 37 + site/models/unit.php | 7 + site/views/accounts/index.ctp | 3 + site/views/accounts/view.ctp | 95 ++ site/views/charges/index.ctp | 3 - site/views/charges/view.ctp | 87 -- site/views/contacts/view.ctp | 113 +-- site/views/customers/index.ctp | 3 + site/views/customers/view.ctp | 189 ++++ site/views/elements/accounts.ctp | 85 ++ site/views/elements/charges.ctp | 68 -- site/views/elements/contacts.ctp | 57 +- .../elements/{receipts.ctp => customers.ctp} | 41 +- site/views/elements/ledger.ctp | 364 ++------ site/views/elements/ledgers.ctp | 77 ++ site/views/elements/payments.ctp | 67 -- site/views/elements/table.ctp | 4 +- site/views/elements/transactions.ctp | 65 ++ site/views/ledgers/index.ctp | 14 + site/views/ledgers/view.ctp | 98 +++ site/views/payments/index.ctp | 3 - site/views/payments/view.ctp | 43 - site/views/receipts/index.ctp | 3 - site/views/receipts/view.ctp | 116 --- site/views/transactions/index.ctp | 13 + site/views/transactions/view.ctp | 102 +++ site/views/units/view.ctp | 44 +- site/webroot/css/layout.css | 83 +- 54 files changed, 3066 insertions(+), 2125 deletions(-) create mode 100644 site/controllers/accounts_controller.php create mode 100644 site/controllers/accounts_controller.php.bak create mode 100644 site/controllers/customers_controller.php create mode 100644 site/controllers/ledger_entries_controller.php create mode 100644 site/controllers/ledgers_controller.php delete mode 100644 site/controllers/payments_controller.php delete mode 100644 site/controllers/receipts_controller.php rename site/controllers/{charges_controller.php => transactions_controller.php} (65%) delete mode 100644 site/models/charge.php delete mode 100644 site/models/charge_type.php create mode 100644 site/models/customer.php create mode 100644 site/models/ledger.php create mode 100644 site/models/ledger_entry.php create mode 100644 site/models/monetary_source.php rename site/models/{payment_type.php => monetary_type.php} (55%) delete mode 100644 site/models/payment.php delete mode 100644 site/models/receipt.php create mode 100644 site/models/transaction.php create mode 100644 site/views/accounts/index.ctp create mode 100644 site/views/accounts/view.ctp delete mode 100644 site/views/charges/index.ctp delete mode 100644 site/views/charges/view.ctp create mode 100644 site/views/customers/index.ctp create mode 100644 site/views/customers/view.ctp create mode 100644 site/views/elements/accounts.ctp delete mode 100644 site/views/elements/charges.ctp rename site/views/elements/{receipts.ctp => customers.ctp} (53%) create mode 100644 site/views/elements/ledgers.ctp delete mode 100644 site/views/elements/payments.ctp create mode 100644 site/views/elements/transactions.ctp create mode 100644 site/views/ledgers/index.ctp create mode 100644 site/views/ledgers/view.ctp delete mode 100644 site/views/payments/index.ctp delete mode 100644 site/views/payments/view.ctp delete mode 100644 site/views/receipts/index.ctp delete mode 100644 site/views/receipts/view.ctp create mode 100644 site/views/transactions/index.ctp create mode 100644 site/views/transactions/view.ctp diff --git a/db/schema.sql b/db/schema.sql index 52d4f6b..e6b638e 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -448,44 +448,6 @@ CREATE TABLE `pmgr_site_areas` ( -- ## --- ---------------------------------------------------------------------- --- ---------------------------------------------------------------------- --- TABLE pmgr_unit_types - -DROP TABLE IF EXISTS `pmgr_unit_types`; -CREATE TABLE `pmgr_unit_types` ( - `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `code` VARCHAR(12) NOT NULL, -- User style "id" - `name` VARCHAR(80) NOT NULL, - `comment` VARCHAR(255) DEFAULT NULL, - - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - - - --- ---------------------------------------------------------------------- --- ---------------------------------------------------------------------- --- TABLE pmgr_unit_sizes - -DROP TABLE IF EXISTS `pmgr_unit_sizes`; -CREATE TABLE `pmgr_unit_sizes` ( - `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `unit_type_id` INT(10) UNSIGNED NOT NULL, - `code` VARCHAR(12) NOT NULL, -- User style "id" - `name` VARCHAR(80) NOT NULL, - `width` SMALLINT UNSIGNED NOT NULL, -- inches - `depth` SMALLINT UNSIGNED NOT NULL, -- inches - `height` SMALLINT UNSIGNED DEFAULT NULL, -- inches - `comment` VARCHAR(255) DEFAULT NULL, - - `deposit` FLOAT(12,2) DEFAULT NULL, - `amount` FLOAT(12,2) DEFAULT NULL, - - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - - -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- -- TABLE pmgr_units @@ -525,6 +487,44 @@ CREATE TABLE `pmgr_units` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8; +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE pmgr_unit_types + +DROP TABLE IF EXISTS `pmgr_unit_types`; +CREATE TABLE `pmgr_unit_types` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `code` VARCHAR(12) NOT NULL, -- User style "id" + `name` VARCHAR(80) NOT NULL, + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE pmgr_unit_sizes + +DROP TABLE IF EXISTS `pmgr_unit_sizes`; +CREATE TABLE `pmgr_unit_sizes` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `unit_type_id` INT(10) UNSIGNED NOT NULL, + `code` VARCHAR(12) NOT NULL, -- User style "id" + `name` VARCHAR(80) NOT NULL, + `width` SMALLINT UNSIGNED NOT NULL, -- inches + `depth` SMALLINT UNSIGNED NOT NULL, -- inches + `height` SMALLINT UNSIGNED DEFAULT NULL, -- inches + `comment` VARCHAR(255) DEFAULT NULL, + + `deposit` FLOAT(12,2) DEFAULT NULL, + `amount` FLOAT(12,2) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + -- ###################################################################### -- ###################################################################### @@ -619,18 +619,16 @@ CREATE TABLE `pmgr_actions_late_schedules` ( -- ###################################################################### -- ###################################################################### -- ## --- ## LEASES +-- ## CUSTOMERS -- ## - -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE pmgr_lease_types +-- TABLE pmgr_customers -DROP TABLE IF EXISTS `pmgr_lease_types`; -CREATE TABLE `pmgr_lease_types` ( +DROP TABLE IF EXISTS `pmgr_customers`; +CREATE TABLE `pmgr_customers` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `code` VARCHAR(12) NOT NULL, -- User style "id" `name` VARCHAR(80) NOT NULL, `comment` VARCHAR(255) DEFAULT NULL, @@ -638,6 +636,44 @@ CREATE TABLE `pmgr_lease_types` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8; +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE pmgr_contacts_customers + +DROP TABLE IF EXISTS `pmgr_contacts_customers`; +CREATE TABLE `pmgr_contacts_customers` ( + `contact_id` INT(10) UNSIGNED NOT NULL, + `customer_id` INT(10) UNSIGNED NOT NULL, + + -- What type of contact is this for the lease? + `type` ENUM('TENANT', -- TENANT + 'ALTERNATE') -- ALTERNATE CONTACT ONLY + NOT NULL DEFAULT 'TENANT', + + -- If the tenant is active as part of the lease + `active` TINYINT DEFAULT 1, + + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`customer_id`, `contact_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + + +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ## +-- ## LEASES +-- ## + + -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- -- TABLE pmgr_leases @@ -652,7 +688,7 @@ CREATE TABLE `pmgr_leases` ( `lease_type_id` INT(10) UNSIGNED NOT NULL, `unit_id` INT(10) UNSIGNED NOT NULL, - `primary_contact_id` INT(10) UNSIGNED DEFAULT NULL, -- NOT NULL, + `customer_id` INT(10) UNSIGNED NOT NULL, `late_schedule_id` INT(10) UNSIGNED DEFAULT NULL, `lease_date` DATE NOT NULL, @@ -678,24 +714,16 @@ CREATE TABLE `pmgr_leases` ( -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE pmgr_contacts_leases - -DROP TABLE IF EXISTS `pmgr_contacts_leases`; -CREATE TABLE `pmgr_contacts_leases` ( - `lease_id` INT(10) UNSIGNED NOT NULL, - `contact_id` INT(10) UNSIGNED NOT NULL, - - -- What type of contact is this for the lease? - `type` ENUM('TENANT', -- TENANT - 'ALTERNATE') -- ALTERNATE CONTACT ONLY - NOT NULL DEFAULT 'TENANT', - - -- If the tenant is active as part of the lease - `active` TINYINT DEFAULT 1, +-- TABLE pmgr_lease_types +DROP TABLE IF EXISTS `pmgr_lease_types`; +CREATE TABLE `pmgr_lease_types` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `code` VARCHAR(12) NOT NULL, -- User style "id" + `name` VARCHAR(80) NOT NULL, `comment` VARCHAR(255) DEFAULT NULL, - PRIMARY KEY (`lease_id`, `contact_id`) + PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; @@ -726,7 +754,7 @@ CREATE TABLE `pmgr_reservations` ( -- If NULL, `id` will be used `number` VARCHAR(20) DEFAULT NULL, - `contact_id` INT(10) UNSIGNED NOT NULL, + `customer_id` INT(10) UNSIGNED NOT NULL, `deposit` FLOAT(12,2) DEFAULT NULL, `reservation_date` DATE NOT NULL, @@ -784,125 +812,166 @@ DROP TABLE IF EXISTS `pmgr_accounts`; CREATE TABLE `pmgr_accounts` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `type` ENUM('ASSET', + 'LIABILITY', + 'EQUITY', + 'INCOME', + 'EXPENSE') + NOT NULL DEFAULT 'ASSET', + + -- Security Level + `level` INT UNSIGNED DEFAULT 1, + `name` VARCHAR(80) NOT NULL, `external_account` INT(10) UNSIGNED DEFAULT NULL, `external_name` VARCHAR(80) DEFAULT NULL, + `comment` VARCHAR(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; - - --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ## --- ## CHARGES --- ## - - --- ---------------------------------------------------------------------- --- ---------------------------------------------------------------------- --- TABLE pmgr_charge_types - -DROP TABLE IF EXISTS `pmgr_charge_types`; -CREATE TABLE `pmgr_charge_types` ( - `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - - `name` VARCHAR(80) NOT NULL, - `comment` VARCHAR(255) DEFAULT NULL, - `account_id` INT(10) UNSIGNED NOT NULL, -- quickbooks tracking - - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -LOCK TABLES `pmgr_charge_types` WRITE; -INSERT INTO `pmgr_charge_types` (`id`, `name`, `account_id`) +LOCK TABLES `pmgr_accounts` WRITE; +INSERT INTO `pmgr_accounts` (`id`, `type`, `name`) VALUES - (1, 'Security Deposit', 0), - (2, 'Rent', 0), - (3, 'Late Charge', 0); + (1, 'ASSET', 'A/R'), + (2, 'LIABILITY', 'A/P'), + (3, 'LIABILITY', 'Tax'), + (4, 'LIABILITY', 'Customer Credit'), + (5, 'ASSET', 'Bank'), + (6, 'ASSET', 'Cash'), + (7, 'LIABILITY', 'Security Deposit'), + (8, 'INCOME', 'Rent'), + (9, 'INCOME', 'Late Charge'); UNLOCK TABLES; --- ---------------------------------------------------------------------- --- ---------------------------------------------------------------------- --- TABLE pmgr_charges -DROP TABLE IF EXISTS `pmgr_charges`; -CREATE TABLE `pmgr_charges` ( +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ###################################################################### +-- ## +-- ## LEDGERS +-- ## + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE pmgr_ledgers +-- +-- REVISIT : 20090605 +-- We may not really need a ledgers table. +-- It's not clear to me though, as we very +-- possibly need to close out certain +-- ledgers every so often, and just carry +-- the balance forward (year end, etc). + +DROP TABLE IF EXISTS `pmgr_ledgers`; +CREATE TABLE `pmgr_ledgers` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `charge_type_id` INT(10) UNSIGNED NOT NULL, - `lease_id` INT(10) UNSIGNED NOT NULL, - `charge_date` DATE NOT NULL, - `charge_to_date` DATE DEFAULT NULL, - `due_date` DATE DEFAULT NULL, - `amount` FLOAT(12,2) NOT NULL, - `tax` FLOAT(12,2) NOT NULL, - `total` FLOAT(12,2) NOT NULL, + -- REVISIT : 20090605 + -- If ledgers do need to be closed, then we'll need + -- to add several parameters indicating the period + -- this particular ledger is valid and so on. + + `name` VARCHAR(80) DEFAULT NULL, + `account_id` INT(10) UNSIGNED NOT NULL, + `closed` INT UNSIGNED DEFAULT 0, + `comment` VARCHAR(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; --- -- ---------------------------------------------------------------------- --- -- ---------------------------------------------------------------------- --- -- TABLE pmgr_invoices +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE pmgr_transactions --- DROP TABLE IF EXISTS `pmgr_invoices`; --- CREATE TABLE `pmgr_invoices` ( --- `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, --- `stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, +DROP TABLE IF EXISTS `pmgr_transactions`; +CREATE TABLE `pmgr_transactions` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, --- `comment` VARCHAR(255) DEFAULT NULL, + `stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `through_date` DATE DEFAULT NULL, + `due_date` DATE DEFAULT NULL, --- PRIMARY KEY (`id`) --- ) ENGINE=MyISAM DEFAULT CHARSET=utf8; + -- REVISIT : 20090604 + -- It really seems this is too restrictive. One tenant + -- should be able to, within a single transaction, pay + -- for their own charges and another tenant's as well. + -- customer_id may need to move to ledger_entries + `customer_id` INT(10) UNSIGNED NOT NULL, + -- REVISIT : 20090604 + -- How should we track which charges have been paid? + -- `related_transaction_id` INT(10) UNSIGNED NOT NULL, + -- `related_entry_id` INT(10) UNSIGNED NOT NULL, --- -- ---------------------------------------------------------------------- --- -- ---------------------------------------------------------------------- --- -- TABLE pmgr_charges_invoices + `comment` VARCHAR(255) DEFAULT NULL, --- DROP TABLE IF EXISTS `pmgr_charges_invoices`; --- CREATE TABLE `pmgr_charges_invoices` ( --- `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, --- `charge_id` INT(10) UNSIGNED NOT NULL, --- `invoice_id` INT(10) UNSIGNED NOT NULL, --- `amount` FLOAT(12,2) NOT NULL, --- PRIMARY KEY (`id`) --- ) ENGINE=MyISAM DEFAULT CHARSET=utf8; - - --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ## --- ## PAYMENTS --- ## + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- ---------------------------------------------------------------------- -- ---------------------------------------------------------------------- --- TABLE pmgr_payment_types +-- TABLE pmgr_ledger_entries -DROP TABLE IF EXISTS `pmgr_payment_types`; -CREATE TABLE `pmgr_payment_types` ( +DROP TABLE IF EXISTS `pmgr_ledger_entries`; +CREATE TABLE `pmgr_ledger_entries` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + `name` VARCHAR(80) DEFAULT NULL, + `monetary_source_id` INT(10) UNSIGNED DEFAULT NULL, -- NULL if internal transfer + `transaction_id` INT(10) UNSIGNED NOT NULL, + `amount` FLOAT(12,2) NOT NULL, + + `debit_ledger_id` INT(10) UNSIGNED NOT NULL, + `credit_ledger_id` INT(10) UNSIGNED NOT NULL, + + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE pmgr_monetary_sources + +DROP TABLE IF EXISTS `pmgr_monetary_sources`; +CREATE TABLE `pmgr_monetary_sources` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + + `name` VARCHAR(80) DEFAULT NULL, + monetary_type_id INT(10) UNSIGNED NOT NULL, + + -- REVISIT : 20090605 + -- Check Number; + -- Routing Number, Account Number; + -- Card Number, Expiration Date; CCV2 Code + -- etc. + + `comment` VARCHAR(255) DEFAULT NULL, + + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + + +-- ---------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- TABLE pmgr_monetary_types + +DROP TABLE IF EXISTS `pmgr_monetary_types`; +CREATE TABLE `pmgr_monetary_types` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `name` VARCHAR(80) NOT NULL, @@ -912,180 +981,21 @@ CREATE TABLE `pmgr_payment_types` ( PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -LOCK TABLES `pmgr_payment_types` WRITE; -INSERT INTO `pmgr_payment_types` (`id`, `name`, `tillable`) +LOCK TABLES `pmgr_monetary_types` WRITE; +INSERT INTO `pmgr_monetary_types` (`id`, `name`, `tillable`) VALUES - (1, 'Cash', 1), - (2, 'Check', 1), - (3, 'Money Order', 1), - (4, 'ACH', 0), - (5, 'Debit Card', 0), - (6, 'Credit Card', 0), - (7, 'Other Tillable', 1), - (8, 'Other Non-Tillable', 0); + -- (1, 'Transfer', 0), + (2, 'Cash', 1), + (3, 'Check', 1), + (4, 'Money Order', 1), + (5, 'ACH', 0), + (6, 'Debit Card', 0), + (7, 'Credit Card', 0), + (8, 'Other Tillable', 1), + (9, 'Other Non-Tillable', 0); UNLOCK TABLES; --- ---------------------------------------------------------------------- --- ---------------------------------------------------------------------- --- TABLE pmgr_payments - -DROP TABLE IF EXISTS `pmgr_payments`; -CREATE TABLE `pmgr_payments` ( - `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - - `receipt_id` INT(10) UNSIGNED NOT NULL, - `payment_type_id` INT(10) UNSIGNED NOT NULL, - `amount` FLOAT(12,2) NOT NULL, - - `comment` VARCHAR(255) DEFAULT NULL, - - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - - - --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ## --- ## CREDITS --- ## - - --- ---------------------------------------------------------------------- --- ---------------------------------------------------------------------- --- TABLE pmgr_credit_types - --- DROP TABLE IF EXISTS `pmgr_credit_types`; --- CREATE TABLE `pmgr_credit_types` ( --- `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - --- `name` VARCHAR(80) NOT NULL, --- `comment` VARCHAR(255) DEFAULT NULL, --- `account_id` INT(10) UNSIGNED NOT NULL, -- quickbooks tracking - --- PRIMARY KEY (`id`) --- ) ENGINE=MyISAM DEFAULT CHARSET=utf8; - --- LOCK TABLES `pmgr_credit_types` WRITE; --- INSERT INTO `pmgr_credit_types` (`id`, `name`, `account_id`) --- VALUES --- (1, 'Security Deposit', 0), --- (2, 'Rent', 0), --- (3, 'Late Credit', 0); --- UNLOCK TABLES; - - --- ---------------------------------------------------------------------- --- ---------------------------------------------------------------------- --- TABLE pmgr_credits - -DROP TABLE IF EXISTS `pmgr_credits`; -CREATE TABLE `pmgr_credits` ( - `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - - -- `credit_type_id` INT(10) UNSIGNED NOT NULL, - `lease_id` INT(10) UNSIGNED NOT NULL, - `credit_date` DATE NOT NULL, - `credit_to_date` DATE DEFAULT NULL, - `due_date` DATE DEFAULT NULL, - `amount` FLOAT(12,2) NOT NULL, - `tax` FLOAT(12,2) NOT NULL, - `total` FLOAT(12,2) NOT NULL, - `comment` VARCHAR(255) DEFAULT NULL, - - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - - --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ###################################################################### --- ## --- ## RECEIPTS --- ## - --- # Charge --- # - Issued against customer lease --- # - associated with account (i.e. QuickBooks account / category) --- # Receipt --- # - Collections of payments paid at one time --- # Payment --- # - Credited towards customer (or lease?) --- # - may be more than customer owes --- # - cash/check/charge/ach/etc --- # Reconciliation --- # - Associates a payment with the charge --- # - Indicates amount of credit towards charge --- # - Payments may cover several charges --- # - Several payments may cover the same charge - - --- Which charges haven not been paid? --- SELECT C.id AS cid, C.total AS total, COALESCE(SUM(R.amount),0) AS paid --- FROM pmgr_charges C --- LEFT JOIN pmgr_charges_receipts R ON R.charge_id = C.id --- GROUP BY C.id --- HAVING paid < C.total - --- SELECT ChL.lid AS lid, U.name, C.display_name, --- SUM(ChL.total) AS total, SUM(ChL.paid) AS paid, --- SUM(ChL.total) - SUM(ChL.paid) AS owing --- FROM (SELECT Ch.lease_id AS lid, Ch.total AS total, COALESCE(SUM(R.amount),0) AS paid --- FROM pmgr_charges Ch --- LEFT JOIN pmgr_charges_receipts R ON R.charge_id = Ch.id --- WHERE Ch.due_date < NOW() --- GROUP BY Ch.id --- HAVING paid < Ch.total) ChL --- LEFT JOIN pmgr_leases L ON L.id = ChL.lid --- LEFT JOIN pmgr_lease_contacts Lc ON Lc.lease_id = L.id AND Lc.type = 'TENANT' --- LEFT JOIN pmgr_contacts C ON C.id = Lc.contact_id --- LEFT JOIN pmgr_units U ON U.id = L.unit_id - - --- ---------------------------------------------------------------------- --- ---------------------------------------------------------------------- --- TABLE pmgr_receipts - -DROP TABLE IF EXISTS `pmgr_receipts`; -CREATE TABLE `pmgr_receipts` ( - `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - - `comment` VARCHAR(255) DEFAULT NULL, - - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - - --- ---------------------------------------------------------------------- --- ---------------------------------------------------------------------- --- TABLE pmgr_charges_receipts - -DROP TABLE IF EXISTS `pmgr_charges_receipts`; -CREATE TABLE `pmgr_charges_receipts` ( - `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `charge_id` INT(10) UNSIGNED NOT NULL, - -- REVISIT : 20090514 - -- THIS SHOULD BE RECEIPT_ID, NOT PAYMENT_ID, RIGHT?? - `receipt_id` INT(10) UNSIGNED NOT NULL, - `amount` FLOAT(12,2) NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -- ###################################################################### diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 3d331b5..3badbf2 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -26,9 +26,12 @@ my($hostname, $database, $user, $password) = ('localhost', 'pmgr', 'pmgruser'); my $db_handle = DBI->connect("DBI:mysql:database=$database;host=$hostname", $user, $password, - {'RaiseError' => 1}); + {'PrintError' => 1, + 'RaiseError' => 0}); +$SIG{__DIE__} = \&Die; + my ($query, $result, $nrows, $row); my ($aicur_c_id, $aicur_ca_id, $aicur_cp_id, $aicur_ce_id) = (0, 0, 0, 0); my ($aicur_g_id, $aicur_gp_id, $aicur_user_id) = (0, 0, 0); @@ -36,6 +39,9 @@ my ($aicur_type_id, $aicur_size_id, $aicur_unit_id) = (0, 0, 0); my ($aicur_site_id, $aicur_area_id) = (0, 0); my ($aicur_lease_type_id, $aicur_lease_id) = (0, 0); my ($aicur_charge_id, $aicur_receipt_id, $aicur_payment_id) = (0, 0, 0); +my ($aicur_tx_id) = (0); +my ($aicur_ledger_id) = (0); +my ($aicur_monetary_source_id) = (0); open(SCHEMA, "<$schema_file") || die ("Can't open schema ($!)\n"); my $schema_query = ""; @@ -224,14 +230,93 @@ $query = "INSERT INTO pmgr_lease_types query($db_handle, $query) || die("Unable to insert"); +my (%account_map, %monetary_type_map); +$query = "SELECT * FROM pmgr_accounts"; +$result = query($db_handle, $query); +foreach $row (@$result) { + ++$aicur_ledger_id; + $query = "INSERT INTO pmgr_ledgers + (`id`, `account_id`, `name`, `comment`) VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($aicur_ledger_id, $row->{'id'}, + $row->{'name'} . ' Ledger', undef) + )) . ")"; + query($db_handle, $query) || die("Unable to insert"); + $account_map{$row->{'name'}} = {'id' => $row->{'id'}, + 'ledger' => $aicur_ledger_id }; +} + +# $query = +# "UPDATE pmgr_accounts A, pmgr_ledgers L SET A.ledger_id = L.id" . +# " WHERE A.id = L.account_id"; +# query($db_handle, $query); + + +$query = "SELECT * FROM pmgr_monetary_types"; +$result = query($db_handle, $query); +foreach $row (@$result) { + $monetary_type_map{$row->{'name'}} = {'id' => $row->{'id'}, 'name' => $row->{'name'}}; +} + +$account_map{'Late Fee'} = $account_map{'Late Charge'}; + +$monetary_type_map{1} = $monetary_type_map{'Cash'}; +$monetary_type_map{2} = $monetary_type_map{'Check'}; +$monetary_type_map{3} = $monetary_type_map{'Money Order'}; +$monetary_type_map{4} = $monetary_type_map{'ACH'}; +$monetary_type_map{12} = $monetary_type_map{'Other Non-Tillable'}; + +my $monetary_source_internal = undef; + +my $monetary_source_cash = ++$aicur_monetary_source_id; +$query = "INSERT INTO pmgr_monetary_sources + (`id`, `monetary_type_id`, `name`, `comment`) VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($monetary_source_cash, + $monetary_type_map{'Cash'}{'id'}, + 'Cash Source', + 'Monetary source used for any cash transaction') + )) . ")"; +query($db_handle, $query) || die("Unable to insert"); + +my $monetary_source_closing = ++$aicur_monetary_source_id; +$query = "INSERT INTO pmgr_monetary_sources + (`id`, `monetary_type_id`, `name`, `comment`) VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($monetary_source_closing, + $monetary_type_map{'Other Non-Tillable'}{'id'}, + 'Closing Monies Credited', + 'Credited at the closing table') + )) . ")"; +query($db_handle, $query) || die("Unable to insert"); + + +###################################################################### +###################################################################### +## Die + +sub Die { + my @text = @_; + warn "----------------------------------------------------------\n"; + warn "FATAL ERROR: @text\n"; + my $count = 0; + { + my ($package, $filename, $line, $sub) = caller($count); + last unless defined $line; + warn sprintf("%02i %5i %-35s %-20s\n", $count++, $line, $sub, + $filename); + redo; + } + exit 1; +} ###################################################################### ###################################################################### ## query sub query { - my ($dbh, $sql) = @_; + my ($dbh, $sql, $data, $ignore) = @_; #print("$sql\n\n"); #return [ { 'id' => 7 } ]; #print("$sql\n\n") if $sql =~ /^\s*UPDATE/i; #return 1 unless $sql =~ /^\s*SELECT/i; @@ -245,8 +330,13 @@ sub query { $result = $dbh->do($sql); } - #print("sth = " . Dumper($sth) . "\n"); - #print("result = " . Dumper($result) . "\n"); + if (!$result && !$ignore) { + print "SQL Query FAILED:\n"; + print "$query\n\n"; + print Dumper $data + if defined $data; + die; + } return ($sth, $result); } @@ -292,7 +382,7 @@ foreach $row (@$result) { (`id`, `code`, `name`) VALUES ($row->{'TypeID'}, 'xxx', '$row->{'UnitType'}')"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); } @@ -323,7 +413,7 @@ foreach $row (@$result) { $internal_adjustment_factor * $row->{'Depth'}, $row->{'StdSecDep'}, $row->{'StdRent'}) )) . ")"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); } @@ -347,7 +437,7 @@ foreach $row (@$result) { $row->{'Rented'} ?'OCCUPIED' :($row->{'Rentable'} ?'VACANT' :'UNAVAILABLE'), $uid, $uid, $row->{'StdSecDep'}, $row->{'StdRent'}) )) . ")"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); } @@ -380,7 +470,7 @@ $query = " (1, 'Main Facility Map', $aicur_area_id," . ($info{'extents'}{'right'} - $info{'extents'}{'left'}) . ", " . ($info{'extents'}{'bottom'} - $info{'extents'}{'top'}) . ")"; -query($db_handle, $query) || die("Unable to insert"); +query($db_handle, $query, \%info); # Get list of units and positions $query = "SELECT U.UnitID, U.UnitID as name,"; @@ -405,7 +495,7 @@ foreach $row (@$result) { $internal_adjustment_factor * ($row->{'pt_t'}), $internal_adjustment_factor * ($row->{'pt_l'}), $row->{'reverseWL'}) . ")"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); } @@ -431,8 +521,12 @@ print(" $nrows Tenants\n"); my %stmap = ( 1=>'AK', 14=>'ID', 48=>'WA' ); my (%tenant_map); foreach $row (@$result) { - $tenant_map{$row->{'TenantID'}} = { 'id' => ++$aicur_c_id }; - my $cid = $tenant_map{$row->{'TenantID'}}{'id'}; + $tenant_map{$row->{'TenantID'}} = { 'cid' => ++$aicur_c_id }; + my $cid = $tenant_map{$row->{'TenantID'}}{'cid'}; + $tenant_map{$row->{'TenantID'}}{'custid'} = $cid; + my $custid = $tenant_map{$row->{'TenantID'}}{'custid'}; + + $tenant_map{$row->{'TenantID'}}{'name'} = "$row->{'LastName'}, $row->{'FirstName'}"; $query = "INSERT INTO pmgr_contacts (`id`, `first_name`, `middle_name`, `last_name`, `display_name`, `id_local`, `id_local_state`) @@ -442,7 +536,23 @@ foreach $row (@$result) { "$row->{'LastName'}, $row->{'FirstName'}", $row->{'IDNum'} || undef, $row->{'IDNum'} ? $stmap{$row->{'DLStateID'}} : undef) )) . ")"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); + + $query = "INSERT INTO pmgr_customers + (`id`, `name`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($custid, "$row->{'LastName'}, $row->{'FirstName'}") + )) . ")"; + query($db_handle, $query, $row); + + $query = "INSERT INTO pmgr_contacts_customers + (`customer_id`, `contact_id`, `type`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($custid, $cid, 'TENANT') + )) . ")"; + query($db_handle, $query, $row); if ($row->{'City'}) { $query = "INSERT INTO pmgr_contact_addresses @@ -454,12 +564,12 @@ foreach $row (@$result) { $row->{'HomeAddress'} . ($row->{'HomeAddr2'} ? "\n".$row->{'HomeAddr2'} : "") || undef, $row->{'City'}, $stmap{$row->{'StateID'}}, $row->{'Zip'} || undef, 'USA') )) . ")"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); $query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES ($cid, 'POST', $aicur_ca_id, 'HOME', 'PRIMARY')"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); } foreach ({'type' => 'LANDLINE', 'preference' => 'PRIMARY', 'phone' => $row->{'Phone'}}, @@ -475,14 +585,14 @@ foreach $row (@$result) { join(", ", map({defined $_ ? "'$_'" : "NULL"} (++$aicur_cp_id, $_->{'type'}, $_->{'phone'}, $_->{'ext'}))) . ")"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); $query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} ($cid, 'PHONE', $aicur_cp_id, 'MAIN', $_->{'preference'}))) . ")"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); } } @@ -490,12 +600,12 @@ foreach $row (@$result) { $query = "INSERT INTO pmgr_contact_emails (`id`, `email`) VALUES (".++$aicur_ce_id.", '$row->{'Email'}')"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); $query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUE ($cid, 'EMAIL', $aicur_ce_id, 'MAIN', 'PRIMARY')"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); } next unless $row->{'AltFirstName'} || $row->{'AltLastName'} || $row->{'AltAddress'} || $row->{'AltPhone'}; @@ -515,7 +625,15 @@ foreach $row (@$result) { ? "$row->{'AltLastName'}, $row->{'AltFirstName'}" : ($row->{'AltLastName'} || $row->{'AltFirstName'} || undef))) )) . ")"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); + + $query = "INSERT INTO pmgr_contacts_customers + (`customer_id`, `contact_id`, `type`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($custid, $cid, 'ALTERNATE') + )) . ")"; + query($db_handle, $query, $row); if ($row->{'AltCity'}) { $query = "INSERT INTO pmgr_contact_addresses @@ -526,12 +644,12 @@ foreach $row (@$result) { $row->{'AltAddress'} . ($row->{'AltAddr2'} ? "\n".$row->{'AltAddr2'} : ""), $row->{'AltCity'}, $stmap{$row->{'AltStateID'}}, $row->{'AltZip'}, 'USA') )) . ")"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); $query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES ($cid, 'POST', $aicur_ca_id, 'MAIN', 'PRIMARY')"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); } if ($row->{'AltPhone'}) { @@ -540,12 +658,12 @@ foreach $row (@$result) { join(", ", map({defined $_ ? "'$_'" : "NULL"} (++$aicur_cp_id, 'LANDLINE', $row->{'AltPhone'}, undef) )) . ")"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); $query = "INSERT INTO pmgr_contacts_methods (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES ($cid, 'PHONE', $aicur_cp_id, 'MAIN', 'PRIMARY')"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); } } @@ -559,45 +677,33 @@ $nrows = @$result; print(" $nrows Tenant Ledgers\n"); my (%ledger_map); foreach $row (@$result) { - $ledger_map{$row->{'LedgerID'}} = ++$aicur_lease_id; - my $cid = $tenant_map{$row->{'TenantID'}}{'id'}; + $ledger_map{$row->{'LedgerID'}} = { 'lid' => ++$aicur_lease_id }; + my $cid = $tenant_map{$row->{'TenantID'}}{'cid'}; my $uid = $unit_map{$row->{'UnitID'}}; - my $lid = $ledger_map{$row->{'LedgerID'}}; + my $lid = $ledger_map{$row->{'LedgerID'}}{'lid'}; + my $custid = $tenant_map{$row->{'TenantID'}}{'custid'}; + $ledger_map{$row->{'LedgerID'}}{'custid'} = $custid; $query = "INSERT INTO pmgr_leases - (`id`, `number`, `lease_type_id`, `unit_id`, + (`id`, `number`, `lease_type_id`, `unit_id`, `customer_id`, `lease_date`, `movein_date`, `moveout_date`, `close_date`, `amount`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($lid, $row->{'LedgerID'}, $aicur_lease_type_id, $uid, + ($lid, $row->{'LedgerID'}, $aicur_lease_type_id, $uid, $custid, datefmt($row->{'DateIn'}), datefmt($row->{'DateIn'}), datefmt($row->{'DateOut'}), datefmt($row->{'DateClosed'}), $row->{'Rent'}) )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $query = "INSERT INTO pmgr_contacts_leases - (`lease_id`, `contact_id`, `type`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($lid, $cid, 'TENANT') - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $cid = $tenant_map{$row->{'TenantID'}}{'alt'}; - next unless $cid; - - $query = "INSERT INTO pmgr_contacts_leases - (`lease_id`, `contact_id`, `type`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($lid, $cid, 'ALTERNATE') - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); } +$query = "UPDATE pmgr_units U, pmgr_leases L + SET U.`current_lease_id` = L.id + WHERE L.unit_id = U.id AND L.close_date IS NULL"; +query($db_handle, $query); + ###################################################################### ## Security Deposits @@ -612,7 +718,7 @@ foreach $row (@$result) { $query = "UPDATE pmgr_leases SET deposit = $row->{'ChargeAmount'} WHERE `number` = '$row->{'LedgerID'}'"; - query($db_handle, $query) || die("Unable to update"); + query($db_handle, $query, $row); } @@ -634,69 +740,116 @@ $result = query($sdbh, $query); $nrows = @$result; print(" $nrows Charges\n"); -my %charge_type_map = ('Rent' => 2, 'Security Deposit' => 1, 'Late Fee' => 3); my %charge_map; foreach $row (@$result) { - $charge_map{$row->{'ChargeID'}} = ++$aicur_charge_id; - my $lid = $ledger_map{$row->{'LedgerID'}}; + $charge_map{$row->{'ChargeID'}} = ++$aicur_tx_id; + my $lid = $ledger_map{$row->{'LedgerID'}}{'lid'}; my $chid = $charge_map{$row->{'ChargeID'}}; + my $custid = $ledger_map{$row->{'LedgerID'}}{'custid'}; + - $query = "INSERT INTO pmgr_charges - (`id`, `charge_type_id`, `lease_id`, - `charge_date`, `charge_to_date`, - `amount`, `tax`, `total`, `comment`) + $query = "INSERT INTO pmgr_transactions + (`id`, + `stamp`, `through_date`, + `customer_id`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($chid, $charge_type_map{$row->{'ChargeDescription'}}, $lid, + ($chid, datefmt($row->{'ChargeDate'}), datefmt($row->{'EndDate'}), - $row->{'ChargeAmount'}, $row->{'TaxAmount'}, - $row->{'ChargeAmount'} + $row->{'TaxAmount'}, - undef) + $custid) )) . ")"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); - $query = "UPDATE pmgr_charges"; - $query .= " SET due_date = DATE_ADD(charge_date, INTERVAL IF(charge_type_id=2,10,0) DAY)"; - query($db_handle, $query) || die("Unable to update"); + $query = "INSERT INTO pmgr_ledger_entries + (`monetary_source_id`, `transaction_id`, + `debit_ledger_id`, + `credit_ledger_id`, + `amount`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($monetary_source_internal, $chid, + $account_map{'A/R'}{'ledger'}, + $account_map{$row->{'ChargeDescription'}}{'ledger'}, + $row->{'ChargeAmount'}, "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}") + )) . ")"; + query($db_handle, $query, $row); + + next unless $row->{'TaxAmount'}; + + $query = "INSERT INTO pmgr_ledger_entries + (`monetary_source_id`, `transaction_id`, + `debit_ledger_id`, + `credit_ledger_id`, + `amount`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($monetary_source_internal, $chid, + $account_map{'A/R'}{'ledger'}, + $account_map{'Tax'}{'ledger'}, + $row->{'TaxAmount'}, undef) + )) . ")"; + query($db_handle, $query, $row); + + +# $query = "UPDATE pmgr_charges"; +# $query .= " SET due_date = DATE_ADD(charge_date, INTERVAL IF(account_id=2,10,0) DAY)"; +# query($db_handle, $query); } ###################################################################### ## Receipts -$query = "SELECT * FROM Receipts ORDER BY ReceiptNum"; +#$query = "SELECT * FROM Receipts ORDER BY ReceiptNum"; +$query = + "SELECT R.ReceiptNum, C.LedgerID, R.ReceiptDate" . + " FROM Receipts R, Payments P, Charges C" . + " WHERE P.ReceiptNum = R.ReceiptNum" . + " AND C.ChargeID = P.ChargeID" . + " GROUP BY R.ReceiptNum, C.LedgerID, R.ReceiptDate" . + " ORDER BY R.ReceiptNum"; $result = query($sdbh, $query); $nrows = @$result; print(" $nrows Receipts\n"); my %receipt_map; foreach $row (@$result) { - $receipt_map{$row->{'ReceiptNum'}} = ++$aicur_receipt_id; - my $lid = $ledger_map{$row->{'LedgerID'}}; - my $rid = $receipt_map{$row->{'ReceiptNum'}}; + #print Dumper $row; + my $lid = $ledger_map{$row->{'LedgerID'}}{'lid'}; + my $custid = $ledger_map{$row->{'LedgerID'}}{'custid'}; - $query = "INSERT INTO pmgr_receipts - (`id`, `stamp`, `comment`) + if ($receipt_map{$row->{'ReceiptNum'}}) { + die unless $receipt_map{$row->{'ReceiptNum'}}{'cust'} == $custid; + push(@{$receipt_map{$row->{'ReceiptNum'}}{'lid'}}, $lid); + #print Dumper $receipt_map{$row->{'ReceiptNum'}}; + next; + } + + $receipt_map{$row->{'ReceiptNum'}} = { 'id' => ++$aicur_tx_id, 'cust' => $custid, 'lid' => [$lid] }; + my $rid = $receipt_map{$row->{'ReceiptNum'}}{'id'}; + #print Dumper $receipt_map{$row->{'ReceiptNum'}}; + + $query = "INSERT INTO pmgr_transactions + (`id`, + `stamp`, `through_date`, + `customer_id`) VALUES (" . join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($rid, datefmt($row->{'ReceiptDate'}), undef) + ($rid, + datefmt($row->{'ReceiptDate'}), undef, + $custid) )) . ")"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query, $row); } -# $query = "SELECT * FROM Receipts R INNER JOIN Payments P ON P.ReceiptNum = R.ReceiptNum" . -# " WHERE P.PaymentDate <> R.ReceiptDate"; -# $result = query($sdbh, $query); -# $nrows = @$result; -# print(" $nrows Mismatches\n"); -# foreach $row (@$result) { -# my @keys = qw(PaymentID P.ReceiptNum PaymentDate ReceiptDate); -# print("Payment Date Mismatch:\n"); -# print(" ", -# join("\n ", map({sprintf("%-12s => %s", $_, $row->{$_})} @keys)), -# "\n"); -# } +# sub idkeys { [ sort( {$a <=> $b} keys(%{$_[0]})) ] } +# $Data::Dumper::Sortkeys = \&idkeys; +# print("Tenant\n"); print Dumper \%tenant_map; +# print("Ledger\n"); print Dumper \%ledger_map; +# print("Charge\n"); print Dumper \%charge_map; +# print("Receipt\n"); print Dumper \%receipt_map; + ###################################################################### ## Payments @@ -710,274 +863,254 @@ my %payment_map; foreach $row (@$result) { $payment_map{$row->{'PaymentID'}} = ++$aicur_payment_id; my $pid = $payment_map{$row->{'PaymentID'}}; - my $rid = $receipt_map{$row->{'ReceiptNum'}}; + my $rid = $receipt_map{$row->{'ReceiptNum'}}{'id'}; my $chid = $charge_map{$row->{'ChargeID'}}; - $query = "INSERT INTO pmgr_payments - (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($pid, $rid, - $row->{'PaymentDate'} =~ m%3/25/2009% ? 8 : $row->{'PaymentType'}, - $row->{'PaymentAmount'}, undef) + my $monetary_source_id; + if ($row->{'PaymentDate'} =~ m%3/25/2009%) { + $monetary_source_id = $monetary_source_closing; + } + elsif ($monetary_type_map{$row->{'PaymentType'}}{'name'} eq 'Cash') { + $monetary_source_id = $monetary_source_cash; + } + else { + $monetary_source_id = ++$aicur_monetary_source_id; + $query = "INSERT INTO pmgr_monetary_sources + (`id`, `monetary_type_id`, `name`, `comment`) VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($monetary_source_id, + $monetary_type_map{$row->{'PaymentType'}}{'id'}, + $row->{'RecdFrom'}, + "Payment: $row->{'PaymentID'}; Type: $row->{'PaymentType'}; Check: $row->{'CheckNum'}; $row->{'Memo'}") )) . ")"; - query($db_handle, $query) || die("Unable to insert"); + query($db_handle, $query) || die("Unable to insert"); + } - $query = "INSERT INTO pmgr_charges_receipts - (`charge_id`, `receipt_id`, `amount`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($chid, $rid, $row->{'PaymentAmount'}) - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); + $query = "INSERT INTO pmgr_ledger_entries + (`monetary_source_id`, + `transaction_id`, + `debit_ledger_id`, + `credit_ledger_id`, + `amount`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($monetary_source_id, + $rid, + $account_map{'Cash'}{'ledger'}, + $account_map{'A/R'}{'ledger'}, + $row->{'PaymentAmount'}, + "Receipt: $row->{'ReceiptNum'}; Payment: $row->{'PaymentID'}; Charge: $row->{'ChargeID'}") + )) . ")"; + query($db_handle, $query, $row); if ($row->{'Memo'}) { $query = - "UPDATE pmgr_receipts SET `comment` = '$row->{'Memo'}'" . + "UPDATE pmgr_transactions SET `comment` = '$row->{'Memo'}'" . " WHERE `id` = $rid"; - query($db_handle, $query) || die("Unable to update"); + query($db_handle, $query, $row); } } - - $query = "INSERT INTO pmgr_charges - (`id`, `charge_type_id`, `lease_id`, - `charge_date`, `charge_to_date`, - `amount`, `tax`, `total`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (1000, $charge_type_map{'Security Deposit'}, 17, - '2009-05-05', undef, - 10, 0, 10, - 'Fake security deposit for testing purposes') - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $query = "INSERT INTO pmgr_charges - (`id`, `charge_type_id`, `lease_id`, - `charge_date`, `charge_to_date`, - `amount`, `tax`, `total`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (1001, $charge_type_map{'Rent'}, 17, - '2009-05-01', '2009-05-31', - 100, 5, 105, - 'Fake charge for testing purposes') - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $query = "INSERT INTO pmgr_charges - (`id`, `charge_type_id`, `lease_id`, - `charge_date`, `charge_to_date`, - `amount`, `tax`, `total`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (1002, $charge_type_map{'Late Fee'}, 17, - '2009-05-11', undef, - 25, 0, 25, - 'Fake late charge for testing purposes') - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $query = "INSERT INTO pmgr_receipts - (`id`, `stamp`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (2000, '2009-05-15', 'Fake receipt #1') - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $query = "INSERT INTO pmgr_payments - (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (3000, 2000, 1, 15, 'Fake receipt #1 payment #1') - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $query = "INSERT INTO pmgr_payments - (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (3001, 2000, 2, 10, 'Fake receipt #1 payment #2') - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $query = "INSERT INTO pmgr_payments - (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (3002, 2000, 3, 5, 'Fake receipt #1 payment #3') - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $query = "INSERT INTO pmgr_charges_receipts - (`charge_id`, `receipt_id`, `amount`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (1000, 2000, 10) - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $query = "INSERT INTO pmgr_charges_receipts - (`charge_id`, `receipt_id`, `amount`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (1001, 2000, 20) - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - - $query = "INSERT INTO pmgr_receipts - (`id`, `stamp`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (2100, '2009-05-18', 'Fake receipt #2') - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $query = "INSERT INTO pmgr_payments - (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (3100, 2100, 5, 30, 'Fake receipt #2 payment #1') - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $query = "INSERT INTO pmgr_payments - (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (3101, 2100, 6, 20, 'Fake receipt #2 payment #2') - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $query = "INSERT INTO pmgr_charges_receipts - (`charge_id`, `receipt_id`, `amount`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (1001, 2100, 50) - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - - $query = "INSERT INTO pmgr_receipts - (`id`, `stamp`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (2200, '2009-05-22', 'Fake receipt #3') - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $query = "INSERT INTO pmgr_payments - (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (3200, 2200, 1, 10, 'Fake receipt #3 payment #1') - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $query = "INSERT INTO pmgr_payments - (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (3201, 2200, 2, 5, 'Fake receipt #3 payment #2') - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $query = "INSERT INTO pmgr_payments - (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (3202, 2200, 7, 20, 'Fake receipt #3 payment #3') - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $query = "INSERT INTO pmgr_payments - (`id`, `receipt_id`, `payment_type_id`, `amount`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (3203, 2200, 8, 15, 'Fake receipt #3 payment #4') - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $query = "INSERT INTO pmgr_charges_receipts - (`charge_id`, `receipt_id`, `amount`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (1001, 2200, 35) - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - $query = "INSERT INTO pmgr_charges_receipts - (`charge_id`, `receipt_id`, `amount`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (1002, 2200, 15) - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - - -__END__ - ###################################################################### -## Reconciliations +## Fake Data for Testing -# $query = "SELECT ReceiptNum, SUM(PaymentAmount) AS 'rTot'"; -# $query .= " FROM Payments GROUP BY ReceiptNum, ORDER BY ReceiptNum"; -$query = "SELECT ChargeID, ReceiptNum"; -$query .= " FROM Payments GROUP BY ChargeID, ReceiptNum ORDER BY ChargeID, ReceiptNum"; -$result = query($sdbh, $query); -$nrows = @$result; -print(" $nrows Reconciliations\n"); +my %fake = + ('custid' => 2, + 'invoice' => [ { 'id' => 1000, + 'date' => '2009-05-05', + 'entry' => [ { 'id' => 2100, + 'account' => 'Security Deposit', + 'amount' => 10, + 'tax' => 0 }, + ], + }, + { 'id' => 1001, + 'date' => '2009-05-01', + 'thru' => '2009-05-31', + 'entry' => [ { 'id' => 2110, + 'account' => 'Rent', + 'amount' => 100, + 'tax' => 5 }, + ], + }, + { 'id' => 1002, + 'date' => '2009-05-11', + 'entry' => [ { 'id' => 2120, + 'account' => 'Late Fee', + 'amount' => 25, + 'tax' => 0 }, + ], + }, + ], + 'receipt' => [ { 'id' => 2000, + 'date' => '2009-05-15', + 'entry' => [ { 'id' => 2200, + 'type' => 1, + 'amount' => 15 }, + { 'id' => 2201, + 'type' => 2, + 'amount' => 10 }, + { 'id' => 2202, + 'type' => 3, + 'amount' => 5 }, + ], + }, + { 'id' => 2001, + 'date' => '2009-05-18', + 'entry' => [ { 'id' => 2210, + 'type' => 5, + 'amount' => 30 }, + { 'id' => 2211, + 'type' => 6, + 'amount' => 20 }, + ], + }, + { 'id' => 2002, + 'date' => '2009-05-22', + 'entry' => [ { 'id' => 2220, + 'type' => 1, + 'amount' => 10 }, + { 'id' => 2221, + 'type' => 2, + 'amount' => 5 }, + { 'id' => 2222, + 'type' => 7, + 'amount' => 20 }, + { 'id' => 2223, + 'type' => 8, + 'amount' => 15 }, + ], + }, + ], -foreach $row (@$result) { - my $chid = $charge_map{$row->{'ChargeID'}}; - my $rid = $receipt_map{$row->{'ReceiptNum'}}; + ); - $query = "INSERT INTO pmgr_charges_receipts - (`charge_id`, `receipt_id`, `amount`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($chid, $rid, 0) - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); +my $old_cash_ledger = $account_map{'Cash'}{'ledger'}; +my $new_cash_ledger = ++$aicur_ledger_id; +$account_map{'Cash'}{'ledger'} = $new_cash_ledger; +$query = "INSERT INTO pmgr_ledgers + (`id`, `account_id`, `name`, `comment`) VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($new_cash_ledger, $account_map{'Cash'}{'id'}, + 'Fake Cash Ledger', 'Fake ledger for testing') + )) . ")"; +query($db_handle, $query) || die("Unable to insert"); + +$query = +"SELECT + SUM(IF(LedgerEntry.debit_ledger_id = Ledger.id, LedgerEntry.amount, 0)) AS debits, + SUM(IF(LedgerEntry.credit_ledger_id = Ledger.id, LedgerEntry.amount, 0)) AS credits, + SUM(IF(Account.type IN ('ASSET', 'EXPENSE'), + IF(LedgerEntry.debit_ledger_id = Ledger.id, 1, -1), + IF(LedgerEntry.credit_ledger_id = Ledger.id, 1, -1) ) + * LedgerEntry.amount) AS balance, + COUNT(`LedgerEntry`.`id`) AS entries +FROM + `pmgr_ledgers` AS `Ledger` + LEFT JOIN `pmgr_accounts` AS `Account` + ON (`Account`.`id` = `Ledger`.`account_id`) + LEFT JOIN `pmgr_ledger_entries` AS `LedgerEntry` + ON (((`LedgerEntry`.`debit_ledger_id` = Ledger.id) + OR (`LedgerEntry`.`credit_ledger_id` = Ledger.id))) +WHERE `Ledger`.`id` = $old_cash_ledger +GROUP BY `Ledger`.`id` LIMIT 1"; +$result = query($db_handle, $query); +my $balance = $result->[0]{'balance'}; + +$query = "INSERT INTO pmgr_transactions + (`id`, `customer_id`, `stamp`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (++$aicur_tx_id, 0, + '2009-05-10') + )) . ")"; +query($db_handle, $query); + +$query = "INSERT INTO pmgr_ledger_entries + (`monetary_source_id`, `transaction_id`, + `debit_ledger_id`, + `credit_ledger_id`, + `amount`, + `name`, + `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($monetary_source_internal, $aicur_tx_id, + $new_cash_ledger, + $old_cash_ledger, + $balance, + "Close Out ($old_cash_ledger -> $new_cash_ledger)", + "Carrying forward old ledger balance onto new ledger") + )) . ")"; +query($db_handle, $query); + +$query = + "UPDATE pmgr_ledgers SET `closed` = 1" . + " WHERE `id` = $old_cash_ledger"; +query($db_handle, $query); + + +# my $monetary_source_cash = ++$aicur_monetary_source_id; +# $query = "INSERT INTO pmgr_monetary_sources +# (`id`, `monetary_type_id`, `name`, `comment`) VALUES (" . +# join(", ", map({defined $_ ? "'$_'" : "NULL"} +# ($monetary_source_cash, +# $monetary_type_map{'Cash'}{'id'}, +# 'Fake Cash Source', +# 'Fake source used for testing') +# )) . ")"; +# query($db_handle, $query) || die("Unable to insert"); + +foreach my $ir ('invoice', 'receipt') { + foreach my $tx (@{$fake{$ir}}) { + #print Dumper ${%$tx{'date'}}; + #exit; + $query = "INSERT INTO pmgr_transactions + (`id`, `stamp`, `through_date`, `customer_id`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + (@{$tx}{'id', 'date', 'thru'}, $fake{'custid'}, "Fake $ir") + )) . ")"; + query($db_handle, $query, $tx); + + foreach my $e (@{$tx->{'entry'}}) { + my $dr = ($ir eq 'invoice') ? $account_map{'A/R'} : $account_map{'Cash'}; + my $cr = ($ir eq 'invoice') ? $account_map{$e->{'account'}} : $account_map{'A/R'}; + + $query = "INSERT INTO pmgr_ledger_entries + (`id`, `monetary_source_id`, + `transaction_id`, + `debit_ledger_id`, + `credit_ledger_id`, + `amount`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($e->{'id'}, $e->{'type'} || $monetary_source_internal, + $tx->{'id'}, + $dr->{'ledger'}, + $cr->{'ledger'}, + $e->{'amount'}, "Fake $ir entry") + )) . ")"; + query($db_handle, $query, $e); + + next unless $e->{'tax'}; + + $query = "INSERT INTO pmgr_ledger_entries + (`id`, `monetary_source_id`, + `transaction_id`, + `debit_ledger_id`, + `credit_ledger_id`, + `amount`, `comment`) + VALUES (" . + join(", ", map({defined $_ ? "'$_'" : "NULL"} + ($e->{'id'}+1, $monetary_source_internal, + $tx->{'id'}, + $account_map{'A/R'}{'ledger'}, + $account_map{'Tax'}{'ledger'}, + $e->{'tax'}, "Fake Tax Charge") + )) . ")"; + query($db_handle, $query, $e); + } + } } - -$query ="UPDATE pmgr_charges_receipts R - JOIN (SELECT P.receipt_id AS rid, - IF(COALESCE(Ch.total, 0)disconnect(); - diff --git a/site/app_model.php b/site/app_model.php index 8914138..0f1bb9c 100644 --- a/site/app_model.php +++ b/site/app_model.php @@ -83,27 +83,51 @@ class AppModel extends Model { // a really large number of rows. However, trying to untagle this // without changing a bunch of core code is near impossible. - var $paginate_rows_save; - function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null, $extra = null) { + //var $paginate_rows_save; + function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null, &$extra = null) { /* pr("paginate"); */ /* pr(array_merge(compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive', 'extra'))); */ if ($page > 1 && isset($limit)) $offset = ($page - 1) * $limit; else $offset = 0; - return array_slice($this->paginate_rows_save, $offset, $limit); + + if (!isset($extra['results'])) + die("Why isn't results set!?!"); + + $results = $extra['results']; + unset($extra['results']); + return array_slice($results, $offset, $limit); } - function paginateCount($conditions = null, $recursive = null, $extra = null) { + function paginateCount($conditions = null, $recursive = null, &$extra = null) { /* pr("paginateCount"); */ -/* pr(array_merge(compact('conditions', 'recursive', 'extra'))); */ +/* pr(compact('conditions', 'recursive', 'extra')); */ - if (!isset($recursive)) - $recursive = $this->recursive; - $parameters = array_merge(compact('conditions', 'recursive'), $extra); - $results = $this->find('all', $parameters); + if (isset($extra['results'])) { + // Beauty! The results are already in! + // This happens if the user sets up a complex query + // and passes us the result to paginate. + $results = $extra['results']; + } + elseif (isset($extra['query'])) { + // Perform the query directly... forget all the find B.S. + $results = $this->query($extra['query']); + } + else { + if (!isset($recursive)) + $recursive = $this->recursive; - $this->paginate_rows_save = $results; - return count($this->paginate_rows_save); + $parameters = array_merge(compact('conditions', 'recursive'), $extra); + $results = $this->find('all', $parameters); + } + + //$this->paginate_rows_save = $results; + //return count($this->paginate_rows_save); + + if (!isset($extra['results'])) + $extra['results'] = $results; + + return count($results); } } diff --git a/site/controllers/accounts_controller.php b/site/controllers/accounts_controller.php new file mode 100644 index 0000000..1bb9c21 --- /dev/null +++ b/site/controllers/accounts_controller.php @@ -0,0 +1,265 @@ + 100, + 'link' => + array(// Models + 'CurrentLedger' => array + (// Models + 'LedgerEntry' => + array('fields' => + array('SUM(IF(LedgerEntry.debit_ledger_id = CurrentLedger.id, LedgerEntry.amount, 0)) AS debits', + 'SUM(IF(LedgerEntry.credit_ledger_id = CurrentLedger.id, LedgerEntry.amount, 0)) AS credits', + "SUM(IF(Account.type IN ('ASSET', 'EXPENSE'), + IF(LedgerEntry.debit_ledger_id = CurrentLedger.id, 1, -1), + IF(LedgerEntry.credit_ledger_id = CurrentLedger.id, 1, -1) + )* LedgerEntry.amount) AS balance", + 'COUNT(LedgerEntry.id) AS entries'), + 'conditions' => + array('OR' => + array('LedgerEntry.debit_ledger_id = CurrentLedger.id', + 'LedgerEntry.credit_ledger_id = CurrentLedger.id'), + ), + ), + ), + ), + 'group' => 'Account.id', + 'order' => array('Account.name' => 'ASC')); + + 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 + * - Lists all accounts + */ + + function index() { + $this->all(); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: asset + * - Lists all asset accounts + */ + + function asset() { + $title = 'Asset Accounts'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('accounts', $this->paginate(array('Account.type' => 'ASSET'))); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: liability + * - Lists all liability accounts + */ + + function liability() { + $title = 'Liability Accounts'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('accounts', $this->paginate(array('Account.type' => 'LIABILITY'))); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: equity + * - Lists all equity accounts + */ + + function equity() { + $title = 'Equity Accounts'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('accounts', $this->paginate(array('Account.type' => 'EQUITY'))); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: income + * - Lists all income accounts + */ + + function income() { + $title = 'Income Accounts'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('accounts', $this->paginate(array('Account.type' => 'INCOME'))); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: expense + * - Lists all expense accounts + */ + + function expense() { + $title = 'Expense Accounts'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('accounts', $this->paginate(array('Account.type' => 'EXPENSE'))); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: all + * - Lists all accounts + */ + + function all() { + $title = 'All Accounts'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('accounts', $this->paginate()); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: view + * - Displays information about a specific account + */ + + function view($id = null) { + if (!$id) { + $this->Session->setFlash(__('Invalid Item.', true)); + $this->redirect(array('action'=>'index')); + } + +/* $this->Account->bindModel(array('hasMany' => array */ +/* ('LedgerEntry' => array */ +/* ('className' => 'LedgerEntry', */ +/* 'foreignKey' => false, */ +/* 'finderQuery' => 'SELECT `LedgerEntry`.* */ +/* FROM pmgr_entries AS `LedgerEntry` */ +/* LEFT JOIN pmgr_transactions AS `Transaction` */ +/* ON `Transaction`.id = `LedgerEntry`.transaction_id */ +/* WHERE LedgerEntry.debit_ledger_id = ({$__cakeID__$}) */ +/* OR LedgerEntry.credit_ledger_id = ({$__cakeID__$}) */ +/* ORDER BY Transaction.stamp', */ +/* )))); */ + +/* $this->Account->Behaviors->attach('Containable'); */ +/* $this->Account->Contain(array('LedgerEntry' => array */ +/* ( */ +/* // Models */ +/* 'Transaction' => array */ +/* ( */ +/* // Models */ +/* 'Customer', */ +/* )), */ + +/* )); */ +/* } */ +/* $account = $this->Account->read(null, $id); */ + + + $this->Account->recursive = -1; + $account = $this->Account->read(null, $id); + + $account['Ledger'] = $this->Account->find + ('all', array + ('link' => array + (// Models + 'Ledger' => array + (// Models + 'LedgerEntry' => + array('fields' => + array('SUM(IF(LedgerEntry.debit_ledger_id = Ledger.id, LedgerEntry.amount, 0)) AS debits', + 'SUM(IF(LedgerEntry.credit_ledger_id = Ledger.id, LedgerEntry.amount, 0)) AS credits', + "SUM(IF(Account.type IN ('ASSET', 'EXPENSE'), + IF(LedgerEntry.debit_ledger_id = Ledger.id, 1, -1), + IF(LedgerEntry.credit_ledger_id = Ledger.id, 1, -1) + ) * LedgerEntry.amount) AS balance", + 'COUNT(LedgerEntry.id) AS entries'), + 'conditions' => + array('OR' => + array('LedgerEntry.debit_ledger_id = Ledger.id', + 'LedgerEntry.credit_ledger_id = Ledger.id'), + ), + ), + ), + ), + 'fields' => array(), + 'conditions' => array('Account.id' => $id), + 'order' => 'Ledger.name', + 'group' => 'Ledger.id', + 'limit' => 4, + )); + + + $account['CurrentLedger'] = array_shift($this->Account->Ledger->find + ('first', array + ('link' => array + (// Models + 'Account' => array('fields' => array()), + 'LedgerEntry' => + array('fields' => + array("SUM(IF(LedgerEntry.debit_ledger_id = Ledger.id, LedgerEntry.amount, 0)) AS debits", + "SUM(IF(LedgerEntry.credit_ledger_id = Ledger.id, LedgerEntry.amount, 0)) AS credits", + "SUM(IF(Account.type IN ('ASSET', 'EXPENSE'), + IF(LedgerEntry.debit_ledger_id = Ledger.id, 1, -1), + IF(LedgerEntry.credit_ledger_id = Ledger.id, 1, -1) + ) * LedgerEntry.amount) AS balance", + 'COUNT(LedgerEntry.id) AS entries'), + 'conditions' => + array('OR' => + array("LedgerEntry.debit_ledger_id = Ledger.id", + "LedgerEntry.credit_ledger_id = Ledger.id"), + ), + ), + ), + 'fields' => array(), + 'conditions' => array(array('Ledger.account_id' => $id), + 'NOT' => array('Ledger.closed')), + //'order' => 'Ledger.name', + 'group' => 'Ledger.id', + //'limit' => 4, + ))); + //pr($account); + + $balance = $account['CurrentLedger']['balance']; + $title = 'Account: ' . $account['Account']['name']; + $this->set(compact('account', 'title', 'balance')); + } +} diff --git a/site/controllers/accounts_controller.php.bak b/site/controllers/accounts_controller.php.bak new file mode 100644 index 0000000..237b95d --- /dev/null +++ b/site/controllers/accounts_controller.php.bak @@ -0,0 +1,244 @@ + 100, + 'link' => + array(// Models + 'CurrentLedger' => array + (// Models + 'LedgerEntry' => + array('fields' => + array('SUM(IF(LedgerEntry.debit_account_id = Account.id, LedgerEntry.amount, 0)) AS debits', + 'SUM(IF(LedgerEntry.credit_account_id = Account.id, LedgerEntry.amount, 0)) AS credits', + "SUM(IF(Account.type IN ('ASSET', 'EXPENSE'), + IF(LedgerEntry.debit_account_id = Account.id, 1, -1), + IF(LedgerEntry.credit_account_id = Account.id, 1, -1) + )* LedgerEntry.amount) AS balance", + 'COUNT(LedgerEntry.id) AS entries'), + 'conditions' => + array('OR' => + array('LedgerEntry.debit_account_id = Account.id', + 'LedgerEntry.credit_account_id = Account.id'), + ), + ), + ), + + 'group' => 'Account.id', + 'order' => array('Account.name' => 'ASC')); + + 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 + * - Lists all accounts + */ + + function index() { + $this->all(); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: asset + * - Lists all asset accounts + */ + + function asset() { + $title = 'Asset Accounts'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('accounts', $this->paginate(array('Account.type' => 'ASSET'))); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: liability + * - Lists all liability accounts + */ + + function liability() { + $title = 'Liability Accounts'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('accounts', $this->paginate(array('Account.type' => 'LIABILITY'))); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: equity + * - Lists all equity accounts + */ + + function equity() { + $title = 'Equity Accounts'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('accounts', $this->paginate(array('Account.type' => 'EQUITY'))); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: income + * - Lists all income accounts + */ + + function income() { + $title = 'Income Accounts'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('accounts', $this->paginate(array('Account.type' => 'INCOME'))); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: expense + * - Lists all expense accounts + */ + + function expense() { + $title = 'Expense Accounts'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('accounts', $this->paginate(array('Account.type' => 'EXPENSE'))); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: all + * - Lists all accounts + */ + + function all() { + $title = 'All Accounts'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('accounts', $this->paginate()); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: view + * - Displays information about a specific account + */ + + function view($id = null) { + if (!$id) { + $this->Session->setFlash(__('Invalid Item.', true)); + $this->redirect(array('action'=>'index')); + } + +/* $this->Account->bindModel(array('hasMany' => array */ +/* ('LedgerEntry' => array */ +/* ('className' => 'LedgerEntry', */ +/* 'foreignKey' => false, */ +/* 'finderQuery' => 'SELECT `LedgerEntry`.* */ +/* FROM pmgr_entries AS `LedgerEntry` */ +/* LEFT JOIN pmgr_transactions AS `Transaction` */ +/* ON `Transaction`.id = `LedgerEntry`.transaction_id */ +/* WHERE LedgerEntry.debit_account_id = ({$__cakeID__$}) */ +/* OR LedgerEntry.credit_account_id = ({$__cakeID__$}) */ +/* ORDER BY Transaction.stamp', */ +/* )))); */ + +/* $this->Account->Behaviors->attach('Containable'); */ +/* $this->Account->Contain(array('LedgerEntry' => array */ +/* ( */ +/* // Models */ +/* 'Transaction' => array */ +/* ( */ +/* // Models */ +/* 'Customer', */ +/* )), */ + +/* )); */ +/* } */ +/* $account = $this->Account->read(null, $id); */ + + $this->Account->recursive = -1; + $account = $this->Account->read(null, $id); + + if (in_array($account['Account']['type'], array('ASSET', 'EXPENSE'))) + $account_type = 'debit'; + else + $account_type = 'credit'; + + $ledger_id = $account['current_ledger_id']; + $account['CurrentLedger']['LedgerEntry'] = + $this->Account->Ledger->LedgerEntry->find + ('all', + array('link' => array + (// Models + 'fields' => + array('id', 'name', 'comment', + "IF(LedgerEntry.debit_ledger_id = $id, LedgerEntry.amount, NULL) AS debit", + "IF(LedgerEntry.credit_ledger_id = $id, LedgerEntry.amount, NULL) AS credit", + "(IF(LedgerEntry.{$account_type}_ledger_id = $id, 1, -1) + * LedgerEntry.amount) AS balance"), + 'conditions' => + array('OR' => + array('LedgerEntry.debit_ledger_id = Account.id', + 'LedgerEntry.credit_ledger_id = Account.id'), + + + 'Transaction' => + array(// Models + 'Customer', + )), + 'conditions' => array('OR' => + array("LedgerEntry.debit_account_id = $id", + "LedgerEntry.credit_account_id = $id")), + 'order' => array('Transaction.stamp'), + //'limit' => 15, + //'limit' => 2, + )); + //pr($account); + + $balance = 0; + foreach($account['LedgerEntry'] AS &$entry) { + if (isset($entry[0])) + $entry = array_merge($entry[0], array_diff_key($entry, array(0))); + + $balance += $entry['balance']; + } + + $title = 'Account: ' . $account['Account']['name']; + $this->set(compact('account', 'title', 'balance')); + } +} diff --git a/site/controllers/contacts_controller.php b/site/controllers/contacts_controller.php index f3aae03..34f1f19 100644 --- a/site/controllers/contacts_controller.php +++ b/site/controllers/contacts_controller.php @@ -7,10 +7,10 @@ class ContactsController extends AppController { 'Contact.first_name' => 'ASC')); var $sidemenu_links = - array(array('name' => 'Tenants', 'header' => true), - array('name' => 'Current', 'url' => array('controller' => 'contacts', 'action' => 'current')), - array('name' => 'Past', 'url' => array('controller' => 'contacts', 'action' => 'past')), - array('name' => 'All Tenants', 'url' => array('controller' => 'contacts', 'action' => 'tenants')), + array(array('name' => 'Contacts', 'header' => true), + //array('name' => 'Current', 'url' => array('controller' => 'contacts', 'action' => 'current')), + //array('name' => 'Past', 'url' => array('controller' => 'contacts', 'action' => 'past')), + //array('name' => 'All Tenants', 'url' => array('controller' => 'contacts', 'action' => 'tenants')), array('name' => 'All Contacts', 'url' => array('controller' => 'contacts', 'action' => 'all')), ); @@ -154,50 +154,12 @@ class ContactsController extends AppController { 'ContactPhone', 'ContactEmail', 'ContactAddress', - 'Lease' => - array('order' => 'movein_date', - 'conditions' => array('Lease.lease_date IS NOT NULL', - 'ContactsLease.type !=' => 'ALTERNATE'), - // Models - 'Unit' => - array('order' => array('sort_order'), - 'fields' => array('id', 'name'), - ), - 'Charge' => - array('order' => array('charge_date'), - // Models - 'ChargeType', - 'Receipt', - ) - ) - ) + 'Customer') ); $contact = $this->Contact->read(null, $id); - - $outstanding_deposit = 0; - $outstanding_balance = 0; - foreach($contact['Lease'] AS $lease) { - foreach($lease['Charge'] AS $charge) { - $outstanding_balance += $charge['total']; - foreach ($charge['Receipt'] AS $receipt) { - $outstanding_balance -= $receipt['ChargesReceipt']['amount']; - // REVISIT 20090530: - // Using hardcoded value for security deposit... - // That can't be good! - if ($charge['charge_type_id'] == 1) - $outstanding_deposit += $receipt['ChargesReceipt']['amount']; - } - } - } - - $this->sidemenu_links[] = - array('name' => 'Operations', 'header' => true); - $this->sidemenu_links[] = - array('name' => 'Move-Out', 'url' => array('controller' => 'units', 'action' => 'move-out')); + //pr($contact); $title = $contact['Contact']['display_name']; - $this->set(compact('contact', 'title', - 'outstanding_balance', - 'outstanding_deposit')); + $this->set(compact('contact', 'title')); } } diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php new file mode 100644 index 0000000..c6db067 --- /dev/null +++ b/site/controllers/customers_controller.php @@ -0,0 +1,177 @@ + 100, + 'group' => 'Customer.id', + 'order' => array('Customer.name' => 'ASC')); + + var $sidemenu_links = + array(array('name' => 'Tenants', 'header' => true), + array('name' => 'Current', 'url' => array('controller' => 'customers', 'action' => 'current')), + array('name' => 'Past', 'url' => array('controller' => 'customers', 'action' => 'past')), + array('name' => 'All', 'url' => array('controller' => 'customers', 'action' => 'all')), + ); + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * override: sideMenuLinks + * - Generates controller specific links for the side menu + */ + function sideMenuLinks() { + return array_merge(parent::sideMenuLinks(), $this->sidemenu_links); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: index + * - Lists all current tenants + */ + + function index() { + $this->current(); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: current + * - Lists all current tenants + */ + + function current() { + $this->paginate = array_merge + ($this->paginate, + array('link' => + array(// Models + 'Lease' => + array('fields' => array(), + 'type' => 'INNER', + ), + ), + 'conditions' => array('Lease.close_date IS NULL') + )); + + $title = 'Current Tenants'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('customers', $this->paginate()); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: past + * - Lists all past tenants + */ + + function past() { + $this->paginate = array_merge + ($this->paginate, + array('link' => + array(// Models + 'Lease' => + array('fields' => array(), + 'type' => 'INNER', + ), + ), + 'conditions' => array('Lease.close_date IS NOT NULL') + )); + + $title = 'Past Tenants'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('customers', $this->paginate()); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: all + * - Lists all customers, including non-tenants + */ + + function all() { + $title = 'All Customers'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('customers', $this->paginate()); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * 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')); + } + + $this->Customer->Behaviors->attach('Containable'); + $this->Customer->contain + (array(// Models + 'Contact' => + array(// Models + 'ContactPhone', + 'ContactEmail', + 'ContactAddress', + ), + 'Transaction' => + array('order' => array('stamp'), + // Models + 'Entry' => + array(// Models + 'DebitAccount', + 'CreditAccount'), + ), + 'Lease' => + array('order' => 'movein_date', + 'conditions' => array('Lease.lease_date IS NOT NULL'), + // Models + 'Unit' => + array('order' => array('sort_order'), + 'fields' => array('id', 'name'), + ), + ), + ) + ); + $customer = $this->Customer->read(null, $id); + //pr($customer); + + $outstanding_deposit = 0; + $outstanding_balance = 0; + foreach($customer['Transaction'] AS $transaction) { + foreach($transaction['Entry'] AS $entry) { + if ($entry['DebitAccount']['name'] === 'A/R') + $outstanding_balance += $entry['amount']; + if ($entry['CreditAccount']['name'] === 'A/R') + $outstanding_balance -= $entry['amount']; + + if ($entry['DebitAccount']['name'] === 'Security Deposit') + $outstanding_deposit -= $entry['amount']; + if ($entry['CreditAccount']['name'] === 'Security Deposit') + $outstanding_deposit += $entry['amount']; + } + } + + $this->sidemenu_links[] = + array('name' => 'Operations', 'header' => true); + $this->sidemenu_links[] = + array('name' => 'Move-Out', 'url' => array('controller' => 'units', 'action' => 'move-out')); + + $title = $customer['Customer']['name']; + $this->set(compact('customer', 'title', + 'outstanding_balance', + 'outstanding_deposit')); + } +} diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php new file mode 100644 index 0000000..5a7c11a --- /dev/null +++ b/site/controllers/ledger_entries_controller.php @@ -0,0 +1,55 @@ + 100, + 'group' => 'Entry.id', + 'order' => array('Entry.stamp' => 'ASC')); + + var $sidemenu_links = + array(array('name' => 'Entries', 'header' => true), + array('name' => 'Cleared', 'url' => array('controller' => 'ledger_entries', 'action' => 'cleared')), + array('name' => 'Unresolved', 'url' => array('controller' => 'ledger_entries', 'action' => 'unresolved')), + ); + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * 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')); + } + + $this->LedgerEntry->Behaviors->attach('Containable'); + $this->LedgerEntry->contain + (array(// Models + 'MonetarySource' => array('MonetaryType'), + 'Transaction', + 'DebitLedger', + 'CreditLedger', + ) + ); + $entry = $this->LedgerEntry->read(null, $id); + pr($entry); + + $title = "Entry #{$entry['LedgerEntry']['id']} ({$entry['LedgerEntry']['name']})"; + $this->set(compact('entry', 'title')); + //$this->autoRender = false; + } +} diff --git a/site/controllers/ledgers_controller.php b/site/controllers/ledgers_controller.php new file mode 100644 index 0000000..e54063c --- /dev/null +++ b/site/controllers/ledgers_controller.php @@ -0,0 +1,188 @@ + 100, + 'link' => + array(// Models + 'Account', + 'LedgerEntry' => + array('fields' => + array('SUM(IF(LedgerEntry.debit_ledger_id = Ledger.id, LedgerEntry.amount, 0)) AS debits', + 'SUM(IF(LedgerEntry.credit_ledger_id = Ledger.id, LedgerEntry.amount, 0)) AS credits', + "SUM(IF(Account.type IN ('ASSET', 'EXPENSE'), + IF(LedgerEntry.debit_ledger_id = Ledger.id, 1, -1), + IF(LedgerEntry.credit_ledger_id = Ledger.id, 1, -1)) * LedgerEntry.amount) AS balance", + 'COUNT(LedgerEntry.id) AS entries'), + 'conditions' => + array('OR' => + array('LedgerEntry.debit_ledger_id = Ledger.id', + 'LedgerEntry.credit_ledger_id = Ledger.id'), + ), + ), + ), + + 'group' => 'Ledger.id', + 'order' => array('Ledger.name' => 'ASC')); + + var $uses = array('Ledger', 'LedgerEntry'); + + 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 + */ + + function index() { + $this->current(); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: current + * - Lists all current ledgers + */ + + function current() { + $title = 'Current Ledgers'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('ledgers', $this->paginate(null, array('NOT' => array('Ledger.closed')))); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: closed + * - Lists all closed ledgers + */ + + function closed() { + $title = 'Closed Ledgers'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('ledgers', $this->paginate(null, array('Ledger.closed'))); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: all + * - Lists all ledgers + */ + + function all() { + $title = 'All Ledgers'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('ledgers', $this->paginate()); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: view + * - Displays information about a specific ledger + */ + + function view($id = null) { + if (!$id) { + $this->Session->setFlash(__('Invalid Item.', true)); + $this->redirect(array('action'=>'index')); + } + +/* $this->Ledger->bindModel(array('hasMany' => array */ +/* ('LedgerEntry' => array */ +/* ('className' => 'LedgerEntry', */ +/* 'foreignKey' => false, */ +/* 'finderQuery' => 'SELECT `LedgerEntry`.* */ +/* FROM pmgr_entries AS `LedgerEntry` */ +/* LEFT JOIN pmgr_transactions AS `Transaction` */ +/* ON `Transaction`.id = `LedgerEntry`.transaction_id */ +/* WHERE LedgerEntry.debit_ledger_id = ({$__cakeID__$}) */ +/* OR LedgerEntry.credit_ledger_id = ({$__cakeID__$}) */ +/* ORDER BY Transaction.stamp', */ +/* )))); */ + +/* $this->Ledger->Behaviors->attach('Containable'); */ +/* $this->Ledger->Contain(array('LedgerEntry' => array */ +/* ( */ +/* // Models */ +/* 'Transaction' => array */ +/* ( */ +/* // Models */ +/* 'Customer', */ +/* )), */ + +/* )); */ +/* } */ +/* $ledger = $this->Ledger->read(null, $id); */ + + $this->Ledger->Behaviors->attach('Containable'); + $this->Ledger->Contain(array('Account')); + $ledger = $this->Ledger->read(null, $id); + //pr($ledger); + + if (in_array($ledger['Account']['type'], array('ASSET', 'EXPENSE'))) + $ledger_type = 'debit'; + else + $ledger_type = 'credit'; + + $ledger['LedgerEntry'] = $this->LedgerEntry->find + ('all', + array('link' => array + (// Models + 'Transaction' => + array(// Models + 'Customer', + )), + 'fields' => + array('id', 'name', 'comment', + "IF(LedgerEntry.debit_ledger_id = $id, LedgerEntry.amount, NULL) AS debit", + "IF(LedgerEntry.credit_ledger_id = $id, LedgerEntry.amount, NULL) AS credit", + "(IF(LedgerEntry.{$ledger_type}_ledger_id = $id, 1, -1) * LedgerEntry.amount) AS balance"), + 'conditions' => array('OR' => + array("LedgerEntry.debit_ledger_id = $id", + "LedgerEntry.credit_ledger_id = $id")), + 'order' => array('Transaction.stamp'), + //'limit' => 15, + //'limit' => 2, + )); + //pr($ledger); + + $balance = 0; + foreach($ledger['LedgerEntry'] AS &$entry) { + if (isset($entry[0])) + $entry = array_merge($entry[0], array_diff_key($entry, array(0))); + + $balance += $entry['balance']; + } + + $title = 'Ledger: ' . $ledger['Ledger']['name']; + $this->set(compact('ledger', 'title', 'balance')); + } +} diff --git a/site/controllers/payments_controller.php b/site/controllers/payments_controller.php deleted file mode 100644 index 63e1a41..0000000 --- a/site/controllers/payments_controller.php +++ /dev/null @@ -1,118 +0,0 @@ - 100, - 'group' => 'Payment.id', - 'order' => array('Payment.id' => 'ASC')); - - var $sidemenu_links = - array(array('name' => 'Payments', 'header' => true), - array('name' => 'Cleared', 'url' => array('controller' => 'payments', 'action' => 'cleared')), - array('name' => 'Unresolved', 'url' => array('controller' => 'payments', 'action' => 'unresolved')), - ); - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * override: sideMenuLinks - * - Generates controller specific links for the side menu - */ - function sideMenuLinks() { - return array_merge(parent::sideMenuLinks(), $this->sidemenu_links); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: index - * - Lists all payments - */ - - function index() { - $this->all(); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: cleared - * - Lists cleared payments - */ - - function cleared() { - $this->all(); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: unresolved - * - Lists unresolved payments - */ - - function unresolved() { - $this->all(); - } - - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: all - * - Lists all payments - */ - - function all() { - $this->paginate = array_merge - ($this->paginate, - array('link' => - array(// Models - 'PaymentType', - 'Receipt', - ), - )); - - $title = 'All Payments'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('payments', $this->paginate()); - $this->render('index'); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: view - * - Displays information about a specific payment - */ - - function view($id = null) { - if (!$id) { - $this->Session->setFlash(__('Invalid Item.', true)); - $this->redirect(array('action'=>'index')); - } - - $this->Payment->Behaviors->attach('Containable'); - $this->Payment->contain - (array(// Models - 'PaymentType', - 'Receipt', - ) - ); - $payment = $this->Payment->read(null, $id); - //pr($payment); - -/* $this->sidemenu_links[] = */ -/* array('name' => 'Operations', 'header' => true); */ -/* $this->sidemenu_links[] = */ -/* array('name' => 'Move-Out', 'url' => array('controller' => 'payments', 'action' => 'move-out')); */ - - $title = 'Payment #' . $payment['Payment']['id']; - $this->set(compact('payment', 'title')); - } -} diff --git a/site/controllers/receipts_controller.php b/site/controllers/receipts_controller.php deleted file mode 100644 index 77215dd..0000000 --- a/site/controllers/receipts_controller.php +++ /dev/null @@ -1,131 +0,0 @@ - 100, - 'group' => 'Receipt.id', - 'order' => array('Receipt.stamp' => 'ASC')); - - var $sidemenu_links = - array(array('name' => 'Receipts', 'header' => true), - array('name' => 'Cleared', 'url' => array('controller' => 'receipts', 'action' => 'cleared')), - array('name' => 'Unresolved', 'url' => array('controller' => 'receipts', 'action' => 'unresolved')), - ); - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * override: sideMenuLinks - * - Generates controller specific links for the side menu - */ - function sideMenuLinks() { - return array_merge(parent::sideMenuLinks(), $this->sidemenu_links); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: index - * - Lists all receipts - */ - - function index() { - $this->all(); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: cleared - * - Lists cleared receipts - */ - - function cleared() { - $this->all(); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: unresolved - * - Lists unresolved receipts - */ - - function unresolved() { - $this->all(); - } - - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: all - * - Lists all receipts - */ - - function all() { - $this->paginate = array_merge - ($this->paginate, - array('link' => - array(// Models - 'Charge', - 'Payment' - ), - )); - - $title = 'All Receipts'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('receipts', $this->paginate()); - $this->render('index'); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: view - * - Displays information about a specific receipt - */ - - function view($id = null) { - if (!$id) { - $this->Session->setFlash(__('Invalid Item.', true)); - $this->redirect(array('action'=>'index')); - } - - $this->Receipt->Behaviors->attach('Containable'); - $this->Receipt->contain - (array(// Models - 'Charge' => array(// Models - 'Lease' => array('fields' => array('number')), - 'ChargesReceipt', - 'ChargeType'), - 'Payment' => array(// Models - 'PaymentType'), - ) - ); - $receipt = $this->Receipt->read(null, $id); - //pr($receipt); - - $charge_amount = 0; - $payment_amount = 0; - foreach($receipt['Charge'] AS $charge) - $charge_amount += $charge['ChargesReceipt']['amount']; - foreach($receipt['Payment'] AS $payment) - $payment_amount += $payment['amount']; - -/* $this->sidemenu_links[] = */ -/* array('name' => 'Operations', 'header' => true); */ -/* $this->sidemenu_links[] = */ -/* array('name' => 'Move-Out', 'url' => array('controller' => 'receipts', 'action' => 'move-out')); */ - - $title = 'Receipt #' . $receipt['Receipt']['id']; - $this->set(compact('receipt', 'title', - 'charge_amount', - 'payment_amount')); - } -} diff --git a/site/controllers/charges_controller.php b/site/controllers/transactions_controller.php similarity index 65% rename from site/controllers/charges_controller.php rename to site/controllers/transactions_controller.php index d1b890c..a5d0da3 100644 --- a/site/controllers/charges_controller.php +++ b/site/controllers/transactions_controller.php @@ -1,14 +1,14 @@ 100, - 'group' => 'Charge.id', - 'order' => array('Charge.charge_date' => 'ASC')); + 'group' => 'Transaction.id', + 'order' => array('Transaction.stamp' => 'ASC')); var $sidemenu_links = - array(array('name' => 'Charges', 'header' => true), - array('name' => 'Cleared', 'url' => array('controller' => 'charges', 'action' => 'cleared')), - array('name' => 'Unresolved', 'url' => array('controller' => 'charges', 'action' => 'unresolved')), + array(array('name' => 'Transactions', 'header' => true), + array('name' => 'Cleared', 'url' => array('controller' => 'transactions', 'action' => 'cleared')), + array('name' => 'Unresolved', 'url' => array('controller' => 'transactions', 'action' => 'unresolved')), ); @@ -27,7 +27,7 @@ class ChargesController extends AppController { ************************************************************************** ************************************************************************** * action: index - * - Lists all charges + * - Lists all transactions */ function index() { @@ -39,7 +39,7 @@ class ChargesController extends AppController { ************************************************************************** ************************************************************************** * action: cleared - * - Lists cleared charges + * - Lists cleared transactions */ function cleared() { @@ -51,7 +51,7 @@ class ChargesController extends AppController { ************************************************************************** ************************************************************************** * action: unresolved - * - Lists unresolved charges + * - Lists unresolved transactions */ function unresolved() { @@ -64,7 +64,7 @@ class ChargesController extends AppController { ************************************************************************** ************************************************************************** * action: all - * - Lists all charges + * - Lists all transactions */ function all() { @@ -72,15 +72,14 @@ class ChargesController extends AppController { ($this->paginate, array('link' => array(// Models - 'ChargeType', - 'Receipt', - 'Lease' => array('fields' => array('number')) + 'Customer', + 'LedgerEntry' => array('DebitLedger', 'CreditLedger') ), )); - $title = 'All Charges'; + $title = 'All Transactions'; $this->set('title', $title); $this->set('heading', $title); - $this->set('charges', $this->paginate()); + $this->set('transactions', $this->paginate()); $this->render('index'); } @@ -89,7 +88,7 @@ class ChargesController extends AppController { ************************************************************************** ************************************************************************** * action: view - * - Displays information about a specific charge + * - Displays information about a specific transaction */ function view($id = null) { @@ -98,30 +97,33 @@ class ChargesController extends AppController { $this->redirect(array('action'=>'index')); } - $this->Charge->Behaviors->attach('Containable'); - $this->Charge->contain + $this->Transaction->Behaviors->attach('Containable'); + $this->Transaction->contain (array(// Models - 'ChargeType', - 'Receipt', - 'Lease' => array('fields' => array('number')), + 'LedgerEntry' => array(//Models + 'DebitLedger', + 'CreditLedger', + ), ) ); - $charge = $this->Charge->read(null, $id); - //pr($charge); + $transaction = $this->Transaction->read(null, $id); + pr($transaction); - $payment_amount = 0; - foreach($charge['Receipt'] AS $receipt) - $payment_amount += $receipt['ChargesReceipt']['amount']; - $balance_amount = $charge['Charge']['total'] - $payment_amount; + $debit_amount = 0; + $credit_amount = 0; + foreach($transaction['LedgerEntry'] AS $entry) { + $debit_amount += $entry['amount']; + $credit_amount += $entry['amount']; + } /* $this->sidemenu_links[] = */ /* array('name' => 'Operations', 'header' => true); */ /* $this->sidemenu_links[] = */ -/* array('name' => 'Move-Out', 'url' => array('controller' => 'charges', 'action' => 'move-out')); */ +/* array('name' => 'Move-Out', 'url' => array('controller' => 'transactions', 'action' => 'move-out')); */ - $title = 'Charge #' . $charge['Charge']['id']; - $this->set(compact('charge', 'title', - 'payment_amount', - 'balance_amount')); + $title = 'Transaction #' . $transaction['Transaction']['id']; + $this->set(compact('transaction', 'title', + 'debit_amount', + 'credit_amount')); } } diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index 453097a..abe18cf 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -156,45 +156,70 @@ class UnitsController extends AppController { $this->Unit->contain (array(// Models 'UnitSize', + //'CurrentLease' => 'Lease' => - array('order' => 'movein_date', - 'conditions' => array('Lease.lease_date IS NOT NULL', - ), + array(//'order' => 'movein_date', + //'conditions' => array('Lease.lease_date IS NOT NULL', + //), // Models - 'Contact' => - array(//'order' => array('sort_order'), - 'fields' => array('id', 'display_name'), - ), - 'Charge' => - array('order' => array('charge_date'), - // Models - 'ChargeType', - 'Receipt' => array(// Models - 'Payment' - ), - ) + //'Contact' => array('alias' => 'PrimaryContact'), + // 'PrimaryContact', + 'Customer' => array('fields' => array('id', 'name'), + // Models + 'Transaction' => + array('order' => array('stamp'), + // Models + 'LedgerEntry' => array('DebitLedger' => array('Account'), + 'CreditLedger' => array('Account'), + ), + ), + ), +/* array(//'order' => array('sort_order'), */ +/* 'fields' => array('id', 'display_name'), */ +/* ), */ ) ) ); - $unit = $this->Unit->read(null, $id); + + //$unit = $this->Unit->read(null, $id); //pr($unit); + $this->Unit->Lease->Customer->Transaction->LedgerEntry->Behaviors->attach('Containable'); + $entries = $this->Unit->Lease->Customer->Transaction->LedgerEntry->find + ('all', + array + ( + 'contain' => + array('Transaction' => + array('Customer' => + array('Lease' => + array('Unit' => + array('conditions' => array('Unit.id' => $id)), + ), + ), + ), + ), + //'conditions' => 'xyz', + 'limit' => 2, + )); + pr($entries); + $this->autoRender = false; + + $outstanding_deposit = 0; $outstanding_balance = 0; foreach($unit['Lease'] AS $lease) { - foreach($lease['Charge'] AS $charge) { - $outstanding_balance += $charge['total']; - foreach ($charge['Receipt'] AS $receipt) { - $outstanding_balance -= $receipt['ChargesReceipt']['amount']; + foreach($lease['Customer']['Transaction'] AS $transaction) { + foreach($transaction['LedgerEntry'] AS $entry) { + if ($entry['DebitLedger']['Account']['name'] === 'A/R') + $outstanding_balance += $entry['amount']; + if ($entry['CreditLedger']['Account']['name'] === 'A/R') + $outstanding_balance -= $entry['amount']; -/* foreach($receipt['Payment'] AS $payment) */ -/* $outstanding_balance -= $payment['amount']; */ - - // REVISIT 20090530: - // Using hardcoded value for security deposit... - // That can't be good! - if ($charge['charge_type_id'] == 1) - $outstanding_deposit += $receipt['ChargesReceipt']['amount']; + if ($entry['DebitLedger']['Account']['name'] === 'Security Deposit') + $outstanding_deposit -= $entry['amount']; + if ($entry['CreditLedger']['Account']['name'] === 'Security Deposit') + $outstanding_deposit += $entry['amount']; } } } diff --git a/site/models/account.php b/site/models/account.php index 35eeca0..0079017 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -8,10 +8,25 @@ class Account extends AppModel { 'external_name' => array('notempty') ); - //The Associations below have been created with all possible keys, those that are not needed can be removed + var $hasOne = array( + 'CurrentLedger' => array( + 'className' => 'Ledger', + 'foreignKey' => 'account_id', + 'dependent' => false, + 'conditions' => array(array('CurrentLedger.closed' => 0)), + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ), + ); + var $hasMany = array( - 'ChargeType' => array( - 'className' => 'ChargeType', + 'Ledger' => array( + 'className' => 'Ledger', 'foreignKey' => 'account_id', 'dependent' => false, 'conditions' => '', @@ -22,7 +37,7 @@ class Account extends AppModel { 'exclusive' => '', 'finderQuery' => '', 'counterQuery' => '' - ) + ), ); } diff --git a/site/models/behaviors/linkable.php b/site/models/behaviors/linkable.php index f38c7da..388456f 100644 --- a/site/models/behaviors/linkable.php +++ b/site/models/behaviors/linkable.php @@ -82,23 +82,51 @@ class LinkableBehavior extends ModelBehavior { /* pr("_Model: $options[class] : $_Model->name ($_Model->alias)"); */ /* pr("Reference: $options[reference] : $Reference->name ($Reference->alias)"); */ $db =& $_Model->getDataSource(); - $associations = $_Model->getAssociated(); - if (isset($associations[$Reference->alias])) { + + $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])) { +/* pr("Reference defines association to _Model"); */ + $associatedThroughReference = 1; + $type = $associations[$_Model->alias]; + $association = $Reference->{$type}[$_Model->alias]; + } + elseif (($associations = $_Model->getAssociated()) && + isset($associations[$Reference->alias])) { +/* pr("_Model defines association to Reference"); */ $type = $associations[$Reference->alias]; $association = $_Model->{$type}[$Reference->alias]; - } else { - $_Model->bind($Reference->alias); + } + else { + // No relationship... make our best effort to create one. +/* pr("No assocation between _Model and Reference"); */ $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) { + $primaryModel = $Reference; + $foreignModel = $_Model; + } else { + $primaryModel = $_Model; + $foreignModel = $Reference; + } + +/* pr("primaryModel: $primaryModel->name ($primaryModel->alias)"); */ +/* pr("foreignModel: $foreignModel->name ($foreignModel->alias)"); */ +/* pr($type); */ +/* pr($association); */ + if (empty($options['conditions'])) { - if ($type === 'belongsTo') { - $modelKey = $_Model->escapeField($association['foreignKey']); - $referenceKey = $Reference->escapeField($Reference->primaryKey); - $options['conditions'] = "{$referenceKey} = {$modelKey}"; - } elseif ($type === 'hasAndBelongsToMany') { + if ($type === 'hasAndBelongsToMany') { if (isset($association['with'])) $Link =& $_Model->{$association['with']}; else @@ -139,17 +167,10 @@ class LinkableBehavior extends ModelBehavior { // 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' => $options['alias'], - 'conditions' => "{$modelKey} = {$modelLink}", - 'table' => $db->fullTableName($_Model, true)); - - // The user may have specified conditions directly in the model - // for this join. Make sure to adhere to those conditions. - if (isset($association['conditions']) && is_array($association['conditions'])) - $options['conditions'] = $association['conditions']; - elseif (!empty($association['conditions'])) - $options['conditions'] = array($association['conditions']); + $options['joins'][] = array('type' => 'INNER', + 'alias' => $options['alias'], + '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. @@ -157,10 +178,28 @@ class LinkableBehavior extends ModelBehavior { $options['table'] = $Link->getDataSource()->fullTableName($Link); $options['conditions'][] = "{$referenceLink} = {$referenceKey}"; } else { - $referenceKey = $Reference->escapeField($association['foreignKey']); - $modelKey = $_Model->escapeField($_Model->primaryKey); - $options['conditions'] = "{$modelKey} = {$referenceKey}"; + $foreignKey = $primaryModel->escapeField($association['foreignKey']); + $primaryKey = $foreignModel->escapeField($foreignModel->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}"; } + + // The user may have specified conditions directly in the model + // for this join. Make sure to adhere to those conditions. + if (isset($association['conditions']) && is_array($association['conditions'])) + $options['conditions'] = array_merge($options['conditions'], $association['conditions']); + elseif (!empty($association['conditions'])) + $options['conditions'][] = $association['conditions']; + +/* pr(array("Link ", $options['conditions'])); */ + //pr($modelKey); + //pr($referenceKey); + } if (empty($options['table'])) { $options['table'] = $db->fullTableName($_Model, true); diff --git a/site/models/charge.php b/site/models/charge.php deleted file mode 100644 index e37a8e9..0000000 --- a/site/models/charge.php +++ /dev/null @@ -1,53 +0,0 @@ - array('numeric'), - 'charge_type_id' => array('numeric'), - 'lease_id' => array('numeric'), - 'charge_date' => array('date'), - 'charge_to_date' => array('date'), - 'due_date' => array('date'), - 'amount' => array('money'), - 'tax' => array('money'), - 'total' => array('money') - ); - - var $belongsTo = array( - 'ChargeType' => array( - 'className' => 'ChargeType', - 'foreignKey' => 'charge_type_id', - 'conditions' => '', - 'fields' => '', - 'order' => '' - ), - 'Lease' => array( - 'className' => 'Lease', - 'foreignKey' => 'lease_id', - 'conditions' => '', - 'fields' => '', - 'order' => '' - ) - ); - - var $hasAndBelongsToMany = array( - 'Receipt' => array( - 'className' => 'Receipt', - 'joinTable' => 'charges_receipts', - 'foreignKey' => 'charge_id', - 'associationForeignKey' => 'receipt_id', - 'unique' => true, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'finderQuery' => '', - 'deleteQuery' => '', - 'insertQuery' => '' - ) - ); - -} -?> \ No newline at end of file diff --git a/site/models/charge_type.php b/site/models/charge_type.php deleted file mode 100644 index fe42c68..0000000 --- a/site/models/charge_type.php +++ /dev/null @@ -1,39 +0,0 @@ - array('numeric'), - 'name' => array('notempty'), - 'account_id' => array('numeric') - ); - - //The Associations below have been created with all possible keys, those that are not needed can be removed -/* var $belongsTo = array( */ -/* 'Account' => array( */ -/* 'className' => 'Account', */ -/* 'foreignKey' => 'account_id', */ -/* 'conditions' => '', */ -/* 'fields' => '', */ -/* 'order' => '' */ -/* ) */ -/* ); */ - - var $hasMany = array( - 'Charge' => array( - 'className' => 'Charge', - 'foreignKey' => 'charge_type_id', - 'dependent' => false, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'exclusive' => '', - 'finderQuery' => '', - 'counterQuery' => '' - ) - ); - -} -?> \ No newline at end of file diff --git a/site/models/contact.php b/site/models/contact.php index c3d834a..04052c2 100644 --- a/site/models/contact.php +++ b/site/models/contact.php @@ -10,11 +10,11 @@ class Contact extends AppModel { ); var $hasAndBelongsToMany = array( - 'Lease' => array( - 'className' => 'Lease', - 'joinTable' => 'contacts_leases', + 'Customer' => array( + 'className' => 'Customer', + 'joinTable' => 'contacts_customers', 'foreignKey' => 'contact_id', - 'associationForeignKey' => 'lease_id', + 'associationForeignKey' => 'customer_id', 'unique' => true, 'conditions' => '', 'fields' => '', diff --git a/site/models/customer.php b/site/models/customer.php new file mode 100644 index 0000000..652cef3 --- /dev/null +++ b/site/models/customer.php @@ -0,0 +1,58 @@ + array('numeric'), + 'name' => array('notempty'), + ); + + var $hasMany = array( + 'Lease' => array( + 'className' => 'Lease', + 'foreignKey' => 'customer_id', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ), + 'Transaction' => array( + 'className' => 'Transaction', + 'foreignKey' => 'customer_id', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); + + var $hasAndBelongsToMany = array( + 'Contact' => array( + 'className' => 'Contact', + 'joinTable' => 'contacts_customers', + 'foreignKey' => 'customer_id', + 'associationForeignKey' => 'contact_id', + 'unique' => true, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'finderQuery' => '', + 'deleteQuery' => '', + 'insertQuery' => '' + ), + ); + +} +?> \ No newline at end of file diff --git a/site/models/lease.php b/site/models/lease.php index 509b333..fd349fe 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -22,7 +22,6 @@ class Lease extends AppModel { 'next_amount_date' => array('date') ); - //The Associations below have been created with all possible keys, those that are not needed can be removed var $belongsTo = array( 'LeaseType' => array( 'className' => 'LeaseType', @@ -44,41 +43,15 @@ class Lease extends AppModel { 'conditions' => '', 'fields' => '', 'order' => '' - ) - ); - - var $hasMany = array( - 'Charge' => array( - 'className' => 'Charge', - 'foreignKey' => 'lease_id', + ), + 'Customer' => array( + 'className' => 'Customer', + 'foreignKey' => 'customer_id', 'dependent' => false, 'conditions' => '', 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'exclusive' => '', - 'finderQuery' => '', - 'counterQuery' => '' - ) - ); - - var $hasAndBelongsToMany = array( - 'Contact' => array( - 'className' => 'Contact', - 'joinTable' => 'contacts_leases', - 'foreignKey' => 'lease_id', - 'associationForeignKey' => 'contact_id', - 'unique' => true, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'finderQuery' => '', - 'deleteQuery' => '', - 'insertQuery' => '' - ) + 'order' => '' + ), ); } diff --git a/site/models/ledger.php b/site/models/ledger.php new file mode 100644 index 0000000..6808a1f --- /dev/null +++ b/site/models/ledger.php @@ -0,0 +1,65 @@ + array('numeric'), + 'name' => array('notempty'), + ); + + var $belongsTo = array( + 'Account' => array( + 'className' => 'Account', + 'foreignKey' => 'account_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ), + ); + + var $hasMany = array( +/* 'LedgerEntry' => array( */ +/* 'className' => 'LedgerEntry', */ +/* 'foreignKey' => false, */ +/* 'dependent' => false, */ +/* 'conditions' => '', */ +/* 'fields' => '', */ +/* 'order' => '', */ +/* 'limit' => '', */ +/* 'offset' => '', */ +/* 'exclusive' => '', */ +/* 'finderQuery' => 'SELECT `Entry`.* FROM pmgr_entries AS `Entry` */ +/* WHERE Entry.debit_ledger_id = ({$__cakeID__$}) */ +/* OR Entry.credit_ledger_id = ({$__cakeID__$})', */ +/* 'counterQuery' => '' */ +/* ), */ + 'DebitLedgerEntry' => array( + 'className' => 'LedgerEntry', + 'foreignKey' => 'debit_ledger_id', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ), + 'CreditLedgerEntry' => array( + 'className' => 'LedgerEntry', + 'foreignKey' => 'credit_ledger_id', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ), + ); + +} +?> \ No newline at end of file diff --git a/site/models/ledger_entry.php b/site/models/ledger_entry.php new file mode 100644 index 0000000..4d84e6c --- /dev/null +++ b/site/models/ledger_entry.php @@ -0,0 +1,43 @@ + array('numeric'), + 'transaction_id' => array('numeric'), + 'amount' => array('money') + ); + + var $belongsTo = array( + 'MonetarySource' => array( + 'className' => 'MonetarySource', + 'foreignKey' => 'monetary_source_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ), + 'Transaction' => array( + 'className' => 'Transaction', + 'foreignKey' => 'transaction_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ), + 'DebitLedger' => array( + 'className' => 'Ledger', + 'foreignKey' => 'debit_ledger_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ), + 'CreditLedger' => array( + 'className' => 'Ledger', + 'foreignKey' => 'credit_ledger_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ), + ); + +} +?> \ No newline at end of file diff --git a/site/models/monetary_source.php b/site/models/monetary_source.php new file mode 100644 index 0000000..a2d5bcc --- /dev/null +++ b/site/models/monetary_source.php @@ -0,0 +1,28 @@ + array('numeric'), + 'name' => array('notempty'), + 'tillable' => array('boolean') + ); + + var $belongsTo = array( + 'MonetaryType' => array( + 'className' => 'MonetaryType', + 'foreignKey' => 'monetary_type_id', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); + +} +?> \ No newline at end of file diff --git a/site/models/payment_type.php b/site/models/monetary_type.php similarity index 55% rename from site/models/payment_type.php rename to site/models/monetary_type.php index 45f5881..d79d4fc 100644 --- a/site/models/payment_type.php +++ b/site/models/monetary_type.php @@ -1,18 +1,17 @@ array('numeric'), 'name' => array('notempty'), 'tillable' => array('boolean') ); - //The Associations below have been created with all possible keys, those that are not needed can be removed var $hasMany = array( - 'Payment' => array( - 'className' => 'Payment', - 'foreignKey' => 'payment_type_id', + 'MonetarySource' => array( + 'className' => 'MonetarySource', + 'foreignKey' => 'monetary_type_id', 'dependent' => false, 'conditions' => '', 'fields' => '', diff --git a/site/models/payment.php b/site/models/payment.php deleted file mode 100644 index e3b2fc8..0000000 --- a/site/models/payment.php +++ /dev/null @@ -1,31 +0,0 @@ - array('numeric'), - 'receipt_id' => array('numeric'), - 'payment_type_id' => array('numeric'), - 'amount' => array('money') - ); - - //The Associations below have been created with all possible keys, those that are not needed can be removed - var $belongsTo = array( - 'Receipt' => array( - 'className' => 'Receipt', - 'foreignKey' => 'receipt_id', - 'conditions' => '', - 'fields' => '', - 'order' => '' - ), - 'PaymentType' => array( - 'className' => 'PaymentType', - 'foreignKey' => 'payment_type_id', - 'conditions' => '', - 'fields' => '', - 'order' => '' - ) - ); - -} -?> \ No newline at end of file diff --git a/site/models/receipt.php b/site/models/receipt.php deleted file mode 100644 index 66a2164..0000000 --- a/site/models/receipt.php +++ /dev/null @@ -1,46 +0,0 @@ - array('numeric'), - 'stamp' => array('time') - ); - - //The Associations below have been created with all possible keys, those that are not needed can be removed - var $hasMany = array( - 'Payment' => array( - 'className' => 'Payment', - 'foreignKey' => 'receipt_id', - 'dependent' => false, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'exclusive' => '', - 'finderQuery' => '', - 'counterQuery' => '' - ) - ); - - var $hasAndBelongsToMany = array( - 'Charge' => array( - 'className' => 'Charge', - 'joinTable' => 'charges_receipts', - 'foreignKey' => 'receipt_id', - 'associationForeignKey' => 'charge_id', - 'unique' => true, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'finderQuery' => '', - 'deleteQuery' => '', - 'insertQuery' => '' - ) - ); - -} -?> \ No newline at end of file diff --git a/site/models/transaction.php b/site/models/transaction.php new file mode 100644 index 0000000..d52f06e --- /dev/null +++ b/site/models/transaction.php @@ -0,0 +1,37 @@ + array('numeric'), + 'stamp' => array('time') + ); + + var $belongsTo = array( + 'Customer' => array( + 'className' => 'Customer', + 'foreignKey' => 'customer_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ), + ); + + var $hasMany = array( + 'LedgerEntry' => array( + 'className' => 'LedgerEntry', + 'foreignKey' => 'transaction_id', + 'dependent' => false, + 'conditions' => '', + 'fields' => '', + 'order' => '', + 'limit' => '', + 'offset' => '', + 'exclusive' => '', + 'finderQuery' => '', + 'counterQuery' => '' + ) + ); + +} +?> \ No newline at end of file diff --git a/site/models/unit.php b/site/models/unit.php index fb0b173..d03ddaa 100644 --- a/site/models/unit.php +++ b/site/models/unit.php @@ -20,6 +20,13 @@ class Unit extends AppModel { 'fields' => '', 'order' => '' ), + 'CurrentLease' => array( + 'className' => 'Lease', + 'foreignKey' => 'current_lease_id', + 'conditions' => '', + 'fields' => '', + 'order' => '' + ), /* 'Map' => array( */ /* 'className' => 'MapsUnit', */ /* 'foreignKey' => 'unit_id', */ diff --git a/site/views/accounts/index.ctp b/site/views/accounts/index.ctp new file mode 100644 index 0000000..2518428 --- /dev/null +++ b/site/views/accounts/index.ctp @@ -0,0 +1,3 @@ +
+element('accounts', array('heading' => '

'.$heading.'

')) ?> +
diff --git a/site/views/accounts/view.ctp b/site/views/accounts/view.ctp new file mode 100644 index 0000000..8d252da --- /dev/null +++ b/site/views/accounts/view.ctp @@ -0,0 +1,95 @@ + + + diff --git a/site/views/charges/index.ctp b/site/views/charges/index.ctp deleted file mode 100644 index 1d4e8e3..0000000 --- a/site/views/charges/index.ctp +++ /dev/null @@ -1,3 +0,0 @@ -
-element('charges', array('heading' => '

'.$heading.'

')) ?> -
diff --git a/site/views/charges/view.ctp b/site/views/charges/view.ctp deleted file mode 100644 index ab4d948..0000000 --- a/site/views/charges/view.ctp +++ /dev/null @@ -1,87 +0,0 @@ - - -
- -element('table', - array('class' => 'item charge detail', - 'caption' => 'Charge Info', - 'rows' => $rows, - 'column_class' => array('field', 'value'))); - - -?> -
-
- Amount Received: -
-
- Amount Owing: -
-
-link('#'.$receipt['id'], - array('controller' => 'receipts', - 'action' => 'view', - $receipt['id'])), - datefmt($receipt['stamp']), - $receipt['comment'], - currency($receipt['ChargesReceipt']['amount']), - currency($running_total) - ); -} - -echo $this->element('table', - array('class' => 'item receipt list', - 'caption' => 'Receipts towards Charge', - 'headers' => $headers, - 'rows' => $rows, - 'column_class' => $headers)); - - -?> - -
diff --git a/site/views/contacts/view.ctp b/site/views/contacts/view.ctp index 7d7f48c..a4986a1 100644 --- a/site/views/contacts/view.ctp +++ b/site/views/contacts/view.ctp @@ -1,6 +1,6 @@ -
+
element('table', array('class' => 'item contact detail', - 'caption' => 'Tenant Info', + 'caption' => 'Contact Details', 'rows' => $rows, 'column_class' => array('field', 'value'))); +/********************************************************************** + * Contact Info Box + */ + ?> -
-
- Security Deposit: -
-
- Balance: -
+
+ +
element('table', /********************************************************************** - * Lease History + * Customers */ -$headers = array('Lease', 'Unit', 'Signed', 'Move-In', 'Move-Out', 'Rent', 'Deposit', 'Comment'); -$rows = array(); -foreach($contact['Lease'] AS $lease) { - $rows[] = array('#'.$lease['number'], - $html->link($lease['Unit']['name'], - array('controller' => 'units', - 'action' => 'view', - $lease['Unit']['id'])), - datefmt($lease['lease_date']), - datefmt($lease['movein_date']), - datefmt($lease['moveout_date']), - $lease['amount'], - $lease['deposit'], - $lease['comment']); -} - -echo $this->element('table', - array('class' => 'item lease list', - 'caption' => 'Lease History', - 'headers' => $headers, - 'rows' => $rows, - 'column_class' => $headers)); +echo $this->element('customers', array('heading' => '', + 'caption' => 'Related Customers', + 'customers' => $contact['Customer'])); -/********************************************************************** - * Ledger History - */ -foreach($contact['Lease'] AS $lease) { - $headers = array(/*'Charge/Receipt'*/'Charge', 'Date', 'Through', 'Type', 'Comment', 'Amount', 'Balance', 'Total'); - - $rows = array(); - $row_class = array(); - $running_total = 0; - $odd = 0; - foreach($lease['Charge'] AS $charge) { - $amount = $charge['total']; - - $balance = $amount; - foreach ($charge['Receipt'] AS $receipt) - $balance -= $receipt['ChargesReceipt']['amount']; - - $running_total += $balance; - - $rows[] = array($html->link('#'.$charge['id'], - array('controller' => 'charges', - 'action' => 'view', - $charge['id'])), - datefmt($charge['charge_date']), - datefmt($charge['charge_to_date']), - $charge['ChargeType']['name'], - $charge['comment'], - currency($amount), - currency($balance), - //currency($amount - $paid)); - currency($running_total)); - - $row_class[] = array('charge', (++$odd % 2) ? 'oddrow' : 'evnrow'); - - } - - echo $this->element('table', - array('class' => 'item ledger list', - 'caption' => 'Lease #'.$lease['number'].' (Unit: '.$lease['Unit']['name'].')', - 'suppress_alternate_rows' => true, - 'headers' => $headers, - 'rows' => $rows, - 'row_class' => $row_class, - 'column_class' => $headers)); -} -?> +/* End "detail supporting" DIV */ ?> +
diff --git a/site/views/customers/index.ctp b/site/views/customers/index.ctp new file mode 100644 index 0000000..b67aad4 --- /dev/null +++ b/site/views/customers/index.ctp @@ -0,0 +1,3 @@ +
+element('customers', array('heading' => '

'.$heading.'

')) ?> +
diff --git a/site/views/customers/view.ctp b/site/views/customers/view.ctp new file mode 100644 index 0000000..f55c9ec --- /dev/null +++ b/site/views/customers/view.ctp @@ -0,0 +1,189 @@ + + +
+ +element('table', + array('class' => 'item customer detail', + 'caption' => 'Tenant Info', + 'rows' => $rows, + 'column_class' => array('field', 'value'))); + + +/********************************************************************** + * Customer Info Box + */ + +?> +
+
+ Security Deposit: +
+
+ Balance: +
+
+ +
+element('contacts', + array('caption' => 'Customer Contacts', + 'contacts' => $customer['Contact'])); + + +/* foreach ($customer['Contact'] AS $contact) { */ + +/* /\********************************************************************** */ +/* * Phones */ +/* *\/ */ +/* $headers = array('Phone', 'Preference', 'Comment'); */ +/* $rows = array(); */ +/* foreach($contact['ContactPhone'] AS $phone) { */ +/* $rows[] = array(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)); */ + + +/* /\********************************************************************** */ +/* * Emails */ +/* *\/ */ +/* $headers = array('Email', 'Preference', 'Comment'); */ +/* $rows = array(); */ +/* foreach($contact['ContactEmail'] 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)); */ + + +/* /\********************************************************************** */ +/* * Addresses */ +/* *\/ */ +/* $headers = array('Address', 'Preference', 'Comment'); */ +/* $rows = array(); */ +/* foreach($contact['ContactAddress'] AS $address) { */ +/* $rows[] = array(preg_replace("/\n/", "
\n", $address['address']) . "
\n" . */ +/* $address['city'] . ", " . */ +/* $address['state'] . " " . */ +/* $address['postcode'], */ +/* //. ? "
\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)); */ + + +/********************************************************************** + * Lease History + */ +$headers = array('Lease', 'Unit', 'Signed', 'Move-In', 'Move-Out', 'Rent', 'Deposit', 'Comment'); +$rows = array(); +foreach($customer['Lease'] AS $lease) { + $rows[] = array('#'.$lease['number'], + $html->link($lease['Unit']['name'], + array('controller' => 'units', + 'action' => 'view', + $lease['Unit']['id'])), + datefmt($lease['lease_date']), + datefmt($lease['movein_date']), + datefmt($lease['moveout_date']), + $lease['amount'], + $lease['deposit'], + $lease['comment']); +} + +echo $this->element('table', + array('class' => 'item lease list', + 'caption' => 'Lease History', + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $headers)); + + +/********************************************************************** + * Ledger History + */ +echo $this->element('ledger', + array('caption' => 'Ledger History', + 'transactions' => $customer['Transaction'], + 'ledger' => array('mix'=>1))); + +/* End "detail supporting" DIV */ ?> +
+ +
diff --git a/site/views/elements/accounts.ctp b/site/views/elements/accounts.ctp new file mode 100644 index 0000000..aaf9452 --- /dev/null +++ b/site/views/elements/accounts.ctp @@ -0,0 +1,85 @@ +'.__('Accounts',true).''; + +function currency($number) { + if ($number < 0) + return "($ " . number_format(-1*$number, 2) . ")"; + else + return "$ " . number_format($number, 2); +} + +function datefmt($date) { + $date_fmt = 'm/d/Y'; + return ($date + ? date_format(date_create($date), $date_fmt) + : null); +} + +$headers = array('Name', 'Type', 'Ext. Name', 'Ext. Account', 'Entries', 'Debits', 'Credits', 'Balance', 'Comment'); +$column_class = array(); +foreach (array_intersect($column_class, array('Debits', 'Credits', 'Balance')) AS $k => $v) { + $column_class[$k] = 'currency'; +} + +if (isset($paginator)) { + echo $paginator->counter(array( + 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); + + $headers = array($paginator->sort('name'), + $paginator->sort('type'), + $paginator->sort('Ext. Name', 'external_name'), + $paginator->sort('Ext. Account', 'external_account'), + $paginator->sort('entries'), + $paginator->sort('debits'), + $paginator->sort('credits'), + $paginator->sort('balance'), + $paginator->sort('comment')); +} + +$rows = array(); +foreach ($accounts as $account) { + $extra = null; + if (isset($account[0])) { + $extra = $account[0]; + unset($account[0]); + } + if (isset($account['Account'])) + $account = $account['Account']; + + if (isset($extra)) + $account = array_merge($account, $extra); + + $rows[] = array($html->link($account['name'], + array('controller' => 'accounts', + 'action' => 'view', + $account['id'])), + $account['type'], + $account['external_name'], + $account['external_account'], + $account['entries'], + currency($account['debits']), + currency($account['credits']), + currency($account['balance']), + $account['comment'], + ); +} + +echo $this->element('table', + array('class' => 'item account list', + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $column_class)); + +if (isset($paginator)) { + echo('
' . "\n"); + echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); + echo(' | '); + echo $paginator->numbers(); + echo(' | '); + echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); + echo('
' . "\n"); +} diff --git a/site/views/elements/charges.ctp b/site/views/elements/charges.ctp deleted file mode 100644 index 461da13..0000000 --- a/site/views/elements/charges.ctp +++ /dev/null @@ -1,68 +0,0 @@ -'.__('Charges',true).''; - -function currency($number) { - if ($number < 0) - return "($ " . number_format(-1*$number, 2) . ")"; - else - return "$ " . number_format($number, 2); -} - -function datefmt($date) { - $date_fmt = 'm/d/Y'; - return ($date - ? date_format(date_create($date), $date_fmt) - : null); -} - -$headers_manual = array('ID', 'Date', 'Due', 'Type', 'Lease', 'Amount', 'Comment'); -if (isset($paginator)) { - echo $paginator->counter(array( - 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); - - $headers = array($paginator->sort('id'), - $paginator->sort('Date', 'charge_date'), - $paginator->sort('Due', 'due_date'), - $paginator->sort('Type', 'charge_type'), - $paginator->sort('Lease', 'number'), - $paginator->sort('total'), - $paginator->sort('comment')); -} else { - $headers = $headers_manual; -} - - -$rows = array(); -foreach ($charges as $charge) { - $rows[] = array($html->link($charge['Charge']['id'], - array('controller' => 'charges', - 'action' => 'view', - $charge['Charge']['id'])), - datefmt($charge['Charge']['charge_date']), - datefmt($charge['Charge']['due_date']), - $charge['ChargeType']['name'], - '#'.$charge['Lease']['number'], - currency($charge['Charge']['total']), - $charge['Charge']['comment'], - ); -} - -echo $this->element('table', - array('class' => 'item charge list', - 'headers' => $headers, - 'rows' => $rows, - 'column_class' => $headers_manual)); - -if (isset($paginator)) { - echo('
' . "\n"); - echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); - echo(' | '); - echo $paginator->numbers(); - echo(' | '); - echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); - echo('
' . "\n"); -} diff --git a/site/views/elements/contacts.ctp b/site/views/elements/contacts.ctp index fca941d..54c10c3 100644 --- a/site/views/elements/contacts.ctp +++ b/site/views/elements/contacts.ctp @@ -2,44 +2,57 @@ if (isset($heading)) echo $heading; -else +elseif (!isset($caption)) echo '

'.__('Contacts',true).'

'; -$headers_manual = array('Id', 'Last Name', 'First Name', 'Company', 'Comment'); +$headers_manual = array_merge(array('Id', 'Last Name', 'First Name', 'Company'), + isset($contacts[0]['ContactsCustomer']) ? array('Type', 'Active') : array(), + array('Comment')); if (isset($paginator)) { echo $paginator->counter(array( 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); - $headers = array($paginator->sort('id'), - $paginator->sort('last_name'), - $paginator->sort('first_name'), - $paginator->sort('company_name'), - //$paginator->sort('unit_id'), - $paginator->sort('comment')); + $headers = array_merge(array($paginator->sort('id'), + $paginator->sort('last_name'), + $paginator->sort('first_name'), + $paginator->sort('company_name')), + (isset($contacts[0]['ContactsCustomer']) + ? array($paginator->sort('type'), + $paginator->sort('active')) + : array()), + array($paginator->sort('comment'))); } else { $headers = $headers_manual; } $rows = array(); foreach ($contacts as $contact) { - $rows[] = array($html->link($contact['Contact']['id'], - array('controller' => 'contacts', - 'action' => 'view', - $contact['Contact']['id'])), - $html->link($contact['Contact']['last_name'], - array('controller' => 'contacts', - 'action' => 'view', - $contact['Contact']['id'])), - $html->link($contact['Contact']['first_name'], - array('controller' => 'contacts', - 'action' => 'view', - $contact['Contact']['id'])), - $contact['Contact']['company_name'], - $contact['Contact']['comment']); + if (isset($contact['Contact'])) + $contact = $contact['Contact']; + + $rows[] = array_merge(array($html->link($contact['id'], + array('controller' => 'contacts', + 'action' => 'view', + $contact['id'])), + $html->link($contact['last_name'], + array('controller' => 'contacts', + 'action' => 'view', + $contact['id'])), + $html->link($contact['first_name'], + array('controller' => 'contacts', + 'action' => 'view', + $contact['id'])), + $contact['company_name']), + (isset($contact['ContactsCustomer']) + ? array($contact['ContactsCustomer']['type'], + $contact['ContactsCustomer']['active'], + $contact['ContactsCustomer']['comment']) + : array($contact['comment']))); } echo $this->element('table', array('class' => 'item contact list', + 'caption' => isset($caption) ? $caption : null, 'headers' => $headers, 'rows' => $rows, 'column_class' => $headers_manual)); diff --git a/site/views/elements/receipts.ctp b/site/views/elements/customers.ctp similarity index 53% rename from site/views/elements/receipts.ctp rename to site/views/elements/customers.ctp index e89adbd..38cf034 100644 --- a/site/views/elements/receipts.ctp +++ b/site/views/elements/customers.ctp @@ -3,46 +3,39 @@ if (isset($heading)) echo $heading; else - echo '

'.__('Receipts',true).'

'; + echo '

'.__('Customers',true).'

'; -function currency($number) { - if ($number < 0) - return "($ " . number_format(-1*$number, 2) . ")"; - else - return "$ " . number_format($number, 2); -} - -function datefmt($date) { - $date_fmt = 'm/d/Y'; - return ($date - ? date_format(date_create($date), $date_fmt) - : null); -} - -$headers_manual = array('Id', 'Timestamp', 'Comment'); +$headers_manual = array('Id', 'Name', 'Comment'); if (isset($paginator)) { echo $paginator->counter(array( 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); $headers = array($paginator->sort('id'), - $paginator->sort('Timestamp', 'stamp'), + $paginator->sort('name'), $paginator->sort('comment')); } else { $headers = $headers_manual; } $rows = array(); -foreach ($receipts as $receipt) { - $rows[] = array($html->link($receipt['Receipt']['id'], - array('controller' => 'receipts', +foreach ($customers as $customer) { + if (isset($customer['Customer'])) + $customer = $customer['Customer']; + + $rows[] = array($html->link($customer['id'], + array('controller' => 'customers', 'action' => 'view', - $receipt['Receipt']['id'])), - datefmt($receipt['Receipt']['stamp']), - $receipt['Receipt']['comment']); + $customer['id'])), + $html->link($customer['name'], + array('controller' => 'customers', + 'action' => 'view', + $customer['id'])), + $customer['comment']); } echo $this->element('table', - array('class' => 'item receipt list', + array('class' => 'item customer list', + 'caption' => isset($caption) ? $caption : null, 'headers' => $headers, 'rows' => $rows, 'column_class' => $headers_manual)); diff --git a/site/views/elements/ledger.ctp b/site/views/elements/ledger.ctp index 7e7cf04..4ae5d62 100644 --- a/site/views/elements/ledger.ctp +++ b/site/views/elements/ledger.ctp @@ -1,314 +1,80 @@ '.__('Payments',true).''; */ - -?> - -
- - -link('#'.$charge['id'], - array('controller' => 'charges', - 'action' => 'view', - $charge['id'])), - datefmt($charge['charge_date']), - datefmt($charge['charge_to_date']), - $charge['ChargeType']['name'], - $charge['comment'], - currency($amount), - currency($balance), - //currency($amount - $paid)); - currency($running_total)); - - $row_class[] = 'charge'; - } - - echo ('
' . "\n"); - echo $this->element('table', - array('class' => 'item ledger list', - 'caption' => $caption, - 'headers' => $headers, - 'rows' => $rows, - 'row_class' => $row_class, - 'column_class' => $headers)); - echo ('
' . "\n"); +$headers = array('Transaction', 'Entry', 'Date', 'Customer', 'Comment', 'Debit', 'Credit', 'Total'); +$column_class = $headers; +foreach (array_intersect($column_class, array('Transaction', 'Entry')) AS $k => $v) { + $column_class[$k] = array($column_class[$k], 'id'); } - - -/********************************************************************** - * Receipts Only - */ - -if (isset($ledger['receipts'])) { - $headers = array('Receipt', 'Date', 'Comment', 'Amount', 'Balance', 'Total'); - - $receipts = array(); - foreach ($lease['Charge'] AS $charge) { - foreach($charge['Receipt'] AS $receipt) { - if (!isset($receipts[$receipt['id']])) { - $receipts[$receipt['id']] = $receipt; - $receipts[$receipt['id']]['amount'] = 0; - $receipts[$receipt['id']]['charge'] = 0; - foreach($receipt['Payment'] AS $payment) - $receipts[$receipt['id']]['amount'] += $payment['amount']; - unset($receipts[$receipt['id']]['ChargesReceipt']); - unset($receipts[$receipt['id']]['Payment']); - } - $receipts[$receipt['id']]['charge'] += $receipt['ChargesReceipt']['amount']; - } - } - - usort($receipts, - create_function('$a, $b', - '$adate = TimeHelper::toUnix(isset($a["charge_date"]) ? $a["charge_date"] : $a["stamp"]); ' . - '$bdate = TimeHelper::toUnix(isset($b["charge_date"]) ? $b["charge_date"] : $b["stamp"]); ' . - 'return strcmp($adate, $bdate);') - ); - - $rows = array(); - $row_class = array(); - $running_total = 0; - - foreach ($receipts AS $receipt) { - $amount = $receipt['amount']; - $balance = $amount - $receipt['charge']; - $running_total += $balance; - - $rows[] = array($html->link('#'.$receipt['id'], - array('controller' => 'receipts', - 'action' => 'view', - $receipt['id'])), - datefmt($receipt['stamp']), - $receipt['comment'], - currency($amount), - currency($balance), - currency($running_total)); - - $row_class[] = 'receipt'; - } - - echo ('
' . "\n"); - echo $this->element('table', - array('class' => 'item ledger list', - 'caption' => $caption, - 'headers' => $headers, - 'rows' => $rows, - 'row_class' => $row_class, - 'column_class' => $headers)); - echo ('
' . "\n"); +foreach (array_intersect($column_class, array('Debits', 'Credits', 'Total')) AS $k => $v) { + $column_class[$k] = array($column_class[$k], 'currency'); } +/* if (isset($paginator)) { */ +/* echo $paginator->counter(array( */ +/* 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); */ -/* $headers = array('Receipt', 'Date', 'Comment', 'Amount', 'Balance', 'Total'); */ - -/* $rows = array(); */ -/* $row_class = array(); */ -/* $running_total = 0; */ -/* $odd = 0; */ -/* foreach($lease['Receipt'] AS $charge) { */ -/* $amount = $charge['total']; */ - -/* $balance = $amount; */ -/* foreach ($charge['Receipt'] AS $receipt) */ -/* $balance -= $receipt['ChargesReceipt']['amount']; */ - -/* $running_total += $balance; */ - - -/* $charge_amount = 0; */ -/* $payment_amount = 0; */ -/* foreach($receipt['Charge'] AS $charge) */ -/* $charge_amount += $charge['ChargesReceipt']['amount']; */ -/* foreach($receipt['Payment'] AS $payment) */ -/* $payment_amount += $payment['amount']; */ - -/* foreach ($charge['Receipt'] AS $receipt) { */ -/* $amount = -1 * $receipt['ChargesReceipt']['amount']; */ -/* $running_total += $amount; */ -/* $rows[] = array($html->link('#'.$receipt['id'], */ -/* array('controller' => 'receipts', */ -/* 'action' => 'view', */ -/* $receipt['id'])), */ -/* datefmt($receipt['stamp']), */ -/* $receipt['comment'], */ -/* currency($amount), */ -/* currency($running_total)); */ -/* $row_class[] = array('receipt', ($odd % 2) ? 'oddrow' : 'evnrow'); */ -/* } */ - -/* $rows[] = array($html->link('#'.$charge['id'], */ -/* array('controller' => 'charges', */ -/* 'action' => 'view', */ -/* $charge['id'])), */ -/* datefmt($charge['charge_date']), */ -/* datefmt($charge['charge_to_date']), */ -/* $charge['ChargeType']['name'], */ -/* $charge['comment'], */ -/* currency($amount), */ -/* currency($balance), */ -/* //currency($amount - $paid)); */ -/* currency($running_total)); */ - -/* $row_class[] = array('charge', (++$odd % 2) ? 'oddrow' : 'evnrow'); */ +/* $headers = array($paginator->sort('Transaction', 'transaction_id'), */ +/* $paginator->sort('entry_id'), */ +/* $paginator->sort('Date', 'stamp'), */ +/* $paginator->sort('customer_id'), */ +/* $paginator->sort('comment'), */ +/* $paginator->sort('debit'), */ +/* $paginator->sort('credit'), */ +/* $paginator->sort('total')); */ /* } */ -/* echo ('
' . "\n"); */ -/* echo $this->element('table', */ -/* array('class' => 'item ledger list', */ -/* 'caption' => $caption */ -/* 'suppress_alternate_rows' => true, */ -/* 'headers' => $headers, */ -/* 'rows' => $rows, */ -/* 'row_class' => $row_class, */ -/* 'column_class' => $headers)); */ -/* echo ('
' . "\n"); */ +$rows = array(); +$running_total = 0; +foreach($entries AS $entry) { + $transaction = $entry['Transaction']; + $customer = $entry['Customer']; + $credit = $debit = null; + $running_total += $entry['balance']; -/********************************************************************** - * Mixture - */ + if (isset($entry['debit'])) + $debit = $entry['debit']; + if (isset($entry['credit'])) + $credit = $entry['credit']; -if (isset($ledger['mix'])) { - $headers = array(/*'Charge/Receipt'*/'ID', 'Date', /*'Through',*/ 'Type', 'Comment', 'Amount', 'Total'); + // Now that we've extracted top level 'entry' data + // move our variable to the meat of 'LedgerEntry' for clarity + $entry = $entry['LedgerEntry']; -/* $mix = array_merge($lease['Charge'], $receipts); */ -/* usort($mix, */ -/* create_function('$a, $b', */ -/* '$adate = TimeHelper::toUnix(isset($a["charge_date"]) ? $a["charge_date"] : $a["stamp"]); ' . */ -/* '$bdate = TimeHelper::toUnix(isset($b["charge_date"]) ? $b["charge_date"] : $b["stamp"]); ' . */ -/* 'return strcmp($adate, $bdate);') */ -/* ); */ - - $rows = array(); - $row_class = array(); - $running_total = 0; - - foreach ($transactions AS $transaction) { - $transaction_date = datefmt($transaction['stamp']); - if (isset($transaction['through_date'])) - $transaction_date .= ' - '. datefmt($transaction['through_date']); - - $comment = $transaction['comment']; - - foreach ($transaction['Entry'] AS $entry) { - if ($entry['DebitAccount']['name'] === 'A/R') { - $name = $entry['CreditAccount']['name']; - $amount = $entry['amount']; - $class = 'charge'; - } - elseif ($entry['CreditAccount']['name'] === 'A/R') { - $name = 'Payment'; - $amount = -1 * $entry['amount']; - $class = 'payment'; - } - else - continue; - - $running_total += $amount; - $rows[] = array($html->link('#'.$transaction['id'], - array('controller' => 'transactions', - 'action' => 'view', - $transaction['id'])), - $transaction_date, - $name, - $comment, - currency($amount), - currency($running_total)); - $row_class[] = $class; - } - } - - echo ('
' . "\n"); - echo $this->element('table', - array('class' => 'item ledger list', - 'caption' => $caption, - //'suppress_alternate_rows' => true, - 'headers' => $headers, - 'rows' => $rows, - 'row_class' => $row_class, - 'column_class' => $headers)); - echo ('
' . "\n"); + $rows[] = array($html->link('#'.$transaction['id'], + array('controller' => 'transactions', + 'action' => 'view', + $transaction['id'])), + $html->link('#'.$entry['id'], + array('controller' => 'ledger_entries', + 'action' => 'view', + $entry['id'])), + datefmt($transaction['stamp']), + $html->link($customer['name'], + array('controller' => 'customers', + 'action' => 'view', + $customer['id'])), + comment(array($transaction['comment'], $entry['comment'])), + currency($debit), + currency($credit), + currency($running_total) + ); } -/********************************************************************** - * Match - */ +echo $this->element('table', + array('class' => 'item account ledger list', + 'caption' => $caption, + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $column_class)); -if (isset($ledger['match'])) { - $headers = array(/*'Charge/Receipt'*/'ID', 'Date', /*'Through',*/ 'Type', 'Comment', 'Amount', 'Total'); +/* if (isset($paginator)) { */ +/* echo('
' . "\n"); */ +/* echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); */ +/* echo(' | '); */ +/* echo $paginator->numbers(); */ +/* echo(' | '); */ +/* echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); */ +/* echo('
' . "\n"); */ +/* } */ - $rows = array(); - $row_class = array(); - $running_total = 0; - $odd = 0; - foreach($lease['Charge'] AS $charge) { - $amount = $charge['total']; - $running_total += $amount; - $rows[] = array($html->link('#'.$charge['id'], - array('controller' => 'charges', - 'action' => 'view', - $charge['id'])), - datefmt($charge['charge_date']) .' - '. datefmt($charge['charge_to_date']), - $charge['ChargeType']['name'], - $charge['comment'], - currency($amount), - currency($running_total)); - $row_class[] = array('charge', (++$odd % 2) ? 'oddrow' : 'evnrow'); - - foreach ($charge['Receipt'] AS $receipt) { - $amount = -1 * $receipt['ChargesReceipt']['amount']; - $running_total += $amount; - $rows[] = array($html->link('#'.$receipt['id'], - array('controller' => 'receipts', - 'action' => 'view', - $receipt['id'])), - ' -- ' . datefmt($receipt['stamp']), - 'Payment Applied', - $receipt['comment'], - currency($amount), - currency($running_total)); - $row_class[] = array('receipt', ($odd % 2) ? 'oddrow' : 'evnrow'); - } - } - - echo ('
' . "\n"); - echo $this->element('table', - array('class' => 'item ledger list', - 'caption' => $caption, - 'suppress_alternate_rows' => true, - 'headers' => $headers, - 'rows' => $rows, - 'row_class' => $row_class, - 'column_class' => $headers)); - echo ('
' . "\n"); -} \ No newline at end of file +?> diff --git a/site/views/elements/ledgers.ctp b/site/views/elements/ledgers.ctp new file mode 100644 index 0000000..13c4219 --- /dev/null +++ b/site/views/elements/ledgers.ctp @@ -0,0 +1,77 @@ +'.__('Ledgers',true).''; + +$headers = array_merge(array('Name'), + (isset($ledgers[0]['Account']) + ? array('Account') + : array()), + array('Entries', 'Debits', 'Credits', 'Balance', 'Closed', 'Comment')); +$column_class = array(); +foreach (array_intersect($column_class, array('Comment')) AS $k => $v) { + $column_class[$k] = 'comment'; +} + +if (isset($paginator)) { + echo $paginator->counter(array( + 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); + + $headers = array_merge(array($paginator->sort('name')), + (isset($ledgers[0]['Account']) + ? array($paginator->sort('Account', 'Account.name')) + : array()), + array($paginator->sort('entries'), + $paginator->sort('debits'), + $paginator->sort('credits'), + $paginator->sort('balance'), + $paginator->sort('closed'), + $paginator->sort('comment'))); +} + +$rows = array(); +foreach ($ledgers as $ledger) { + if (isset($ledger[0])) + $ledger = array_merge($ledger[0], array_diff_key($ledger, array(0=>1))); + if (isset($ledger['Ledger'])) + $ledger = array_merge($ledger['Ledger'], array_diff_key($ledger, array('Ledger'=>1))); + + if (isset($ledger['Account'])) + $account = $ledger['Account']; + + $rows[] = array_merge(array($html->link($ledger['name'], + array('controller' => 'ledgers', + 'action' => 'view', + $ledger['id']))), + (isset($ledger['Account']) + ? array($html->link($account['name'], + array('controller' => 'accounts', + 'action' => 'view', + $account['id']))) + : array()), + array($ledger['entries'], + currency($ledger['debits']), + currency($ledger['credits']), + currency($ledger['balance']), + $ledger['closed'] ? 'Closed' : 'Open', + $ledger['comment'])); +} + +echo $this->element('table', + array('class' => 'item ledger list', + 'caption' => isset($caption) ? $caption : null, + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $column_class)); + +if (isset($paginator)) { + echo('
' . "\n"); + echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); + echo(' | '); + echo $paginator->numbers(); + echo(' | '); + echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); + echo('
' . "\n"); +} diff --git a/site/views/elements/payments.ctp b/site/views/elements/payments.ctp deleted file mode 100644 index 6a8818c..0000000 --- a/site/views/elements/payments.ctp +++ /dev/null @@ -1,67 +0,0 @@ -'.__('Payments',true).''; - -function currency($number) { - if ($number < 0) - return "($ " . number_format(-1*$number, 2) . ")"; - else - return "$ " . number_format($number, 2); -} - -function datefmt($date) { - $date_fmt = 'm/d/Y'; - return ($date - ? date_format(date_create($date), $date_fmt) - : null); -} - -$headers_manual = array('ID', 'Type', 'Receipt', 'Amount', 'Comment'); -if (isset($paginator)) { - echo $paginator->counter(array( - 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); - - $headers = array($paginator->sort('id'), - $paginator->sort('Type', 'payment_type'), - $paginator->sort('Receipt', 'receipt_id'), - $paginator->sort('amount'), - $paginator->sort('comment')); -} else { - $headers = $headers_manual; -} - - -$rows = array(); -foreach ($payments as $payment) { - $rows[] = array($html->link($payment['Payment']['id'], - array('controller' => 'payments', - 'action' => 'view', - $payment['Payment']['id'])), - $payment['PaymentType']['name'], - $html->link('#'.$payment['Receipt']['id'], - array('controller' => 'receipts', - 'action' => 'view', - $payment['Receipt']['id'])), - currency($payment['Payment']['amount']), - $payment['Payment']['comment'], - ); -} - -echo $this->element('table', - array('class' => 'item payment list', - 'headers' => $headers, - 'rows' => $rows, - 'column_class' => $headers_manual)); - -if (isset($paginator)) { - echo('
' . "\n"); - echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); - echo(' | '); - echo $paginator->numbers(); - echo(' | '); - echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); - echo('
' . "\n"); -} diff --git a/site/views/elements/table.ctp b/site/views/elements/table.ctp index de95c71..32bc8d5 100644 --- a/site/views/elements/table.ctp +++ b/site/views/elements/table.ctp @@ -32,7 +32,7 @@ if (isset($rows) && is_array($rows) && count($rows)) { if (!is_array($rca)) $rca = array($rca); foreach ($rca AS &$rc) - $rc = preg_replace("/ /", "-", strtolower($rc)); + $rc = preg_replace("/ /", "-", preg_replace('/\./', '', strtolower($rc))); } // Same prework for column_class @@ -40,7 +40,7 @@ if (isset($rows) && is_array($rows) && count($rows)) { if (!is_array($cca)) $cca = array($cca); foreach ($cca AS &$cc) - $cc = preg_replace("/ /", "-", strtolower($cc)); + $cc = preg_replace("/ /", "-", preg_replace('/\./', '', strtolower($cc))); } // Associate each cell with the appropriate class(es). diff --git a/site/views/elements/transactions.ctp b/site/views/elements/transactions.ctp new file mode 100644 index 0000000..abf2535 --- /dev/null +++ b/site/views/elements/transactions.ctp @@ -0,0 +1,65 @@ +'.__('Transactions',true).''; + +$headers = array('Id', 'Timestamp', 'Comment'); +$column_class = array(); +foreach (array_intersect($headers, array('Comment')) AS $k => $v) { + $column_class[$k] = 'comment'; +} +foreach (array_intersect($headers, array('Id')) AS $k => $v) { + $column_class[$k] = 'id'; +} + +if (isset($paginator)) { + echo $paginator->counter(array( + 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); + + $headers = array($paginator->sort('id'), + $paginator->sort('customer_id'), + $paginator->sort('Timestamp', 'stamp'), + $paginator->sort('Through', 'through_date'), + $paginator->sort('Due', 'due_date'), + $paginator->sort('comment')); +} + +$rows = array(); +foreach ($transactions as $transaction) { + $customer = $transaction['Customer']; + + if (isset($transaction['Transaction'])) + $transaction = $transaction['Transaction']; + + $rows[] = array($html->link('#'.$transaction['id'], + array('controller' => 'transactions', + 'action' => 'view', + $transaction['id'])), + $html->link($customer['name'], + array('controller' => 'customers', + 'action' => 'view', + $customer['id'])), + datefmt($transaction['stamp']), + datefmt($transaction['through_date']), + datefmt($transaction['due_date']), + $transaction['comment']); +} + +echo $this->element('table', + array('class' => 'item transaction list', + 'caption' => isset($caption) ? $caption : null, + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $column_class)); + +if (isset($paginator)) { + echo('
' . "\n"); + echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); + echo(' | '); + echo $paginator->numbers(); + echo(' | '); + echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); + echo('
' . "\n"); +} diff --git a/site/views/ledgers/index.ctp b/site/views/ledgers/index.ctp new file mode 100644 index 0000000..ad27c94 --- /dev/null +++ b/site/views/ledgers/index.ctp @@ -0,0 +1,14 @@ +
+ +element('ledgers', array('heading' => '

'.$heading.'

')) ?> +
diff --git a/site/views/ledgers/view.ctp b/site/views/ledgers/view.ctp new file mode 100644 index 0000000..63320e3 --- /dev/null +++ b/site/views/ledgers/view.ctp @@ -0,0 +1,98 @@ + + +
+ +link($ledger['Account']['name'], + array('controller' => 'accounts', + 'action' => 'view', + $ledger['Account']['id']))), + array('Closed', $ledger['Ledger']['closed']), + array('Comment', $ledger['Ledger']['comment'])); + +echo $this->element('table', + array('class' => 'item ledger detail', + 'caption' => 'Ledger Detail', + 'rows' => $rows, + 'column_class' => array('field', 'value'))); + + +/********************************************************************** + * Ledger Info Box + */ + +?> + +
+
+ Ledger Balance: +
+
+ +
+element('ledger', + array('caption' => $ledger['Ledger']['name'], + 'ledger' => array('id' => $ledger['Ledger']['id'], + 'type' => $ledger['Account']['type']), + 'entries' => $ledger['LedgerEntry'])); + +/* End "detail supporting" DIV */ ?> +
+ +
diff --git a/site/views/payments/index.ctp b/site/views/payments/index.ctp deleted file mode 100644 index 4258e83..0000000 --- a/site/views/payments/index.ctp +++ /dev/null @@ -1,3 +0,0 @@ -
-element('payments', array('heading' => '

'.$heading.'

')) ?> -
diff --git a/site/views/payments/view.ctp b/site/views/payments/view.ctp deleted file mode 100644 index 7bca3fd..0000000 --- a/site/views/payments/view.ctp +++ /dev/null @@ -1,43 +0,0 @@ - - -
- -link('#'.$payment['Receipt']['id'], - array('controller' => 'receipts', - 'action' => 'view', - $payment['Receipt']['id']))), - array('Amount', currency($payment['Payment']['amount'])), - array('Comment', $payment['Payment']['comment'])); - -echo $this->element('table', - array('class' => 'item payment detail', - 'caption' => 'Payment Info', - 'rows' => $rows, - 'column_class' => array('field', 'value'))); - - -?> - -
diff --git a/site/views/receipts/index.ctp b/site/views/receipts/index.ctp deleted file mode 100644 index e6ce32d..0000000 --- a/site/views/receipts/index.ctp +++ /dev/null @@ -1,3 +0,0 @@ -
-element('receipts', array('heading' => '

'.$heading.'

')) ?> -
diff --git a/site/views/receipts/view.ctp b/site/views/receipts/view.ctp deleted file mode 100644 index 3b4c42f..0000000 --- a/site/views/receipts/view.ctp +++ /dev/null @@ -1,116 +0,0 @@ - - -
- -element('table', - array('class' => 'item receipt detail', - 'caption' => 'Receipt Info', - 'rows' => $rows, - 'column_class' => array('field', 'value'))); - - -?> -
-
- Amount Received: -
-
- Amount Applied: -
-
-link('#'.$payment['id'], - array('controller' => 'payments', - 'action' => 'view', - $payment['id'])), - $payment['PaymentType']['name'], - $payment['comment'], - currency($payment['amount']), - currency($running_total) - ); -} - -echo $this->element('table', - array('class' => 'item payment list', - 'caption' => 'Payments in Receipt', - 'headers' => $headers, - 'rows' => $rows, - 'column_class' => $headers)); - - -/********************************************************************** - * Charges - */ - -$headers = array('ID', 'Date', /*'Due',*/ 'Type', 'Lease', 'Comment', 'Amount' /*, 'Tax', 'Subtotal'*/, 'Applied', /*'Total'*/); -$rows = array(); -$running_total = 0; -foreach($receipt['Charge'] AS $charge) { - $amount = $charge['total']; - $running_total += $amount; - $rows[] = array($html->link('#'.$charge['id'], - array('controller' => 'charges', - 'action' => 'view', - $charge['id'])), - datefmt($charge['charge_date']) .' - '. datefmt($charge['charge_to_date']), - //datefmt($charge['due_date']), - $charge['ChargeType']['name'], - '#'.$charge['Lease']['number'], - $charge['comment'], - //currency($charge['amount']), - //currency($charge['tax']), - currency($charge['total']), - currency($charge['ChargesReceipt']['amount']), - //currency($running_total) - ); -} - -echo $this->element('table', - array('class' => 'item charge list', - 'caption' => 'Charges Applied Towards', - 'headers' => $headers, - 'rows' => $rows, - 'column_class' => $headers)); - - - -?> - -
diff --git a/site/views/transactions/index.ctp b/site/views/transactions/index.ctp new file mode 100644 index 0000000..16f1c5c --- /dev/null +++ b/site/views/transactions/index.ctp @@ -0,0 +1,13 @@ +
+ + + +element('transactions', array('heading' => '

'.$heading.'

')) ?> +
diff --git a/site/views/transactions/view.ctp b/site/views/transactions/view.ctp new file mode 100644 index 0000000..3a9e87f --- /dev/null +++ b/site/views/transactions/view.ctp @@ -0,0 +1,102 @@ + + +
+ +element('table', + array('class' => 'item transaction detail', + 'caption' => 'Transaction Info', + 'rows' => $rows, + 'column_class' => array('field', 'value'))); + + +/********************************************************************** + * Transaction Info Box + */ + +?> +
+
+ Debits: +
+
+ Credits: +
+
+ +
+link($entry['DebitLedger']['name'], + array('controller' => 'ledgers', + 'action' => 'view', + $entry['DebitLedger']['id'])), + $html->link($entry['CreditLedger']['name'], + array('controller' => 'ledgers', + 'action' => 'view', + $entry['CreditLedger']['id'])), + $entry['comment'], + currency($entry['amount']), + currency($running_total) + ); +} + +echo $this->element('table', + array('class' => 'item entry list', + 'caption' => 'Entries in Transaction', + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $headers)); + + +/* End "detail supporting" DIV */ ?> +
+ +
diff --git a/site/views/units/view.ctp b/site/views/units/view.ctp index 04a84a8..5bc79ce 100644 --- a/site/views/units/view.ctp +++ b/site/views/units/view.ctp @@ -1,6 +1,6 @@ -
+
element('table', 'column_class' => array('field', 'value'))); +/********************************************************************** + * Unit Info Box + */ + ?> -
+
Security Deposit:
@@ -42,7 +51,17 @@ echo $this->element('table', Balance:
+ +
link($lease['Contact'][0]['display_name'], - array('controller' => 'contacts', + $html->link($lease['Customer']['name'], + array('controller' => 'customers', 'action' => 'view', - $lease['Contact'][0]['id'])), + $lease['Customer']['id'])), datefmt($lease['lease_date']), datefmt($lease['movein_date']), datefmt($lease['moveout_date']), @@ -76,12 +95,15 @@ echo $this->element('table', * Ledger History */ foreach($unit['Lease'] AS $lease) { - $caption = 'Lease #'.$lease['number'].' (Tenant: '.$lease['Contact'][0]['display_name'].')'; + pr($lease); + $caption = 'Lease #'.$lease['number'].' (Tenant: '.$lease['Customer']['name'].')'; echo $this->element('ledger', - array('lease' => $lease, - 'caption' => $caption, - 'ledger' => array('charges'=>1, 'receipts'=>1, 'match'=>1, 'zmix'=>1))); + array('caption' => $caption, + 'entries' => $lease['Customer']['Transaction'], + 'ledger' => array('mix'=>1))); } -?> + +/* End "detail supporting" DIV */ ?> +
diff --git a/site/webroot/css/layout.css b/site/webroot/css/layout.css index b814585..3f7e015 100644 --- a/site/webroot/css/layout.css +++ b/site/webroot/css/layout.css @@ -60,45 +60,16 @@ tr.evnrow { background: #f4f4f4; } /************************************************************ ************************************************************ - * Item table formats + * Item detail formats + * (such as Tenant Info, Unit Info, etc) */ -/* Item listing width and borders */ -table.detail { width : 60%; } -table.list { width : 100%; } +table.detail { width : 60%; + float: left; } +table.detail td.field { width: 10em; } -/* Text alignment exceptions */ -table.list td.id { text-align: center; } +div.detail.supporting { clear : both; } -/* White spacing exceptions */ -td.comment { white-space: normal; } - -/* Detail Tables (such as Tenant Info, Unit Info, etc) */ -table.detail { float: left; } -table.detail td.field { width: 10em; } - -/* List Tables (listing multiple items of one type) */ -table.list { clear: both; } - -/* Contact methods */ -table.list.phone td.preference , -table.list.email td.preference , -table.list.address td.preference { width: 18em; } -table.list.phone td.phone , -table.list.email td.email , -table.list.address td.address { width: 15em; } -table.list.phone td.comment , -table.list.email td.comment , -table.list.address td.comment { width: auto; } - -/* Leases */ -table.list.lease td.comment { width : 99%; } - -/* Ledger Entries */ -table.list.ledger td { border-top : 1px dashed #ccc; } -table.list.ledger td.date.receipt { padding-left: 1em; } -table.list.ledger td.evnrow { background: #f4f4f4; } -table.list.ledger td.comment { width : 99%; } /************************************************************ @@ -123,6 +94,48 @@ div.summary { color: #993; } +/************************************************************ + ************************************************************ + * Item table formats + * (listing multiple items of one type) + */ + +/* Item listing width and borders */ +table.list { width : 100%; } + +/* Text alignment exceptions */ +table.list td.id { text-align: center; } +table.list td.currency { text-align: right; } + +/* White spacing exceptions */ +td.comment { white-space: normal; } + +/* Contacts */ +table.list.contact td.comment { width : 66%; } + +/* Contact methods */ +table.list.phone td.preference , +table.list.email td.preference , +table.list.address td.preference { width: 18em; } +table.list.phone td.phone , +table.list.email td.email , +table.list.address td.address { width: 15em; } +table.list.phone td.comment , +table.list.email td.comment , +table.list.address td.comment { width: auto; } + +/* Leases */ +table.list.lease td.comment { width : 99%; } + +/* Ledger Entries */ +table.list.ledger td { border-top : 1px dashed #ccc; } +table.list.ledger td.date.receipt { padding-left: 1em; } +table.list.ledger td.evnrow { background: #f4f4f4; } +table.list.ledger td.comment { width : 99%; } + +/* Account Ledger Entries */ + + /************************************************************ ************************************************************ * General Style Info From bb5b563738cb395cfeacfaa34539ad6ebab487a9 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 6 Jun 2009 20:23:54 +0000 Subject: [PATCH 071/717] Removed the .bak files, since everything has now been snapshotted. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@72 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/accounts_controller.php.bak | 244 ------------------- 1 file changed, 244 deletions(-) delete mode 100644 site/controllers/accounts_controller.php.bak diff --git a/site/controllers/accounts_controller.php.bak b/site/controllers/accounts_controller.php.bak deleted file mode 100644 index 237b95d..0000000 --- a/site/controllers/accounts_controller.php.bak +++ /dev/null @@ -1,244 +0,0 @@ - 100, - 'link' => - array(// Models - 'CurrentLedger' => array - (// Models - 'LedgerEntry' => - array('fields' => - array('SUM(IF(LedgerEntry.debit_account_id = Account.id, LedgerEntry.amount, 0)) AS debits', - 'SUM(IF(LedgerEntry.credit_account_id = Account.id, LedgerEntry.amount, 0)) AS credits', - "SUM(IF(Account.type IN ('ASSET', 'EXPENSE'), - IF(LedgerEntry.debit_account_id = Account.id, 1, -1), - IF(LedgerEntry.credit_account_id = Account.id, 1, -1) - )* LedgerEntry.amount) AS balance", - 'COUNT(LedgerEntry.id) AS entries'), - 'conditions' => - array('OR' => - array('LedgerEntry.debit_account_id = Account.id', - 'LedgerEntry.credit_account_id = Account.id'), - ), - ), - ), - - 'group' => 'Account.id', - 'order' => array('Account.name' => 'ASC')); - - 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 - * - Lists all accounts - */ - - function index() { - $this->all(); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: asset - * - Lists all asset accounts - */ - - function asset() { - $title = 'Asset Accounts'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('accounts', $this->paginate(array('Account.type' => 'ASSET'))); - $this->render('index'); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: liability - * - Lists all liability accounts - */ - - function liability() { - $title = 'Liability Accounts'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('accounts', $this->paginate(array('Account.type' => 'LIABILITY'))); - $this->render('index'); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: equity - * - Lists all equity accounts - */ - - function equity() { - $title = 'Equity Accounts'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('accounts', $this->paginate(array('Account.type' => 'EQUITY'))); - $this->render('index'); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: income - * - Lists all income accounts - */ - - function income() { - $title = 'Income Accounts'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('accounts', $this->paginate(array('Account.type' => 'INCOME'))); - $this->render('index'); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: expense - * - Lists all expense accounts - */ - - function expense() { - $title = 'Expense Accounts'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('accounts', $this->paginate(array('Account.type' => 'EXPENSE'))); - $this->render('index'); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: all - * - Lists all accounts - */ - - function all() { - $title = 'All Accounts'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('accounts', $this->paginate()); - $this->render('index'); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: view - * - Displays information about a specific account - */ - - function view($id = null) { - if (!$id) { - $this->Session->setFlash(__('Invalid Item.', true)); - $this->redirect(array('action'=>'index')); - } - -/* $this->Account->bindModel(array('hasMany' => array */ -/* ('LedgerEntry' => array */ -/* ('className' => 'LedgerEntry', */ -/* 'foreignKey' => false, */ -/* 'finderQuery' => 'SELECT `LedgerEntry`.* */ -/* FROM pmgr_entries AS `LedgerEntry` */ -/* LEFT JOIN pmgr_transactions AS `Transaction` */ -/* ON `Transaction`.id = `LedgerEntry`.transaction_id */ -/* WHERE LedgerEntry.debit_account_id = ({$__cakeID__$}) */ -/* OR LedgerEntry.credit_account_id = ({$__cakeID__$}) */ -/* ORDER BY Transaction.stamp', */ -/* )))); */ - -/* $this->Account->Behaviors->attach('Containable'); */ -/* $this->Account->Contain(array('LedgerEntry' => array */ -/* ( */ -/* // Models */ -/* 'Transaction' => array */ -/* ( */ -/* // Models */ -/* 'Customer', */ -/* )), */ - -/* )); */ -/* } */ -/* $account = $this->Account->read(null, $id); */ - - $this->Account->recursive = -1; - $account = $this->Account->read(null, $id); - - if (in_array($account['Account']['type'], array('ASSET', 'EXPENSE'))) - $account_type = 'debit'; - else - $account_type = 'credit'; - - $ledger_id = $account['current_ledger_id']; - $account['CurrentLedger']['LedgerEntry'] = - $this->Account->Ledger->LedgerEntry->find - ('all', - array('link' => array - (// Models - 'fields' => - array('id', 'name', 'comment', - "IF(LedgerEntry.debit_ledger_id = $id, LedgerEntry.amount, NULL) AS debit", - "IF(LedgerEntry.credit_ledger_id = $id, LedgerEntry.amount, NULL) AS credit", - "(IF(LedgerEntry.{$account_type}_ledger_id = $id, 1, -1) - * LedgerEntry.amount) AS balance"), - 'conditions' => - array('OR' => - array('LedgerEntry.debit_ledger_id = Account.id', - 'LedgerEntry.credit_ledger_id = Account.id'), - - - 'Transaction' => - array(// Models - 'Customer', - )), - 'conditions' => array('OR' => - array("LedgerEntry.debit_account_id = $id", - "LedgerEntry.credit_account_id = $id")), - 'order' => array('Transaction.stamp'), - //'limit' => 15, - //'limit' => 2, - )); - //pr($account); - - $balance = 0; - foreach($account['LedgerEntry'] AS &$entry) { - if (isset($entry[0])) - $entry = array_merge($entry[0], array_diff_key($entry, array(0))); - - $balance += $entry['balance']; - } - - $title = 'Account: ' . $account['Account']['name']; - $this->set(compact('account', 'title', 'balance')); - } -} From 2e07cb87a5d99b29848dae5bfe96915cf2c370d6 Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 7 Jun 2009 16:23:15 +0000 Subject: [PATCH 072/717] Probably still have some bugs to flush out, but this major overhaul of the conversion code works well enough to check in. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@73 97e9348a-65ac-dc4b-aefc-98561f571b83 --- scripts/sitelink2pmgr.pl | 1478 +++++++++++++++++++------------------- 1 file changed, 751 insertions(+), 727 deletions(-) diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 3badbf2..9082ce6 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -33,263 +33,10 @@ my $db_handle = DBI->connect("DBI:mysql:database=$database;host=$hostname", $SIG{__DIE__} = \&Die; my ($query, $result, $nrows, $row); -my ($aicur_c_id, $aicur_ca_id, $aicur_cp_id, $aicur_ce_id) = (0, 0, 0, 0); -my ($aicur_g_id, $aicur_gp_id, $aicur_user_id) = (0, 0, 0); -my ($aicur_type_id, $aicur_size_id, $aicur_unit_id) = (0, 0, 0); -my ($aicur_site_id, $aicur_area_id) = (0, 0); -my ($aicur_lease_type_id, $aicur_lease_id) = (0, 0); -my ($aicur_charge_id, $aicur_receipt_id, $aicur_payment_id) = (0, 0, 0); -my ($aicur_tx_id) = (0); -my ($aicur_ledger_id) = (0); -my ($aicur_monetary_source_id) = (0); - -open(SCHEMA, "<$schema_file") || die ("Can't open schema ($!)\n"); -my $schema_query = ""; -while () { - next if /^\s*-- /; - $schema_query .= $_; - query($db_handle, $schema_query), $schema_query = "" - if /;\s*$/; -} -close(SCHEMA); - -++$aicur_c_id; -$query = "INSERT INTO pmgr_contacts - (`id`, `first_name`, `middle_name`, `last_name`, `display_name`) VALUES - ($aicur_c_id, 'Abijah', 'M', 'Perkins', 'Perkins, Abijah')"; - query($db_handle, $query) || die("Unable to insert"); - -++$aicur_ca_id; -$query = "INSERT INTO pmgr_contact_addresses - (`id`, `address`, `city`, `state`, `postcode`, `country`) VALUES - ($aicur_ca_id, '1324 N Liberty Lake Rd\nPMB 263', 'Liberty Lake', 'WA', '99019', 'USA')"; - query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO pmgr_contacts_methods - (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES - ($aicur_c_id, 'POST', $aicur_ca_id, 'MAIN', 'PRIMARY')"; - query($db_handle, $query) || die("Unable to insert"); - -++$aicur_ca_id; -$query = "INSERT INTO pmgr_contact_addresses - (`id`, `address`, `city`, `state`, `postcode`, `country`) VALUES - ($aicur_ca_id, '5221 W Myrtlewood Ct', 'Spokane', 'WA', '99208', 'USA')"; - query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO pmgr_contacts_methods - (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES - ($aicur_c_id, 'POST', $aicur_ca_id, 'HOME', 'ALTERNATE')"; - query($db_handle, $query) || die("Unable to insert"); - -++$aicur_ca_id; -$query = "INSERT INTO pmgr_contact_addresses - (`id`, `address`, `city`, `state`, `postcode`, `country`) VALUES - ($aicur_ca_id, 'PO Box 69', 'Granger', 'WA', '98932', 'USA')"; - query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO pmgr_contacts_methods - (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES - ($aicur_c_id, 'POST', $aicur_ca_id, 'HOME', 'ALTERNATE')"; - query($db_handle, $query) || die("Unable to insert"); - -++$aicur_cp_id; -$query = "INSERT INTO pmgr_contact_phones - (`id`, `type`, `phone`) VALUES - ($aicur_cp_id, 'MOBILE', '5098445573')"; - query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO pmgr_contacts_methods - (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES - ($aicur_c_id, 'PHONE', $aicur_cp_id, 'MAIN', 'PRIMARY')"; - query($db_handle, $query) || die("Unable to insert"); - -++$aicur_cp_id; -$query = "INSERT INTO pmgr_contact_phones - (`id`, `type`, `phone`) VALUES - ($aicur_cp_id, 'MOBILE', '5098445973')"; - query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO pmgr_contacts_methods - (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES - ($aicur_c_id, 'PHONE', $aicur_cp_id, 'MAIN', 'ALTERNATE')"; - query($db_handle, $query) || die("Unable to insert"); - -++$aicur_cp_id; -$query = "INSERT INTO pmgr_contact_phones - (`id`, `type`, `phone`) VALUES - ($aicur_cp_id, 'VIRTUAL', '5095901112')"; - query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO pmgr_contacts_methods - (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES - ($aicur_c_id, 'PHONE', $aicur_cp_id, 'BUSINESS', 'WORK')"; - query($db_handle, $query) || die("Unable to insert"); - -++$aicur_cp_id; -$query = "INSERT INTO pmgr_contact_phones - (`id`, `type`, `phone`) VALUES - ($aicur_cp_id, 'LANDLINE', '5098541491')"; - query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO pmgr_contacts_methods - (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES - ($aicur_c_id, 'PHONE', $aicur_cp_id, 'HOME', 'ALTERNATE')"; - query($db_handle, $query) || die("Unable to insert"); - -++$aicur_cp_id; -$query = "INSERT INTO pmgr_contact_phones - (`id`, `type`, `phone`) VALUES - ($aicur_cp_id, 'VIRTUAL', '8774488664')"; - query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO pmgr_contacts_methods - (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES - ($aicur_c_id, 'PHONE', $aicur_cp_id, 'BUSINESS', 'WORK')"; - query($db_handle, $query) || die("Unable to insert"); - -++$aicur_cp_id; -$query = "INSERT INTO pmgr_contact_phones - (`id`, `type`, `phone`) VALUES - ($aicur_cp_id, 'FAX', '8662960131')"; - query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO pmgr_contacts_methods - (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES - ($aicur_c_id, 'PHONE', $aicur_cp_id, 'BUSINESS', 'WORK')"; - query($db_handle, $query) || die("Unable to insert"); - -++$aicur_ce_id; -$query = "INSERT INTO pmgr_contact_emails - (`id`, `email`) VALUES - ($aicur_ce_id, 'abijah\@PerkinsHouse.com')"; - query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO pmgr_contacts_methods - (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES - ($aicur_c_id, 'EMAIL', $aicur_ce_id, 'HOME', 'PRIMARY')"; - query($db_handle, $query) || die("Unable to insert"); - -++$aicur_ce_id; -$query = "INSERT INTO pmgr_contact_emails - (`id`, `email`) VALUES - ($aicur_ce_id, 'abijah\@PerkinsREI.com')"; - query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO pmgr_contacts_methods - (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES - ($aicur_c_id, 'EMAIL', $aicur_ce_id, 'HOME', 'WORK')"; - query($db_handle, $query) || die("Unable to insert"); - -++$aicur_ce_id; -$query = "INSERT INTO pmgr_contact_emails - (`id`, `email`) VALUES - ($aicur_ce_id, 'abijah\@ValleyStorage.com')"; - query($db_handle, $query) || die("Unable to insert"); -$query = "INSERT INTO pmgr_contacts_methods - (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES - ($aicur_c_id, 'EMAIL', $aicur_ce_id, 'BUSINESS', 'WORK')"; - query($db_handle, $query) || die("Unable to insert"); - -++$aicur_g_id; -$query = "INSERT INTO pmgr_groups - (`id`, `code`, `name`) - VALUES - ($aicur_g_id, 'Owner', 'Owner Group')"; - query($db_handle, $query) || die("Unable to insert"); - -++$aicur_gp_id; -$query = "INSERT INTO pmgr_group_permissions - (`group_id`, `name`, `access`) - VALUES - ($aicur_gp_id, 'EVERYTHING', 'FORCED')"; - query($db_handle, $query) || die("Unable to insert"); - - -++$aicur_user_id; -$query = "INSERT INTO pmgr_users - (`id`, `code`, `login`, `contact_id`) - VALUES - ($aicur_user_id, 'AP', 'abijah', $aicur_c_id)"; - query($db_handle, $query) || die("Unable to insert"); - - -++$aicur_site_id; -$query = "INSERT INTO pmgr_sites - (`id`, `code`, `name`) - VALUES - ($aicur_site_id, 'VSS', 'Valley Storage')"; - query($db_handle, $query) || die("Unable to insert"); - -$query = "INSERT INTO pmgr_site_memberships - (`site_id`, `user_id`, `group_id`) - VALUES - ($aicur_site_id, $aicur_user_id, $aicur_g_id)"; - query($db_handle, $query) || die("Unable to insert"); - -++$aicur_area_id; -$query = "INSERT INTO pmgr_site_areas - (`id`, `site_id`, `code`, `name`) - VALUES - ($aicur_area_id, $aicur_site_id, 'Main', 'Main Facility Area')"; - query($db_handle, $query) || die("Unable to insert"); - -++$aicur_lease_type_id; -$query = "INSERT INTO pmgr_lease_types - (`id`, `code`, `name`) - VALUES - ($aicur_lease_type_id, 'SL', 'Storage Lease')"; - query($db_handle, $query) || die("Unable to insert"); - - -my (%account_map, %monetary_type_map); - -$query = "SELECT * FROM pmgr_accounts"; -$result = query($db_handle, $query); -foreach $row (@$result) { - ++$aicur_ledger_id; - $query = "INSERT INTO pmgr_ledgers - (`id`, `account_id`, `name`, `comment`) VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($aicur_ledger_id, $row->{'id'}, - $row->{'name'} . ' Ledger', undef) - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); - $account_map{$row->{'name'}} = {'id' => $row->{'id'}, - 'ledger' => $aicur_ledger_id }; -} - -# $query = -# "UPDATE pmgr_accounts A, pmgr_ledgers L SET A.ledger_id = L.id" . -# " WHERE A.id = L.account_id"; -# query($db_handle, $query); - - -$query = "SELECT * FROM pmgr_monetary_types"; -$result = query($db_handle, $query); -foreach $row (@$result) { - $monetary_type_map{$row->{'name'}} = {'id' => $row->{'id'}, 'name' => $row->{'name'}}; -} - -$account_map{'Late Fee'} = $account_map{'Late Charge'}; - -$monetary_type_map{1} = $monetary_type_map{'Cash'}; -$monetary_type_map{2} = $monetary_type_map{'Check'}; -$monetary_type_map{3} = $monetary_type_map{'Money Order'}; -$monetary_type_map{4} = $monetary_type_map{'ACH'}; -$monetary_type_map{12} = $monetary_type_map{'Other Non-Tillable'}; - -my $monetary_source_internal = undef; - -my $monetary_source_cash = ++$aicur_monetary_source_id; -$query = "INSERT INTO pmgr_monetary_sources - (`id`, `monetary_type_id`, `name`, `comment`) VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($monetary_source_cash, - $monetary_type_map{'Cash'}{'id'}, - 'Cash Source', - 'Monetary source used for any cash transaction') - )) . ")"; -query($db_handle, $query) || die("Unable to insert"); - -my $monetary_source_closing = ++$aicur_monetary_source_id; -$query = "INSERT INTO pmgr_monetary_sources - (`id`, `monetary_type_id`, `name`, `comment`) VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($monetary_source_closing, - $monetary_type_map{'Other Non-Tillable'}{'id'}, - 'Closing Monies Credited', - 'Credited at the closing table') - )) . ")"; -query($db_handle, $query) || die("Unable to insert"); +my (%newdb) = ( 'schema' => [], + 'tables' => {}, + 'ids' => {}, + 'lookup' => {'state' => { 1=>'AK', 14=>'ID', 48=>'WA' }} ); ###################################################################### @@ -311,6 +58,40 @@ sub Die { exit 1; } + +###################################################################### +###################################################################### +## addRow + +sub addRow { + my ($table, $cols, $noid) = @_; + die unless $table; + die unless ref($cols) eq 'HASH'; + + die "Table `$table` is unknown!" + unless defined $newdb{'tables'}{$table}; + + my $id; + if ($noid) { + $id = $cols->{'id'}; + } + + if (!defined $id) { + $id = ++$newdb{'tables'}{$table}{'autoid'}; + } + + $cols->{'id'} = $id + unless ($noid); + + # For debug purposes + my $line = (caller())[2]; + $cols->{'--LINE--'} = "addRow called from line: $line"; + + $newdb{'tables'}{$table}{'rows'}[$id] = $cols; + return $id; +} + + ###################################################################### ###################################################################### ## query @@ -331,9 +112,9 @@ sub query { } if (!$result && !$ignore) { - print "SQL Query FAILED:\n"; - print "$query\n\n"; - print Dumper $data + print STDERR "SQL Query FAILED:\n"; + print STDERR "$sql\n\n"; + print STDERR Dumper $data if defined $data; die; } @@ -341,6 +122,49 @@ sub query { } +###################################################################### +###################################################################### +## executeSchema + +sub executeSchema { + foreach (@{$newdb{'schema'}}) { + query($db_handle, $_); + } + + foreach my $table (values %{$newdb{'tables'}}) { + foreach (@{$table->{'schema'}}) { + query($db_handle, $_); + } + } +} + + +###################################################################### +###################################################################### +## buildTables + +sub buildTables { + foreach my $table (values %{$newdb{'tables'}}) { + foreach (@{$table->{'rows'}}) { + next unless defined $_; + + my %row = %$_; + delete $row{'--LINE--'}; + + my $query; + $query = "INSERT INTO " . $table->{'name'}; + $query .= " (" . join(", ", map({"`$_`"} keys(%row))) . ")"; + $query .= " VALUES (" . join(", ", map({s/'/''/g if defined $_; defined $_ ? "'$_'" : "NULL"} values(%row))) . ")"; + query($db_handle, $query, $_); + } + } +} + + +###################################################################### +###################################################################### +## helper functions + sub sizeCode { my ($width, $depth) = @_; return "YARD" @@ -358,6 +182,316 @@ sub datefmt { return sprintf("%04d-%02d-%02d%s", $dt[2], $dt[0], $dt[1], $dt[3] ? ' '.$dt[3] : ""); } + +###################################################################### +###################################################################### +###################################################################### +###################################################################### +## BUILD THE DATABASE + +open(SCHEMA, "<$schema_file") || die ("Can't open schema ($!)\n"); +my $schema_query = ""; +my $table; +while () { + next if /^\s*--/; + if (/DROP\s+TABLE\s.*`?(pmgr_(\w+))/i) { + $table = $2; + $newdb{'tables'}{$table} = { 'name' => $1, + 'schema' => [], + 'autoid' => 0, + 'rows' => [] }; + } + + $schema_query .= $_; + if (/;\s*$/) { + $schema_query =~ s/^\s+//; + $schema_query =~ s/\s*;\s*$//; + if (!$table) { + push(@{$newdb{'schema'}}, $schema_query); + } else { + push(@{$newdb{'tables'}{$table}{'schema'}}, $schema_query); + } + $schema_query = ""; + } +} +close(SCHEMA); + +executeSchema(); + + +################################################################# +## Test Contact + +addRow('contacts', + { 'first_name' => 'Abijah', + 'middle_name' => 'M', + 'last_name' => 'Perkins' }); + +addRow('contact_addresses', + { 'address' => '1324 N Liberty Lake Rd\nPMB 263', + 'city' => 'Liberty Lake', + 'state' => 'WA', + 'postcode' => '99019', + 'country' => 'USA' }); +addRow('contacts_methods', + { 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'}, + 'method_id' => $newdb{'tables'}{'contact_addresses'}{'autoid'}, + 'method' => 'POST', + 'type' => 'MAIN', + 'preference' => 'PRIMARY' }, + 1); + +addRow('contact_addresses', + { 'address' => '5221 W Myrtlewood Ct', + 'city' => 'Spokane', + 'state' => 'WA', + 'postcode' => '99208', + 'country' => 'USA' }); +addRow('contacts_methods', + { 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'}, + 'method_id' => $newdb{'tables'}{'contact_addresses'}{'autoid'}, + 'method' => 'POST', + 'type' => 'HOME', + 'preference' => 'ALTERNATE' }, + 1); + +addRow('contact_addresses', + { 'address' => 'PO Box 69', + 'city' => 'Granger', + 'state' => 'WA', + 'postcode' => '98932', + 'country' => 'USA' }); +addRow('contacts_methods', + { 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'}, + 'method_id' => $newdb{'tables'}{'contact_addresses'}{'autoid'}, + 'method' => 'POST', + 'type' => 'HOME', + 'preference' => 'ALTERNATE' }, + 1); + +addRow('contact_phones', + { 'type' => 'MOBILE', + 'phone' => '5098445573' }); +addRow('contacts_methods', + { 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'}, + 'method_id' => $newdb{'tables'}{'contact_phones'}{'autoid'}, + 'method' => 'PHONE', + 'type' => 'MAIN', + 'preference' => 'PRIMARY' }, + 1); + +addRow('contact_phones', + { 'type' => 'MOBILE', + 'phone' => '5098445973' }); +addRow('contacts_methods', + { 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'}, + 'method_id' => $newdb{'tables'}{'contact_phones'}{'autoid'}, + 'method' => 'PHONE', + 'type' => 'MAIN', + 'preference' => 'ALTERNATE' }, + 1); + +addRow('contact_phones', + { 'type' => 'VIRTUAL', + 'phone' => '5095901112' }); +addRow('contacts_methods', + { 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'}, + 'method_id' => $newdb{'tables'}{'contact_phones'}{'autoid'}, + 'method' => 'PHONE', + 'type' => 'BUSINESS', + 'preference' => 'WORK' }, + 1); + +addRow('contact_phones', + { 'type' => 'LANDLINE', + 'phone' => '5098541491' }); +addRow('contacts_methods', + { 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'}, + 'method_id' => $newdb{'tables'}{'contact_phones'}{'autoid'}, + 'method' => 'PHONE', + 'type' => 'HOME', + 'preference' => 'ALTERNATE' }, + 1); + +addRow('contact_phones', + { 'type' => 'VIRTUAL', + 'phone' => '8774488664' }); +addRow('contacts_methods', + { 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'}, + 'method_id' => $newdb{'tables'}{'contact_phones'}{'autoid'}, + 'method' => 'PHONE', + 'type' => 'BUSINESS', + 'preference' => 'WORK' }, + 1); + +addRow('contact_phones', + { 'type' => 'FAX', + 'phone' => '8662960131' }); +addRow('contacts_methods', + { 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'}, + 'method_id' => $newdb{'tables'}{'contact_phones'}{'autoid'}, + 'method' => 'PHONE', + 'type' => 'BUSINESS', + 'preference' => 'WORK' }, + 1); + +addRow('contact_emails', + { 'email' => 'abijah\@PerkinsHouse.com' }); +addRow('contacts_methods', + { 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'}, + 'method_id' => $newdb{'tables'}{'contact_emails'}{'autoid'}, + 'method' => 'EMAIL', + 'type' => 'HOME', + 'preference' => 'PRIMARY' }, + 1); + +addRow('contact_emails', + { 'email' => 'abijah\@PerkinsREI.com' }); +addRow('contacts_methods', + { 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'}, + 'method_id' => $newdb{'tables'}{'contact_emails'}{'autoid'}, + 'method' => 'EMAIL', + 'type' => 'HOME', + 'preference' => 'WORK' }, + 1); + +addRow('contact_emails', + { 'email' => 'abijah\@ValleyStorage.com' }); +addRow('contacts_methods', + { 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'}, + 'method_id' => $newdb{'tables'}{'contact_emails'}{'autoid'}, + 'method' => 'EMAIL', + 'type' => 'BUSINESS', + 'preference' => 'WORK' }, + 1); + + +################################################################# +## GROUPS + +addRow('groups', + { 'code' => 'Owner', + 'name' => 'Owner Group' }); +addRow('group_permissions', + { 'group_id' => $newdb{'tables'}{'groups'}{'autoid'}, + 'name' => 'EVERYTHING', + 'access' => 'FORCED' }, + 1); + + +################################################################# +## USERS + +addRow('users', + { 'code' => 'AP', + 'login' => 'abijah', + 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'} }); + + +################################################################# +## SITES + +addRow('sites', + { 'code' => 'VSS', + 'name' => 'Valley Storage' }); + +addRow('site_memberships', + { 'site_id' => $newdb{'tables'}{'sites'}{'autoid'}, + 'user_id' => $newdb{'tables'}{'users'}{'autoid'}, + 'group_id' => $newdb{'tables'}{'groups'}{'autoid'} }, + 1); + +addRow('site_areas', + { 'site_id' => $newdb{'tables'}{'sites'}{'autoid'}, + 'code' => 'Main', + 'name' => 'Main Facility Area' }); + + +################################################################# +## LEASES + +addRow('lease_types', + { 'code' => 'SL', + 'name' => 'Storage Lease' }); + + +################################################################# +## LEDGERS + +$newdb{'lookup'}{'account'} = {}; + +$query = "SELECT * FROM pmgr_accounts"; +$result = query($db_handle, $query); +foreach $row (@$result) { + addRow('ledgers', + { 'account_id' => $row->{'id'}, + 'name' => $row->{'name'} . ' Ledger', + 'comment' => undef }); + + $newdb{'lookup'}{'account'}{$row->{'name'}} + = {'account' => $row->{'id'}, + 'ledger' => $newdb{'tables'}{'ledgers'}{'autoid'} }; + + if ((!defined $newdb{'tables'}{'accounts'}{'autoid'}) || + $row->{'id'} > $newdb{'tables'}{'accounts'}{'autoid'}) { + $newdb{'tables'}{'accounts'}{'autoid'} = $row->{'id'}; + } +} + +$newdb{'lookup'}{'charge_type'} = {}; +$newdb{'lookup'}{'charge_type'}{'Rent'} = + $newdb{'lookup'}{'account'}{'Rent'}; +$newdb{'lookup'}{'charge_type'}{'Late Fee'} = + $newdb{'lookup'}{'account'}{'Late Charge'}; +$newdb{'lookup'}{'charge_type'}{'Security Deposit'} = + $newdb{'lookup'}{'account'}{'Security Deposit'}; + + +################################################################# +## MONETARY + +$newdb{'lookup'}{'monetary_type'} = {}; + +$query = "SELECT * FROM pmgr_monetary_types"; +$result = query($db_handle, $query); +foreach $row (@$result) { + $newdb{'lookup'}{'monetary_type'}{$row->{'name'}} + = {'id' => $row->{'id'} }; +} + +$newdb{'lookup'}{'payment_type'} = {}; +$newdb{'lookup'}{'payment_type'}{1} += { 'name' => 'Cash', 'id' => $newdb{'lookup'}{'monetary_type'}{'Cash'}{'id'} }; +$newdb{'lookup'}{'payment_type'}{2} += { 'name' => 'Check', 'id' => $newdb{'lookup'}{'monetary_type'}{'Check'}{'id'} }; +$newdb{'lookup'}{'payment_type'}{3} += { 'name' => 'Money Order', 'id' => $newdb{'lookup'}{'monetary_type'}{'Money Order'}{'id'} }; +$newdb{'lookup'}{'payment_type'}{4} += { 'name' => 'ACH', 'id' => $newdb{'lookup'}{'monetary_type'}{'ACH'}{'id'} }; +$newdb{'lookup'}{'payment_type'}{12} += { 'name' => 'Transfer', 'id' => $newdb{'lookup'}{'monetary_type'}{'Other Non-Tillable'}{'id'} }; + + +$newdb{'ids'}{'monetary_source'} = {}; +$newdb{'ids'}{'monetary_source'}{'internal'} = undef; + +addRow('monetary_sources', + { 'monetary_type_id' => $newdb{'lookup'}{'monetary_type'}{'Cash'}{'id'}, + 'name' => 'Cash Source', + 'comment' => 'Monetary source used for any cash transaction' }); +$newdb{'ids'}{'monetary_source'}{'Cash'} = + $newdb{'tables'}{'monetary_sources'}{'autoid'}; + +addRow('monetary_sources', + { 'monetary_type_id' => $newdb{'lookup'}{'monetary_type'}{'Other Non-Tillable'}{'id'}, + 'name' => 'Closing Monies Credited', + 'comment' => 'Credited at the closing table' }); +$newdb{'ids'}{'monetary_source'}{'Closing'} = + $newdb{'tables'}{'monetary_sources'}{'autoid'}; + + + + ###################################################################### ###################################################################### ###################################################################### @@ -372,72 +506,63 @@ sub datefmt { ###################################################################### ## Unit Types +$newdb{'lookup'}{'unit_type'} = {}; + $query = "SELECT * FROM UnitType ORDER BY TypeID"; -$result = query($sdbh, $query); -$nrows = @$result; -print(" $nrows Unit Types\n"); - -foreach $row (@$result) { - $query = "INSERT INTO pmgr_unit_types - (`id`, `code`, `name`) - VALUES - ($row->{'TypeID'}, 'xxx', '$row->{'UnitType'}')"; - query($db_handle, $query, $row); +foreach $row (@{query($sdbh, $query)}) { + addRow('unit_types', + { 'code' => 'xxx', + 'name' => $row->{'UnitType'} }); + $newdb{'lookup'}{'unit_type'}{$row->{'TypeID'}} = + $newdb{'tables'}{'unit_types'}{'autoid'}; } - ###################################################################### ## Unit Sizes +$newdb{'lookup'}{'unit_size'} = {}; + $query = "SELECT * FROM UnitInfo WHERE UnitID <> 'POS\$' ORDER BY UnitID"; -$result = query($sdbh, $query); -$nrows = @$result; -print(" $nrows Units\n"); - -my (%unit_size_map); -foreach $row (@$result) { +foreach $row (@{query($sdbh, $query)}) { my $sz = sizeCode($row->{'Width'}, $row->{'Depth'}); - next if defined $unit_size_map{$sz}; - $unit_size_map{$sz} = { 'id' => ++$aicur_size_id }; - $unit_size_map{$sz}{'rent'} = $row->{'StdRent'}; - $unit_size_map{$sz}{'dep'} = $row->{'StdSecDep'}; - my $szid = $unit_size_map{$sz}{'id'}; + next if defined $newdb{'lookup'}{'unit_size'}{$sz}; - $query = "INSERT INTO pmgr_unit_sizes - (`id`, `unit_type_id`, `code`, `name`, `width`, `depth`, - `deposit`, `amount`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($szid, $row->{'Type'}, $sz, $sz, - $internal_adjustment_factor * $row->{'Width'}, - $internal_adjustment_factor * $row->{'Depth'}, - $row->{'StdSecDep'}, $row->{'StdRent'}) - )) . ")"; - query($db_handle, $query, $row); + addRow('unit_sizes', + { 'unit_type_id' => $row->{'Type'}, + 'code' => $sz, + 'name' => $sz, + 'width' => $internal_adjustment_factor * $row->{'Width'}, + 'depth' => $internal_adjustment_factor * $row->{'Depth'}, + 'deposit' => $row->{'StdSecDep'}, + 'amount' => $row->{'StdRent'} }); + + $newdb{'lookup'}{'unit_size'}{$sz} + = { 'id' => $newdb{'tables'}{'unit_sizes'}{'autoid'}, + 'rent' => $row->{'StdRent'}, + 'dep' => $row->{'StdSecDep'} }; } - ###################################################################### ## Units -my (%unit_map); -foreach $row (@$result) { - my $sz = sizeCode($row->{'Width'}, $row->{'Depth'}); - my $szid = $unit_size_map{$sz}{'id'}; - $unit_map{$row->{'UnitID'}} = ++$aicur_unit_id; - my $uid = $unit_map{$row->{'UnitID'}}; +$newdb{'lookup'}{'unit'} = {}; - $query = "INSERT INTO pmgr_units - (`id`, `unit_size_id`, `code`, `name`, - `status`, - `sort_order`, `walk_order`, `deposit`, `amount`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($uid, $szid, $row->{'UnitID'}, $row->{'UnitID'}, - $row->{'Rented'} ?'OCCUPIED' :($row->{'Rentable'} ?'VACANT' :'UNAVAILABLE'), - $uid, $uid, $row->{'StdSecDep'}, $row->{'StdRent'}) - )) . ")"; - query($db_handle, $query, $row); +foreach $row (@{query($sdbh, $query)}) { + my $sz = sizeCode($row->{'Width'}, $row->{'Depth'}); + my $szid = $newdb{'lookup'}{'unit_size'}{$sz}{'id'}; + + addRow('units', + { 'unit_size_id' => $szid, + 'code' => $row->{'UnitID'}, + 'name' => $row->{'UnitID'}, + 'status' => $row->{'Rented'} ?'OCCUPIED' :($row->{'Rentable'} ?'VACANT' :'UNAVAILABLE'), + 'sort_order' => $newdb{'tables'}{'units'}{'autoid'}, + 'walk_order' => $newdb{'tables'}{'units'}{'autoid'}, + 'deposit' => $row->{'StdSecDep'}, + 'amount' => $row->{'StdRent'} }); + + $newdb{'lookup'}{'unit'}{$row->{'UnitID'}} + = { 'id' => $newdb{'tables'}{'units'}{'autoid'} }; } @@ -465,12 +590,11 @@ $info{'extents'}{'left'} = 0; $info{'extents'}{'bottom'} = $internal_adjustment_factor * ($top_adjustment + $row->{'bot'} + 0); $info{'extents'}{'right'} = $internal_adjustment_factor * ($left_adjustment + $row->{'rgt'} + 0); -$query = - "INSERT INTO pmgr_maps (id, name, site_area_id, width, depth) VALUES\n" . - " (1, 'Main Facility Map', $aicur_area_id," . - ($info{'extents'}{'right'} - $info{'extents'}{'left'}) . ", " . - ($info{'extents'}{'bottom'} - $info{'extents'}{'top'}) . ")"; -query($db_handle, $query, \%info); +addRow('maps', + { 'name' => 'Main Facility Map', + 'site_area_id' => $newdb{'tables'}{'site_areas'}{'autoid'}, + 'width' => $info{'extents'}{'right'} - $info{'extents'}{'left'}, + 'depth' => $info{'extents'}{'bottom'} - $info{'extents'}{'top'} }); # Get list of units and positions $query = "SELECT U.UnitID, U.UnitID as name,"; @@ -480,22 +604,15 @@ $query .= " IIF(M.reverseWL, U.Depth, U.Width) AS Width,"; $query .= " IIF(M.reverseWL, U.Width, U.Depth) AS Depth,"; $query .= " M.reverseWL, U.Rented, U.Rentable"; $query .= " FROM UnitInfo U INNER JOIN mapUnitsV2 M ON M.unitID = U.UnitID"; -$result = query($sdbh, $query); # Go through each one, calculating the map location -foreach $row (@$result) { - my $uid = $unit_map{$row->{'UnitID'}}; - - $query = # pt_bottom, pt_right, - "INSERT INTO pmgr_maps_units (map_id, unit_id, - pt_top, pt_left, - transpose) VALUES - (" . join(", ", - 1, $uid, - $internal_adjustment_factor * ($row->{'pt_t'}), - $internal_adjustment_factor * ($row->{'pt_l'}), - $row->{'reverseWL'}) . ")"; - query($db_handle, $query, $row); +foreach $row (@{query($sdbh, $query)}) { + addRow('maps_units', + { 'map_id' => $newdb{'tables'}{'maps'}{'autoid'}, + 'unit_id' => $newdb{'lookup'}{'unit'}{$row->{'UnitID'}}{'id'}, + 'pt_top' => $internal_adjustment_factor * ($row->{'pt_t'}), + 'pt_left' => $internal_adjustment_factor * ($row->{'pt_l'}), + 'transpose' => $row->{'reverseWL'} }); } @@ -513,63 +630,64 @@ foreach $row (@$result) { ###################################################################### ## Tenants +$newdb{'lookup'}{'tenant'} = {}; + $query = "SELECT * FROM TenantInfo WHERE FirstName <> 'POS' ORDER BY TenantID"; -$result = query($sdbh, $query); -$nrows = @$result; -print(" $nrows Tenants\n"); +foreach $row (@{query($sdbh, $query)}) { -my %stmap = ( 1=>'AK', 14=>'ID', 48=>'WA' ); -my (%tenant_map); -foreach $row (@$result) { - $tenant_map{$row->{'TenantID'}} = { 'cid' => ++$aicur_c_id }; - my $cid = $tenant_map{$row->{'TenantID'}}{'cid'}; - $tenant_map{$row->{'TenantID'}}{'custid'} = $cid; - my $custid = $tenant_map{$row->{'TenantID'}}{'custid'}; + $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}} + = { 'name' => "$row->{'LastName'}, $row->{'FirstName'}" }; - $tenant_map{$row->{'TenantID'}}{'name'} = "$row->{'LastName'}, $row->{'FirstName'}"; + addRow('contacts', + { 'first_name' => $row->{'FirstName'}, + 'middle_name' => $row->{'MiddleName'}, + 'last_name' => $row->{'LastName'}, + 'id_local' => $row->{'IDNum'} || undef, + 'id_local_state' => $row->{'IDNum'} ? $newdb{'lookup'}{'state'}{$row->{'DLStateID'}} : undef }); - $query = "INSERT INTO pmgr_contacts - (`id`, `first_name`, `middle_name`, `last_name`, `display_name`, `id_local`, `id_local_state`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($cid, $row->{'FirstName'}, $row->{'MiddleName'}, $row->{'LastName'}, - "$row->{'LastName'}, $row->{'FirstName'}", - $row->{'IDNum'} || undef, $row->{'IDNum'} ? $stmap{$row->{'DLStateID'}} : undef) - )) . ")"; - query($db_handle, $query, $row); + $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'} = + $newdb{'tables'}{'contacts'}{'autoid'}; - $query = "INSERT INTO pmgr_customers - (`id`, `name`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($custid, "$row->{'LastName'}, $row->{'FirstName'}") - )) . ")"; - query($db_handle, $query, $row); + # Every customer gets their own ledger + addRow('accounts', + { 'type' => 'ASSET', + 'name' => 'Customer: ' . $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'name'}, + 'comment' => undef }); + addRow('ledgers', + { 'account_id' => $newdb{'tables'}{'accounts'}{'autoid'}, + 'name' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'name'} . ' Ledger', + 'comment' => 'Ledger for Customer Account #' . $newdb{'tables'}{'accounts'}{'autoid'} }); - $query = "INSERT INTO pmgr_contacts_customers - (`customer_id`, `contact_id`, `type`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($custid, $cid, 'TENANT') - )) . ")"; - query($db_handle, $query, $row); + $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'ledger'} = + $newdb{'tables'}{'ledgers'}{'autoid'}; + + addRow('customers', + { 'name' => "$row->{'LastName'}, $row->{'FirstName'}", + 'ledger_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'ledger'} }); + + $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'} = + $newdb{'tables'}{'customers'}{'autoid'}; + + addRow('contacts_customers', + { 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'}, + 'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'}, + 'type' => 'TENANT' }, + 1); if ($row->{'City'}) { - $query = "INSERT INTO pmgr_contact_addresses - (`id`, `address`, `city`, `state`, `postcode`, `country`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (++$aicur_ca_id, - #$row->{'HomeAddress'} - $row->{'HomeAddress'} . ($row->{'HomeAddr2'} ? "\n".$row->{'HomeAddr2'} : "") || undef, - $row->{'City'}, $stmap{$row->{'StateID'}}, $row->{'Zip'} || undef, 'USA') - )) . ")"; - query($db_handle, $query, $row); - - $query = "INSERT INTO pmgr_contacts_methods - (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES - ($cid, 'POST', $aicur_ca_id, 'HOME', 'PRIMARY')"; - query($db_handle, $query, $row); + addRow('contact_addresses', + { 'address' => $row->{'HomeAddress'} . ($row->{'HomeAddr2'} ? "\n".$row->{'HomeAddr2'} : "") || undef, + 'city' => $row->{'City'}, + 'state' => $newdb{'lookup'}{'state'}{$row->{'StateID'}}, + 'postcode' => $row->{'Zip'} || undef, + 'country' => 'USA' }); + addRow('contacts_methods', + { 'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'}, + 'method_id' => $newdb{'tables'}{'contact_addresses'}{'autoid'}, + 'method' => 'POST', + 'type' => 'HOME', + 'preference' => 'PRIMARY' }, + 1); } foreach ({'type' => 'LANDLINE', 'preference' => 'PRIMARY', 'phone' => $row->{'Phone'}}, @@ -580,90 +698,76 @@ foreach $row (@$result) { {'type' => 'MOBILE', 'preference' => 'ALTERNATE', 'phone' => $row->{'CellPhone'}}) { if ($_->{'phone'}) { - $query = "INSERT INTO pmgr_contact_phones - (`id`, `type`, `phone`, `ext`) VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (++$aicur_cp_id, $_->{'type'}, $_->{'phone'}, $_->{'ext'}))) - . ")"; - query($db_handle, $query, $row); - - $query = "INSERT INTO pmgr_contacts_methods - (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($cid, 'PHONE', $aicur_cp_id, 'MAIN', $_->{'preference'}))) - . ")"; - query($db_handle, $query, $row); + addRow('contact_phones', + { 'type' => $_->{'type'}, + 'phone' => $_->{'phone'}, + 'ext' => $_->{'ext'} }); + addRow('contacts_methods', + { 'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'}, + 'method_id' => $newdb{'tables'}{'contact_phones'}{'autoid'}, + 'method' => 'PHONE', + 'type' => 'MAIN', + 'preference' => $_->{'preference'} }, + 1); } } if ($row->{'Email'}) { - $query = "INSERT INTO pmgr_contact_emails - (`id`, `email`) VALUES - (".++$aicur_ce_id.", '$row->{'Email'}')"; - query($db_handle, $query, $row); - - $query = "INSERT INTO pmgr_contacts_methods - (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUE - ($cid, 'EMAIL', $aicur_ce_id, 'MAIN', 'PRIMARY')"; - query($db_handle, $query, $row); + addRow('contact_emails', + { 'email' => $row->{'Email'} }); + addRow('contacts_methods', + { 'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'}, + 'method_id' => $newdb{'tables'}{'contact_emails'}{'autoid'}, + 'method' => 'EMAIL', + 'type' => 'MAIN', + 'preference' => 'PRIMARY' }, + 1); } next unless $row->{'AltFirstName'} || $row->{'AltLastName'} || $row->{'AltAddress'} || $row->{'AltPhone'}; - $tenant_map{$row->{'TenantID'}}{'alt'} = ++$aicur_c_id; - $cid = $tenant_map{$row->{'TenantID'}}{'alt'}; + addRow('contacts', + { 'first_name' => $row->{'AltFirstName'} || undef, + 'middle_name' => $row->{'AltMI'} || undef, + 'last_name' => $row->{'AltLastName'} || undef }); - $query = "INSERT INTO pmgr_contacts - (`id`, `first_name`, `middle_name`, `last_name`, `display_name`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($cid, - $row->{'AltFirstName'} || undef, - $row->{'AltMI'} || undef, - $row->{'AltLastName'} || undef, - ($row->{'AltLastName'} && $row->{'AltFirstName'} - ? "$row->{'AltLastName'}, $row->{'AltFirstName'}" - : ($row->{'AltLastName'} || $row->{'AltFirstName'} || undef))) - )) . ")"; - query($db_handle, $query, $row); + $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'alt'} = + $newdb{'tables'}{'contacts'}{'autoid'}; - $query = "INSERT INTO pmgr_contacts_customers - (`customer_id`, `contact_id`, `type`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($custid, $cid, 'ALTERNATE') - )) . ")"; - query($db_handle, $query, $row); + addRow('contacts_customers', + { 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'}, + 'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'alt'}, + 'type' => 'ALTERNATE' }, + 1); if ($row->{'AltCity'}) { - $query = "INSERT INTO pmgr_contact_addresses - (`id`, `address`, `city`, `state`, `postcode`, `country`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (++$aicur_ca_id, - $row->{'AltAddress'} . ($row->{'AltAddr2'} ? "\n".$row->{'AltAddr2'} : ""), - $row->{'AltCity'}, $stmap{$row->{'AltStateID'}}, $row->{'AltZip'}, 'USA') - )) . ")"; - query($db_handle, $query, $row); - - $query = "INSERT INTO pmgr_contacts_methods - (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES - ($cid, 'POST', $aicur_ca_id, 'MAIN', 'PRIMARY')"; - query($db_handle, $query, $row); + addRow('contact_addresses', + { 'address' => $row->{'AltAddress'} . ($row->{'AltAddr2'} ? "\n".$row->{'AltAddr2'} : ""), + 'city' => $row->{'AltCity'}, + 'state' => $newdb{'lookup'}{'state'}{$row->{'AltStateID'}}, + 'postcode' => $row->{'AltZip'}, + 'country' => 'USA' }); + addRow('contacts_methods', + { 'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'alt'}, + 'method_id' => $newdb{'tables'}{'contact_addresses'}{'autoid'}, + 'method' => 'POST', + 'type' => 'MAIN', + 'preference' => 'PRIMARY' }, + 1); } if ($row->{'AltPhone'}) { - $query = "INSERT INTO pmgr_contact_phones - (`id`, `type`, `phone`, `ext`) VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (++$aicur_cp_id, 'LANDLINE', $row->{'AltPhone'}, undef) - )) . ")"; - query($db_handle, $query, $row); - - $query = "INSERT INTO pmgr_contacts_methods - (`contact_id`, `method`, `method_id`, `type`, `preference`) VALUES - ($cid, 'PHONE', $aicur_cp_id, 'MAIN', 'PRIMARY')"; - query($db_handle, $query, $row); + addRow('contact_phones', + { 'type' => 'LANDLINE', + 'phone' => $row->{'AltPhone'}, + 'ext' => undef }); + addRow('contacts_methods', + { 'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'alt'}, + 'method_id' => $newdb{'tables'}{'contact_phones'}{'autoid'}, + 'method' => 'PHONE', + 'type' => 'MAIN', + 'preference' => 'PRIMARY' }, + 1); } } @@ -671,55 +775,42 @@ foreach $row (@$result) { ###################################################################### ## Tenant Leases +$newdb{'lookup'}{'ledger'} = {}; + $query = "SELECT L.*, A.TenantID FROM TenantLedger L LEFT JOIN `Access` A ON A.LedgerID = L.LedgerID WHERE L.UnitID <> 'POS\$' ORDER BY L.LedgerID"; -$result = query($sdbh, $query); -$nrows = @$result; -print(" $nrows Tenant Ledgers\n"); -my (%ledger_map); -foreach $row (@$result) { - $ledger_map{$row->{'LedgerID'}} = { 'lid' => ++$aicur_lease_id }; - my $cid = $tenant_map{$row->{'TenantID'}}{'cid'}; - my $uid = $unit_map{$row->{'UnitID'}}; - my $lid = $ledger_map{$row->{'LedgerID'}}{'lid'}; - my $custid = $tenant_map{$row->{'TenantID'}}{'custid'}; - $ledger_map{$row->{'LedgerID'}}{'custid'} = $custid; +foreach $row (@{query($sdbh, $query)}) { - $query = "INSERT INTO pmgr_leases - (`id`, `number`, `lease_type_id`, `unit_id`, `customer_id`, - `lease_date`, `movein_date`, - `moveout_date`, `close_date`, - `amount`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($lid, $row->{'LedgerID'}, $aicur_lease_type_id, $uid, $custid, - datefmt($row->{'DateIn'}), datefmt($row->{'DateIn'}), - datefmt($row->{'DateOut'}), datefmt($row->{'DateClosed'}), - $row->{'Rent'}) - )) . ")"; - query($db_handle, $query, $row); + # Every lease gets its own ledger + addRow('accounts', + { 'type' => 'ASSET', + 'name' => 'Lease: #' . $newdb{'tables'}{'leases'}{'autoid'}, + 'comment' => undef }); + addRow('ledgers', + { 'account_id' => $newdb{'tables'}{'accounts'}{'autoid'}, + 'name' => 'Lease #' . ($newdb{'tables'}{'leases'}{'autoid'}+1) . ' Ledger', + 'comment' => 'Ledger for Customer Account #' . $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'} }); + + $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'} = + $newdb{'tables'}{'ledgers'}{'autoid'}; + + addRow('leases', + { 'number' => $row->{'LedgerID'}, + 'lease_type_id' => $newdb{'tables'}{'lease_types'}{'autoid'}, + 'unit_id' => $newdb{'lookup'}{'unit'}{$row->{'UnitID'}}{'id'}, + 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'}, + 'ledger_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'}, + 'lease_date' => datefmt($row->{'DateIn'}), + 'movein_date' => datefmt($row->{'DateIn'}), + 'moveout_date' => datefmt($row->{'DateOut'}), + 'close_date' => datefmt($row->{'DateClosed'}), + 'amount' => $row->{'Rent'} }); + + $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}} + = { 'lease' => $newdb{'tables'}{'leases'}{'autoid'}, + 'cust' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'}, + 'ledger' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'} }; } -$query = "UPDATE pmgr_units U, pmgr_leases L - SET U.`current_lease_id` = L.id - WHERE L.unit_id = U.id AND L.close_date IS NULL"; -query($db_handle, $query); - - -###################################################################### -## Security Deposits - -$query = "SELECT L.LedgerID, L.UnitID, C.ChargeAmount FROM TenantLedger L INNER JOIN Charges C ON C.LedgerID = L.LedgerID WHERE L.UnitID <> 'POS\$' AND C.ChargeDescription = 'Security Deposit' ORDER BY UnitID"; -$result = query($sdbh, $query); -$nrows = @$result; -print(" $nrows Security Deposits\n"); - -foreach $row (@$result) { - my $uid = $unit_map{$row->{'UnitID'}}; - $query = "UPDATE pmgr_leases - SET deposit = $row->{'ChargeAmount'} - WHERE `number` = '$row->{'LedgerID'}'"; - query($db_handle, $query, $row); -} ###################################################################### @@ -735,72 +826,44 @@ foreach $row (@$result) { ###################################################################### ## Charges +$newdb{'lookup'}{'charge'} = {}; + $query = "SELECT * FROM Charges ORDER BY ChargeID"; -$result = query($sdbh, $query); -$nrows = @$result; -print(" $nrows Charges\n"); +foreach $row (@{query($sdbh, $query)}) { -my %charge_map; -foreach $row (@$result) { - $charge_map{$row->{'ChargeID'}} = ++$aicur_tx_id; - my $lid = $ledger_map{$row->{'LedgerID'}}{'lid'}; - my $chid = $charge_map{$row->{'ChargeID'}}; - my $custid = $ledger_map{$row->{'LedgerID'}}{'custid'}; - + addRow('transactions', + { 'stamp' => datefmt($row->{'ChargeDate'}), + 'through_date' => datefmt($row->{'EndDate'}), + 'customer_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust'} }); - $query = "INSERT INTO pmgr_transactions - (`id`, - `stamp`, `through_date`, - `customer_id`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($chid, - datefmt($row->{'ChargeDate'}), datefmt($row->{'EndDate'}), - $custid) - )) . ")"; - query($db_handle, $query, $row); + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}} + = {'tx' => $newdb{'tables'}{'transactions'}{'autoid'} }; - $query = "INSERT INTO pmgr_ledger_entries - (`monetary_source_id`, `transaction_id`, - `debit_ledger_id`, - `credit_ledger_id`, - `amount`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($monetary_source_internal, $chid, - $account_map{'A/R'}{'ledger'}, - $account_map{$row->{'ChargeDescription'}}{'ledger'}, - $row->{'ChargeAmount'}, "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}") - )) . ")"; - query($db_handle, $query, $row); + addRow('ledger_entries', + { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, + 'debit_ledger_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'}, + 'credit_ledger_id' => $newdb{'lookup'}{'charge_type'}{$row->{'ChargeDescription'}}{'ledger'}, + 'amount' => $row->{'ChargeAmount'}, + 'comment' => "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}" }); next unless $row->{'TaxAmount'}; - $query = "INSERT INTO pmgr_ledger_entries - (`monetary_source_id`, `transaction_id`, - `debit_ledger_id`, - `credit_ledger_id`, - `amount`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($monetary_source_internal, $chid, - $account_map{'A/R'}{'ledger'}, - $account_map{'Tax'}{'ledger'}, - $row->{'TaxAmount'}, undef) - )) . ")"; - query($db_handle, $query, $row); - - -# $query = "UPDATE pmgr_charges"; -# $query .= " SET due_date = DATE_ADD(charge_date, INTERVAL IF(account_id=2,10,0) DAY)"; -# query($db_handle, $query); + addRow('ledger_entries', + { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, + 'debit_ledger_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'}, + 'credit_ledger_id' => $newdb{'lookup'}{'charge_type'}{'Tax'}{'ledger'}, + 'amount' => $row->{'TaxAmount'}, + 'comment' => undef }); } ###################################################################### ## Receipts -#$query = "SELECT * FROM Receipts ORDER BY ReceiptNum"; +$newdb{'lookup'}{'receipt'} = {}; + $query = "SELECT R.ReceiptNum, C.LedgerID, R.ReceiptDate" . " FROM Receipts R, Payments P, Charges C" . @@ -808,38 +871,26 @@ $query = " AND C.ChargeID = P.ChargeID" . " GROUP BY R.ReceiptNum, C.LedgerID, R.ReceiptDate" . " ORDER BY R.ReceiptNum"; -$result = query($sdbh, $query); -$nrows = @$result; -print(" $nrows Receipts\n"); +foreach $row (@{query($sdbh, $query)}) { -my %receipt_map; -foreach $row (@$result) { - #print Dumper $row; - my $lid = $ledger_map{$row->{'LedgerID'}}{'lid'}; - my $custid = $ledger_map{$row->{'LedgerID'}}{'custid'}; - - if ($receipt_map{$row->{'ReceiptNum'}}) { - die unless $receipt_map{$row->{'ReceiptNum'}}{'cust'} == $custid; - push(@{$receipt_map{$row->{'ReceiptNum'}}{'lid'}}, $lid); + if ($newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}) { + die unless ($newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'cust'} + == $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'cust'}); + push(@{$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'ledgers'}}, + $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'}); #print Dumper $receipt_map{$row->{'ReceiptNum'}}; next; } - $receipt_map{$row->{'ReceiptNum'}} = { 'id' => ++$aicur_tx_id, 'cust' => $custid, 'lid' => [$lid] }; - my $rid = $receipt_map{$row->{'ReceiptNum'}}{'id'}; - #print Dumper $receipt_map{$row->{'ReceiptNum'}}; + addRow('transactions', + { 'stamp' => datefmt($row->{'ReceiptDate'}), + 'through_date' => undef, + 'customer_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust'} }); - $query = "INSERT INTO pmgr_transactions - (`id`, - `stamp`, `through_date`, - `customer_id`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($rid, - datefmt($row->{'ReceiptDate'}), undef, - $custid) - )) . ")"; - query($db_handle, $query, $row); + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}} + = {'tx' => $newdb{'tables'}{'transactions'}{'autoid'}, + 'cust' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust'}, + 'ledgers' => [ $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'} ] }; } @@ -854,60 +905,47 @@ foreach $row (@$result) { ###################################################################### ## Payments +$newdb{'lookup'}{'payment'} = {}; + $query = "SELECT * FROM Payments ORDER BY PaymentID"; -$result = query($sdbh, $query); -$nrows = @$result; -print(" $nrows Payments\n"); - -my %payment_map; -foreach $row (@$result) { - $payment_map{$row->{'PaymentID'}} = ++$aicur_payment_id; - my $pid = $payment_map{$row->{'PaymentID'}}; - my $rid = $receipt_map{$row->{'ReceiptNum'}}{'id'}; - my $chid = $charge_map{$row->{'ChargeID'}}; - +foreach $row (@{query($sdbh, $query)}) +{ my $monetary_source_id; if ($row->{'PaymentDate'} =~ m%3/25/2009%) { - $monetary_source_id = $monetary_source_closing; - } - elsif ($monetary_type_map{$row->{'PaymentType'}}{'name'} eq 'Cash') { - $monetary_source_id = $monetary_source_cash; + $monetary_source_id = $newdb{'ids'}{'monetary_source'}{'closing'}; } else { - $monetary_source_id = ++$aicur_monetary_source_id; - $query = "INSERT INTO pmgr_monetary_sources - (`id`, `monetary_type_id`, `name`, `comment`) VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($monetary_source_id, - $monetary_type_map{$row->{'PaymentType'}}{'id'}, - $row->{'RecdFrom'}, - "Payment: $row->{'PaymentID'}; Type: $row->{'PaymentType'}; Check: $row->{'CheckNum'}; $row->{'Memo'}") - )) . ")"; - query($db_handle, $query) || die("Unable to insert"); + $monetary_source_id = $newdb{'ids'}{'monetary_source'}{ + $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'} + }; } - $query = "INSERT INTO pmgr_ledger_entries - (`monetary_source_id`, - `transaction_id`, - `debit_ledger_id`, - `credit_ledger_id`, - `amount`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($monetary_source_id, - $rid, - $account_map{'Cash'}{'ledger'}, - $account_map{'A/R'}{'ledger'}, - $row->{'PaymentAmount'}, - "Receipt: $row->{'ReceiptNum'}; Payment: $row->{'PaymentID'}; Charge: $row->{'ChargeID'}") - )) . ")"; - query($db_handle, $query, $row); + if (!defined $monetary_source_id) { + addRow('monetary_sources', + { 'monetary_type_id' => $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'id'}, + 'name' => $row->{'RecdFrom'}, + 'comment' => "Payment: $row->{'PaymentID'}; Type: $row->{'PaymentType'}; Check: $row->{'CheckNum'}; $row->{'Memo'}" }); + $monetary_source_id = $newdb{'tables'}{'monetary_sources'}{'autoid'}; + } + addRow('ledger_entries', + { 'monetary_source_id' => $monetary_source_id, + 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, + 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Cash'}{'ledger'}, + 'credit_ledger_id' => $newdb{'lookup'}{'account'}{'A/R'}{'ledger'}, + 'amount' => $row->{'PaymentAmount'}, + 'comment' => "Receipt: $row->{'ReceiptNum'}; Payment: $row->{'PaymentID'}; Charge: $row->{'ChargeID'}" }); + + + # Map this to the Charge ?? + # $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'id'} + # $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'id'} + + + # Update the transaction to use the memo from this payment if ($row->{'Memo'}) { - $query = - "UPDATE pmgr_transactions SET `comment` = '$row->{'Memo'}'" . - " WHERE `id` = $rid"; - query($db_handle, $query, $row); + my $txid = $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}; + $newdb{'tables'}{'transactions'}{'rows'}[$txid]{'comment'} = $row->{'Memo'}; } } @@ -937,7 +975,7 @@ my %fake = { 'id' => 1002, 'date' => '2009-05-11', 'entry' => [ { 'id' => 2120, - 'account' => 'Late Fee', + 'account' => 'Late Charge', 'amount' => 25, 'tax' => 0 }, ], @@ -986,131 +1024,117 @@ my %fake = ); -my $old_cash_ledger = $account_map{'Cash'}{'ledger'}; -my $new_cash_ledger = ++$aicur_ledger_id; -$account_map{'Cash'}{'ledger'} = $new_cash_ledger; -$query = "INSERT INTO pmgr_ledgers - (`id`, `account_id`, `name`, `comment`) VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($new_cash_ledger, $account_map{'Cash'}{'id'}, - 'Fake Cash Ledger', 'Fake ledger for testing') - )) . ")"; -query($db_handle, $query) || die("Unable to insert"); -$query = -"SELECT - SUM(IF(LedgerEntry.debit_ledger_id = Ledger.id, LedgerEntry.amount, 0)) AS debits, - SUM(IF(LedgerEntry.credit_ledger_id = Ledger.id, LedgerEntry.amount, 0)) AS credits, - SUM(IF(Account.type IN ('ASSET', 'EXPENSE'), - IF(LedgerEntry.debit_ledger_id = Ledger.id, 1, -1), - IF(LedgerEntry.credit_ledger_id = Ledger.id, 1, -1) ) - * LedgerEntry.amount) AS balance, - COUNT(`LedgerEntry`.`id`) AS entries -FROM - `pmgr_ledgers` AS `Ledger` - LEFT JOIN `pmgr_accounts` AS `Account` - ON (`Account`.`id` = `Ledger`.`account_id`) - LEFT JOIN `pmgr_ledger_entries` AS `LedgerEntry` - ON (((`LedgerEntry`.`debit_ledger_id` = Ledger.id) - OR (`LedgerEntry`.`credit_ledger_id` = Ledger.id))) -WHERE `Ledger`.`id` = $old_cash_ledger -GROUP BY `Ledger`.`id` LIMIT 1"; -$result = query($db_handle, $query); -my $balance = $result->[0]{'balance'}; +$newdb{'ids'}{'ledger'}{'Cash-Old'} = + $newdb{'lookup'}{'account'}{'Cash'}{'ledger'}; -$query = "INSERT INTO pmgr_transactions - (`id`, `customer_id`, `stamp`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (++$aicur_tx_id, 0, - '2009-05-10') - )) . ")"; -query($db_handle, $query); +addRow('ledgers', + { 'account_id' => $newdb{'lookup'}{'account'}{'Cash'}{'account'}, + 'name' => 'Fake Cash Ledger', + 'comment' => 'Fake ledger for testing' }); -$query = "INSERT INTO pmgr_ledger_entries - (`monetary_source_id`, `transaction_id`, - `debit_ledger_id`, - `credit_ledger_id`, - `amount`, - `name`, - `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($monetary_source_internal, $aicur_tx_id, - $new_cash_ledger, - $old_cash_ledger, - $balance, - "Close Out ($old_cash_ledger -> $new_cash_ledger)", - "Carrying forward old ledger balance onto new ledger") - )) . ")"; -query($db_handle, $query); +$newdb{'lookup'}{'account'}{'Cash'}{'ledger'} = + $newdb{'tables'}{'ledgers'}{'autoid'}; -$query = - "UPDATE pmgr_ledgers SET `closed` = 1" . - " WHERE `id` = $old_cash_ledger"; -query($db_handle, $query); +my $balance = 0; +foreach $row (@{$newdb{'tables'}{'ledger_entries'}{'rows'}}) { + next unless defined $row; + $balance += $row->{'amount'} + if $row->{'debit_ledger_id'} == $newdb{'ids'}{'ledger'}{'Cash-Old'}; + $balance -= $row->{'amount'} + if $row->{'credit_ledger_id'} == $newdb{'ids'}{'ledger'}{'Cash-Old'}; +} +addRow('transactions', + { 'customer_id' => 0, + 'stamp' => '2009-05-10' }); + +addRow('ledger_entries', + { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + 'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'}, + 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Cash'}{'ledger'}, + 'credit_ledger_id' => $newdb{'ids'}{'ledger'}{'Cash-Old'}, + 'amount' => $balance, + 'name' => "Close Out ($newdb{'ids'}{'ledger'}{'Cash-Old'} -> $newdb{'tables'}{'transactions'}{'autoid'})", + 'comment' => "Carrying forward old ledger balance onto new ledger" }); + +$newdb{'tables'}{'ledgers'}{'rows'}[$newdb{'ids'}{'ledger'}{'Cash-Old'}]{'closed'} => 1; -# my $monetary_source_cash = ++$aicur_monetary_source_id; -# $query = "INSERT INTO pmgr_monetary_sources -# (`id`, `monetary_type_id`, `name`, `comment`) VALUES (" . -# join(", ", map({defined $_ ? "'$_'" : "NULL"} -# ($monetary_source_cash, -# $monetary_type_map{'Cash'}{'id'}, -# 'Fake Cash Source', -# 'Fake source used for testing') -# )) . ")"; -# query($db_handle, $query) || die("Unable to insert"); foreach my $ir ('invoice', 'receipt') { foreach my $tx (@{$fake{$ir}}) { #print Dumper ${%$tx{'date'}}; #exit; - $query = "INSERT INTO pmgr_transactions - (`id`, `stamp`, `through_date`, `customer_id`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - (@{$tx}{'id', 'date', 'thru'}, $fake{'custid'}, "Fake $ir") - )) . ")"; - query($db_handle, $query, $tx); + addRow('transactions', + { 'id' => $tx->{'id'}, + 'stamp' => $tx->{'date'}, + 'through_date' => $tx->{'thru'}, + 'customer_id' => $fake{'custid'}, + 'comment' => "Fake $ir" }, + 1); foreach my $e (@{$tx->{'entry'}}) { - my $dr = ($ir eq 'invoice') ? $account_map{'A/R'} : $account_map{'Cash'}; - my $cr = ($ir eq 'invoice') ? $account_map{$e->{'account'}} : $account_map{'A/R'}; + my $dr = ($ir eq 'invoice') ? 'A/R' : 'Cash'; + my $cr = ($ir eq 'invoice') ? $e->{'account'} : 'A/R'; - $query = "INSERT INTO pmgr_ledger_entries - (`id`, `monetary_source_id`, - `transaction_id`, - `debit_ledger_id`, - `credit_ledger_id`, - `amount`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($e->{'id'}, $e->{'type'} || $monetary_source_internal, - $tx->{'id'}, - $dr->{'ledger'}, - $cr->{'ledger'}, - $e->{'amount'}, "Fake $ir entry") - )) . ")"; - query($db_handle, $query, $e); + addRow('ledger_entries', + { 'id' => $e->{'id'}, + 'monetary_source_id' => $e->{'type'} || $newdb{'ids'}{'monetary_source'}{'internal'}, + 'transaction_id' => $tx->{'id'}, + 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$dr}{'ledger'}, + 'credit_ledger_id' => $newdb{'lookup'}{'account'}{$cr}{'ledger'}, + 'amount' => $e->{'amount'}, + 'comment' => "Fake $ir entry" }, + 1); next unless $e->{'tax'}; - $query = "INSERT INTO pmgr_ledger_entries - (`id`, `monetary_source_id`, - `transaction_id`, - `debit_ledger_id`, - `credit_ledger_id`, - `amount`, `comment`) - VALUES (" . - join(", ", map({defined $_ ? "'$_'" : "NULL"} - ($e->{'id'}+1, $monetary_source_internal, - $tx->{'id'}, - $account_map{'A/R'}{'ledger'}, - $account_map{'Tax'}{'ledger'}, - $e->{'tax'}, "Fake Tax Charge") - )) . ")"; - query($db_handle, $query, $e); + addRow('ledger_entries', + { 'id' => $e->{'id'}+1, + 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + 'transaction_id' => $tx->{'id'}, + 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$dr}{'ledger'}, + 'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Tax'}{'ledger'}, + 'amount' => $e->{'tax'}, + 'comment' => "Fake Tax" }, + 1); } } } + +$Data::Dumper::Sortkeys = 1; +print Dumper \%newdb; +# exit; + +buildTables(); + + +###################################################################### +## Security Deposits + +$query = "SELECT L.LedgerID, L.UnitID, C.ChargeAmount FROM TenantLedger L INNER JOIN Charges C ON C.LedgerID = L.LedgerID WHERE L.UnitID <> 'POS\$' AND C.ChargeDescription = 'Security Deposit' ORDER BY UnitID"; + +foreach $row (@{query($sdbh, $query)}) { + #my $uid = $newdb{'lookup'}{'unit'}{$row->{'UnitID'}}; + $query = "UPDATE pmgr_leases + SET deposit = $row->{'ChargeAmount'} + WHERE `number` = '$row->{'LedgerID'}'"; + query($db_handle, $query, $row); +} + +###################################################################### +## Ledger Assignments + +# $query = +# "UPDATE pmgr_accounts A, pmgr_ledgers L SET A.ledger_id = L.id" . +# " WHERE A.id = L.account_id"; +# query($db_handle, $query); + +###################################################################### +## Unit Lease Assignments + +$query = "UPDATE pmgr_units U, pmgr_leases L + SET U.`current_lease_id` = L.id + WHERE L.unit_id = U.id AND L.close_date IS NULL"; +query($db_handle, $query); + From 2a2d11ba0f7784588956096b973311f4bcb4f9e3 Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 7 Jun 2009 17:00:08 +0000 Subject: [PATCH 073/717] Fixed bug causing payments to show up on the A/R ledger instead of the customer ledger. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@74 97e9348a-65ac-dc4b-aefc-98561f571b83 --- scripts/sitelink2pmgr.pl | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 9082ce6..fed83b5 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -783,11 +783,12 @@ foreach $row (@{query($sdbh, $query)}) { # Every lease gets its own ledger addRow('accounts', { 'type' => 'ASSET', - 'name' => 'Lease: #' . $newdb{'tables'}{'leases'}{'autoid'}, + 'name' => 'Lease: #' . ($newdb{'tables'}{'leases'}{'autoid'}+1), 'comment' => undef }); addRow('ledgers', { 'account_id' => $newdb{'tables'}{'accounts'}{'autoid'}, - 'name' => 'Lease #' . ($newdb{'tables'}{'leases'}{'autoid'}+1) . ' Ledger', + 'name' => 'Lease #' . ($newdb{'tables'}{'leases'}{'autoid'}+1) + . ' ('.$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'name'} . ')', 'comment' => 'Ledger for Customer Account #' . $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'} }); $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'} = @@ -837,12 +838,13 @@ foreach $row (@{query($sdbh, $query)}) { 'customer_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust'} }); $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}} - = {'tx' => $newdb{'tables'}{'transactions'}{'autoid'} }; + = { 'tx' => $newdb{'tables'}{'transactions'}{'autoid'}, + 'ledger' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'} }; addRow('ledger_entries', { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'}, + 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger'}, 'credit_ledger_id' => $newdb{'lookup'}{'charge_type'}{$row->{'ChargeDescription'}}{'ledger'}, 'amount' => $row->{'ChargeAmount'}, 'comment' => "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}" }); @@ -852,7 +854,7 @@ foreach $row (@{query($sdbh, $query)}) { addRow('ledger_entries', { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'}, + 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger'}, 'credit_ledger_id' => $newdb{'lookup'}{'charge_type'}{'Tax'}{'ledger'}, 'amount' => $row->{'TaxAmount'}, 'comment' => undef }); @@ -896,10 +898,6 @@ foreach $row (@{query($sdbh, $query)}) { # sub idkeys { [ sort( {$a <=> $b} keys(%{$_[0]})) ] } # $Data::Dumper::Sortkeys = \&idkeys; -# print("Tenant\n"); print Dumper \%tenant_map; -# print("Ledger\n"); print Dumper \%ledger_map; -# print("Charge\n"); print Dumper \%charge_map; -# print("Receipt\n"); print Dumper \%receipt_map; ###################################################################### @@ -932,7 +930,7 @@ foreach $row (@{query($sdbh, $query)}) { 'monetary_source_id' => $monetary_source_id, 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Cash'}{'ledger'}, - 'credit_ledger_id' => $newdb{'lookup'}{'account'}{'A/R'}{'ledger'}, + 'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger'}, 'amount' => $row->{'PaymentAmount'}, 'comment' => "Receipt: $row->{'ReceiptNum'}; Payment: $row->{'PaymentID'}; Charge: $row->{'ChargeID'}" }); @@ -1058,7 +1056,7 @@ addRow('ledger_entries', 'name' => "Close Out ($newdb{'ids'}{'ledger'}{'Cash-Old'} -> $newdb{'tables'}{'transactions'}{'autoid'})", 'comment' => "Carrying forward old ledger balance onto new ledger" }); -$newdb{'tables'}{'ledgers'}{'rows'}[$newdb{'ids'}{'ledger'}{'Cash-Old'}]{'closed'} => 1; +$newdb{'tables'}{'ledgers'}{'rows'}[$newdb{'ids'}{'ledger'}{'Cash-Old'}]{'closed'} = 1; foreach my $ir ('invoice', 'receipt') { From d14b715a88f2da88583f5b3e1371536ec213b507 Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 7 Jun 2009 17:06:17 +0000 Subject: [PATCH 074/717] Added menu items to help me work on development. Some of these will likely be removed later. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@75 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/site/app_controller.php b/site/app_controller.php index 6557f34..9d4a328 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -43,6 +43,10 @@ class AppController extends Controller { array('name' => 'Site Map', 'url' => array('controller' => 'maps', 'action' => 'view', 1)), array('name' => 'Tenants', 'url' => array('controller' => 'contacts', 'action' => 'index')), array('name' => 'Units', 'url' => array('controller' => 'units', 'action' => 'index')), + array('name' => 'Customers', 'url' => array('controller' => 'customers', 'action' => 'index')), + array('name' => 'Contacts', 'url' => array('controller' => 'contacts', 'action' => 'index')), + array('name' => 'Accounts', 'url' => array('controller' => 'accounts', 'action' => 'index')), + array('name' => 'Ledgers', 'url' => array('controller' => 'ledgers', 'action' => 'index')), ); } From 52032180f39fd9524f8d4dc9e21a72b762337544 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 8 Jun 2009 02:08:04 +0000 Subject: [PATCH 075/717] Fixed more ledger mixups git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@76 97e9348a-65ac-dc4b-aefc-98561f571b83 --- scripts/sitelink2pmgr.pl | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index fed83b5..a397309 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -658,12 +658,14 @@ foreach $row (@{query($sdbh, $query)}) { 'name' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'name'} . ' Ledger', 'comment' => 'Ledger for Customer Account #' . $newdb{'tables'}{'accounts'}{'autoid'} }); + $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account'} = + $newdb{'tables'}{'accounts'}{'autoid'}; $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'ledger'} = $newdb{'tables'}{'ledgers'}{'autoid'}; addRow('customers', { 'name' => "$row->{'LastName'}, $row->{'FirstName'}", - 'ledger_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'ledger'} }); + 'account_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account'} }); $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'} = $newdb{'tables'}{'customers'}{'autoid'}; @@ -791,25 +793,25 @@ foreach $row (@{query($sdbh, $query)}) { . ' ('.$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'name'} . ')', 'comment' => 'Ledger for Customer Account #' . $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'} }); - $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'} = - $newdb{'tables'}{'ledgers'}{'autoid'}; + $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}} + = { 'cust' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'}, + 'account' => $newdb{'tables'}{'accounts'}{'autoid'}, + 'ledger' => $newdb{'tables'}{'ledgers'}{'autoid'} }; addRow('leases', { 'number' => $row->{'LedgerID'}, 'lease_type_id' => $newdb{'tables'}{'lease_types'}{'autoid'}, 'unit_id' => $newdb{'lookup'}{'unit'}{$row->{'UnitID'}}{'id'}, 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'}, - 'ledger_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'}, + 'account_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'account'}, 'lease_date' => datefmt($row->{'DateIn'}), 'movein_date' => datefmt($row->{'DateIn'}), 'moveout_date' => datefmt($row->{'DateOut'}), 'close_date' => datefmt($row->{'DateClosed'}), 'amount' => $row->{'Rent'} }); - $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}} - = { 'lease' => $newdb{'tables'}{'leases'}{'autoid'}, - 'cust' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'}, - 'ledger' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'} }; + $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease'} = + $newdb{'tables'}{'leases'}{'autoid'}; } From 374843aeeeb581cb955cccf1151fbe1843165d78 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 8 Jun 2009 03:32:07 +0000 Subject: [PATCH 076/717] Finally added a format helper, which has been long intended. There may be still be conversion issues, it hasn't been tested much. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@77 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 2 +- site/views/accounts/view.ctp | 32 +------ site/views/contacts/view.ctp | 28 +----- site/views/customers/view.ctp | 134 +++------------------------ site/views/elements/accounts.ctp | 28 ++---- site/views/elements/contacts.ctp | 18 ++-- site/views/elements/customers.ctp | 16 +++- site/views/elements/ledger.ctp | 48 ++++------ site/views/elements/ledgers.ctp | 13 ++- site/views/elements/maps.ctp | 16 +++- site/views/elements/transactions.ctp | 8 +- site/views/elements/units.ctp | 15 ++- site/views/helpers/format.php | 66 +++++++++++++ site/views/ledgers/view.ctp | 34 +------ site/views/transactions/view.ctp | 24 +---- site/views/units/view.ctp | 45 ++------- 16 files changed, 178 insertions(+), 349 deletions(-) create mode 100644 site/views/helpers/format.php diff --git a/site/app_controller.php b/site/app_controller.php index 9d4a328..19af659 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -35,7 +35,7 @@ * @subpackage cake.app */ class AppController extends Controller { - var $helpers = array('Html', 'Number', 'Time'); + var $helpers = array('Html', 'Format'); function sideMenuLinks() { return array( diff --git a/site/views/accounts/view.ctp b/site/views/accounts/view.ctp index 8d252da..2a56256 100644 --- a/site/views/accounts/view.ctp +++ b/site/views/accounts/view.ctp @@ -5,36 +5,6 @@ element('table',
- Account Balance: + Account Balance:
diff --git a/site/views/contacts/view.ctp b/site/views/contacts/view.ctp index a4986a1..ceb91c9 100644 --- a/site/views/contacts/view.ctp +++ b/site/views/contacts/view.ctp @@ -3,31 +3,7 @@
element('table', $headers = array('Phone', 'Preference', 'Comment'); $rows = array(); foreach($contact['ContactPhone'] AS $phone) { - $rows[] = array(phone($phone['phone']) . + $rows[] = array(FormatHelper::phone($phone['phone']) . ($phone['ext'] ? " x".$phone['ext'] : ""), $phone['ContactsMethod']['preference'] . " / " . $phone['ContactsMethod']['type'] . " / " . diff --git a/site/views/customers/view.ctp b/site/views/customers/view.ctp index f55c9ec..c37ff22 100644 --- a/site/views/customers/view.ctp +++ b/site/views/customers/view.ctp @@ -3,31 +3,7 @@
element('table', ?>
- Security Deposit: + Security Deposit:
- Balance: + Balance:
@@ -80,108 +56,22 @@ echo $this->element('contacts', 'contacts' => $customer['Contact'])); -/* foreach ($customer['Contact'] AS $contact) { */ - -/* /\********************************************************************** */ -/* * Phones */ -/* *\/ */ -/* $headers = array('Phone', 'Preference', 'Comment'); */ -/* $rows = array(); */ -/* foreach($contact['ContactPhone'] AS $phone) { */ -/* $rows[] = array(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)); */ - - -/* /\********************************************************************** */ -/* * Emails */ -/* *\/ */ -/* $headers = array('Email', 'Preference', 'Comment'); */ -/* $rows = array(); */ -/* foreach($contact['ContactEmail'] 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)); */ - - -/* /\********************************************************************** */ -/* * Addresses */ -/* *\/ */ -/* $headers = array('Address', 'Preference', 'Comment'); */ -/* $rows = array(); */ -/* foreach($contact['ContactAddress'] AS $address) { */ -/* $rows[] = array(preg_replace("/\n/", "
\n", $address['address']) . "
\n" . */ -/* $address['city'] . ", " . */ -/* $address['state'] . " " . */ -/* $address['postcode'], */ -/* //. ? "
\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)); */ - - /********************************************************************** * Lease History */ -$headers = array('Lease', 'Unit', 'Signed', 'Move-In', 'Move-Out', 'Rent', 'Deposit', 'Comment'); -$rows = array(); -foreach($customer['Lease'] AS $lease) { - $rows[] = array('#'.$lease['number'], - $html->link($lease['Unit']['name'], - array('controller' => 'units', - 'action' => 'view', - $lease['Unit']['id'])), - datefmt($lease['lease_date']), - datefmt($lease['movein_date']), - datefmt($lease['moveout_date']), - $lease['amount'], - $lease['deposit'], - $lease['comment']); -} - -echo $this->element('table', - array('class' => 'item lease list', - 'caption' => 'Lease History', - 'headers' => $headers, - 'rows' => $rows, - 'column_class' => $headers)); +echo $this->element('leases', + array('caption' => 'Lease History', + 'leases' => $customer['Lease'])); /********************************************************************** - * Ledger History + * Account */ -echo $this->element('ledger', - array('caption' => 'Ledger History', - 'transactions' => $customer['Transaction'], - 'ledger' => array('mix'=>1))); + +echo $this->element('accounts', + array('caption' => 'Account', + 'accounts' => array($customer['Account']))); + /* End "detail supporting" DIV */ ?>
diff --git a/site/views/elements/accounts.ctp b/site/views/elements/accounts.ctp index aaf9452..1d312f0 100644 --- a/site/views/elements/accounts.ctp +++ b/site/views/elements/accounts.ctp @@ -2,28 +2,17 @@ if (isset($heading)) echo $heading; -else +elseif (!isset($caption)) echo '

'.__('Accounts',true).'

'; -function currency($number) { - if ($number < 0) - return "($ " . number_format(-1*$number, 2) . ")"; - else - return "$ " . number_format($number, 2); -} - -function datefmt($date) { - $date_fmt = 'm/d/Y'; - return ($date - ? date_format(date_create($date), $date_fmt) - : null); -} - $headers = array('Name', 'Type', 'Ext. Name', 'Ext. Account', 'Entries', 'Debits', 'Credits', 'Balance', 'Comment'); $column_class = array(); -foreach (array_intersect($column_class, array('Debits', 'Credits', 'Balance')) AS $k => $v) { +foreach (array_intersect($headers, array('Debits', 'Credits', 'Balance')) AS $k => $v) { $column_class[$k] = 'currency'; } +foreach (array_intersect($headers, array('Comment')) AS $k => $v) { + $column_class[$k] = 'slack'; +} if (isset($paginator)) { echo $paginator->counter(array( @@ -61,15 +50,16 @@ foreach ($accounts as $account) { $account['external_name'], $account['external_account'], $account['entries'], - currency($account['debits']), - currency($account['credits']), - currency($account['balance']), + FormatHelper::currency($account['debits']), + FormatHelper::currency($account['credits']), + FormatHelper::currency($account['balance']), $account['comment'], ); } echo $this->element('table', array('class' => 'item account list', + 'caption' => isset($caption) ? $caption : null, 'headers' => $headers, 'rows' => $rows, 'column_class' => $column_class)); diff --git a/site/views/elements/contacts.ctp b/site/views/elements/contacts.ctp index 54c10c3..cdb4c5f 100644 --- a/site/views/elements/contacts.ctp +++ b/site/views/elements/contacts.ctp @@ -5,9 +5,17 @@ if (isset($heading)) elseif (!isset($caption)) echo '

'.__('Contacts',true).'

'; -$headers_manual = array_merge(array('Id', 'Last Name', 'First Name', 'Company'), - isset($contacts[0]['ContactsCustomer']) ? array('Type', 'Active') : array(), - array('Comment')); +$headers = array_merge(array('ID', 'Last Name', 'First Name', 'Company'), + isset($contacts[0]['ContactsCustomer']) ? array('Type', 'Active') : array(), + array('Comment')); + +foreach (array_intersect($headers, array('ID')) AS $k => $v) { + $column_class[$k] = 'id'; +} +foreach (array_intersect($headers, array('Comment')) AS $k => $v) { + $column_class[$k] = 'comment'; +} + if (isset($paginator)) { echo $paginator->counter(array( 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); @@ -21,8 +29,6 @@ if (isset($paginator)) { $paginator->sort('active')) : array()), array($paginator->sort('comment'))); -} else { - $headers = $headers_manual; } $rows = array(); @@ -55,7 +61,7 @@ echo $this->element('table', 'caption' => isset($caption) ? $caption : null, 'headers' => $headers, 'rows' => $rows, - 'column_class' => $headers_manual)); + 'column_class' => $column_class)); if (isset($paginator)) { echo('
' . "\n"); diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index 38cf034..471e203 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -2,10 +2,18 @@ if (isset($heading)) echo $heading; -else +elseif (!isset($caption)) echo '

'.__('Customers',true).'

'; -$headers_manual = array('Id', 'Name', 'Comment'); +$headers = array('ID', 'Name', 'Comment'); +$column_class = array(); +foreach (array_intersect($headers, array('ID')) AS $k => $v) { + $column_class[$k] = 'id'; +} +foreach (array_intersect($headers, array('Comment')) AS $k => $v) { + $column_class[$k] = 'comment'; +} + if (isset($paginator)) { echo $paginator->counter(array( 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); @@ -13,8 +21,6 @@ if (isset($paginator)) { $headers = array($paginator->sort('id'), $paginator->sort('name'), $paginator->sort('comment')); -} else { - $headers = $headers_manual; } $rows = array(); @@ -38,7 +44,7 @@ echo $this->element('table', 'caption' => isset($caption) ? $caption : null, 'headers' => $headers, 'rows' => $rows, - 'column_class' => $headers_manual)); + 'column_class' => $column_class)); if (isset($paginator)) { echo('
' . "\n"); diff --git a/site/views/elements/ledger.ctp b/site/views/elements/ledger.ctp index 4ae5d62..4128277 100644 --- a/site/views/elements/ledger.ctp +++ b/site/views/elements/ledger.ctp @@ -1,26 +1,22 @@ '.__('Ledger',true).''; + $headers = array('Transaction', 'Entry', 'Date', 'Customer', 'Comment', 'Debit', 'Credit', 'Total'); -$column_class = $headers; -foreach (array_intersect($column_class, array('Transaction', 'Entry')) AS $k => $v) { +$column_class = array(); +foreach (array_intersect($headers, array('Transaction', 'Entry')) AS $k => $v) { $column_class[$k] = array($column_class[$k], 'id'); } -foreach (array_intersect($column_class, array('Debits', 'Credits', 'Total')) AS $k => $v) { +foreach (array_intersect($headers, array('Debit', 'Credit', 'Total')) AS $k => $v) { $column_class[$k] = array($column_class[$k], 'currency'); } -/* if (isset($paginator)) { */ -/* echo $paginator->counter(array( */ -/* 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); */ +foreach (array_intersect($headers, array('Comment')) AS $k => $v) { + $column_class[$k] = 'slack'; +} -/* $headers = array($paginator->sort('Transaction', 'transaction_id'), */ -/* $paginator->sort('entry_id'), */ -/* $paginator->sort('Date', 'stamp'), */ -/* $paginator->sort('customer_id'), */ -/* $paginator->sort('comment'), */ -/* $paginator->sort('debit'), */ -/* $paginator->sort('credit'), */ -/* $paginator->sort('total')); */ -/* } */ $rows = array(); $running_total = 0; @@ -48,33 +44,23 @@ foreach($entries AS $entry) { array('controller' => 'ledger_entries', 'action' => 'view', $entry['id'])), - datefmt($transaction['stamp']), + FormatHelper::date($transaction['stamp']), $html->link($customer['name'], array('controller' => 'customers', 'action' => 'view', $customer['id'])), - comment(array($transaction['comment'], $entry['comment'])), - currency($debit), - currency($credit), - currency($running_total) + FormatHelper::comment(array($transaction['comment'], $entry['comment'])), + FormatHelper::currency($debit), + FormatHelper::currency($credit), + FormatHelper::currency($running_total) ); } echo $this->element('table', array('class' => 'item account ledger list', - 'caption' => $caption, + 'caption' => isset($caption) ? $caption : null, 'headers' => $headers, 'rows' => $rows, 'column_class' => $column_class)); -/* if (isset($paginator)) { */ -/* echo('
' . "\n"); */ -/* echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); */ -/* echo(' | '); */ -/* echo $paginator->numbers(); */ -/* echo(' | '); */ -/* echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); */ -/* echo('
' . "\n"); */ -/* } */ - ?> diff --git a/site/views/elements/ledgers.ctp b/site/views/elements/ledgers.ctp index 13c4219..4155126 100644 --- a/site/views/elements/ledgers.ctp +++ b/site/views/elements/ledgers.ctp @@ -11,8 +11,11 @@ $headers = array_merge(array('Name'), : array()), array('Entries', 'Debits', 'Credits', 'Balance', 'Closed', 'Comment')); $column_class = array(); -foreach (array_intersect($column_class, array('Comment')) AS $k => $v) { - $column_class[$k] = 'comment'; +foreach (array_intersect($headers, array('Debits', 'Credits', 'Balance')) AS $k => $v) { + $column_class[$k] = 'currency'; +} +foreach (array_intersect($headers, array('Comment')) AS $k => $v) { + $column_class[$k] = 'slack'; } if (isset($paginator)) { @@ -52,9 +55,9 @@ foreach ($ledgers as $ledger) { $account['id']))) : array()), array($ledger['entries'], - currency($ledger['debits']), - currency($ledger['credits']), - currency($ledger['balance']), + FormatHelper::currency($ledger['debits']), + FormatHelper::currency($ledger['credits']), + FormatHelper::currency($ledger['balance']), $ledger['closed'] ? 'Closed' : 'Open', $ledger['comment'])); } diff --git a/site/views/elements/maps.ctp b/site/views/elements/maps.ctp index ee148c9..dc475fb 100644 --- a/site/views/elements/maps.ctp +++ b/site/views/elements/maps.ctp @@ -2,10 +2,18 @@ if (isset($heading)) echo $heading; -else +elseif (!isset($caption)) echo '

'.__('Maps',true).'

'; -$headers_manual = array('Id', 'Name', 'Area', 'Width', 'Depth', 'Comment'); +$headers = array('ID', 'Name', 'Area', 'Width', 'Depth', 'Comment'); +$column_class = array(); +foreach (array_intersect($headers, array('ID')) AS $k => $v) { + $column_class[$k] = 'id'; +} +foreach (array_intersect($headers, array('Comment')) AS $k => $v) { + $column_class[$k] = 'slack'; +} + if (isset($paginator)) { echo $paginator->counter(array( 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); @@ -16,8 +24,6 @@ if (isset($paginator)) { $paginator->sort('width'), $paginator->sort('depth'), $paginator->sort('comment')); -} else { - $headers = $headers_manual; } $rows = array(); @@ -40,7 +46,7 @@ echo $this->element('table', array('class' => 'item map list', 'headers' => $headers, 'rows' => $rows, - 'column_class' => $headers_manual)); + 'column_class' => $column_class)); if (isset($paginator)) { echo('
' . "\n"); diff --git a/site/views/elements/transactions.ctp b/site/views/elements/transactions.ctp index abf2535..556e71b 100644 --- a/site/views/elements/transactions.ctp +++ b/site/views/elements/transactions.ctp @@ -8,7 +8,7 @@ elseif (!isset($caption)) $headers = array('Id', 'Timestamp', 'Comment'); $column_class = array(); foreach (array_intersect($headers, array('Comment')) AS $k => $v) { - $column_class[$k] = 'comment'; + $column_class[$k] = 'slack'; } foreach (array_intersect($headers, array('Id')) AS $k => $v) { $column_class[$k] = 'id'; @@ -41,9 +41,9 @@ foreach ($transactions as $transaction) { array('controller' => 'customers', 'action' => 'view', $customer['id'])), - datefmt($transaction['stamp']), - datefmt($transaction['through_date']), - datefmt($transaction['due_date']), + FormatHelper::date($transaction['stamp']), + FormatHelper::date($transaction['through_date']), + FormatHelper::date($transaction['due_date']), $transaction['comment']); } diff --git a/site/views/elements/units.ctp b/site/views/elements/units.ctp index d0f90ee..6376a3c 100644 --- a/site/views/elements/units.ctp +++ b/site/views/elements/units.ctp @@ -5,7 +5,15 @@ if (isset($heading)) else echo '

'.__('Units',true).'

'; -$headers_manual = array('Id', 'Unit', 'Size', 'Status', 'Comment'); +$headers = array('ID', 'Unit', 'Size', 'Status', 'Comment'); +$column_class = array(); +foreach (array_intersect($headers, array('ID')) AS $k => $v) { + $column_class[$k] = 'id'; +} +foreach (array_intersect($headers, array('Comment')) AS $k => $v) { + $column_class[$k] = 'slack'; +} + if (isset($paginator)) { echo $paginator->counter(array( 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); @@ -15,8 +23,6 @@ if (isset($paginator)) { $paginator->sort('unit_size_id'), $paginator->sort('status'), $paginator->sort('comment')); -} else { - $headers = $headers_manual; } $rows = array(); @@ -36,9 +42,10 @@ foreach ($units as $unit) { echo $this->element('table', array('class' => 'item unit list', + 'caption' => isset($caption) ? $caption : null, 'headers' => $headers, 'rows' => $rows, - 'column_class' => $headers_manual)); + 'column_class' => $column_class)); if (isset($paginator)) { echo('
' . "\n"); diff --git a/site/views/helpers/format.php b/site/views/helpers/format.php new file mode 100644 index 0000000..4b93bab --- /dev/null +++ b/site/views/helpers/format.php @@ -0,0 +1,66 @@ +currency($amount) + : null); + +/* if ($money < 0) */ +/* return "($ " . number_format(-1*$money, 2) . ")"; */ +/* else */ +/* return "$ " . number_format($money, 2); */ + } + + function date($date) { + $date_fmt = 'm/d/Y'; + return (isset($date) + ? self::$time->format($date_fmt, $date) + //? date_format(date_create($date), $date_fmt) + : null); + } + + function datetime($datetime) { + if (!$date) return null; + return self::$time->nice($datetime); + } + + function phone($phone) { + if (!isset($phone)) + return null; + + $phone = preg_replace("/\D/", "", $phone); + if(strlen($phone) == 7) + return preg_replace("/(\d{3})(\d{4})/", "$1-$2", $phone); + elseif(strlen($phone) == 10) + return preg_replace("/(\d{3})(\d{3})(\d{4})/", "$1-$2-$3", $phone); + else + return $phone; + } + + function comment($comment) { + if (isset($comment) && is_array($comment)) { + foreach (array_keys($comment) AS $k) { + if (!$comment[$k]) + unset($comment[$k]); + } + return implode('; ', $comment); + } + + return $comment; + } + +} diff --git a/site/views/ledgers/view.ctp b/site/views/ledgers/view.ctp index 63320e3..0cddc40 100644 --- a/site/views/ledgers/view.ctp +++ b/site/views/ledgers/view.ctp @@ -5,36 +5,6 @@ 'accounts', 'action' => 'view', $ledger['Account']['id']))), - array('Closed', $ledger['Ledger']['closed']), + array('Status', $ledger['Ledger']['closed'] ? 'Closed' : 'Open'), array('Comment', $ledger['Ledger']['comment'])); echo $this->element('table', @@ -66,7 +36,7 @@ echo $this->element('table',
- Ledger Balance: + Ledger Balance:
diff --git a/site/views/transactions/view.ctp b/site/views/transactions/view.ctp index 3a9e87f..4771455 100644 --- a/site/views/transactions/view.ctp +++ b/site/views/transactions/view.ctp @@ -3,21 +3,7 @@
element('table', ?>
- Debits: + Debits:
- Credits: + Credits:
@@ -83,8 +69,8 @@ foreach($transaction['LedgerEntry'] AS $entry) { 'action' => 'view', $entry['CreditLedger']['id'])), $entry['comment'], - currency($entry['amount']), - currency($running_total) + FormatHelper::currency($entry['amount']), + FormatHelper::currency($running_total) ); } diff --git a/site/views/units/view.ctp b/site/views/units/view.ctp index 5bc79ce..e6b79fe 100644 --- a/site/views/units/view.ctp +++ b/site/views/units/view.ctp @@ -3,22 +3,7 @@
element('table', ?>
- Security Deposit: + Security Deposit:
- Balance: + Balance:
@@ -67,28 +52,10 @@ echo $this->element('table', /********************************************************************** * Lease History */ -$headers = array('Lease', 'Tenant', 'Signed', 'Move-In', 'Move-Out', 'Rent', 'Deposit', 'Comment'); -$rows = array(); -foreach($unit['Lease'] AS $lease) { - $rows[] = array('#'.$lease['number'], - $html->link($lease['Customer']['name'], - array('controller' => 'customers', - 'action' => 'view', - $lease['Customer']['id'])), - datefmt($lease['lease_date']), - datefmt($lease['movein_date']), - datefmt($lease['moveout_date']), - currency($lease['amount']), - currency($lease['deposit']), - $lease['comment']); -} -echo $this->element('table', - array('class' => 'item lease list', - 'caption' => 'Lease History', - 'headers' => $headers, - 'rows' => $rows, - 'column_class' => $headers)); +echo $this->element('leases', + array('caption' => 'Lease History', + 'leases' => $unit['Lease'])); /********************************************************************** From 190a9259d476d70afd18f3ffff950505c46e87d3 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 10 Jun 2009 02:27:03 +0000 Subject: [PATCH 077/717] More changes to how accounts/ledgers/transactions are all handled. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@78 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 39 ++++++++++++---------- scripts/sitelink2pmgr.pl | 70 ++++++++++++++++++++++++---------------- 2 files changed, 64 insertions(+), 45 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index e6b638e..b2c4115 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -632,6 +632,8 @@ CREATE TABLE `pmgr_customers` ( `name` VARCHAR(80) NOT NULL, `comment` VARCHAR(255) DEFAULT NULL, + `account_id` INT(10) UNSIGNED NOT NULL, + PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; @@ -689,6 +691,7 @@ CREATE TABLE `pmgr_leases` ( `lease_type_id` INT(10) UNSIGNED NOT NULL, `unit_id` INT(10) UNSIGNED NOT NULL, `customer_id` INT(10) UNSIGNED NOT NULL, + `account_id` INT(10) UNSIGNED NOT NULL, `late_schedule_id` INT(10) UNSIGNED DEFAULT NULL, `lease_date` DATE NOT NULL, @@ -832,17 +835,17 @@ CREATE TABLE `pmgr_accounts` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8; LOCK TABLES `pmgr_accounts` WRITE; -INSERT INTO `pmgr_accounts` (`id`, `type`, `name`) +INSERT INTO `pmgr_accounts` (`type`, `name`) VALUES - (1, 'ASSET', 'A/R'), - (2, 'LIABILITY', 'A/P'), - (3, 'LIABILITY', 'Tax'), - (4, 'LIABILITY', 'Customer Credit'), - (5, 'ASSET', 'Bank'), - (6, 'ASSET', 'Cash'), - (7, 'LIABILITY', 'Security Deposit'), - (8, 'INCOME', 'Rent'), - (9, 'INCOME', 'Late Charge'); + ('ASSET', 'A/R'), + ('LIABILITY', 'A/P'), + ('LIABILITY', 'Tax'), + ('LIABILITY', 'Customer Credit'), + ('ASSET', 'Bank'), + ('ASSET', 'Cash'), + ('LIABILITY', 'Security Deposit'), + ('INCOME', 'Rent'), + ('INCOME', 'Late Charge'); UNLOCK TABLES; @@ -882,9 +885,18 @@ CREATE TABLE `pmgr_ledgers` ( -- this particular ledger is valid and so on. `name` VARCHAR(80) DEFAULT NULL, + `sequence` INT(10) UNSIGNED DEFAULT 1, `account_id` INT(10) UNSIGNED NOT NULL, `closed` INT UNSIGNED DEFAULT 0, + -- REVISIT : 20090607 + -- Probably, a single close should have the ability to close + -- many different account ledgers. For now, just timestamping. + -- `close_id` INT(10) UNSIGNED NOT NULL, + + `open_stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `close_stamp` DATETIME DEFAULT NULL, + `comment` VARCHAR(255) DEFAULT NULL, PRIMARY KEY (`id`) @@ -903,13 +915,6 @@ CREATE TABLE `pmgr_transactions` ( `through_date` DATE DEFAULT NULL, `due_date` DATE DEFAULT NULL, - -- REVISIT : 20090604 - -- It really seems this is too restrictive. One tenant - -- should be able to, within a single transaction, pay - -- for their own charges and another tenant's as well. - -- customer_id may need to move to ledger_entries - `customer_id` INT(10) UNSIGNED NOT NULL, - -- REVISIT : 20090604 -- How should we track which charges have been paid? -- `related_transaction_id` INT(10) UNSIGNED NOT NULL, diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index a397309..975c15e 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -145,17 +145,25 @@ sub executeSchema { sub buildTables { foreach my $table (values %{$newdb{'tables'}}) { + printf(STDERR "%-30s : %d rows\n", $table->{'name'}, int(@{$table->{'rows'}})); + foreach (@{$table->{'rows'}}) { - next unless defined $_; + next unless defined $_; - my %row = %$_; - delete $row{'--LINE--'}; + my %row = %$_; + delete $row{'--LINE--'}; - my $query; - $query = "INSERT INTO " . $table->{'name'}; - $query .= " (" . join(", ", map({"`$_`"} keys(%row))) . ")"; - $query .= " VALUES (" . join(", ", map({s/'/''/g if defined $_; defined $_ ? "'$_'" : "NULL"} values(%row))) . ")"; - query($db_handle, $query, $_); + my $query; + $query = "INSERT INTO " . $table->{'name'}; + $query .= " (" . join(", ", map({"`$_`"} keys(%row))) . ")"; + $query .= " VALUES (" . join(", ", map({s/'/''/g if defined $_; + defined $_ + ? (/^\w+\(.*\)$/ + ? $_ + : "'$_'" ) + : "NULL" } + values(%row))) . ")"; + query($db_handle, $query, $_); } } } @@ -425,6 +433,7 @@ $result = query($db_handle, $query); foreach $row (@$result) { addRow('ledgers', { 'account_id' => $row->{'id'}, + 'open_stamp' => '2009-01-01', 'name' => $row->{'name'} . ' Ledger', 'comment' => undef }); @@ -648,15 +657,19 @@ foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'} = $newdb{'tables'}{'contacts'}{'autoid'}; - # Every customer gets their own ledger + # Every customer gets their own account addRow('accounts', { 'type' => 'ASSET', - 'name' => 'Customer: ' . $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'name'}, - 'comment' => undef }); + 'name' => ('Account: Customer #' . ($newdb{'tables'}{'customers'}{'autoid'}+1) . + ' ('.$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'name'} . ')'), + 'comment' => undef }); + #'comment' => 'For direct customer transaction, NOT lease charges!' }); addRow('ledgers', { 'account_id' => $newdb{'tables'}{'accounts'}{'autoid'}, - 'name' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'name'} . ' Ledger', - 'comment' => 'Ledger for Customer Account #' . $newdb{'tables'}{'accounts'}{'autoid'} }); + 'open_stamp' => '2009-01-01', + 'name' => 'Ledger: Customer #' . ($newdb{'tables'}{'customers'}{'autoid'}+1) + . ' ('.$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'name'} . ')', + 'comment' => undef }); $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account'} = $newdb{'tables'}{'accounts'}{'autoid'}; @@ -782,16 +795,19 @@ $newdb{'lookup'}{'ledger'} = {}; $query = "SELECT L.*, A.TenantID FROM TenantLedger L LEFT JOIN `Access` A ON A.LedgerID = L.LedgerID WHERE L.UnitID <> 'POS\$' ORDER BY L.LedgerID"; foreach $row (@{query($sdbh, $query)}) { - # Every lease gets its own ledger + # Every lease gets its own account addRow('accounts', { 'type' => 'ASSET', - 'name' => 'Lease: #' . ($newdb{'tables'}{'leases'}{'autoid'}+1), - 'comment' => undef }); + 'name' => ('Account: Lease #' . ($newdb{'tables'}{'leases'}{'autoid'}+1) + . ' ('.$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'name'} . ')'), + 'comment' => undef }); + #'comment' => 'For lease related transaction, NOT personal charges!' }); addRow('ledgers', { 'account_id' => $newdb{'tables'}{'accounts'}{'autoid'}, - 'name' => 'Lease #' . ($newdb{'tables'}{'leases'}{'autoid'}+1) + 'open_stamp' => datefmt($row->{'DateIn'}), + 'name' => 'Ledger: Lease #' . ($newdb{'tables'}{'leases'}{'autoid'}+1) . ' ('.$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'name'} . ')', - 'comment' => 'Ledger for Customer Account #' . $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'} }); + 'comment' => undef }); $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}} = { 'cust' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'}, @@ -836,8 +852,7 @@ foreach $row (@{query($sdbh, $query)}) { addRow('transactions', { 'stamp' => datefmt($row->{'ChargeDate'}), - 'through_date' => datefmt($row->{'EndDate'}), - 'customer_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust'} }); + 'through_date' => datefmt($row->{'EndDate'}) }); $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}} = { 'tx' => $newdb{'tables'}{'transactions'}{'autoid'}, @@ -888,8 +903,7 @@ foreach $row (@{query($sdbh, $query)}) { addRow('transactions', { 'stamp' => datefmt($row->{'ReceiptDate'}), - 'through_date' => undef, - 'customer_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust'} }); + 'through_date' => undef }); $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}} = {'tx' => $newdb{'tables'}{'transactions'}{'autoid'}, @@ -1030,8 +1044,10 @@ $newdb{'ids'}{'ledger'}{'Cash-Old'} = addRow('ledgers', { 'account_id' => $newdb{'lookup'}{'account'}{'Cash'}{'account'}, - 'name' => 'Fake Cash Ledger', - 'comment' => 'Fake ledger for testing' }); + 'open_stamp' => 'NOW()', + 'sequence' => 2, + 'name' => 'Fake Cash Ledger', + 'comment' => 'Fake ledger for testing' }); $newdb{'lookup'}{'account'}{'Cash'}{'ledger'} = $newdb{'tables'}{'ledgers'}{'autoid'}; @@ -1046,8 +1062,7 @@ foreach $row (@{$newdb{'tables'}{'ledger_entries'}{'rows'}}) { } addRow('transactions', - { 'customer_id' => 0, - 'stamp' => '2009-05-10' }); + { 'stamp' => '2009-05-10' }); addRow('ledger_entries', { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, @@ -1059,7 +1074,7 @@ addRow('ledger_entries', 'comment' => "Carrying forward old ledger balance onto new ledger" }); $newdb{'tables'}{'ledgers'}{'rows'}[$newdb{'ids'}{'ledger'}{'Cash-Old'}]{'closed'} = 1; - +$newdb{'tables'}{'ledgers'}{'rows'}[$newdb{'ids'}{'ledger'}{'Cash-Old'}]{'close_stamp'} = 'NOW()'; foreach my $ir ('invoice', 'receipt') { foreach my $tx (@{$fake{$ir}}) { @@ -1069,7 +1084,6 @@ foreach my $ir ('invoice', 'receipt') { { 'id' => $tx->{'id'}, 'stamp' => $tx->{'date'}, 'through_date' => $tx->{'thru'}, - 'customer_id' => $fake{'custid'}, 'comment' => "Fake $ir" }, 1); From 136d8e845abe5f0e8ec194003f8724f20c9b645e Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 10 Jun 2009 02:29:33 +0000 Subject: [PATCH 078/717] Fixed issue with the SQL debug output since the error column is typically empty git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@79 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/webroot/css/cake.generic.css | 1 + 1 file changed, 1 insertion(+) diff --git a/site/webroot/css/cake.generic.css b/site/webroot/css/cake.generic.css index 6a5579f..2dab93b 100644 --- a/site/webroot/css/cake.generic.css +++ b/site/webroot/css/cake.generic.css @@ -67,6 +67,7 @@ table.cake-sql-log { background: #f4f4f4; + empty-cells: show; border:1px solid #ccc; border-right:0; clear: both; From 4988d2717fe0bceaddb588d8db1d5115e09bbbd6 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 10 Jun 2009 02:31:49 +0000 Subject: [PATCH 079/717] Fixed problem with relationships that are defined soley on the 'conditions' part of the association, and not on 'foreignKey' (which is allowed to be 'false'). git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@80 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/behaviors/linkable.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/site/models/behaviors/linkable.php b/site/models/behaviors/linkable.php index 388456f..c530ea5 100644 --- a/site/models/behaviors/linkable.php +++ b/site/models/behaviors/linkable.php @@ -177,7 +177,8 @@ class LinkableBehavior extends ModelBehavior { $options['alias'] = $linkAlias; $options['table'] = $Link->getDataSource()->fullTableName($Link); $options['conditions'][] = "{$referenceLink} = {$referenceKey}"; - } else { + } + elseif (isset($association['foreignKey']) && $association['foreignKey']) { $foreignKey = $primaryModel->escapeField($association['foreignKey']); $primaryKey = $foreignModel->escapeField($foreignModel->primaryKey); @@ -188,6 +189,10 @@ class LinkableBehavior extends ModelBehavior { else $options['conditions'][] = "{$foreignKey} = {$primaryKey}"; } + else { + // No Foreign Key... nothing we can do. + $options['conditions'] = array(); + } // The user may have specified conditions directly in the model // for this join. Make sure to adhere to those conditions. From 9f8d4fa9b2f71b41845358695cd6ca873d791137 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 10 Jun 2009 02:41:23 +0000 Subject: [PATCH 080/717] Significant changes to work with the new account/ledger structure. Removed much of the auto-generated model association code. Added helper functions into the models to perform model related work, such as model 'stats' (a bad name for a function to return a summary of pertinent financial information from a given model instance). There is a ton of cleanup to do, but first I want to get it all captured. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@81 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 1 - site/app_model.php | 33 ++ site/controllers/accounts_controller.php | 133 +++---- site/controllers/contacts_controller.php | 89 +---- site/controllers/customers_controller.php | 125 +++--- site/controllers/ledgers_controller.php | 90 ++--- site/controllers/units_controller.php | 77 +--- site/models/account.php | 440 ++++++++++++++++++++-- site/models/contact.php | 37 +- site/models/contact_address.php | 7 - site/models/contact_email.php | 7 - site/models/contact_phone.php | 7 - site/models/customer.php | 220 +++++++++-- site/models/lease.php | 177 +++++++-- site/models/lease_type.php | 15 +- site/models/ledger.php | 205 +++++++--- site/models/ledger_entry.php | 94 ++++- site/models/map.php | 25 +- site/models/monetary_source.php | 14 +- site/models/monetary_type.php | 14 +- site/models/site.php | 29 +- site/models/site_area.php | 18 +- site/models/transaction.php | 22 +- site/models/unit.php | 60 +-- site/models/unit_size.php | 22 +- site/models/unit_type.php | 14 +- site/views/accounts/view.ctp | 11 +- site/views/contacts/view.ctp | 4 +- site/views/elements/accounts.ctp | 23 +- site/views/elements/contacts.ctp | 2 +- site/views/elements/customers.ctp | 38 +- site/views/elements/leases.ctp | 82 ++++ site/views/elements/ledger.ctp | 66 ---- site/views/elements/ledger_entries.ctp | 69 ++++ site/views/elements/ledgers.ctp | 36 +- site/views/helpers/format.php | 5 +- site/views/ledgers/view.ctp | 6 +- site/views/transactions/index.ctp | 10 - site/views/transactions/view.ctp | 2 +- site/views/units/view.ctp | 16 +- site/webroot/css/layout.css | 12 +- 41 files changed, 1441 insertions(+), 916 deletions(-) create mode 100644 site/views/elements/leases.ctp delete mode 100644 site/views/elements/ledger.ctp create mode 100644 site/views/elements/ledger_entries.ctp diff --git a/site/app_controller.php b/site/app_controller.php index 19af659..c1e74e5 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -41,7 +41,6 @@ class AppController extends Controller { return array( array('name' => 'Common', 'header' => true), array('name' => 'Site Map', 'url' => array('controller' => 'maps', 'action' => 'view', 1)), - array('name' => 'Tenants', 'url' => array('controller' => 'contacts', 'action' => 'index')), array('name' => 'Units', 'url' => array('controller' => 'units', 'action' => 'index')), array('name' => 'Customers', 'url' => array('controller' => 'customers', 'action' => 'index')), array('name' => 'Contacts', 'url' => array('controller' => 'contacts', 'action' => 'index')), diff --git a/site/app_model.php b/site/app_model.php index 0f1bb9c..97f8611 100644 --- a/site/app_model.php +++ b/site/app_model.php @@ -78,6 +78,39 @@ class AppModel extends Model { } //end getEnumValues + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * 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"); + } + } + // Overriding pagination, since the stupid count mechanism blows. // This is also a crappy solution, especially if the query returns // a really large number of rows. However, trying to untagle this diff --git a/site/controllers/accounts_controller.php b/site/controllers/accounts_controller.php index 1bb9c21..c1080ad 100644 --- a/site/controllers/accounts_controller.php +++ b/site/controllers/accounts_controller.php @@ -9,12 +9,13 @@ class AccountsController extends AppController { (// Models 'LedgerEntry' => array('fields' => - array('SUM(IF(LedgerEntry.debit_ledger_id = CurrentLedger.id, LedgerEntry.amount, 0)) AS debits', - 'SUM(IF(LedgerEntry.credit_ledger_id = CurrentLedger.id, LedgerEntry.amount, 0)) AS credits', + array('SUM(IF(LedgerEntry.debit_ledger_id = CurrentLedger.id, LedgerEntry.amount, NULL)) AS debits', + 'SUM(IF(LedgerEntry.credit_ledger_id = CurrentLedger.id, LedgerEntry.amount, NULL)) AS credits', "SUM(IF(Account.type IN ('ASSET', 'EXPENSE'), IF(LedgerEntry.debit_ledger_id = CurrentLedger.id, 1, -1), IF(LedgerEntry.credit_ledger_id = CurrentLedger.id, 1, -1) - )* LedgerEntry.amount) AS balance", + ) * IF(LedgerEntry.amount, LedgerEntry.amount, 0) + ) AS balance", 'COUNT(LedgerEntry.id) AS entries'), 'conditions' => array('OR' => @@ -166,99 +167,51 @@ class AccountsController extends AppController { $this->redirect(array('action'=>'index')); } -/* $this->Account->bindModel(array('hasMany' => array */ -/* ('LedgerEntry' => array */ -/* ('className' => 'LedgerEntry', */ -/* 'foreignKey' => false, */ -/* 'finderQuery' => 'SELECT `LedgerEntry`.* */ -/* FROM pmgr_entries AS `LedgerEntry` */ -/* LEFT JOIN pmgr_transactions AS `Transaction` */ -/* ON `Transaction`.id = `LedgerEntry`.transaction_id */ -/* WHERE LedgerEntry.debit_ledger_id = ({$__cakeID__$}) */ -/* OR LedgerEntry.credit_ledger_id = ({$__cakeID__$}) */ -/* ORDER BY Transaction.stamp', */ -/* )))); */ + // Get details about the account and its ledgers (no ledger entries yet) + $this->Account->Behaviors->attach('Containable'); + $account = $this->Account->find + ('first', + array('contain' => + array(// Models + 'CurrentLedger' => + array('fields' => array('id', 'sequence')), -/* $this->Account->Behaviors->attach('Containable'); */ -/* $this->Account->Contain(array('LedgerEntry' => array */ -/* ( */ -/* // Models */ -/* 'Transaction' => array */ -/* ( */ -/* // Models */ -/* 'Customer', */ -/* )), */ - -/* )); */ -/* } */ -/* $account = $this->Account->read(null, $id); */ + 'Ledger' => + array('order' => array('Ledger.open_stamp' => 'DESC')), + ), + 'conditions' => array(array('Account.id' => $id)), + ) + ); + $this->Account->Behaviors->detach('Containable'); + // Simply debug stuff... testing. + $cond = null; + //$cond = array('Transaction.stamp >' => '2009-05-16'); - $this->Account->recursive = -1; - $account = $this->Account->read(null, $id); + // Get all ledger entries of the CURRENT ledger + //$crap = $this->Account->findSecurityDeposits($id); + //$crap = $this->Account->findAccountRelatedEntries($id, 8); + //pr(array('crap', $crap)); +/* $this->autoRender = false; */ +/* return; */ - $account['Ledger'] = $this->Account->find - ('all', array - ('link' => array - (// Models - 'Ledger' => array - (// Models - 'LedgerEntry' => - array('fields' => - array('SUM(IF(LedgerEntry.debit_ledger_id = Ledger.id, LedgerEntry.amount, 0)) AS debits', - 'SUM(IF(LedgerEntry.credit_ledger_id = Ledger.id, LedgerEntry.amount, 0)) AS credits', - "SUM(IF(Account.type IN ('ASSET', 'EXPENSE'), - IF(LedgerEntry.debit_ledger_id = Ledger.id, 1, -1), - IF(LedgerEntry.credit_ledger_id = Ledger.id, 1, -1) - ) * LedgerEntry.amount) AS balance", - 'COUNT(LedgerEntry.id) AS entries'), - 'conditions' => - array('OR' => - array('LedgerEntry.debit_ledger_id = Ledger.id', - 'LedgerEntry.credit_ledger_id = Ledger.id'), - ), - ), - ), - ), - 'fields' => array(), - 'conditions' => array('Account.id' => $id), - 'order' => 'Ledger.name', - 'group' => 'Ledger.id', - 'limit' => 4, - )); + // Get all ledger entries of the CURRENT ledger + $account['CurrentLedger']['LedgerEntry'] + = $this->Account->findCurrentLedgerEntries($id, $cond); + //pr(array('Account summary', $account)); - - $account['CurrentLedger'] = array_shift($this->Account->Ledger->find - ('first', array - ('link' => array - (// Models - 'Account' => array('fields' => array()), - 'LedgerEntry' => - array('fields' => - array("SUM(IF(LedgerEntry.debit_ledger_id = Ledger.id, LedgerEntry.amount, 0)) AS debits", - "SUM(IF(LedgerEntry.credit_ledger_id = Ledger.id, LedgerEntry.amount, 0)) AS credits", - "SUM(IF(Account.type IN ('ASSET', 'EXPENSE'), - IF(LedgerEntry.debit_ledger_id = Ledger.id, 1, -1), - IF(LedgerEntry.credit_ledger_id = Ledger.id, 1, -1) - ) * LedgerEntry.amount) AS balance", - 'COUNT(LedgerEntry.id) AS entries'), - 'conditions' => - array('OR' => - array("LedgerEntry.debit_ledger_id = Ledger.id", - "LedgerEntry.credit_ledger_id = Ledger.id"), - ), - ), - ), - 'fields' => array(), - 'conditions' => array(array('Ledger.account_id' => $id), - 'NOT' => array('Ledger.closed')), - //'order' => 'Ledger.name', - 'group' => 'Ledger.id', - //'limit' => 4, - ))); - //pr($account); + // Summarize each ledger + foreach($account['Ledger'] AS &$ledger) + $ledger = array_merge($ledger, + $this->Account->Ledger->stats($ledger['id'])); - $balance = $account['CurrentLedger']['balance']; + // Obtain the overall account balance + $account['Account'] = + array_merge($account['Account'], + array('stats' => $this->Account->stats($id))); + $balance = $account['Account']['stats']['Ledger']['balance']; + + // Prepare to render $title = 'Account: ' . $account['Account']['name']; $this->set(compact('account', 'title', 'balance')); } diff --git a/site/controllers/contacts_controller.php b/site/controllers/contacts_controller.php index 34f1f19..097b927 100644 --- a/site/controllers/contacts_controller.php +++ b/site/controllers/contacts_controller.php @@ -29,94 +29,11 @@ class ContactsController extends AppController { ************************************************************************** ************************************************************************** * action: index - * - Lists all current tenants + * - Lists all contacts */ function index() { - $this->current(); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: past - * - Lists all tenants, past and present - */ - - function tenants() { - $this->paginate = array_merge - ($this->paginate, - array('link' => - array(// Models - 'Lease' => - array('fields' => array(), - 'type' => 'INNER', - ), - ), - 'conditions' => array('ContactsLease.type !=' => 'ALTERNATE') - )); - - $title = 'All Tenants'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('contacts', $this->paginate()); - $this->render('index'); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: current - * - Lists all current tenants - */ - - function current() { - $this->paginate = array_merge - ($this->paginate, - array('link' => - array(// Models - 'Lease' => - array('fields' => array(), - 'type' => 'INNER', - ), - ), - 'conditions' => array('ContactsLease.type !=' => 'ALTERNATE', - 'Lease.close_date IS NULL') - )); - - $title = 'Current Tenants'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('contacts', $this->paginate()); - $this->render('index'); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: past - * - Lists all past tenants - */ - - function past() { - $this->paginate = array_merge - ($this->paginate, - array('link' => - array(// Models - 'Lease' => - array('fields' => array(), - 'type' => 'INNER', - ), - ), - 'conditions' => array('ContactsLease.type !=' => 'ALTERNATE', - 'Lease.close_date IS NOT NULL') - )); - - $title = 'Past Tenants'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('contacts', $this->paginate()); - $this->render('index'); + $this->all(); } @@ -124,7 +41,7 @@ class ContactsController extends AppController { ************************************************************************** ************************************************************************** * action: all - * - Lists all contacts, including non-tenants + * - Lists all contacts */ function all() { diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index c6db067..b4a47d1 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -2,15 +2,15 @@ class CustomersController extends AppController { var $paginate = array('limit' => 100, - 'group' => 'Customer.id', - 'order' => array('Customer.name' => 'ASC')); + 'group' => 'Customer.id', + 'order' => array('Customer.name' => 'ASC')); var $sidemenu_links = array(array('name' => 'Tenants', 'header' => true), - array('name' => 'Current', 'url' => array('controller' => 'customers', 'action' => 'current')), - array('name' => 'Past', 'url' => array('controller' => 'customers', 'action' => 'past')), - array('name' => 'All', 'url' => array('controller' => 'customers', 'action' => 'all')), - ); + 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')), + ); /************************************************************************** ************************************************************************** @@ -46,14 +46,14 @@ class CustomersController extends AppController { $this->paginate = array_merge ($this->paginate, array('link' => - array(// Models - 'Lease' => - array('fields' => array(), - 'type' => 'INNER', - ), - ), - 'conditions' => array('Lease.close_date IS NULL') - )); + array(// Models + 'Lease' => + array('fields' => array(), + 'type' => 'INNER', + ), + ), + 'conditions' => array('Lease.close_date IS NULL') + )); $title = 'Current Tenants'; $this->set('title', $title); $this->set('heading', $title); @@ -73,14 +73,14 @@ class CustomersController extends AppController { $this->paginate = array_merge ($this->paginate, array('link' => - array(// Models - 'Lease' => - array('fields' => array(), - 'type' => 'INNER', - ), - ), - 'conditions' => array('Lease.close_date IS NOT NULL') - )); + array(// Models + 'Lease' => + array('fields' => array(), + 'type' => 'INNER', + ), + ), + 'conditions' => array('Lease.close_date IS NOT NULL') + )); $title = 'Past Tenants'; $this->set('title', $title); $this->set('heading', $title); @@ -120,58 +120,61 @@ class CustomersController extends AppController { $this->Customer->Behaviors->attach('Containable'); $this->Customer->contain (array(// Models - 'Contact' => - array(// Models - 'ContactPhone', - 'ContactEmail', - 'ContactAddress', - ), - 'Transaction' => - array('order' => array('stamp'), - // Models - 'Entry' => - array(// Models - 'DebitAccount', - 'CreditAccount'), - ), - 'Lease' => - array('order' => 'movein_date', - 'conditions' => array('Lease.lease_date IS NOT NULL'), - // Models + 'Contact' => + array(// Models + 'ContactPhone', + 'ContactEmail', + 'ContactAddress', + ), + 'Account', + 'Lease' => + array(//'order' => 'movein_date', + //'conditions' => array('Lease.lease_date IS NOT NULL'), + // Models + //'Account', 'Unit' => - array('order' => array('sort_order'), - 'fields' => array('id', 'name'), - ), - ), - ) + array('order' => array('sort_order'), + 'fields' => array('id', 'name'), + ), + ), + ) ); $customer = $this->Customer->read(null, $id); + $this->Customer->Behaviors->detach('Containable'); + + foreach ($customer['Lease'] AS &$lease) { + $stats = $this->Customer->Lease->stats($lease['id']); + //pr($stats); + $lease['balance'] = $stats['Account']['Ledger']['balance']; + } + //pr($customer); - $outstanding_deposit = 0; - $outstanding_balance = 0; - foreach($customer['Transaction'] AS $transaction) { - foreach($transaction['Entry'] AS $entry) { - if ($entry['DebitAccount']['name'] === 'A/R') - $outstanding_balance += $entry['amount']; - if ($entry['CreditAccount']['name'] === 'A/R') - $outstanding_balance -= $entry['amount']; + $stats = $this->Customer->stats($id); + $deposits = $this->Customer->findSecurityDeposits($id); - if ($entry['DebitAccount']['name'] === 'Security Deposit') - $outstanding_deposit -= $entry['amount']; - if ($entry['CreditAccount']['name'] === 'Security Deposit') - $outstanding_deposit += $entry['amount']; - } - } + $outstanding_balance = $stats['balance']; + $outstanding_deposit = $deposits['summary']['balance']; + +/* pr(array('Customer Stats', $stats)); */ +/* pr(array('Security Deposits', $deposits)); */ $this->sidemenu_links[] = array('name' => 'Operations', 'header' => true); $this->sidemenu_links[] = array('name' => 'Move-Out', 'url' => array('controller' => 'units', 'action' => 'move-out')); + + $customer['Account'] = array_merge($customer['Account'], $stats['Account']['Ledger']); + //pr($stats); + //unset($stats['Lease'], $stats['Account']); +/* $customer['Account']['debits'] = 10; */ +/* $customer['Account']['credits'] = 20; */ +/* $customer['Account']['balance'] = 55; */ + $title = $customer['Customer']['name']; $this->set(compact('customer', 'title', - 'outstanding_balance', - 'outstanding_deposit')); + 'outstanding_balance', + 'outstanding_deposit')); } } diff --git a/site/controllers/ledgers_controller.php b/site/controllers/ledgers_controller.php index e54063c..644f2b4 100644 --- a/site/controllers/ledgers_controller.php +++ b/site/controllers/ledgers_controller.php @@ -25,8 +25,6 @@ class LedgersController extends AppController { 'group' => 'Ledger.id', 'order' => array('Ledger.name' => 'ASC')); - var $uses = array('Ledger', 'LedgerEntry'); - var $sidemenu_links = array(array('name' => 'Ledgers', 'header' => true), array('name' => 'Current', 'url' => array('controller' => 'ledgers', 'action' => 'current')), @@ -115,73 +113,37 @@ class LedgersController extends AppController { $this->redirect(array('action'=>'index')); } -/* $this->Ledger->bindModel(array('hasMany' => array */ -/* ('LedgerEntry' => array */ -/* ('className' => 'LedgerEntry', */ -/* 'foreignKey' => false, */ -/* 'finderQuery' => 'SELECT `LedgerEntry`.* */ -/* FROM pmgr_entries AS `LedgerEntry` */ -/* LEFT JOIN pmgr_transactions AS `Transaction` */ -/* ON `Transaction`.id = `LedgerEntry`.transaction_id */ -/* WHERE LedgerEntry.debit_ledger_id = ({$__cakeID__$}) */ -/* OR LedgerEntry.credit_ledger_id = ({$__cakeID__$}) */ -/* ORDER BY Transaction.stamp', */ -/* )))); */ - -/* $this->Ledger->Behaviors->attach('Containable'); */ -/* $this->Ledger->Contain(array('LedgerEntry' => array */ -/* ( */ -/* // Models */ -/* 'Transaction' => array */ -/* ( */ -/* // Models */ -/* 'Customer', */ -/* )), */ - -/* )); */ -/* } */ -/* $ledger = $this->Ledger->read(null, $id); */ - + // Get details about the ledger itself (no entries yet) $this->Ledger->Behaviors->attach('Containable'); - $this->Ledger->Contain(array('Account')); - $ledger = $this->Ledger->read(null, $id); - //pr($ledger); + $ledger = $this->Ledger->find + ('first', + array('contain' => + array(// Models + 'Account', + ), + 'conditions' => array(array('Ledger.id' => $id)), + ) + ); + $this->Ledger->Behaviors->detach('Containable'); - if (in_array($ledger['Account']['type'], array('ASSET', 'EXPENSE'))) - $ledger_type = 'debit'; - else - $ledger_type = 'credit'; + // Get all ledger entries of this ledger + $ledger['LedgerEntry'] = $this->Ledger->findLedgerEntries + ($id, $ledger['Account']['type']); - $ledger['LedgerEntry'] = $this->LedgerEntry->find - ('all', - array('link' => array - (// Models - 'Transaction' => - array(// Models - 'Customer', - )), - 'fields' => - array('id', 'name', 'comment', - "IF(LedgerEntry.debit_ledger_id = $id, LedgerEntry.amount, NULL) AS debit", - "IF(LedgerEntry.credit_ledger_id = $id, LedgerEntry.amount, NULL) AS credit", - "(IF(LedgerEntry.{$ledger_type}_ledger_id = $id, 1, -1) * LedgerEntry.amount) AS balance"), - 'conditions' => array('OR' => - array("LedgerEntry.debit_ledger_id = $id", - "LedgerEntry.credit_ledger_id = $id")), - 'order' => array('Transaction.stamp'), - //'limit' => 15, - //'limit' => 2, - )); - //pr($ledger); +/* $ledger['LedgerEntry'] = $this->Ledger->LedgerEntry->findInLedgerContext */ +/* ($id, +/* $ledger['LedgerEntry'] = $this->Ledger->findLedgerEntries */ +/* ($id); */ + //($id, $ledger['Account']['type']); - $balance = 0; - foreach($ledger['LedgerEntry'] AS &$entry) { - if (isset($entry[0])) - $entry = array_merge($entry[0], array_diff_key($entry, array(0))); - - $balance += $entry['balance']; - } + // Summarize the entries, and obtain the ledger balance + $ledger['Ledger'] = + array_merge($ledger['Ledger'], + array('stats' => $this->Ledger->stats($id))); + $balance = $ledger['Ledger']['stats']['balance']; + + // OK, set our view variables and render! $title = 'Ledger: ' . $ledger['Ledger']['name']; $this->set(compact('ledger', 'title', 'balance')); } diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index abe18cf..805a3aa 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -156,74 +156,27 @@ class UnitsController extends AppController { $this->Unit->contain (array(// Models 'UnitSize', - //'CurrentLease' => - 'Lease' => - array(//'order' => 'movein_date', - //'conditions' => array('Lease.lease_date IS NOT NULL', - //), - // Models - //'Contact' => array('alias' => 'PrimaryContact'), - // 'PrimaryContact', - 'Customer' => array('fields' => array('id', 'name'), - // Models - 'Transaction' => - array('order' => array('stamp'), - // Models - 'LedgerEntry' => array('DebitLedger' => array('Account'), - 'CreditLedger' => array('Account'), - ), - ), - ), -/* array(//'order' => array('sort_order'), */ -/* 'fields' => array('id', 'display_name'), */ -/* ), */ - ) + 'Lease' => array('Customer'), + 'CurrentLease' => array('Customer') ) ); + $unit = $this->Unit->read(null, $id); + $this->Unit->Behaviors->detach('Containable'); - //$unit = $this->Unit->read(null, $id); - //pr($unit); + pr($unit); - $this->Unit->Lease->Customer->Transaction->LedgerEntry->Behaviors->attach('Containable'); - $entries = $this->Unit->Lease->Customer->Transaction->LedgerEntry->find - ('all', - array - ( - 'contain' => - array('Transaction' => - array('Customer' => - array('Lease' => - array('Unit' => - array('conditions' => array('Unit.id' => $id)), - ), - ), - ), - ), - //'conditions' => 'xyz', - 'limit' => 2, - )); - pr($entries); - $this->autoRender = false; - - - $outstanding_deposit = 0; - $outstanding_balance = 0; - foreach($unit['Lease'] AS $lease) { - foreach($lease['Customer']['Transaction'] AS $transaction) { - foreach($transaction['LedgerEntry'] AS $entry) { - if ($entry['DebitLedger']['Account']['name'] === 'A/R') - $outstanding_balance += $entry['amount']; - if ($entry['CreditLedger']['Account']['name'] === 'A/R') - $outstanding_balance -= $entry['amount']; - - if ($entry['DebitLedger']['Account']['name'] === 'Security Deposit') - $outstanding_deposit -= $entry['amount']; - if ($entry['CreditLedger']['Account']['name'] === 'Security Deposit') - $outstanding_deposit += $entry['amount']; - } - } + foreach ($unit['Lease'] AS &$lease) { + $stats = $this->Unit->Lease->stats($lease['id']); + $lease['balance'] = $stats['Account']['Ledger']['balance']; } + $stats = $this->Unit->stats($id); + $deposits = $this->Unit->Lease->findSecurityDeposits($unit['CurrentLease']['id']); + + //pr($stats); + $outstanding_balance = $stats['CurrentLease']['Account']['Ledger']['balance']; + $outstanding_deposit = $deposits['summary']['balance']; + $this->sidemenu_links[] = array('name' => 'Operations', 'header' => true); $this->sidemenu_links[] = diff --git a/site/models/account.php b/site/models/account.php index 0079017..1487c3e 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -11,34 +11,428 @@ class Account extends AppModel { var $hasOne = array( 'CurrentLedger' => array( 'className' => 'Ledger', - 'foreignKey' => 'account_id', - 'dependent' => false, - 'conditions' => array(array('CurrentLedger.closed' => 0)), - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'exclusive' => '', - 'finderQuery' => '', - 'counterQuery' => '' + //'foreignKey' => 'account_id', + 'conditions' => array('NOT' => array('CurrentLedger.closed')) ), ); var $hasMany = array( - 'Ledger' => array( - 'className' => 'Ledger', - 'foreignKey' => 'account_id', - 'dependent' => false, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'exclusive' => '', - 'finderQuery' => '', - 'counterQuery' => '' - ), + 'Ledger', ); + var $cache; +/* var $instantiated; */ + + +/* /\************************************************************************** */ +/* ************************************************************************** */ +/* ************************************************************************** */ +/* * function: constructor */ +/* *\/ */ +/* function __constructor($id = null) { */ +/* parent::__contstructor(); */ +/* $this->id = $id; */ +/* $this->instantiated = true; */ +/* } */ + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: securityDepositAccountID + * - Returns the ID of the Security Deposit Account + */ + function securityDepositAccountID() { + $account = $this->find('first', array + ('recursive' => -1, + 'conditions' => array(array('name' => 'Security Deposit')), + )); + return $account['Account']['id']; + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function:rentAccountID + * - Returns the ID of the Rent Account + */ + function rentAccountID() { + $account = $this->find('first', array + ('recursive' => -1, + 'conditions' => array(array('name' => 'Rent')), + )); + return $account['Account']['id']; + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: type + * - Returns the type of this array of ledger ids from the given account + */ + function type($id) { + if (isset($this->cache[$id]['type'])) { +/* pr(array('function' => 'Account::type', */ +/* 'args' => compact('id'), */ +/* 'cache_hit' => true, */ +/* 'return' => $this->cache[$id]['type'])); */ + return $this->cache[$id]['type']; + } + + $account = $this->find('first', array + ('recursive' => -1, + 'fields' => array('type'), + 'conditions' => array(array('Account.id' => $id)), + )); + + $this->cache[$id]['type'] = $account['Account']['type']; +/* pr(array('function' => 'Account::type', */ +/* 'args' => compact('id'), */ +/* 'return' => $this->cache[$id]['type'])); */ + + return $this->cache[$id]['type']; + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: ledgers + * - Returns an array of ledger ids from the given account + */ + function ledgers($id, $all = false) { + $cachekey = $all ? 'all' : 'current'; + if (isset($this->cache[$id]['ledgers'][$cachekey])) { +/* pr(array('function' => 'Account::ledgers', */ +/* 'args' => compact('id', 'all'), */ +/* 'cache_hit' => true, */ +/* 'return' => $this->cache[$id]['ledgers'][$cachekey])); */ + return $this->cache[$id]['ledgers'][$cachekey]; + } + + if ($all) { + $contain = array('Ledger' => array('fields' => array('Ledger.id'))); + } else { + $contain = array('CurrentLedger' => array('fields' => array('CurrentLedger.id'))); + } + + $this->Behaviors->attach('Containable'); + $account = $this->find('first', array + ('contain' => $contain, + 'fields' => array(), + 'conditions' => array(array('Account.id' => $id)), + )); + $this->Behaviors->detach('Containable'); + + if ($all) { + $ledger_ids = array(); + foreach ($account['Ledger'] AS $ledger) + array_push($ledger_ids, $ledger['id']); + } + else { + $ledger_ids = array($account['CurrentLedger']['id']); + } + + $this->cache[$id]['ledgers'][$cachekey] = $ledger_ids; + +/* pr(array('function' => 'Account::ledgers', */ +/* 'args' => compact('id', 'all'), */ +/* 'return' => $this->cache[$id]['ledgers'][$cachekey])); */ + + return $this->cache[$id]['ledgers'][$cachekey]; + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findLedgerEntries + * - Returns an array of ledger entries that belong to the given + * account, either just from the current ledger, or from all ledgers. + */ + function findLedgerEntries($id, $all = false, $cond = null, $link = null) { +/* pr(array('function' => 'Account::findLedgerEntries', */ +/* 'args' => compact('id', 'all', 'cond', 'link'), */ +/* )); */ + + $entries = array(); + foreach ($this->ledgers($id, $all) AS $ledger_id) { + $ledger_entries = $this->Ledger->findLedgerEntries($ledger_id, $this->type($id), $cond, $link); + $entries = array_merge($entries, $ledger_entries); + //$entries = array_merge($entries, array_diff_key($ledger_entries, array('summary'=>1))); + //$this->statsMerge($entries['summary'], $ledger_entries['summary']); + } + +/* pr(array('function' => 'Account::findLedgerEntries', */ +/* 'args' => compact('id', 'all', 'cond', 'link'), */ +/* 'return' => compact('entries'), */ +/* )); */ + + $stats = $this->stats($id, $all, $cond); + return array('Entries' => $entries, 'summary' => $stats['Ledger']); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findLedgerEntriesRelatedToAccount + * - Returns an array of ledger entries that belong to the given + * account, and are related to a specific account, either just from + * the current ledger, or from all ledgers. + */ + function findLedgerEntriesRelatedToAccount($id, $rel_ids, $all = false, $cond = null, $link = null) { +/* pr(array('function' => 'Account::findLedgerEntriesRelatedToAccount', */ +/* 'args' => compact('id', 'rel_ids', 'all', 'cond', 'link'), */ +/* )); */ + if (!isset($cond)) + $cond = array(); + + if (!is_array($rel_ids)) + $rel_ids = array($rel_ids); + + $ledger_ids = array(); + foreach ($rel_ids AS $rel_id) + $ledger_ids = array_merge($ledger_ids, $this->ledgers($rel_id)); + + array_push($cond, $this->Ledger->LedgerEntry->conditionEntryAsCreditOrDebit($ledger_ids)); + $entries = $this->findLedgerEntries($id, $all, $cond, $link); + +/* pr(array('function' => 'Account::findLedgerEntriesRelatedToAccount', */ +/* 'args' => compact('id', 'relid', 'all', 'cond', 'link'), */ +/* 'vars' => compact('ledger_ids'), */ +/* 'return' => compact('entries'), */ +/* )); */ + return $entries; + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findCurrentLedgerEntries + * - Returns an array of ledger entries that belong to the current + * ledger of the given account. There is extra work done... see the + * LedgerEntry model. + */ + function findCurrentLedgerEntries($id, $cond = null, $link = null) { + $this->Behaviors->attach('Containable'); + $account = $this->find('first', array + ('contain' => array('CurrentLedger'), + 'fields' => array('Account.type', 'CurrentLedger.id'), + 'conditions' => array(array('Account.id' => $id)), + )); + $this->Behaviors->detach('Containable'); + + $ledger_id = $account['CurrentLedger']['id']; + $account_type = $account['Account']['type']; + + return $this->Ledger->findLedgerEntries($ledger_id, $account_type, $cond, $link); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findLedgerRelatedEntries + * - Returns an array of ledger entries from this account that are + * related to one of the given ledgers. + */ + function findLedgerRelatedEntries($id, $ledgers, $link = null) { + pr(array_merge(array('function' => 'Account::findLedgerRelatedEntries', + 'checkpoint' => 'begin'), + compact('id', 'ledgers', 'link'))); + $this->Behaviors->attach('Containable'); + $account = $this->find('first', array + ('contain' => array + ('Ledger' => array('fields' => array('Ledger.id')), + ), + 'fields' => array('Account.type'), + 'conditions' => array(array('Account.id' => $id)), + )); + $this->Behaviors->detach('Containable'); + + $cond = array('OR' => + array(array('debit_ledger_id' => $ledgers), + array('credit_ledger_id' => $ledgers))); + + pr(array_merge(array('function' => 'Account::findLedgerRelatedEntries', + 'checkpoint' => 'get-account-ledgers'), + compact('account', 'cond'))); + + $entries = array(); + foreach($account['Ledger'] AS $ledger) { + //pr(array('find', $ledger, $account, $cond, $link)); + $entries = array_merge + ($entries, + $this->Ledger->findLedgerEntries($ledger['id'], + $account['Account']['type'], + $cond, $link)); + } + + foreach($entries AS $entry) + $this->statsMerge($entries['summary'], $entry[0]); + + //$entries['summary'] + + pr(array_merge(array('function' => 'Account::findLedgerRelatedEntries', + 'checkpoint' => 'return'), + compact('entries'))); + return $entries; + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findAccountRelatedEntries + * - Returns an array of ledger entries from this account that are + * related to the given account. + */ + function findAccountRelatedEntries($id, $relid, $link = null) { + pr(array_merge(array('function' => 'Account::findAccountRelatedEntries', + 'checkpoint' => 'begin'), + compact('id', 'relid', 'link'))); + $this->Behaviors->attach('Containable'); + $related = $this->find('first', array + ('contain' => array + ('Ledger' => array('fields' => array('Ledger.id')), + ), + 'fields' => array(), + 'conditions' => array(array('Account.id' => $relid)), + )); + $this->Behaviors->detach('Containable'); + + $ledger_ids = array(); + foreach ($related['Ledger'] AS $ledger) + array_push($ledger_ids, $ledger['id']); + + pr(array_merge(array('function' => 'Account::findAccountRelatedEntries', + 'checkpoint' => 'get-related'), + compact('related', 'ledger_ids'))); + + $entries = $this->findLedgerRelatedEntries($id, $ledger_ids, $link); + pr(array_merge(array('function' => 'Account::findAccountRelatedEntries', + 'checkpoint' => 'return'), + compact('entries'))); + return $entries; + //return $this->findLedgerRelatedEntries($id, $ledger_ids, $link); + } + + +/* /\************************************************************************** */ +/* ************************************************************************** */ +/* ************************************************************************** */ +/* * function: findSecurityDeposits */ +/* * - Returns an array of security deposit entries */ +/* *\/ */ +/* function findSecurityDeposits($id, $link = null) { */ +/* pr(array_merge(array('function' => 'Account::findSecurityDeposits', */ +/* 'checkpoint' => 'begin'), */ +/* compact('id', 'link'))); */ +/* $sd_account = $this->find('first', array */ +/* ('recursive' => -1, */ +/* 'conditions' => array(array('name' => 'Security Deposit')), */ +/* )); */ +/* pr(array_merge(array('function' => 'Account::findSecurityDeposits', */ +/* 'checkpoint' => 'get-security-deposit-account'), */ +/* compact('sd_account'))); */ + +/* $deposits = $this->findAccountRelatedEntries($id, $sd_account['Account']['id'], $link); */ +/* pr(array_merge(array('function' => 'Account::findSecurityDeposits', */ +/* 'checkpoint' => 'return'), */ +/* compact('deposits'))); */ +/* return $deposits; */ +/* //return $this->findAccountRelatedEntries($id, $sd_account['Account']['id'], $link); */ +/* } */ + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findSecurityDeposits + * - Returns an array of security deposit entries + */ + function zzfindSecurityDeposits($id, $cond = array(), $link = null) { + $this->Behaviors->attach('Containable'); + $account = $this->find('first', array + ('contain' => array + ('Ledger' => array('fields' => array('Ledger.id')), + ), + 'fields' => array('Account.type'), + 'conditions' => array(array('Account.id' => $id)), + )); + + $sd_account = $this->find('first', array + ('contain' => array + ('Ledger' => array('fields' => array('Ledger.id')), + ), + 'conditions' => array(array('name' => 'Security Deposit')), + )); + $this->Behaviors->detach('Containable'); + + pr(array('sd_account', $sd_account)); + $sd_ledger_ids = array(); + foreach ($sd_account['Ledger'] AS $ledger) + array_push($sd_ledger_ids, $ledger['id']); + + pr(array('sd_ledger_ids', $sd_ledger_ids)); + array_push($cond, + array('OR' => + array(array('debit_ledger_id' => $sd_ledger_ids), + array('credit_ledger_id' => $sd_ledger_ids)))); + + $sd_entries = array(); + foreach($account['Ledger'] AS $ledger) { + pr(array('find', $ledger, $account, $cond, $link)); + $add = $this->Ledger->findLedgerEntries($ledger['id'], + $account['Account']['type'], + $cond, $link); + $sd_entries = array_merge($sd_entries, $add); + } + + pr(array('sd_entries', $sd_entries)); + + //return $this->Ledger->findLedgerEntries($ledger_id, $account_type, $cond, $link); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: stats + * - Returns summary data from the requested account. + */ + + function stats($id = null, $all = false, $cond = null) { + if (!$id) + return null; + + // All old, closed ledgers MUST balance to 0. + // However, the user may want the ENTIRE running totals. + $this->Behaviors->attach('Containable'); + $account = $this->find('first', + array('contain' => + ($all + ? array('Ledger' => array('fields' => array('id'))) + : array('CurrentLedger' => array('fields' => array('id'))) + ), + 'conditions' => array(array('Account.id' => $id)))); + $this->Behaviors->detach('Containable'); + + if ($all) + $ledgers = $account['Ledger']; + else + $ledgers = array($account['CurrentLedger']); + + foreach ($ledgers AS $ledger) { + $this->statsMerge($stats['Ledger'], $this->Ledger->stats($ledger['id'], $cond)); + } + + return $stats; + } + } ?> \ No newline at end of file diff --git a/site/models/contact.php b/site/models/contact.php index 04052c2..d4e18d5 100644 --- a/site/models/contact.php +++ b/site/models/contact.php @@ -10,21 +10,7 @@ class Contact extends AppModel { ); var $hasAndBelongsToMany = array( - 'Customer' => array( - 'className' => 'Customer', - 'joinTable' => 'contacts_customers', - 'foreignKey' => 'contact_id', - 'associationForeignKey' => 'customer_id', - 'unique' => true, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'finderQuery' => '', - 'deleteQuery' => '', - 'insertQuery' => '' - ), + 'Customer', 'ContactAddress' => array( 'className' => 'ContactAddress', 'joinTable' => 'contacts_methods', @@ -32,13 +18,6 @@ class Contact extends AppModel { 'associationForeignKey' => 'method_id', 'unique' => true, 'conditions' => "method = 'POST'", - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'finderQuery' => '', - 'deleteQuery' => '', - 'insertQuery' => '' ), 'ContactPhone' => array( 'className' => 'ContactPhone', @@ -47,13 +26,6 @@ class Contact extends AppModel { 'associationForeignKey' => 'method_id', 'unique' => true, 'conditions' => "method = 'PHONE'", - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'finderQuery' => '', - 'deleteQuery' => '', - 'insertQuery' => '' ), 'ContactEmail' => array( 'className' => 'ContactEmail', @@ -62,13 +34,6 @@ class Contact extends AppModel { 'associationForeignKey' => 'method_id', 'unique' => true, 'conditions' => "method = 'EMAIL'", - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'finderQuery' => '', - 'deleteQuery' => '', - 'insertQuery' => '' ), ); diff --git a/site/models/contact_address.php b/site/models/contact_address.php index 5503268..d064016 100644 --- a/site/models/contact_address.php +++ b/site/models/contact_address.php @@ -15,13 +15,6 @@ class ContactAddress extends AppModel { 'associationForeignKey' => 'contact_id', 'unique' => true, 'conditions' => "method = 'POST'", - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'finderQuery' => '', - 'deleteQuery' => '', - 'insertQuery' => '' ) ); } diff --git a/site/models/contact_email.php b/site/models/contact_email.php index 474e2b2..f2bbf75 100644 --- a/site/models/contact_email.php +++ b/site/models/contact_email.php @@ -15,13 +15,6 @@ class ContactEmail extends AppModel { 'associationForeignKey' => 'contact_id', 'unique' => true, 'conditions' => "method = 'EMAIL'", - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'finderQuery' => '', - 'deleteQuery' => '', - 'insertQuery' => '' ) ); diff --git a/site/models/contact_phone.php b/site/models/contact_phone.php index 8569c89..f53b61d 100644 --- a/site/models/contact_phone.php +++ b/site/models/contact_phone.php @@ -17,13 +17,6 @@ class ContactPhone extends AppModel { 'associationForeignKey' => 'contact_id', 'unique' => true, 'conditions' => "method = 'PHONE'", - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'finderQuery' => '', - 'deleteQuery' => '', - 'insertQuery' => '' ) ); diff --git a/site/models/customer.php b/site/models/customer.php index 652cef3..80c6cb6 100644 --- a/site/models/customer.php +++ b/site/models/customer.php @@ -7,52 +7,194 @@ class Customer extends AppModel { 'name' => array('notempty'), ); + var $belongsTo = array( + 'Account', + ); + var $hasMany = array( - 'Lease' => array( + 'CurrentLease' => array( 'className' => 'Lease', - 'foreignKey' => 'customer_id', - 'dependent' => false, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'exclusive' => '', - 'finderQuery' => '', - 'counterQuery' => '' + 'conditions' => 'CurrentLease.close_date IS NULL', ), - 'Transaction' => array( - 'className' => 'Transaction', - 'foreignKey' => 'customer_id', - 'dependent' => false, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'exclusive' => '', - 'finderQuery' => '', - 'counterQuery' => '' - ) + 'Lease', + 'Transaction', ); var $hasAndBelongsToMany = array( - 'Contact' => array( - 'className' => 'Contact', - 'joinTable' => 'contacts_customers', - 'foreignKey' => 'customer_id', - 'associationForeignKey' => 'contact_id', - 'unique' => true, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'finderQuery' => '', - 'deleteQuery' => '', - 'insertQuery' => '' - ), + 'Contact', ); + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findAccountEntries + * - Returns an array of ledger entries that belong to the current + * ledger of the account for the given customer. There is extra work + * done... see the LedgerEntry model. + */ +/* function findAccountEntries($id, $date = null, $link = null) { */ +/* $result = $this->find('first', array */ +/* ('recursive' => -1, */ +/* 'fields' => array('account_id'), */ +/* 'conditions' => array(array('id' => $id)), */ +/* )); */ + +/* return $this->Account->findCurrentLedgerEntries($result['account_id'], */ +/* $date, $link); */ +/* } */ + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findSecurityDeposits + * - Returns an array of security deposit entries + */ + function zfindSecurityDeposits($id, $link = null) { + pr(array('function' => 'Customer::findSecurityDeposits', + 'args' => compact('id', 'link'), + )); + + $this->Behaviors->attach('Containable'); + $customer = $this->find('first', + array('contain' => + array('Lease' => array + ('fields' => array('Lease.account_id')), + ), + 'fields' => array('Customer.account_id'), + 'conditions' => array(array('Customer.id' => $id)))); + $this->Behaviors->detach('Containable'); + + $account_ids = array($customer['Customer']['account_id']); + foreach ($customer['Lease'] AS $lease) + array_push($account_ids, $lease['account_id']); + + $acct = new Account(); + $entries = $acct->findLedgerEntriesRelatedToAccount + ($acct->securityDepositAccountID(), + $account_ids, + //$acct->rentAccountID(), + //6, + //array_merge(array(1), $account_ids), + true, null, $link); + + // OK, we cheated by finding the entries of the security deposit account, + // and not by finding the security deposit entries of the customer + // account(s). Therefore, we have to invert the credit/debit business. + $entries['summary']['debits'] = $entries['summary']['credit']; + $entries['summary']['credits'] = $entries['summary']['debit']; + unset($entries['summary']['credit']); + unset($entries['summary']['debit']); + + pr(array('function' => 'Customer::findSecurityDeposits', + 'args' => compact('id', 'link'), + 'vars' => compact('customer', 'account_ids'), + 'return' => compact('entries'), + )); + return $entries; + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findSecurityDeposits + * - Returns an array of security deposit entries + */ + function findSecurityDeposits($id, $link = null) { +/* pr(array_merge(array('function' => 'Customer::findSecurityDeposits', */ +/* 'checkpoint' => 'begin'), */ +/* compact('id', 'link'))); */ + + $this->Behaviors->attach('Containable'); + $customer = $this->find('first', + array('contain' => + array('Lease' => array('fields' => array('id'))), + 'fields' => array('account_id'), + 'conditions' => array(array('Customer.id' => $id)))); + $this->Behaviors->detach('Containable'); + + $entries = $this->Account->findLedgerEntriesRelatedToAccount + ($customer['Customer']['account_id'], + $this->Account->securityDepositAccountID(), + true, null, $link); + + foreach ($customer['Lease'] AS $lease) { + $ledger_entries = $this->Lease->findSecurityDeposits($lease['id'], $link); + //$this->statsMerge($ledger_entries['summary'], $entries['summary']); + //unset($entries['summary']); + $this->statsMerge($entries['summary'], $ledger_entries['summary']); + $entries['Entries'] = array_merge($entries['Entries'], $ledger_entries['Entries']); + } + +/* pr(array('function' => 'Customer::findSecurityDeposits', */ +/* 'args' => compact('id', 'link'), */ +/* 'vars' => compact('customer'), */ +/* 'return' => compact('entries'))); */ + + return $entries; + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: stats + * - Returns summary data from the requested customer. + */ + + function stats($id = null) { + if (!$id) + return null; + + $this->Behaviors->attach('Containable'); + $customer = $this->find('first', + array('contain' => + array('Account' => array('fields' => array('Account.id')), + 'Lease' => array('fields' => array('Lease.id')) + ), +/* array('Account' => array */ +/* ('fields' => array('id'), */ +/* /\* 'CurrentLedger' => array *\/ */ +/* /\* ('fields => *\/ */ +/* /\* 'Lease' => array('fields' => array('id') *\/ */ +/* ), */ +/* ), */ + 'conditions' => array(array('Customer.id' => $id)))); + $this->Behaviors->detach('Containable'); + + $stats['Account'] = $this->Account->stats($customer['Account']['id']); + foreach ($customer['Lease'] AS $lease) { + $this->statsMerge($stats['Lease'], $this->Lease->stats($lease['id'])); + } + +/* foreach($lease['Customer']['Transaction'] AS $transaction) { */ +/* foreach($transaction['LedgerEntry'] AS $entry) { */ +/* if ($entry['DebitLedger']['Account']['name'] === 'A/R') */ +/* $outstanding_balance += $entry['amount']; */ +/* if ($entry['CreditLedger']['Account']['name'] === 'A/R') */ +/* $outstanding_balance -= $entry['amount']; */ + +/* if ($entry['DebitLedger']['Account']['name'] === 'Security Deposit') */ +/* $outstanding_deposit -= $entry['amount']; */ +/* if ($entry['CreditLedger']['Account']['name'] === 'Security Deposit') */ +/* $outstanding_deposit += $entry['amount']; */ +/* } */ +/* } */ +/* } */ +/* if ($entry['DebitLedger']['Account']['name'] === 'Security Deposit') */ +/* $outstanding_deposit -= $entry['amount']; */ +/* if ($entry['CreditLedger']['Account']['name'] === 'Security Deposit') */ +/* $outstanding_deposit += $entry['amount']; */ + + // Merge the stats from both the customer specific account, as + // well as the lease. This will provide current customer standing. + $this->statsMerge($stats, $stats['Account']['Ledger']); + $this->statsMerge($stats, $stats['Lease']['Account']['Ledger']); + + return $stats; + } + } ?> \ No newline at end of file diff --git a/site/models/lease.php b/site/models/lease.php index fd349fe..6ce5cc8 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -23,36 +23,155 @@ class Lease extends AppModel { ); var $belongsTo = array( - 'LeaseType' => array( - 'className' => 'LeaseType', - 'foreignKey' => 'lease_type_id', - 'conditions' => '', - 'fields' => '', - 'order' => '' - ), - 'Unit' => array( - 'className' => 'Unit', - 'foreignKey' => 'unit_id', - 'conditions' => '', - 'fields' => '', - 'order' => '' - ), - 'LateSchedule' => array( - 'className' => 'LateSchedule', - 'foreignKey' => 'late_schedule_id', - 'conditions' => '', - 'fields' => '', - 'order' => '' - ), - 'Customer' => array( - 'className' => 'Customer', - 'foreignKey' => 'customer_id', - 'dependent' => false, - 'conditions' => '', - 'fields' => '', - 'order' => '' - ), + 'LeaseType', + 'Unit', + 'Account', + 'Customer', + 'LateSchedule', ); + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findAccountEntries + * - Returns an array of ledger entries from the account of the given + * lease. + */ + function findAccountEntries($id, $all = false, $cond = null, $link = null) { +/* pr(array('function' => 'Lease::findAccountEntries', */ +/* 'args' => compact('id', 'all', 'cond', 'link'), */ +/* )); */ + + $lease = $this->find('first', array + ('recursive' => -1, + 'fields' => array('account_id'), + 'conditions' => array(array('id' => $id)), + )); + + $entries = $this->Account->findLedgerEntries($lease['Lease']['account_id'], + $all, $cond, $link); +/* pr(array('function' => 'Lease::findAccountEntries', */ +/* 'args' => compact('id', 'all', 'cond', 'link'), */ +/* 'vars' => compact('lease'), */ +/* 'return' => compact('entries'), */ +/* )); */ + return $entries; + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findSecurityDeposits + * - Returns an array of security deposit entries + */ + function findSecurityDeposits($id, $link = null) { +/* pr(array('function' => 'Lease::findSecurityDeposits', */ +/* 'args' => compact('id', 'link'), */ +/* )); */ + + $lease = $this->find('first', array + ('recursive' => -1, + 'fields' => array('account_id'), + 'conditions' => array(array('id' => $id)), + )); + +/* $sd_account_id = $this->Account->securityDepositAccountID(); */ +/* $sd_ledger_ids = $this->Account->ledgers($sd_account_id); */ +/* $cond = conditionEntryAsCreditOrDebit($sd_ledger_ids); */ + + $entries = $this->Account->findLedgerEntriesRelatedToAccount + ($lease['Lease']['account_id'], + $this->Account->securityDepositAccountID(), + true, null, $link); + +/* pr(array('function' => 'Lease::findSecurityDeposits', */ +/* 'args' => compact('id', 'link'), */ +/* 'vars' => compact('lease'), */ +/* 'return' => compact('entries'), */ +/* )); */ + return $entries; + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findSecurityDeposits + * - Returns an array of security deposit entries + */ + function findAccountDeposits($id, $link = null) { + pr(array_merge(array('function' => 'Lease::findSecurityDeposits', + 'checkpoint' => 'begin'), + compact('id', 'link'))); + $lease = $this->find('first', array + ('recursive' => -1, + 'fields' => array('account_id'), + 'conditions' => array(array('id' => $id)), + )); + pr(array_merge(array('function' => 'Lease::findSecurityDeposits', + 'checkpoint' => 'get-lease'), + compact('lease'))); + + $deposits = $this->Account->findSecurityDeposits($lease['Lease']['account_id'], $link); + pr(array_merge(array('function' => 'Lease::findSecurityDeposits', + 'checkpoint' => 'return'), + compact('deposits'))); + return $deposits; + //return $this->Account->findSecurityDeposits($lease['Lease']['account_id'], $link); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findSecurityDeposits + * - Returns an array of security deposit entries + */ + function qqfindSecurityDeposits($id, $link = null) { + pr(array_merge(array('function' => 'Lease::findSecurityDeposits', + 'checkpoint' => 'begin'), + compact('id', 'link'))); + $lease = $this->find('first', array + ('recursive' => -1, + 'fields' => array('account_id'), + 'conditions' => array(array('id' => $id)), + )); + pr(array_merge(array('function' => 'Lease::findSecurityDeposits', + 'checkpoint' => 'get-lease'), + compact('lease'))); + + return $this->Account->findAccountRelatedEntries($id, $relaccount, $link); + $deposits = $this->Account->findSecurityDeposits($lease['Lease']['account_id'], $link); + pr(array_merge(array('function' => 'Lease::findSecurityDeposits', + 'checkpoint' => 'return'), + compact('deposits'))); + return $deposits; + //return $this->Account->findSecurityDeposits($lease['Lease']['account_id'], $link); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: stats + * - Returns summary data from the requested lease. + */ + + function stats($id = null) { + if (!$id) + return null; + + // Find the associated account. + $lease = $this->find('first', + array('recursive' => -1, + 'conditions' => array(array('Lease.id' => $id)))); + + // Pull the stats from the account. + $stats['Account'] = $this->Account->stats($lease['Lease']['account_id']); + return $stats; + } + } ?> \ No newline at end of file diff --git a/site/models/lease_type.php b/site/models/lease_type.php index f4a5208..e606b80 100644 --- a/site/models/lease_type.php +++ b/site/models/lease_type.php @@ -7,21 +7,8 @@ class LeaseType extends AppModel { 'name' => array('notempty') ); - //The Associations below have been created with all possible keys, those that are not needed can be removed var $hasMany = array( - 'Lease' => array( - 'className' => 'Lease', - 'foreignKey' => 'lease_type_id', - 'dependent' => false, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'exclusive' => '', - 'finderQuery' => '', - 'counterQuery' => '' - ) + 'Lease', ); } diff --git a/site/models/ledger.php b/site/models/ledger.php index 6808a1f..02c509b 100644 --- a/site/models/ledger.php +++ b/site/models/ledger.php @@ -1,65 +1,156 @@ array('numeric'), - 'name' => array('notempty'), - ); + var $name = 'Ledger'; + var $validate = array( + 'id' => array('numeric'), + 'name' => array('notempty'), + ); - var $belongsTo = array( - 'Account' => array( - 'className' => 'Account', - 'foreignKey' => 'account_id', - 'conditions' => '', - 'fields' => '', - 'order' => '' - ), - ); + var $belongsTo = array( + 'Account', + ); - var $hasMany = array( -/* 'LedgerEntry' => array( */ -/* 'className' => 'LedgerEntry', */ -/* 'foreignKey' => false, */ -/* 'dependent' => false, */ -/* 'conditions' => '', */ -/* 'fields' => '', */ -/* 'order' => '', */ -/* 'limit' => '', */ -/* 'offset' => '', */ -/* 'exclusive' => '', */ -/* 'finderQuery' => 'SELECT `Entry`.* FROM pmgr_entries AS `Entry` */ -/* WHERE Entry.debit_ledger_id = ({$__cakeID__$}) */ -/* OR Entry.credit_ledger_id = ({$__cakeID__$})', */ -/* 'counterQuery' => '' */ -/* ), */ - 'DebitLedgerEntry' => array( - 'className' => 'LedgerEntry', - 'foreignKey' => 'debit_ledger_id', - 'dependent' => false, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'exclusive' => '', - 'finderQuery' => '', - 'counterQuery' => '' - ), - 'CreditLedgerEntry' => array( - 'className' => 'LedgerEntry', - 'foreignKey' => 'credit_ledger_id', - 'dependent' => false, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'exclusive' => '', - 'finderQuery' => '', - 'counterQuery' => '' - ), - ); + var $hasMany = array( + 'LedgerEntry' => array( + 'className' => 'LedgerEntry', + 'foreignKey' => false, + // conditions will be used when JOINing tables + // (such as find with LinkableBehavior) + 'conditions' => array('OR' => + array('LedgerEntry.debit_ledger_id = Ledger.id', + 'LedgerEntry.credit_ledger_id = Ledger.id')), + // finderQuery will be used when tables are put + // together across several querys, not with JOIN. + // (such as find with ContainableBehavior) + 'finderQuery' => 'SELECT `LedgerEntry`.* + FROM pmgr_ledger_entries AS `LedgerEntry` + WHERE LedgerEntry.debit_ledger_id = ({$__cakeID__$}) + OR LedgerEntry.credit_ledger_id = ({$__cakeID__$})', + 'counterQuery' => '' + ), + 'DebitLedgerEntry' => array( + 'className' => 'LedgerEntry', + 'foreignKey' => 'debit_ledger_id', + 'dependent' => false, + ), + 'CreditLedgerEntry' => array( + 'className' => 'LedgerEntry', + 'foreignKey' => 'credit_ledger_id', + 'dependent' => false, + ), + ); + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findLedgerEntries + * - Returns an array of ledger entries that belong to a given + * ledger. There is extra work done... see the LedgerEntry model. + */ + function findLedgerEntries($id, $account_type = null, $cond = null, $link = null) { +/* pr(array('function' => 'Ledger::findLedgerEntries', */ +/* 'args' => compact('id', 'account_type', 'cond', 'link'), */ +/* )); */ + + if (!isset($account_type)) { + $this->Behaviors->attach('Containable'); + $ledger = $this->find('first', array + ('contain' => array + ('Account' => array + ('fields' => array('type'), + ), + ), + 'fields' => array(), + 'conditions' => array(array('Ledger.id' => $id)), + )); + $this->Behaviors->detach('Containable'); + $account_type = $ledger['Account']['type']; + } + + // If the requested entries are limited by date, we must calculate + // a balance forward, or the resulting balance will be thrown off. + + // REVISIT : This obviously is more general than date. + // As such, it will not work (or, only work if the + // condition only manages to exclude the first parts + // of the ledger, nothing in the middle or at the + // end. For now, I'll just create an 'other' entry, + // not necessarily a balance forward. + + $bf = array(); + if (0 && isset($cond)) { + //$date = ''; + $stats = $this->stats($id, array('NOT' => array($cond))); + $bf = array(array(array('debit' => $stats['debits'], + 'credit' => $stats['credits'], + 'balance' => $stats['balance']), + + 'LedgerEntry' => array('id' => null, + //'comment' => "Balance Forward from $date"), + 'comment' => "-- SUMMARY OF EXCLUDED ENTRIES --"), + + 'Transaction' => array('id' => null, + //'stamp' => $date, + 'stamp' => null, + 'comment' => null), + )); + } + + $entries = $this->LedgerEntry->findInLedgerContext($id, $account_type, $cond, $link); +/* pr(array('function' => 'Ledger::findLedgerEntries', */ +/* 'args' => compact('id', 'account_type', 'cond', 'link'), */ +/* 'vars' => compact('ledger'), */ +/* 'return' => compact('entries'), */ +/* )); */ + return $entries; + + // Return entries from the ledger, along with our balance forward. +/* return array_merge($bf, */ +/* $this->LedgerEntry->findInLedgerContext($id, $account_type, $cond, $link)); */ + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: stats + * - Returns summary data from the requested ledger. + */ + function stats($id, $cond = null) { + + $stats = $this->find + ('first', array + ('link' => + array(// Models + 'Account' => array('fields' => array()), + //'LedgerEntry' => array('fields' => array()), + 'LedgerEntry' => + array('fields' => array(), + 'Transaction' => array('fields' => array('stamp')), + ), + ), + 'fields' => + array("SUM(IF(LedgerEntry.debit_ledger_id = Ledger.id, + LedgerEntry.amount, NULL)) AS debits", + "SUM(IF(LedgerEntry.credit_ledger_id = Ledger.id, + LedgerEntry.amount, NULL)) AS credits", + "SUM(IF(Account.type IN ('ASSET', 'EXPENSE'), + IF(LedgerEntry.debit_ledger_id = Ledger.id, 1, -1), + IF(LedgerEntry.credit_ledger_id = Ledger.id, 1, -1) + ) * IF(LedgerEntry.amount, LedgerEntry.amount, 0) + ) AS balance", + "COUNT(LedgerEntry.id) AS entries"), + 'conditions' => array(isset($cond) ? $cond : array(), + array('Ledger.id' => $id)), + 'group' => 'Ledger.id', + )); + + // The fields are all tucked into the [0] index, + // and the rest of the array is useless (empty). + return $stats[0]; + } } ?> \ No newline at end of file diff --git a/site/models/ledger_entry.php b/site/models/ledger_entry.php index 4d84e6c..254e411 100644 --- a/site/models/ledger_entry.php +++ b/site/models/ledger_entry.php @@ -9,35 +9,89 @@ class LedgerEntry extends AppModel { ); var $belongsTo = array( - 'MonetarySource' => array( - 'className' => 'MonetarySource', - 'foreignKey' => 'monetary_source_id', - 'conditions' => '', - 'fields' => '', - 'order' => '' - ), - 'Transaction' => array( - 'className' => 'Transaction', - 'foreignKey' => 'transaction_id', - 'conditions' => '', - 'fields' => '', - 'order' => '' - ), + 'MonetarySource', + 'Transaction', + 'DebitLedger' => array( 'className' => 'Ledger', 'foreignKey' => 'debit_ledger_id', - 'conditions' => '', - 'fields' => '', - 'order' => '' ), 'CreditLedger' => array( 'className' => 'Ledger', 'foreignKey' => 'credit_ledger_id', - 'conditions' => '', - 'fields' => '', - 'order' => '' ), ); + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: + * - + */ + function conditionEntryAsCreditOrDebit($ledger_ids) { + return array('OR' => + array(array('debit_ledger_id' => $ledger_ids), + array('credit_ledger_id' => $ledger_ids))); + } + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findInLedgerContext + * - Returns an array of ledger entries that belong to a given ledger. + * There is extra logic to also figure out whether the ledger_entry + * amount is either a credit, or a debit, depending on how it was + * written into the ledger, as well as whether the amount increases or + * decreases the balance depending on the particular account type of + * the ledger. + */ + function findInLedgerContext($ledger_id, $account_type, $cond = null, $link = null) { + if (!isset($link)) + $link = array('Transaction'); + + if (in_array($account_type, array('ASSET', 'EXPENSE'))) + $ledger_type = 'debit'; + else + $ledger_type = 'credit'; + + $entries = $this->find + ('all', + array('link' => $link, + + 'fields' => + array('id', 'name', 'comment', + "IF(LedgerEntry.debit_ledger_id = $ledger_id," . + " LedgerEntry.amount, NULL) AS debit", + "IF(LedgerEntry.credit_ledger_id = $ledger_id," . + " LedgerEntry.amount, NULL) AS credit", + "(IF(LedgerEntry.{$ledger_type}_ledger_id = $ledger_id, 1, -1)" . + " * LedgerEntry.amount) AS balance"), + + 'conditions' => + array(isset($cond) ? $cond : array(), + 'OR' => + array(array('LedgerEntry.debit_ledger_id' => $ledger_id), + array('LedgerEntry.credit_ledger_id' => $ledger_id))), + + 'order' => + array('Transaction.stamp'), + )); + +/* $entries['summary'] = array('balance' => null, 'debit' => null, 'credit' => null); */ +/* foreach($entries AS $entry) */ +/* $this->statsMerge($entries['summary'], $entry[0]); */ + +/* //if (isset($entries['summary']['debit']) || isset($entries['summary']['credit'])) { */ +/* $entries['summary']['debits'] = $entries['summary']['debit']; */ +/* $entries['summary']['credits'] = $entries['summary']['credit']; */ +/* unset($entries['summary']['debit']); */ +/* unset($entries['summary']['credit']); */ +/* //} */ + + + return $entries; + } } + ?> \ No newline at end of file diff --git a/site/models/map.php b/site/models/map.php index c9c2c2e..2e14359 100644 --- a/site/models/map.php +++ b/site/models/map.php @@ -11,33 +11,12 @@ class Map extends AppModel { 'depth' => array('numeric') ); - //The Associations below have been created with all possible keys, those that are not needed can be removed var $belongsTo = array( - 'SiteArea' => array( - 'className' => 'SiteArea', - 'foreignKey' => 'site_area_id', - 'conditions' => '', - 'fields' => '', - 'order' => '' - ) + 'SiteArea', ); var $hasAndBelongsToMany = array( - 'Unit' => array( - 'className' => 'Unit', - 'joinTable' => 'maps_units', - 'foreignKey' => 'map_id', - 'associationForeignKey' => 'unit_id', - 'unique' => true, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'finderQuery' => '', - 'deleteQuery' => '', - 'insertQuery' => '' - ) + 'Unit', ); } diff --git a/site/models/monetary_source.php b/site/models/monetary_source.php index a2d5bcc..df530bf 100644 --- a/site/models/monetary_source.php +++ b/site/models/monetary_source.php @@ -9,19 +9,7 @@ class MonetarySource extends AppModel { ); var $belongsTo = array( - 'MonetaryType' => array( - 'className' => 'MonetaryType', - 'foreignKey' => 'monetary_type_id', - 'dependent' => false, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'exclusive' => '', - 'finderQuery' => '', - 'counterQuery' => '' - ) + 'MonetaryType', ); } diff --git a/site/models/monetary_type.php b/site/models/monetary_type.php index d79d4fc..22241a4 100644 --- a/site/models/monetary_type.php +++ b/site/models/monetary_type.php @@ -9,19 +9,7 @@ class MonetaryType extends AppModel { ); var $hasMany = array( - 'MonetarySource' => array( - 'className' => 'MonetarySource', - 'foreignKey' => 'monetary_type_id', - 'dependent' => false, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'exclusive' => '', - 'finderQuery' => '', - 'counterQuery' => '' - ) + 'MonetarySource', ); } diff --git a/site/models/site.php b/site/models/site.php index d2882df..4825faa 100644 --- a/site/models/site.php +++ b/site/models/site.php @@ -7,34 +7,9 @@ class Site extends AppModel { 'name' => array('notempty') ); - //The Associations below have been created with all possible keys, those that are not needed can be removed var $hasMany = array( - 'SiteArea' => array( - 'className' => 'SiteArea', - 'foreignKey' => 'site_id', - 'dependent' => false, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'exclusive' => '', - 'finderQuery' => '', - 'counterQuery' => '' - ), - 'SiteOption' => array( - 'className' => 'SiteOption', - 'foreignKey' => 'site_id', - 'dependent' => false, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'exclusive' => '', - 'finderQuery' => '', - 'counterQuery' => '' - ) + 'SiteArea', + 'SiteOption', ); } diff --git a/site/models/site_area.php b/site/models/site_area.php index 1aec59f..2303946 100644 --- a/site/models/site_area.php +++ b/site/models/site_area.php @@ -8,26 +8,12 @@ class SiteArea extends AppModel { 'name' => array('notempty') ); - //The Associations below have been created with all possible keys, those that are not needed can be removed var $belongsTo = array( - 'Site' => array( - 'className' => 'Site', - 'foreignKey' => 'site_id', - 'conditions' => '', - 'fields' => '', - 'order' => '' - ) + 'Site', ); var $hasOne = array( - 'Map' => array( - 'className' => 'Map', - 'foreignKey' => 'site_area_id', - 'dependent' => false, - 'conditions' => '', - 'fields' => '', - 'order' => '' - ) + 'Map', ); } diff --git a/site/models/transaction.php b/site/models/transaction.php index d52f06e..08ddf6d 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -8,29 +8,11 @@ class Transaction extends AppModel { ); var $belongsTo = array( - 'Customer' => array( - 'className' => 'Customer', - 'foreignKey' => 'customer_id', - 'conditions' => '', - 'fields' => '', - 'order' => '' - ), + 'Customer', ); var $hasMany = array( - 'LedgerEntry' => array( - 'className' => 'LedgerEntry', - 'foreignKey' => 'transaction_id', - 'dependent' => false, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'exclusive' => '', - 'finderQuery' => '', - 'counterQuery' => '' - ) + 'LedgerEntry', ); } diff --git a/site/models/unit.php b/site/models/unit.php index d03ddaa..17d9197 100644 --- a/site/models/unit.php +++ b/site/models/unit.php @@ -13,27 +13,15 @@ class Unit extends AppModel { ); var $belongsTo = array( - 'UnitSize' => array( - 'className' => 'UnitSize', - 'foreignKey' => 'unit_size_id', - 'conditions' => '', - 'fields' => '', - 'order' => '' - ), + 'UnitSize', + ); + + var $hasOne = array( 'CurrentLease' => array( 'className' => 'Lease', - 'foreignKey' => 'current_lease_id', - 'conditions' => '', - 'fields' => '', - 'order' => '' + //'foreignKey' => 'unit_id', + 'conditions' => 'CurrentLease.close_date IS NULL', ), -/* 'Map' => array( */ -/* 'className' => 'MapsUnit', */ -/* 'foreignKey' => 'unit_id', */ -/* 'conditions' => '', */ -/* 'fields' => '', */ -/* 'order' => '' */ -/* ) */ ); var $hasMany = array( @@ -41,14 +29,6 @@ class Unit extends AppModel { 'className' => 'Lease', 'foreignKey' => 'unit_id', 'dependent' => false, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'exclusive' => '', - 'finderQuery' => '', - 'counterQuery' => '' ) ); @@ -83,4 +63,32 @@ class Unit extends AppModel { return ('Unit.status <= ' . $this->statusValue('UNAVAILABLE')); } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: stats + * - Returns summary data from the requested customer. + */ + + function stats($id = null) { + if (!$id) + return null; + + $this->Behaviors->attach('Containable'); + $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)))); + $this->Behaviors->detach('Containable'); + + $stats['CurrentLease'] = $this->Lease->stats($unit['CurrentLease']['id']); + + foreach ($unit['Lease'] AS $lease) { + $this->statsMerge($stats['Lease'], $this->Lease->stats($lease['id'])); + } + + return $stats; + } + } diff --git a/site/models/unit_size.php b/site/models/unit_size.php index 29d1a2f..ca06b60 100644 --- a/site/models/unit_size.php +++ b/site/models/unit_size.php @@ -14,29 +14,11 @@ class UnitSize extends AppModel { ); var $belongsTo = array( - 'UnitType' => array( - 'className' => 'UnitType', - 'foreignKey' => 'unit_type_id', - 'conditions' => '', - 'fields' => '', - 'order' => '' - ) + 'UnitType', ); var $hasMany = array( - 'Unit' => array( - 'className' => 'Unit', - 'foreignKey' => 'unit_size_id', - 'dependent' => false, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'exclusive' => '', - 'finderQuery' => '', - 'counterQuery' => '' - ) + 'Unit', ); } diff --git a/site/models/unit_type.php b/site/models/unit_type.php index 8488ca0..d2bd90d 100644 --- a/site/models/unit_type.php +++ b/site/models/unit_type.php @@ -9,19 +9,7 @@ class UnitType extends AppModel { ); var $hasMany = array( - 'UnitSize' => array( - 'className' => 'UnitSize', - 'foreignKey' => 'unit_type_id', - 'dependent' => false, - 'conditions' => '', - 'fields' => '', - 'order' => '', - 'limit' => '', - 'offset' => '', - 'exclusive' => '', - 'finderQuery' => '', - 'counterQuery' => '' - ) + 'UnitSize', ); } diff --git a/site/views/accounts/view.ctp b/site/views/accounts/view.ctp index 2a56256..d25c71d 100644 --- a/site/views/accounts/view.ctp +++ b/site/views/accounts/view.ctp @@ -51,13 +51,22 @@ echo $this->element('table', /********************************************************************** - * Ledger + * Ledgers */ echo $this->element('ledgers', array('caption' => $account['Account']['name'] . " Ledgers", 'ledgers' => $account['Ledger'])); + +/********************************************************************** + * Current Ledger + */ + +echo $this->element('ledger_entries', + array('caption' => "Current Ledger: (#{$account['CurrentLedger']['sequence']})", + 'ledger_entries' => $account['CurrentLedger']['LedgerEntry'])); + /* End "detail supporting" DIV */ ?>
diff --git a/site/views/contacts/view.ctp b/site/views/contacts/view.ctp index ceb91c9..b63f769 100644 --- a/site/views/contacts/view.ctp +++ b/site/views/contacts/view.ctp @@ -12,7 +12,9 @@ * Contact Detail Main Section */ -$rows = array(array('Name', $contact['Contact']['display_name']), +$rows = array(array('First Name', $contact['Contact']['first_name']), + array('Middle Name', $contact['Contact']['middle_name']), + array('Last Name', $contact['Contact']['last_name']), array('Company', $contact['Contact']['company_name']), array('SSN', $contact['Contact']['id_federal']), array('ID', ($contact['Contact']['id_local'] diff --git a/site/views/elements/accounts.ctp b/site/views/elements/accounts.ctp index 1d312f0..d7db42a 100644 --- a/site/views/elements/accounts.ctp +++ b/site/views/elements/accounts.ctp @@ -31,17 +31,16 @@ if (isset($paginator)) { $rows = array(); foreach ($accounts as $account) { - $extra = null; - if (isset($account[0])) { - $extra = $account[0]; - unset($account[0]); - } + //pr($account); + if (isset($account[0])) + $stats = $account[0]; + else + $stats = $account; + + // Move our pointer to the meat if (isset($account['Account'])) $account = $account['Account']; - if (isset($extra)) - $account = array_merge($account, $extra); - $rows[] = array($html->link($account['name'], array('controller' => 'accounts', 'action' => 'view', @@ -49,10 +48,10 @@ foreach ($accounts as $account) { $account['type'], $account['external_name'], $account['external_account'], - $account['entries'], - FormatHelper::currency($account['debits']), - FormatHelper::currency($account['credits']), - FormatHelper::currency($account['balance']), + $stats['entries'], + FormatHelper::currency($stats['debits']), + FormatHelper::currency($stats['credits']), + FormatHelper::currency($stats['balance']), $account['comment'], ); } diff --git a/site/views/elements/contacts.ctp b/site/views/elements/contacts.ctp index cdb4c5f..9df365a 100644 --- a/site/views/elements/contacts.ctp +++ b/site/views/elements/contacts.ctp @@ -51,7 +51,7 @@ foreach ($contacts as $contact) { $contact['company_name']), (isset($contact['ContactsCustomer']) ? array($contact['ContactsCustomer']['type'], - $contact['ContactsCustomer']['active'], + $contact['ContactsCustomer']['active'] ? 'Yes' : 'No', $contact['ContactsCustomer']['comment']) : array($contact['comment']))); } diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index 471e203..74d0fbb 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -5,11 +5,12 @@ if (isset($heading)) elseif (!isset($caption)) echo '

'.__('Customers',true).'

'; -$headers = array('ID', 'Name', 'Comment'); +$headers = array_merge(array('Name'), + isset($customers[0]['ContactsCustomer']) + ? array('Relationship') + : array(), + array('Comment')); $column_class = array(); -foreach (array_intersect($headers, array('ID')) AS $k => $v) { - $column_class[$k] = 'id'; -} foreach (array_intersect($headers, array('Comment')) AS $k => $v) { $column_class[$k] = 'comment'; } @@ -18,25 +19,30 @@ if (isset($paginator)) { echo $paginator->counter(array( 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); - $headers = array($paginator->sort('id'), - $paginator->sort('name'), - $paginator->sort('comment')); + $headers = array_merge(array($paginator->sort('name')), + isset($customers[0]['ContactsCustomer']) + ? array($paginator->sort('Relationship', 'type')) + : array(), + array($paginator->sort('comment'))); } $rows = array(); foreach ($customers as $customer) { + $contacts_customer = null; + if (isset($customer['ContactsCustomer'])) + $contacts_customer = $customer['ContactsCustomer']; + if (isset($customer['Customer'])) $customer = $customer['Customer']; - $rows[] = array($html->link($customer['id'], - array('controller' => 'customers', - 'action' => 'view', - $customer['id'])), - $html->link($customer['name'], - array('controller' => 'customers', - 'action' => 'view', - $customer['id'])), - $customer['comment']); + $rows[] = array_merge(array($html->link($customer['name'], + array('controller' => 'customers', + 'action' => 'view', + $customer['id']))), + isset($contacts_customer) + ? array($contacts_customer['type']) + : array(), + array($customer['comment'])); } echo $this->element('table', diff --git a/site/views/elements/leases.ctp b/site/views/elements/leases.ctp new file mode 100644 index 0000000..bb4e56a --- /dev/null +++ b/site/views/elements/leases.ctp @@ -0,0 +1,82 @@ +'.__('Leases',true).''; + +$headers = array_merge(array('Lease'), + isset($leases[0]['Unit']) + ? array('Unit') + : array('Customer'), + array('Signed', 'Move-In', 'Move-Out', 'Balance', 'Comment')); +$column_class = array(); +foreach (array_intersect($headers, array('Lease', 'Unit')) AS $k => $v) { + $column_class[$k] = 'id'; +} +foreach (array_intersect($headers, array('Balance')) AS $k => $v) { + $column_class[$k] = 'currency'; +} + +if (isset($paginator)) { + echo $paginator->counter(array('format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); + + $headers = array_merge(array($paginator->sort('Lease')), + isset($leases[0]['Unit']) + ? $paginator->sort('Unit', 'Unit.id') + : $paginator->sort('Customer.id'), + array($paginator->sort('Signed', 'lease_date'), + $paginator->sort('Move-In', 'movein_date'), + $paginator->sort('Move-Out', 'moveout_date'), + $paginator->sort('balance'), + $paginator->sort('comment'))); +} + +$rows = array(); +foreach($leases AS $lease) { + $unit = $customer = null; + + if (isset($lease['Unit'])) + $unit = $lease['Unit']; + else + $customer = $lease['Customer']; + + if (isset($lease['Lease'])) + $lease = $lease['Lease']; + + $rows[] = array_merge(array($html->link('#'.$lease['number'], + array('controller' => 'leases', + 'action' => 'view', + $lease['id']))), + isset($unit) + ? array($html->link($unit['name'], + array('controller' => 'units', + 'action' => 'view', + $unit['id']))) + : array($html->link($customer['name'], + array('controller' => 'customers', + 'action' => 'view', + $customer['id']))), + array(FormatHelper::date($lease['lease_date']), + FormatHelper::date($lease['movein_date']), + FormatHelper::date($lease['moveout_date']), + FormatHelper::currency($lease['balance']), + $lease['comment'])); +} + +echo $this->element('table', + array('class' => 'item lease list', + 'caption' => isset($caption) ? $caption : null, + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $column_class)); + +if (isset($paginator)) { + echo('
' . "\n"); + echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); + echo(' | '); + echo $paginator->numbers(); + echo(' | '); + echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); + echo('
' . "\n"); +} diff --git a/site/views/elements/ledger.ctp b/site/views/elements/ledger.ctp deleted file mode 100644 index 4128277..0000000 --- a/site/views/elements/ledger.ctp +++ /dev/null @@ -1,66 +0,0 @@ -'.__('Ledger',true).''; - -$headers = array('Transaction', 'Entry', 'Date', 'Customer', 'Comment', 'Debit', 'Credit', 'Total'); -$column_class = array(); -foreach (array_intersect($headers, array('Transaction', 'Entry')) AS $k => $v) { - $column_class[$k] = array($column_class[$k], 'id'); -} -foreach (array_intersect($headers, array('Debit', 'Credit', 'Total')) AS $k => $v) { - $column_class[$k] = array($column_class[$k], 'currency'); -} -foreach (array_intersect($headers, array('Comment')) AS $k => $v) { - $column_class[$k] = 'slack'; -} - - -$rows = array(); -$running_total = 0; -foreach($entries AS $entry) { - $transaction = $entry['Transaction']; - $customer = $entry['Customer']; - - $credit = $debit = null; - $running_total += $entry['balance']; - - if (isset($entry['debit'])) - $debit = $entry['debit']; - if (isset($entry['credit'])) - $credit = $entry['credit']; - - // Now that we've extracted top level 'entry' data - // move our variable to the meat of 'LedgerEntry' for clarity - $entry = $entry['LedgerEntry']; - - $rows[] = array($html->link('#'.$transaction['id'], - array('controller' => 'transactions', - 'action' => 'view', - $transaction['id'])), - $html->link('#'.$entry['id'], - array('controller' => 'ledger_entries', - 'action' => 'view', - $entry['id'])), - FormatHelper::date($transaction['stamp']), - $html->link($customer['name'], - array('controller' => 'customers', - 'action' => 'view', - $customer['id'])), - FormatHelper::comment(array($transaction['comment'], $entry['comment'])), - FormatHelper::currency($debit), - FormatHelper::currency($credit), - FormatHelper::currency($running_total) - ); -} - -echo $this->element('table', - array('class' => 'item account ledger list', - 'caption' => isset($caption) ? $caption : null, - 'headers' => $headers, - 'rows' => $rows, - 'column_class' => $column_class)); - -?> diff --git a/site/views/elements/ledger_entries.ctp b/site/views/elements/ledger_entries.ctp new file mode 100644 index 0000000..3edf18a --- /dev/null +++ b/site/views/elements/ledger_entries.ctp @@ -0,0 +1,69 @@ +'.__('Ledger Entries',true).''; + +$headers = array('Transaction', 'Entry', 'Date', 'Comment', 'Debit', 'Credit', 'Total'); +$column_class = array(); +foreach (array_intersect($headers, array('Transaction', 'Entry')) AS $k => $v) { + $column_class[$k] = 'id'; +} +foreach (array_intersect($headers, array('Debit', 'Credit', 'Total')) AS $k => $v) { + $column_class[$k] = 'currency'; +} +foreach (array_intersect($headers, array('Comment')) AS $k => $v) { + $column_class[$k] = 'slack'; +} + + +$rows = array(); +$running_total = 0; +foreach($ledger_entries AS $entry) { + $credit = $debit = null; + $running_total += $entry[0]['balance']; + + if (isset($entry[0]['debit'])) + $debit = $entry[0]['debit']; + if (isset($entry[0]['credit'])) + $credit = $entry[0]['credit']; + + // local references to linked tables + $transaction = $entry['Transaction']; + + // Now that we've extracted top level 'LedgerEntry' data + // move our variable to the meat of 'LedgerEntry' for clarity + if (isset($entry['LedgerEntry'])) + $entry = $entry['LedgerEntry']; + + $rows[] = array(isset($transaction['id']) + ? $html->link('#'.$transaction['id'], + array('controller' => 'transactions', + 'action' => 'view', + $transaction['id'])) + : null, + + isset($entry['id']) + ? $html->link('#'.$entry['id'], + array('controller' => 'ledger_entries', + 'action' => 'view', + $entry['id'])) + : null, + + FormatHelper::date($transaction['stamp']), + FormatHelper::comment(array($transaction['comment'], $entry['comment'])), + FormatHelper::currency($debit), + FormatHelper::currency($credit), + FormatHelper::currency($running_total) + ); +} + +echo $this->element('table', + array('class' => 'item ledger-entries list', + 'caption' => isset($caption) ? $caption : null, + 'headers' => $headers, + 'rows' => $rows, + 'column_class' => $column_class)); + +?> diff --git a/site/views/elements/ledgers.ctp b/site/views/elements/ledgers.ctp index 4155126..8013036 100644 --- a/site/views/elements/ledgers.ctp +++ b/site/views/elements/ledgers.ctp @@ -5,12 +5,15 @@ if (isset($heading)) elseif (!isset($caption)) echo '

'.__('Ledgers',true).'

'; -$headers = array_merge(array('Name'), +$headers = array_merge(array('Sequence'), //array('Name'), (isset($ledgers[0]['Account']) ? array('Account') : array()), - array('Entries', 'Debits', 'Credits', 'Balance', 'Closed', 'Comment')); + array('Entries', 'Debits', 'Credits', 'Balance', 'Close Date', 'Comment')); $column_class = array(); +foreach (array_intersect($headers, array('ID', 'Sequence')) AS $k => $v) { + $column_class[$k] = 'id'; +} foreach (array_intersect($headers, array('Debits', 'Credits', 'Balance')) AS $k => $v) { $column_class[$k] = 'currency'; } @@ -22,7 +25,7 @@ if (isset($paginator)) { echo $paginator->counter(array( 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); - $headers = array_merge(array($paginator->sort('name')), + $headers = array_merge(array($paginator->sort('sequence')), //array($paginator->sort('name')), (isset($ledgers[0]['Account']) ? array($paginator->sort('Account', 'Account.name')) : array()), @@ -30,35 +33,40 @@ if (isset($paginator)) { $paginator->sort('debits'), $paginator->sort('credits'), $paginator->sort('balance'), - $paginator->sort('closed'), + $paginator->sort('Close Date', 'close_stamp'), $paginator->sort('comment'))); } $rows = array(); foreach ($ledgers as $ledger) { + $account = null; + $stats = null; + if (isset($ledger[0])) - $ledger = array_merge($ledger[0], array_diff_key($ledger, array(0=>1))); - if (isset($ledger['Ledger'])) - $ledger = array_merge($ledger['Ledger'], array_diff_key($ledger, array('Ledger'=>1))); + $stats = $ledger[0]; + else + $stats = $ledger; if (isset($ledger['Account'])) $account = $ledger['Account']; + if (isset($ledger['Ledger'])) + $ledger = $ledger['Ledger']; - $rows[] = array_merge(array($html->link($ledger['name'], + $rows[] = array_merge(array($html->link('#'.$ledger['sequence'],//$ledger['name'], array('controller' => 'ledgers', 'action' => 'view', $ledger['id']))), - (isset($ledger['Account']) + (isset($account) ? array($html->link($account['name'], array('controller' => 'accounts', 'action' => 'view', $account['id']))) : array()), - array($ledger['entries'], - FormatHelper::currency($ledger['debits']), - FormatHelper::currency($ledger['credits']), - FormatHelper::currency($ledger['balance']), - $ledger['closed'] ? 'Closed' : 'Open', + array($stats['entries'], + FormatHelper::currency($stats['debits']), + FormatHelper::currency($stats['credits']), + FormatHelper::currency($stats['balance']), + FormatHelper::datetime($ledger['close_stamp']), $ledger['comment'])); } diff --git a/site/views/helpers/format.php b/site/views/helpers/format.php index 4b93bab..948a5a8 100644 --- a/site/views/helpers/format.php +++ b/site/views/helpers/format.php @@ -13,7 +13,8 @@ class FormatHelper extends AppHelper { function currency($amount) { if (!isset($amount)) - return null; + return '-'; + //return null; return (isset($amount) ? self::$number->currency($amount) @@ -34,7 +35,7 @@ class FormatHelper extends AppHelper { } function datetime($datetime) { - if (!$date) return null; + if (!$datetime) return null; return self::$time->nice($datetime); } diff --git a/site/views/ledgers/view.ctp b/site/views/ledgers/view.ctp index 0cddc40..3b46388 100644 --- a/site/views/ledgers/view.ctp +++ b/site/views/ledgers/view.ctp @@ -56,11 +56,9 @@ echo $this->element('table', * Ledger */ -echo $this->element('ledger', +echo $this->element('ledger_entries', array('caption' => $ledger['Ledger']['name'], - 'ledger' => array('id' => $ledger['Ledger']['id'], - 'type' => $ledger['Account']['type']), - 'entries' => $ledger['LedgerEntry'])); + 'ledger_entries' => $ledger['LedgerEntry'])); /* End "detail supporting" DIV */ ?>
diff --git a/site/views/transactions/index.ctp b/site/views/transactions/index.ctp index 16f1c5c..52066c9 100644 --- a/site/views/transactions/index.ctp +++ b/site/views/transactions/index.ctp @@ -1,13 +1,3 @@
- - - element('transactions', array('heading' => '

'.$heading.'

')) ?>
diff --git a/site/views/transactions/view.ctp b/site/views/transactions/view.ctp index 4771455..30c07b5 100644 --- a/site/views/transactions/view.ctp +++ b/site/views/transactions/view.ctp @@ -13,7 +13,7 @@ */ $rows = array(array('ID', $transaction['Transaction']['id']), - array('Timestamp', datefmt($transaction['Transaction']['stamp'])), + array('Timestamp', FormatHelper::datetime($transaction['Transaction']['stamp'])), array('Comment', $transaction['Transaction']['comment'])); echo $this->element('table', diff --git a/site/views/units/view.ctp b/site/views/units/view.ctp index e6b79fe..5bbc852 100644 --- a/site/views/units/view.ctp +++ b/site/views/units/view.ctp @@ -61,14 +61,14 @@ echo $this->element('leases', /********************************************************************** * Ledger History */ -foreach($unit['Lease'] AS $lease) { - pr($lease); - $caption = 'Lease #'.$lease['number'].' (Tenant: '.$lease['Customer']['name'].')'; - echo $this->element('ledger', - array('caption' => $caption, - 'entries' => $lease['Customer']['Transaction'], - 'ledger' => array('mix'=>1))); -} +/* foreach($unit['Lease'] AS $lease) { */ +/* pr($lease); */ +/* $caption = 'Lease #'.$lease['number'].' (Tenant: '.$lease['Customer']['name'].')'; */ +/* echo $this->element('lease', */ +/* array('caption' => $caption, */ +/* 'entries' => $lease['Customer']['Transaction'], */ +/* 'ledger' => array('mix'=>1))); */ +/* } */ /* End "detail supporting" DIV */ ?>
diff --git a/site/webroot/css/layout.css b/site/webroot/css/layout.css index 3f7e015..0a4bd8a 100644 --- a/site/webroot/css/layout.css +++ b/site/webroot/css/layout.css @@ -110,6 +110,12 @@ table.list td.currency { text-align: right; } /* White spacing exceptions */ td.comment { white-space: normal; } +/* Generic column to assign excess space */ +table.list td.slack { width : 99%; } + +/* Customers */ +table.list.customer td.comment { width : 66%; } + /* Contacts */ table.list.contact td.comment { width : 66%; } @@ -124,16 +130,10 @@ table.list.phone td.comment , table.list.email td.comment , table.list.address td.comment { width: auto; } -/* Leases */ -table.list.lease td.comment { width : 99%; } - /* Ledger Entries */ table.list.ledger td { border-top : 1px dashed #ccc; } table.list.ledger td.date.receipt { padding-left: 1em; } table.list.ledger td.evnrow { background: #f4f4f4; } -table.list.ledger td.comment { width : 99%; } - -/* Account Ledger Entries */ /************************************************************ From 55b896a9f055ee7f9218da69b99314c5a28c042d Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 10 Jun 2009 05:14:08 +0000 Subject: [PATCH 081/717] Primarly a cleanup checkin, although a couple minor bugfixes were included as well. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@82 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/accounts_controller.php | 22 +- site/controllers/contacts_controller.php | 3 +- site/controllers/customers_controller.php | 30 +- .../controllers/ledger_entries_controller.php | 6 +- site/controllers/ledgers_controller.php | 25 +- site/controllers/transactions_controller.php | 22 +- site/controllers/units_controller.php | 12 +- site/models/account.php | 267 +++--------------- site/models/customer.php | 125 ++------ site/models/lease.php | 61 ---- site/models/ledger.php | 27 +- site/models/ledger_entry.php | 18 +- site/models/unit.php | 23 +- site/views/elements/ledgers.ctp | 2 +- site/views/transactions/view.ctp | 27 +- 15 files changed, 151 insertions(+), 519 deletions(-) diff --git a/site/controllers/accounts_controller.php b/site/controllers/accounts_controller.php index c1080ad..f317b0c 100644 --- a/site/controllers/accounts_controller.php +++ b/site/controllers/accounts_controller.php @@ -9,8 +9,10 @@ class AccountsController extends AppController { (// Models 'LedgerEntry' => array('fields' => - array('SUM(IF(LedgerEntry.debit_ledger_id = CurrentLedger.id, LedgerEntry.amount, NULL)) AS debits', - 'SUM(IF(LedgerEntry.credit_ledger_id = CurrentLedger.id, LedgerEntry.amount, NULL)) AS credits', + array('SUM(IF(LedgerEntry.debit_ledger_id = CurrentLedger.id, + LedgerEntry.amount, NULL)) AS debits', + 'SUM(IF(LedgerEntry.credit_ledger_id = CurrentLedger.id, + LedgerEntry.amount, NULL)) AS credits', "SUM(IF(Account.type IN ('ASSET', 'EXPENSE'), IF(LedgerEntry.debit_ledger_id = CurrentLedger.id, 1, -1), IF(LedgerEntry.credit_ledger_id = CurrentLedger.id, 1, -1) @@ -184,21 +186,9 @@ class AccountsController extends AppController { ); $this->Account->Behaviors->detach('Containable'); - // Simply debug stuff... testing. - $cond = null; - //$cond = array('Transaction.stamp >' => '2009-05-16'); - // Get all ledger entries of the CURRENT ledger - //$crap = $this->Account->findSecurityDeposits($id); - //$crap = $this->Account->findAccountRelatedEntries($id, 8); - //pr(array('crap', $crap)); -/* $this->autoRender = false; */ -/* return; */ - - // Get all ledger entries of the CURRENT ledger - $account['CurrentLedger']['LedgerEntry'] - = $this->Account->findCurrentLedgerEntries($id, $cond); - //pr(array('Account summary', $account)); + $entries = $this->Account->findLedgerEntries($id); + $account['CurrentLedger']['LedgerEntry'] = $entries['Entries']; // Summarize each ledger foreach($account['Ledger'] AS &$ledger) diff --git a/site/controllers/contacts_controller.php b/site/controllers/contacts_controller.php index 097b927..360429a 100644 --- a/site/controllers/contacts_controller.php +++ b/site/controllers/contacts_controller.php @@ -74,8 +74,9 @@ class ContactsController extends AppController { 'Customer') ); $contact = $this->Contact->read(null, $id); - //pr($contact); + $this->Contact->Behaviors->detach('Containable'); + // Prepare to render. $title = $contact['Contact']['display_name']; $this->set(compact('contact', 'title')); } diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index b4a47d1..f98d1d6 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -128,11 +128,7 @@ class CustomersController extends AppController { ), 'Account', 'Lease' => - array(//'order' => 'movein_date', - //'conditions' => array('Lease.lease_date IS NOT NULL'), - // Models - //'Account', - 'Unit' => + array('Unit' => array('order' => array('sort_order'), 'fields' => array('id', 'name'), ), @@ -142,36 +138,30 @@ class CustomersController extends AppController { $customer = $this->Customer->read(null, $id); $this->Customer->Behaviors->detach('Containable'); + // Add the lease balance to each lease. foreach ($customer['Lease'] AS &$lease) { $stats = $this->Customer->Lease->stats($lease['id']); - //pr($stats); $lease['balance'] = $stats['Account']['Ledger']['balance']; } - //pr($customer); - + // Figure out the outstanding balance of the current lease. $stats = $this->Customer->stats($id); - $deposits = $this->Customer->findSecurityDeposits($id); - $outstanding_balance = $stats['balance']; + + // Figure out the total security deposit for the current lease. + $deposits = $this->Customer->findSecurityDeposits($id); $outstanding_deposit = $deposits['summary']['balance']; -/* pr(array('Customer Stats', $stats)); */ -/* pr(array('Security Deposits', $deposits)); */ + // Add statistics into the customer account. + $customer['Account'] = array_merge($customer['Account'], + $stats['Account']['Ledger']); $this->sidemenu_links[] = array('name' => 'Operations', 'header' => true); $this->sidemenu_links[] = array('name' => 'Move-Out', 'url' => array('controller' => 'units', 'action' => 'move-out')); - - $customer['Account'] = array_merge($customer['Account'], $stats['Account']['Ledger']); - //pr($stats); - //unset($stats['Lease'], $stats['Account']); -/* $customer['Account']['debits'] = 10; */ -/* $customer['Account']['credits'] = 20; */ -/* $customer['Account']['balance'] = 55; */ - + // Prepare to render. $title = $customer['Customer']['name']; $this->set(compact('customer', 'title', 'outstanding_balance', diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index 5a7c11a..a389a56 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -46,10 +46,12 @@ class LedgerEntriesController extends AppController { ) ); $entry = $this->LedgerEntry->read(null, $id); - pr($entry); + $this->LedgerEntry->Behaviors->detach('Containable'); $title = "Entry #{$entry['LedgerEntry']['id']} ({$entry['LedgerEntry']['name']})"; $this->set(compact('entry', 'title')); - //$this->autoRender = false; + + pr($entry); + $this->autoRender = false; } } diff --git a/site/controllers/ledgers_controller.php b/site/controllers/ledgers_controller.php index 644f2b4..965270f 100644 --- a/site/controllers/ledgers_controller.php +++ b/site/controllers/ledgers_controller.php @@ -8,12 +8,16 @@ class LedgersController extends AppController { 'Account', 'LedgerEntry' => array('fields' => - array('SUM(IF(LedgerEntry.debit_ledger_id = Ledger.id, LedgerEntry.amount, 0)) AS debits', - 'SUM(IF(LedgerEntry.credit_ledger_id = Ledger.id, LedgerEntry.amount, 0)) AS credits', - "SUM(IF(Account.type IN ('ASSET', 'EXPENSE'), - IF(LedgerEntry.debit_ledger_id = Ledger.id, 1, -1), - IF(LedgerEntry.credit_ledger_id = Ledger.id, 1, -1)) * LedgerEntry.amount) AS balance", - 'COUNT(LedgerEntry.id) AS entries'), + array('SUM(IF(LedgerEntry.debit_ledger_id = Ledger.id, + LedgerEntry.amount, NULL)) AS debits', + 'SUM(IF(LedgerEntry.credit_ledger_id = Ledger.id, + LedgerEntry.amount, NULL)) AS credits', + "SUM(IF(Account.type IN ('ASSET', 'EXPENSE'), + IF(LedgerEntry.debit_ledger_id = Ledger.id, 1, -1), + IF(LedgerEntry.credit_ledger_id = Ledger.id, 1, -1) + ) * IF(LedgerEntry.amount, LedgerEntry.amount, 0) + ) AS balance", + 'COUNT(LedgerEntry.id) AS entries'), 'conditions' => array('OR' => array('LedgerEntry.debit_ledger_id = Ledger.id', @@ -23,7 +27,7 @@ class LedgersController extends AppController { ), 'group' => 'Ledger.id', - 'order' => array('Ledger.name' => 'ASC')); + 'order' => array('Ledger.account_id', 'Ledger.sequence')); var $sidemenu_links = array(array('name' => 'Ledgers', 'header' => true), @@ -130,13 +134,6 @@ class LedgersController extends AppController { $ledger['LedgerEntry'] = $this->Ledger->findLedgerEntries ($id, $ledger['Account']['type']); -/* $ledger['LedgerEntry'] = $this->Ledger->LedgerEntry->findInLedgerContext */ -/* ($id, -/* $ledger['LedgerEntry'] = $this->Ledger->findLedgerEntries */ -/* ($id); */ - //($id, $ledger['Account']['type']); - - // Summarize the entries, and obtain the ledger balance $ledger['Ledger'] = array_merge($ledger['Ledger'], diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php index a5d0da3..8641019 100644 --- a/site/controllers/transactions_controller.php +++ b/site/controllers/transactions_controller.php @@ -107,23 +107,15 @@ class TransactionsController extends AppController { ) ); $transaction = $this->Transaction->read(null, $id); - pr($transaction); + $this->Transaction->Behaviors->detach('Containable'); - $debit_amount = 0; - $credit_amount = 0; - foreach($transaction['LedgerEntry'] AS $entry) { - $debit_amount += $entry['amount']; - $credit_amount += $entry['amount']; - } - -/* $this->sidemenu_links[] = */ -/* array('name' => 'Operations', 'header' => true); */ -/* $this->sidemenu_links[] = */ -/* array('name' => 'Move-Out', 'url' => array('controller' => 'transactions', 'action' => 'move-out')); */ + // Figure out the transaction total + $total = 0; + foreach($transaction['LedgerEntry'] AS $entry) + $total += $entry['amount']; + // OK, prepare to render. $title = 'Transaction #' . $transaction['Transaction']['id']; - $this->set(compact('transaction', 'title', - 'debit_amount', - 'credit_amount')); + $this->set(compact('transaction', 'title', 'total')); } } diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index 805a3aa..59515db 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -163,18 +163,19 @@ class UnitsController extends AppController { $unit = $this->Unit->read(null, $id); $this->Unit->Behaviors->detach('Containable'); - pr($unit); - + // Get the balance on each lease. foreach ($unit['Lease'] AS &$lease) { $stats = $this->Unit->Lease->stats($lease['id']); $lease['balance'] = $stats['Account']['Ledger']['balance']; } + // Figure out the outstanding balance of the current lease. $stats = $this->Unit->stats($id); - $deposits = $this->Unit->Lease->findSecurityDeposits($unit['CurrentLease']['id']); + $outstanding_balance = + $stats['CurrentLease']['Account']['Ledger']['balance']; - //pr($stats); - $outstanding_balance = $stats['CurrentLease']['Account']['Ledger']['balance']; + // Figure out the total security deposit for the current lease. + $deposits = $this->Unit->Lease->findSecurityDeposits($unit['CurrentLease']['id']); $outstanding_deposit = $deposits['summary']['balance']; $this->sidemenu_links[] = @@ -182,6 +183,7 @@ class UnitsController extends AppController { $this->sidemenu_links[] = array('name' => 'Move-Out', 'url' => array('controller' => 'units', 'action' => 'move-out')); + // Prepare to render. $title = 'Unit ' . $unit['Unit']['name']; $this->set(compact('unit', 'title', 'outstanding_balance', diff --git a/site/models/account.php b/site/models/account.php index 1487c3e..add07bf 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -11,7 +11,6 @@ class Account extends AppModel { var $hasOne = array( 'CurrentLedger' => array( 'className' => 'Ledger', - //'foreignKey' => 'account_id', 'conditions' => array('NOT' => array('CurrentLedger.closed')) ), ); @@ -21,19 +20,6 @@ class Account extends AppModel { ); var $cache; -/* var $instantiated; */ - - -/* /\************************************************************************** */ -/* ************************************************************************** */ -/* ************************************************************************** */ -/* * function: constructor */ -/* *\/ */ -/* function __constructor($id = null) { */ -/* parent::__contstructor(); */ -/* $this->id = $id; */ -/* $this->instantiated = true; */ -/* } */ /************************************************************************** @@ -45,7 +31,8 @@ class Account extends AppModel { function securityDepositAccountID() { $account = $this->find('first', array ('recursive' => -1, - 'conditions' => array(array('name' => 'Security Deposit')), + 'conditions' => array + (array('name' => 'Security Deposit')), )); return $account['Account']['id']; } @@ -60,7 +47,8 @@ class Account extends AppModel { function rentAccountID() { $account = $this->find('first', array ('recursive' => -1, - 'conditions' => array(array('name' => 'Rent')), + 'conditions' => array + (array('name' => 'Rent')), )); return $account['Account']['id']; } @@ -74,10 +62,6 @@ class Account extends AppModel { */ function type($id) { if (isset($this->cache[$id]['type'])) { -/* pr(array('function' => 'Account::type', */ -/* 'args' => compact('id'), */ -/* 'cache_hit' => true, */ -/* 'return' => $this->cache[$id]['type'])); */ return $this->cache[$id]['type']; } @@ -87,7 +71,9 @@ class Account extends AppModel { 'conditions' => array(array('Account.id' => $id)), )); + // Save the account type in our cache for future reference $this->cache[$id]['type'] = $account['Account']['type']; + /* pr(array('function' => 'Account::type', */ /* 'args' => compact('id'), */ /* 'return' => $this->cache[$id]['type'])); */ @@ -105,10 +91,6 @@ class Account extends AppModel { function ledgers($id, $all = false) { $cachekey = $all ? 'all' : 'current'; if (isset($this->cache[$id]['ledgers'][$cachekey])) { -/* pr(array('function' => 'Account::ledgers', */ -/* 'args' => compact('id', 'all'), */ -/* 'cache_hit' => true, */ -/* 'return' => $this->cache[$id]['ledgers'][$cachekey])); */ return $this->cache[$id]['ledgers'][$cachekey]; } @@ -135,6 +117,7 @@ class Account extends AppModel { $ledger_ids = array($account['CurrentLedger']['id']); } + // Save the ledgers in our cache for future reference $this->cache[$id]['ledgers'][$cachekey] = $ledger_ids; /* pr(array('function' => 'Account::ledgers', */ @@ -159,19 +142,22 @@ class Account extends AppModel { $entries = array(); foreach ($this->ledgers($id, $all) AS $ledger_id) { - $ledger_entries = $this->Ledger->findLedgerEntries($ledger_id, $this->type($id), $cond, $link); + $ledger_entries = $this->Ledger->findLedgerEntries + ($ledger_id, $this->type($id), $cond, $link); $entries = array_merge($entries, $ledger_entries); - //$entries = array_merge($entries, array_diff_key($ledger_entries, array('summary'=>1))); - //$this->statsMerge($entries['summary'], $ledger_entries['summary']); } + $stats = $this->stats($id, $all, $cond); + $entries = array('Entries' => $entries, + 'summary' => $stats['Ledger']); + /* pr(array('function' => 'Account::findLedgerEntries', */ /* 'args' => compact('id', 'all', 'cond', 'link'), */ +/* 'vars' => compact('stats'), */ /* 'return' => compact('entries'), */ /* )); */ - $stats = $this->stats($id, $all, $cond); - return array('Entries' => $entries, 'summary' => $stats['Ledger']); + return $entries; } @@ -187,9 +173,9 @@ class Account extends AppModel { /* pr(array('function' => 'Account::findLedgerEntriesRelatedToAccount', */ /* 'args' => compact('id', 'rel_ids', 'all', 'cond', 'link'), */ /* )); */ + if (!isset($cond)) $cond = array(); - if (!is_array($rel_ids)) $rel_ids = array($rel_ids); @@ -209,196 +195,6 @@ class Account extends AppModel { } - /************************************************************************** - ************************************************************************** - ************************************************************************** - * function: findCurrentLedgerEntries - * - Returns an array of ledger entries that belong to the current - * ledger of the given account. There is extra work done... see the - * LedgerEntry model. - */ - function findCurrentLedgerEntries($id, $cond = null, $link = null) { - $this->Behaviors->attach('Containable'); - $account = $this->find('first', array - ('contain' => array('CurrentLedger'), - 'fields' => array('Account.type', 'CurrentLedger.id'), - 'conditions' => array(array('Account.id' => $id)), - )); - $this->Behaviors->detach('Containable'); - - $ledger_id = $account['CurrentLedger']['id']; - $account_type = $account['Account']['type']; - - return $this->Ledger->findLedgerEntries($ledger_id, $account_type, $cond, $link); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * function: findLedgerRelatedEntries - * - Returns an array of ledger entries from this account that are - * related to one of the given ledgers. - */ - function findLedgerRelatedEntries($id, $ledgers, $link = null) { - pr(array_merge(array('function' => 'Account::findLedgerRelatedEntries', - 'checkpoint' => 'begin'), - compact('id', 'ledgers', 'link'))); - $this->Behaviors->attach('Containable'); - $account = $this->find('first', array - ('contain' => array - ('Ledger' => array('fields' => array('Ledger.id')), - ), - 'fields' => array('Account.type'), - 'conditions' => array(array('Account.id' => $id)), - )); - $this->Behaviors->detach('Containable'); - - $cond = array('OR' => - array(array('debit_ledger_id' => $ledgers), - array('credit_ledger_id' => $ledgers))); - - pr(array_merge(array('function' => 'Account::findLedgerRelatedEntries', - 'checkpoint' => 'get-account-ledgers'), - compact('account', 'cond'))); - - $entries = array(); - foreach($account['Ledger'] AS $ledger) { - //pr(array('find', $ledger, $account, $cond, $link)); - $entries = array_merge - ($entries, - $this->Ledger->findLedgerEntries($ledger['id'], - $account['Account']['type'], - $cond, $link)); - } - - foreach($entries AS $entry) - $this->statsMerge($entries['summary'], $entry[0]); - - //$entries['summary'] - - pr(array_merge(array('function' => 'Account::findLedgerRelatedEntries', - 'checkpoint' => 'return'), - compact('entries'))); - return $entries; - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * function: findAccountRelatedEntries - * - Returns an array of ledger entries from this account that are - * related to the given account. - */ - function findAccountRelatedEntries($id, $relid, $link = null) { - pr(array_merge(array('function' => 'Account::findAccountRelatedEntries', - 'checkpoint' => 'begin'), - compact('id', 'relid', 'link'))); - $this->Behaviors->attach('Containable'); - $related = $this->find('first', array - ('contain' => array - ('Ledger' => array('fields' => array('Ledger.id')), - ), - 'fields' => array(), - 'conditions' => array(array('Account.id' => $relid)), - )); - $this->Behaviors->detach('Containable'); - - $ledger_ids = array(); - foreach ($related['Ledger'] AS $ledger) - array_push($ledger_ids, $ledger['id']); - - pr(array_merge(array('function' => 'Account::findAccountRelatedEntries', - 'checkpoint' => 'get-related'), - compact('related', 'ledger_ids'))); - - $entries = $this->findLedgerRelatedEntries($id, $ledger_ids, $link); - pr(array_merge(array('function' => 'Account::findAccountRelatedEntries', - 'checkpoint' => 'return'), - compact('entries'))); - return $entries; - //return $this->findLedgerRelatedEntries($id, $ledger_ids, $link); - } - - -/* /\************************************************************************** */ -/* ************************************************************************** */ -/* ************************************************************************** */ -/* * function: findSecurityDeposits */ -/* * - Returns an array of security deposit entries */ -/* *\/ */ -/* function findSecurityDeposits($id, $link = null) { */ -/* pr(array_merge(array('function' => 'Account::findSecurityDeposits', */ -/* 'checkpoint' => 'begin'), */ -/* compact('id', 'link'))); */ -/* $sd_account = $this->find('first', array */ -/* ('recursive' => -1, */ -/* 'conditions' => array(array('name' => 'Security Deposit')), */ -/* )); */ -/* pr(array_merge(array('function' => 'Account::findSecurityDeposits', */ -/* 'checkpoint' => 'get-security-deposit-account'), */ -/* compact('sd_account'))); */ - -/* $deposits = $this->findAccountRelatedEntries($id, $sd_account['Account']['id'], $link); */ -/* pr(array_merge(array('function' => 'Account::findSecurityDeposits', */ -/* 'checkpoint' => 'return'), */ -/* compact('deposits'))); */ -/* return $deposits; */ -/* //return $this->findAccountRelatedEntries($id, $sd_account['Account']['id'], $link); */ -/* } */ - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * function: findSecurityDeposits - * - Returns an array of security deposit entries - */ - function zzfindSecurityDeposits($id, $cond = array(), $link = null) { - $this->Behaviors->attach('Containable'); - $account = $this->find('first', array - ('contain' => array - ('Ledger' => array('fields' => array('Ledger.id')), - ), - 'fields' => array('Account.type'), - 'conditions' => array(array('Account.id' => $id)), - )); - - $sd_account = $this->find('first', array - ('contain' => array - ('Ledger' => array('fields' => array('Ledger.id')), - ), - 'conditions' => array(array('name' => 'Security Deposit')), - )); - $this->Behaviors->detach('Containable'); - - pr(array('sd_account', $sd_account)); - $sd_ledger_ids = array(); - foreach ($sd_account['Ledger'] AS $ledger) - array_push($sd_ledger_ids, $ledger['id']); - - pr(array('sd_ledger_ids', $sd_ledger_ids)); - array_push($cond, - array('OR' => - array(array('debit_ledger_id' => $sd_ledger_ids), - array('credit_ledger_id' => $sd_ledger_ids)))); - - $sd_entries = array(); - foreach($account['Ledger'] AS $ledger) { - pr(array('find', $ledger, $account, $cond, $link)); - $add = $this->Ledger->findLedgerEntries($ledger['id'], - $account['Account']['type'], - $cond, $link); - $sd_entries = array_merge($sd_entries, $add); - } - - pr(array('sd_entries', $sd_entries)); - - //return $this->Ledger->findLedgerEntries($ledger_id, $account_type, $cond, $link); - } - - /************************************************************************** ************************************************************************** ************************************************************************** @@ -411,24 +207,33 @@ class Account extends AppModel { return null; // All old, closed ledgers MUST balance to 0. - // However, the user may want the ENTIRE running totals. + // However, the user may want the ENTIRE running totals, + // (not just the balance), so we may have to query all + // ledgers, as dictated by the $all parameter. + $this->Behaviors->attach('Containable'); $account = $this->find('first', array('contain' => ($all - ? array('Ledger' => array('fields' => array('id'))) - : array('CurrentLedger' => array('fields' => array('id'))) + ? array('Ledger' => array + ('fields' => array('id'))) + : array('CurrentLedger' => array + ('fields' => array('id'))) ), - 'conditions' => array(array('Account.id' => $id)))); + 'conditions' => array + (array('Account.id' => $id)) + )); $this->Behaviors->detach('Containable'); - if ($all) - $ledgers = $account['Ledger']; - else - $ledgers = array($account['CurrentLedger']); - - foreach ($ledgers AS $ledger) { - $this->statsMerge($stats['Ledger'], $this->Ledger->stats($ledger['id'], $cond)); + $stats = array(); + if ($all) { + foreach ($account['Ledger'] AS $ledger) + $this->statsMerge($stats['Ledger'], + $this->Ledger->stats($ledger['id'], $cond)); + } + else { + $stats['Ledger'] = + $this->Ledger->stats($account['CurrentLedger']['id'], $cond); } return $stats; diff --git a/site/models/customer.php b/site/models/customer.php index 80c6cb6..af777a1 100644 --- a/site/models/customer.php +++ b/site/models/customer.php @@ -25,77 +25,6 @@ class Customer extends AppModel { ); - /************************************************************************** - ************************************************************************** - ************************************************************************** - * function: findAccountEntries - * - Returns an array of ledger entries that belong to the current - * ledger of the account for the given customer. There is extra work - * done... see the LedgerEntry model. - */ -/* function findAccountEntries($id, $date = null, $link = null) { */ -/* $result = $this->find('first', array */ -/* ('recursive' => -1, */ -/* 'fields' => array('account_id'), */ -/* 'conditions' => array(array('id' => $id)), */ -/* )); */ - -/* return $this->Account->findCurrentLedgerEntries($result['account_id'], */ -/* $date, $link); */ -/* } */ - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * function: findSecurityDeposits - * - Returns an array of security deposit entries - */ - function zfindSecurityDeposits($id, $link = null) { - pr(array('function' => 'Customer::findSecurityDeposits', - 'args' => compact('id', 'link'), - )); - - $this->Behaviors->attach('Containable'); - $customer = $this->find('first', - array('contain' => - array('Lease' => array - ('fields' => array('Lease.account_id')), - ), - 'fields' => array('Customer.account_id'), - 'conditions' => array(array('Customer.id' => $id)))); - $this->Behaviors->detach('Containable'); - - $account_ids = array($customer['Customer']['account_id']); - foreach ($customer['Lease'] AS $lease) - array_push($account_ids, $lease['account_id']); - - $acct = new Account(); - $entries = $acct->findLedgerEntriesRelatedToAccount - ($acct->securityDepositAccountID(), - $account_ids, - //$acct->rentAccountID(), - //6, - //array_merge(array(1), $account_ids), - true, null, $link); - - // OK, we cheated by finding the entries of the security deposit account, - // and not by finding the security deposit entries of the customer - // account(s). Therefore, we have to invert the credit/debit business. - $entries['summary']['debits'] = $entries['summary']['credit']; - $entries['summary']['credits'] = $entries['summary']['debit']; - unset($entries['summary']['credit']); - unset($entries['summary']['debit']); - - pr(array('function' => 'Customer::findSecurityDeposits', - 'args' => compact('id', 'link'), - 'vars' => compact('customer', 'account_ids'), - 'return' => compact('entries'), - )); - return $entries; - } - - /************************************************************************** ************************************************************************** ************************************************************************** @@ -103,9 +32,9 @@ class Customer extends AppModel { * - Returns an array of security deposit entries */ function findSecurityDeposits($id, $link = null) { -/* pr(array_merge(array('function' => 'Customer::findSecurityDeposits', */ -/* 'checkpoint' => 'begin'), */ -/* compact('id', 'link'))); */ +/* pr(array('function' => 'Customer::findSecurityDeposits', */ +/* 'args' => compact('id', 'link'), */ +/* )); */ $this->Behaviors->attach('Containable'); $customer = $this->find('first', @@ -122,16 +51,16 @@ class Customer extends AppModel { foreach ($customer['Lease'] AS $lease) { $ledger_entries = $this->Lease->findSecurityDeposits($lease['id'], $link); - //$this->statsMerge($ledger_entries['summary'], $entries['summary']); - //unset($entries['summary']); $this->statsMerge($entries['summary'], $ledger_entries['summary']); - $entries['Entries'] = array_merge($entries['Entries'], $ledger_entries['Entries']); + $entries['Entries'] = array_merge($entries['Entries'], + $ledger_entries['Entries']); } /* pr(array('function' => 'Customer::findSecurityDeposits', */ /* 'args' => compact('id', 'link'), */ /* 'vars' => compact('customer'), */ -/* 'return' => compact('entries'))); */ +/* 'return' => compact('entries'), */ +/* )); */ return $entries; } @@ -148,48 +77,28 @@ class Customer extends AppModel { if (!$id) return null; + // Get the basic information necessary $this->Behaviors->attach('Containable'); $customer = $this->find('first', array('contain' => - array('Account' => array('fields' => array('Account.id')), - 'Lease' => array('fields' => array('Lease.id')) + array('Account' => array + ('fields' => array('Account.id')), + + 'Lease' => array + ('fields' => array('Lease.id')) ), -/* array('Account' => array */ -/* ('fields' => array('id'), */ -/* /\* 'CurrentLedger' => array *\/ */ -/* /\* ('fields => *\/ */ -/* /\* 'Lease' => array('fields' => array('id') *\/ */ -/* ), */ -/* ), */ - 'conditions' => array(array('Customer.id' => $id)))); + 'conditions' => array + (array('Customer.id' => $id)))); $this->Behaviors->detach('Containable'); + // Get stats from the customer account, and each lease $stats['Account'] = $this->Account->stats($customer['Account']['id']); foreach ($customer['Lease'] AS $lease) { $this->statsMerge($stats['Lease'], $this->Lease->stats($lease['id'])); } -/* foreach($lease['Customer']['Transaction'] AS $transaction) { */ -/* foreach($transaction['LedgerEntry'] AS $entry) { */ -/* if ($entry['DebitLedger']['Account']['name'] === 'A/R') */ -/* $outstanding_balance += $entry['amount']; */ -/* if ($entry['CreditLedger']['Account']['name'] === 'A/R') */ -/* $outstanding_balance -= $entry['amount']; */ - -/* if ($entry['DebitLedger']['Account']['name'] === 'Security Deposit') */ -/* $outstanding_deposit -= $entry['amount']; */ -/* if ($entry['CreditLedger']['Account']['name'] === 'Security Deposit') */ -/* $outstanding_deposit += $entry['amount']; */ -/* } */ -/* } */ -/* } */ -/* if ($entry['DebitLedger']['Account']['name'] === 'Security Deposit') */ -/* $outstanding_deposit -= $entry['amount']; */ -/* if ($entry['CreditLedger']['Account']['name'] === 'Security Deposit') */ -/* $outstanding_deposit += $entry['amount']; */ - // Merge the stats from both the customer specific account, as - // well as the lease. This will provide current customer standing. + // well as the leases. This will provide current customer standing. $this->statsMerge($stats, $stats['Account']['Ledger']); $this->statsMerge($stats, $stats['Lease']['Account']['Ledger']); diff --git a/site/models/lease.php b/site/models/lease.php index 6ce5cc8..b482b2a 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -77,10 +77,6 @@ class Lease extends AppModel { 'conditions' => array(array('id' => $id)), )); -/* $sd_account_id = $this->Account->securityDepositAccountID(); */ -/* $sd_ledger_ids = $this->Account->ledgers($sd_account_id); */ -/* $cond = conditionEntryAsCreditOrDebit($sd_ledger_ids); */ - $entries = $this->Account->findLedgerEntriesRelatedToAccount ($lease['Lease']['account_id'], $this->Account->securityDepositAccountID(), @@ -95,63 +91,6 @@ class Lease extends AppModel { } - /************************************************************************** - ************************************************************************** - ************************************************************************** - * function: findSecurityDeposits - * - Returns an array of security deposit entries - */ - function findAccountDeposits($id, $link = null) { - pr(array_merge(array('function' => 'Lease::findSecurityDeposits', - 'checkpoint' => 'begin'), - compact('id', 'link'))); - $lease = $this->find('first', array - ('recursive' => -1, - 'fields' => array('account_id'), - 'conditions' => array(array('id' => $id)), - )); - pr(array_merge(array('function' => 'Lease::findSecurityDeposits', - 'checkpoint' => 'get-lease'), - compact('lease'))); - - $deposits = $this->Account->findSecurityDeposits($lease['Lease']['account_id'], $link); - pr(array_merge(array('function' => 'Lease::findSecurityDeposits', - 'checkpoint' => 'return'), - compact('deposits'))); - return $deposits; - //return $this->Account->findSecurityDeposits($lease['Lease']['account_id'], $link); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * function: findSecurityDeposits - * - Returns an array of security deposit entries - */ - function qqfindSecurityDeposits($id, $link = null) { - pr(array_merge(array('function' => 'Lease::findSecurityDeposits', - 'checkpoint' => 'begin'), - compact('id', 'link'))); - $lease = $this->find('first', array - ('recursive' => -1, - 'fields' => array('account_id'), - 'conditions' => array(array('id' => $id)), - )); - pr(array_merge(array('function' => 'Lease::findSecurityDeposits', - 'checkpoint' => 'get-lease'), - compact('lease'))); - - return $this->Account->findAccountRelatedEntries($id, $relaccount, $link); - $deposits = $this->Account->findSecurityDeposits($lease['Lease']['account_id'], $link); - pr(array_merge(array('function' => 'Lease::findSecurityDeposits', - 'checkpoint' => 'return'), - compact('deposits'))); - return $deposits; - //return $this->Account->findSecurityDeposits($lease['Lease']['account_id'], $link); - } - - /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/models/ledger.php b/site/models/ledger.php index 02c509b..956d9c2 100644 --- a/site/models/ledger.php +++ b/site/models/ledger.php @@ -15,18 +15,21 @@ class Ledger extends AppModel { 'LedgerEntry' => array( 'className' => 'LedgerEntry', 'foreignKey' => false, + // conditions will be used when JOINing tables // (such as find with LinkableBehavior) 'conditions' => array('OR' => array('LedgerEntry.debit_ledger_id = Ledger.id', 'LedgerEntry.credit_ledger_id = Ledger.id')), - // finderQuery will be used when tables are put - // together across several querys, not with JOIN. - // (such as find with ContainableBehavior) + + // finderQuery will be used when tables are put + // together across several querys, not with JOIN. + // (such as find with ContainableBehavior) 'finderQuery' => 'SELECT `LedgerEntry`.* FROM pmgr_ledger_entries AS `LedgerEntry` WHERE LedgerEntry.debit_ledger_id = ({$__cakeID__$}) OR LedgerEntry.credit_ledger_id = ({$__cakeID__$})', + 'counterQuery' => '' ), 'DebitLedgerEntry' => array( @@ -71,7 +74,7 @@ class Ledger extends AppModel { // If the requested entries are limited by date, we must calculate // a balance forward, or the resulting balance will be thrown off. - + // // REVISIT : This obviously is more general than date. // As such, it will not work (or, only work if the // condition only manages to exclude the first parts @@ -105,10 +108,6 @@ class Ledger extends AppModel { /* 'return' => compact('entries'), */ /* )); */ return $entries; - - // Return entries from the ledger, along with our balance forward. -/* return array_merge($bf, */ -/* $this->LedgerEntry->findInLedgerContext($id, $account_type, $cond, $link)); */ } @@ -133,14 +132,14 @@ class Ledger extends AppModel { ), 'fields' => array("SUM(IF(LedgerEntry.debit_ledger_id = Ledger.id, - LedgerEntry.amount, NULL)) AS debits", + LedgerEntry.amount, NULL)) AS debits", "SUM(IF(LedgerEntry.credit_ledger_id = Ledger.id, - LedgerEntry.amount, NULL)) AS credits", + LedgerEntry.amount, NULL)) AS credits", "SUM(IF(Account.type IN ('ASSET', 'EXPENSE'), - IF(LedgerEntry.debit_ledger_id = Ledger.id, 1, -1), - IF(LedgerEntry.credit_ledger_id = Ledger.id, 1, -1) - ) * IF(LedgerEntry.amount, LedgerEntry.amount, 0) - ) AS balance", + IF(LedgerEntry.debit_ledger_id = Ledger.id, 1, -1), + IF(LedgerEntry.credit_ledger_id = Ledger.id, 1, -1) + ) * IF(LedgerEntry.amount, LedgerEntry.amount, 0) + ) AS balance", "COUNT(LedgerEntry.id) AS entries"), 'conditions' => array(isset($cond) ? $cond : array(), array('Ledger.id' => $id)), diff --git a/site/models/ledger_entry.php b/site/models/ledger_entry.php index 254e411..970efa4 100644 --- a/site/models/ledger_entry.php +++ b/site/models/ledger_entry.php @@ -26,14 +26,16 @@ class LedgerEntry extends AppModel { /************************************************************************** ************************************************************************** ************************************************************************** - * function: - * - + * function: conditionEntryAsCreditOrDebit + * - returns the condition necessary to match a set of + * Ledgers to all related LedgerEntries */ function conditionEntryAsCreditOrDebit($ledger_ids) { return array('OR' => array(array('debit_ledger_id' => $ledger_ids), array('credit_ledger_id' => $ledger_ids))); } + /************************************************************************** ************************************************************************** @@ -78,18 +80,6 @@ class LedgerEntry extends AppModel { array('Transaction.stamp'), )); -/* $entries['summary'] = array('balance' => null, 'debit' => null, 'credit' => null); */ -/* foreach($entries AS $entry) */ -/* $this->statsMerge($entries['summary'], $entry[0]); */ - -/* //if (isset($entries['summary']['debit']) || isset($entries['summary']['credit'])) { */ -/* $entries['summary']['debits'] = $entries['summary']['debit']; */ -/* $entries['summary']['credits'] = $entries['summary']['credit']; */ -/* unset($entries['summary']['debit']); */ -/* unset($entries['summary']['credit']); */ -/* //} */ - - return $entries; } } diff --git a/site/models/unit.php b/site/models/unit.php index 17d9197..f7aa047 100644 --- a/site/models/unit.php +++ b/site/models/unit.php @@ -19,17 +19,12 @@ class Unit extends AppModel { var $hasOne = array( 'CurrentLease' => array( 'className' => 'Lease', - //'foreignKey' => 'unit_id', 'conditions' => 'CurrentLease.close_date IS NULL', ), ); var $hasMany = array( - 'Lease' => array( - 'className' => 'Lease', - 'foreignKey' => 'unit_id', - 'dependent' => false, - ) + 'Lease', ); function statusEnums() { @@ -74,20 +69,30 @@ class Unit extends AppModel { if (!$id) return null; + // Get the basic information necessary $this->Behaviors->attach('Containable'); $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)))); + ('Lease' => array + ('fields' => array('Lease.id')), + + 'CurrentLease' => array + ('fields' => array('CurrentLease.id'))), + + 'conditions' => array + (array('Unit.id' => $id)), + )); $this->Behaviors->detach('Containable'); + // 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; } diff --git a/site/views/elements/ledgers.ctp b/site/views/elements/ledgers.ctp index 8013036..a9818b4 100644 --- a/site/views/elements/ledgers.ctp +++ b/site/views/elements/ledgers.ctp @@ -52,7 +52,7 @@ foreach ($ledgers as $ledger) { if (isset($ledger['Ledger'])) $ledger = $ledger['Ledger']; - $rows[] = array_merge(array($html->link('#'.$ledger['sequence'],//$ledger['name'], + $rows[] = array_merge(array($html->link('#'.$ledger['account_id'].'-'.$ledger['sequence'], array('controller' => 'ledgers', 'action' => 'view', $ledger['id']))), diff --git a/site/views/transactions/view.ctp b/site/views/transactions/view.ctp index 30c07b5..f15f03d 100644 --- a/site/views/transactions/view.ctp +++ b/site/views/transactions/view.ctp @@ -29,11 +29,8 @@ echo $this->element('table', ?>
-
- Debits: -
-
- Credits: +
+ Total:
@@ -53,13 +50,27 @@ echo $this->element('table', * Entries */ -$headers = array('Name', 'Debit', 'Credit', 'Comment', 'Amount', 'Total'); +$headers = array('Entry', 'Debit', 'Credit', 'Comment', 'Amount', 'Total'); +$column_class = array(); +foreach (array_intersect($headers, array('Entry')) AS $k => $v) { + $column_class[$k] = 'id'; +} +foreach (array_intersect($headers, array('Amount', 'Total')) AS $k => $v) { + $column_class[$k] = 'currency'; +} +foreach (array_intersect($headers, array('Comment')) AS $k => $v) { + $column_class[$k] = 'slack'; +} + $rows = array(); $running_total = 0; foreach($transaction['LedgerEntry'] AS $entry) { $amount = $entry['amount']; $running_total += $amount; - $rows[] = array($entry['name'], + $rows[] = array($html->link('#'.$entry['id'], + array('controller' => 'ledger_entries', + 'action' => 'view', + $entry['id'])), $html->link($entry['DebitLedger']['name'], array('controller' => 'ledgers', 'action' => 'view', @@ -79,7 +90,7 @@ echo $this->element('table', 'caption' => 'Entries in Transaction', 'headers' => $headers, 'rows' => $rows, - 'column_class' => $headers)); + 'column_class' => $column_class)); /* End "detail supporting" DIV */ ?> From a60d69ba5201619efe3cbdbcc2c044a654448d88 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 10 Jun 2009 05:15:16 +0000 Subject: [PATCH 082/717] Added small script to help regenerate the database from the sitelink data git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@83 97e9348a-65ac-dc4b-aefc-98561f571b83 --- build.cmd | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 build.cmd diff --git a/build.cmd b/build.cmd new file mode 100644 index 0000000..d073afd --- /dev/null +++ b/build.cmd @@ -0,0 +1,3 @@ +@echo off +%~dp0\scripts\sitelink2pmgr.pl %~dp0\db\schema.sql %~dp0db\vss.mdb > NUL +echo Done! From 4277962e3b12e7b7cb20412dd56b82553108a439 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 10 Jun 2009 08:51:18 +0000 Subject: [PATCH 083/717] Fixed a spelling error in the database schema git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@84 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index b2c4115..e2b826b 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -695,10 +695,10 @@ CREATE TABLE `pmgr_leases` ( `late_schedule_id` INT(10) UNSIGNED DEFAULT NULL, `lease_date` DATE NOT NULL, - `movein_planed_date` DATE DEFAULT NULL, + `movein_planned_date` DATE DEFAULT NULL, `movein_date` DATE DEFAULT NULL, `moveout_date` DATE DEFAULT NULL, - `moveout_planed_date` DATE DEFAULT NULL, + `moveout_planned_date` DATE DEFAULT NULL, `notice_given_date` DATE DEFAULT NULL, `notice_received_date` DATE DEFAULT NULL, `close_date` DATE DEFAULT NULL, From f8eb45a0b9e13948085508a80ca0f2affca3b7ce Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 10 Jun 2009 08:53:22 +0000 Subject: [PATCH 084/717] Added lease and ledger_entry controllers/views. Minor bugfixes as well. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@85 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 3 +- site/controllers/leases_controller.php | 152 ++++++++++++++++++ .../controllers/ledger_entries_controller.php | 66 +++++--- site/controllers/transactions_controller.php | 19 ++- site/models/lease.php | 4 +- site/views/elements/leases.ctp | 7 +- site/views/leases/index.ctp | 3 + site/views/leases/view.ctp | 94 +++++++++++ site/views/ledger_entries/view.ctp | 77 +++++++++ site/views/transactions/view.ctp | 40 +++-- 10 files changed, 427 insertions(+), 38 deletions(-) create mode 100644 site/controllers/leases_controller.php create mode 100644 site/views/leases/index.ctp create mode 100644 site/views/leases/view.ctp create mode 100644 site/views/ledger_entries/view.ctp diff --git a/site/app_controller.php b/site/app_controller.php index c1e74e5..46af502 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -35,13 +35,14 @@ * @subpackage cake.app */ class AppController extends Controller { - var $helpers = array('Html', 'Format'); + var $helpers = array('Html', 'Format', 'Time'); function sideMenuLinks() { return array( array('name' => 'Common', 'header' => true), array('name' => 'Site Map', 'url' => array('controller' => 'maps', 'action' => 'view', 1)), array('name' => 'Units', 'url' => array('controller' => 'units', 'action' => 'index')), + array('name' => 'Leases', 'url' => array('controller' => 'leases', 'action' => 'index')), array('name' => 'Customers', 'url' => array('controller' => 'customers', 'action' => 'index')), array('name' => 'Contacts', 'url' => array('controller' => 'contacts', 'action' => 'index')), array('name' => 'Accounts', 'url' => array('controller' => 'accounts', 'action' => 'index')), diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php new file mode 100644 index 0000000..bb85591 --- /dev/null +++ b/site/controllers/leases_controller.php @@ -0,0 +1,152 @@ + 100, + 'group' => 'Lease.id', + 'order' => array('Lease.movein_date' => 'DESC')); + + var $sidemenu_links = + array(array('name' => 'Leases', 'header' => true), + array('name' => 'Active', 'url' => array('controller' => 'leases', 'action' => 'active')), + array('name' => 'Closed', 'url' => array('controller' => 'leases', 'action' => 'closed')), + array('name' => 'All', 'url' => array('controller' => 'leases', 'action' => 'all')), + ); + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * override: sideMenuLinks + * - Generates controller specific links for the side menu + */ + function sideMenuLinks() { + return array_merge(parent::sideMenuLinks(), $this->sidemenu_links); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: index + * - Lists current leases + */ + + function index() { + $this->active(); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: active + * - Lists all active leases + */ + + function active() { + $leases = $this->paginate(array('Lease.close_date IS NULL')); + + // Get the balance on each lease. + foreach ($leases AS &$lease) { + $stats = $this->Lease->stats($lease['Lease']['id']); + $lease['Lease']['balance'] = $stats['Account']['Ledger']['balance']; + } + + $title = 'Active Leases'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('leases', $leases); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: closed + * - Lists all closed (inactive) leases + */ + + function closed() { + $leases = $this->paginate(array('Lease.close_date IS NOT NULL')); + + // Get the balance on each lease. + foreach ($leases AS &$lease) { + $stats = $this->Lease->stats($lease['Lease']['id']); + $lease['Lease']['balance'] = $stats['Account']['Ledger']['balance']; + } + + $title = 'Past Leases'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('leases', $leases); + $this->render('index'); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: all + * - Lists all leases + */ + + function all() { + $leases = $this->paginate(); + + // Get the balance on each lease. + foreach ($leases AS &$lease) { + $stats = $this->Lease->stats($lease['Lease']['id']); + $lease['Lease']['balance'] = $stats['Account']['Ledger']['balance']; + } + + $title = 'All Leases'; + $this->set('title', $title); $this->set('heading', $title); + $this->set('leases', $leases); + $this->render('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) + $this->Lease->Behaviors->attach('Containable'); + $lease = $this->Lease->find + ('first', + array('contain' => + array(// Models + 'LeaseType', + 'Unit', + 'Account' => array('Ledger'), + 'Customer', + ), + 'conditions' => array(array('Lease.id' => $id)), + 'limit' => 2 + ) + ); + $this->Lease->Behaviors->detach('Containable'); + + // Summarize each ledger + $this->Lease->statsMerge($lease, + $this->Lease->stats($lease['Lease']['id'])); + + // Obtain the overall lease balance + $this->Lease->statsMerge($lease['Lease'], + array('stats' => $this->Lease->stats($id))); + $balance = $lease['Lease']['stats']['Account']['Ledger']['balance']; + + // Prepare to render + $title = 'Lease: #' . $lease['Lease']['id']; + $this->set(compact('lease', 'title', 'balance')); + } +} diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index a389a56..21ed6af 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -5,11 +5,7 @@ class LedgerEntriesController extends AppController { 'group' => 'Entry.id', 'order' => array('Entry.stamp' => 'ASC')); - var $sidemenu_links = - array(array('name' => 'Entries', 'header' => true), - array('name' => 'Cleared', 'url' => array('controller' => 'ledger_entries', 'action' => 'cleared')), - array('name' => 'Unresolved', 'url' => array('controller' => 'ledger_entries', 'action' => 'unresolved')), - ); + var $sidemenu_links = array(); /************************************************************************** @@ -36,22 +32,56 @@ class LedgerEntriesController extends AppController { $this->redirect(array('controller' => 'accounts', 'action'=>'index')); } + // Get the LedgerEntry and related fields $this->LedgerEntry->Behaviors->attach('Containable'); - $this->LedgerEntry->contain - (array(// Models - 'MonetarySource' => array('MonetaryType'), - 'Transaction', - 'DebitLedger', - 'CreditLedger', - ) - ); - $entry = $this->LedgerEntry->read(null, $id); + $entry = $this->LedgerEntry->find + ('first', + array('contain' => array('MonetarySource.id', + 'MonetarySource.MonetaryType.id', + 'Transaction.id', + 'Transaction.stamp', + 'DebitLedger.id', + 'DebitLedger.sequence', + 'DebitLedger.account_id', + 'CreditLedger.id', + 'CreditLedger.sequence', + 'CreditLedger.account_id', + ), + + 'fields' => array('LedgerEntry.id', + 'LedgerEntry.amount', + 'LedgerEntry.comment'), + )); $this->LedgerEntry->Behaviors->detach('Containable'); - $title = "Entry #{$entry['LedgerEntry']['id']} ({$entry['LedgerEntry']['name']})"; - $this->set(compact('entry', 'title')); + // Because 'DebitLedger' and 'CreditLedger' both relate to 'Account', + // CakePHP will not include them in the LedgerEntry->find (or so it + // seems). We'll have to break out each Account separately. - pr($entry); - $this->autoRender = false; + // Get the Account from DebitLedger + $this->LedgerEntry->DebitLedger->Account->Behaviors->attach('Containable'); + $account = $this->LedgerEntry->DebitLedger->Account->find + ('first', + array('contain' => true, + 'fields' => array('Account.id', 'Account.name', 'Account.type'), + 'conditions' => array('Account.id' => $entry['DebitLedger']['account_id']), + )); + $entry['DebitLedger'] = array_merge($entry['DebitLedger'], $account); + $this->LedgerEntry->DebitLedger->Account->Behaviors->detach('Containable'); + + // Get the Account from CreditLedger + $this->LedgerEntry->CreditLedger->Account->Behaviors->attach('Containable'); + $account = $this->LedgerEntry->CreditLedger->Account->find + ('first', + array('contain' => true, + 'fields' => array('Account.id', 'Account.name', 'Account.type'), + 'conditions' => array('Account.id' => $entry['CreditLedger']['account_id']), + )); + $entry['CreditLedger'] = array_merge($entry['CreditLedger'], $account); + $this->LedgerEntry->CreditLedger->Account->Behaviors->detach('Containable'); + + // Prepare to render. + $title = "Ledger Entry #{$entry['LedgerEntry']['id']}"; + $this->set(compact('entry', 'title')); } } diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php index 8641019..6a49247 100644 --- a/site/controllers/transactions_controller.php +++ b/site/controllers/transactions_controller.php @@ -100,9 +100,22 @@ class TransactionsController extends AppController { $this->Transaction->Behaviors->attach('Containable'); $this->Transaction->contain (array(// Models - 'LedgerEntry' => array(//Models - 'DebitLedger', - 'CreditLedger', + 'LedgerEntry' => array('fields' => array('LedgerEntry.id', + 'LedgerEntry.amount', + 'LedgerEntry.comment'), + //Models + + 'DebitLedger' => array + ('fields' => array('DebitLedger.id', 'DebitLedger.sequence'), + 'Account' => array + ('fields' => array('Account.id', 'Account.name')), + ), + + 'CreditLedger' => array + ('fields' => array('CreditLedger.id', 'CreditLedger.sequence'), + 'Account' => array + ('fields' => array('Account.id', 'Account.name')), + ), ), ) ); diff --git a/site/models/lease.php b/site/models/lease.php index b482b2a..a7da73e 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -9,10 +9,10 @@ class Lease extends AppModel { 'unit_id' => array('numeric'), 'late_schedule_id' => array('numeric'), 'lease_date' => array('date'), - 'movein_planed_date' => array('date'), + 'movein_planned_date' => array('date'), 'movein_date' => array('date'), 'moveout_date' => array('date'), - 'moveout_planed_date' => array('date'), + 'moveout_planned_date' => array('date'), 'notice_given_date' => array('date'), 'notice_received_date' => array('date'), 'close_date' => array('date'), diff --git a/site/views/elements/leases.ctp b/site/views/elements/leases.ctp index bb4e56a..098da00 100644 --- a/site/views/elements/leases.ctp +++ b/site/views/elements/leases.ctp @@ -17,14 +17,17 @@ foreach (array_intersect($headers, array('Lease', 'Unit')) AS $k => $v) { foreach (array_intersect($headers, array('Balance')) AS $k => $v) { $column_class[$k] = 'currency'; } +foreach (array_intersect($headers, array('Comment')) AS $k => $v) { + $column_class[$k] = 'slack'; +} if (isset($paginator)) { echo $paginator->counter(array('format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); $headers = array_merge(array($paginator->sort('Lease')), isset($leases[0]['Unit']) - ? $paginator->sort('Unit', 'Unit.id') - : $paginator->sort('Customer.id'), + ? array($paginator->sort('Unit', 'Unit.id')) + : array($paginator->sort('Customer.id')), array($paginator->sort('Signed', 'lease_date'), $paginator->sort('Move-In', 'movein_date'), $paginator->sort('Move-Out', 'moveout_date'), diff --git a/site/views/leases/index.ctp b/site/views/leases/index.ctp new file mode 100644 index 0000000..e003f18 --- /dev/null +++ b/site/views/leases/index.ctp @@ -0,0 +1,3 @@ +
+element('leases', array('heading' => '

'.$heading.'

')) ?> +
diff --git a/site/views/leases/view.ctp b/site/views/leases/view.ctp new file mode 100644 index 0000000..217a0e8 --- /dev/null +++ b/site/views/leases/view.ctp @@ -0,0 +1,94 @@ + + +
+ +link($unit['id'], + array('controller' => 'units', + 'action' => 'view', + $unit['id']))), + array('Customer', $html->link($customer['name'], + array('controller' => 'customers', + 'action' => 'view', + $customer['id']))), + array('Lease_Date', FormatHelper::date($lease['lease_date'])), + array('Move-in Planned', FormatHelper::date($lease['movein_planned_date'])), + array('Move-in', (FormatHelper::date($lease['movein_date']) + . ' (' + . $time->timeAgoInWords($lease['movein_date'], + array('end' => '+99 years')) + . ')')), + array('Move-out', (FormatHelper::date($lease['moveout_date']) + . ' (' + . $time->timeAgoInWords($lease['moveout_date'], + array('end' => '+99 years')) + . ')')), + array('Move-out Planned', FormatHelper::date($lease['moveout_planned_date'])), + array('Notice Given', FormatHelper::date($lease['notice_given_date'])), + array('Notice Received', FormatHelper::date($lease['notice_received_date'])), + array('Closed', FormatHelper::date($lease['close_date'])), + array('Account', $html->link($account['name'], + array('controller' => 'accounts', + 'action' => 'view', + $account['id']))), + array('Deposit', (FormatHelper::currency($lease['deposit']))), + array('Rent', (FormatHelper::currency($lease['amount']))), + array('Comment', $lease['comment'])); + + +echo $this->element('table', + array('class' => 'item account detail', + 'caption' => 'Account Detail', + 'rows' => $rows, + 'column_class' => array('field', 'value'))); + + +/********************************************************************** + * Account Info Box + */ + +?> + +
+
+ Account Balance: +
+
+ +
+ +
+ + +
diff --git a/site/views/ledger_entries/view.ctp b/site/views/ledger_entries/view.ctp new file mode 100644 index 0000000..7b04524 --- /dev/null +++ b/site/views/ledger_entries/view.ctp @@ -0,0 +1,77 @@ + + +
+ +link('#'.$entry['Transaction']['id'], + array('controller' => 'transactions', + 'action' => 'view', + $entry['Transaction']['id']))), + array('Timestamp', FormatHelper::datetime($entry['Transaction']['stamp'])), + array('Source', $entry['MonetarySource']['id']), + array('Amount', FormatHelper::currency($entry['LedgerEntry']['amount'])), + array('Debit', ($html->link($entry['DebitLedger']['Account']['name'], + array('controller' => 'accounts', + 'action' => 'view', + $entry['DebitLedger']['Account']['id'])) + . ' (' + . $html->link('#' . $entry['DebitLedger']['Account']['id'] + . '-' . $entry['DebitLedger']['sequence'], + array('controller' => 'ledgers', + 'action' => 'view', + $entry['DebitLedger']['id'])) + . ')')), + array('Credit', ($html->link($entry['CreditLedger']['Account']['name'], + array('controller' => 'accounts', + 'action' => 'view', + $entry['CreditLedger']['Account']['id'])) + . ' (' + . $html->link('#' . $entry['CreditLedger']['Account']['id'] + . '-' . $entry['CreditLedger']['sequence'], + array('controller' => 'ledgers', + 'action' => 'view', + $entry['CreditLedger']['id'])) + . ')')), + array('Comment', $entry['LedgerEntry']['comment'])); + +echo $this->element('table', + array('class' => 'item ledger-entry detail', + 'caption' => 'Ledger Entry Detail', + 'rows' => $rows, + 'column_class' => array('field', 'value'))); + + +/********************************************************************** + * LedgerEntry Info Box + */ + +?> +
+
+ +
+ +
+ +
diff --git a/site/views/transactions/view.ctp b/site/views/transactions/view.ctp index f15f03d..e0ce6b6 100644 --- a/site/views/transactions/view.ctp +++ b/site/views/transactions/view.ctp @@ -14,11 +14,13 @@ $rows = array(array('ID', $transaction['Transaction']['id']), array('Timestamp', FormatHelper::datetime($transaction['Transaction']['stamp'])), + array('Through', FormatHelper::date($transaction['Transaction']['through_date'])), + array('Due', FormatHelper::date($transaction['Transaction']['due_date'])), array('Comment', $transaction['Transaction']['comment'])); echo $this->element('table', array('class' => 'item transaction detail', - 'caption' => 'Transaction Info', + 'caption' => 'Transaction Detail', 'rows' => $rows, 'column_class' => array('field', 'value'))); @@ -50,7 +52,7 @@ echo $this->element('table', * Entries */ -$headers = array('Entry', 'Debit', 'Credit', 'Comment', 'Amount', 'Total'); +$headers = array('Entry', 'Debit', 'Credit', 'Amount', 'Comment',/* 'Total'*/); $column_class = array(); foreach (array_intersect($headers, array('Entry')) AS $k => $v) { $column_class[$k] = 'id'; @@ -71,17 +73,31 @@ foreach($transaction['LedgerEntry'] AS $entry) { array('controller' => 'ledger_entries', 'action' => 'view', $entry['id'])), - $html->link($entry['DebitLedger']['name'], - array('controller' => 'ledgers', - 'action' => 'view', - $entry['DebitLedger']['id'])), - $html->link($entry['CreditLedger']['name'], - array('controller' => 'ledgers', - 'action' => 'view', - $entry['CreditLedger']['id'])), - $entry['comment'], + ($html->link($entry['DebitLedger']['Account']['name'], + array('controller' => 'accounts', + 'action' => 'view', + $entry['DebitLedger']['Account']['id'])) + . ' (' + . $html->link('#' . $entry['DebitLedger']['Account']['id'] + . '-' . $entry['DebitLedger']['sequence'], + array('controller' => 'ledgers', + 'action' => 'view', + $entry['DebitLedger']['id'])) + . ')'), + ($html->link($entry['CreditLedger']['Account']['name'], + array('controller' => 'accounts', + 'action' => 'view', + $entry['CreditLedger']['Account']['id'])) + . ' (' + . $html->link('#' . $entry['CreditLedger']['Account']['id'] + . '-' . $entry['CreditLedger']['sequence'], + array('controller' => 'ledgers', + 'action' => 'view', + $entry['CreditLedger']['id'])) + . ')'), FormatHelper::currency($entry['amount']), - FormatHelper::currency($running_total) + $entry['comment'], + //FormatHelper::currency($running_total), ); } From d60c9721caebc96a6d038afff01a643f3545eceb Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 10 Jun 2009 08:58:43 +0000 Subject: [PATCH 085/717] Added in security deposit information to the lease view git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@86 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/leases_controller.php | 10 ++++++++-- site/views/leases/view.ctp | 11 +++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index bb85591..f0952fe 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -143,10 +143,16 @@ class LeasesController extends AppController { // Obtain the overall lease balance $this->Lease->statsMerge($lease['Lease'], array('stats' => $this->Lease->stats($id))); - $balance = $lease['Lease']['stats']['Account']['Ledger']['balance']; + $outstanding_balance = $lease['Lease']['stats']['Account']['Ledger']['balance']; + + // Determine the lease security deposit + $deposits = $this->Lease->findSecurityDeposits($lease['Lease']['id']); + $outstanding_deposit = $deposits['summary']['balance']; // Prepare to render $title = 'Lease: #' . $lease['Lease']['id']; - $this->set(compact('lease', 'title', 'balance')); + $this->set(compact('lease', 'title', + 'outstanding_deposit', + 'outstanding_balance')); } } diff --git a/site/views/leases/view.ctp b/site/views/leases/view.ctp index 217a0e8..cae813a 100644 --- a/site/views/leases/view.ctp +++ b/site/views/leases/view.ctp @@ -57,8 +57,8 @@ $rows = array(array('ID', $lease['id']), echo $this->element('table', - array('class' => 'item account detail', - 'caption' => 'Account Detail', + array('class' => 'item lease detail', + 'caption' => 'Lease Detail', 'rows' => $rows, 'column_class' => array('field', 'value'))); @@ -70,8 +70,11 @@ echo $this->element('table', ?>
-
- Account Balance: +
+ Security Deposit: +
+
+ Balance:
From fb48baf5757e8265c7f95f3c9ebd73f4dc4432cf Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 10 Jun 2009 09:10:09 +0000 Subject: [PATCH 086/717] Fixed problem with units that are vacant, and thus have no current lease. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@87 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/units_controller.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index 59515db..9fcb630 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -169,14 +169,18 @@ class UnitsController extends AppController { $lease['balance'] = $stats['Account']['Ledger']['balance']; } - // Figure out the outstanding balance of the current lease. - $stats = $this->Unit->stats($id); - $outstanding_balance = - $stats['CurrentLease']['Account']['Ledger']['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']['Account']['Ledger']['balance']; - // Figure out the total security deposit for the current lease. - $deposits = $this->Unit->Lease->findSecurityDeposits($unit['CurrentLease']['id']); - $outstanding_deposit = $deposits['summary']['balance']; + // Figure out the total security deposit for the current lease. + $deposits = $this->Unit->Lease->findSecurityDeposits($unit['CurrentLease']['id']); + $outstanding_deposit = $deposits['summary']['balance']; + } $this->sidemenu_links[] = array('name' => 'Operations', 'header' => true); From 760420bdc54ce347698cc2d77c9cab3d33b9c6ab Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 10 Jun 2009 15:08:52 +0000 Subject: [PATCH 087/717] Removed the external account information (such as quickbooks account number) from account listings. This is fairly specific information that probably only needs to be in the account detail. When setting up quickbooks though, I could see it being useful, so perhaps an action in the accounts controller to list all accounts with their external info, or a parameter to the existing actions. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@88 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/accounts.ctp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/site/views/elements/accounts.ctp b/site/views/elements/accounts.ctp index d7db42a..7b1821f 100644 --- a/site/views/elements/accounts.ctp +++ b/site/views/elements/accounts.ctp @@ -5,7 +5,7 @@ if (isset($heading)) elseif (!isset($caption)) echo '

'.__('Accounts',true).'

'; -$headers = array('Name', 'Type', 'Ext. Name', 'Ext. Account', 'Entries', 'Debits', 'Credits', 'Balance', 'Comment'); +$headers = array('Name', 'Type', /*'Ext. Name', 'Ext. Account',*/ 'Entries', 'Debits', 'Credits', 'Balance', 'Comment'); $column_class = array(); foreach (array_intersect($headers, array('Debits', 'Credits', 'Balance')) AS $k => $v) { $column_class[$k] = 'currency'; @@ -20,8 +20,8 @@ if (isset($paginator)) { $headers = array($paginator->sort('name'), $paginator->sort('type'), - $paginator->sort('Ext. Name', 'external_name'), - $paginator->sort('Ext. Account', 'external_account'), +/* $paginator->sort('Ext. Name', 'external_name'), */ +/* $paginator->sort('Ext. Account', 'external_account'), */ $paginator->sort('entries'), $paginator->sort('debits'), $paginator->sort('credits'), @@ -46,8 +46,8 @@ foreach ($accounts as $account) { 'action' => 'view', $account['id'])), $account['type'], - $account['external_name'], - $account['external_account'], +/* $account['external_name'], */ +/* $account['external_account'], */ $stats['entries'], FormatHelper::currency($stats['debits']), FormatHelper::currency($stats['credits']), From 147c1e7097fc119bf027178b53c4dbd46fb625f7 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 10 Jun 2009 17:06:35 +0000 Subject: [PATCH 088/717] Added a formatting method to print the age of a datetime object, and modified the lease view to use it. I anticipate customizing the function to be more fuzzy and less precise. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@89 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/helpers/format.php | 5 +++ site/views/leases/view.ctp | 64 +++++++++++++++++------------------ 2 files changed, 36 insertions(+), 33 deletions(-) diff --git a/site/views/helpers/format.php b/site/views/helpers/format.php index 948a5a8..eeab2df 100644 --- a/site/views/helpers/format.php +++ b/site/views/helpers/format.php @@ -64,4 +64,9 @@ class FormatHelper extends AppHelper { return $comment; } + function age($datetime) { + return $time->timeAgoInWords($datetime, + array('end' => '+99 years')); + } + } diff --git a/site/views/leases/view.ctp b/site/views/leases/view.ctp index cae813a..3d47698 100644 --- a/site/views/leases/view.ctp +++ b/site/views/leases/view.ctp @@ -20,40 +20,38 @@ $unit = $lease['Unit']; if (isset($lease['Lease'])) $lease = $lease['Lease']; -$rows = array(array('ID', $lease['id']), - array('Number', $lease['number']), - array('Lease Type', $lease_type['name']), - array('Unit', $html->link($unit['id'], - array('controller' => 'units', - 'action' => 'view', - $unit['id']))), - array('Customer', $html->link($customer['name'], - array('controller' => 'customers', - 'action' => 'view', - $customer['id']))), - array('Lease_Date', FormatHelper::date($lease['lease_date'])), - array('Move-in Planned', FormatHelper::date($lease['movein_planned_date'])), - array('Move-in', (FormatHelper::date($lease['movein_date']) - . ' (' - . $time->timeAgoInWords($lease['movein_date'], - array('end' => '+99 years')) - . ')')), - array('Move-out', (FormatHelper::date($lease['moveout_date']) - . ' (' - . $time->timeAgoInWords($lease['moveout_date'], - array('end' => '+99 years')) - . ')')), +$rows = array(array('ID', $lease['id']), + array('Number', $lease['number']), + array('Lease Type', $lease_type['name']), + array('Unit', $html->link($unit['id'], + array('controller' => 'units', + 'action' => 'view', + $unit['id']))), + array('Customer', $html->link($customer['name'], + array('controller' => 'customers', + 'action' => 'view', + $customer['id']))), + array('Lease_Date', FormatHelper::date($lease['lease_date'])), + array('Move-in Planned', FormatHelper::date($lease['movein_planned_date'])), + array('Move-in', (FormatHelper::date($lease['movein_date']) + . ' (' + . FormatHelper::age($lease['movein_date']) + . ')')), + array('Move-out', (FormatHelper::date($lease['moveout_date']) + . ' (' + . FormatHelper::age($lease['moveout_date']) + . ')')), array('Move-out Planned', FormatHelper::date($lease['moveout_planned_date'])), - array('Notice Given', FormatHelper::date($lease['notice_given_date'])), - array('Notice Received', FormatHelper::date($lease['notice_received_date'])), - array('Closed', FormatHelper::date($lease['close_date'])), - array('Account', $html->link($account['name'], - array('controller' => 'accounts', - 'action' => 'view', - $account['id']))), - array('Deposit', (FormatHelper::currency($lease['deposit']))), - array('Rent', (FormatHelper::currency($lease['amount']))), - array('Comment', $lease['comment'])); + array('Notice Given', FormatHelper::date($lease['notice_given_date'])), + array('Notice Received', FormatHelper::date($lease['notice_received_date'])), + array('Closed', FormatHelper::date($lease['close_date'])), + array('Account', $html->link($account['name'], + array('controller' => 'accounts', + 'action' => 'view', + $account['id']))), + array('Deposit', FormatHelper::currency($lease['deposit'])), + array('Rent', FormatHelper::currency($lease['amount'])), + array('Comment', $lease['comment'])); echo $this->element('table', From 8d062ab92e3a9da50ce6f8fcfdbcc585b17e40a5 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 10 Jun 2009 20:20:55 +0000 Subject: [PATCH 089/717] Customized our fuzzy 'age' function to suit our purpose git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@90 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/helpers/format.php | 140 +++++++++++++++++++++++++++++++--- site/views/leases/view.ctp | 22 ++---- 2 files changed, 136 insertions(+), 26 deletions(-) diff --git a/site/views/helpers/format.php b/site/views/helpers/format.php index eeab2df..b28042c 100644 --- a/site/views/helpers/format.php +++ b/site/views/helpers/format.php @@ -11,6 +11,14 @@ class FormatHelper extends AppHelper { self::$number = new NumberHelper; } + function _n($amount, $singular, $plural = null) { + return ($amount . ' ' . + __n($singular, + $plural ? $plural : $singular.'s', + $amount, + true)); + } + function currency($amount) { if (!isset($amount)) return '-'; @@ -19,19 +27,16 @@ class FormatHelper extends AppHelper { return (isset($amount) ? self::$number->currency($amount) : null); - -/* if ($money < 0) */ -/* return "($ " . number_format(-1*$money, 2) . ")"; */ -/* else */ -/* return "$ " . number_format($money, 2); */ } - function date($date) { + function date($date, $age = false) { + if (!$date) return null; + $date_fmt = 'm/d/Y'; - return (isset($date) - ? self::$time->format($date_fmt, $date) - //? date_format(date_create($date), $date_fmt) - : null); + return (self::$time->format($date_fmt, $date) . + ($age + ? ' (' . self::age($date) . ')' + : '')); } function datetime($datetime) { @@ -65,8 +70,119 @@ class FormatHelper extends AppHelper { } function age($datetime) { - return $time->timeAgoInWords($datetime, - array('end' => '+99 years')); + if (!isset($datetime)) + return null; + + $now = time(); + $seconds = self::$time->fromString($datetime); + $backwards = ($seconds > $now); + + $timefrom = $backwards ? $now : $seconds; + $timeto = $backwards ? $seconds : $now; + $span = $timeto - $timefrom; + + // Display seconds if under 45 seconds + if ($span === 0) { + return __('now', true); + } + if ($span < 45) { + $approx = round($span); + $unit = 'second'; + } + // Display minutes if under 45 minutes + elseif (($span /= 60) < 45) { + $approx = round($span); + $unit = 'minute'; + } + // Display hours if under 18 hours + elseif (($span /= 60) < 18) { + $approx = round($span); + $unit = 'hour'; + } + // Display days if under 6.5 days + elseif (($span /= 24) < 6.5) { + $approx = round($span); + $unit = 'day'; + } + // Display weeks if less than 8 weeks + elseif (($span /= 7) < 8) { + $approx = round($span); + $unit = 'week'; + } + // Display months if less than 20 months + elseif (($span /= (365.2425 / (7 * 12))) < 20) { + $approx = round($span); + $unit = 'month'; + + // Months are from 28-31 days. If it's too + // close to being an exact month, just fudge + // by saying the result is 'about' N months + // instead of 'almost' or 'over' N months, + // since we can't be accurate on this without + // taking into account the day of the week. + if ((abs($span - $approx) * (365.2425 / 12)) < 3) + $relative = 'about'; + } + else { + $span /= 12; + $approx = round($span); + $unit = 'year'; + } + + return (__(isset($relative) + ? $relative + : ($approx == $span + ? '' + : ($approx > $span ? 'almost' : 'over')), true) + . ' ' + . self::_n($approx, $unit) + . ($backwards ? '' : __(' ago', true))); } +/***************************** + ** Test code + **/ +/* function basevals($max) { */ +/* return incrvals($max); */ +/* if ($max % 2) { */ +/* return array(0, 1, ($max+1)/2-1, $max/2, ($max+1)/2, $max-1); */ +/* } */ +/* else { */ +/* return array(0, 1, $max/2-1, $max/2, $max/2+1, $max-1); */ +/* } */ +/* } */ + +/* function incrvals($max, $suppress = false) { */ +/* if ($suppress) */ +/* //return array(0); */ +/* return array(0, 4, $max-1); */ + +/* //return array(0, 1, $max/3, (int)(($max+1)/2)-1, 2*$max/3, 3*$max/4, 4*$max/5, $max-1); */ +/* return array(0, 1, 3, $max/2+2, (int)(($max+1)/2)+4, 2*$max/3, 3*$max/4, 4*$max/5, $max-1); */ +/* } */ + +/* echo('' . "\n"); */ +/* foreach (incrvals(10) AS $y) { */ +/* foreach (incrvals(12, $y) AS $w) { */ +/* foreach (incrvals(30, $y||$w) AS $d) { */ +/* foreach (incrvals(24, $y||$w||$d) AS $h) { */ +/* foreach (incrvals(60, $y||$w||$d||$h) AS $m) { */ +/* foreach ($y||$w||$d||$h||$m ? array(0,1,59) : basevals(60) AS $s) { */ +/* $seconds = 60*(60*(24*(30*(12*$y +$w) + $d) + $h) + $m) + $s; */ +/* //$seconds = 60*(60*(24*(7*(52*$y +$w) + $d) + $h) + $m) + $s; */ +/* $age = time() - $seconds; */ +/* echo ('' */ +/* . ' ' */ +/* . ' ' */ +/* . ' ' */ +/* . ' ' */ +/* .'' . "\n"); */ +/* } */ +/* } */ +/* } */ +/* } */ +/* } */ +/* } */ +/* echo('
' . "y:$y; M:$w; d:$d; h:$h; m:$m; s:$s" . '' . FormatHelper::datetime($age) . '' . FormatHelper::age($age) . '' . $seconds . '; days='.($seconds/60/60/24).'
' . "\n"); */ + } diff --git a/site/views/leases/view.ctp b/site/views/leases/view.ctp index 3d47698..1b4d0b4 100644 --- a/site/views/leases/view.ctp +++ b/site/views/leases/view.ctp @@ -31,20 +31,14 @@ $rows = array(array('ID', $lease['id']), array('controller' => 'customers', 'action' => 'view', $customer['id']))), - array('Lease_Date', FormatHelper::date($lease['lease_date'])), - array('Move-in Planned', FormatHelper::date($lease['movein_planned_date'])), - array('Move-in', (FormatHelper::date($lease['movein_date']) - . ' (' - . FormatHelper::age($lease['movein_date']) - . ')')), - array('Move-out', (FormatHelper::date($lease['moveout_date']) - . ' (' - . FormatHelper::age($lease['moveout_date']) - . ')')), - array('Move-out Planned', FormatHelper::date($lease['moveout_planned_date'])), - array('Notice Given', FormatHelper::date($lease['notice_given_date'])), - array('Notice Received', FormatHelper::date($lease['notice_received_date'])), - array('Closed', FormatHelper::date($lease['close_date'])), + array('Lease_Date', FormatHelper::date($lease['lease_date'], true)), + array('Move-in Planned', FormatHelper::date($lease['movein_planned_date'], true)), + array('Move-in', FormatHelper::date($lease['movein_date'], true)), + array('Move-out', FormatHelper::date($lease['moveout_date'], true)), + array('Move-out Planned', FormatHelper::date($lease['moveout_planned_date'], true)), + array('Notice Given', FormatHelper::date($lease['notice_given_date'], true)), + array('Notice Received', FormatHelper::date($lease['notice_received_date'], true)), + array('Closed', FormatHelper::date($lease['close_date'], true)), array('Account', $html->link($account['name'], array('controller' => 'accounts', 'action' => 'view', From 18b928411bf5281a49767e8220c07edb1bfff507 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 10 Jun 2009 21:09:23 +0000 Subject: [PATCH 090/717] Added the Containable behavior back into the AppModel, since it's obviously getting used in every controller. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@91 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_model.php | 3 +- site/controllers/accounts_controller.php | 2 - site/controllers/contacts_controller.php | 21 ++++----- site/controllers/customers_controller.php | 41 ++++++++--------- site/controllers/leases_controller.php | 2 - .../controllers/ledger_entries_controller.php | 8 +--- site/controllers/ledgers_controller.php | 2 - site/controllers/transactions_controller.php | 44 +++++++++---------- site/controllers/units_controller.php | 20 ++++----- 9 files changed, 67 insertions(+), 76 deletions(-) diff --git a/site/app_model.php b/site/app_model.php index 97f8611..424965c 100644 --- a/site/app_model.php +++ b/site/app_model.php @@ -38,8 +38,7 @@ */ class AppModel extends Model { - //var $actsAs = array('Containable'); - var $actsAs = array('Linkable'); + var $actsAs = array('Containable', 'Linkable'); /** * Get Enum Values diff --git a/site/controllers/accounts_controller.php b/site/controllers/accounts_controller.php index f317b0c..6e3ffc2 100644 --- a/site/controllers/accounts_controller.php +++ b/site/controllers/accounts_controller.php @@ -170,7 +170,6 @@ class AccountsController extends AppController { } // Get details about the account and its ledgers (no ledger entries yet) - $this->Account->Behaviors->attach('Containable'); $account = $this->Account->find ('first', array('contain' => @@ -184,7 +183,6 @@ class AccountsController extends AppController { 'conditions' => array(array('Account.id' => $id)), ) ); - $this->Account->Behaviors->detach('Containable'); // Get all ledger entries of the CURRENT ledger $entries = $this->Account->findLedgerEntries($id); diff --git a/site/controllers/contacts_controller.php b/site/controllers/contacts_controller.php index 360429a..2e2100a 100644 --- a/site/controllers/contacts_controller.php +++ b/site/controllers/contacts_controller.php @@ -65,16 +65,17 @@ class ContactsController extends AppController { $this->redirect(array('action'=>'index')); } - $this->Contact->Behaviors->attach('Containable'); - $this->Contact->contain - (array(// Models - 'ContactPhone', - 'ContactEmail', - 'ContactAddress', - 'Customer') - ); - $contact = $this->Contact->read(null, $id); - $this->Contact->Behaviors->detach('Containable'); + $contact = $this->Contact->find + ('first', array + ('contain' => array + (// Models + 'ContactPhone', + 'ContactEmail', + 'ContactAddress', + 'Customer'), + + 'conditions' => array('Contact.id' => $id), + )); // Prepare to render. $title = $contact['Contact']['display_name']; diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index f98d1d6..a866b96 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -117,26 +117,27 @@ class CustomersController extends AppController { $this->redirect(array('action'=>'index')); } - $this->Customer->Behaviors->attach('Containable'); - $this->Customer->contain - (array(// Models - 'Contact' => - array(// Models - 'ContactPhone', - 'ContactEmail', - 'ContactAddress', - ), - 'Account', - 'Lease' => - array('Unit' => - array('order' => array('sort_order'), - 'fields' => array('id', 'name'), - ), - ), - ) - ); - $customer = $this->Customer->read(null, $id); - $this->Customer->Behaviors->detach('Containable'); + $customer = $this->Customer->find + ('first', array + ('contain' => array + (// Models + 'Contact' => + array(// Models + 'ContactPhone', + 'ContactEmail', + 'ContactAddress', + ), + 'Account', + 'Lease' => + array('Unit' => + array('order' => array('sort_order'), + 'fields' => array('id', 'name'), + ), + ), + ), + + 'conditions' => array('Customer.id' => $id), + )); // Add the lease balance to each lease. foreach ($customer['Lease'] AS &$lease) { diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index f0952fe..ecc593a 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -120,7 +120,6 @@ class LeasesController extends AppController { } // Get details about the lease and its ledgers (no ledger entries yet) - $this->Lease->Behaviors->attach('Containable'); $lease = $this->Lease->find ('first', array('contain' => @@ -134,7 +133,6 @@ class LeasesController extends AppController { 'limit' => 2 ) ); - $this->Lease->Behaviors->detach('Containable'); // Summarize each ledger $this->Lease->statsMerge($lease, diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index 21ed6af..1132c68 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -33,7 +33,6 @@ class LedgerEntriesController extends AppController { } // Get the LedgerEntry and related fields - $this->LedgerEntry->Behaviors->attach('Containable'); $entry = $this->LedgerEntry->find ('first', array('contain' => array('MonetarySource.id', @@ -51,15 +50,15 @@ class LedgerEntriesController extends AppController { 'fields' => array('LedgerEntry.id', 'LedgerEntry.amount', 'LedgerEntry.comment'), + + 'conditions' => array('LedgerEntry.id' => $id), )); - $this->LedgerEntry->Behaviors->detach('Containable'); // Because 'DebitLedger' and 'CreditLedger' both relate to 'Account', // CakePHP will not include them in the LedgerEntry->find (or so it // seems). We'll have to break out each Account separately. // Get the Account from DebitLedger - $this->LedgerEntry->DebitLedger->Account->Behaviors->attach('Containable'); $account = $this->LedgerEntry->DebitLedger->Account->find ('first', array('contain' => true, @@ -67,10 +66,8 @@ class LedgerEntriesController extends AppController { 'conditions' => array('Account.id' => $entry['DebitLedger']['account_id']), )); $entry['DebitLedger'] = array_merge($entry['DebitLedger'], $account); - $this->LedgerEntry->DebitLedger->Account->Behaviors->detach('Containable'); // Get the Account from CreditLedger - $this->LedgerEntry->CreditLedger->Account->Behaviors->attach('Containable'); $account = $this->LedgerEntry->CreditLedger->Account->find ('first', array('contain' => true, @@ -78,7 +75,6 @@ class LedgerEntriesController extends AppController { 'conditions' => array('Account.id' => $entry['CreditLedger']['account_id']), )); $entry['CreditLedger'] = array_merge($entry['CreditLedger'], $account); - $this->LedgerEntry->CreditLedger->Account->Behaviors->detach('Containable'); // Prepare to render. $title = "Ledger Entry #{$entry['LedgerEntry']['id']}"; diff --git a/site/controllers/ledgers_controller.php b/site/controllers/ledgers_controller.php index 965270f..ac13fb4 100644 --- a/site/controllers/ledgers_controller.php +++ b/site/controllers/ledgers_controller.php @@ -118,7 +118,6 @@ class LedgersController extends AppController { } // Get details about the ledger itself (no entries yet) - $this->Ledger->Behaviors->attach('Containable'); $ledger = $this->Ledger->find ('first', array('contain' => @@ -128,7 +127,6 @@ class LedgersController extends AppController { 'conditions' => array(array('Ledger.id' => $id)), ) ); - $this->Ledger->Behaviors->detach('Containable'); // Get all ledger entries of this ledger $ledger['LedgerEntry'] = $this->Ledger->findLedgerEntries diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php index 6a49247..d54b2eb 100644 --- a/site/controllers/transactions_controller.php +++ b/site/controllers/transactions_controller.php @@ -97,30 +97,30 @@ class TransactionsController extends AppController { $this->redirect(array('action'=>'index')); } - $this->Transaction->Behaviors->attach('Containable'); - $this->Transaction->contain - (array(// Models - 'LedgerEntry' => array('fields' => array('LedgerEntry.id', - 'LedgerEntry.amount', - 'LedgerEntry.comment'), - //Models + $transaction = $this->Transaction->find + ('first', + array('contain' => + array(// Models + 'LedgerEntry' => array('fields' => array('LedgerEntry.id', + 'LedgerEntry.amount', + 'LedgerEntry.comment'), + //Models - 'DebitLedger' => array - ('fields' => array('DebitLedger.id', 'DebitLedger.sequence'), - 'Account' => array - ('fields' => array('Account.id', 'Account.name')), - ), + 'DebitLedger' => array + ('fields' => array('DebitLedger.id', 'DebitLedger.sequence'), + 'Account' => array + ('fields' => array('Account.id', 'Account.name')), + ), - 'CreditLedger' => array - ('fields' => array('CreditLedger.id', 'CreditLedger.sequence'), - 'Account' => array - ('fields' => array('Account.id', 'Account.name')), - ), - ), - ) - ); - $transaction = $this->Transaction->read(null, $id); - $this->Transaction->Behaviors->detach('Containable'); + 'CreditLedger' => array + ('fields' => array('CreditLedger.id', 'CreditLedger.sequence'), + 'Account' => array + ('fields' => array('Account.id', 'Account.name')), + ), + ), + ), + 'conditions' => array('Transaction.id' => $id), + )); // Figure out the transaction total $total = 0; diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index 9fcb630..6326447 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -152,16 +152,16 @@ class UnitsController extends AppController { $this->redirect(array('action'=>'')); } - $this->Unit->Behaviors->attach('Containable'); - $this->Unit->contain - (array(// Models - 'UnitSize', - 'Lease' => array('Customer'), - 'CurrentLease' => array('Customer') - ) - ); - $unit = $this->Unit->read(null, $id); - $this->Unit->Behaviors->detach('Containable'); + $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) { From 8ab8d087e64493b4f1344206cf4b76ce89392112 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 10 Jun 2009 21:12:59 +0000 Subject: [PATCH 091/717] Added the debug toolkit plugin, found on the bakery website. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@92 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 1 + site/plugins/debug_kit/README | 5 + .../debug_kit/controllers/components/empty | 0 .../controllers/components/toolbar.php | 471 +++++++++++++++ .../debug_kit/debug_kit_app_controller.php | 32 ++ .../plugins/debug_kit/debug_kit_app_model.php | 32 ++ site/plugins/debug_kit/models/empty | 0 .../controllers/components/toolbar.test.php | 323 +++++++++++ site/plugins/debug_kit/tests/cases/empty | 0 .../debug_kit/tests/cases/test_objects.php | 62 ++ .../cases/vendors/debug_kit_debugger.test.php | 157 +++++ .../tests/cases/vendors/fire_cake.test.php | 336 +++++++++++ .../tests/cases/views/debug.test.php | 144 +++++ .../views/helpers/fire_php_toobar.test.php | 137 +++++ .../cases/views/helpers/html_toolbar.test.php | 358 ++++++++++++ site/plugins/debug_kit/tests/fixtures/empty | 0 site/plugins/debug_kit/tests/groups/empty | 0 .../tests/test_app/vendors/test_panel.php | 33 ++ .../debug_kit/vendors/css/debug_toolbar.css | 165 ++++++ .../debug_kit/vendors/debug_kit_debugger.php | 226 ++++++++ site/plugins/debug_kit/vendors/fire_cake.php | 539 ++++++++++++++++++ .../debug_kit/vendors/img/cake.icon.png | Bin 0 -> 1041 bytes .../vendors/js/jquery_debug_toolbar.js | 84 +++ .../debug_kit/vendors/js/js_debug_toolbar.js | 212 +++++++ .../vendors/js/mootools_debug_toolbar.js | 95 +++ .../vendors/js/prototype_debug_toolbar.js | 95 +++ .../debug_kit/vendors/js/yui_debug_toolbar.js | 126 ++++ .../debug_kit/vendors/shells/benchmark.php | 79 +++ site/plugins/debug_kit/views/debug.php | 133 +++++ .../views/elements/debug_toolbar.ctp | 52 ++ site/plugins/debug_kit/views/elements/empty | 0 .../debug_kit/views/elements/log_panel.ctp | 48 ++ .../debug_kit/views/elements/memory_panel.ctp | 43 ++ .../views/elements/request_panel.ctp | 45 ++ .../views/elements/session_panel.ctp | 31 + .../views/elements/sql_log_panel.ctp | 40 ++ .../debug_kit/views/elements/timer_panel.ctp | 44 ++ .../views/elements/variables_panel.ctp | 35 ++ .../views/helpers/fire_php_toolbar.php | 79 +++ .../debug_kit/views/helpers/html_toolbar.php | 150 +++++ .../debug_kit/views/helpers/toolbar.php | 90 +++ 41 files changed, 4502 insertions(+) create mode 100644 site/plugins/debug_kit/README create mode 100644 site/plugins/debug_kit/controllers/components/empty create mode 100644 site/plugins/debug_kit/controllers/components/toolbar.php create mode 100644 site/plugins/debug_kit/debug_kit_app_controller.php create mode 100644 site/plugins/debug_kit/debug_kit_app_model.php create mode 100644 site/plugins/debug_kit/models/empty create mode 100644 site/plugins/debug_kit/tests/cases/controllers/components/toolbar.test.php create mode 100644 site/plugins/debug_kit/tests/cases/empty create mode 100644 site/plugins/debug_kit/tests/cases/test_objects.php create mode 100644 site/plugins/debug_kit/tests/cases/vendors/debug_kit_debugger.test.php create mode 100644 site/plugins/debug_kit/tests/cases/vendors/fire_cake.test.php create mode 100644 site/plugins/debug_kit/tests/cases/views/debug.test.php create mode 100644 site/plugins/debug_kit/tests/cases/views/helpers/fire_php_toobar.test.php create mode 100644 site/plugins/debug_kit/tests/cases/views/helpers/html_toolbar.test.php create mode 100644 site/plugins/debug_kit/tests/fixtures/empty create mode 100644 site/plugins/debug_kit/tests/groups/empty create mode 100644 site/plugins/debug_kit/tests/test_app/vendors/test_panel.php create mode 100644 site/plugins/debug_kit/vendors/css/debug_toolbar.css create mode 100644 site/plugins/debug_kit/vendors/debug_kit_debugger.php create mode 100644 site/plugins/debug_kit/vendors/fire_cake.php create mode 100644 site/plugins/debug_kit/vendors/img/cake.icon.png create mode 100644 site/plugins/debug_kit/vendors/js/jquery_debug_toolbar.js create mode 100644 site/plugins/debug_kit/vendors/js/js_debug_toolbar.js create mode 100644 site/plugins/debug_kit/vendors/js/mootools_debug_toolbar.js create mode 100644 site/plugins/debug_kit/vendors/js/prototype_debug_toolbar.js create mode 100644 site/plugins/debug_kit/vendors/js/yui_debug_toolbar.js create mode 100644 site/plugins/debug_kit/vendors/shells/benchmark.php create mode 100644 site/plugins/debug_kit/views/debug.php create mode 100644 site/plugins/debug_kit/views/elements/debug_toolbar.ctp create mode 100644 site/plugins/debug_kit/views/elements/empty create mode 100644 site/plugins/debug_kit/views/elements/log_panel.ctp create mode 100644 site/plugins/debug_kit/views/elements/memory_panel.ctp create mode 100644 site/plugins/debug_kit/views/elements/request_panel.ctp create mode 100644 site/plugins/debug_kit/views/elements/session_panel.ctp create mode 100644 site/plugins/debug_kit/views/elements/sql_log_panel.ctp create mode 100644 site/plugins/debug_kit/views/elements/timer_panel.ctp create mode 100644 site/plugins/debug_kit/views/elements/variables_panel.ctp create mode 100644 site/plugins/debug_kit/views/helpers/fire_php_toolbar.php create mode 100644 site/plugins/debug_kit/views/helpers/html_toolbar.php create mode 100644 site/plugins/debug_kit/views/helpers/toolbar.php diff --git a/site/app_controller.php b/site/app_controller.php index 46af502..188567c 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -36,6 +36,7 @@ */ class AppController extends Controller { var $helpers = array('Html', 'Format', 'Time'); + var $components = array('DebugKit.Toolbar'); function sideMenuLinks() { return array( diff --git a/site/plugins/debug_kit/README b/site/plugins/debug_kit/README new file mode 100644 index 0000000..4f31f67 --- /dev/null +++ b/site/plugins/debug_kit/README @@ -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. \ No newline at end of file diff --git a/site/plugins/debug_kit/controllers/components/empty b/site/plugins/debug_kit/controllers/components/empty new file mode 100644 index 0000000..e69de29 diff --git a/site/plugins/debug_kit/controllers/components/toolbar.php b/site/plugins/debug_kit/controllers/components/toolbar.php new file mode 100644 index 0000000..0b72acb --- /dev/null +++ b/site/plugins/debug_kit/controllers/components/toolbar.php @@ -0,0 +1,471 @@ + + * 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); + } +} +?> \ No newline at end of file diff --git a/site/plugins/debug_kit/debug_kit_app_controller.php b/site/plugins/debug_kit/debug_kit_app_controller.php new file mode 100644 index 0000000..0a63efb --- /dev/null +++ b/site/plugins/debug_kit/debug_kit_app_controller.php @@ -0,0 +1,32 @@ + + * 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 { + +} +?> \ No newline at end of file diff --git a/site/plugins/debug_kit/debug_kit_app_model.php b/site/plugins/debug_kit/debug_kit_app_model.php new file mode 100644 index 0000000..ee7af0b --- /dev/null +++ b/site/plugins/debug_kit/debug_kit_app_model.php @@ -0,0 +1,32 @@ + + * 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 { + +} +?> \ No newline at end of file diff --git a/site/plugins/debug_kit/models/empty b/site/plugins/debug_kit/models/empty new file mode 100644 index 0000000..e69de29 diff --git a/site/plugins/debug_kit/tests/cases/controllers/components/toolbar.test.php b/site/plugins/debug_kit/tests/cases/controllers/components/toolbar.test.php new file mode 100644 index 0000000..1435303 --- /dev/null +++ b/site/plugins/debug_kit/tests/cases/controllers/components/toolbar.test.php @@ -0,0 +1,323 @@ + + * 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(); + } + } +} +?> \ No newline at end of file diff --git a/site/plugins/debug_kit/tests/cases/empty b/site/plugins/debug_kit/tests/cases/empty new file mode 100644 index 0000000..e69de29 diff --git a/site/plugins/debug_kit/tests/cases/test_objects.php b/site/plugins/debug_kit/tests/cases/test_objects.php new file mode 100644 index 0000000..d7a91dc --- /dev/null +++ b/site/plugins/debug_kit/tests/cases/test_objects.php @@ -0,0 +1,62 @@ + + * 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; + } +} + +?> diff --git a/site/plugins/debug_kit/tests/cases/vendors/debug_kit_debugger.test.php b/site/plugins/debug_kit/tests/cases/vendors/debug_kit_debugger.test.php new file mode 100644 index 0000000..79bbe8b --- /dev/null +++ b/site/plugins/debug_kit/tests/cases/vendors/debug_kit_debugger.test.php @@ -0,0 +1,157 @@ + + * 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); + } + +} +?> \ No newline at end of file diff --git a/site/plugins/debug_kit/tests/cases/vendors/fire_cake.test.php b/site/plugins/debug_kit/tests/cases/vendors/fire_cake.test.php new file mode 100644 index 0000000..513fb96 --- /dev/null +++ b/site/plugins/debug_kit/tests/cases/vendors/fire_cake.test.php @@ -0,0 +1,336 @@ + + * 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(); + } +} +?> \ No newline at end of file diff --git a/site/plugins/debug_kit/tests/cases/views/debug.test.php b/site/plugins/debug_kit/tests/cases/views/debug.test.php new file mode 100644 index 0000000..916a67d --- /dev/null +++ b/site/plugins/debug_kit/tests/cases/views/debug.test.php @@ -0,0 +1,144 @@ + + * 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); + } +} +?> \ No newline at end of file diff --git a/site/plugins/debug_kit/tests/cases/views/helpers/fire_php_toobar.test.php b/site/plugins/debug_kit/tests/cases/views/helpers/fire_php_toobar.test.php new file mode 100644 index 0000000..60206dc --- /dev/null +++ b/site/plugins/debug_kit/tests/cases/views/helpers/fire_php_toobar.test.php @@ -0,0 +1,137 @@ + + * 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(); + } +} +?> \ No newline at end of file diff --git a/site/plugins/debug_kit/tests/cases/views/helpers/html_toolbar.test.php b/site/plugins/debug_kit/tests/cases/views/helpers/html_toolbar.test.php new file mode 100644 index 0000000..d924c9e --- /dev/null +++ b/site/plugins/debug_kit/tests/cases/views/helpers/html_toolbar.test.php @@ -0,0 +1,358 @@ + + * 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'), + 'assertTags($result, $expected); + + $in = null; + $result = $this->Toolbar->makeNeatArray($in); + $expected = array( + 'ul' => array('class' => 'neat-array depth-0'), + 'assertTags($result, $expected); + + $in = true; + $result = $this->Toolbar->makeNeatArray($in); + $expected = array( + 'ul' => array('class' => 'neat-array depth-0'), + 'assertTags($result, $expected); + + $in = array('key' => 'value'); + $result = $this->Toolbar->makeNeatArray($in); + $expected = array( + 'ul' => array('class' => 'neat-array depth-0'), + 'assertTags($result, $expected); + + $in = array('key' => null); + $result = $this->Toolbar->makeNeatArray($in); + $expected = array( + 'ul' => array('class' => 'neat-array depth-0'), + 'assertTags($result, $expected); + + $in = array('key' => 'value', 'foo' => 'bar'); + $result = $this->Toolbar->makeNeatArray($in); + $expected = array( + 'ul' => array('class' => 'neat-array depth-0'), + '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'), + ' array('class' => 'neat-array depth-1')), + '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'), + ' array('class' => 'neat-array depth-1')), + ' array('class' => 'neat-array depth-1')), + 'assertTags($result, $expected); + + $result = $this->Toolbar->makeNeatArray($in, 2); + $expected = array( + 'ul' => array('class' => 'neat-array depth-0 expanded'), + ' array('class' => 'neat-array depth-1 expanded')), + ' array('class' => 'neat-array depth-1 expanded')), + 'assertTags($result, $expected); + + $in = array('key' => 'value', 'array' => array()); + $result = $this->Toolbar->makeNeatArray($in); + $expected = array( + 'ul' => array('class' => 'neat-array depth-0'), + '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('#
.+
#', $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('#\s?#', $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('#\s?#', $result); + } +/** + * test message creation + * + * @return void + */ + function testMessage() { + $result = $this->Toolbar->message('test', 'one, two'); + $expected = array( + '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')), + ' array('class' => 'even')), + '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(); + } +} +?> \ No newline at end of file diff --git a/site/plugins/debug_kit/tests/fixtures/empty b/site/plugins/debug_kit/tests/fixtures/empty new file mode 100644 index 0000000..e69de29 diff --git a/site/plugins/debug_kit/tests/groups/empty b/site/plugins/debug_kit/tests/groups/empty new file mode 100644 index 0000000..e69de29 diff --git a/site/plugins/debug_kit/tests/test_app/vendors/test_panel.php b/site/plugins/debug_kit/tests/test_app/vendors/test_panel.php new file mode 100644 index 0000000..26a3de9 --- /dev/null +++ b/site/plugins/debug_kit/tests/test_app/vendors/test_panel.php @@ -0,0 +1,33 @@ + + * 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; + } +} +?> \ No newline at end of file diff --git a/site/plugins/debug_kit/vendors/css/debug_toolbar.css b/site/plugins/debug_kit/vendors/css/debug_toolbar.css new file mode 100644 index 0000000..cbcb274 --- /dev/null +++ b/site/plugins/debug_kit/vendors/css/debug_toolbar.css @@ -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; +} + diff --git a/site/plugins/debug_kit/vendors/debug_kit_debugger.php b/site/plugins/debug_kit/vendors/debug_kit_debugger.php new file mode 100644 index 0000000..a1d111f --- /dev/null +++ b/site/plugins/debug_kit/vendors/debug_kit_debugger.php @@ -0,0 +1,226 @@ + + * 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'); +?> \ No newline at end of file diff --git a/site/plugins/debug_kit/vendors/fire_cake.php b/site/plugins/debug_kit/vendors/fire_cake.php new file mode 100644 index 0000000..6984439 --- /dev/null +++ b/site/plugins/debug_kit/vendors/fire_cake.php @@ -0,0 +1,539 @@ + + * 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); + } +} +?> \ No newline at end of file diff --git a/site/plugins/debug_kit/vendors/img/cake.icon.png b/site/plugins/debug_kit/vendors/img/cake.icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f56f321f71bd926a458b19987e8f65ded42a78af GIT binary patch literal 1041 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqJQak|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+m>B|mLR|A3%KrcV&tvbiaKqM%=Qllg_Tup2$vh6eht8bu zn>~5a@@j40aG&zV;N&<~3s<1YqhK@yhEoW%K9HRa^p8MEkY6w`BOn8Y2gPB_0xXtIONjz&1(6 zW#_HEiMA*1TJr2k6hBu>S=S@M5%e-?jUp2x_>AnL$t^Uh4B925nf Lu6{1-oD!M + * 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); \ No newline at end of file diff --git a/site/plugins/debug_kit/vendors/js/js_debug_toolbar.js b/site/plugins/debug_kit/vendors/js/js_debug_toolbar.js new file mode 100644 index 0000000..9991d47 --- /dev/null +++ b/site/plugins/debug_kit/vendors/js/js_debug_toolbar.js @@ -0,0 +1,212 @@ +/* SVN FILE: $Id$ */ +/** + * Debug Toolbar Javascript. + * + * Long description here. + * + * PHP versions 4 and 5 + * + * CakePHP : Rapid Development Framework + * 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(); \ No newline at end of file diff --git a/site/plugins/debug_kit/vendors/js/mootools_debug_toolbar.js b/site/plugins/debug_kit/vendors/js/mootools_debug_toolbar.js new file mode 100644 index 0000000..2f858c6 --- /dev/null +++ b/site/plugins/debug_kit/vendors/js/mootools_debug_toolbar.js @@ -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 + * 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'); + } + }); + } +}); \ No newline at end of file diff --git a/site/plugins/debug_kit/vendors/js/prototype_debug_toolbar.js b/site/plugins/debug_kit/vendors/js/prototype_debug_toolbar.js new file mode 100644 index 0000000..8e1e63f --- /dev/null +++ b/site/plugins/debug_kit/vendors/js/prototype_debug_toolbar.js @@ -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 + * 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(); + } + } + }); + }; + }); + } + +}); diff --git a/site/plugins/debug_kit/vendors/js/yui_debug_toolbar.js b/site/plugins/debug_kit/vendors/js/yui_debug_toolbar.js new file mode 100644 index 0000000..91571a1 --- /dev/null +++ b/site/plugins/debug_kit/vendors/js/yui_debug_toolbar.js @@ -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 + * 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); \ No newline at end of file diff --git a/site/plugins/debug_kit/vendors/shells/benchmark.php b/site/plugins/debug_kit/vendors/shells/benchmark.php new file mode 100644 index 0000000..bac6d68 --- /dev/null +++ b/site/plugins/debug_kit/vendors/shells/benchmark.php @@ -0,0 +1,79 @@ + + * 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 = <<out($out); + } +} + +?> \ No newline at end of file diff --git a/site/plugins/debug_kit/views/debug.php b/site/plugins/debug_kit/views/debug.php new file mode 100644 index 0000000..d296bc6 --- /dev/null +++ b/site/plugins/debug_kit/views/debug.php @@ -0,0 +1,133 @@ + + * 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) { + 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)); + } + 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) { + DebugKitDebugger::startTimer('viewRender', __('Rendering View', true)); + $out = parent::render($action, $layout, $file); + DebugKitDebugger::stopTimer('viewRender'); + DebugKitDebugger::stopTimer('controllerRender'); + + if (isset($this->loaded['toolbar'])) { + $this->loaded['toolbar']->postRender(); + } + //Temporary work around to hide the SQL dump at page bottom + Configure::write('debug', 0); + 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; + } +} +?> \ No newline at end of file diff --git a/site/plugins/debug_kit/views/elements/debug_toolbar.ctp b/site/plugins/debug_kit/views/elements/debug_toolbar.ctp new file mode 100644 index 0000000..a706fa3 --- /dev/null +++ b/site/plugins/debug_kit/views/elements/debug_toolbar.ctp @@ -0,0 +1,52 @@ + + * 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 + */ +?> +
+ +

+ + + +
\ No newline at end of file diff --git a/site/plugins/debug_kit/views/elements/empty b/site/plugins/debug_kit/views/elements/empty new file mode 100644 index 0000000..e69de29 diff --git a/site/plugins/debug_kit/views/elements/log_panel.ctp b/site/plugins/debug_kit/views/elements/log_panel.ctp new file mode 100644 index 0000000..0a075ce --- /dev/null +++ b/site/plugins/debug_kit/views/elements/log_panel.ctp @@ -0,0 +1,48 @@ + + * 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 + */ +?> +

+
+ $logs): ?> +

+ 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: ?> +

+ + +
\ No newline at end of file diff --git a/site/plugins/debug_kit/views/elements/memory_panel.ctp b/site/plugins/debug_kit/views/elements/memory_panel.ctp new file mode 100644 index 0000000..df9e059 --- /dev/null +++ b/site/plugins/debug_kit/views/elements/memory_panel.ctp @@ -0,0 +1,43 @@ + + * 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 + */ +?> +

+
+ message( + __('Current Memory Use',true), + $number->toReadableSize(DebugKitDebugger::getMemoryUse()) + );?> +
+
+message( + __('Peak Memory Use', true), + $number->toReadableSize(DebugKitDebugger::getPeakMemoryUse()) + ); +?>
\ No newline at end of file diff --git a/site/plugins/debug_kit/views/elements/request_panel.ctp b/site/plugins/debug_kit/views/elements/request_panel.ctp new file mode 100644 index 0000000..8da4289 --- /dev/null +++ b/site/plugins/debug_kit/views/elements/request_panel.ctp @@ -0,0 +1,45 @@ + + * 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 + */ +?> +

+

Cake Params

+makeNeatArray($content['params']); ?> + +

$_GET

+makeNeatArray($content['get']); ?> + +

Cookie

+ + makeNeatArray($content['cookie']); ?> + +

To view Cookies, add CookieComponent to Controller + + +

+makeNeatArray($content['currentRoute']); ?> \ No newline at end of file diff --git a/site/plugins/debug_kit/views/elements/session_panel.ctp b/site/plugins/debug_kit/views/elements/session_panel.ctp new file mode 100644 index 0000000..003032a --- /dev/null +++ b/site/plugins/debug_kit/views/elements/session_panel.ctp @@ -0,0 +1,31 @@ + + * 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 + */ +?> +

+makeNeatArray($content); ?> \ No newline at end of file diff --git a/site/plugins/debug_kit/views/elements/sql_log_panel.ctp b/site/plugins/debug_kit/views/elements/sql_log_panel.ctp new file mode 100644 index 0000000..cda2d5a --- /dev/null +++ b/site/plugins/debug_kit/views/elements/sql_log_panel.ctp @@ -0,0 +1,40 @@ + + * 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 + */ +?> +

+ + $queryLog) : ?> +
+

+ +
+ + +

+ \ No newline at end of file diff --git a/site/plugins/debug_kit/views/elements/timer_panel.ctp b/site/plugins/debug_kit/views/elements/timer_panel.ctp new file mode 100644 index 0000000..1ec74d6 --- /dev/null +++ b/site/plugins/debug_kit/views/elements/timer_panel.ctp @@ -0,0 +1,44 @@ + + * 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(); +?> +

+

+ precision(DebugKitDebugger::requestTime(), 6)); ?> + message(__('Total Request Time:', true), $totalTime)?> +

+ + $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')); ?> \ No newline at end of file diff --git a/site/plugins/debug_kit/views/elements/variables_panel.ctp b/site/plugins/debug_kit/views/elements/variables_panel.ctp new file mode 100644 index 0000000..95dc9bf --- /dev/null +++ b/site/plugins/debug_kit/views/elements/variables_panel.ctp @@ -0,0 +1,35 @@ + + * 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 + */ +?> +

+viewVars; + unset($vars['debugToolbarPanels'], $vars['debugToolbarJavascript']); +?> +makeNeatArray($vars); ?> \ No newline at end of file diff --git a/site/plugins/debug_kit/views/helpers/fire_php_toolbar.php b/site/plugins/debug_kit/views/helpers/fire_php_toolbar.php new file mode 100644 index 0000000..630a707 --- /dev/null +++ b/site/plugins/debug_kit/views/helpers/fire_php_toolbar.php @@ -0,0 +1,79 @@ + + * 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); + } +} +?> \ No newline at end of file diff --git a/site/plugins/debug_kit/views/helpers/html_toolbar.php b/site/plugins/debug_kit/views/helpers/html_toolbar.php new file mode 100644 index 0000000..fc58014 --- /dev/null +++ b/site/plugins/debug_kit/views/helpers/html_toolbar.php @@ -0,0 +1,150 @@ + + * 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 = "
    "; + if (!is_array($values)) { + if (is_bool($values)) { + $values = array($values); + } + if (is_null($values)) { + $values = array(null); + } + } + foreach ($values as $key => $value) { + $out .= '
  • ' . $key . ''; + 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 .= '
  • '; + } + $out .= '
'; + return $out; + } +/** + * Create an HTML message + * + * @param string $label label content + * @param string $message message content + * @return string + */ + function message($label, $message) { + return sprintf('

%s %s

', $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 = ''; + if (!empty($headers)) { + $out .= $this->Html->tableHeaders($headers); + } + $out .= $this->Html->tableCells($rows, array('class' => 'odd'), array('class' => 'even')); + $out .= '
'; + 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('##', $view->output)) { + $view->output = preg_replace('##', $head . "\n", $view->output, 1); + } + $toolbar = $view->element('debug_toolbar', array('plugin' => 'debug_kit', 'disableTimer' => true)); + if (preg_match('##', $view->output)) { + $view->output = preg_replace('##', $toolbar . "\n", $view->output, 1); + } + } +} +?> \ No newline at end of file diff --git a/site/plugins/debug_kit/views/helpers/toolbar.php b/site/plugins/debug_kit/views/helpers/toolbar.php new file mode 100644 index 0000000..c107730 --- /dev/null +++ b/site/plugins/debug_kit/views/helpers/toolbar.php @@ -0,0 +1,90 @@ + + * 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(); + } +} \ No newline at end of file From 99263920a319231ee92df7f978025fb6ec098525 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 10 Jun 2009 21:14:26 +0000 Subject: [PATCH 092/717] Fixed to handle the possibility of a NULL monetary source, and tidied the formatting a bit. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@93 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/ledger_entries/view.ctp | 74 +++++++++++++++++------------- 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/site/views/ledger_entries/view.ctp b/site/views/ledger_entries/view.ctp index 7b04524..ef04f2a 100644 --- a/site/views/ledger_entries/view.ctp +++ b/site/views/ledger_entries/view.ctp @@ -12,37 +12,49 @@ * LedgerEntry Detail Main Section */ -$rows = array(array('ID', $entry['LedgerEntry']['id']), - array('Transaction', $html->link('#'.$entry['Transaction']['id'], - array('controller' => 'transactions', - 'action' => 'view', - $entry['Transaction']['id']))), - array('Timestamp', FormatHelper::datetime($entry['Transaction']['stamp'])), - array('Source', $entry['MonetarySource']['id']), - array('Amount', FormatHelper::currency($entry['LedgerEntry']['amount'])), - array('Debit', ($html->link($entry['DebitLedger']['Account']['name'], - array('controller' => 'accounts', - 'action' => 'view', - $entry['DebitLedger']['Account']['id'])) - . ' (' - . $html->link('#' . $entry['DebitLedger']['Account']['id'] - . '-' . $entry['DebitLedger']['sequence'], - array('controller' => 'ledgers', - 'action' => 'view', - $entry['DebitLedger']['id'])) - . ')')), - array('Credit', ($html->link($entry['CreditLedger']['Account']['name'], - array('controller' => 'accounts', - 'action' => 'view', - $entry['CreditLedger']['Account']['id'])) - . ' (' - . $html->link('#' . $entry['CreditLedger']['Account']['id'] - . '-' . $entry['CreditLedger']['sequence'], - array('controller' => 'ledgers', - 'action' => 'view', - $entry['CreditLedger']['id'])) - . ')')), - array('Comment', $entry['LedgerEntry']['comment'])); +$transaction = $entry['Transaction']; +$debit_ledger = $entry['DebitLedger']; +$credit_ledger = $entry['CreditLedger']; +$source = $entry['MonetarySource']; +$entry = $entry['LedgerEntry']; + +$rows = array(array('ID', $entry['id']), + array('Transaction', $html->link('#'.$transaction['id'], + array('controller' => 'transactions', + 'action' => 'view', + $transaction['id']))), + array('Timestamp', FormatHelper::datetime($transaction['stamp'])), + array('Monetary Source', (isset($source['id']) + ? $html->link('#'.$source['id'], + array('controller' => 'monetary_sources', + 'action' => 'view', + $source['id'])) + : null)), + array('Amount', FormatHelper::currency($entry['amount'])), + array('Debit', ($html->link($debit_ledger['Account']['name'], + array('controller' => 'accounts', + 'action' => 'view', + $debit_ledger['Account']['id'])) + . ' (' + . $html->link('#' . $debit_ledger['Account']['id'] + . '-' . $debit_ledger['sequence'], + array('controller' => 'ledgers', + 'action' => 'view', + $debit_ledger['id'])) + . ')')), + array('Credit', ($html->link($credit_ledger['Account']['name'], + array('controller' => 'accounts', + 'action' => 'view', + $credit_ledger['Account']['id'])) + . ' (' + . $html->link('#' . $credit_ledger['Account']['id'] + . '-' . $credit_ledger['sequence'], + array('controller' => 'ledgers', + 'action' => 'view', + $credit_ledger['id'])) + . ')')), + array('Comment', $entry['comment'])); + echo $this->element('table', array('class' => 'item ledger-entry detail', From 3d89da7a61df49f45e0b5cb2df865fcfb64a284d Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 10 Jun 2009 21:24:05 +0000 Subject: [PATCH 093/717] Added a monetary_sources controller/view. Don't know if we'll really want this, since it might just make the most sense to embed its actions within ledger entry. We'll keep it for now. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@94 97e9348a-65ac-dc4b-aefc-98561f571b83 --- .../monetary_sources_controller.php | 47 +++++++++++++++ site/views/monetary_sources/view.ctp | 57 +++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 site/controllers/monetary_sources_controller.php create mode 100644 site/views/monetary_sources/view.ctp diff --git a/site/controllers/monetary_sources_controller.php b/site/controllers/monetary_sources_controller.php new file mode 100644 index 0000000..aa294d5 --- /dev/null +++ b/site/controllers/monetary_sources_controller.php @@ -0,0 +1,47 @@ + 100, + 'group' => 'Entry.id', + 'order' => array('Entry.stamp' => 'ASC')); + + 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 MonetarySource and related fields + $monetary_source = $this->MonetarySource->find + ('first', array + ('contain' => array + ('MonetaryType', + ), + )); + + // Prepare to render. + $title = "Monetary Source #{$monetary_source['MonetarySource']['id']}"; + $this->set(compact('monetary_source', 'title')); + } +} diff --git a/site/views/monetary_sources/view.ctp b/site/views/monetary_sources/view.ctp new file mode 100644 index 0000000..68d82f4 --- /dev/null +++ b/site/views/monetary_sources/view.ctp @@ -0,0 +1,57 @@ + + +
+ +link(array('jquery'), false); + + +$type = $monetarySource['MonetaryType']; +$source = $monetarySource['MonetarySource']; + +$rows = array(array('ID', $source['id']), + array('Name', $source['name']), + array('Type', $type['name']), + array('Tillable', $type['tillable'] ? 'Yes' : 'No'), + array('Comment', $source['comment'])); + +echo $this->element('table', + array('class' => 'item monetary-source detail', + 'caption' => 'Monetary Source Detail', + 'rows' => $rows, + 'column_class' => array('field', 'value'))); + + +/********************************************************************** + * MonetarySource Info Box + */ + +?> +
+
+ +
+ +
+ +
From 13b2283d761cd69d08632cbb800b991590435b34 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 10 Jun 2009 23:39:40 +0000 Subject: [PATCH 094/717] Removed the unintended javascript addition from the last checkin. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@95 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/monetary_sources/view.ctp | 2 -- 1 file changed, 2 deletions(-) diff --git a/site/views/monetary_sources/view.ctp b/site/views/monetary_sources/view.ctp index 68d82f4..b89180f 100644 --- a/site/views/monetary_sources/view.ctp +++ b/site/views/monetary_sources/view.ctp @@ -12,8 +12,6 @@ * MonetarySource Detail Main Section */ -$javascript->link(array('jquery'), false); - $type = $monetarySource['MonetaryType']; $source = $monetarySource['MonetarySource']; From 2c224dbc6215d2e3a1ade5dc5fb33f3b1847a822 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 11 Jun 2009 00:09:10 +0000 Subject: [PATCH 095/717] Added the jquery and jquery-ui libraries to the application. Added jquery inclusion in the default layout, on the presumption that it will get used on most pages. I'll remove it and pepper it where necessary if that proves not to be the case. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@96 97e9348a-65ac-dc4b-aefc-98561f571b83 --- .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 120 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 111 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 110 bytes .../images/ui-bg_glass_75_ffffff_1x400.png | Bin 0 -> 107 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 101 bytes .../ui-bg_inset-soft_95_fef1ec_1x100.png | Bin 0 -> 123 bytes .../base/images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../base/images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../base/images/ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes .../base/images/ui-icons_888888_256x240.png | Bin 0 -> 4369 bytes .../base/images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes site/vendors/css/jquery/base/ui.accordion.css | 9 + site/vendors/css/jquery/base/ui.all.css | 2 + site/vendors/css/jquery/base/ui.base.css | 8 + site/vendors/css/jquery/base/ui.core.css | 37 + .../vendors/css/jquery/base/ui.datepicker.css | 62 + site/vendors/css/jquery/base/ui.dialog.css | 13 + .../css/jquery/base/ui.progressbar.css | 4 + site/vendors/css/jquery/base/ui.resizable.css | 13 + site/vendors/css/jquery/base/ui.slider.css | 17 + site/vendors/css/jquery/base/ui.tabs.css | 11 + site/vendors/css/jquery/base/ui.theme.css | 245 + .../ui-bg_diagonals-thick_15_0b3e6f_40x40.png | Bin 0 -> 260 bytes .../ui-bg_dots-medium_30_0b58a2_4x4.png | Bin 0 -> 98 bytes .../images/ui-bg_dots-small_20_333333_2x2.png | Bin 0 -> 83 bytes .../images/ui-bg_dots-small_30_a32d00_2x2.png | Bin 0 -> 84 bytes .../images/ui-bg_dots-small_40_00498f_2x2.png | Bin 0 -> 83 bytes .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_40_292929_40x100.png | Bin 0 -> 180 bytes .../ui-bg_gloss-wave_20_111111_500x100.png | Bin 0 -> 1620 bytes .../dotluv/images/ui-icons_00498f_256x240.png | Bin 0 -> 4379 bytes .../dotluv/images/ui-icons_98d2fb_256x240.png | Bin 0 -> 4379 bytes .../dotluv/images/ui-icons_9ccdfc_256x240.png | Bin 0 -> 4379 bytes .../dotluv/images/ui-icons_ffffff_256x240.png | Bin 0 -> 4379 bytes site/vendors/css/jquery/dotluv/ui.all.css | 406 + .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 144 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 111 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 151 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 101 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_454545_256x240.png | Bin 0 -> 5355 bytes .../images/ui-icons_888888_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes site/vendors/css/jquery/smoothness/ui.all.css | 406 + .../images/ui-bg_flat_55_999999_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_75_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_glass_45_0078ae_1x400.png | Bin 0 -> 136 bytes .../images/ui-bg_glass_55_f8da4e_1x400.png | Bin 0 -> 131 bytes .../images/ui-bg_glass_75_79c9ec_1x400.png | Bin 0 -> 132 bytes .../ui-bg_gloss-wave_45_e14f1c_500x100.png | Bin 0 -> 3649 bytes .../ui-bg_gloss-wave_50_6eac2c_500x100.png | Bin 0 -> 4256 bytes .../ui-bg_gloss-wave_75_2191c0_500x100.png | Bin 0 -> 3457 bytes .../ui-bg_inset-hard_100_fcfdfd_1x100.png | Bin 0 -> 88 bytes .../start/images/ui-icons_0078ae_256x240.png | Bin 0 -> 4379 bytes .../start/images/ui-icons_056b93_256x240.png | Bin 0 -> 4379 bytes .../start/images/ui-icons_d8e7f3_256x240.png | Bin 0 -> 4379 bytes .../start/images/ui-icons_e0fdff_256x240.png | Bin 0 -> 4379 bytes .../start/images/ui-icons_f5e175_256x240.png | Bin 0 -> 4379 bytes .../start/images/ui-icons_f7a50d_256x240.png | Bin 0 -> 5399 bytes .../start/images/ui-icons_fcd113_256x240.png | Bin 0 -> 4379 bytes site/vendors/css/jquery/start/ui.all.css | 406 + site/vendors/js/jquery/jquery-ui.js | 9133 +++++++++++++++++ site/vendors/js/jquery/jquery.js | 4376 ++++++++ site/views/layouts/default.ctp | 8 +- 73 files changed, 15155 insertions(+), 1 deletion(-) create mode 100644 site/vendors/css/jquery/base/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 site/vendors/css/jquery/base/images/ui-bg_flat_75_ffffff_40x100.png create mode 100644 site/vendors/css/jquery/base/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 site/vendors/css/jquery/base/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 site/vendors/css/jquery/base/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 site/vendors/css/jquery/base/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 site/vendors/css/jquery/base/images/ui-bg_glass_75_ffffff_1x400.png create mode 100644 site/vendors/css/jquery/base/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 site/vendors/css/jquery/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 site/vendors/css/jquery/base/images/ui-bg_inset-soft_95_fef1ec_1x100.png create mode 100644 site/vendors/css/jquery/base/images/ui-icons_222222_256x240.png create mode 100644 site/vendors/css/jquery/base/images/ui-icons_2e83ff_256x240.png create mode 100644 site/vendors/css/jquery/base/images/ui-icons_454545_256x240.png create mode 100644 site/vendors/css/jquery/base/images/ui-icons_888888_256x240.png create mode 100644 site/vendors/css/jquery/base/images/ui-icons_cd0a0a_256x240.png create mode 100644 site/vendors/css/jquery/base/ui.accordion.css create mode 100644 site/vendors/css/jquery/base/ui.all.css create mode 100644 site/vendors/css/jquery/base/ui.base.css create mode 100644 site/vendors/css/jquery/base/ui.core.css create mode 100644 site/vendors/css/jquery/base/ui.datepicker.css create mode 100644 site/vendors/css/jquery/base/ui.dialog.css create mode 100644 site/vendors/css/jquery/base/ui.progressbar.css create mode 100644 site/vendors/css/jquery/base/ui.resizable.css create mode 100644 site/vendors/css/jquery/base/ui.slider.css create mode 100644 site/vendors/css/jquery/base/ui.tabs.css create mode 100644 site/vendors/css/jquery/base/ui.theme.css create mode 100644 site/vendors/css/jquery/dotluv/images/ui-bg_diagonals-thick_15_0b3e6f_40x40.png create mode 100644 site/vendors/css/jquery/dotluv/images/ui-bg_dots-medium_30_0b58a2_4x4.png create mode 100644 site/vendors/css/jquery/dotluv/images/ui-bg_dots-small_20_333333_2x2.png create mode 100644 site/vendors/css/jquery/dotluv/images/ui-bg_dots-small_30_a32d00_2x2.png create mode 100644 site/vendors/css/jquery/dotluv/images/ui-bg_dots-small_40_00498f_2x2.png create mode 100644 site/vendors/css/jquery/dotluv/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 site/vendors/css/jquery/dotluv/images/ui-bg_flat_40_292929_40x100.png create mode 100644 site/vendors/css/jquery/dotluv/images/ui-bg_gloss-wave_20_111111_500x100.png create mode 100644 site/vendors/css/jquery/dotluv/images/ui-icons_00498f_256x240.png create mode 100644 site/vendors/css/jquery/dotluv/images/ui-icons_98d2fb_256x240.png create mode 100644 site/vendors/css/jquery/dotluv/images/ui-icons_9ccdfc_256x240.png create mode 100644 site/vendors/css/jquery/dotluv/images/ui-icons_ffffff_256x240.png create mode 100644 site/vendors/css/jquery/dotluv/ui.all.css create mode 100644 site/vendors/css/jquery/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 site/vendors/css/jquery/smoothness/images/ui-bg_flat_75_ffffff_40x100.png create mode 100644 site/vendors/css/jquery/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 site/vendors/css/jquery/smoothness/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 site/vendors/css/jquery/smoothness/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 site/vendors/css/jquery/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 site/vendors/css/jquery/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 site/vendors/css/jquery/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 site/vendors/css/jquery/smoothness/images/ui-icons_222222_256x240.png create mode 100644 site/vendors/css/jquery/smoothness/images/ui-icons_2e83ff_256x240.png create mode 100644 site/vendors/css/jquery/smoothness/images/ui-icons_454545_256x240.png create mode 100644 site/vendors/css/jquery/smoothness/images/ui-icons_888888_256x240.png create mode 100644 site/vendors/css/jquery/smoothness/images/ui-icons_cd0a0a_256x240.png create mode 100644 site/vendors/css/jquery/smoothness/ui.all.css create mode 100644 site/vendors/css/jquery/start/images/ui-bg_flat_55_999999_40x100.png create mode 100644 site/vendors/css/jquery/start/images/ui-bg_flat_75_aaaaaa_40x100.png create mode 100644 site/vendors/css/jquery/start/images/ui-bg_glass_45_0078ae_1x400.png create mode 100644 site/vendors/css/jquery/start/images/ui-bg_glass_55_f8da4e_1x400.png create mode 100644 site/vendors/css/jquery/start/images/ui-bg_glass_75_79c9ec_1x400.png create mode 100644 site/vendors/css/jquery/start/images/ui-bg_gloss-wave_45_e14f1c_500x100.png create mode 100644 site/vendors/css/jquery/start/images/ui-bg_gloss-wave_50_6eac2c_500x100.png create mode 100644 site/vendors/css/jquery/start/images/ui-bg_gloss-wave_75_2191c0_500x100.png create mode 100644 site/vendors/css/jquery/start/images/ui-bg_inset-hard_100_fcfdfd_1x100.png create mode 100644 site/vendors/css/jquery/start/images/ui-icons_0078ae_256x240.png create mode 100644 site/vendors/css/jquery/start/images/ui-icons_056b93_256x240.png create mode 100644 site/vendors/css/jquery/start/images/ui-icons_d8e7f3_256x240.png create mode 100644 site/vendors/css/jquery/start/images/ui-icons_e0fdff_256x240.png create mode 100644 site/vendors/css/jquery/start/images/ui-icons_f5e175_256x240.png create mode 100644 site/vendors/css/jquery/start/images/ui-icons_f7a50d_256x240.png create mode 100644 site/vendors/css/jquery/start/images/ui-icons_fcd113_256x240.png create mode 100644 site/vendors/css/jquery/start/ui.all.css create mode 100644 site/vendors/js/jquery/jquery-ui.js create mode 100644 site/vendors/js/jquery/jquery.js diff --git a/site/vendors/css/jquery/base/images/ui-bg_flat_0_aaaaaa_40x100.png b/site/vendors/css/jquery/base/images/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..5b5dab2ab7b1c50dea9cfe73dc5a269a92d2d4b4 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FscKIb$B>N1x91EQ4=4yQ7#`R^ z$vje}bP0l+XkK DSH>_4 literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/base/images/ui-bg_flat_75_ffffff_40x100.png b/site/vendors/css/jquery/base/images/ui-bg_flat_75_ffffff_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..ac8b229af950c29356abf64a6c4aa894575445f0 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FsY*{5$B>N1x91EQ4=4yQYz+E8 zPo9&<{J;c_6SHRil>2s{Zw^OT)6@jj2u|u!(plXsM>LJD`vD!n;OXk;vd$@?2>^GI BH@yG= literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/base/images/ui-bg_glass_55_fbf9ee_1x400.png b/site/vendors/css/jquery/base/images/ui-bg_glass_55_fbf9ee_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..ad3d6346e00f246102f72f2e026ed0491988b394 GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnour0hLi978O6-<~(*I$*%ybaDOn z{W;e!B}_MSUQoPXhYd^Y6RUoS1yepnPx`2Kz)7OXQG!!=-jY=F+d2OOy?#DnJ32>z UEim$g7SJdLPgg&ebxsLQ09~*s;{X5v literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/base/images/ui-bg_glass_65_ffffff_1x400.png b/site/vendors/css/jquery/base/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..42ccba269b6e91bef12ad0fa18be651b5ef0ee68 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouqzpV=978O6-=0?FV^9z|eBtf= z|7WztIJ;WT>{+tN>ySr~=F{k$>;_x^_y?afmf9pRKH0)6?eSP?3s5hEr>mdKI;Vst E0O;M1& literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/base/images/ui-bg_glass_75_dadada_1x400.png b/site/vendors/css/jquery/base/images/ui-bg_glass_75_dadada_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..5a46b47cb16631068aee9e0bd61269fc4e95e5cd GIT binary patch literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq|7{B978O6lPf+wIa#m9#>Unb zm^4K~wN3Zq+uPMaW978O6-<~?i$)F&>d~nX+ z>vO)oJQ&&FVaKefeOt$qOR>f~^ebnN_=~%qdHEa{vDV26o)#~38k_!`W=^oo1w6ixmPC4R1b Tyd6G3lNdZ*{an^LB{Ts5`idse literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/site/vendors/css/jquery/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..7c9fa6c6edcfcdd3e5b77e6f547b719e6fc66e30 GIT binary patch literal 101 zcmeAS@N?(olHy`uVBq!ia0vp^j6j^i!3HGVb)pi0l#Zv1V~E7mS{Ou}E*`%9 zKPdOkfrN+ZlHSt7(uY{3{#;wiJb&Ugx1>W4qtrSDm(4hFaaY-$3p3x|sIU3`%J?Qj YcLn#R=pC)AfTl5cy85}Sb4q9e0MP_2(*OVf literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/base/images/ui-icons_222222_256x240.png b/site/vendors/css/jquery/base/images/ui-icons_222222_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..ee039dc096a38a3753f92519546eee94bcfbeffa GIT binary patch literal 4369 zcmd^?`8yPD_s3^phOrG}UnfiUEn8(9QW1?MNkxXVDEpFin2{xWrLx5kBC;k~GmI3`<(O3xvulR&VAkQJHZBho(m=l0{{SA7UpJl008iB z3Rqvn`1P1SiomLXkg776;)RSXXXV1Iqu_@e2%8dEPZ*NvG6-d*$oWlBXKKg zV({l@ll0gM+F;pm#SBg*2mQ!Rn_HBhT&5w_d`jyG6+_vuxMHXoKj|Yh2EGJ-B`N+E z$pmy>sA-*C0S`BfHv`&Y>Z626r?uZY8?`zzbXj7u1}` z;TS<~e1eY(jD4j)wElgyeR*V7`qdhf3S5Vcdq_R*a&F^r|9|M*i>!yeL)xMH?-6M_ zJjl&7(M|RQJ2z;fI7;E!$?Pfq$usWpjLxzlazT~K6v`ft@@P32;&o$5@b}Yj#d~r) z9^2%vhdyIgOXOGiCNOR_sjx3j8*01pUqQBn7r}I@E53HUy&DusRETO9wG~Rdfx=Ta zwD>0smtXx6l#X>f`lTc3c!pmLbwTP$Zfe7s__87<&i+s33P`Udim99RAA$T_Y7T3^ z>vV9wL8Sc0x! z_eRl4cEFZ`EXPfL3omdIIY|MS@P4-79I_Af%(!ONP=msk&*mFs^(0gOj->4HEJ}Ca zL(HZSEXEQH#fbJDfQ^RQnvtlx$kD>NeLhPB+yUp!E5O$&?fP1}JdI;l4(=H(hEfAQ zNRU;>uU@{f`2)^*UI^NA8VHraDlXrE*?OWOs z7D#P(ftiy|@ab?=t923@#mR}=S6GNj1 z?mTR4hby}vE*2>Wg7-X!KAz3vwvJ)qVMtB~**$wrQ^&0>;8UR6E7imZV-)iH?Tt~> zX-EGVhMYWVxX}dU)MQaN+jv0*8;3JBy*az#1aW|^_4%i?mlU$yRTy>-wCJJVC==P> zEx=B7cZ&E7jJ@{Z{CG+0A-lAG;ovs3FALs8|JLq?o#M-to~~wx^JI)GhP%l=X?-mS zEbfx}Nj)D74<>(1{)gt2^%v7UAlLYp6gO$gsv=`$#2)3F9ed8@mcK6i!h@mGQqU}e zyItCAfl~4IqG~(AU2lV?`)nu#S5+1BrCJv>QmoI?LyuLj8e^o>li?U6OMey{r_T(* zY8RG<@x>cK$(nNMlhy)E`{;|c6$@%L*hZEYs{mUmt$8-u8m?YV3{83m{YAwB%6Y{L z6k9V^jd0tnd%q4+xwp&Yfr#>WqoooH9K5xYM|V_s8{16~N?TcuYd@6+y1_aS;c{q^(Kyv6DZcFd zd@RkCqyC{5yX5E=oHd-`WBQ0I>9_&^<}<7793`JA=$mRuSrr}iQyzxG9T)%=Xp2g4 zkFI*p1^XIjQQE0yQNGyZNn{h@1;N1>r@)!(21u5LGg2Ob1==Thh`ZXost~Y05y+XE zrc7k%zx|Fxe^LX9HhqjcV~P|W`3AXYj%WAaFNz@uZ-xRmf!NHrNh4zKSO1WrwFL6P zXM}G=*p9v_k=mUmpg-$Y6I7Mt4@y2D+ys?c;_C@aVePnKabqAS%y%AoFzKI#JaeQxo%Il=}>GqqqxhG8cPyu>P?R=}Ol7vhvDcW{Z8i0Zn zzm^YCS5qT4m#*SycTaxzIpnMMHwFrEO>lJzqr0i6lGn6M7x;$7B7Iy)6renY$OiZc zMEFF-;Ff)@RWrYEodz{P?avD?^RtUsN$GEP>xrgxlbtd22`L1q+Vm;zyBzLIj#2fp zQZS2sUF)*%MR5S(jid&TIT<2`Js!yUdi}%lzzxkuKjf|bHvGZz#1l5%O0plla6C28K&%)=R}0F6xRI>HvM|=4x#=-to|lSN^N9P6&xIP z2dq0{CX-Xc&YJNeXXD#dn;c9feR-*P_CfUEp8(wN{z!yEZrI*MPs**fh@b|xe*S&i zHc8i5C2XFuJ)xhg7K~%2H`zsX?JhZT+>};UB5HaE$E92V@>aXAPbP zjHGY7LH_&c+;-7yblDf5tKrky!+N>Vx>?)QZi1hm1Aea(92RyRiFczw&w7)GT*KddVhT(T~0Egdo9qyLRosyG6?!=QbqPzk^x9!b!;O zjEYZ(YM2+oYg-TrJTt9??(26|bMF?&#cgl&%SzC;-tOToW%SoAmvaoExO%bz%?xjk zc(|{^J<~z4;>Loltn&Q#cD-zLlA0oFa(P1*5{sdl$v0#75<`$?CT{uv?urEF5%l#% z1*lLBO|PYH2z}OUCDP!56T6(s<{oG|TOAmiP3Z95>EKzFu=~wRiHd}%-yn`p^?J6( zih27|xpMpU0(-^Ma=J7`xm^&DhSqXkjnQt=LQjM?m_ss!!0cIcfgCXk7TijCGz5At zUKx0OZ(Pc2owm3zR5RS0N)Y#iMfl$WQCVB&sa%OY<#3FtYF&H{`S5{&n#aQKe2Se9 zB?KD>qbcT%&$2w0lfgg>hoa-{bj}D!0GrB0(o9%dP6Pxsw8y%(rU7O|*#fSHYBm2h zyytq$C(2?`j}W=ORiP$Y;41*}G=Y$(2OhqHVfd_b2NmhSboLunMtOr5!~U=jF_g7g zx!U^R$M++HtM%nJWA0HW6A->{j|_B;D@i9waP$)>{6HyW zi?%Q-uGS3xs5_COdmgZjld7Pfo4dBxil@eQDw4^F*Vcb}d)bfW?|OD#N(nd^;T^jB zZea;L9}obXL9cH4o}9qQv(@ovFw_meU5D94g#m>tZ>F(pY-+sVc~p1lWWYncfsZBD zlLUulh#8ZKbJZaXx~7T%9*9kCI?ptUWNtB6zk6wB?Esa@U>adq3-GJsAap@@buxd8 zEh*0kH65g*0pwfcCE82`98Gls@jB5(U`@lWMLxq4sPDlmq!Rv*Vp(zSX$437XGBPqZRXNva3-1V4LK`FF19js@6mZK*48gf-Z-ZNB zLM=}?fKd18YCyN<3I%#wqeFjR9^PLn0C|nbyn1-&Ph!re@O0EEp`97_ouN^T>luaA zQbRd68s2B-M1Q}bL`59M`{jC(<_`P4m+_LOgr`2Gt(Rm4y+wDaGcvik0$;t-0c3C{ zKhx0TB~7CpakFn?r9>!&+;ccIO!hd{$-sX1k+O&#=VmV@?^gOz?c=kZ*8x}L)H)dP zYzhfqNU`(IVUtd)A!)GN@5UL@&OX&+@1C?lb`+!>)>=w1JnE$X>Lw#Yjk7&t)#5>X#Cjs|&jQ!X46aWn?QOjkKm*1G ztbhAifM)AKF=tIbp&vSIPqX&9FQ`BEN|??$UXR)85VQkj*P`!)ht-9)fQ|t&EI}c) zY_Dp0Km2C(q8potDF7er6kZ;VOs*dAVznYFU=Tj)$Gq2%pheYQJdTMt)xV?d0aA0f zf!9BB;E?X!!FWTWHx>8q_1{a`32+aVn2QqF4@>>wO;ea#m&96EhNkjIR(#vwq%yr` zfH0w))fHpM%M^W;nW$_)tb@EVVvhrYi*g_wUlF^|U`HFf<~&JOeBOMX&56=R~^VwL+|j!Ca?>Tx==&$#g^C#2+mS?tyG29g?7BC;5|* zhNhNJ?*-LgdlM)3Jx?L+w7;FK4mFXC;;XzQ429NM`AD>QNUJVX`T3s9}m~hbK7csE0P(!l|C~FWjU=g#?C}12ipKQAA~kz3%msO zg2N0*dRqd|SG=WcPVM-2UAcd>w1y8d%zsl=9Z^nq83TK_9xPH=!{}}AuqY7aaFPnP l;BjQ_^4`vQQuBMqxOYB4T*@HG=I>V@U~v|0R%wcf{y%IJ0Z9M= literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/base/images/ui-icons_2e83ff_256x240.png b/site/vendors/css/jquery/base/images/ui-icons_2e83ff_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..45e8928e5284adacea3f9ec07b9b50667d2ac65f GIT binary patch literal 4369 zcmd^?`8O2)_s3^phOrG}UnfiUEn8(9QW1?MNkxXVDEpFin2{xWrLx5kBC;k~GmFhwsn)TR1w<4t)tA3_robX4CdCOHJC|7j+vW z%J-EMX&`87enIluaSc0_SnYUx$GzUc?vrNXt&I`o?~7C3RJ>C-Ajq!3AfU8Dx90^_ zp3}MKjJzYC+`T(&egFXQ#9Ek{*oVAaa!zrZtmlRFnwQPRJXH<%pkK2*eP`pT=lwD7 zifq+4BY_rUTa+U|2#&?i7>PVvD?7R4ZfOLPT{e9G~G!Ls3s8JtQE`jMM9wl2V9&Q+K2DHW0M+uQmEr%nYJ^7cK?uIpU-)=wn71ZZ-=@ar0;3^AY z5+TI{2b(e%t{2PZ^HKF*vu@+Xr&BAc@2BC4 z_vCgww#i=)ea5Vo$glEEVBBg_VPBj!)OO>)f@}#dg6ULOeC>LBHz<;*5Y;YfE0lNx zg{N+4@lO~ozxpF69qV@VOGnc248Iuag4C1T)P^(hWkpP!{h!JekX}m^Q#b2B4f1oT zIjsGz)4}-$rQ*-tSuc%qG>%<4xM#E& zN)7lRK~^2VdiloY4>;#}A!yHOAXEmEi^+eA#05pawGXs>!z)gSoDuI#>bRCq-qjJe zZ)r=A`*EMX6+)~er1kdv1L^)0-PsAEM7JF$O6G8>496$24lkOSR^RTfUuIz%iSfn5b-t!##cs7sQI);gdAvqmn_v|%I9k;fCPl0Z)R1+hNQONJN zH%3jT9sOq*a`LF*MiY=zlSSQZ;{_FL9M07A=In+O!~wR}=bzGEQpk2!Vc0p)qKAH? zOk{(%06W#)DdICQ_S%Q@<0Y+!?9%#$gWJ%)EO->^YZP{<`oB4~9xh zL9-0*c4@B#O2ylYs_g`Ky$zb~v!M`NRaMNFYF*Gsu|7)=JyyMHjFC=HhGUE@{aI|B zJ~ITXU052%7jFb5Ys#fhS_?4kqc7H0EU49B8(Chg0&JzU=Gka#xOz1)H0d4m7ZnRA z=M^tdY|U6T!fmte{W?_r8H~qdq|q{5AMU_2It1I4143n~xL?4&K#BOB48l9_Rdm!(c^C?JU;tF0 zEh@o1y6Qa_>}#AwX{VY+`C^kNkxhgb1P5cB0%xupAXyg9NO=SnXrJUE?rQg{Lcsn+ zAZKctGLfbK_B#^&Nev|0^fB&?DN=ak8|0!np524LD25=s84BP8Vl(3=jflNp{X>e@ z637Ri5xx;&JNl+XYImA|{;XR~P*svYDEWYJ6I5!6uO~2twFC1ZQevB7#3z~(apxn& z^J@>Mc`>PJair{yT`iuan-V+i%|Ho-pA<1?V-k^R2Q<5;Co%XxmL` z018t4T0TTwO^w)Gx{9OSJ^9_|kgwX`7%0Rw!PO~@?xvnfUehvN;2Rc;^l>3kfbtk3 z8{j7p;S&{uTlTe9&HTc38q@%_KQFk<&n{vmrN7y&Cz{etcE->rq!6HL)2F!aa=0%! zM%Bwo!7TQ5t;@a_#Q}sjk{UebWQZ8{cp&HN^$*JfH#8spkhk{R@CVBiPuP@yEhu{} zsQfuhTqV%rioATpEphMfhyRYbVfVW`YwLFXUWm-===J(byMf!5;W^CV1g~2194Xx) zFK|z{pm%n-)-DRe{Qhk(d!QaoI*y%Wn6h7<6A{i*Sob&B^y|Spg!&J$`kN>zwUJ3x zaB$ciu*0FJKg}T ztgnh)ASF8njz5>h6?f#{c=*Yr4W_34$GmVIo8OLWjcZK4a0`+Yv-!*}9 zBwKm;DAsA(nDI-`iH@;`=gP+m{lgFLHK3m$W@?)&dGhDA_Z2xOzI0$p(ZJtH$vCxE zj>+kYNBJzs-TlSx!tSH}%I9fQv)mc!C7X0bKlZv4f&}C3+O-4k7AmVO|KYZ9ydP%(N1^uisV8y;~p`x4qFXD?!_OyN9=w(Od6W; zGrT?G;l2v@Ob5k^8w<9w%Jbjb^|H}PYKo}I~bobd!XrTbzp2Zp~H8lgJ)I3?l&(bDiWf8gE&6b z>)9GB=Iu-6%I((+>=jGP>CzD8c0oWITFZGgM!Q7|JrUYq4#^Y(vuDu-a>OWDa4Y4} z5a_*lW#IL_aVf8L+Ty}c&2VojLEIA-;eQK6Wo?xAuK>i;1VWx3c=!s2;j_*iRHOsb*>6-CgcYP+Ho=L@XLd*j~2ln-;WHg)|cCixksH$K={5rGSD@yB%LI|(NCc8 z1Er8H+QO)~S~K{g?nH|2dB8SKs)BxQ?%G}}o*LV!NG2m*TmR|pWj~g`>)ClJCE#F$ zcj)fBg(dKOKmc$Cy}IRlasngIR>z~kP&WW~9cC951{AKmnZ~ZMsqup6QQf7J0T1;C zK9*Qd5*(HxW=tl|RfjO>nkoW#AU3t>JkuzWxy4-l?xmTv15_r1X@p@dz^{&j&;{Mq z$^0$0q&y?kbdZh)kZ+NfXfqLTG}Q^j>qHlUH4VEK`3y^-z6Y<6O88Hf4v^;}!{t-a zDWg;znYu%6zA1~A5~w?fxO~i8-Ib(^02{c4pXjhDI^2 zXB1LP4dvWuc%PXQ{r!d#6>${rm+M8EJM8yf#!H$Kp8AxwUXm5`7Tu-J$mHeCG>vw|&Ay415}_1w&*9K8+2d3v1N+@a$|820o4u60Tj@u&kI!~q2V9X; z>tMvQDI|O$#m+m2O**ZHq`_{#8)ry6`&5s~2k{O4Du16Fn0P;&_(0!e5%Bel){nU0 zJX~<8U6hoI%yx}qGY_1Tq7YKDJ)ETOCs&W)TiCrK*1%DE*vXdD-7hwE*LUgjeHRM` z&@pkhTi>m#Kc+QIK+2Ybn9-sFVKNHyIgfob4H_77yYh))Rq$7Pw|+aD6&yZ|ki9 z8Zb6s{oBt1G+PgfIcxd}{m@~1nzhe;LH)5;!gS8@ddyabpdBc?7JVl?tS+<#bPSMT z2@0uYdsWN(;Ww)n-PlA-0r+62@bYkEa`k{0s})fJgYZ#5=DmIdEvok7aZJRi{w-|} zkea&6X}ZA3b7&vbDb7)v8CuI(+zzSf3z&P2eOrPNP?D~ zf zn0@)0h;~5F&BG5vOFU!=woW&ZSl~nrs{?1w>nWfW_dnpTd z4qvLDYJ*ft>Sp%M(^_xCZpNBnc66JX}A|ZL9IENM`U>`ph7d<+RQiI}@E8Y)70s zMC*_&))}GlmR}@{v9*nm)29-=rn`Q$rc^4G)GVQHlTr6BpGxtHuU(8AF7Ffh54?5w zj+EYT9>x)PWL-iQ@RNmT?R+|c@=FOmj)5Za6_ z@DkVy4l^L>Z3#SI@s_eVwd3D)<^Ivq8a~J{|4mhOL^<7M4D8){ut;GIqqn`oqCk|x pNh;Wa$C0(mdpqYz&F>xK-uVD=DT5%Jzh8ZT#aXmjr70%*{{S|9XD$E$ literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/base/images/ui-icons_454545_256x240.png b/site/vendors/css/jquery/base/images/ui-icons_454545_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..7ec70d11bfb2f77374dfd00ef61ba0c3647b5a0c GIT binary patch literal 4369 zcmd^?`8yPD_s3^phOrG}UnfiUEn8(9QW1?MNkxXVDEpFin2{xWrLx5kBC;k~GmI3`<(O3xvulR&VAkQJHZBho(m=l0{{SA7UpJl008iB z3RqC-Ajq!3AfU8Dx90^_p3}MK zjJzYC+`T(&egFXQ#9Ek{*oVAaa!zrZtmlRFnwQPRJXH<%pkK2*eP`pT=lwD7ifq+4 zBY_rUTa+U|2#&?i7>PVvD?7R4ZfOLPT{e9G~G!Ls3s8JtQE`jMM9wl2V9&Q+K2DHW0M+uQmEr%nYJ^7cK?uIpU-)=wn71ZZ-=@ar0;3^AY5+TI{ z2b(e%t{2PZ^HKF*vu@+Xr&BAc@2BC4_vCgw zw#i=)ea5Vo$glEEVBBg_VPBj!)OO>)f@}#dg6ULOeC>LBHz<;*5Y;YfE0lNxg{N+4 z@lO~ozxpF69qV@VOGnc248Iuag4C1T)P^(hWkpP!{h!JekX}m^Q#b2B0{OYr9M*o< z>EL{WQt@Z+Ea-hxX0}nTSZxnpi^#Kn8Ox8FgIS|hc}KJQ4tm*HO16ui{(O9}1YN)G zjiQt6fGq`Cj+^`zUf?8hk^(T{{cOQGWFP98am}is28A!5%{R#ENv8fCN!j69lMEK(2z?|BY=Je$XD9mB-Kkem*(d-j^9j$2#6r$Dz?s)-TCDCGCs8>6Pv zj{Y+YIeFA@qY22V$)awy@q!9A4rgk5b9TcC;s9Ig^G|6nDP+5=Fzg&?(L=vcCbGd> zfSu~@6!94td+o#d@sid!EIX$rx7*cawe6`dScJ z+$HssdOjE)O#Ybs56vm-FQ$7yuJJD^Zqk%hMaIgAJ<2yb_MFQte_i;62ScT$pjifY zyR_E=rQ+>H)pmlr-Udzg*-!|ssw(D7wJvC+Sf8bb9;;q8#z?0p!!bsd{wy|5pBaMH zE-Ve>i#LLjHRaMLtp%9&(HCng7Sw96jVv!#0k%?F^K7&=T)mnYn)D9(i;4x5^NJTJ zwq~pv;kH@#ejTd*48~(J(r6j34|m`h9fEDj0im)~+%I5XphWymhT;_Zty|Q&zjPg# z-ufAHZ1M*Gccw?Kf|8Pnhtb0`!{N`Bqsa37J+>wC$!e00k+2 zEgzz;rbcWoUB%Jvp8W1}$XD%e3>4y;;OZ1ccT-O#uW6Ys@C}Pa`nZrNKzR(24e%3) z@QI4SE&E!lW`5y14QhbepBG%_XBV-O(%5tj)@9#|;sC-MNev!zGDHk}JdpGC`iJF#8=8-P$Xoku_=Dw%Cv3{U7L>gfRQ?<$ zt`cZ*MP5GQmbmx#!++P@u>0MewRO9GFGS{b^m_fJ-N0?j@EqoFf>$khj+E|@7r3We z&^tR^YZrxKe*d22agXqCO0l44&kqCv{u)T|(lv`~PK@DvE{QI_T zlCH5z*gR!>LO)k67{^R+vWx24U2^2ODXpwT;6y+6+$5m)_*w4WY&#do9dCeE)>p+Y zkdhq($DhmMiaYXey!_kiL26uz($aJ!QT{B^Wu}U$^9e#5)=c+XF9@Ill?ZmMlNgHi zz*9!vDc&uxOo;ZVxb`Q!Sk0*gnfxWzmbZh4(=%CD%qP?0=);n$&zaW_$UKV98axdc zN#AyZ{P)wj?V{P}vM)YY!>6@}^>U+iv$`9>nMTCPjN>z%yF&3yf%>+T@0vh4lC8Xa z6zeo?%=o3}M8{aebLHcO{^1Ar8qiM=Gquf?Jo)q5`-+?sUpg?QXyEUpWSm+n$K-Uy zqkIwHLquru~o(OF)hhz$Y*|X>ZIbswnxRvr~2=rdO zGVuD|xRlpAZE<0!X1F(%Anpl^@V^D3vbM}qxe|NI;TTiZy7(IM;R69RkA>a&6gwYE z2sREzQ_LHmWqB+ogMk(fMaSFeoDq-!HkFB_nXt5+2ncFuk9BQL1I&oB1zZi)YW{6_ z&-Ip1l*OVRA##1ILQS;5R{-K^0wGTiJbVSi@LA^$D$;@J>^G{6@&+%4{b3(sC~LEH ziTv(0b#zxt?YJ0r_~pUZM~mQ(??(n#>&tD%+@nq=Abj5*8R!~Ul1`G~=qFJ4fl|m8 zZDCYgtr`4LcOpgiJYX9qRY5;DcWti~PmS$VB$E-Zt^f4)vLDOe_3XTq5^ylWJ9PKm z!V-8sAOJXnUfuFNIf0R9tK-pNs2hO04zr620}5B(Ok>yB)Of-3sP59qfQNbmA4{w! z2@cB;GbR(~szVrbO%(w=5S!X`o@o@x++wbN_tMPT0Vc)*I;Fgsbf^*g02Di?H zTApwKq3+YwfNsqd3iP%{hyK1iyuVZc@*0tO_3+N0#GFsz>8MjeJ2UJ%L!%hiGYYAt zhH`E+ywA*u{(eJ=ia3h*%k?779rk-K<0VZAPkl;TFUbmei|$fqWO8!_zIvqt$ly$V zrlH46nnpX~X5Yk0iBJl;=WuA4>~X4-f&K0yWf42h&0b30t@NYX$7egQ1Fp!abui-D z6cWCWV&|R1CY@G8(qOmWjWeX3eX7UggZPGimA}soOuQdXe4uZ#2>5zN>qlI09xk}l zE=tNpX1m6*nFr2EQ3xs79!^sCldDJYE$m(qYv3q7>}1R7?iZW7>$~*%zKaC|=$N?M zE$>#+%T&MZC`dW1wUl6Z)JgxkeN920S>e@EK`q~>k| zuYcsgA>F%!@rFciD(>Iwzn8KT;2tb77bUPCmioh+rZBfIiM6f_P34cQ__o1GWqQp3 zVL~~pE5?qODf%iiQQ3f42YF@09tQ*$4v_EKUx;t1KCPCBtgqg@+Tn; zO)a0uky_%jm+WjNB?=~VyH>V#L!*=l*@OSMSVyt_UEH&NA=?V2stHPyKkVN!&jg<#cjros){#ji)dK%)We0 zL_478=HZ8-@xnwsKrWs8)x`MB;(Y`Cmu2c-&SH(vN-F(*e`l?c%+l$|y_AJJhcDGn zwLvN+bu;_sX|1AiePhx@u&%P$hf*xE+O=~D?_(_KGWQ!158YL-y9$*6mmPo;Rp*Dl5lm-mVM2i`h-M@nxv z590_tvMwPD_{l=b$iOm|+|S{D9&P%zeT$GgX6Akl-tfUF>tL@Ld!B&{pN39tH>3V> zqksMAYul+jb7UiouWVGPNsxX7Ueba+9|~dz?d*QM$ng0DZfO0`7fAy?2yMm|cnRzU zhZ&IcwgjH9cuU!w+VStYa{p*)4IgBf|E8)sqMYtB2KH_}SfsFq(c9i(Q6S3UBo%DI k*Kv;w;*%(i9W@fAqs5i2wiq literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/base/images/ui-icons_888888_256x240.png b/site/vendors/css/jquery/base/images/ui-icons_888888_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..5ba708c39172a69e069136bd1309c4322c61f571 GIT binary patch literal 4369 zcmd^?`8yPD_s3^phOrG}UnfiUEn8(9QW1?MNkxXVDEpFin2{xWrLx5kBC;k~GmI3`<(O3xvulR&VAkQJHZBho(m=l0{{SA7UpJl008iB z3RqU$@Wfh}nb?QCTyjovo2=)B^qQB=#XMCF_n=?1Jbh>5sptJM?}}{I zHzR=-V_TFXKM0P+&lrh3TPr)c<8EmLl3g~EY}W@od*0X6Ljv>L(67bjz58EDypsu&ddu2a@@x)`5aA^S^DxkW8rs_vKtu8N8(o0 z#Nf}*Ch4&iw866BiW!_r4*HRsHn%80xlBW<`IOcXDu%LQam7$Ge$q#1415XvN>cnS zk_qU%P}4fO0v>J{Zw9o*)JF-CPA!KcpFR1Pn(l@*bKh=1_!ZRWb?FoG5a22cVG<$5 z0|%Qj7p@n}=Hrkk`BkD99I57h7_+lQ-AZ-?fETz5E~q(= z!!d%~_yivn82d_pX#M+Y`|`-F^s6-{6}S!?_mFzr<=n>M{{PUq7g-N`hqOcY-y_m= zc#xZEqMPgqc5cu{ag@Tdli5@JlV{xH8J%TA}P<$=Qej`5Hq>_Gzk+NDFM{b*SA6Yydp9VOs1VgIYAcj@1BIt< zXz@=NF2DLCC>`r|^h-z5@eIEh>Vnjh+|-6M@nuC!oc*856_8#_6jL|rKLYu=)Ew4+ z*XiJVgHrKl?=0wjQ)aeNu2^jkUW>@Hei_S;nuA%RRe49V`VM;8SxUBxpZPe>l9ZA{YS(NU; zhnP(vSd1kYiV^KQ02>XpH6u}Xk)wrk`+SxNxC73cSAefm+V!<`c^b#A9NaTn45bEq zkRYp$U%h-|^9P*syb!eKG!QC-$;IS9MdE^@-`WRSzTp+8M9zqJCUsoPC-3Tr+qbkO z$o;ra-wGjC64H8m{(*FVitg+LQKH+96D4!FREFb|Scex)lw()`rHV$WMdUJNe3E}`->+?@(FDYcZt1#>wXwgHzQ6{p% zTY#PF?iBGE7<=u*`SFt0Lw0HX!oh85UlzQH{;k~&JH?kPJzdQX=gAmX40n@#()wBu zSllJ`lX^ZF9!&n2{1443>o2BzK(6sGDQ?n~RYk_ih&{?TJNBH*Eq`73g$F~WrJz{` zce}LL0;S^ZMb&nKyWR#(_t{VguBs~LOSLX&q*$M&haRh5HO5G%C&MvDmi{a@PM;Zq z)h;XzD;Cshu#GG)RsptBTJvnQHC(-#7@G7B`iqJMl=F%g zD7I#-8sWBC_kJC!{tU)rGSX-nt`B$M86ARc$^oIWRNOCMU!X+%PKM$X`mI~kxxaKB znBMvsb8nZ)0}JBmidn3FUeG@ZcdpwZy_4oi*b{&c?T^HaVC|`tnlo?1SjRKLNPk{gDWT+_1fio|Ic{5kU=X{rvm3 zZIZ6BO4vMQdqO`~Ef~j4Z?cQ(+Ff$wxGAlyMBqd}_S__(_xM@v-fTM;$Q^HhR@PU= zE|8KP1IM4s;)*-+Z@m25>p^N(PgHJsq+a!8`ezsTQ3Np0+k4Mtdkgu z^}tg`-YMQKuuO>dsJQkgyjabt1)2OM)|R(}hto4zSIj5V;^@PYtIwI&4#+%;&Kf)o z7)jrDgZ%f?x$UCa=&~<9SHq{ZhxKx!b+ft~!I?(H$&BMOox4KuOo95gl<%5AIg+is zd=%?6ZOr(k=S0U?!*k{1h5q3O_ZrYo5Hq#Sl|1?L+WU%}6JI(orD)*qq-300E63z? z#iM){^ff?RwehBsE3Uh)}m z74!C`a^?2x1@?-i<#cI?a=RcP4Xx$88l&B!g`Nm)Fo$Fcf!VX@0y$z7EVz~OXbALP zyfX0m-nf+4I&E=bsAjk~l_2g3i}1e%qO!KkQ@Ij*%HbGO)w=i^^5FvkHIIee`4l@J zN(eR%MpMiipJjP0Cxd|&4n@b?>6{Ue05+A0q?xd^oCpYNXpePmO#{q`vISfX)oT82 zc+d5gPn5-?9wBmlt3pk*z*hj`X#ycn4?KJY!|++>4l2@t>FhVEjPeFAhW%k5Vkm2~ zbcy`#HFb1XOYOKAcKGGN*GG%skMBnYSL@4d#@wS$CLny@9vSEwSCUSW;OHk%_<>T$ z7HwfvT&)@WQFkIm_dH-5Csjc|H+OBX6;F-rR3wuTudV;|_Oc(#-}UUgloD_-!aH>L z-NF)hJ|F-%gI?Y8Jvo7qXRG7UV5l2_yAHF93IhsP-b`cH*wlEz^Qi99$$*D?10PGQ zCkYPA5Hltd=c+>(bWIfjJP@1Obe?Gx$=qVDe)rPM+5sw)!8F3K7T{OMLFj_+>SX>F zTT-48YC1?q1IV|?OSG8?IGXAN;&q~nz?z0#i+qM9P~U@BNG1FyO9#kvk>T>G=#)_^ zj!fMlH{X;+ONmr!LsJx(j*b2&WMpJ+s&cN;7Tyu8gf>RT2kOR+DBzZr7=m-v-UheM zgj$|(0HN;F)qrlz6$FyVsy6e02`M!$<1L&Bz z+b!=_(#ur8?I=h&thJP2c+^S%)lEi*8fSaPs>Or&i1kF^p9QX&8C;)E+S__7fCh{W zSpW930L|8eV$Pa=LO*oao@VWHUr>MSl`x%iydJaFA!rB6u0`Jo5337p0UZNmSb{=o z*%W(>6W|^!F&8DUAC~&Vo2D?gE{V0S3{B;atoXLUNo9J? z0AWHot1HHimnr%xGf~-qSOO6>z*MtHe(EIN3<7@k-U&gFD+Xq}Ua*o~(!1kApC zO+-7O=jP#uq4B~*JwPs<`_;tw%;J3m{g-9xU(RBU&q^x&eSc@Ik<8NR$i0+>JBKgT zPqjfRC3Q3V=4q|BVK-yVuyUMByvXqR1a4^k&=*MqJ_v2b7I+El z1&0}s^tJ?^uXsz@oZ9j4x^n+$X$>D_nE$4#I-;EJG6wc;Jy@i$hSA&JVNoE;;UpDo l!Q;r<<-MKrq~`aIaqoP9xRgPV&EKy+z~U_0tkM({{ePlYU?u&Z`mr_kcwz5Nh&g=McJ3E!;CE1E0ryV5Ro;>nvty8 zA{omJnn+{p4952Let*87zvA;auXFF~{<`_uPA4&sV%P>LMpp1PTBEIL*yWZ2%{t3Pe;FXZ3XmxI8(D_g57_$Zil~sY6d4T}-hu9_Wqp4C0AMO{-e2$W~1A}=8 z?24)=?B)4HUDo_oXckN%okP)HFJjaB4*3_SNpKaf;yPT}KqfS{2x7`d{0xbPErH%h zh`mQJ03DaATP9aP!}a4$fY#``NI~M6&RljED)8z}hhWxrNbxIBlTxG^j z!X>$3AQQ&I%_5mRECOjaGwR-GHmde})^)t-3_~aFM1G_L#mpCNdcLqr(RKjv3R}(z zG2^yBftMYh;H3a#-slaj|5$BX9+{PTv&NtR*P-L?l21FGTG`$H9~##p%VE!uR>=NG zc&auxVl!1_lP%uX71AJvlz(wLYl?63oLd~dqjZRrU#UEWw8J6Yn-7L~T$$tjeAQiW z9$XG5Hu>rxFBnzgd6ho#^gE5pY>U$dTCRN85Y1tQQ0=Pn{?7OJ10x9Xk!>P2f(f^f zILd}5--N;Po4*25F|J3ywIv+R@rfcYNj}R-sXrH2TFAiK{jFGG(ru1p=w$wR;IXQwAX*S~oiEK{g;kZPW;YE|!QY|g^2`dMS{&1Fr zkf?!sj~m)xO3v`hh4KQRJ&&Q!=X1HNq8T_Sg2P^B&rZX{VQUNc9O(K+B_Z4hiTH7M zW7K5Y!Ec5xD~B9zFlKUWG_Rd)xTK7U#hRGhp51T++e6oS{gT^?3s~>V4?6{zchhc_ z3UBb_W2U+~guMsG-g=@#aWPSFypk)5jIUTxFiM zycGZzbxQuCTnvH*kv=E=LsRnltLbhgm$=ttS1IzU0)1t~4(XE>bHVwJpAPKOqoI-# zrdc{yo0R7Qx%~ZQl{UPa?gmxo#ZWM|vNHNxl@8NLksfn5Ek>C${w=x~pekl%gfwaLwWspL{af)?f zTOBmhTyU&3;}QeF&VLwhJ>Dezu>~P zc+$aFxKDWKj-CmD(v`}uH|ts*SefX@lyrc<%~WE6tHU#dv;y+LlA@cTgl8J!u@@u6 z@@fvJdC)1TvBa$QT@ck`rUxF**7w4Yh0!vZUsGu%Lm(cl(l#QPpmoOH3JC>FMe07G zq0kl#K+GLndyoOx8{t9g8JiLs#`pH8JWqR_ZM%J!Yr>cp>95<^#=FWQfzPm%q;5B+ z0>}ul8+l+gRaHV$$tsq5|MU;?AJ~m-XNxjW3U6JH2k`tOXAqi)yGI@^uA&dQ% zZCJIe7{qK>+p_F)Sqy-GC!x-5MgogsP6lwiUH`N^a7*LKPdO{!4L^_^;goe*e}3s( z0i~~@V#)#L*W~2F?}&N*IQ)0a4Z1$uTU)p7^Mq&IM6K6d*$vpX2+L*+$9vY0=7?$b zxdD4R`8~74HMWsx#*goNSp#(_;z`UT-GuGxoUl-){JNk1rf)aSKE!W`#m`t#v6V!u zgn>fufpkVprL(KqSkhl*Z+yRQosF)bEiV<#K8hOr>yQ1@7Xg>g3EjKwLB7)(9$3%X z$G30OD&Z2Nh{;v5!}oF4fUu0TM%&2F-6aS1+fqu3cn;K4k4-#kkB|BO?bZtcTygp+ zB|R0)0x`)UVEm;Fwx~Vt*6ZV3k5Xcj6_=(X2y*8M&NGz^?Jr>Jutu8idcHpesED^^ znM9MV2AcX%oppm45TS9yYBtteX?1liAe($}l8Mrk|YY*cFUp@Yl5_|Ih%+ z5^dz*^BpQ&l8;Le-Z+E?J1_|}dtK>`0HCSg@u z*e9pUpX4zkcJ~*%3c8N=D_*8f&2puu6>riMeA#MG3E+*kYt|0Dnl;U^u0x`IJLnY* zjELAyFaL6=ihd=uwgnc)F;a_ZKEBsA_UuVc$NS1$GwozcE)2-hGS_c!*V9@%u`#?lhbMR;p$MXpbUS7*AsAt5?3(xQtcatZ zK;B-KhX__vb(?F4Q0GloBJ>|QvdJoM?lDbgsR3iM@a;Z3?cA&4wtslYkr80ETZHkc z9*>q7Q7<0~XHK7PK#yo@cBi@smopq(-%`e-KH4Qx-~rbHu}dW58QqJ{;3Inef@=x4 zI)BgQYXff|j7xg1Qx_M8s)u`0@M0d&aKAfD6qe?B3THxh84PWrQX5xII()>h>b|f$ zpKR+*4#vbnsS3H{v&>IrrO}Xrp{O`p?Q{I%z{XPHRAc7mQ~rVVZ80t_sel;~R{!fE znoWNU9=P1`jx=A?#Ye1fm8**6`|yK3jKQSofyZy4XkM$FK?NExjqO&YVea7N(7$X$ zbR{k3PT@a2CJt_@Dead-55GO?f3gVr{BdM(wXV#1%q{YCJlyB~k-m;m1@SZyhI$5p z9ViBGQ5QzVRGUDbbtaN^E&{f(lI64ub2s){aFm!11riDV*6MFh58H{nU5}0{$^Hi; zJVW(-UYp)>>|Lx|%+y^DwKhz`tPS-85#6Rh0)ckL)U$^na{7 z@VVG(5^ui@Hf1odF537(mlR>ZBhjf%rT+ zPUdZ~CgvIZM_wUkJAw%w}x9jc8!TL)0!EfOi*AMUgP00QdmWDhdxHH4HGc<~J zIVYb|Vj$~E#d*)1>gzKQFOMaAy}BVVo}IK&7ZMB zx!9l*+ek@g>FsKVCTu!A+bt50<5zR%LvhtB47 zphLoLmz-;H4@2#)g8=!k#zLI#UMqFnH)&}~tj#&gW_Q99mQw+L7dU5Tu)W%;@9Qi9 z>QGi--TSZnR2z4)8B5wJy^vu$s+IRc0ll#|LNt!?I`me%fGty24eDN4Xl+O{(+NPj z1ygVh>zf*$Pk&fEX-3AP^1w$s1y_e7lBxzgSu6?iXt=l939t1dNMV&Hw?hI}<+!vx zKuXRw@aAWBEW)iT2xma>qG11B|GnfLf43m`S%SD z3d3^-2o=m;T`_XFO4d`JiOd4T*vl!w_t?SMNPGOr712xew$!m3PP4`3g2iVGiU!9* z&w=GY2O}!evGB%RQa5rA7s5%`YA&A$+(`a%B< z)4%^Wyf-xKA)KjJ=y>(k$Cki3nVk)wxAEYIGA3p>sG^i;f$cIw3$H&^I7dNHU=sw$d)j7 zh|(sSuhT>1EWU{wVQLz{XV1iYPIvxnNv=>Vu3kdkB_SVNJ(KJiSF;#9T-Gc6A9!kU z?a4i1-1H;R$hx=;;1@G7Jsm?|a=U>2b+qZz`aN9sgsIyFSp6r%%!9oq%tbmjY#K7P z-Gux{jUMaKw>DF`W{3tTZ|SIDqX6v)w4@1rITXmow6pv9GTr+NsJ`V>Zv++iD5MFK z@5#Rx6sk|u-Qs__;w5Q)X2-Ad+QXxzHC&)U-n+`G@G_e77|5&TV3EucN^AXqK{AmK pCn+FvZU>f5ukGw-)qi%3dglGbB=rNWkH7i=^YbXv3KMkH{{f&jC-?vW literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/base/ui.accordion.css b/site/vendors/css/jquery/base/ui.accordion.css new file mode 100644 index 0000000..ee1b1b6 --- /dev/null +++ b/site/vendors/css/jquery/base/ui.accordion.css @@ -0,0 +1,9 @@ +/* Accordion +----------------------------------*/ +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } +.ui-accordion .ui-accordion-li-fix { display: inline; } +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; } +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; } +.ui-accordion .ui-accordion-content-active { display: block; } \ No newline at end of file diff --git a/site/vendors/css/jquery/base/ui.all.css b/site/vendors/css/jquery/base/ui.all.css new file mode 100644 index 0000000..543e4c3 --- /dev/null +++ b/site/vendors/css/jquery/base/ui.all.css @@ -0,0 +1,2 @@ +@import "ui.base.css"; +@import "ui.theme.css"; diff --git a/site/vendors/css/jquery/base/ui.base.css b/site/vendors/css/jquery/base/ui.base.css new file mode 100644 index 0000000..d716095 --- /dev/null +++ b/site/vendors/css/jquery/base/ui.base.css @@ -0,0 +1,8 @@ +@import url("ui.core.css"); +@import url("ui.resizable.css"); +@import url("ui.accordion.css"); +@import url("ui.dialog.css"); +@import url("ui.slider.css"); +@import url("ui.tabs.css"); +@import url("ui.datepicker.css"); +@import url("ui.progressbar.css"); \ No newline at end of file diff --git a/site/vendors/css/jquery/base/ui.core.css b/site/vendors/css/jquery/base/ui.core.css new file mode 100644 index 0000000..c2f18f2 --- /dev/null +++ b/site/vendors/css/jquery/base/ui.core.css @@ -0,0 +1,37 @@ +/* +* jQuery UI CSS Framework +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. +*/ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } +.ui-helper-clearfix { display: inline-block; } +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { height:1%; } +.ui-helper-clearfix { display:block; } +/* end clearfix */ +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } \ No newline at end of file diff --git a/site/vendors/css/jquery/base/ui.datepicker.css b/site/vendors/css/jquery/base/ui.datepicker.css new file mode 100644 index 0000000..567f8c9 --- /dev/null +++ b/site/vendors/css/jquery/base/ui.datepicker.css @@ -0,0 +1,62 @@ +/* Datepicker +----------------------------------*/ +.ui-datepicker { width: 17em; padding: .2em .2em 0; } +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } +.ui-datepicker .ui-datepicker-prev { left:2px; } +.ui-datepicker .ui-datepicker-next { right:2px; } +.ui-datepicker .ui-datepicker-prev-hover { left:1px; } +.ui-datepicker .ui-datepicker-next-hover { right:1px; } +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } +.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; } +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { width: 49%;} +.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; } +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } +.ui-datepicker td { border: 0; padding: 1px; } +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { width:auto; } +.ui-datepicker-multi .ui-datepicker-group { float:left; } +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } +.ui-datepicker-row-break { clear:both; width:100%; } + +/* RTL support */ +.ui-datepicker-rtl { direction: rtl; } +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } +.ui-datepicker-rtl .ui-datepicker-group { float:right; } +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } + +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ +.ui-datepicker-cover { + display: none; /*sorry for IE5*/ + display/**/: block; /*sorry for IE5*/ + position: absolute; /*must have*/ + z-index: -1; /*must have*/ + filter: mask(); /*must have*/ + top: -4px; /*must have*/ + left: -4px; /*must have*/ + width: 200px; /*must have*/ + height: 200px; /*must have*/ +} \ No newline at end of file diff --git a/site/vendors/css/jquery/base/ui.dialog.css b/site/vendors/css/jquery/base/ui.dialog.css new file mode 100644 index 0000000..2997595 --- /dev/null +++ b/site/vendors/css/jquery/base/ui.dialog.css @@ -0,0 +1,13 @@ +/* Dialog +----------------------------------*/ +.ui-dialog { position: relative; padding: .2em; width: 300px; } +.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } +.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } +.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } diff --git a/site/vendors/css/jquery/base/ui.progressbar.css b/site/vendors/css/jquery/base/ui.progressbar.css new file mode 100644 index 0000000..bc0939e --- /dev/null +++ b/site/vendors/css/jquery/base/ui.progressbar.css @@ -0,0 +1,4 @@ +/* Progressbar +----------------------------------*/ +.ui-progressbar { height:2em; text-align: left; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } \ No newline at end of file diff --git a/site/vendors/css/jquery/base/ui.resizable.css b/site/vendors/css/jquery/base/ui.resizable.css new file mode 100644 index 0000000..44efeb2 --- /dev/null +++ b/site/vendors/css/jquery/base/ui.resizable.css @@ -0,0 +1,13 @@ +/* Resizable +----------------------------------*/ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; } +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;} \ No newline at end of file diff --git a/site/vendors/css/jquery/base/ui.slider.css b/site/vendors/css/jquery/base/ui.slider.css new file mode 100644 index 0000000..4c56218 --- /dev/null +++ b/site/vendors/css/jquery/base/ui.slider.css @@ -0,0 +1,17 @@ +/* Slider +----------------------------------*/ +.ui-slider { position: relative; text-align: left; } +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; } + +.ui-slider-horizontal { height: .8em; } +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } +.ui-slider-horizontal .ui-slider-range-min { left: 0; } +.ui-slider-horizontal .ui-slider-range-max { right: 0; } + +.ui-slider-vertical { width: .8em; height: 100px; } +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } +.ui-slider-vertical .ui-slider-range-max { top: 0; } \ No newline at end of file diff --git a/site/vendors/css/jquery/base/ui.tabs.css b/site/vendors/css/jquery/base/ui.tabs.css new file mode 100644 index 0000000..3ca6b9a --- /dev/null +++ b/site/vendors/css/jquery/base/ui.tabs.css @@ -0,0 +1,11 @@ +/* Tabs +----------------------------------*/ +.ui-tabs { padding: .2em; zoom: 1; } +.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; } +.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } diff --git a/site/vendors/css/jquery/base/ui.theme.css b/site/vendors/css/jquery/base/ui.theme.css new file mode 100644 index 0000000..73ed788 --- /dev/null +++ b/site/vendors/css/jquery/base/ui.theme.css @@ -0,0 +1,245 @@ + + +/* +* jQuery UI CSS Framework +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. +* To view and modify this theme, visit http://jqueryui.com/themeroller/ +*/ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; } +.ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(images/ui-bg_flat_75_ffffff_40x100.png)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; color: #222222/*{fcContent}*/; } +.ui-widget-content a { color: #222222/*{fcContent}*/; } +.ui-widget-header { border: 1px solid #aaaaaa/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(images/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; } +.ui-widget-header a { color: #222222/*{fcHeader}*/; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; outline: none; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; outline: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(images/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; outline: none; } +.ui-state-hover a, .ui-state-hover a:hover { color: #212121/*{fcHover}*/; text-decoration: none; outline: none; } +.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(images/ui-bg_glass_65_ffffff_1x400.png)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; outline: none; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; outline: none; text-decoration: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(images/ui-bg_glass_55_fbf9ee_1x400.png)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636/*{fcHighlight}*/; } +.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(images/ui-bg_glass_95_fef1ec_1x400.png)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; } +.ui-state-error a, .ui-widget-content .ui-state-error a { color: #cd0a0a/*{fcError}*/; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a/*{fcError}*/; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsHeader}*/; } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png)/*{iconsDefault}*/; } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsHover}*/; } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsActive}*/; } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png)/*{iconsHighlight}*/; } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png)/*{iconsError}*/; } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; } +.ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; } +.ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; } +.ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; } +.ui-corner-top { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; } +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; } +.ui-corner-right { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; } +.ui-corner-left { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; } +.ui-corner-all { -moz-border-radius: 4px/*{cornerRadius}*/; -webkit-border-radius: 4px/*{cornerRadius}*/; } + +/* Overlays */ +.ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; } +.ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; } \ No newline at end of file diff --git a/site/vendors/css/jquery/dotluv/images/ui-bg_diagonals-thick_15_0b3e6f_40x40.png b/site/vendors/css/jquery/dotluv/images/ui-bg_diagonals-thick_15_0b3e6f_40x40.png new file mode 100644 index 0000000000000000000000000000000000000000..44d890ae4d801c1cccaef511b6b2ca83834979d9 GIT binary patch literal 260 zcmeAS@N?(olHy`uVBq!ia0vp^8X(NU1|)m_?Z^dEr#)R9Ln2z=UU%d=WFXS=@O}=f z_`AIm)jwU(W4XR-r9kqhNhZ3IPtI~Un35oyq}IKeQrU;+cGI$rx% z^ETPaZR51~Y_WzZeg0Lo0y93I1x$Qg4x%zY)IR!N3jfxbKWS^~K2NvPYksI@YMwr7 y?&%*Xb6+L<)B*F85s}$7lc$`@`gz*-6Ps7pC!_x>CiVlp#o+1c=d#Wzp$PyfK4_Bw literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/dotluv/images/ui-bg_dots-medium_30_0b58a2_4x4.png b/site/vendors/css/jquery/dotluv/images/ui-bg_dots-medium_30_0b58a2_4x4.png new file mode 100644 index 0000000000000000000000000000000000000000..fa6c9cb810781fcc1575630fa8d8663ccff71e23 GIT binary patch literal 98 zcmeAS@N?(olHy`uVBq!ia0vp^EFjFm1|(O0oL2{=G(BA$LpWw8Kk1A3GM|ytz|g?J uV1>sgLm*aUnZU@+%*=dv?(_K%m>72bV2$isCSwoO#Ng@b=d#Wzp$Pziq8n)d literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/dotluv/images/ui-bg_dots-small_20_333333_2x2.png b/site/vendors/css/jquery/dotluv/images/ui-bg_dots-small_20_333333_2x2.png new file mode 100644 index 0000000000000000000000000000000000000000..b90acb9e2fd681f24c1073efb17ff4bbebe35fa8 GIT binary patch literal 83 zcmeAS@N?(olHy`uVBq!ia0vp^Od!m`1|*BN@u~nRDNh&25RRG2CT3>;&L04RBS5U6 cq;!aZK_Z9ohErwy3!o|nPgg&ebxsLQ0P+GBaR2}S literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/dotluv/images/ui-bg_dots-small_30_a32d00_2x2.png b/site/vendors/css/jquery/dotluv/images/ui-bg_dots-small_30_a32d00_2x2.png new file mode 100644 index 0000000000000000000000000000000000000000..1e4b105f4c770d7814646634af573276c975aedd GIT binary patch literal 84 zcmeAS@N?(olHy`uVBq!ia0vp^Od!m`#=yYHy3uwMkR$Es;uyj)GdW_-=@0W0H|ia( jKX!B%&;QD&S0xziSXd9f*RgyIRL0=x>gTe~DWM4fKlm7f literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/dotluv/images/ui-bg_dots-small_40_00498f_2x2.png b/site/vendors/css/jquery/dotluv/images/ui-bg_dots-small_40_00498f_2x2.png new file mode 100644 index 0000000000000000000000000000000000000000..fa3531359377d9a0ecb22022123cc6f40c352b13 GIT binary patch literal 83 zcmeAS@N?(olHy`uVBq!ia0vp^Od!m`1|*BN@u~nRDNh&25RRG2DIebaKYsuSjsS7O d8l__l3^KJ$9-^D_#ek|9JYD@<);T3K0RS?W7q9>T literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/dotluv/images/ui-bg_flat_0_aaaaaa_40x100.png b/site/vendors/css/jquery/dotluv/images/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..5b5dab2ab7b1c50dea9cfe73dc5a269a92d2d4b4 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FscKIb$B>N1x91EQ4=4yQ7#`R^ z$vje}bP0l+XkK DSH>_4 literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/dotluv/images/ui-bg_flat_40_292929_40x100.png b/site/vendors/css/jquery/dotluv/images/ui-bg_flat_40_292929_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..70bf37a6eb41eb9574e946772a6076d850a549b1 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FscKIb$B>N1x91EQ4=4yQ7#=wL zTRcLgSQ_7APXpjarkLb;T-E6X%X%swpHmy_rHa-QUU&hMP- zL4gQkquoXT02uon_xTn8^cHnG>LUYPP2@f%1Au{rpU>AJmx|>h;mII;I}qg6_4!cP z!-#gRa2>nX=0HWR-?Ba0zE&Zo+n!^Tz5xQRJbb8KUsVhNnFUIvKo0Ehi;J$#7a6ooc+?d#2dDSGMj`n=SMF4$pe-#}eZt!gjm` zUvL4WL$i)fp|q9~2bj0v)fjpso#Jb3Y?+u|qj=f}}n77<2SpG(~d zTuS#wzf?e95}dU{Qnn21ynl7#3TL%Rk*s1!0W)jUhTTS-9*~x|K4arbOt2p zJWjqdYQux<#)1+0*a{Y$%vwLp_nSjlJ86zmjByoW#&iu&R{ z^JYAVn}XNE)iG*cg{gdswzq2V=>UU{0dYC?>OxFQY#^}~&O$o=gd_Wo^$c7hj40RS zJb!|5%sfIJofd=17vIJl$j4jswHbXj^Jqqm4D z{SSN}i)e9ajnmFo(Rz>^w!_XKkz(bNYI*^4$*>6Go7ru&d&o^$-*2Q0rl$PIT0Cyk zv-C_X|8=6-&zS_>b3|;DBA0t12ZPn3NcPvwblqI=>pRn(rKbzjESgcOpa#od;%3!? zOVlS+KZuT}F~b_s&1uA3tbW@g=xZcYZzqH*^7FQ^gFKUTM6@S*pMd} zlnImIC7$>x@KKBU?>C}+Y%57Af$D4+G7N1hjt0&^Zj=cU(cmu!Yn z%0q&AYvO1ZO;)(*NBC$&^Ot=a=yTVymuc9T zyD-nJW_M~Hru!PNYnfU=A+6M+=}{R&uvX95i-gNJQ1Y5g*s14S?N&b%y-{^q`kPKwKUt8Y(9-fxN0qzUK z-Ud4LJ-lIY`r365ev~H3NjUo*R^nHUs;?$FEz1N+Hj?2;kwwQYfk-v=yvonTTx?5_ zjcGZ;$Xfrv&wk@QK5}=YuHUi1bO|B2$6(u^gvLKAM<-L$o7D<@wcireZA;qk9%Ds? zM{BhHQ|ge8{YWjNUqIpohmMPTHn1@d-?9@BtHuFKneMMWfG(>2Y8 z6;{*^V#S)WkfD9|>joB6YhbOBnFL225x${8kcnX|b18RGbS{5DD8LGOpOy4mE-$rw zdChQEA?zUQ94#RH4@!qT+ns#6h2~HfSd!oePCU$Y1iv;WHsl`gSq9{>37-jgK#rFa ziaqaz%&R`4a^k)lSa{s3 zEuR}Uzo{CK1oA21AJ}mOFOf0;6w_I-Y~MI9?-$~b8@syGd>)q=NHMsOQ5s}N+mG+v z%0Idl#6dIiT7g=JNL@qkMB|vgYSM`Sg}RYpf_Pg z^%~rr!w!#cCP&4{t}p(Kta?0K@jdtNmGYs5>`32vnNaTu-t39j41#B_gu4n`*eN;W zcr>c+6lI)WZoc8-*IN5#SooQy(^_+JU4=rBp;kjqimtf|3?uQVRRD2U(68vmOTl_# zcIKlFA>|#Zj|9zeLWSaB&wUS__Vl^M2XA?vN<8~K;T-1GltXhr5TvQrQK3fu&ZPJ+ z6HA$^Y`ny*NUg=Ob8pP@tNe+JPwLU5z-z5i_ig8FYEu1WiQ0mVaT;qc=J?;Y#%O}t zPWi{K>6C6)r;=tCp>qBNrIs{kbpYRRLPBO$|D}Pq=J|&cCVL;5_E`ShAYmxlch&C8 zV>JW3)V1d<%5Xw`EuFW%QR^^zvt%Zu$rZ+QpW!}=U?7KCG8j8*eeAu~ccEz6z#_;O zv1jzK;%KG#scaVG9eG64J*3$L^-eoy8M^F?_pJ!3%+@;L8#T4yJ3 z_rY8vDQQ>^q)NF}f;ob>jZ{S_*8Yp2&RWSnOZ>EaSU$-5D4QVB;@%CoVLNj>@(R^i zW8K(P?CwF|{+mNR3NnC-1HHU8i_l>Zmrc-k`3J>a=ik;1AX*zA`_nhqW^I2JsA%!+!*0KM02t zR#ViH*Y*?qL)O9lypQ{KY!ru1eZlKWZ9+UZx@L>z5@SD%MT5LnA3(1K+BiP-jJ%KQ zEnII-XgzXT^X7dd8~2V_YUuUdufg(jcsYlFC?7;Mnw4DJRkO^S=}()5*FZ!QS3|aDaq~m$3xDq^Rj2sg|NW5JUB=m?itc^S6&0+}fV3bZ=mDSxvGGkXRqy z&+b58&Y~SI&USVbWhMchBpnM}w(m>nJ^lF^mC2$pt*YHbMMrXD&_4fE!|6|H*$8KQ zFm}7DWZurgL(qfC|0hU~1h##z7FtgzZ)hLGv<&Vr(U5C}=`U_Ie-C%2g}BO8C4asI;BM2oXfx3=fIg%-MX#oNDTRAO5 znaMP`98N$@|AVbU=n!Rh%k{7-V}d!gQVw@hnup~k4o1*`H6C(@cuCyP(Nqt#!Af{_ z7$p-9>{j@IjnO|3CIxB9=-(VXLXL#+MK>H+Oz9j!v~lbxl#4NBhbay8F_Evze@j(^ z@Pe1$oSA#7R$j92sqLT#<)#)JMGH%PkJ6vnN}V?HH;Z>jOh=vP;^gF1>R?|@(md{E zmD9>uHFY`K+GDMg<5i)aw8k3bPHa|aap8}F!>$Xa7o&3X`a>5)w|e)9 z-&FPQ%@(I>v1xuAxixq<7rMYfE*e<9`pYto*_O{@G`z9ZWeKxGZ&<-@UT9b?JX%k+ ze72lQsBNASU&&rHtF=MW)ViH0;ldzQU;dWCRuk{?Gss+XvWL>|OWy)vsD}=`Aepw? z6TNv&HH=#*rrV6KH5DB_Lw+%Z#9a(bUKjThPI%l6w9~NdjPEnC_;{(BCn?%hr0*RT z+JW8}ist=(no-mXOsjADPd>t{l!!^rFq6>;xuM#%oy>=eK8AItng0WYVHWirBXF?X zTNoV_qAmRMNj&+@0||hSAsVpBn1#cCUbMco~(ytW7Sws_H8pwO_g){g=n> zTEgs4_9e;!=K|>ymPy12O%aJr&w$^be(yAv3Vu+1t74}=f9Aqi`q;9!g)01LpMa<& zV%p?trcGq5ZCpL~TdZKR<^3Co%0If!$MDFx`v&KwO8iEm>8-jimw@@U+uD~? zwn9lGnR5kgHfML!XGau{QS1+gy-A0dEd`RS)g8O2Vx-cuPxCA9?ct6wdJn}};bYEF zy>0U^$84eI<0K7m@d9c=9lAF)CMWrw)UB(7#I%M4jS;`$NG>_z{%fjFpeWV0a53uzqjhSIFk^{_5A$>} z#b@7DY6GOH;NBz85TJ1vJ8r5$_VRAL6z~QYflX$l7q=B`911}m!78)YZ%jl4<8c;< z*Nalp)C+XwZ34>sxY(4)Mqgd#V<*-fuk2|LLq>@;E&I7A_GV9udDvgjNxanTfj>(2V^4%O8@`> literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/dotluv/images/ui-icons_98d2fb_256x240.png b/site/vendors/css/jquery/dotluv/images/ui-icons_98d2fb_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..b077584035a7f9f18c7671e0edd310693fea9654 GIT binary patch literal 4379 zcmd^?`8(8o7stP|*oKTPTMP;*OIfmwZ7f4%5K$=x$-eIy%vf)ct&k#XgzVWOGnB0) zyAhc|dJH^u0mf$_rt0625qK=&p9fKE$boe^^S zlCK*coTe4i8y0%chiLylks5`II9(j$e-mR4@UqE48BK{%Su*D>ytN);`8mF_2&-{x z8yF()ieJ4c6{8SG_~_dEty@`F;6pR6y#Do*(uz8Xqg>H77(F<-&^|rC%AJyf*6<8Z zb#@*yI0688@^xL5MR4}YeP)Nr26p;hgR=SPG-)@N<-10zPFrd2ZsVR6FQiL{{jZPj z9G`sS12nwhY$;OlX@WRIDIpLzNGO>q2=p3?iHZsUay`2h9Z9LECN9=&!nIL|rzbiY z54!aADkQcdoXHN+vt6hET%%~}83(5dh!2Xy{+hH64PaU&qye6wYpJ# zgdnrz8pUPqrISn5K~pDM5+Z+@;Y0^(P}fCfpH-t?E#)8JkGfI!K(bchKq>g>$`LBcW0K_uXtq# zyOZ$)n$82#9Itzre35uliJ=#2T&g-n-MgJ-1H<{{eH4@_$i$^7!j@SiQn%Up#%$ll7)lFmgZ;uyid@M^)k;=zJ7gRGdcnO=( z{=g0}@D}IRIIVnT%}2?hyKHpgDVENuCYR7x42mE=ncaqaM_lBMgGTaTYRZ4C$78oV zO3%ge-6WX)oK4WVK)^I9aJm(;(^)PFXMfvD*U1IHxi`~UdbU8-ycwwiYOwevW?C(< zOnFN2g=l*i(XA6)9Y@VX>v!A(zePfIcVlU)1Yrp3_)}NVH(Wy8dD5t?p8ZO8NQyz6 z`h>FP?69o_^~#O{N#WVAP+T6(AB7*#D%1aRAkBS|R0XJ?zpVRMuj7WEr4Y}iHEEJg z2|op1=8m5RAGfIeek;Pux|);{pvHtH`U3XAN7+xvFu(lTn1h+zOtc#J~vG}>4weu zOAAb@wr3XTb>84~EK&=|#MN39Eh=M}zSSf4GXCoA)MfJ+M!QiZ1_Szk;u|E^kAPRE zFDtB=!*qI4elpEKTE8^MK+#LxbFa#yhn&_WL>0I-zByuFvsFs%@lGMK^mS5K3#_#t z?%n*FlFYdBQA4IOIN(FW5!O5EMb-_r3BDs7u_T+RZ4z;fn}5!dm+OGwfe&u#!%W0w zpPz7Z=QMRc7Ez1vhx<@gj0{d`qV%loNA+nl6o!_#uu!F{2a zyFjO&yBB?&o>twXAEimM;!eItmAEy->g!34E7E}yjU*UCc*&uQKT=gKukuSVC+jj~ zb4C_Fy52wVv)^c+m((4p<9otCQ-Tlb(ckeSqHvGPQOT6_X4L{8t#<@9o09hXCm0c- zu^P?)lsc?!Hydrga|oyBhX84n*cavq{E);^$j#hr zpSPV3qas_{JJs~ad|4($`aBz5=x&hqKW7re)wukh-Ed@kUB&_9T<3TB3JM7PmP?v7 z3w=>Lhy`Q9OoH}3tQ%NLt)Xv?%)~or3-b;Sf{YDfnM%2eqI3EDLjV@ghpeREvU#cH zE9(Yx@}Y-W7pVT>e~{Xwx$fk%EmZrufRY4XaN<#}1Ne;*p&|E>*TO%KRp^}mBT~Gq zVC+RtL|*kVg#-It-`xF{UnMGxSuG^ei;y*xsdeIRBC-5C1IkMidKEEktkuQ3c;QZ9 zT0R&3!j_7E63DxNZ(!E}yiCjhkc{WSGJO*~JYNaJu54e?Z7-TGe0k;%ySlDn#~e-7}rAgcFLIK7;~tl7<&-hikCf3WP2a8O`uHj zGz5{Dc&~!-!K6u=Hh?OdyaKfX(f55E6-Y1IZnh2Ew& ztXJpi9I=0LJ2@&wW@G7RWYv?oito99uaq}6cvtG)tAu(F@K#T}Mj$M6HQYtW+*Z*( z$GuTywnh{}4Ky2aQgqCe>CxhkTlwMl1$>Kcy%MM= zWM@9^5LDWg{Djw-z*i^?_B?dgZcm?Idi0L_nfUWBlTM+YO*vGzLjkHv9R+IW=R}PE zI=P&=#>zv;iqu>hzwp*HzsirW^t2u|2E5TMb=z^urXI z2Fw+ufn8ug=0=gkn~87F2AY8CI{#Tya%LJKsyTj*aqL{qWWpt_SY08Gf291RW!5WS z+lxRb+w$Ip7do@i-88CEw0KJ*u6#l=?q*0+-b+ zq9GzM4#=q)5fxnq>8QziXsa}_+@frZX}55(;|@2-KGHv{M>I3{2XS-~BYy;9KMIB8 z*HToI*AEi>f;YhZJWu*|trdpPe8uTVZb3XYyXJ~z6JtM)M}s`q9zkyeSUWuPhQEcO;PO_G!M%FMM~FH>Ec zIDpeNUp{eVH^O@6aqKIvX^EYMC&Nx}^0H^s1u?*c95_%8<`LX;>)NeBj=b_02fVr@ z$vVq8ER2 zFlMK!WWmY5x9p+c_=6 znaNa`ES6tY@1u=;$S`?t+vTV#W0EPgQWkq#ikta1mL9K8-+06o>?!^*M?)>Z8YAx6 zVVI0Rv|Z%|Hpl)vni8NUqkgk<3p(J#mt3)6QN;^*k;d`k5Ke~RUB)!fr$pW=zikzD z{7W7_GbXO-S~-cnXEuZGd3{_=}S2mj)*^zyil2(|XayAJlMky-N* z+*M7|tx8N5b6_C>kkEI2DfjhG_Sc2FQtIoFd$Cy|#f3ixj=CknBJ+3r0c z45{cnm@7`zWYriNy)$?}7rMw!DjHb3{>vhc$%fZ_EWEMRc^SP+Ygol>U20e>Jl;sP zc)pT~uWg(-f^L;`a`7 ztpG1HS>s_p)iCNMy45HBColeWO2iaLsPR~Y>~QV+Zf4k$w?W-mrvE^qnM8cX@$AeG z7RLq!sf+)77E6BnNF3m$iw3MS=3w&@N}2|APvw+0i^@iFrZc1hW%OjpXKUNAJ0H1k zg3D?xokBz2g|vc2fJ`HBa4lm&Ejw*1Qgt^s5AqB^9+^qHP|&x3y$6e9f7ZnB@vt`@ z>_O}oCn1*S^PJ#|K`c}w96^l&5YQ`Y>X~;ug!?X2mZEm$7>X@dSJSfLa}W;sWOSp7Zv`@)cg-*k%f&q43kY zVx;Qz`>xyuoBjZ_k*4i$7QXB=+r&VcV)o$CGMfG}ywA-$Z^pxH?IqFI%2|!BZt@k* zn}Homl zaMlYnmh1xcE2?~g9XK+I^x+(|8yL454<=U?U$|!oE2Hq0waJE8Rehr&4@wWB|MH|= zQ;6;9fp}TKd;o3IB8d>8AuPV-;s5*d@7=~yfsZQhlx_7E&RrT$A7Ak@SAiWL;Ng`7 zben9=jIp$pwTs6=izU5GdH*K7@{f+w2`qB{q5eh565r8iTB{BtRTXdP$#1sfy8iWy zjbPGf=6pe$_4&Q@xl#EOBwN^s7x4(aEl-rOyk{F#j8J_3d13W~9n2v{H%yELHtqz~ z-7))m!Wv>WK~x79FCrJ!p!?I~vJ&5k-8$L`Y@5deP_-&(!O8OM=8%SJEF9Upc4>Gr@E(&x&$(c{@@BZjX1UgR^ zXY2|O4Ye725`~?^{d^Km7 zvm_}+xkOXi!6Us+icJWtw6zspHbULW>b}+pWQrCL& zmvY_c;54n6-LTXr_W$|+39oqQnbXBF0XH!g06unk2$LBpI$QR>}tB5*} zj-e6auEf=w(y@y1gpY2$U%OTG1V1$6%IjZ0DXplJJjxYYgF!(lg$^0{RUXtFw5C@? znv2Uf!y^Cyo^o9eWf?+TxzFM_*}wtqH7uKtNtbbVUA}9q=Dd~e;XdwF@j|9_INV#Uj@fiL@?VUdbaBfo@*9OJ>%q31@c3X*k6-&VS&u6gmi!x@LHN33Z=d7k)o7c z(k-O3Sk*dy)ePZi_DEYh=e_KjZ#+BVZOr38AY(W)Ro8))Npg_HxX&&K76Y0?azT9z zbYbu;rABF)XX)fpb@0@QwxsA^X1LHHnzVJ%*=NfY@v8ywCr@1vs3fTpfZk#;PiQF_fTH*Slx zfUTH>VgsXZ3I~A#&Q=bRZe)qu|0oF)SijA#rC}B;aC^L1^J7_}s&qakrl6XI(Obln z{s(q|fw#D{#%t%RXgx{^+hu2vNVRfFGrfeqVps(B&FVJVJL0Bn95hmf(o+9pJpsGr zS$Zyx|0cog=WL?x1p=l?k;}c1gTZP^g!pwULpK-n=H5(a>DdA`i)N%Mu)*?|xLLK} zGW99d53J*9%&<;ya~d@ltKabm`Wgk%+l`~E5k$bK<4;||UvY`?=gFgT`VK3^&{V^C zjR_U4*HiSHsnbL zW&9LqnI~Zybljr;`>iM++iG%ZpgJ3x3`LoWqX6e1cS`v(9TZerBfnmQ@zU$HOSZx& z%QS4x zUs_;Rvpcf@)qR80wM;9ZkXCC^^ytiCXsc)3W&G9KY0DO|O!lM7jE2yE5*j4ej{vXC zURGGMgzNUA{AHT~=>syHgGDd(&b=y+`R2SXDW=Gy`PB*gn!Qqbk8cW*ZJ?XBT41B| zaPMY+Y6{cJM@`wvkiZWOM_8Ze7uh%1C-{$Wq!J=?+a%%|kHDN2ANK*l6Ccvlhna{c zo}X~{;4LtzV=S4?h={6H@EY z(FL0^lVOm=clk%IPM&UTtLK%as`?3nm*GA;89w}D@y^WwDS+$`>nl6oBhqs?Kz(7D zyMRu84{vC^zINTCAEn8163%`{mAEyd>g&l)D>6Znjbs=?WXZ8hAWBU=ukuSV7uzy; zb4Ct7x;`-YbHI3?kK7%l>vtkBQ-TlfG1&1Zp>U7OQ7P1nX0-xe?RNxq+miPCCm2!T zu^O%alsc?qKO5t)a|nkDz=KNQon}(X0 Qo`fmd8(7Bs8`2@Z91C*<0dUeN_+~EA z_id-+sOXl?PBj#nFUO3?m}h4Q+YQ$F=S-r6I(NXc8}2M6pQf!GWfL+&vNQ4xXPa!t2k zg%-5~Suv(8WJuq`y1}Ki8fa@&7T!@ugl~8VXkr-0T*_S(lgl3v3Sb3($WHz(mzP$) zvTiu15O$b-fff+)2dP7z>rOe_LUX7KEJ^eOB^~8Dg5DSt8gdW$ECce`gwF*$A}7cR z#a;A5Sw7b|AFWd=A z&*z3NY^eq$1APkk2X`Go%cM*IlIc81wr_%$x1TWV#;)$PkjEtkR17X;lm^<-4ib8| z^N;TYagdQQjw~ZH^Yh{=yk`++MArDj_!fq@Qzm4m*h6ilxPy>ZyxegT`}^2!0(FwN zA(+g}cNK&WA%B_>7RmEmEoJa;Mi~S4@Ux!^n)P&`3SDgX>FC0Zrf^u&%j51Cz}r+Y zksub@rW>pDPH{1yVCbwCDwa_wt5mYgJ4;!5w5}(c1jL8 z9*wHIMVS{@ns2%Iwbs5J5q_@ewBB4?SD_GOsMU~@s%x$SMN2$x6@cFt^eejcO0b?l z%zE4*q`WKj39mVUuTUK7dFY|jo-x1l=pD~9iRWJ?ox{AEa%k>{f;81SD#Xa&nUv5! zxtz7e#!JYK(pnn7@YXE9%Ac_Gv>r7Ec%xP7zT-@!Cf8q;s4du>pt1I%PyT&pjKZt! zmVfG+N$qxZDrsgBD(6pBYDtGw2k?y~CT3L)Tp4_4o_{oHvj2%`pXJXj5}KlYU+tkh zMl--mU3=c53@g;v(s}0_wGOQ}M`l8pTw~1e8R?@426C9CfG}g$C*JFQmx@*lEP{OD z`$pjv$E(H9WV0FX$-|o-Aj~GI_u4tjP-XqzcOt2l-;^t&l(M^GR4_`4H=4B3`1!y&K?$>CElOD^zEV zb7NDndjNU&Zw~c1$N(Y^=;gK3LTDWS3a-a}Qw(l>q5j(1G{Gh>vu6KK^V275jaxak zAns^Q>;fY)H<~QbOnQ4Z$P`%D`OliN3-bs`-Kjs;sdG7t8JE0beT6jsk@}OKRj+bw zFA||*$9ETA=)%r$)8xixoeJJGOkra0%vI6Q&nv%DP`5mn{5pg5Y4#S<8vob}URJk^ z0gJ*o!KY?KOl%pbt1joMquRuJi@GtU)56VxJKUi7%KWSz(aPE%!ZApW{1J@%C>()b zOI1r*KS=Zs*#HgjKIz-FQ5-(gkJFXf0()+D%@xZf#eE!)0eY=Hg4_tSaeU?(^$^=z zxY3;0dhE3B&HGq3{ym}8(CfQjgXNcq(x=we2Jy+Un4qay>@8Zl6c^u>nQOV;W_q^q z04}$Dg`}0;NSm3*aj(3mC3hB{3_HKcBhF?BVE_~IpdfjeXGqVjYqy3t^U7Zw@ad7I z>a60C_XNgTm;jZ8t63S=uCt>kD;eNP(y_o2eP2oM>o3fzOcjl5RqZ7yI+7cM4)~`V&VEiO!kz6w zn4PMU1v?85K@TSXpFlkl$o7L;Xg$8Xp?w_PGPKJ?L#!8Oyu8!=J;Iq5;wo2Cg6!B9 z*FYjKKrGklRmPhJPws*)duHZ1k{#^50P0L_2sQ&7K?ork*meBckxa2m4+yZ|&S@FW zN}<8zumWoOA8i#vhbep8u18gwlgw$Aa@gC_JS?}dP`n1T@rXObOX6XUrh1?aM#8JZ zCIhelrG>!8^@1BxfnxsnbLuulK86pw^cRp zFM0XRnYpKH79Rvjm5v4CF;FPEJmx4)(QV&68eM zIjx*Elb6RE2wJ$*pQ)txT5INo5gVVL(~Ecp$}c7#{ENdv6>uGq>g`E)9Uau7vgadt zs+we4m6vp0<2m@7p`CEosO}xv`A#%;h9!kHjd<%pk!yR~mGHrJ! zd-IxV7`Ks3cNyPkDmr?G{9+1;zZ{sdA?_!f_@o=qPQ$b_e#pY$5~OOLrfOG_zIRw? z2YRC^nhytPM$s?Pt-cvQ`S7n(Bd0jSOvWPRhHKY%v%;5r4C~G^{|6GyEb2Rs=U{oT zI5s3iTm0vGkIbc9sp#9k-h(8tKWh^9csUvm z_P`E{lVGd!dCu^~U{)H1&NsMa0f2~xMZg3ByXP4Hs$UHEohdSTx$VM9Rg~S8!D$nr z*Z0D8s88KB4Pd0q#Vyvk&5B=OZWE6V(h2td0j)ab#1+K-J?HI>ex}28>&ehfu1DFWfVNl~MW2+TnlEUxIlq@NH>z-gWDg(lCLN)-6-csH_w1sJ5lYWLFRXsBhdIXTg^RPo#+@O0 zJLdf-Y@y~8Bn?pUB63k3vOhg8C;6S!t*e8;ws}4PR;vLwY{)pem3Ds97w}U@h|U|0 z&L#gl3e_&Z4NiBX@sGSf4W4nprGjLG;bqgP^u4c)ckWKF4~xGH%gZQSq{}t@>lkof zHMtF(Z2~S0oL4zyb5cI@dOYK=q)!380mtX`GQxNFz;l}#Vt@_^CF|+^-5)(kfXM(y2K{k0%|4=jo!0 z&%dwK29TzMdyhRs0F8T?2~!QSmv`fpfVbF4ObR2txUFFGNC^BGT1nivH5nOgVxoVseLcO3vgCnd1P1UZS6 zt48}LY1!03W+Nl*x<~l_h)D(ntF~PJr_ZtB5*}j-e6q zw#4P@(lLs0#1C%0U%OTG1m8E~%j;h~F0H7OJj@kag~Pzfg%0WYRUXtFjHXw3s*B4v z!$SZ-Bwy7-TZUvW-(_)}XyAbL8kWsPr^&dxF5Na(bKXqza3AxkcrH^q6mWHH`{?*9 zKcMM@U{8^bPZPo$NehF(!NSQjA)wbtTue+5knh>4=txRMH*vFN6R(Uwyu2{U1ki;q zmm#qg;mr2Po~=5AXPQNmPdT|%LHtk@?$?A}SRnHXF%9qnT}ib=qqWyOl9jSbx`lKW zs#?b`n;{*|9%yUlypvt^jblf?iGK74Y>Z&0>N>D8Ne+-0_t*s?Vjy#9F1U|@E)1EW z)F>_SEFNE|4xT*LmK6QVG#4gBleQ*0^RycMaxs6OaM+E$1L9cP?8$aIZfz@hCn8eV z$zMVBmRvH|cFV5uvwGodd=|y3_^bD2m`Q9AXv(+?i>r@m{}HWkp-~OpQg$=s-TCqM zq|<`T#}_Qts}qpcp3&xezm?9zchzAZYc}@@ALNz)8!jrEZ{WeR*PU7BugZ=T_4#>fY%r8yLzj@1vs4K&Gxu5q2!1k$TN8*KUfmK&+UA zVgjSC3kQJ%PFD_)u4Rhb|0oF)Si8xtrC}B$aC59!^FvvJs&qa!x}chc(Obln{s+E~ zMYOoI#%brPXgx>{+hJ#rNU?HBHNAkjWLO08&FnVXJ>;gW?>ABgQ&aw9EgrY&S$Zax z|2om^=S+g`IU=@6k;}c1gTZQ1B>U@Tx^6D`^_}U?($fWM7R@MCP=n0R<}_k1R=@2L^feNyw-ZZOBZ@%KM<2U_zv2_(&XPyu^c|M7LsJanG{#l5 zW`^t}X_vMY$%;>Zh2it)0cgU2cA3HFeHotf_xpt`W@Hwt%P|uY{(M~%7jVq z5>NaT_^3tw_Zv|@ww0umKy@|@8HP3$M+0Y|w@Udk928VqBfegN^U~|JOE$wOSgU93MZ)EqsY@0yO!gznjE1m(;u|E_4uO|uFDk5A z9_sd@{biehw0;@Rfua|BXI_>^e{)`w6jS8U{OW{z#a=1B%QuP4GSE$3DX`JGzkB^l zN;1>(2Tj?^kihp1hd7_8=ULa-$N3NOq>^mrwh81F9)VdaKJI;@Cn2P%4?7;0eRka4 zgUih0NK`!{0O3nrHa0w=iQ2Qe7uClV)H5d|F#~C=IZnv{w|tPE4u8L=|jA zPlQ1e-sT^=I(fRWt(;Yss`^3{yom7GPWRy-jdN}eNCvXruPtwX4^PYC0QZGqZv&nB z9^SAxeeJpjKT4D2B%J*YEAgvF)mM|8mSut@8_95_$f9GHK%|;_UghUvF197e#f8ZOuer07e4Mg!lubyln0?ne_~3GEJJ1Cw zAaM3VsqVi|mqEDfl0DO`GMsFQ9P($OA~15(0(m<`k7>Xp*X3=#q9T&8>6&K43M*;{ zv0_bG$k4v~bpwm3HL%vmOoF412;a~k$iy&~xsv^wr`x5_X}~zja}VoK95Tbq!?VtC=Ifs?Z@|Sh|~$*hF~%? z-(@f%g#2+_SR~JLrIf+H8Ep*g5@tRYH0$ZW6uQ{%(lLeWO%LITFOIsSfj22)B0(&) z4L4TliBB>hhUF^H%102I!U$*{RMU-n^)!$dJXQ* zVTZ>zlcQo}*B5_ARz04r_@4XsO8L-2cBJpTOsMw+Z}!A%2Ej8|!d-(rC>cVJM&S8 zkn)byM}p=!p+a%6=e~zdd-~ksgSR|SC7ykra1Qfo%AvU*2+~yRs8Az+XHxu^iKWa{ zHeO;@q}Jltxi@C{RsO`qC-vx2;I&q%`?hm7HL3oxL~X&wIE}RzbNugHV>Cf+r~G5r zbV|3YQ%N(6P&t2sQcD`NI)HCDAtAG>|I)x)^ZdgJlf92jdn|u$kT4YOyK494v6=y1 z>e_P_WjLX}md;z>sC5{ICU;%GUJn$tuK+rK2U$sGwW5Z>_#9} z?D%dY3SHP4uA5xjs8b=BhAE8ip1Ld=`f2%BGWv$+qF-l_KF!`jTH_yk!Hepa(GXEM zC*;J8h>0zMbk*fNbyS;JZ&24qby~PN@CWM@UzwlP!&;epgLnqX;Xi`0AB4jRt0`*9 zYx@cQA?x6N-p74AHi|>1zTkDGHX)uHU9-hrLFdGkJ!jeAEdHT3%K*I@ZMy!45+wLx4`3^r(T26uy&CdI{fY5Gd8x0#-89Khw4 zuaLOB6Jay`DE6iIl;rmO<00qQdD%1RLRes29vmbO_YCQ|aplG!XI}a9eLg+1RGn2E z>W;u@3lmUDyquYCT^`n7m|+#P^XqN+_6m<3b+Ld0Zf#Fix;L=7tR`6oNURUCkJ;u`DXsQR=U?sddjFJfl zb}M|q#^|31lY+El^luIxAxA>^q8kn@rgV-V+BkL;%EcJ6!;}X4n8;VaS& zRhijx7A!0X68swD zW{Xp`*fhV5+#0-_3tiwK7Y(dl{bd=)Y|Cdc8s6CIvV_^8H>_YcFEp$c9<8TZK3h&D z)HY9vuVgQp)!HCwYTZthaAAPUgc!AH%xS%>RMHFpK(*5ja@xEsPEd z(H8#sB%b`{fds(E5DnO5%);j+m9-2Rp2#b26qOC{KwmhGH--S3V zOhBy8<~bu4f>~)4I^V#i1ppNd3x^8=J7*aGs$UHMohc$|sqNfxRixdefhiNAS9c!j zP@lMK8o)^z3!AL78x_AG+$J6!q+{IOeOh(&u`8JSd(N9{OPBb7Bil)=rs7YZis7nP z@49juZ2JQ-##(m2S^2Y1ZIOcLO4);lOBmQiM4!7)-n6Ir>I;&ewTn7K-NZ}04qj_sIL_rJDAAet7)y!k9tr6NotZ0io+k+syqtH)mLpTx)k@MmxuzBG}H+ zS+ff?E~)Vgb>Jyz^7}K;ZeYxMEQC^3eD01Byo}0U)+QHTRrQsQ+ArOY{>$TbEn)U2 z`x0e=bAj{;%OqlirijF*XTa}Izjqo-1wW|1Rk72bKXYL$eQep=LKS|rPe4=>F>P`+ z(W*DhF;eN-r}>rl_Hf4-y@%qg@G)no-nRLd zW42K9agqkOcmcJb4&9p?lau^T>ekgk;@Uj#fvVL&>o#OO-AX&Z=`-YsBUIBG7rfFl}FW zV5Gy;lPKa69?-k=l`5o`#)#i=B$pg<|25SoP?Tz0xR~{V(KqRMP z>IJ&;HUZ^*Tx?2YqpvRWu@mc#SN61rA)~~ami^old$Xs-JnS#%BwlKE^7I2&^|5-D II=IOH0a+rl`~Uy| literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/dotluv/ui.all.css b/site/vendors/css/jquery/dotluv/ui.all.css new file mode 100644 index 0000000..67df307 --- /dev/null +++ b/site/vendors/css/jquery/dotluv/ui.all.css @@ -0,0 +1,406 @@ +/* +* jQuery UI CSS Framework +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. +*/ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } +.ui-helper-clearfix { display: inline-block; } +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { height:1%; } +.ui-helper-clearfix { display:block; } +/* end clearfix */ +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } + + + +/* +* jQuery UI CSS Framework +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Arial,%20sans-serif&fwDefault=bold&fsDefault=1.3em&cornerRadius=4px&bgColorHeader=0b3e6f&bgTextureHeader=08_diagonals_thick.png&bgImgOpacityHeader=15&borderColorHeader=0b3e6f&fcHeader=f6f6f6&iconColorHeader=98d2fb&bgColorContent=111111&bgTextureContent=12_gloss_wave.png&bgImgOpacityContent=20&borderColorContent=000000&fcContent=d9d9d9&iconColorContent=9ccdfc&bgColorDefault=333333&bgTextureDefault=09_dots_small.png&bgImgOpacityDefault=20&borderColorDefault=333333&fcDefault=ffffff&iconColorDefault=9ccdfc&bgColorHover=00498f&bgTextureHover=09_dots_small.png&bgImgOpacityHover=40&borderColorHover=222222&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=292929&bgTextureActive=01_flat.png&bgImgOpacityActive=40&borderColorActive=096ac8&fcActive=75abff&iconColorActive=00498f&bgColorHighlight=0b58a2&bgTextureHighlight=10_dots_medium.png&bgImgOpacityHighlight=30&borderColorHighlight=052f57&fcHighlight=ffffff&iconColorHighlight=ffffff&bgColorError=a32d00&bgTextureError=09_dots_small.png&bgImgOpacityError=30&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffffff&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px +*/ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Arial, sans-serif; font-size: 1.3em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Arial, sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #000000; background: #111111 url(images/ui-bg_gloss-wave_20_111111_500x100.png) 50% top repeat-x; color: #d9d9d9; } +.ui-widget-content a { color: #d9d9d9; } +.ui-widget-header { border: 1px solid #0b3e6f; background: #0b3e6f url(images/ui-bg_diagonals-thick_15_0b3e6f_40x40.png) 50% 50% repeat; color: #f6f6f6; font-weight: bold; } +.ui-widget-header a { color: #f6f6f6; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #333333; background: #333333 url(images/ui-bg_dots-small_20_333333_2x2.png) 50% 50% repeat; font-weight: bold; color: #ffffff; outline: none; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #ffffff; text-decoration: none; outline: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #222222; background: #00498f url(images/ui-bg_dots-small_40_00498f_2x2.png) 50% 50% repeat; font-weight: bold; color: #ffffff; outline: none; } +.ui-state-hover a, .ui-state-hover a:hover { color: #ffffff; text-decoration: none; outline: none; } +.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #096ac8; background: #292929 url(images/ui-bg_flat_40_292929_40x100.png) 50% 50% repeat-x; font-weight: bold; color: #75abff; outline: none; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #75abff; outline: none; text-decoration: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #052f57; background: #0b58a2 url(images/ui-bg_dots-medium_30_0b58a2_4x4.png) 50% 50% repeat; color: #ffffff; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #ffffff; } +.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #a32d00 url(images/ui-bg_dots-small_30_a32d00_2x2.png) 50% 50% repeat; color: #ffffff; } +.ui-state-error a, .ui-widget-content .ui-state-error a { color: #ffffff; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #ffffff; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_9ccdfc_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_9ccdfc_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_98d2fb_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_9ccdfc_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_00498f_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; } +.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } +.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; } +.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; } +.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; } +.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; } +.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; } +.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; } + +/* Overlays */ +.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } +.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; }/* Accordion +----------------------------------*/ +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } +.ui-accordion .ui-accordion-li-fix { display: inline; } +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; } +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; } +.ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker +----------------------------------*/ +.ui-datepicker { width: 17em; padding: .2em .2em 0; } +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } +.ui-datepicker .ui-datepicker-prev { left:2px; } +.ui-datepicker .ui-datepicker-next { right:2px; } +.ui-datepicker .ui-datepicker-prev-hover { left:1px; } +.ui-datepicker .ui-datepicker-next-hover { right:1px; } +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } +.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; } +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { width: 49%;} +.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; } +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } +.ui-datepicker td { border: 0; padding: 1px; } +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { width:auto; } +.ui-datepicker-multi .ui-datepicker-group { float:left; } +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } +.ui-datepicker-row-break { clear:both; width:100%; } + +/* RTL support */ +.ui-datepicker-rtl { direction: rtl; } +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } +.ui-datepicker-rtl .ui-datepicker-group { float:right; } +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } + +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ +.ui-datepicker-cover { + display: none; /*sorry for IE5*/ + display/**/: block; /*sorry for IE5*/ + position: absolute; /*must have*/ + z-index: -1; /*must have*/ + filter: mask(); /*must have*/ + top: -4px; /*must have*/ + left: -4px; /*must have*/ + width: 200px; /*must have*/ + height: 200px; /*must have*/ +}/* Dialog +----------------------------------*/ +.ui-dialog { position: relative; padding: .2em; width: 300px; } +.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } +.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } +.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } +/* Progressbar +----------------------------------*/ +.ui-progressbar { height:2em; text-align: left; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* Resizable +----------------------------------*/ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; } +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Slider +----------------------------------*/ +.ui-slider { position: relative; text-align: left; } +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; } + +.ui-slider-horizontal { height: .8em; } +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } +.ui-slider-horizontal .ui-slider-range-min { left: 0; } +.ui-slider-horizontal .ui-slider-range-max { right: 0; } + +.ui-slider-vertical { width: .8em; height: 100px; } +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } +.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs +----------------------------------*/ +.ui-tabs { padding: .2em; zoom: 1; } +.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; } +.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } diff --git a/site/vendors/css/jquery/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png b/site/vendors/css/jquery/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..5b5dab2ab7b1c50dea9cfe73dc5a269a92d2d4b4 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FscKIb$B>N1x91EQ4=4yQ7#`R^ z$vje}bP0l+XkK DSH>_4 literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/smoothness/images/ui-bg_flat_75_ffffff_40x100.png b/site/vendors/css/jquery/smoothness/images/ui-bg_flat_75_ffffff_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..ac8b229af950c29356abf64a6c4aa894575445f0 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FsY*{5$B>N1x91EQ4=4yQYz+E8 zPo9&<{J;c_6SHRil>2s{Zw^OT)6@jj2u|u!(plXsM>LJD`vD!n;OXk;vd$@?2>^GI BH@yG= literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png b/site/vendors/css/jquery/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..b39a6fb27ffbb1f3712e6cfa09e32d8ac084469b GIT binary patch literal 144 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAGVZ#9R3S1;RaD978O6-%c^)YcSwpKJWJD z|JpSjLTyTM0au+P{Q|{~ccrfTtih}jaMj?JLB%GE%IBZ@R;P8R&vh>hKRn4$W8y9m tv41~zz4&^o`JA=qud+j;_MeV>*a(IzZneqYxgKZ*gQu&X%Q~loCIF^PH4y*+ literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/smoothness/images/ui-bg_glass_65_ffffff_1x400.png b/site/vendors/css/jquery/smoothness/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..42ccba269b6e91bef12ad0fa18be651b5ef0ee68 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouqzpV=978O6-=0?FV^9z|eBtf= z|7WztIJ;WT>{+tN>ySr~=F{k$>;_x^_y?afmf9pRKH0)6?eSP?3s5hEr>mdKI;Vst E0O;M1& literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/smoothness/images/ui-bg_glass_75_dadada_1x400.png b/site/vendors/css/jquery/smoothness/images/ui-bg_glass_75_dadada_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..5a46b47cb16631068aee9e0bd61269fc4e95e5cd GIT binary patch literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq|7{B978O6lPf+wIa#m9#>Unb zm^4K~wN3Zq+uP!ti978O6-(K0sd%%E$<-qfe zy5H_kW;AfU6yYV-p*iPSO9q3Y?VZ0$3?Tx74{vDV26o)#~38k_!`W=^oo1w6ixmPC4R1b Tyd6G3lNdZ*{an^LB{Ts5`idse literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/site/vendors/css/jquery/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..7c9fa6c6edcfcdd3e5b77e6f547b719e6fc66e30 GIT binary patch literal 101 zcmeAS@N?(olHy`uVBq!ia0vp^j6j^i!3HGVb)pi0l#Zv1V~E7mI3`<(O3xvulR&VAkQJHZBho(m=l0{{SA7UpJl008iB z3Rqvn`1P1SiomLXkg776;)RSXXXV1Iqu_@e2%8dEPZ*NvG6-d*$oWlBXKKg zV({l@ll0gM+F;pm#SBg*2mQ!Rn_HBhT&5w_d`jyG6+_vuxMHXoKj|Yh2EGJ-B`N+E z$pmy>sA-*C0S`BfHv`&Y>Z626r?uZY8?`zzbXj7u1}` z;TS<~e1eY(jD4j)wElgyeR*V7`qdhf3S5Vcdq_R*a&F^r|9|M*i>!yeL)xMH?-6M_ zJjl&7(M|RQJ2z;fI7;E!$?Pfq$usWpjLxzlazT~K6v`ft@@P32;&o$5@b}Yj#d~r) z9^2%vhdyIgOXOGiCNOR_sjx3j8*01pUqQBn7r}I@E53HUy&DusRETO9wG~Rdfx=Ta zwD>0smtXx6l#X>f`lTc3c!pmLbwTP$Zfe7s__87<&i+s33P`Udim99RAA$T_Y7T3^ z>vV9wL8Sc0x! z_eRl4cEFZ`EXPfL3omdIIY|MS@P4-79I_Af%(!ONP=msk&*mFs^(0gOj->4HEJ}Ca zL(HZSEXEQH#fbJDfQ^RQnvtlx$kD>NeLhPB+yUp!E5O$&?fP1}JdI;l4(=H(hEfAQ zNRU;>uU@{f`2)^*UI^NA8VHraDlXrE*?OWOs z7D#P(ftiy|@ab?=t923@#mR}=S6GNj1 z?mTR4hby}vE*2>Wg7-X!KAz3vwvJ)qVMtB~**$wrQ^&0>;8UR6E7imZV-)iH?Tt~> zX-EGVhMYWVxX}dU)MQaN+jv0*8;3JBy*az#1aW|^_4%i?mlU$yRTy>-wCJJVC==P> zEx=B7cZ&E7jJ@{Z{CG+0A-lAG;ovs3FALs8|JLq?o#M-to~~wx^JI)GhP%l=X?-mS zEbfx}Nj)D74<>(1{)gt2^%v7UAlLYp6gO$gsv=`$#2)3F9ed8@mcK6i!h@mGQqU}e zyItCAfl~4IqG~(AU2lV?`)nu#S5+1BrCJv>QmoI?LyuLj8e^o>li?U6OMey{r_T(* zY8RG<@x>cK$(nNMlhy)E`{;|c6$@%L*hZEYs{mUmt$8-u8m?YV3{83m{YAwB%6Y{L z6k9V^jd0tnd%q4+xwp&Yfr#>WqoooH9K5xYM|V_s8{16~N?TcuYd@6+y1_aS;c{q^(Kyv6DZcFd zd@RkCqyC{5yX5E=oHd-`WBQ0I>9_&^<}<7793`JA=$mRuSrr}iQyzxG9T)%=Xp2g4 zkFI*p1^XIjQQE0yQNGyZNn{h@1;N1>r@)!(21u5LGg2Ob1==Thh`ZXost~Y05y+XE zrc7k%zx|Fxe^LX9HhqjcV~P|W`3AXYj%WAaFNz@uZ-xRmf!NHrNh4zKSO1WrwFL6P zXM}G=*p9v_k=mUmpg-$Y6I7Mt4@y2D+ys?c;_C@aVePnKabqAS%y%AoFzKI#JaeQxo%Il=}>GqqqxhG8cPyu>P?R=}Ol7vhvDcW{Z8i0Zn zzm^YCS5qT4m#*SycTaxzIpnMMHwFrEO>lJzqr0i6lGn6M7x;$7B7Iy)6renY$OiZc zMEFF-;Ff)@RWrYEodz{P?avD?^RtUsN$GEP>xrgxlbtd22`L1q+Vm;zyBzLIj#2fp zQZS2sUF)*%MR5S(jid&TIT<2`Js!yUdi}%lzzxkuKjf|bHvGZz#1l5%O0plla6C28K&%)=R}0F6xRI>HvM|=4x#=-to|lSN^N9P6&xIP z2dq0{CX-Xc&YJNeXXD#dn;c9feR-*P_CfUEp8(wN{z!yEZrI*MPs**fh@b|xe*S&i zHc8i5C2XFuJ)xhg7K~%2H`zsX?JhZT+>};UB5HaE$E92V@>aXAPbP zjHGY7LH_&c+;-7yblDf5tKrky!+N>Vx>?)QZi1hm1Aea(92RyRiFczw&w7)GT*KddVhT(T~0Egdo9qyLRosyG6?!=QbqPzk^x9!b!;O zjEYZ(YM2+oYg-TrJTt9??(26|bMF?&#cgl&%SzC;-tOToW%SoAmvaoExO%bz%?xjk zc(|{^J<~z4;>Loltn&Q#cD-zLlA0oFa(P1*5{sdl$v0#75<`$?CT{uv?urEF5%l#% z1*lLBO|PYH2z}OUCDP!56T6(s<{oG|TOAmiP3Z95>EKzFu=~wRiHd}%-yn`p^?J6( zih27|xpMpU0(-^Ma=J7`xm^&DhSqXkjnQt=LQjM?m_ss!!0cIcfgCXk7TijCGz5At zUKx0OZ(Pc2owm3zR5RS0N)Y#iMfl$WQCVB&sa%OY<#3FtYF&H{`S5{&n#aQKe2Se9 zB?KD>qbcT%&$2w0lfgg>hoa-{bj}D!0GrB0(o9%dP6Pxsw8y%(rU7O|*#fSHYBm2h zyytq$C(2?`j}W=ORiP$Y;41*}G=Y$(2OhqHVfd_b2NmhSboLunMtOr5!~U=jF_g7g zx!U^R$M++HtM%nJWA0HW6A->{j|_B;D@i9waP$)>{6HyW zi?%Q-uGS3xs5_COdmgZjld7Pfo4dBxil@eQDw4^F*Vcb}d)bfW?|OD#N(nd^;T^jB zZea;L9}obXL9cH4o}9qQv(@ovFw_meU5D94g#m>tZ>F(pY-+sVc~p1lWWYncfsZBD zlLUulh#8ZKbJZaXx~7T%9*9kCI?ptUWNtB6zk6wB?Esa@U>adq3-GJsAap@@buxd8 zEh*0kH65g*0pwfcCE82`98Gls@jB5(U`@lWMLxq4sPDlmq!Rv*Vp(zSX$437XGBPqZRXNva3-1V4LK`FF19js@6mZK*48gf-Z-ZNB zLM=}?fKd18YCyN<3I%#wqeFjR9^PLn0C|nbyn1-&Ph!re@O0EEp`97_ouN^T>luaA zQbRd68s2B-M1Q}bL`59M`{jC(<_`P4m+_LOgr`2Gt(Rm4y+wDaGcvik0$;t-0c3C{ zKhx0TB~7CpakFn?r9>!&+;ccIO!hd{$-sX1k+O&#=VmV@?^gOz?c=kZ*8x}L)H)dP zYzhfqNU`(IVUtd)A!)GN@5UL@&OX&+@1C?lb`+!>)>=w1JnE$X>Lw#Yjk7&t)#5>X#Cjs|&jQ!X46aWn?QOjkKm*1G ztbhAifM)AKF=tIbp&vSIPqX&9FQ`BEN|??$UXR)85VQkj*P`!)ht-9)fQ|t&EI}c) zY_Dp0Km2C(q8potDF7er6kZ;VOs*dAVznYFU=Tj)$Gq2%pheYQJdTMt)xV?d0aA0f zf!9BB;E?X!!FWTWHx>8q_1{a`32+aVn2QqF4@>>wO;ea#m&96EhNkjIR(#vwq%yr` zfH0w))fHpM%M^W;nW$_)tb@EVVvhrYi*g_wUlF^|U`HFf<~&JOeBOMX&56=R~^VwL+|j!Ca?>Tx==&$#g^C#2+mS?tyG29g?7BC;5|* zhNhNJ?*-LgdlM)3Jx?L+w7;FK4mFXC;;XzQ429NM`AD>QNUJVX`T3s9}m~hbK7csE0P(!l|C~FWjU=g#?C}12ipKQAA~kz3%msO zg2N0*dRqd|SG=WcPVM-2UAcd>w1y8d%zsl=9Z^nq83TK_9xPH=!{}}AuqY7aaFPnP l;BjQ_^4`vQQuBMqxOYB4T*@HG=I>V@U~v|0R%wcf{y%IJ0Z9M= literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/smoothness/images/ui-icons_2e83ff_256x240.png b/site/vendors/css/jquery/smoothness/images/ui-icons_2e83ff_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..45e8928e5284adacea3f9ec07b9b50667d2ac65f GIT binary patch literal 4369 zcmd^?`8O2)_s3^phOrG}UnfiUEn8(9QW1?MNkxXVDEpFin2{xWrLx5kBC;k~GmFhwsn)TR1w<4t)tA3_robX4CdCOHJC|7j+vW z%J-EMX&`87enIluaSc0_SnYUx$GzUc?vrNXt&I`o?~7C3RJ>C-Ajq!3AfU8Dx90^_ zp3}MKjJzYC+`T(&egFXQ#9Ek{*oVAaa!zrZtmlRFnwQPRJXH<%pkK2*eP`pT=lwD7 zifq+4BY_rUTa+U|2#&?i7>PVvD?7R4ZfOLPT{e9G~G!Ls3s8JtQE`jMM9wl2V9&Q+K2DHW0M+uQmEr%nYJ^7cK?uIpU-)=wn71ZZ-=@ar0;3^AY z5+TI{2b(e%t{2PZ^HKF*vu@+Xr&BAc@2BC4 z_vCgww#i=)ea5Vo$glEEVBBg_VPBj!)OO>)f@}#dg6ULOeC>LBHz<;*5Y;YfE0lNx zg{N+4@lO~ozxpF69qV@VOGnc248Iuag4C1T)P^(hWkpP!{h!JekX}m^Q#b2B4f1oT zIjsGz)4}-$rQ*-tSuc%qG>%<4xM#E& zN)7lRK~^2VdiloY4>;#}A!yHOAXEmEi^+eA#05pawGXs>!z)gSoDuI#>bRCq-qjJe zZ)r=A`*EMX6+)~er1kdv1L^)0-PsAEM7JF$O6G8>496$24lkOSR^RTfUuIz%iSfn5b-t!##cs7sQI);gdAvqmn_v|%I9k;fCPl0Z)R1+hNQONJN zH%3jT9sOq*a`LF*MiY=zlSSQZ;{_FL9M07A=In+O!~wR}=bzGEQpk2!Vc0p)qKAH? zOk{(%06W#)DdICQ_S%Q@<0Y+!?9%#$gWJ%)EO->^YZP{<`oB4~9xh zL9-0*c4@B#O2ylYs_g`Ky$zb~v!M`NRaMNFYF*Gsu|7)=JyyMHjFC=HhGUE@{aI|B zJ~ITXU052%7jFb5Ys#fhS_?4kqc7H0EU49B8(Chg0&JzU=Gka#xOz1)H0d4m7ZnRA z=M^tdY|U6T!fmte{W?_r8H~qdq|q{5AMU_2It1I4143n~xL?4&K#BOB48l9_Rdm!(c^C?JU;tF0 zEh@o1y6Qa_>}#AwX{VY+`C^kNkxhgb1P5cB0%xupAXyg9NO=SnXrJUE?rQg{Lcsn+ zAZKctGLfbK_B#^&Nev|0^fB&?DN=ak8|0!np524LD25=s84BP8Vl(3=jflNp{X>e@ z637Ri5xx;&JNl+XYImA|{;XR~P*svYDEWYJ6I5!6uO~2twFC1ZQevB7#3z~(apxn& z^J@>Mc`>PJair{yT`iuan-V+i%|Ho-pA<1?V-k^R2Q<5;Co%XxmL` z018t4T0TTwO^w)Gx{9OSJ^9_|kgwX`7%0Rw!PO~@?xvnfUehvN;2Rc;^l>3kfbtk3 z8{j7p;S&{uTlTe9&HTc38q@%_KQFk<&n{vmrN7y&Cz{etcE->rq!6HL)2F!aa=0%! zM%Bwo!7TQ5t;@a_#Q}sjk{UebWQZ8{cp&HN^$*JfH#8spkhk{R@CVBiPuP@yEhu{} zsQfuhTqV%rioATpEphMfhyRYbVfVW`YwLFXUWm-===J(byMf!5;W^CV1g~2194Xx) zFK|z{pm%n-)-DRe{Qhk(d!QaoI*y%Wn6h7<6A{i*Sob&B^y|Spg!&J$`kN>zwUJ3x zaB$ciu*0FJKg}T ztgnh)ASF8njz5>h6?f#{c=*Yr4W_34$GmVIo8OLWjcZK4a0`+Yv-!*}9 zBwKm;DAsA(nDI-`iH@;`=gP+m{lgFLHK3m$W@?)&dGhDA_Z2xOzI0$p(ZJtH$vCxE zj>+kYNBJzs-TlSx!tSH}%I9fQv)mc!C7X0bKlZv4f&}C3+O-4k7AmVO|KYZ9ydP%(N1^uisV8y;~p`x4qFXD?!_OyN9=w(Od6W; zGrT?G;l2v@Ob5k^8w<9w%Jbjb^|H}PYKo}I~bobd!XrTbzp2Zp~H8lgJ)I3?l&(bDiWf8gE&6b z>)9GB=Iu-6%I((+>=jGP>CzD8c0oWITFZGgM!Q7|JrUYq4#^Y(vuDu-a>OWDa4Y4} z5a_*lW#IL_aVf8L+Ty}c&2VojLEIA-;eQK6Wo?xAuK>i;1VWx3c=!s2;j_*iRHOsb*>6-CgcYP+Ho=L@XLd*j~2ln-;WHg)|cCixksH$K={5rGSD@yB%LI|(NCc8 z1Er8H+QO)~S~K{g?nH|2dB8SKs)BxQ?%G}}o*LV!NG2m*TmR|pWj~g`>)ClJCE#F$ zcj)fBg(dKOKmc$Cy}IRlasngIR>z~kP&WW~9cC951{AKmnZ~ZMsqup6QQf7J0T1;C zK9*Qd5*(HxW=tl|RfjO>nkoW#AU3t>JkuzWxy4-l?xmTv15_r1X@p@dz^{&j&;{Mq z$^0$0q&y?kbdZh)kZ+NfXfqLTG}Q^j>qHlUH4VEK`3y^-z6Y<6O88Hf4v^;}!{t-a zDWg;znYu%6zA1~A5~w?fxO~i8-Ib(^02{c4pXjhDI^2 zXB1LP4dvWuc%PXQ{r!d#6>${rm+M8EJM8yf#!H$Kp8AxwUXm5`7Tu-J$mHeCG>vw|&Ay415}_1w&*9K8+2d3v1N+@a$|820o4u60Tj@u&kI!~q2V9X; z>tMvQDI|O$#m+m2O**ZHq`_{#8)ry6`&5s~2k{O4Du16Fn0P;&_(0!e5%Bel){nU0 zJX~<8U6hoI%yx}qGY_1Tq7YKDJ)ETOCs&W)TiCrK*1%DE*vXdD-7hwE*LUgjeHRM` z&@pkhTi>m#Kc+QIK+2Ybn9-sFVKNHyIgfob4H_77yYh))Rq$7Pw|+aD6&yZ|ki9 z8Zb6s{oBt1G+PgfIcxd}{m@~1nzhe;LH)5;!gS8@ddyabpdBc?7JVl?tS+<#bPSMT z2@0uYdsWN(;Ww)n-PlA-0r+62@bYkEa`k{0s})fJgYZ#5=DmIdEvok7aZJRi{w-|} zkea&6X}ZA3b7&vbDb7)v8CuI(+zzSf3z&P2eOrPNP?D~ zf zn0@)0h;~5F&BG5vOFU!=woW&ZSl~nrs{?1w>nWfW_dnpTd z4qvLDYJ*ft>Sp%M(^_xCZpNBnc66JX}A|ZL9IENM`U>`ph7d<+RQiI}@E8Y)70s zMC*_&))}GlmR}@{v9*nm)29-=rn`Q$rc^4G)GVQHlTr6BpGxtHuU(8AF7Ffh54?5w zj+EYT9>x)PWL-iQ@RNmT?R+|c@=FOmj)5Za6_ z@DkVy4l^L>Z3#SI@s_eVwd3D)<^Ivq8a~J{|4mhOL^<7M4D8){ut;GIqqn`oqCk|x pNh;Wa$C0(mdpqYz&F>xK-uVD=DT5%Jzh8ZT#aXmjr70%*{{S|9XD$E$ literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/smoothness/images/ui-icons_454545_256x240.png b/site/vendors/css/jquery/smoothness/images/ui-icons_454545_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..fe1085b393bf346b975b96f8e7d110d4022a8136 GIT binary patch literal 5355 zcmd^D=RX^c!;C~?#onvbu3faY#8!L6-m_Y2i%o1*^INM%DWyh>wx}6Vd&I1n+7zW? z*5=pe?|AOj-MhPcb)S1_sIN&*%0dbN0LY(csTl(R1pg@DfEe_T)#-+j`T@rJCIBWX2|{AS&e%7iTnHbyn*$3C7Rsr>prWOH&x%jnSU6rPF}nNt z;8?$m8e2z8cuiw@YSpK&0yo7xcv1*3z04{5U7hE0k%p32WTw0Oq}B}pKx_X*O&Jkf z_{Wya8P`M&8Pv9_%qzXlV||L85}yCU7Y36Pv6gJxnXKKtxhs}j^Tn(JGJZ^Hrx@hC z>pu1&+y_t*#xoHH6sz1Y7PXO}A|8W+WnVV>Lrq@fs18h93^Z@D9Imrvtxe8s7%NcI z8ZnR7YW(7anVepw58(^7+?a&;T0+i>0+vnGMKljr&NF0om3EaY3SP`tyCj!i>``z= zT5<3H>LBo^TAZ$XJjTB_Uhk$~P!(75LxB8qNi>@{Z*vc~pMaVLt%VLlg;A{TS3B(j z5S<`%gHAR9rU#rl^f?rf_eHs@p}uJ+@-D>_t&Hyw_7loOH*k7PbGo~`Cc#d1$T zv}O19xT0<;@BdCiUuX}5db+2BH8>xF{kxowVvxibOXbbJILSL~cF?pbsBeCaj;tefmQxiS-^?}Lc6|GO%l{@& z)mB=8%2ispyiOnt1($36IsId@5$oLZR2;?aDRJR~^axf-{zXjnx0r;C0fJ`G3+UBJp3N zR%YenCGV{UpSscf{f}5Wq|7ggU4WP4b z{;Yb-!_m~vqayAv_qCWIOfayPr!O*{_{-S(nU*D6%x2T?SC1rOQ)i05{aPVLu`k<& z|5{*Wi@5-eA2{K{!X3MWVIF9dx)`z-6C3XV(rp@n%|ifX-iq=rv%#LMbL=2WdW`yL z7;WddvK-7YLr2Vf`xutL?;f@byy1kRgnptZ5iW zobMlGwFmoWbY&_vkRAU@3@y$UW4`iT2v)YcMZe%%&!uTTT$!K0=@5i{f3<7gsl2}0 zwzZ}4O9V^h;5fBg18}XeE%M?TXL{qLr()agBlM_zsgoe8@P=HnP}A0=J5BT<$kH*m zYWTt7QgG2M*VjWp)08Q*XFYJc? z6kIBbs6~Q~H}?ck`0tkAu1mtoe{$)!g*Q!uEHGM%hMXtYUU-29ydQ50RS-br(6Rk4d4cm`gEA{zHZM?^EG8K%da`tvKB zp$$Z%;50SWO8eBn&(+9B!e^^nT=M?lD9;QQvZ~S>^N1QfS?LYczc?e#H;M zWj1R9FTe;8*Q}p}7sDEg|AUMFC)ZFkww|2M@lhV!y?){wFW-8(x-$KB3t30{`Cwp0 zREF5wjW?9tgxJ_%e}E!^7O0V{F%g`yf52xm4v|?)kz4gP2HkcsldKlB|+86{pr(|gp-QtP|oMLv>0U@qB&W z#m|jr6D#>sLHVJ0Vt;WMl#a<)sdzVOR!-HWBwsYQ&$KIhz9Vc=xxCK%xv_p+G)ehZ zeFkeB8z^g{*ocG$vd3VO(uo2WeFlh8*`kTCW{BKkUnszSRuhsvv@VPBSLd+`Y90d| zJI=CH<4fNG&;NHX%Cab*?jM)gcpw_NiOOefaS)<3#2dAe}B>92(}>99lJO&P_^;iYC6 za_{_mL;Ma5ZC1O}U~b=)I;vrbt$HRjWXhj;yd*_t_H_;Vo^D)vjdh$igc9Mfn^^6) zPVnbls>Ov{l>w+2vN-C!`5vCG%<8RVenrN*9_0m*DA$P+Tx4|Xuh2XDl{)AyS0kMP zD0$SYcPTWU&fXjnr~h}4S)n`GkVMzpYi>{p1kG@l|wdWhadGznH;#--ra#t%ie5CVTPv-!Y=)f@fe zVGC9nj+K3R6vyRHMC<)r)l`x?n*Ch@>FnD6RPmAm#Zj^!-AJm#AcLuQok>^6cmtT@ zbwM8Rp+9gdhAp^XLIQkn?iiXR;lsUVfLjlTn<84j74;V#-Z@;G?6d2Q*$|+~q}`Uf zP{#!Ok?r z0u*#U{=(cVdS96r1!Zf$R$~=N?)J?%1Q@Yh-JX29*j;>YTRA(xV7C#gt+ww_x~VLF zB)}Qm{9k-1b@RQ|!ERv8fbz?*IN{{t!37~y9x7CbiL~V3kSB8>{EGtz(<%fr4*bJ* z|5EnKO|^m&g^zUsbtbVwt2h4*DZL{y!mZIzr!es~2|QqIbBB4dD6$sCWP?&%!`hG9@W- zO!qZY)HSIFjd)rZm`Y=G9hH)j&Jy;gEBcL-)dOLh3IT;S8VA%mM*MikyFO)!5zU*D zt-XXXQ&v2?6olqA1t1^vZwQWX8Q0*xLdhJ0h32X7);g)zJ{o?1J z)bVqIU%Ugg1r)z-%*p#PxoR>;w}d_hV~$TMsYghgF-PxYHhIIH6mdzF6#Fb$_SZ+uWpkhC{Jt zwu0{Yr9Uvx*4@?IAkj=3z;n%8#Gac!Ax_L^u zNB7wY4RASy1+5xh(!|Gv44ALd56652boKVCw}LT#^NpodAy3)`n~kH)01}bvga?R< z$V)m!{mq@IMj6-X`y_&4+rk4DqLvNmUF=V3i8%%EZ-B4Qd+hFuqMlcw z*dS5^c8|gM$AJBQLE1Q5)bgsPjilD?#tRQnnG=pR69}ba z>GgN3!(w5vIw5>j?AWpQ*f1l5qS25a4>EhXYr0E2>illUQfVU7b{y|_@tLF9Yj#7) zt;T-rz3WItY?S|*EmuIgE6?)V0ozaJv!8N(W6XQgG?mjCb4V15fX{%?p_iA~X%h*n z>ehF(vJnU}PE*Hok?Y#45iM}}uR3NutiH5he#XJf)A6~7@?M9-S2Ry1N!@%VRXlhJ zzkr)B!N76g8R5aJkhA;KAGmGdBo?iNkLFY^DGze@kIlcq*X$kD%~SYRfBz1IcTZH7 z7P_jo>Hpqp{Pwv1KEUNKhh^KOrUw5Xiu&kV|8CSS&`wpQSxuPtg&9%tlO{wWU~ed&)(S zHQ>*@Sy@$Zo2K%5;3Js>`q^$q{Rg)uYxeqNbrrUdPX)ETBYrM}*`xTX)f_SX%)~m} zQ2ZRTd5F$MVS<>YII8`a(dF6*Wb&AMyoJ{XP^Oa`^lZ{Rd(pgrj&1oar41z`H;Xz zaxmB#A)N4o8NcXTWRz#LbG9dewDjU$q21WRmiZoJt)=GpSiZA}rqWz8< z;B72yYx|-4ML}j2O_E9}7=r+oZb6r5_3``qB=c_ve6?SS0m;Hj?4swLZtin;_lI$A zjYKBu?YD((Y}W^ii4bY8#O`|?-4U_IKIqCb@+^Grp~%Z|xFS`_$k06d_=IUOqNMG1 zG5~!>dKO|)|2nm8TT*8rSz7HIkz7s9i}}gZRD4_1av1e!J6$3@szzL-y_iS>hcG?U z#mxW>dlK-6794QSo!PW-J?_tHaR)VG$Z>Ee0|!Mk$A$&n(v45C0^0;9FZcQs(a79h zk3H`q=$_)yPM_E(*$n|WlPWxZg#;64saMzR;fCR!6QT1Pfp@DG41IEuA3rZ$nJW3g?_QyWU(@0x&ju7f3|N{lGcy+xpGTnXUo!0Au-k#dxSV^yPRauU z;S4h|m9|GGMagyF@xtVV41))hqSvZl!U;N7{VuZNuNp?bFV1d*GTNF*tnB2kCdGZg zeCw~>xz-?uUFooabc}aQj&!8A=XXZ}ABeDLi=Vw|{;K1`*qDYEF|p0Z22`l~Ok>!qd>;)5%I>dExC|8D<2Hwj%lYATnMkbpP@^et_dB^K69?Z};9 z9mTyJ3!|sI0aBf`VAeGmFsgXqzaUreyD;@M(s(90wofcJQ=8K_m3D<|BmmNDDwrTZ z9#<-h5<{tUD0|yq@3Y}Z;r)zRw@KD;=#4F>(M@_I*pn;}@ZrLZP5zehGTEQ4WE-;i Qe_!Skb$zv36^EGr0aH~0b^rhX literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/smoothness/images/ui-icons_888888_256x240.png b/site/vendors/css/jquery/smoothness/images/ui-icons_888888_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..5ba708c39172a69e069136bd1309c4322c61f571 GIT binary patch literal 4369 zcmd^?`8yPD_s3^phOrG}UnfiUEn8(9QW1?MNkxXVDEpFin2{xWrLx5kBC;k~GmI3`<(O3xvulR&VAkQJHZBho(m=l0{{SA7UpJl008iB z3RqU$@Wfh}nb?QCTyjovo2=)B^qQB=#XMCF_n=?1Jbh>5sptJM?}}{I zHzR=-V_TFXKM0P+&lrh3TPr)c<8EmLl3g~EY}W@od*0X6Ljv>L(67bjz58EDypsu&ddu2a@@x)`5aA^S^DxkW8rs_vKtu8N8(o0 z#Nf}*Ch4&iw866BiW!_r4*HRsHn%80xlBW<`IOcXDu%LQam7$Ge$q#1415XvN>cnS zk_qU%P}4fO0v>J{Zw9o*)JF-CPA!KcpFR1Pn(l@*bKh=1_!ZRWb?FoG5a22cVG<$5 z0|%Qj7p@n}=Hrkk`BkD99I57h7_+lQ-AZ-?fETz5E~q(= z!!d%~_yivn82d_pX#M+Y`|`-F^s6-{6}S!?_mFzr<=n>M{{PUq7g-N`hqOcY-y_m= zc#xZEqMPgqc5cu{ag@Tdli5@JlV{xH8J%TA}P<$=Qej`5Hq>_Gzk+NDFM{b*SA6Yydp9VOs1VgIYAcj@1BIt< zXz@=NF2DLCC>`r|^h-z5@eIEh>Vnjh+|-6M@nuC!oc*856_8#_6jL|rKLYu=)Ew4+ z*XiJVgHrKl?=0wjQ)aeNu2^jkUW>@Hei_S;nuA%RRe49V`VM;8SxUBxpZPe>l9ZA{YS(NU; zhnP(vSd1kYiV^KQ02>XpH6u}Xk)wrk`+SxNxC73cSAefm+V!<`c^b#A9NaTn45bEq zkRYp$U%h-|^9P*syb!eKG!QC-$;IS9MdE^@-`WRSzTp+8M9zqJCUsoPC-3Tr+qbkO z$o;ra-wGjC64H8m{(*FVitg+LQKH+96D4!FREFb|Scex)lw()`rHV$WMdUJNe3E}`->+?@(FDYcZt1#>wXwgHzQ6{p% zTY#PF?iBGE7<=u*`SFt0Lw0HX!oh85UlzQH{;k~&JH?kPJzdQX=gAmX40n@#()wBu zSllJ`lX^ZF9!&n2{1443>o2BzK(6sGDQ?n~RYk_ih&{?TJNBH*Eq`73g$F~WrJz{` zce}LL0;S^ZMb&nKyWR#(_t{VguBs~LOSLX&q*$M&haRh5HO5G%C&MvDmi{a@PM;Zq z)h;XzD;Cshu#GG)RsptBTJvnQHC(-#7@G7B`iqJMl=F%g zD7I#-8sWBC_kJC!{tU)rGSX-nt`B$M86ARc$^oIWRNOCMU!X+%PKM$X`mI~kxxaKB znBMvsb8nZ)0}JBmidn3FUeG@ZcdpwZy_4oi*b{&c?T^HaVC|`tnlo?1SjRKLNPk{gDWT+_1fio|Ic{5kU=X{rvm3 zZIZ6BO4vMQdqO`~Ef~j4Z?cQ(+Ff$wxGAlyMBqd}_S__(_xM@v-fTM;$Q^HhR@PU= zE|8KP1IM4s;)*-+Z@m25>p^N(PgHJsq+a!8`ezsTQ3Np0+k4Mtdkgu z^}tg`-YMQKuuO>dsJQkgyjabt1)2OM)|R(}hto4zSIj5V;^@PYtIwI&4#+%;&Kf)o z7)jrDgZ%f?x$UCa=&~<9SHq{ZhxKx!b+ft~!I?(H$&BMOox4KuOo95gl<%5AIg+is zd=%?6ZOr(k=S0U?!*k{1h5q3O_ZrYo5Hq#Sl|1?L+WU%}6JI(orD)*qq-300E63z? z#iM){^ff?RwehBsE3Uh)}m z74!C`a^?2x1@?-i<#cI?a=RcP4Xx$88l&B!g`Nm)Fo$Fcf!VX@0y$z7EVz~OXbALP zyfX0m-nf+4I&E=bsAjk~l_2g3i}1e%qO!KkQ@Ij*%HbGO)w=i^^5FvkHIIee`4l@J zN(eR%MpMiipJjP0Cxd|&4n@b?>6{Ue05+A0q?xd^oCpYNXpePmO#{q`vISfX)oT82 zc+d5gPn5-?9wBmlt3pk*z*hj`X#ycn4?KJY!|++>4l2@t>FhVEjPeFAhW%k5Vkm2~ zbcy`#HFb1XOYOKAcKGGN*GG%skMBnYSL@4d#@wS$CLny@9vSEwSCUSW;OHk%_<>T$ z7HwfvT&)@WQFkIm_dH-5Csjc|H+OBX6;F-rR3wuTudV;|_Oc(#-}UUgloD_-!aH>L z-NF)hJ|F-%gI?Y8Jvo7qXRG7UV5l2_yAHF93IhsP-b`cH*wlEz^Qi99$$*D?10PGQ zCkYPA5Hltd=c+>(bWIfjJP@1Obe?Gx$=qVDe)rPM+5sw)!8F3K7T{OMLFj_+>SX>F zTT-48YC1?q1IV|?OSG8?IGXAN;&q~nz?z0#i+qM9P~U@BNG1FyO9#kvk>T>G=#)_^ zj!fMlH{X;+ONmr!LsJx(j*b2&WMpJ+s&cN;7Tyu8gf>RT2kOR+DBzZr7=m-v-UheM zgj$|(0HN;F)qrlz6$FyVsy6e02`M!$<1L&Bz z+b!=_(#ur8?I=h&thJP2c+^S%)lEi*8fSaPs>Or&i1kF^p9QX&8C;)E+S__7fCh{W zSpW930L|8eV$Pa=LO*oao@VWHUr>MSl`x%iydJaFA!rB6u0`Jo5337p0UZNmSb{=o z*%W(>6W|^!F&8DUAC~&Vo2D?gE{V0S3{B;atoXLUNo9J? z0AWHot1HHimnr%xGf~-qSOO6>z*MtHe(EIN3<7@k-U&gFD+Xq}Ua*o~(!1kApC zO+-7O=jP#uq4B~*JwPs<`_;tw%;J3m{g-9xU(RBU&q^x&eSc@Ik<8NR$i0+>JBKgT zPqjfRC3Q3V=4q|BVK-yVuyUMByvXqR1a4^k&=*MqJ_v2b7I+El z1&0}s^tJ?^uXsz@oZ9j4x^n+$X$>D_nE$4#I-;EJG6wc;Jy@i$hSA&JVNoE;;UpDo l!Q;r<<-MKrq~`aIaqoP9xRgPV&EKy+z~U_0tkM({{ePlYU?u&Z`mr_kcwz5Nh&g=McJ3E!;CE1E0ryV5Ro;>nvty8 zA{omJnn+{p4952Let*87zvA;auXFF~{<`_uPA4&sV%P>LMpp1PTBEIL*yWZ2%{t3Pe;FXZ3XmxI8(D_g57_$Zil~sY6d4T}-hu9_Wqp4C0AMO{-e2$W~1A}=8 z?24)=?B)4HUDo_oXckN%okP)HFJjaB4*3_SNpKaf;yPT}KqfS{2x7`d{0xbPErH%h zh`mQJ03DaATP9aP!}a4$fY#``NI~M6&RljED)8z}hhWxrNbxIBlTxG^j z!X>$3AQQ&I%_5mRECOjaGwR-GHmde})^)t-3_~aFM1G_L#mpCNdcLqr(RKjv3R}(z zG2^yBftMYh;H3a#-slaj|5$BX9+{PTv&NtR*P-L?l21FGTG`$H9~##p%VE!uR>=NG zc&auxVl!1_lP%uX71AJvlz(wLYl?63oLd~dqjZRrU#UEWw8J6Yn-7L~T$$tjeAQiW z9$XG5Hu>rxFBnzgd6ho#^gE5pY>U$dTCRN85Y1tQQ0=Pn{?7OJ10x9Xk!>P2f(f^f zILd}5--N;Po4*25F|J3ywIv+R@rfcYNj}R-sXrH2TFAiK{jFGG(ru1p=w$wR;IXQwAX*S~oiEK{g;kZPW;YE|!QY|g^2`dMS{&1Fr zkf?!sj~m)xO3v`hh4KQRJ&&Q!=X1HNq8T_Sg2P^B&rZX{VQUNc9O(K+B_Z4hiTH7M zW7K5Y!Ec5xD~B9zFlKUWG_Rd)xTK7U#hRGhp51T++e6oS{gT^?3s~>V4?6{zchhc_ z3UBb_W2U+~guMsG-g=@#aWPSFypk)5jIUTxFiM zycGZzbxQuCTnvH*kv=E=LsRnltLbhgm$=ttS1IzU0)1t~4(XE>bHVwJpAPKOqoI-# zrdc{yo0R7Qx%~ZQl{UPa?gmxo#ZWM|vNHNxl@8NLksfn5Ek>C${w=x~pekl%gfwaLwWspL{af)?f zTOBmhTyU&3;}QeF&VLwhJ>Dezu>~P zc+$aFxKDWKj-CmD(v`}uH|ts*SefX@lyrc<%~WE6tHU#dv;y+LlA@cTgl8J!u@@u6 z@@fvJdC)1TvBa$QT@ck`rUxF**7w4Yh0!vZUsGu%Lm(cl(l#QPpmoOH3JC>FMe07G zq0kl#K+GLndyoOx8{t9g8JiLs#`pH8JWqR_ZM%J!Yr>cp>95<^#=FWQfzPm%q;5B+ z0>}ul8+l+gRaHV$$tsq5|MU;?AJ~m-XNxjW3U6JH2k`tOXAqi)yGI@^uA&dQ% zZCJIe7{qK>+p_F)Sqy-GC!x-5MgogsP6lwiUH`N^a7*LKPdO{!4L^_^;goe*e}3s( z0i~~@V#)#L*W~2F?}&N*IQ)0a4Z1$uTU)p7^Mq&IM6K6d*$vpX2+L*+$9vY0=7?$b zxdD4R`8~74HMWsx#*goNSp#(_;z`UT-GuGxoUl-){JNk1rf)aSKE!W`#m`t#v6V!u zgn>fufpkVprL(KqSkhl*Z+yRQosF)bEiV<#K8hOr>yQ1@7Xg>g3EjKwLB7)(9$3%X z$G30OD&Z2Nh{;v5!}oF4fUu0TM%&2F-6aS1+fqu3cn;K4k4-#kkB|BO?bZtcTygp+ zB|R0)0x`)UVEm;Fwx~Vt*6ZV3k5Xcj6_=(X2y*8M&NGz^?Jr>Jutu8idcHpesED^^ znM9MV2AcX%oppm45TS9yYBtteX?1liAe($}l8Mrk|YY*cFUp@Yl5_|Ih%+ z5^dz*^BpQ&l8;Le-Z+E?J1_|}dtK>`0HCSg@u z*e9pUpX4zkcJ~*%3c8N=D_*8f&2puu6>riMeA#MG3E+*kYt|0Dnl;U^u0x`IJLnY* zjELAyFaL6=ihd=uwgnc)F;a_ZKEBsA_UuVc$NS1$GwozcE)2-hGS_c!*V9@%u`#?lhbMR;p$MXpbUS7*AsAt5?3(xQtcatZ zK;B-KhX__vb(?F4Q0GloBJ>|QvdJoM?lDbgsR3iM@a;Z3?cA&4wtslYkr80ETZHkc z9*>q7Q7<0~XHK7PK#yo@cBi@smopq(-%`e-KH4Qx-~rbHu}dW58QqJ{;3Inef@=x4 zI)BgQYXff|j7xg1Qx_M8s)u`0@M0d&aKAfD6qe?B3THxh84PWrQX5xII()>h>b|f$ zpKR+*4#vbnsS3H{v&>IrrO}Xrp{O`p?Q{I%z{XPHRAc7mQ~rVVZ80t_sel;~R{!fE znoWNU9=P1`jx=A?#Ye1fm8**6`|yK3jKQSofyZy4XkM$FK?NExjqO&YVea7N(7$X$ zbR{k3PT@a2CJt_@Dead-55GO?f3gVr{BdM(wXV#1%q{YCJlyB~k-m;m1@SZyhI$5p z9ViBGQ5QzVRGUDbbtaN^E&{f(lI64ub2s){aFm!11riDV*6MFh58H{nU5}0{$^Hi; zJVW(-UYp)>>|Lx|%+y^DwKhz`tPS-85#6Rh0)ckL)U$^na{7 z@VVG(5^ui@Hf1odF537(mlR>ZBhjf%rT+ zPUdZ~CgvIZM_wUkJAw%w}x9jc8!TL)0!EfOi*AMUgP00QdmWDhdxHH4HGc<~J zIVYb|Vj$~E#d*)1>gzKQFOMaAy}BVVo}IK&7ZMB zx!9l*+ek@g>FsKVCTu!A+bt50<5zR%LvhtB47 zphLoLmz-;H4@2#)g8=!k#zLI#UMqFnH)&}~tj#&gW_Q99mQw+L7dU5Tu)W%;@9Qi9 z>QGi--TSZnR2z4)8B5wJy^vu$s+IRc0ll#|LNt!?I`me%fGty24eDN4Xl+O{(+NPj z1ygVh>zf*$Pk&fEX-3AP^1w$s1y_e7lBxzgSu6?iXt=l939t1dNMV&Hw?hI}<+!vx zKuXRw@aAWBEW)iT2xma>qG11B|GnfLf43m`S%SD z3d3^-2o=m;T`_XFO4d`JiOd4T*vl!w_t?SMNPGOr712xew$!m3PP4`3g2iVGiU!9* z&w=GY2O}!evGB%RQa5rA7s5%`YA&A$+(`a%B< z)4%^Wyf-xKA)KjJ=y>(k$Cki3nVk)wxAEYIGA3p>sG^i;f$cIw3$H&^I7dNHU=sw$d)j7 zh|(sSuhT>1EWU{wVQLz{XV1iYPIvxnNv=>Vu3kdkB_SVNJ(KJiSF;#9T-Gc6A9!kU z?a4i1-1H;R$hx=;;1@G7Jsm?|a=U>2b+qZz`aN9sgsIyFSp6r%%!9oq%tbmjY#K7P z-Gux{jUMaKw>DF`W{3tTZ|SIDqX6v)w4@1rITXmow6pv9GTr+NsJ`V>Zv++iD5MFK z@5#Rx6sk|u-Qs__;w5Q)X2-Ad+QXxzHC&)U-n+`G@G_e77|5&TV3EucN^AXqK{AmK pCn+FvZU>f5ukGw-)qi%3dglGbB=rNWkH7i=^YbXv3KMkH{{f&jC-?vW literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/smoothness/ui.all.css b/site/vendors/css/jquery/smoothness/ui.all.css new file mode 100644 index 0000000..444486b --- /dev/null +++ b/site/vendors/css/jquery/smoothness/ui.all.css @@ -0,0 +1,406 @@ +/* +* jQuery UI CSS Framework +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. +*/ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } +.ui-helper-clearfix { display: inline-block; } +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { height:1%; } +.ui-helper-clearfix { display:block; } +/* end clearfix */ +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } + + + +/* +* jQuery UI CSS Framework +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px +*/ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } +.ui-widget-content a { color: #222222; } +.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } +.ui-widget-header a { color: #222222; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; outline: none; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; outline: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; outline: none; } +.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; outline: none; } +.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; outline: none; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; outline: none; text-decoration: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } +.ui-state-error a, .ui-widget-content .ui-state-error a { color: #cd0a0a; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; } +.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } +.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; } +.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; } +.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; } +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; } +.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; } +.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; } +.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; } + +/* Overlays */ +.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } +.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; }/* Accordion +----------------------------------*/ +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } +.ui-accordion .ui-accordion-li-fix { display: inline; } +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; } +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; } +.ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker +----------------------------------*/ +.ui-datepicker { width: 17em; padding: .2em .2em 0; } +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } +.ui-datepicker .ui-datepicker-prev { left:2px; } +.ui-datepicker .ui-datepicker-next { right:2px; } +.ui-datepicker .ui-datepicker-prev-hover { left:1px; } +.ui-datepicker .ui-datepicker-next-hover { right:1px; } +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } +.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; } +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { width: 49%;} +.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; } +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } +.ui-datepicker td { border: 0; padding: 1px; } +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { width:auto; } +.ui-datepicker-multi .ui-datepicker-group { float:left; } +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } +.ui-datepicker-row-break { clear:both; width:100%; } + +/* RTL support */ +.ui-datepicker-rtl { direction: rtl; } +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } +.ui-datepicker-rtl .ui-datepicker-group { float:right; } +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } + +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ +.ui-datepicker-cover { + display: none; /*sorry for IE5*/ + display/**/: block; /*sorry for IE5*/ + position: absolute; /*must have*/ + z-index: -1; /*must have*/ + filter: mask(); /*must have*/ + top: -4px; /*must have*/ + left: -4px; /*must have*/ + width: 200px; /*must have*/ + height: 200px; /*must have*/ +}/* Dialog +----------------------------------*/ +.ui-dialog { position: relative; padding: .2em; width: 300px; } +.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } +.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } +.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } +/* Progressbar +----------------------------------*/ +.ui-progressbar { height:2em; text-align: left; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* Resizable +----------------------------------*/ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; } +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Slider +----------------------------------*/ +.ui-slider { position: relative; text-align: left; } +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; } + +.ui-slider-horizontal { height: .8em; } +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } +.ui-slider-horizontal .ui-slider-range-min { left: 0; } +.ui-slider-horizontal .ui-slider-range-max { right: 0; } + +.ui-slider-vertical { width: .8em; height: 100px; } +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } +.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs +----------------------------------*/ +.ui-tabs { padding: .2em; zoom: 1; } +.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; } +.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } diff --git a/site/vendors/css/jquery/start/images/ui-bg_flat_55_999999_40x100.png b/site/vendors/css/jquery/start/images/ui-bg_flat_55_999999_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..6b6de7d5af391fdae847bff6a3c0aea46596dc01 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FscKIb$B>N1x91EQ4=4yQ7#`T) z7#^)sa^eD?IO|R0&uiqZh6adImlC&OVxF{e)AU@RGZ;Kw{an^LB{Ts5 DOb#zJ literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/start/images/ui-bg_flat_75_aaaaaa_40x100.png b/site/vendors/css/jquery/start/images/ui-bg_flat_75_aaaaaa_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..5b5dab2ab7b1c50dea9cfe73dc5a269a92d2d4b4 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FscKIb$B>N1x91EQ4=4yQ7#`R^ z$vje}bP0l+XkK DSH>_4 literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/start/images/ui-bg_glass_45_0078ae_1x400.png b/site/vendors/css/jquery/start/images/ui-bg_glass_45_0078ae_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..3dac65068c84bd0ecfff5188f540c182fd169cad GIT binary patch literal 136 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnour2IWy978O6-<~%VY%maDy|{O; z$__{EHiJg4C=rLrLX14cXJ_ZueT>}xS8Rbs*Zrb7;%o`VYKv9Nn5R#(Fe+GLF>CX# lM%%gFCi@DOX>^&(9ns}DIA!Y189<{MJYD@<);T3K0RS}&EUW+k literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/start/images/ui-bg_glass_55_f8da4e_1x400.png b/site/vendors/css/jquery/start/images/ui-bg_glass_55_f8da4e_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..b383704a49d8334bf593fe5acacfe39f93776fb6 GIT binary patch literal 131 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq`W*`978O6-=1G6*bumMHLzK+IlM6Uw<=GY|5{{$M%R6#>y2zVoZA|l3ncEGnHw#<`@xCLrOmbp g#_<-xB1fggKfmN$(P5D72{e|$)78&qol`;+01;y>g8%>k literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/start/images/ui-bg_gloss-wave_45_e14f1c_500x100.png b/site/vendors/css/jquery/start/images/ui-bg_gloss-wave_45_e14f1c_500x100.png new file mode 100644 index 0000000000000000000000000000000000000000..b9851ba5d6c20c710571dfd6a67637ce376d456c GIT binary patch literal 3649 zcmcImXH=8vwvJOg)6}b@2nb{iK{zZ7484b$0cj%^)BuSF2O?2J8A1ywgfrf&2r(Ey zkQOe|WFW*4LQlddRZ2i0kWj)9sv#6f0YbUaIX`Bt^ZWk!o^QYFefQe?*=z6pJi2_* z>&RESUjYDsBR<|9{s6!sx#l1F#bM3&*REGY0O05sJ{~__!xqR2Co-fCr+z4l-8%Mr zGXG!CAM_UeaERpG+IMZE%{dn4BDa*hP+iYw)S4R!VlSpOd%h-)Zn(D;GC`K!9|lP zSNlDUkIBT{t;4Z6S06;C&a%B^VNUSQbVuv{~27CWypz~ z-?vuMiJ@pQ5)98kFr+=Jp-V)SvJ`t3e}Z@+Z*3*oEWYw6%m8*2rU#4UxY7?mwxgKL zT{+X6i%+DRi=HttLrC_PSKQg^g0pUKCkH!A?H22r;Y8!@^}!H@;1u|nX%ad-(5_69 zR~Sy7CS(&Hx9cz&^a-kE2^%f-2bPq9MtflD5;avTv!N!CJ+e>?z0_0D;FhRPyETO4he{Ezz1{O(esIRpfMQSfq7H=ai;ZrVgarC^i_{VZ}IsEuf_H|1GH%}vylF% z?6iW;erg2~+fJ~?p0ET?m!SEJWqtW3&?BrQ%7|+-uwRtss{?mOk^iR;#*^Hur|h;7 zp(Kx_&SP)L<1dq5B*_DfDdd`y(!Tw{m9V`a+y2gzLym6~u1tX9(sojo`n4y7c}TS- zI^m=rNvVqwz!rN3o-Jk|+NW2zv|?v7feu=fVj&A0T)1=wr(AKuc|s(q9`|xqkONSD z;~Qqk6hV>1VX>?Sc0mCi#8&k)w!>MSo+9Xd4ugA>Pww5U8cHT9;8^}Iwl?AgHjd` zwOlV@*9%UWB0zjKd=-RxOdCkqBl}sD4_Vg-rTvyrK3`ba?=aEZjU4!-W((==V=Ht+-Cz90lf$% zyp_Hv^1jG%H8rOr5R*`SFp$PeiKv8T_<@ZXHLwU9M{q#zgRF-OT`ZH10{w(M%6xFD zINu)XG99SIuxAIuePkks^;!PRV_OCSK@)EOu1ILFurn?rm2KH1R_#+KZQOF1t#Y8IEpBjH`P$H~+uFh9{Uu^0>9J;W5J99Z};GN}?kSC**F*k8{PV|q2?U?%PLUs2w2|HlVn)h!>IYUbzl;RgumUc*2* zX+{8?=#9eS@`%gGpPbEq5stj4hA3n4O$ZX{La&%rCCrxN9D7kVhnKPKjB6yi0gbD5 zHOhS_AXWG#&Rv)9PZnXtQdp?*J@?c~{+M&v_RG!}HayOaGOUs3j?=4eTD%sk?H?H4 zkvP8gE=pv|ak*m|q)JZ#;`ykN6QY%9!m5|QKkjyAdwTyt!+zW(DF+|*0!6xDc1wrRokU8x;E(TG-f{Uiq85z~&7isz3h@Ch z_8Y*<5;jzXCY>OxtX?K2n#Pe5W-ui4V8&F_9+x9XmjS+is@%bmuIwszm_&XJhpkG- zF&afaJf`7~1mKT^M*L;5TjbK8=ARJ0n`;@AO?b5(5=P!n z!V|&PDlrWE&!d2h5yKncEOolcQQ{M*McECAd7LIIfPW&bn7jKbp`-9&ML8Rqs(KQQ zH}f06w$?b6+K8WyEK?lQZ7_^{%W{;2?3e;mKTR&OltEKp(!zkgh0V1$L(Y)4KKo9s zTF4+6mCtqvgwWdeyRQQn3GXlzV-yFBae-*Z><2b6Oek? zy?CPsebY0K@0tw^HG7S5sS0HF+Lin@2BV@Ht|4H(a{aQNCgo4oQRt5n;FQxx>*imA zKwPYup63AnUYrkS|3+COH28xeqv_Ew9|u8X)5ojFIyB?p93Wunqqoz&8aUTBzgOI7 zo%C?*t(RQx1QN9Sh=Bn2&->5}<`Pq@W29&-5V3@%DOB1td(87Z7&Ut?P9Dj$RAs z>k^X~BOZTx#7hRr(2>6GHvVWyKZ67#gvyW9?@$D!Dmv&T6FEDu7U(_0=MPZb4rwYGA&b+elx zs*w7HCr{H)Jv=+ykQf@kvJlF5$z*HBsz3QkP_LJ`W*HtDJiOUib&6qMUVrdTMcO}- z^MT>u0yTdS7_H{mPOS+94ftqJ5jdBaZ-U;Qqy$CKC?<=Xv6VZC=lAYLWbjrRGj^tW z`Dx(cheJ11OoK=L_#z#z5_Y!S_JF!CK-M`%Y^&yMrtXl!Ixoi?+>Jo!8^#+Q2)7OX zc=Jc9U#%s6IxJ)<&c&Gsd@Qho6{Q^Mg6{2K;w^lTi8E<28dbQn^v};=i35$Exm5l= z+uT1`qwQ%Z@qYJs5k1mci0NH;w%l?BGSQjB%MFzb)k6&yPvoHdltB{R+n$iBQRHDh z^jizs@2&gcG|hv`DP9m~NT~w}o6z2{j|q1X3EoI<%J!p+K7{l(K!Drv)*I@C3v zJI2kS5|nnzE@iYlzEnv=c)lH*!{u{oPFBqYY?_Sv++$$|yzq@5M=bfNiF zQ5HPR9Jbk$2Zs_{odSu++0yS<)LVCflIV?`f>JC+aBIZVCfi!Q ze69%9Q6LkeX2}ZFVe0nD$I|Y}-EgZ7WakuFaVv~o8?Qpgo?EN>ju{%i=(Td22*D*A z{N*oft1cX?baSSWX<>_fNlv|sL6#`BD%T-&FZV|zfRpsMOA z@-AM@J`W*%P$Cr%fGABf1SYGFOtts|IjL(3Sc{v0Hx_H(lu|u!0b=P-G^i|txSU1~ z!RRJ~26G`+`$uwWa&k^qov%x`3I%^FIj;8F;n&I@yUIAH;dWX+2=wM`YJ2Q|ujplo zO5$?nY>Nx`g4rVJDdyNV3Ie*ck=BHb~{U5>bQ{?~v literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/start/images/ui-bg_gloss-wave_50_6eac2c_500x100.png b/site/vendors/css/jquery/start/images/ui-bg_gloss-wave_50_6eac2c_500x100.png new file mode 100644 index 0000000000000000000000000000000000000000..76dac56d2c5b0c1b6735bcd6117f3d10a95a50d7 GIT binary patch literal 4256 zcmcJSc~Fywy2jJm)>C^p6ct1P(?S6aAcY*Dtf?)6f! zRzS7{2oREh5Ykpi2wOxokrGsge`fZCPI&es5dcSMKhH~#U#;qf-@k4ymIW5gBbi@qsUJJmsPD^E1;UJMLG zmY1r*ZBxg5Fb|3!9xa-zdo`#~`-+$^%NbE+L&CU}0iS?gjC$cOyOV z3bD0gf6Y~2b$X_!cI!Yxx>A{4?S)H??z5*iyHh zq8Cdyt6ieXtiD_T`08CU&zov^#K7zHBC{WxmyerP7h6oMf|P@CK1FjP;lSE|2zq;= zc`)-IhdM95gM0Q40HAe8O%DM0_MO?c&C(NId(^!AdvOZSDJ;7OlF|dYVGvXf!&TDH zhHqv{_S#a+(zP>&Sg2I+u%(2Hm%+CELE?=|mh%{w0|<)wd$eHS@BW zzb)U}3}6qGJ+w^UN;PDeR%qk~mm=T_Or{?d#@ASb_n0>*eM9n!bs1ZT2;6lEW(RrD zBE`<^Vx zoJ{%oKNS9$GnR=88ru~Q5+vq-1jgkmb26B_raJ0+?#ZH;2HEXw+wlZPJrfpsn7;z_rtSwug z^#t=!al8?4E9>7Vb7Z?(dmR{A*UbXqdBd_L8qPu*eidH?ub(<3{J4jE=N&vw=w;7VImdd(bL7#lMQC<@kvlqa4 zR;|g+w~897NcJR1H|{EXcke}98ye3AP1z)!*)TWc43afng7AT zKoe=1|7Uda3f*rT8W~~X7cKU=1*JzH_3c}GmP5hhAFpL5Q6v1_8xl|GxuybJaZ_pD z+;8|k6F!Z#Ah&22?nU$>emyF}y}jMd!=#%@sIx0aY{*A+&(h)kA2Iu4=q`Oafe=vE z2l78I#lFGQQuL;r2WiaYDGMz%$b-l48KQ=dv%8lk=IWg;@l$KNKv|_u;=Q)sfed)8 zNv-R7TS1&2n-~XYi^4_)TWi!3q3jI1Q}#+q-ww2Zawn(nD}wk4p;4|ecC8KPty^P; zUBLcmsyr6h4wsI~P8VeJXt}gJo4ko`uGqY!NPrVf2pgzjuT#P`*kW0Il_bMg-bHd8 z99^*dwFheS1E?~wZOaDFB*BSzXT)IXl{(S+N@vW#8Qexg{RVwpTiBusjMfJtYf80E z_CR?z8$Up>ZLugeeapR_UtCq#alTAjAIMBiA`a@yM|H2wl(d8*HUidzn5XG*Eje23 zXS;5e3;^7Dzqf}-f~W#@=N;HEBRK`qJi7@`SCu=OP}^{r5JnAro*Pt7JLeS$bdYQK zhn9Bj9z@7$%)J(|A91T>Ah**+$_#6DQ~Rk{LY97QAh2}SQdNG{+D5-0R#m(>`jVg& z$EFEt)ELRDj6CnD0#;>Ya9M1Q49*@?q*|EJU=D8C_1X>6VzJ4zBupf07!UWlfKy=; zEwAOk$sewG{5lf-xM4HZA|k3GNt1$zgvTLG*{gnuF4Pxx9eaL!tjGf2I06zF&_>_Y zsm2nEM6Gt_2K{K>RF$h`V0#r`gANs$2tUP#w5l66xdnp@O=54L+~8Th!nUD=y{gd4 z|4G;CRNxzL+&`<_pL--Y@-a&t5MX&=%NR_gE73r+oap-Oe49L+EL`KDKw&0#TLksl zkNRbOR`(!z7+02U4nz;0DiMGEA*bkj-z?wyqP5F01~LsjG40w(9sjGD+4%V4q867j z;C>F$>%gM6g)I9K2;Q!##s{jMuad@AHmHroB$EG(Yf^sVv${Cy-BXcb>&-QsPX?jf z&2jtQYw2?JZZU2n&39W(oS)%}3xn8&5?W6(`HoO_yrxofx~z zESKg@BD%rUM3<1(4VPtY`oi`cE;@oSn#mm0$Iha^Gq8s|0>fcNZAAw0UK3Eb+89gA z(BEosif|sUqntaF-${}m?42AV9YE(POW+6Og(hiVB*UzWG$x+L&*enT&k@Ov7W#lY zyjOFc4h9)o@~jxi!7gzzIqGR2kMfwaz*ChhKiQ#tW*hLM4UaxT?DO)yFwY`JK)&k@ z=8PKyD|Vg}3%EY-Ea|Re5-5u=E0i3pSBx-YvFeCk$LNoz)@IH+PRV)GifHPIyAlr- z!}wT`e1DhLKN)1qD0%M=<@ijtY9n+}?+8G5RzhBQVtfJt8R|;_dJKd(IeoXeSkS9G zM|e{Yt7l^>CDSH8(r|M z6vqB8FZqcv^GOQttZr>WO7F~--|{+D9Ni=Lm%2#uBK7&7@1t-}_*|ezWP8#@0U~vHW+C-`+sTy=nHx|{?S&g0BI^O_aT}EU z`D9t%a{wT0`J>O&6M@f zaXswoWG&Y%C>n*>4zRf7R2w33RTXJtY+I`rH9QFN znewBO?2H)ud#-R@Q?f=i{)RBqB?@A~!Ym-h5HbuIocK$@JX#x+{# zk^&5^?TkFM`rl4H{R{ZN&9L5xatHcXI&BYqn*(@tM*sj*Kuq7;a%%W+XbSi%Q7w&H zy>SW%kP~;PTL9qiGDtimLnmP1tG7dyk-tuR$+P6xb!9agiO>6QRK7#9+S8 z>j+x83d6w*R;AcEf7yfAz6rHIGbKoe^!a%LX1r;#sYZ&1XD5IsCbNf|4s!~#$q6a3 zM|U~pN50Dlo^@U4;H|~rG|fuzw>}V(r;uRvhVo1GU%Z9AK&E^6${SBj65h7E8BuC) zK0zqgOrx~&?!~k3;v7Exb34dsAin?H4A)tS*Cs#IoQEl31Aeyd=5{kQZb79!Vt8}7 zSb8noSFl|->MWjyOv;eV%Z4^EU2>sc1#G)`N8=>0xKON`;*89lVCKUi!p1gl*usrH z4EL8O9~8FTFDKtD@Ck1jpFUTvtkP@%=}0%{9S>Ue93A0GgmU={+#`JP{l?LAC#d*_ zgn>uno3qmlnN~H_h+^0*qT%bP?fI(9y52#=0E|WcNI)D~b=np;gqyr#UU;=5ckAhM zbg_<=s;qZFSQgv9Dj$!9PfsMY5pxgl+*?|C%OriBYG8rkG`8bY!gb}Jr)9|*N6q_F zzmE%l&pqY^0*B+Y8OSc|j7TD}i)G?MM|&7$k^}sfrFLAl->rmq`B6Is)h}C|u!-08 zz8-dQDMc_SmYkY=n`Q$Qx~dslh-kcv5ssk71i#L9DWDtuU%j|@&U%cxof>q%Zic=s z3jg<`AS+02!8ofKh&Zh$!dHbTFngBh;(`3D+araR=&}{$KQR!T+4X&_vvrNdYo^C1 z_Rs(eRS&Txh z+1d0CL?S}1{?AJa1Waoe#Y9^Hk4T8C)(H+u&;F1?*eNP0TA{hiX)7yzHTSYuS*2YW zd)9>;g|VWfw!In{^|@pRh_a~xj=C#{F}f$Q0CsUAL};Su=b>8s{=dwGDEOYn4f8f?ZgQBcNif&Ekm zd$=qep&H>U#IZw7nk%Q}2&#E^H4}Cce=QqnT0SsSKHNBzaCb|$XO1}#Bw)YqR^!p= zk4Hmv(PB}t+cyw;)ZuN~6qyReypsNQT=fF-dM;`xzp)xLAm&|wR>a>>)VE{3d7*E2FkEkesoO^80B{+2{mK9Uw%q*xbG{pRMVXVGj1~HTNr{zXVrG9( zi3G+bLwfejR;ze#@i8PDBc0nuug`He#!XI#uZy-V(KS5f?x?*09CH<>pm_7YIr^=UkTNGV^$Y$n zLfakF#U)J_3tWX($pCQE;PP2R0N8UATMa>ew^=`scN6+nANWnJx3&SmaUkZSb6f)F zIdROrXmZ39TE~NPWpHjqDkemjM0u1uxN?8tuj>clzVN9jtj})`45{XDGbeMn9G(T= zfW$vx_-6M;=ZCQt;YhlDIK#7{e_=_Ce=0lnB7fqR^C5<7m10osXnpH8xgQZoPx4x! z*8QM+(2dTlH|6M#y-aUaF6Ub2>`9Y(?^>CU@KtuFHUPSHz?Y= zN~KBusb5TKuyOYt4)aV$D1Nc~v@mxUGWVSi*v88z1v;a+~W9#0SA9^@c{DZ$aV$*c_X+#RTZNoY@{g5Qf# zh_c_jxVKyoZ>8&V!eaa5Nm6fF#cMsfIJ1uV!>DeY8x>~~+A}RM^T~55u-f>Wd9hvf zB{M_f`qrVK`8fr{(Jhp*j(gtMUa^4asgfdeg*Q-5^0CLes&V4o1))@%{CRjzj9avI zB<_4|4ED;`9vIR+q*JYuVl$r(+2wf@7UAz98}}`L%-J1)s7X_!oFNPB{!BX;Sk6@< zeWk$nxvd-0);_Z#W5BI|Gizc#26EMe1UQ)1?2%%b$?3uCmI>c95rZ@`w~pr5qLU!@ z0)09-)UxAJ{6{kP`lExh4l*N)G3c?iSfOV+ory{BEUOTq(S5WD=p26bTY!p~DG< zPt&6{`A%txh~Jp&i>2aqFS!F-E(^9NnO4l_H~OzL(o?i2e5uANR)sWrGTVu0l`Bgr zoEv4d%^g5R%O?p9VL{>F7Y`#5Rv_3mr&Aat2b8(g9UQmS^HqDoEh2cHPS-lnDwq9n zH5?DV_l@S1_kLF}D2?Uy@2?P6pk=Vx0w6{t)Z?gWeLa3~KFiPX;O<(J9 z3%D#iIOXJI@#Rz8t8wSZ{@}9l+2msKoOkt-%E?5<=}13`HynxpTK%3w-wJ(9T%N&w zuzv%89bKYib2CQorv$5iDBEm+n-HaJT1xr7F#s!HWpx=>B?s;zqf(Q#V@`O7IQ7gS zgOQH#bs=X{uiL~~{H#=%xh+jzoH0!_dPp`+yLNdGu#ZSygo+5JEE?EeOA$0+^BbaK{b;J`%m!1&qg zz|7cOe67MWrRf~!$;^!(PFrzjvx+RvBn5P?xxqS-X~z@zY*=yw|LM7y5L+J`JHd}# zRjBxlSw6o=`4|_0TitySxM@+;A$fh0t%Pl9MW*z8`X6fBc>ALeBwXa4Nj$=+iR_gq zzeE=e5hPP5n3>1Sgn3mAY7234*1R8unpr@B^IqZamZ3TpFIihnxkulxHd779l5qQJ=be7arq(~p^oHD2?+zHJpZQp&*tP>7w6`(YkMZEE!Jaf` zW;Jf2V=jxzGMDsSzz;)K3UGFNmEUXxw}`*3{mg7K(WAo|*H0^a=u^Z_KkAXNL*r&w z;38R^p!HjuM~%W0IpNls%%RG;iWmG99Q_65es!941v5(9=g%vpc9AoSf@0Ji%bMUl zpc0Vgw?*>M)_VAtfj^`0 z@#gt$`+XFRaG)5$IWPp;PD?Ear(SBSzaJll!mqsS`8C(BIz+aI)lM~$@a~=1a$?Q@6xFW+ zT4PVB6Ln(~#q&e5FoylfEmqW?ORNQN48O}04GvD=^YRJ}DR$+V9M=Pky4=ba4J&_X z*cBGNfO+B7YEO&6g#Y~CTFevKGddXV-DmkCA2DjD(lhRWq$i9cz6M5 zmiCB~TgQzX*dgiBFuZ#jTnstja=5J&T9}Qs7D(4QRZSS3XqibOj&w~U)tM@8@d%H?k zc?;{gmAK6EPFL0AT2R8gEMg&|eQ^8a@A+)rir_U(k+3Eren^@${`!OqNAe~@>Lp>R?6;iK{d*xYEG@T)zYOW(bHa}|AyG+b zVgt-HuS@VU^;cbeH)c#A^3xD1IA6f%waG(A@3pH3`#?t0CI|))-Q6zQStnfntFdp aVL*6y?dQ$#a|iS;;O*(>QG4d{-~SJ&h4LT( literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/start/images/ui-bg_inset-hard_100_fcfdfd_1x100.png b/site/vendors/css/jquery/start/images/ui-bg_inset-hard_100_fcfdfd_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..38c38335d0919ceb7b0dd09e88a86be90a966ef3 GIT binary patch literal 88 zcmeAS@N?(olHy`uVBq!ia0vp^j6j^i!3HGVb)pi0l)R^lV~E7m1R+}Z$C%HZkh=d#Wzp$Pz8A{XNT literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/start/images/ui-icons_0078ae_256x240.png b/site/vendors/css/jquery/start/images/ui-icons_0078ae_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..58f96f83a0d82669f6b1ede59ae62e05d8602bb6 GIT binary patch literal 4379 zcmd^?`8(8o7stP|7z`O(wiruDS;~@q8_N(GL{y4FvhRBaGuB&VE2PL8A$zvS3}q{c zY$Gy*$SwQMgh%(k@w~2cea`vmoa_AXKG*w`V1_X`1LuPS0C47-q23Ju0G*b=Is@eN zC0{c-I87^N*DdvdkgETmNW_WUK3yCWa06oj@UY538O(^$*)k%QKH3kkeC%JCh19up z42_U?#IM|tidBdwd~oag+M}$;|GouR(eUbVS!KP%QJ&};90pD)a>yvC_MqgVHN7Iz zTwJ~x9svL%<(eMKG9+i^9+Tr_BO9#GuzWryUE1As`Hr!w^H#ct`?y!-bLq0-fNSGB z$0uKT0ZktSYpPU2x&Y2dN)QAN7EGZE0DVScqN4nOT<>mWXL1^o<%Lec zgD!r#0*R}PV6;c}Zr2+;(=48P%Fdwz;)SYVe@)tj1v0J@(g82f)igU4N_*WSMKQay zM?hz>x^4W58Pd`0p|*DJJDD}#cvj?_m`8uW#t24=t^+fJ#2}G=pOqgX3NnZ0f&1xb zf{QA*(#ge|;HeXB3E{uYaG*mpsq4bCPis&wmkJK>M?I*!AhzYL-W;csw)WC@ zLPAAdypuB{xIv z-5+mHJ1t6oe8FVBHVJ9#9c#J&Tk!&XPaXELcIyEDK~Cwv;ljcN1|D4dJz3=rE8aOF z9%THWmdl_t`>S3?KQ+9W#JA__oT|FTJ-c1ygTna!60zJ*{VU}^(-;_AEjY@>$h07G|Xc8ZjF~{eke~=kt)E%6xJ}&dkdM; z{=g3~h*p=jcODD>)$<&wkbxq2rhXZ6UESt9sr=d5TxBS~+zq^*bbmQjy z#RW!HyE6+g-Pbr>%d|o=akUObi_RQ|wRy%}!e6~!@y%KBa2^mm@gdFqn2Got zkqLJX4l|EqVfDxWgfC^q*zlBQO7Gf!bU#N>@4U45ETpOSBsCM<_E}2d@KaF*A+;VI zUAP%D83s*!TX5v+E(7CC6^QC{^|Rs?Q}HEX$D1 z8Cm@3`oQ4N0poohQcskw-wEGLDL%N@V8@?`!ab@$rBE_jR11Bz-xAbqOFQnJV1xz7 zYPJ4T>adReY>dOsAp*vS2r5N%nMo?~#kt|Q5~irH;Ti9)ONIEdEzA-4AW5T;8+kdt zZ@L^ug|~EeYG7&wvW&=#c~-ix-C&)6&LoPfa|S%U?#@*DaoWmJCNZOO?p@o^!z*ze zKsTfi&)x^6xc@#|4&ks%@l3bMbh0I|$%#OPV5H_n(oTpT!=Oo?%i9741tfmUHQk08 zR@?z%#+WjZp#2Z(2ba=nVQo=act;%}p5Y;oiD4XL8E0`!9&bP>zzlkyo%~xiKdoYA z-EdAm>@fR0H6Y@Tnht5MC*^D_)uBGHG|>;7bd=`^er-%>%sb?<49I5@JQwhglpre* zcfkvpUvo@h$9^}k@VMz;g$id<4~_CBWPi)jKJhS>SpJ;}<)I0_jGQ*n?q*p$e>*6> zfD^W`r4o<~@+ssU+;s#m6Egud1`)7K{{%Pp7s9X`tGd%dK8GksA-ITM3S>t;Na))x zIKCakMpBD$WEz>7pBGc+K8rNVVU9nHZ>4)PWkPa_J=9i=I|ymR%N{4OzKh)^P$sz> zgGr1$SHSoX(#Huwp?uHPGCKbjlrgY}pZ!?aqNf9s?`FA2Ll1XpQJ%_E7hJ=k04a}QP2XYwg>y_Ys^3g=jzap?~>v}?|xofwM9~)w_rvM z8k}7t4v%l8M90c(Ed7kCemqzCJ@4<8@}Y+8O5J^#*x(7?>P^rLf@iHpxC&a>DLUkO zG^y+sXI@xox#{B9R`+H^@R_F5dP_-trF@W~R%33euDLP{E&iyD4{?v*ulVLm{sux$ z)}u}VrCrI7c+ClXrNU6}0}q{!jQOR9Z@Hd|Kl?oC9Ol)WOLafwr>fLbpho`A#Dp)C z%UNqI+=T2Xt)=nvZ_Em+{RvA?8c<`vYppW(9p@ZMa>Etzy28x~DsvzD$?AUAMnc>d|_0BnG6(Rr(B{k$y6NAe&hV7&B&l;=SH~v3SM6BFGo9 zZxmj6yjt>9CY%1Q9HRL?(rl7)w}ZVLRsO~Mb|l5}n^I+zVs=jpS@VAH&;6t0NWa{zXvctYn@geOfuH7-D{ugBNdg?*ZH}U3s1PMe59P zZY;`n_n~k9&7~X%89>E=K5jcLq{i{D;0D|`h2Xa5>aVO#6KwJ`Yxn=OJbApRQfX#3ip-UnY)!p!}p|H7H-* zi$p5h@!UZaxv^!ns5CR*q->1ov~sfH4mZfY(m!iPw6gYxaC8zQfB54*2u9%7 zQdLvd4-)-DHoybikNbCR6o$`y!RbnFK|D9R=SpOg;y#SWfV|coLaztfI6n1^dVuXK z+Gt5^J9b+4=6)m-|Bg^*==I&N(eiUd*%NDPgZSiFOwiOU_9iu5l7r{+%+)+^Gddhhc{EFuXJbEO_ zdaHP~yL@A<3_um(N>+w-Mc6=5rd81HueT99t6X-Jr9w8iwLMAk{@~V%szf;;zA*_4dN(MZMIu_U*-If}70=^^o5qhrIp{-n8PY)?lX$BAw^cOo zFSvQl89ArxDMPC~3i@|_Wj!OT=Ljc0Jn0)PsKMZo!i-E;JR)h~+s&JdZr+_JZhV?V?UsKlu{p zL(hgK@=2??w%Z}(dgc7{(@gt6ho8K>IBrn)1R_Ryi0{7IKKtPAtyyLy$NIh4v99r_ z2$u6S=A1%}%c{Hroj5Xz^!^;Q2N<^=4W{AT2|Q~4fx!jIQoqp{TAMBdRTXdL#b>_bw*KXe ztw8c<)_h^RjmTcc+^GDC8f*B7H}MF)El-rOx@#9*f>eC=X<_xfJ=`%?FI*mlqRpc+-sh7Acvv(heT{tS8I2-SJ5 z(Y54%TfWBSx54RdRNj&2sKGN1xKyxAFrs`KmA?0t{`Q^e^x_Z@qN08M+C2~!P{mv__UfH&AkObR`%q`h$SNC5H(R+Y1Hb22g*hqXYw zUXqleT%;-O;MKfON=ykXw6zr;Rzm&B>b~{}WQdJHNongf%Cxu06249U*{$OfKE$bjRA7{ zQmz~9pQdG#8|J!nuBrb&ad|M+`gC!u-%YF;z{4sFWiTN{WJ;em_tJcb<75BIETqb% zrEh?|D|Yp!WR!di@uN%6w=N|e{tr#~vbxt#OUi4-k8(s-;V^Jwfn8c&r5iOHqwW!! z?Bq14e*^%C#Opd}^PsHd`%Lx|^=z;n{nEL}6e(BdrMreIj+-fNu45kMFQiI_{H~8} zAD?{V1=PI|tVxowDFS!{NkI@eP%x1u0Q4A$iiq$7vfVr7?Fq@~MoyM2;8irT`wGYsoffwC0*yqC#eI zmw?tnWy{!A6QsS#BTdch_tLB0F|5e9kx%}B4H1k~Z98TL@qQBh9xFdY1Y`=$0r%1! z3PNTm)e1{oizk<=0w+&2#fASe&4CG0r>zOkJgY*#TFl!g9Ce}Zf!LNdyR#flT3Uenje;sZ~L@6kYVW zcYeG(?X)2E=_Qlp>I9^vd$j4nZ-tBST~*kp>dk$^M_I-Hh6@Yl>A7+3b!C*=Eqi7K zxlsuH8czLE?612SeNY4w@xd3WoGRLdT{|76{X=bBhizJ)_|cA^heh(Zwb@u$wfZ}_;F^W+g3UAyJ1;3WMR zwQ(hlnIRi-+Ldj2vi!4OA^6-wKQy6VvsCZPz7*F*awVX4{<6*!-S!*07J}RxR^$mf zMZzR_i7R#reB7-1`>ik!%Su9$zbXrc3_}}>qJeYJJ0(2nc5+HBVc)L7xex0!i#J0k zWkG@5)iJcoMk^eL$M_pse`!bCHyC^KzNt$5{HTxOfn)QO=G6Cu^Og?w_quA>O4V=7 zU7BZ9u{kpj(|&{3Hc!r{kXCBYhY{&Ruom~|%Y>`9lb6h*7;Hxr>Gfg%#MX@e&b=y&9CTb07m?>u|K@;u%~~P3%QK10)YDF0$+yya zxO?+!QX<3hM|J6nApZ~bM>wyD7nwI$$9a$Nq~a{b)(PY_F1}d{9?pHDJ0YmC7dsx4 zb$;B{jl;z4SXed858+K+Hq<|*k=nhw7tzZR&^;$5HUnv>K1oUkw|tS5KlofwMog;3 zMC5NoPJ}??-sK%RJGi^BtejVrsQgOgzl`wOPV?d&jd5)9O9V1MtSxVU4^7Et1NVkt z?*bjVZl16hUCr7@KS~m0#2kH&D)6fYRo4?7mZbv38^~~^(4u`OU$}~DZpD`(4wfaz z#LWG7JTpEGe{s+@k$Zn!cPf10wemySy-pMBpl@aSrE z8_)^KC$RTGsjk1zmO?me65UfQ(jBacY_jK}LNIdU0(m<~hoRpn$LU?3ygZVy>6~K4 z3@dB{F=LIH$k5)0wf&39)v%WE41&Fu5YNy6$Vfk$v4pcQGKbeM7+?l{$V~Vxlbc+& zyrw@Z7jlq!f#w(b2c<=x?Mgh`OtY)?FOKs8#~vIlx%>8m%1kd?BBFD-I zL|^nk=2jh3*>T_X%-nAIR-hjX?C(KT(}dE zlE(>~-&FQX0D0x}_V3t(mq_UVis3w1x_6wL`zvwCg;mvIK9@rTBp+BnFA1`t?Z@_P zP$<`ZrG(D632g}M5@tT-H|c1>J!&*~OZMj^4zD9j^lD4T53?ufWg%5F`->2}_EB-oS zR>qTd0mU7OPXzUGLb?1v_d_?WwzRp$NAI|vi9P=^;TYo4m`!s%;HN3qQlSREj-=SH z6H6JZEZoG*aE-;W3vW&GDt(EIsdea4;EhI!>$YPSHKFdRSWW)MIE}dnbMo&yLo`8U zr|eVbbW)eILva(6KpAhGLURhV%8zF_E-s_8?@IqW)4ZbzqrFcIdrW_BkuVg^`zjA* zvFd&vs+x0Vr8t4!=8ijq)LM+rESUjmbd5gEYq*!f@6TqE2*!?Do_MbHUMgJHGYjxW z>=`^RKVB(%CY?!tPZrVm0BJHoz1PNGiZ1=?c_)l&KB!n8u8`T)1bHq)9_PMD>*(O_ zI+$x9B@D}elqq+LF~{)Mk;*Xnntu`0Sqtgs@t>EE$_AL9WD&%gUAq7mY)4LeZh(GWf3vB_0eVnTpoiN=1F3fWE3ghfC?DAJLiM$!ajaEtdiCC)rqrja4V&54 zV9p42+&n!hCxR^2M0$HRz!+59@z1KF6XP&R)!}QDL&s7EBR*l-@(O9}BlYKDMxD~N z-7ut*4bNRfffFm;O`{tdwMqoz5V`T)GgpO!KQI4EMBj2>^yvuDrP-QEs{Lcje_7Q$ z5+V#|hn$)b5s@X3wyKP~mU1KWE$aHHRx>9X{$QQrE%mc%SR-R^08b}A{D(jKqhKgu zHAy9LZ9mR8XdT?g{j_(-N`C0fSG=~wCd7TCbGAq(KKkQWB*dn7|mZVx*>cu2PVFM;-aJOhF5*$2Nrmy9An&?=^ z030rPa`DSMVOG;mqF;GViEqz89ddk=n>CXrfCa{7!2z;x_n_`u*KQ54=a#+L=g}cc z)LO)#?(vN_GXNFDs~KsQWg&e9=@tPyzutvzuW;E=7xUTRmbPSt2mPDND&nPp*!u8( zRy*=)Chcf(wxhi;BLQ$HX_?`&ykAM~>CVq6O%{%6RPM&h+mjmt_Iao3&wftHLO9xj zvD=l!^EPH~{B8`sKS4Squ=NL(;5tHCecKqOd0>ZuhFmL1dwHknd#EEV$XTYi7}dTd zs)j;cfSRw?DUCJupWFpsc2Cc?C)?S20ICeFNESUSekd^k)Oq~co=mYx@$<9Y%5EOY zNTk7KaC|DdAFbtrhbX&S&PSE$6O73fGPv84TuirdFoGJa;fOQHL+oL;x~jhwR?MT_ zAdzrjv%&*xjQ)8v$xll}|7PP7uqT8ry5PVf3Ks~%4P(c_9P~ju3@M;b@jR8jTgqyL zm)yLjjGR+7vf{nZtOwjEw>4NO8d&NFlH0>RNLb3+S{pwXU>Ij zRW?esC^DMQf(7|Og5UWh-PStTUKi*{s;xopMP~*V75wNw>bzupIU*;wFL*(Ct7o4$ zsI2>7wkTPHMSXDO&cOW~=mHzLuz&UXFY_2iYaX-F(1sSLCCtuY{R(#TQvGVd@p`iP z^W|hhP1BUxftgWTsILdHOfa0H|ngPZdTo8o9NTPH^}4X;qOY&S1{(*>7(wUEu+attYYS@;|-G zhbv#d@64&U?(@eOYS{c{=FK{@MG81n$Qn3W!oV&gdR@J8r`=6gUy^(*omA;+Ctl&b z=-F^2J}H!Qs|`Z7Th=!>*|_)1d#9m<|D*CdB^%xObC<@_#+E(Jl;Oww1VjZ9 z(<)OvZ6sxB)Sw7{LywifrrmM)VnBA>@yO1*rLrqQz2M*@R@GAtbILW zEs!vhF_+(Jb$&N(c0}$3#rk;IlXQgHk|Rl5+_Q-&LMlA}Jiqe67H%J<^H`J_KIRD3 z**5)p!V+vcPErFGEua=up?gzfGUDG!UD{emT&w#7P?ZX3-HMDqw9w3J`~pd}hibi1 z>sa)?BUk10Tkmu?8t?E6bpIJUd=gkX5K%gXPTBoNf9LMh+K}kWkleI_g+rP8f9?J5 zD<`x^XK10vdL)G?tdg)Mcn}G5>DKaLq9Ih_&uo7!eR`xW9A*00V=KY*gd$Xs(IPA;sAX;K_`soL* M>tb~(v~c171HOS3xc~qF literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/start/images/ui-icons_d8e7f3_256x240.png b/site/vendors/css/jquery/start/images/ui-icons_d8e7f3_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..2c8aac4612416c51f1cefb9e0741232c618e31d8 GIT binary patch literal 4379 zcmd^?`8(8o7stP|7;DCsEe3^@r7YRTHkKhWh^Q2UWZ(A;W~{f!R!EUGLiTKt8Ol}? z*+ygrS#H^PCOo?Tjpucp>vPUe=UnH9_qpDmcvFo2876)v007QhH_*Ka0HD(nSZ9Eo zzU1qM2d8Pp^oE5Vd134SCz#KGHBT4E_}|2s1H5cijR^)$F0@b2uX3m4pfxs=n{aIe;^~P_ z#)B?>y$Xq~2xqiI^laDZKi4Rle8$140^)-ru?rKnp#hAmgfzetbS>2uh0xP^I%x7lOG4x?)12sF4eGkc%(H6LtEKz{{82aR9*BK;t0&v>q_wT& zy|8d$Ctn4{OJdnf%Qd^k*Yc&4(Rn0`!b0z>P~+Gl(3DXZ23sG~{xe$7T)i5)t>kLJ zv-|ViX{SZ$PcNCR)+QjWJ)_MJek)#N+Easls@Xcgf0R@DZ@7p^zP>y6es^Y>{fbw1 zusaz)py@my&GEX2(HDs~mH7TbjZ0OhsC&1wY+xwAypMu11(~=sMc6WnMCvv>-?%N@ z0CFfBiO_rn+ei|Lw72jgMssDpL8F=z?lydM{xU z+8?F^47|m;HBKvES@ThH=q?+bc#5TSs>vnv6@wy(PiD8_-Vqmh+#qv zkJ59od^ZWEzh)A2E)XzH3Y>0*>~xk(!r9-p(sgpdZ|+TZmYyw8HE%|$fEp|o#7wIN zmMKpuz7TB>Bf52htK*27X#I|R;I~Mq?rtnil^_g39e?Ty`i4u0J5L&s)w5s84oNYH zQy*8>oEfr}pkCQgASpas2*u^m{89J;tup;D2h!XZNmYRQ`OCVG^*V0oSqkxNT9YQ| zl<uxpwCUyPP$=p z?$SJ?s_mJ1n9duVjzww#nYdbuqD5s4!CF0HFXOM?PF*&SVXzxfqBns36W<`QegwQS zeOY0}9H!HY@{?%>()y)228v$lo_kdu{oQF@LR5iU18|OR15lgZe+a?g#xcO%-dASY<9{AvH1sR$otYT#*ixXe2QqgqIw;_#;)-@+!X+bFwZ& zHm7CrBkTPGzxs{#c}d-oI=(0T(KRmDm-f1eS#2@R55DUhHnFQ^7SU0egS_5m1%)~or3-b;Qf{YDf8B4i}qI3EDLjV@ghpeREvU#cH zE9(Zc@}Y-W7pVT>e~{Xw+3w`CEmZrufRY4XaN<#}1Ne;*p&|E>*TO%KRp^}mBT~Gq zVC+RtL|*kVg#-IT-`xF{UnMGxSuG^ei;(p_Q|rXtL}K}O29%d3^eSS?SgVV5@xqe?Z7-dJvS$&%ySlDn#~e-7}rAgcG8&S7;~tl7<&-hikCf3WP2a8O`uHh zGz5_td9Q-;!K6>)Lc)0-tEF^)%_t*a4?pv%pjlTNCf~(+pN1~nXbNLWe0kg*4ZKYe z6%J&kZo0BaO?;LH(XCW@R6d4Ku=Hh?OdyaKYvJy55E6(Y1IZnh2Dl4 z)~j=M4%nh{}4Ky2aQgqCeVQBHkt^Dx&0=`AJUJ29_ zvNIod2rBJLe!^>v<0}*fdmg%Lx2Ml7J$lFeO#Jzm38zrcrW~rR_uy6re+QXs3zqXGD7K_QtNnS06B073`mYSUGs{1kFy8;fu+RMG77y07|B z4x{1ksirk&UWOIyYw5i6ol=L^oh30KjIYtBdk^=K1p?Sjlfjr#s}ryFzDq?b`sRT? z@O{IuisRMdXEIsz_vGMB4-lpklzZ(QWvH^RUUwoW7T=XBA{Dc`n<39-N#i^hshyoX z-G_6H#H3+akP7)u3Hq3+ZKNtfq4r-mW!6&WdE)1lqw+zP$Ju!C7PoG|71Np9kyoh3 z66?yUZ2JKE?%y2BaiBg_4Cv*t)kLTtF9g-&zAFT^zEFE@WfE_lmr=9-r}^oVwZ^R+ z8!%Ut26mnvnHxnCZzjGy8)yQm>-=X;$(eDOsOI=J#<6oblM$D+Vs(W$_L1_7mRYZS zZ7%|$Y|DEWUg*q5chmUBW}PzLBvgKU@61(^kk2a%$*5Z%OTL|fdQ>}eDfNHs1TL#t zL_%ya*MJts@=lHjyv2S`$+$)9@fml~4F3^`{U{WU zUrSLwN@B9^A)Efxdrjq?3yi>O^p3G77g-Tdj!1^VD0eCBl01( zw{W95q4n5t-HYe3Ox$}yse$JY-v)~>;iXTltn}lOVlaV|GuT_yG)Ye0E7R9HsU-rnzaUj{-c>-z-Z3tFo#B}6EP7V$Z#SXT$B#o0^ z7Fo@lHRG4Z8whHcFh2a~Yp3{oB`^zsT9sG;K!sKxs5o+y;cOC3iBeUir zxT~6^Ta_3sX2C)NAfX@pQts=W?5_)TrPS9U_hPd`iVJ@Z9CckXxg3?7*B`PdvfXK+S5)}~J8)za>BBi_H!x;37EG=xzHrZwsf@x`)+QTXRrQUAJSaVg{>zhg zO(C|Y2jXP`a{;soizGsXhOqdShyU--zjqr;1wN|0Q?}KcKX+*?eQd?cT!rcQ01vMu zpxb0?rj4botX(_~S}b8Q<^7xR%0D_zCrpuZ5A`ofmiUfD(^_>HsH%8NPkyr<*Y&Sw zYy^`=GUp1~tk3VI&yL8SAlbr(y@*HXZF!=M40n8uu- zx;tiHPgq0D#)<0S;zi`58gzeZOjhCtv0FzQfo=160IF66ZCI0VG)t}grZ14E4p8kk z>YYn|cjT*`f9s#_M&%oRff_htk4pi|1i{OuP-%PL=7|G7?m=cZ)kT30C^_@#{oS8Ei9qMc z;7#ugC&2lIRYaXf z$Iu9QTjKI{=@`X0;s>|huiYwog72I0<@K)~msZqC9_EUz!eQX#LWlJHDi3N7M$;=i z)y3tT;UNGZlCSEaEkm-G@3J^fG;qLr4a?@D(`4LTmu?%YId7(UxQ}^NJeMgQ3b;D9 zeRTYlAJFtcu%}4JrwQSWq=iA?VBut%5YTHRE+!@j$oK42bR?yso4DDsiC0D-US61F z0_eh*%aGWLaAtdC&sLqmGtHvOr<`1>Abuzc_iMr~ERcDHm0d+dS`F_1Yl7u?4{ z7lzDGYLu3E7LPAf2TvYrON#zwnhO)6Nm~=0d0LHrxtPCCIP6B>0dXvC_GCL9x3-nM z6A>xwsfyJgq-S-o&JK8s>i{MGw1%p|r5G-cd{#ns2O|A^MN(5QxPDZ3f+ z?)-Rr(rH2F;|mt+)d@&z&uH_#-%97&`55SoY2i z@t_a}v|I*cIA8TJ`=JPClHZ=IbF1kVb?qgf?XWXQq*%G6nqI(MGAx4lW_BCx9&%IG_ZumLsVV=l7LVKX zEIkv;f1POdb0$Ie91+{3$mL$h!CFEMBi)NH6sKN4=xLLK} z67>ny52E8~%&Hg+HslEg zWx^zQi6?#veAJ@;`;90c+e%VOpgJ3d3`3iWqk%KfTcvy%4hkx*5nr#sdFl1qC7WTC z@{nNOnmF1;lNB!d5&oLaUpml^ji$c*ud9AuG6TBa6INGr8ydQ`>`tkpC2BH{AQ)Fq1;Ci@X(Mnl*?@ePt|hrmm- z7Zuhl4|RLd{<6(LTE7hEK+y}mGcU`dzd5f-iYfAFes#jVVy~3m<(oui8R(|26xit8 z-@X1NC7EgYgQjd{NZ|X1L!3|4^Q>#^haHd0 zK0EI2!DZ%gB&r?}fbgX*8ylX`MD1DKi|XSF>Y0;~n1M9b9H(S}TR%%H9(*b+C#KY4 zq6#*mC&Hi!Z}Sgbojl#xR?aF*Red1}UPSn8r~B}a#yK|!Bm-IR*Os@xho|LmfcwI* zw}DQ54{unUzINS%AEilh63%{ymH1Vo>Z?gk%Q8Wdjbu1dWYMupAW}^|ukv#-7uynK zV_J?dverNFv)_1+kK7%p>vt?LT|x-%G1&Geq4AH((aF^GX0-xe?YBgA+miOX$5>I} z(HgD)lscqiKNIb+eSm-oAc9H|on}(X0KF7`wwiB%L+nb?$(t*W6i3K2BLV$|j^&%)V+&{VQ4vYlbWO8i zg%!1fSh1!oWN6?0x`D;i8dz&&Cc#lhgl}jNWMUZ0T*_S(oy#8(3b2CSXC?iX%S$a^ zUNf9k2s_9+M+*r5gVG_-b|;^1p*hqAmL&Lr6AyD8!LN;p4Y>z=mH~Ne!e;^=kmKcq zV$XXa^Qw=ioVf1>79KbJE71>G)I%e^iCNz=wU0eaC6|6@K>6sxFC(T*w7b|A&fN-1 z%jbs8Z>k0)fqV-12X-96OQZ|{#dH=d+c(b3`-M2<#;)!(pT{KzQVcF+lm^++_TziE z@{eu>agb5bjx58|b93S#2{RuHn)P&G3SDe>>6pUxribvv7f0REz?&2? zksub@h8wHvaL!*Z2p1Dx(}ls~*o*e9!%RrF>{1JJNSvCe(X^H+$kWgW#Df;jY3Kc1jL8 z9*wFyMH%Opn{T-Iwbs5F7JjDbwANf)SD_GOsMU~@qHC@K!$>@86+qk-^eejYQm~$w zo%yIkNO?!3bKgU!J$-KR!CRiE63;$QIEQ&P<uRH%`^Gb#Sd z#8T!e8!s^{QfqPS+#9p}Du3eQlX~Mun6)+ z>=`|*I9e%wDx1Z4M;_614{0_*z0=NFhA#W!eJg@$`AxYZQYovu8S+eyJkEQb*4fG1 zeK6NZN*a~}sZws0V2 zST{BmyL-^L|K?DSf()SIKrgSI7EwU6_YS>P}x`oH~~>nej=>)|W_QAE-a+ne{4H zb|a7~c6_%Hg)Zz2*G;Z%)Tt0m!xYAMPhA!b{j~fm8GXZZ(XTT|pJs0%t?`e&;6-)I zXox7B6LMlk#Ke|By6SSCI;u^qH>m5QIxXBB_=9zduguTtVXe%)K|F)x@E^h055nPu z)fBblwfzMDkaciB@8iB58^xhhU+}t8n-I^9uGwO_#MlpG(IBtY2heMQHjYm{Bk$vS z3)h8VGq3#lKA#?0 zs?I77bw^;dg$bx6Ud~LnE)VN3%&-dD`Smt@dxgi2x>&#gx3(uM-5c0kR+B6PB-V%b zvpbNNvuKBlvz;A9nMr^rNyh@0?fX)CPk(+!WwK~Yt75cFX3{|V9~foSIz-vsay_idm|#w=l*8SW=3%*sgAp`fjfdPJUK00nG}Qxbuo7M! zM#+Q&yA?iQWAx91NkLjN`ZouUkRu^{(G3R{Q#wZwZ5%ra>~( z<+O5EOY)QKNT%)f zL~mYG4dWJy={DnQO+`n~kY7w8aTf!V*TwyW6CQU1?KEsV3fHT zcAz(gqIticW)$@T)9Rc4laKH!C1R2@%w#k|Zm4!`C-dQ=k73cZ2plZ; z7Dfk!Xbb;*5>I~fKmy=nhz4vjX5n*^%36jDPvn(1ipqv_rZS|1WcB4Jr)%4A+aGwY zgUf2IoWnxjhPHx5flOm?NG(%AEeCxwQf((U5Aqa19hytIQZYAwy#q_&e%8eA@^Uop z??N0FCLmU4^PCY2!K^e2oo`^%0)UE!g~J7boimJo)h~ws&J>Zf)OPN;D$?%Kz?6y5 zt2+;Ms88HA4dA4Vg-zDkjf!6oZWE6V(lPGtKCL?X*cHtEJ?G7}rAvIkk?kZ_Q}L%y z#c4OB@FB$qR-tYZ`#v*^##e#+C`nAZsH~0 zhmiwE5|BZ;w%H-%d*uD|Qce3lKRkYUVa%ZR2}GRyfY5cNZRY-+n=`CPuC=={qn%?< z5p3t^tl0$`m(=)$I`9-U`TZGaH!x;B7DA~iK6l3mUPk3FYm*DFs`^St?U(LH|K)MJ zmN5I1eTlNbxj_1aWfCz$Q$%9ZGvN29-#d+^f*(}hs@UnzpSduWKDO*_p$b3RCm{$w_`Eb?fRNac!RWK-FrXbsI9CZl#^y^cnKR5vucA zqjS;!mO{15Z-bNFX#B&^(F3O(@F`%~U_{vzI&JqWg|2hWT zRZVJxWSKxp1Lsr@*qoG4y&6mZE9n!!uOV?cy^M&RUC8W)h8WNRrDQ(2yYr(b5$HT# zn6@uGFw$Y_NfdDj59nR`N)=K|W5jPbl1q-b|C;I(C`z?0T+DjGXq}oP%vj>#!#rI~ z@!5Bk+5l-PxcA621ZdpFj+<(by}TPQ1-!vUV3Qf?#cc%}heD7?u*&T98xs-1c$@{| z^`ewC^#Waan}G5@E;c2y(N~xG*ok$=D|_0*kWpey%YN>Oz1h=Z9`+Y>5-&A7`Sb%< M^|5-DI=IOH0UUIui2wiq literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/start/images/ui-icons_f5e175_256x240.png b/site/vendors/css/jquery/start/images/ui-icons_f5e175_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..7862520c961135847e5dc20a3a148e9fae80e60a GIT binary patch literal 4379 zcmd^?`8(8o7stP|7z`O(wipyrma=3U+gOIkAfi$Xl6~JZF=I_+E98!>5wd5C%uu$H z$TlJ~h}^R8On7wv8_(-H*XNv{&biJH?{mFB@n%?qQ*Z$|005`18tPpK0MJPZtT91O zUdmOY{gbq8cFj_Mdphv{Cmy{w-ac6z8*m+K0r0WQLz&D-QCYHQEq%1_;{-Uru!^Yj z=olIyZ%bUhE*+y7NBrQ{`?Xs|Pw;&+zP$d`lhTSh$-`W+RX7ZsTuVL9-befF2>(XswHRsJV5BD*zihpEEhXSsS zZ66(fb=q7HqY~qy>h?f^8 znE<-*jnAT36@T@<3^R!>0!ndG;B)VbAki@J9@%Laz>%loKkGmxokQ-mFhXrx}V%e9*# zEf6avp_ss^>%u|cfYX%&q-&Yt_CHF(1lDe{YiXFp2;3Yi*8EVGpemh@jV`EWVe}R; zrT>BNV-YPbt#R7-&wA!PJ!hSc}JP zdX}Dv<-ble`#F=Kdya^0QsiIc#BG-g;Mx;c%Qi`8#?1bvN!>g~kR)rcYx^wGzz;IH_ExU=LDIemxa?9dd$ zIE`@?t(hS^N!q1tMY7_vUt#z>dH|X*pj~G0d0&R-Jh=+cID1j=v3|!jeJf$!4IAB~YCWLx!PE#nHeS=&e$|3_vq&%R}8>w7+aKkk&85IZ*UM@65~c=x@$zl46QHnqQr8uh=W4cljofSq8ePD+M+> z_jj*cfu5 zWuF~)_uw+~I1*Kl2tfE!myHciXrlJ4?nU)+1@+9yNX$SQYmQSgz^$L96%RfYmJ?Iz zFi`~?(Gy|Ngtz&Ju1=nAY%6D#rK-LV1ur6ew$pw1N8_BE1CoKP_iM}B-^0^#IKX{j z*xNv-zK1s~PG7t3!H?1;ISFUK!%F%#~n2T)* zvN0`37+LEd_}Oo~$4Bmt)b%?Sm@Xj%_ZV#ZlhF9b<>+K;db3)Aul8G_x@}4O-D9k% z@Mw+Je@Y$Fv7d={*ginO1Q02?KM38-8JbDUyk`%q5vdu1adt$ z+xJbUR? zm)8tu6~Yd(&d~zG|Dbfpv)#$3TWAh-fh7rk;KajRNAPQ7Vngl$pJhNEoA8-{2jqA; zq1f|Y$h_(!Dktu{frZBn|4Q^j7WL3bZ(`QBOzmS2Q^}>@8BjjD@XLrP6YVaxg>$!p z((<`s^P8#xNg$sB{(&7w@DeElKrx*K%l3`)@_r!>xv{G|&F686ffR!a8KpsXwEg(r zt^A`~K^$aMv?I&#^xT}d3h!y8SvG6jL0k*Nn@JP0Q_O+3QtW<6D?#okk^NoF7Lhu^ z+Yn4<=DQ3ggpfau3yb7=u9PzPH=~V#UBb-Af@VD(m_irZT{@<4z3Cx5@x@VhH1H-x zOeBbfw&BJqJ@H8f#IRiDS@{@3Qy2lwgKD~Quf9h2w{x!y{`f8>G5GH1g%w*Q4SEx1 zRIkC^IqdM{W^z=F?E2!*$f_r^72k9JUMU}1$d2@#mkITr;LVFPEp4B<>nhMeyz1{hJ~MNI;}Mq*HtJ48EQ4;r0ANfz%UYzTLlnz1^tR{ycDb_ zW@kR`5K`We`bf|mCsZg7_T2Z-X-}V9eDId%nZ)zY6V72?O*u6813{W<9TjTi?@WsS zGO?7o%En8~iqu*hJNL#czsjGu__Q893cS`Tb>DW*rY6;2mZ&Y*7^kuJVvhfPYm6qS z?UaA)noj9@;q6{b0*V1|G8?_FjH%n$hnp|N__ZjY^2nKSPC4;e}*2ms!eHV(B4J?9u z5qm}tD~?u*pUGx1-jPQ%-9ws9Q17&JmZ8hOc;AYkT7FZmh*ZkzZiYOUBaic*r*(Gn zb|1_&l9GnyK&q5mC72_4+elS}V(q^O>a3OQ^TbcfhvkE;kFyC9E$-cb8@4mIBd<`M zHP($y#qJ*T?Y}wHqaXvQIMB;$r-jrw`W0M{|E3t+`j7f6Ytwj}yo{Q?Kg~~{tTt}u z*n+vEG;#BcsN5*BL^J8l=^#^3UFV}!Wf$gQlDgBE7^lvqOlEx2vh^j>*azxQdS<=K zmE8!WiXGo=M4<~i!*!Eu8+9rK(=dhc-BXuELq9G5N=D!CT=eS<(x=&5NNYT@7rdx$ z84VGIb3#tch?v+CNLO9XQ%ALl^#*l)RHucT1Anki@s;^mJ*<_vH;8AD9R4F1`$0II zu$rQlytbdYa=Y7(*W1~29>I+_1Y7^qQ(KTBvml*qDEE?ps`T%+@(8lqZXXJfc zZ{d1#LhF&!nm6xb*|>MaQbVurehrqN!%Lr9TN}hB#bARbXK*)YX;NH#m!_}edYkFl z#sOSz`3i~4I}tY1k7HkYPf2diKN)gOc7DAL-(KOdqb?S3z^(1cO7{jfm(?W80EzYC z{p=3pvW&6IA-qW9-QJE|n)2iA{RCFXa2JQ1tHJtvGmW^<> z2V=LZO6Kh>JOn+M{C|S~SmPmgh?m6u98L8=8?1y^ zhfy-&z;1;P*ckouU{a8ljQ-8RBjiX3Uv$HP#gxtwL>tGBLb(`2c9_yY9~1ei{I^s! z2rqc~&6&BUYUL&Sp4kq1P;P3mQM9ns_bC0Dt<-5Ff3tXp#B|hoE>2EPr4IJhB+cVq zRynPlRg)J->qy!|sXvp6@3dCU3&YnxKBpJ)^p~Gc+W!}igDK!UBGlUxZ#z1uMP|)K z@KiO)v??=O&Vq#nLBih!q&?O;IbId&No%Y@?!;z=78m{)IPAJ$dNC?DuRnA_bgOrt z_)S&+-fVHI7Mtd`kz0dzbD;|yhJQd!H8;iA()j$q4N!FS^!YduyD8_uycm-ulmLC- zdUfZa4)v+KrU9Ikv9QTHyHW8A!foQwK|03W-KSMYAG?CNzvsNUwseUPII^9@YAXKp zsTi($^{y+o!L~mTW2|NOo0UKN)D|g-u9Q7^xP*aSMD)4)fdRaIZ-(m%mE$`nzRQ}O*K88om-8VQdRpK`iO>fm@qNx$Ayadd*-PXRG zvK2}i$($=_vpKt)K0BgtjADN{>`gkvY$=drt?t-G6(g0Nf0|!;Zx45j(R(P)3LkTZ z>TR2UIc5trA17&mix*G}>d?KZF*(Waq;6duB(BZ#9;jLkv~EMj)2+1gn?6IHIzn|` zYjiI9-%_Y{`E78r8;yVXAN0T}2Yd=xHW*Phg-+Z3%6RMc)Y_2vi?F=(!Ueiq!@rIJ zcU6D12!k+Q?JI-|4RA<@M}n1PA?;3XBRTNp& MReh{pr4BCge|;=_i2wiq literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/start/images/ui-icons_f7a50d_256x240.png b/site/vendors/css/jquery/start/images/ui-icons_f7a50d_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..2ed57ef96b5c0f2e4d52f7a3fb6129fd84f4f7fc GIT binary patch literal 5399 zcmd^@)mPMw*TugRlypcl3=IN;G&s~CDcve5Dcv1IgS3j$APO=dpfm!`z^EV$%_A+{ zB11R)T<^c}o^>wvzS`^DeAYTU#ZX_9@)qkY001bpwH_D)0O+3t2&9mIs!l)5`=8k{ z)HPKrkR%br;b}?ZrNon+lQc0kZLarjf{v3B z=>*?fe!gB0{qDk&Qv@lTm>?!u81$DLjkY4X!9$1dahxUH(Tn;<(OQx;vX(4!)u|L(2G ztLz1++`8=t%Q_7Fta9$D<6g1XNTaE@>~$(s*L1*i_lEh$ds&z|*RO3S-cNVDb+Whf{;>F+;%y z`0NdIcYrVb;v{>CKUT^b+~hm?a?8uq44}Q zQMJece{2Wyk@2spg1(9oV-i1fkW7s7g;8?-XWPi~Gccu7z19mP6Uh=8T)Mg=RDVAk z&(=9a_{Ik`!hE8>p%1Q1*ZmchVr=BRb_8QCTh``L#r3yWEA&hyeXmk^ee`Nu{(SN3 zq$0B{hYGGTq4f64SDVBe-KN8xRm%8?}{-Z!XAe!37n zg9xZrb#I=r=NNo9EnsxoHt#aq+(8VFhG@noWZkufBOnmLr{cKe9cDF}ui;|*Q=B1L(ADi{SExI(F6 z$>h45%4QF9YYP$o$uia6KrpkOa*H4;3$NyGCAvjo?^o0#R7cn>?;mH#j7hh#2X7wM z2#Ym z$kLXIv+nZOvyCj;VPYGSW=*U$5y82K69knNfmKV*jS!R0FvcR=fO~O{h)?=+p;^yt zg?G?=A-Sq=7A?x~A4?}48{o)H7Q_<+ zU^JZ!)HJlX`oBXVRAI8Gn;zyq;Rbrb#v~1<(gX#^FGEm~fNV5T$edI2_iagepo2+l<*Esm=o{?reJ`P< zy;}sQeGvT8CZZ!F5}W>WqvCU)(@F3TeO=WZURY{o5a{dKo>_5CR~iU17SxWvJSEj4 zm3!i2H2HLuE%rMp)k`K*9+XWdC~JPbi{>= z&$eF>lMb5z$@UZ^M7xA+gf#>?~t(U(bjWfh_0Ce~(SC4B{j4a!0)Q zBt0q6tFd?m?k=r)0(;y8cOCZZbhIj+4Dv3T_&A5HUlMLDL}}G+la<~R2Y2_$DgIs; z+iCHI55GU28xrVT!jZV^$AryBSuMUUj;ibkyK0-OMuvs(`miy?r#=#`$smIY3ABt; zCqlr^L+Pb^q;pH$R)!>UOF3}qn@r+;cEPm;<+*S?2oGxlPfjzwDsc_QQYOdd`VZeX z`+jw?B?8_oLsaQ_R^8Uj8PMX4B?@a0p#zZKQ4pVk71Ir}zh4#aHir6j=SvSSfSE?t z`7yJNA8vWGh6SV@_-CTfsB(R+^^!QM;HbOQdNgGbr3RjeJY9W?4;{XVYyyJdHJ=;F zOcVuVaNVDSU@VXfWf)r>&FyO!Zx0q@t2|vb)80>^5r2CuFS0_+r3vsIn)Iovq2``G zUu61J%EP$8QugztbSif1lAa2*(0`t6jAkze5JsZjX+pP)OBZ8Qn6dGSN{HXke6;J?jlcOd-{%& zpj#1#t*Xx@Q%xW+DM6CI26CsZ78(iM`C7~H8XG^O$%0=FbPqQVj&R%RKJ3}edB(c) z-NL8*rBUbF`1oz7s+YZ??)gLwk9@(?&|!lmfnoVjF;lypq%xm#RM2pd<+UH$08&Cc zFj%+BtCp$4=A~qDK`y);<;IXV`(63h{J2)vO#+ zGyIYn=AbG_Qek27$FT$k))Ftuc&E!&MA2if_1*Op%>==A$W@{tB&4E@~A;_((>! zgYA=$QJB>EkZ;C!_)yHO*4z2q2YKf0%$-YM9vYwfJhtM20PLE#Q(0u{^7!r6$k{92 zr0vdV_+$A>ar3_uQIy*%-8IV?f?*y|5ZU7@Vtxa$Z=7O*wU9t+Yr6O?!Czg=kK$G( z#>B>4!osNRp4rqUc}Cf2;oXder1+die+@W_DByP%DLbaz!pPhqJ&@T5N`m{FDaN{? z6+?wZ_0+Sn9*@)sdkxaz|6n~tTTb_rTiaVUhpoTOogH25GGE`}SHb6E^We94Es^{X zm{JbBd~-;oGZIN^ z#Yv$nvo-gK@0J7-9FI|U4TjFjkkHYA8z-6+JIxqrP-lO)Yh=`buK_bF1#jCdsNkUR zAxt@yevU7&*eH?rXD@vD6^-jFvi zpY1T33CQd(XDE4=uOh!GZ>-m6p0+Gbno6p6sEX-tK_eV*iq!5~+%1)-u4gXj{{hcJ&qa?+S<;xb8`jB_4hv z9bRMUk5(Zy#}b57IkI^u_Q}%JccYM3@&O?lOLggb^pl>Kh9eKPw6s3;p1PU`i2c+= zaL2S?_$ryF(W+b$ab!}`xL$gg{(iQ1mZpWl`^V^mkxgCil*j$T#;I5USD!mQF(z1M zS1=^l=Xki>gxcXOiH~`OLs$INoUu5^fbcyBPHuxr`vo-j0+Idj5uM-Jky)w>92Gqq z%Ld|fF-EgLQQ|(M5IQ;~*FTL!By$Web?nz9G}exUL1BVa3eHNGJC8L9<<6UR$C zZeQis^+FF0ug@dr5mEE63`%~F)X4Dh^0Kpcd)Gu7CTEC5biE{j$S7Se@7f=ee^Glx zn=mO-Kfk?_6+ZW3!dpl3#2DzRd1cQsOa#G4>$M;A?D#wU5>tyEk=7t-=D&402jsU8O!3 z8cjW;$ohVRKU4eb&mge|S59~%Dk%Yhy12OPNCU6?D;V_#G?&bNB%C);WG#|+qmm?! zaY-9KA_h0Y-|q=ir5H}Cx!gm|zr3J&4k|I}bTpbL2`<#bqTraGTWQPm7x8kC=jC8y z=1JA&dZ7@5_adJ3g7>1sv05s_JVytco3)^ETiG@p4@z|-VGn}#GXa2@I4Qjm9kAxz zZH;5H4G3G`*EOyl7;-E*X)IL8^RJ`jP7OCtRDWW-I9tNZbqQU@A!8|PFQYz+^h^H< zd+$uWQ}Z4^#B`dN)!L3xj2A zO$GeUE1gxI#4L&tCe~zmh+e(GI0jAcNIf2jKb=sDso-n~OD&maa^-8XBi582f2{_0 zM+w_vfdQXPP{~jMr;yTr0U&w19eF_~@*P`T@W3voSM0aw?mipw`+F7!b)X>joW8yz zkIA~1`=LiQROd8+#Cay(dXwkflM4>J=hyUVD0i?QGG$22l6wW`{4;QdNcppZtFgT3 z*N{CNGWk2TSX$F-1C0BrP0%Ta$S--y#@ey$d9s!aA+sOl3~~Ln3++W3BK9&xU%}JI z?Jem?Z@otE6uk$BvY$ThUz8MJxZ&IL7D%udZ#@msp9?5gh4cH!7VaE4?Oqx*eGlzGtjcfXntd2Op&hQZ5?3|qYv zeFFnUVwxZ5sg#DK0nUO2%cftb>T2fz{SueWG2!NUXtB2E_|Zkj&|^`?`4{-AHL+k3 zUj4>=F0M zH+X;U>+Dp2ew->>zpg^nF*cxg9qpnf&c(dVAS^KLX3(q2-pVmfLO$!lrl2rqT^f2_ zza6pc^mpu&odBC`m&-41avRzySntP*#!$U=+267^zr#WL9n2R_C}Ht|jsjwd>3@~h zm*#YqQV|}^@@FNK%CxQAHaTmuIyWQc^eMSssl&cK=c(CN8R2|l=KUh-)vNgUOipo! zcl6P(14vqfhgvM6y#7;a0_+vQeb7wMk0G5fb!%w|4D0naO9663ePR0hVWJMI@vjB_ zqyS`E2mdkL5nEgUSiJJ;B>RW`(Amvh+}c1dV^no-nEj(p=a=v41m7?^S2i*~Q+KYTpJoR!3h4}6*uBv$xeJEb!B!Tdw*$dWfX@FgVYDv9m>hPt*ILkuTwHHSG@Sq7qX=0JfeKb6(YD3I z%b|6svI0=-SEi6tEsEA{JvbMaJ=4ZD!;mT$ePq(R+nxSjI$Al$lS~lADv8QV8Z362 zPo#(lELmu=jh*MeYaC37HwdxQ$_uPCYQglbLf1);AuLK~qR^k6RWK>w QU*QL6tLs0gMcT#w4-}h1IRF3v literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/start/images/ui-icons_fcd113_256x240.png b/site/vendors/css/jquery/start/images/ui-icons_fcd113_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..68dcff54de8a46fe05a3f1d10dab78c7818b5351 GIT binary patch literal 4379 zcmd^?`8(8o7stP|7z`O(wipyrma=3U+gOIkAfi$Xl6~JZF=M?&wnB=m5wd5C%uu$H z$TlJ~h}^R8On7wv8_(-H*XNv{&biJH?{mFB@n%?qQ*Z$|005`18tPpK0MJPZtT91O zUdmOY{gbq8cFj`%&mh2=$acf)2 zI}wq>PW}q2x8#z!wp(_MpVbRz~6 z@6M06C!H2#KE7bFUY&rn_KY^)`>k{yzN-%VShKlL_#m(R-*8dUd;<@jz3$91hh^{V z5DyArK+9!7hVxYqvmc6JCi(5TI=7l`QTI+~*}zbKc^?&R1~PSRim+o5jnr#)xpq^e z1!Bb{6cZSAT{s9FaJq7UbS+cd{zplez}iiAEe*36ftzE+njgv%RHgH=(FN5kjNT%q z^gr-@ETYAwHBLKUMe9Lw*bX~`M2eM5s_6yHCBq_!Z)UgA?jbj2eZP@1n40n*Yw@^E z&(bro{MU(QKW7qj&k?arid^o691K>ABH3Rz({*#fukTEEmYyz9vuH-Cf*LG;iJMgm zE>WLQ{UAD?#tdsjH>VMEvHER~ps$foy`5OP8c_s-KKj@d{1u-Nca}UNr|+<>8u9fCoR?m&U9uTQ zDGv$et%;*uG+E)IAK|a*{G|i!*l6m@|GGN)(}RAB7mmYQmfO%9&R_OzpwC^)UZ!DV z?!r8?n%${+nC@%5u4QTgg|t$OrblHA!CF0IFA^@_OkJ{wVX_}lW;BHT6W<`Yb_l#Q zdr@J{@=&)I?JwI5r1i^i4ivr6JM*$U`kV8bq?jU)=2s`&EA~q1UA{?VmVs{SN`Z~e z{oU(dQj(dLKWNHUh6KKEIK=rxJZ` zdmHG~_wa_r>1)?L_)(f9C*kaOSczXXs=k`!v@8=O*+_;XMHU^q1R~Yc^C~|VbFnQ! zHm2nWBWwKwKl_dM_{iOnx_-w3(2vH1VLQP(|C~yYQ0ESKdd;1s6%~<$P1iIV zR#;Ixh!tzfLWcI;uNzoQt%0>hW)d8AMEHgVK_-T=%%$8#(YgEqp#UrBeOA(MxxCc! zIPoyo5&YVi*pPd`XBm*kCVVE~0Xbey zDE7P;GOzlG%8C1KVBvAYzY_hBMLjgqo0#=2Q~TJ%RC4Ke29%F3{4!$7M7xV^;oPmD zw0v&Z{HAI^63C~3e_+QEyhO?XP)ujRvVG&cykCezZtUt#^LboiAjRN9Mrn{8Z9l$u zEC1+L5C<6*?Z`4bJvS$=!h0HNmdzS>5ZA)+X3~W06my`h6uTeNN{~BBWPca4MWjyf zHUyKI`7VPAA>@za!XkN|E2Rwn&1hp_moW3Opjl4`rqIQ9myRi1Z+Zw%d~wtr4ZKMa z6A5CWZMd;YPkfRAF)UYkRz8Bz6h=Vvpqg&ntFO`h?c6JaKfX&z48Hq$VZ|0ngWiN0 z)oXBf4m&))nH&`(yT14{vg+|{#rNF5SIUPLvLk)xWkS6tc(W&7GYFo!67DK&VW;Gf z|gmaizQx47jK#-sJCowS zOe|%tvhfnLBDEIB&b=|qukt4@KB-5K0iD)d76N2??21{g(#bn&%%*nCyLI+GF{1gM^`I-&MOW zkJSwDQrDidD8mW$wRGP4My&61grCRZ5KeTMref`J@n$zbfL^|AL_--V)O1B)PE z#GcW^ildd{r?Od$cjOUG_mE~2)I05*W$3am-nSyCmfw^sB9*ebn<3BS$m6`{X`P+C z-3N1xq@-avkSgU?3FZjiHc}O#So<%6I%_5SEb-IwVfi5Iqiljii+eZVhV9Jl$SYK5 zjdf#FvAYL-`)>~QD98XR4)pTcX(2U^eg)U#zbOW{K39KbZ5nTrmr=9#r}@d_)yB;n zTQGN&CT^Y)l^aEtXePZm9b^is>-=X`*@bzSr0(=3#;J2DlNq11Y<-C|_JR77o>{MQ zWj6w;V#jwIQRu?XaNXqEMx6@5G)!T9_ta(4&`-<1lF>Ij7yUYe^lA1M(i;ER3tm*W zjE0E9IUy%zL`-Z6q^mCHsiWG&dV{(?s?);Ffj?NM_{#jO9@fg-8^kk64*wC1{U97p zSWQt&UfWOb4_OEI^FHp|u~8g4^#!jhwF&Xu=$b8-ON{+677g-ReE_`{Xyf?QGx9#J zw{X2Vq4mgV&71d;Y}`9ysiD_*zXr?C;iXTktqtOmVz5DzGq@YHG$}5=OVd|!z0LG& z;{YzVe1*j2od}!hN3k!xrzE%M9}hXd&dZ)j7s3ML^57tOxMxVujVm_>IrGY&@AK)A zrRuEWP+-Pv!VIgRonLRmw^w-VsEY+0aBF+A(!GJrWi`n%Kw^D( zKf42YIg56^=T4+6?yrF#z(=xcjL_@9>roXt={5{;67UC*bQiAH( z64yYX&Ot3#>s7{@299roFM4L=IFcRgy#RHlHYA&YjUbem1nN3^d$22JFQjo!tnKv&*()w{pIJA_W#A>U<&w-2=(^F+l~%uky&#Q zJXK9Ht;)=nvtVICknnc_X^*u|j#q_x(i&@!JF!`z#f3ix4!bUxUX04k>knNJ-Rj*Z zepA)IH(Q*l#isdfMzSUW?Mds(eTDrmnF;&yL%#4Ee`WV)oX8sQphFR2ijKINi zZ((#$h_>+0C-LMr4E-y#p z{w~B}VFF@xHqRNc5X?%W(D?>7EdZ!!SU6k|*g3=aSN&r6?@SR%OKsLy;| zeHb}#Bmo(eYnvTHzDM3aFV(c~^TXqp7sd=~pFqUP4+vdX+Gg(GxjDm%C|r~^+yli#0#b^~M9VS5t%{xg{Fw`5>0`^@7OL>0eFCDA zh-s6nnKqHJwsG~`Z?S^OmiKQUD*xy@AHyT(?i-w!D)AeMrnl-c(bNc5UIOOZZfjpo z*$O3%WX=_|*__=?pB+&+MzKE}_9h)-wiHORR(I^8ijhjsKFzPZw}(5%=sgr?g^xKy z^|sBw9J7U*kCQaO#S5qfb?DyIn4IKyQn#)S64&N=4^*uNTDKwN=~mkLO`jo89HBa| zH98mlZz)u}{5Ck*jmAIx96fN#0iObv4Mvnrq0@H1GTyp9wKgRFA}lYxaDgt@@ULUQ zUDc#ENR|ntG;mJkfXzwy)T^=dzmh%y{2CIM)60n1*@et*XovwFP)g>LyE{L65`oU+ zg=zc310x-#ouT&wmG)DY}Be~>=`>&}!fudB~!o{o?jMk|+!i*&zKFrg_ z6rX)psSS{(f_slVLx9Fz?6|20*~`1}QotKr1U8wGUffo&aVP|N1gp$mzcCRJjK^6Z zUN1^XQ!mh!w+Sfk<6=`H8+~<|kDXX|yt1b~3>hWXwCv}e*qc2q=3#$9C-G9VlTSZz MRUfNYse_CBAD`Y@O8@`> literal 0 HcmV?d00001 diff --git a/site/vendors/css/jquery/start/ui.all.css b/site/vendors/css/jquery/start/ui.all.css new file mode 100644 index 0000000..d30294c --- /dev/null +++ b/site/vendors/css/jquery/start/ui.all.css @@ -0,0 +1,406 @@ +/* +* jQuery UI CSS Framework +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. +*/ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } +.ui-helper-clearfix { display: inline-block; } +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { height:1%; } +.ui-helper-clearfix { display:block; } +/* end clearfix */ +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } + + + +/* +* jQuery UI CSS Framework +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=2191c0&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=75&borderColorHeader=4297d7&fcHeader=eaf5f7&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=0078ae&bgColorDefault=0078ae&bgTextureDefault=02_glass.png&bgImgOpacityDefault=45&borderColorDefault=77d5f7&fcDefault=ffffff&iconColorDefault=e0fdff&bgColorHover=79c9ec&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=448dae&fcHover=026890&iconColorHover=056b93&bgColorActive=6eac2c&bgTextureActive=12_gloss_wave.png&bgImgOpacityActive=50&borderColorActive=acdd4a&fcActive=ffffff&iconColorActive=f5e175&bgColorHighlight=f8da4e&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcd113&fcHighlight=915608&iconColorHighlight=f7a50d&bgColorError=e14f1c&bgTextureError=12_gloss_wave.png&bgImgOpacityError=45&borderColorError=cd0a0a&fcError=ffffff&iconColorError=fcd113&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=75&opacityOverlay=30&bgColorShadow=999999&bgTextureShadow=01_flat.png&bgImgOpacityShadow=55&opacityShadow=45&thicknessShadow=0px&offsetTopShadow=5px&offsetLeftShadow=5px&cornerRadiusShadow=5px +*/ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #a6c9e2; background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x; color: #222222; } +.ui-widget-content a { color: #222222; } +.ui-widget-header { border: 1px solid #4297d7; background: #2191c0 url(images/ui-bg_gloss-wave_75_2191c0_500x100.png) 50% 50% repeat-x; color: #eaf5f7; font-weight: bold; } +.ui-widget-header a { color: #eaf5f7; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #77d5f7; background: #0078ae url(images/ui-bg_glass_45_0078ae_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #ffffff; outline: none; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #ffffff; text-decoration: none; outline: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #448dae; background: #79c9ec url(images/ui-bg_glass_75_79c9ec_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #026890; outline: none; } +.ui-state-hover a, .ui-state-hover a:hover { color: #026890; text-decoration: none; outline: none; } +.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #acdd4a; background: #6eac2c url(images/ui-bg_gloss-wave_50_6eac2c_500x100.png) 50% 50% repeat-x; font-weight: normal; color: #ffffff; outline: none; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #ffffff; outline: none; text-decoration: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fcd113; background: #f8da4e url(images/ui-bg_glass_55_f8da4e_1x400.png) 50% 50% repeat-x; color: #915608; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #915608; } +.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #e14f1c url(images/ui-bg_gloss-wave_45_e14f1c_500x100.png) 50% top repeat-x; color: #ffffff; } +.ui-state-error a, .ui-widget-content .ui-state-error a { color: #ffffff; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #ffffff; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_0078ae_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_0078ae_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_d8e7f3_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_e0fdff_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_056b93_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_f5e175_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_f7a50d_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_fcd113_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-tl { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; } +.ui-corner-tr { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; } +.ui-corner-bl { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; } +.ui-corner-br { -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; } +.ui-corner-top { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; } +.ui-corner-bottom { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; } +.ui-corner-right { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; } +.ui-corner-left { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; } +.ui-corner-all { -moz-border-radius: 5px; -webkit-border-radius: 5px; } + +/* Overlays */ +.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_75_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } +.ui-widget-shadow { margin: 5px 0 0 5px; padding: 0px; background: #999999 url(images/ui-bg_flat_55_999999_40x100.png) 50% 50% repeat-x; opacity: .45;filter:Alpha(Opacity=45); -moz-border-radius: 5px; -webkit-border-radius: 5px; }/* Accordion +----------------------------------*/ +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } +.ui-accordion .ui-accordion-li-fix { display: inline; } +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; } +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; } +.ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker +----------------------------------*/ +.ui-datepicker { width: 17em; padding: .2em .2em 0; } +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } +.ui-datepicker .ui-datepicker-prev { left:2px; } +.ui-datepicker .ui-datepicker-next { right:2px; } +.ui-datepicker .ui-datepicker-prev-hover { left:1px; } +.ui-datepicker .ui-datepicker-next-hover { right:1px; } +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } +.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; } +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { width: 49%;} +.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; } +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } +.ui-datepicker td { border: 0; padding: 1px; } +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { width:auto; } +.ui-datepicker-multi .ui-datepicker-group { float:left; } +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } +.ui-datepicker-row-break { clear:both; width:100%; } + +/* RTL support */ +.ui-datepicker-rtl { direction: rtl; } +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } +.ui-datepicker-rtl .ui-datepicker-group { float:right; } +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } + +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ +.ui-datepicker-cover { + display: none; /*sorry for IE5*/ + display/**/: block; /*sorry for IE5*/ + position: absolute; /*must have*/ + z-index: -1; /*must have*/ + filter: mask(); /*must have*/ + top: -4px; /*must have*/ + left: -4px; /*must have*/ + width: 200px; /*must have*/ + height: 200px; /*must have*/ +}/* Dialog +----------------------------------*/ +.ui-dialog { position: relative; padding: .2em; width: 300px; } +.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } +.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } +.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } +/* Progressbar +----------------------------------*/ +.ui-progressbar { height:2em; text-align: left; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* Resizable +----------------------------------*/ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; } +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Slider +----------------------------------*/ +.ui-slider { position: relative; text-align: left; } +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; } + +.ui-slider-horizontal { height: .8em; } +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } +.ui-slider-horizontal .ui-slider-range-min { left: 0; } +.ui-slider-horizontal .ui-slider-range-max { right: 0; } + +.ui-slider-vertical { width: .8em; height: 100px; } +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } +.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs +----------------------------------*/ +.ui-tabs { padding: .2em; zoom: 1; } +.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; } +.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } diff --git a/site/vendors/js/jquery/jquery-ui.js b/site/vendors/js/jquery/jquery-ui.js new file mode 100644 index 0000000..01da18f --- /dev/null +++ b/site/vendors/js/jquery/jquery-ui.js @@ -0,0 +1,9133 @@ +/* + * jQuery UI 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI + */ +;jQuery.ui || (function($) { + +var _remove = $.fn.remove, + isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9); + +//Helper functions and ui object +$.ui = { + version: "1.7.2", + + // $.ui.plugin is deprecated. Use the proxy pattern instead. + plugin: { + add: function(module, option, set) { + var proto = $.ui[module].prototype; + for(var i in set) { + proto.plugins[i] = proto.plugins[i] || []; + proto.plugins[i].push([option, set[i]]); + } + }, + call: function(instance, name, args) { + var set = instance.plugins[name]; + if(!set || !instance.element[0].parentNode) { return; } + + for (var i = 0; i < set.length; i++) { + if (instance.options[set[i][0]]) { + set[i][1].apply(instance.element, args); + } + } + } + }, + + contains: function(a, b) { + return document.compareDocumentPosition + ? a.compareDocumentPosition(b) & 16 + : a !== b && a.contains(b); + }, + + hasScroll: function(el, a) { + + //If overflow is hidden, the element might have extra content, but the user wants to hide it + if ($(el).css('overflow') == 'hidden') { return false; } + + var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop', + has = false; + + if (el[scroll] > 0) { return true; } + + // TODO: determine which cases actually cause this to happen + // if the element doesn't have the scroll set, see if it's possible to + // set the scroll + el[scroll] = 1; + has = (el[scroll] > 0); + el[scroll] = 0; + return has; + }, + + isOverAxis: function(x, reference, size) { + //Determines when x coordinate is over "b" element axis + return (x > reference) && (x < (reference + size)); + }, + + isOver: function(y, x, top, left, height, width) { + //Determines when x, y coordinates is over "b" element + return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width); + }, + + keyCode: { + BACKSPACE: 8, + CAPS_LOCK: 20, + COMMA: 188, + CONTROL: 17, + DELETE: 46, + DOWN: 40, + END: 35, + ENTER: 13, + ESCAPE: 27, + HOME: 36, + INSERT: 45, + LEFT: 37, + NUMPAD_ADD: 107, + NUMPAD_DECIMAL: 110, + NUMPAD_DIVIDE: 111, + NUMPAD_ENTER: 108, + NUMPAD_MULTIPLY: 106, + NUMPAD_SUBTRACT: 109, + PAGE_DOWN: 34, + PAGE_UP: 33, + PERIOD: 190, + RIGHT: 39, + SHIFT: 16, + SPACE: 32, + TAB: 9, + UP: 38 + } +}; + +// WAI-ARIA normalization +if (isFF2) { + var attr = $.attr, + removeAttr = $.fn.removeAttr, + ariaNS = "http://www.w3.org/2005/07/aaa", + ariaState = /^aria-/, + ariaRole = /^wairole:/; + + $.attr = function(elem, name, value) { + var set = value !== undefined; + + return (name == 'role' + ? (set + ? attr.call(this, elem, name, "wairole:" + value) + : (attr.apply(this, arguments) || "").replace(ariaRole, "")) + : (ariaState.test(name) + ? (set + ? elem.setAttributeNS(ariaNS, + name.replace(ariaState, "aaa:"), value) + : attr.call(this, elem, name.replace(ariaState, "aaa:"))) + : attr.apply(this, arguments))); + }; + + $.fn.removeAttr = function(name) { + return (ariaState.test(name) + ? this.each(function() { + this.removeAttributeNS(ariaNS, name.replace(ariaState, "")); + }) : removeAttr.call(this, name)); + }; +} + +//jQuery plugins +$.fn.extend({ + remove: function() { + // Safari has a native remove event which actually removes DOM elements, + // so we have to use triggerHandler instead of trigger (#3037). + $("*", this).add(this).each(function() { + $(this).triggerHandler("remove"); + }); + return _remove.apply(this, arguments ); + }, + + enableSelection: function() { + return this + .attr('unselectable', 'off') + .css('MozUserSelect', '') + .unbind('selectstart.ui'); + }, + + disableSelection: function() { + return this + .attr('unselectable', 'on') + .css('MozUserSelect', 'none') + .bind('selectstart.ui', function() { return false; }); + }, + + scrollParent: function() { + var scrollParent; + if(($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) { + scrollParent = this.parents().filter(function() { + return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); + }).eq(0); + } else { + scrollParent = this.parents().filter(function() { + return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); + }).eq(0); + } + + return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent; + } +}); + + +//Additional selectors +$.extend($.expr[':'], { + data: function(elem, i, match) { + return !!$.data(elem, match[3]); + }, + + focusable: function(element) { + var nodeName = element.nodeName.toLowerCase(), + tabIndex = $.attr(element, 'tabindex'); + return (/input|select|textarea|button|object/.test(nodeName) + ? !element.disabled + : 'a' == nodeName || 'area' == nodeName + ? element.href || !isNaN(tabIndex) + : !isNaN(tabIndex)) + // the element and all of its ancestors must be visible + // the browser may report that the area is hidden + && !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length; + }, + + tabbable: function(element) { + var tabIndex = $.attr(element, 'tabindex'); + return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable'); + } +}); + + +// $.widget is a factory to create jQuery plugins +// taking some boilerplate code out of the plugin code +function getter(namespace, plugin, method, args) { + function getMethods(type) { + var methods = $[namespace][plugin][type] || []; + return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods); + } + + var methods = getMethods('getter'); + if (args.length == 1 && typeof args[0] == 'string') { + methods = methods.concat(getMethods('getterSetter')); + } + return ($.inArray(method, methods) != -1); +} + +$.widget = function(name, prototype) { + var namespace = name.split(".")[0]; + name = name.split(".")[1]; + + // create plugin method + $.fn[name] = function(options) { + var isMethodCall = (typeof options == 'string'), + args = Array.prototype.slice.call(arguments, 1); + + // prevent calls to internal methods + if (isMethodCall && options.substring(0, 1) == '_') { + return this; + } + + // handle getter methods + if (isMethodCall && getter(namespace, name, options, args)) { + var instance = $.data(this[0], name); + return (instance ? instance[options].apply(instance, args) + : undefined); + } + + // handle initialization and non-getter methods + return this.each(function() { + var instance = $.data(this, name); + + // constructor + (!instance && !isMethodCall && + $.data(this, name, new $[namespace][name](this, options))._init()); + + // method call + (instance && isMethodCall && $.isFunction(instance[options]) && + instance[options].apply(instance, args)); + }); + }; + + // create widget constructor + $[namespace] = $[namespace] || {}; + $[namespace][name] = function(element, options) { + var self = this; + + this.namespace = namespace; + this.widgetName = name; + this.widgetEventPrefix = $[namespace][name].eventPrefix || name; + this.widgetBaseClass = namespace + '-' + name; + + this.options = $.extend({}, + $.widget.defaults, + $[namespace][name].defaults, + $.metadata && $.metadata.get(element)[name], + options); + + this.element = $(element) + .bind('setData.' + name, function(event, key, value) { + if (event.target == element) { + return self._setData(key, value); + } + }) + .bind('getData.' + name, function(event, key) { + if (event.target == element) { + return self._getData(key); + } + }) + .bind('remove', function() { + return self.destroy(); + }); + }; + + // add widget prototype + $[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype); + + // TODO: merge getter and getterSetter properties from widget prototype + // and plugin prototype + $[namespace][name].getterSetter = 'option'; +}; + +$.widget.prototype = { + _init: function() {}, + destroy: function() { + this.element.removeData(this.widgetName) + .removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled') + .removeAttr('aria-disabled'); + }, + + option: function(key, value) { + var options = key, + self = this; + + if (typeof key == "string") { + if (value === undefined) { + return this._getData(key); + } + options = {}; + options[key] = value; + } + + $.each(options, function(key, value) { + self._setData(key, value); + }); + }, + _getData: function(key) { + return this.options[key]; + }, + _setData: function(key, value) { + this.options[key] = value; + + if (key == 'disabled') { + this.element + [value ? 'addClass' : 'removeClass']( + this.widgetBaseClass + '-disabled' + ' ' + + this.namespace + '-state-disabled') + .attr("aria-disabled", value); + } + }, + + enable: function() { + this._setData('disabled', false); + }, + disable: function() { + this._setData('disabled', true); + }, + + _trigger: function(type, event, data) { + var callback = this.options[type], + eventName = (type == this.widgetEventPrefix + ? type : this.widgetEventPrefix + type); + + event = $.Event(event); + event.type = eventName; + + // copy original event properties over to the new event + // this would happen if we could call $.event.fix instead of $.Event + // but we don't have a way to force an event to be fixed multiple times + if (event.originalEvent) { + for (var i = $.event.props.length, prop; i;) { + prop = $.event.props[--i]; + event[prop] = event.originalEvent[prop]; + } + } + + this.element.trigger(event, data); + + return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false + || event.isDefaultPrevented()); + } +}; + +$.widget.defaults = { + disabled: false +}; + + +/** Mouse Interaction Plugin **/ + +$.ui.mouse = { + _mouseInit: function() { + var self = this; + + this.element + .bind('mousedown.'+this.widgetName, function(event) { + return self._mouseDown(event); + }) + .bind('click.'+this.widgetName, function(event) { + if(self._preventClickEvent) { + self._preventClickEvent = false; + event.stopImmediatePropagation(); + return false; + } + }); + + // Prevent text selection in IE + if ($.browser.msie) { + this._mouseUnselectable = this.element.attr('unselectable'); + this.element.attr('unselectable', 'on'); + } + + this.started = false; + }, + + // TODO: make sure destroying one instance of mouse doesn't mess with + // other instances of mouse + _mouseDestroy: function() { + this.element.unbind('.'+this.widgetName); + + // Restore text selection in IE + ($.browser.msie + && this.element.attr('unselectable', this._mouseUnselectable)); + }, + + _mouseDown: function(event) { + // don't let more than one widget handle mouseStart + // TODO: figure out why we have to use originalEvent + event.originalEvent = event.originalEvent || {}; + if (event.originalEvent.mouseHandled) { return; } + + // we may have missed mouseup (out of window) + (this._mouseStarted && this._mouseUp(event)); + + this._mouseDownEvent = event; + + var self = this, + btnIsLeft = (event.which == 1), + elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false); + if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { + return true; + } + + this.mouseDelayMet = !this.options.delay; + if (!this.mouseDelayMet) { + this._mouseDelayTimer = setTimeout(function() { + self.mouseDelayMet = true; + }, this.options.delay); + } + + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { + this._mouseStarted = (this._mouseStart(event) !== false); + if (!this._mouseStarted) { + event.preventDefault(); + return true; + } + } + + // these delegates are required to keep context + this._mouseMoveDelegate = function(event) { + return self._mouseMove(event); + }; + this._mouseUpDelegate = function(event) { + return self._mouseUp(event); + }; + $(document) + .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate) + .bind('mouseup.'+this.widgetName, this._mouseUpDelegate); + + // preventDefault() is used to prevent the selection of text here - + // however, in Safari, this causes select boxes not to be selectable + // anymore, so this fix is needed + ($.browser.safari || event.preventDefault()); + + event.originalEvent.mouseHandled = true; + return true; + }, + + _mouseMove: function(event) { + // IE mouseup check - mouseup happened when mouse was out of window + if ($.browser.msie && !event.button) { + return this._mouseUp(event); + } + + if (this._mouseStarted) { + this._mouseDrag(event); + return event.preventDefault(); + } + + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { + this._mouseStarted = + (this._mouseStart(this._mouseDownEvent, event) !== false); + (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); + } + + return !this._mouseStarted; + }, + + _mouseUp: function(event) { + $(document) + .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate) + .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate); + + if (this._mouseStarted) { + this._mouseStarted = false; + this._preventClickEvent = (event.target == this._mouseDownEvent.target); + this._mouseStop(event); + } + + return false; + }, + + _mouseDistanceMet: function(event) { + return (Math.max( + Math.abs(this._mouseDownEvent.pageX - event.pageX), + Math.abs(this._mouseDownEvent.pageY - event.pageY) + ) >= this.options.distance + ); + }, + + _mouseDelayMet: function(event) { + return this.mouseDelayMet; + }, + + // These are placeholder methods, to be overriden by extending plugin + _mouseStart: function(event) {}, + _mouseDrag: function(event) {}, + _mouseStop: function(event) {}, + _mouseCapture: function(event) { return true; } +}; + +$.ui.mouse.defaults = { + cancel: null, + distance: 1, + delay: 0 +}; + +})(jQuery); +/* + * jQuery UI Draggable 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Draggables + * + * Depends: + * ui.core.js + */ +(function($) { + +$.widget("ui.draggable", $.extend({}, $.ui.mouse, { + + _init: function() { + + if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position"))) + this.element[0].style.position = 'relative'; + + (this.options.addClasses && this.element.addClass("ui-draggable")); + (this.options.disabled && this.element.addClass("ui-draggable-disabled")); + + this._mouseInit(); + + }, + + destroy: function() { + if(!this.element.data('draggable')) return; + this.element + .removeData("draggable") + .unbind(".draggable") + .removeClass("ui-draggable" + + " ui-draggable-dragging" + + " ui-draggable-disabled"); + this._mouseDestroy(); + }, + + _mouseCapture: function(event) { + + var o = this.options; + + if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle')) + return false; + + //Quit if we're not on a valid handle + this.handle = this._getHandle(event); + if (!this.handle) + return false; + + return true; + + }, + + _mouseStart: function(event) { + + var o = this.options; + + //Create and append the visible helper + this.helper = this._createHelper(event); + + //Cache the helper size + this._cacheHelperProportions(); + + //If ddmanager is used for droppables, set the global draggable + if($.ui.ddmanager) + $.ui.ddmanager.current = this; + + /* + * - Position generation - + * This block generates everything position related - it's the core of draggables. + */ + + //Cache the margins of the original element + this._cacheMargins(); + + //Store the helper's css position + this.cssPosition = this.helper.css("position"); + this.scrollParent = this.helper.scrollParent(); + + //The element's absolute position on the page minus margins + this.offset = this.element.offset(); + this.offset = { + top: this.offset.top - this.margins.top, + left: this.offset.left - this.margins.left + }; + + $.extend(this.offset, { + click: { //Where the click happened, relative to the element + left: event.pageX - this.offset.left, + top: event.pageY - this.offset.top + }, + parent: this._getParentOffset(), + relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper + }); + + //Generate the original position + this.originalPosition = this._generatePosition(event); + this.originalPageX = event.pageX; + this.originalPageY = event.pageY; + + //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied + if(o.cursorAt) + this._adjustOffsetFromHelper(o.cursorAt); + + //Set a containment if given in the options + if(o.containment) + this._setContainment(); + + //Call plugins and callbacks + this._trigger("start", event); + + //Recache the helper size + this._cacheHelperProportions(); + + //Prepare the droppable offsets + if ($.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + + this.helper.addClass("ui-draggable-dragging"); + this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position + return true; + }, + + _mouseDrag: function(event, noPropagation) { + + //Compute the helpers position + this.position = this._generatePosition(event); + this.positionAbs = this._convertPositionTo("absolute"); + + //Call plugins and callbacks and use the resulting position if something is returned + if (!noPropagation) { + var ui = this._uiHash(); + this._trigger('drag', event, ui); + this.position = ui.position; + } + + if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; + if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; + if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); + + return false; + }, + + _mouseStop: function(event) { + + //If we are using droppables, inform the manager about the drop + var dropped = false; + if ($.ui.ddmanager && !this.options.dropBehaviour) + dropped = $.ui.ddmanager.drop(this, event); + + //if a drop comes from outside (a sortable) + if(this.dropped) { + dropped = this.dropped; + this.dropped = false; + } + + if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) { + var self = this; + $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { + self._trigger("stop", event); + self._clear(); + }); + } else { + this._trigger("stop", event); + this._clear(); + } + + return false; + }, + + _getHandle: function(event) { + + var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false; + $(this.options.handle, this.element) + .find("*") + .andSelf() + .each(function() { + if(this == event.target) handle = true; + }); + + return handle; + + }, + + _createHelper: function(event) { + + var o = this.options; + var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element); + + if(!helper.parents('body').length) + helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)); + + if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) + helper.css("position", "absolute"); + + return helper; + + }, + + _adjustOffsetFromHelper: function(obj) { + if(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left; + if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; + if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top; + if(obj.bottom != undefined) this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; + }, + + _getParentOffset: function() { + + //Get the offsetParent and cache its position + this.offsetParent = this.helper.offsetParent(); + var po = this.offsetParent.offset(); + + // This is a special case where we need to modify a offset calculated on start, since the following happened: + // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that + // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag + if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) { + po.left += this.scrollParent.scrollLeft(); + po.top += this.scrollParent.scrollTop(); + } + + if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information + || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix + po = { top: 0, left: 0 }; + + return { + top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), + left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) + }; + + }, + + _getRelativeOffset: function() { + + if(this.cssPosition == "relative") { + var p = this.element.position(); + return { + top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), + left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() + }; + } else { + return { top: 0, left: 0 }; + } + + }, + + _cacheMargins: function() { + this.margins = { + left: (parseInt(this.element.css("marginLeft"),10) || 0), + top: (parseInt(this.element.css("marginTop"),10) || 0) + }; + }, + + _cacheHelperProportions: function() { + this.helperProportions = { + width: this.helper.outerWidth(), + height: this.helper.outerHeight() + }; + }, + + _setContainment: function() { + + var o = this.options; + if(o.containment == 'parent') o.containment = this.helper[0].parentNode; + if(o.containment == 'document' || o.containment == 'window') this.containment = [ + 0 - this.offset.relative.left - this.offset.parent.left, + 0 - this.offset.relative.top - this.offset.parent.top, + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top + ]; + + if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) { + var ce = $(o.containment)[0]; if(!ce) return; + var co = $(o.containment).offset(); + var over = ($(ce).css("overflow") != 'hidden'); + + this.containment = [ + co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, + co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, + co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left, + co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top + ]; + } else if(o.containment.constructor == Array) { + this.containment = o.containment; + } + + }, + + _convertPositionTo: function(d, pos) { + + if(!pos) pos = this.position; + var mod = d == "absolute" ? 1 : -1; + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + return { + top: ( + pos.top // The absolute mouse position + + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) + ), + left: ( + pos.left // The absolute mouse position + + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) + ) + }; + + }, + + _generatePosition: function(event) { + + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + // This is another very weird special case that only happens for relative elements: + // 1. If the css position is relative + // 2. and the scroll parent is the document or similar to the offset parent + // we have to refresh the relative offset during the scroll so there are no jumps + if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) { + this.offset.relative = this._getRelativeOffset(); + } + + var pageX = event.pageX; + var pageY = event.pageY; + + /* + * - Position constraining - + * Constrain the position to a mix of grid, containment. + */ + + if(this.originalPosition) { //If we are not dragging yet, we won't check for options + + if(this.containment) { + if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left; + if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top; + if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left; + if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top; + } + + if(o.grid) { + var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; + pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; + + var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; + pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; + } + + } + + return { + top: ( + pageY // The absolute mouse position + - this.offset.click.top // Click offset (relative to the element) + - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.top // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) + ), + left: ( + pageX // The absolute mouse position + - this.offset.click.left // Click offset (relative to the element) + - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.left // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) + ) + }; + + }, + + _clear: function() { + this.helper.removeClass("ui-draggable-dragging"); + if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove(); + //if($.ui.ddmanager) $.ui.ddmanager.current = null; + this.helper = null; + this.cancelHelperRemoval = false; + }, + + // From now on bulk stuff - mainly helpers + + _trigger: function(type, event, ui) { + ui = ui || this._uiHash(); + $.ui.plugin.call(this, type, [event, ui]); + if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins + return $.widget.prototype._trigger.call(this, type, event, ui); + }, + + plugins: {}, + + _uiHash: function(event) { + return { + helper: this.helper, + position: this.position, + absolutePosition: this.positionAbs, //deprecated + offset: this.positionAbs + }; + } + +})); + +$.extend($.ui.draggable, { + version: "1.7.2", + eventPrefix: "drag", + defaults: { + addClasses: true, + appendTo: "parent", + axis: false, + cancel: ":input,option", + connectToSortable: false, + containment: false, + cursor: "auto", + cursorAt: false, + delay: 0, + distance: 1, + grid: false, + handle: false, + helper: "original", + iframeFix: false, + opacity: false, + refreshPositions: false, + revert: false, + revertDuration: 500, + scope: "default", + scroll: true, + scrollSensitivity: 20, + scrollSpeed: 20, + snap: false, + snapMode: "both", + snapTolerance: 20, + stack: false, + zIndex: false + } +}); + +$.ui.plugin.add("draggable", "connectToSortable", { + start: function(event, ui) { + + var inst = $(this).data("draggable"), o = inst.options, + uiSortable = $.extend({}, ui, { item: inst.element }); + inst.sortables = []; + $(o.connectToSortable).each(function() { + var sortable = $.data(this, 'sortable'); + if (sortable && !sortable.options.disabled) { + inst.sortables.push({ + instance: sortable, + shouldRevert: sortable.options.revert + }); + sortable._refreshItems(); //Do a one-time refresh at start to refresh the containerCache + sortable._trigger("activate", event, uiSortable); + } + }); + + }, + stop: function(event, ui) { + + //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper + var inst = $(this).data("draggable"), + uiSortable = $.extend({}, ui, { item: inst.element }); + + $.each(inst.sortables, function() { + if(this.instance.isOver) { + + this.instance.isOver = 0; + + inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance + this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) + + //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid' + if(this.shouldRevert) this.instance.options.revert = true; + + //Trigger the stop of the sortable + this.instance._mouseStop(event); + + this.instance.options.helper = this.instance.options._helper; + + //If the helper has been the original item, restore properties in the sortable + if(inst.options.helper == 'original') + this.instance.currentItem.css({ top: 'auto', left: 'auto' }); + + } else { + this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance + this.instance._trigger("deactivate", event, uiSortable); + } + + }); + + }, + drag: function(event, ui) { + + var inst = $(this).data("draggable"), self = this; + + var checkPos = function(o) { + var dyClick = this.offset.click.top, dxClick = this.offset.click.left; + var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left; + var itemHeight = o.height, itemWidth = o.width; + var itemTop = o.top, itemLeft = o.left; + + return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth); + }; + + $.each(inst.sortables, function(i) { + + //Copy over some variables to allow calling the sortable's native _intersectsWith + this.instance.positionAbs = inst.positionAbs; + this.instance.helperProportions = inst.helperProportions; + this.instance.offset.click = inst.offset.click; + + if(this.instance._intersectsWith(this.instance.containerCache)) { + + //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once + if(!this.instance.isOver) { + + this.instance.isOver = 1; + //Now we fake the start of dragging for the sortable instance, + //by cloning the list group item, appending it to the sortable and using it as inst.currentItem + //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one) + this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true); + this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it + this.instance.options.helper = function() { return ui.helper[0]; }; + + event.target = this.instance.currentItem[0]; + this.instance._mouseCapture(event, true); + this.instance._mouseStart(event, true, true); + + //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes + this.instance.offset.click.top = inst.offset.click.top; + this.instance.offset.click.left = inst.offset.click.left; + this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; + this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; + + inst._trigger("toSortable", event); + inst.dropped = this.instance.element; //draggable revert needs that + //hack so receive/update callbacks work (mostly) + inst.currentItem = inst.element; + this.instance.fromOutside = inst; + + } + + //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable + if(this.instance.currentItem) this.instance._mouseDrag(event); + + } else { + + //If it doesn't intersect with the sortable, and it intersected before, + //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval + if(this.instance.isOver) { + + this.instance.isOver = 0; + this.instance.cancelHelperRemoval = true; + + //Prevent reverting on this forced stop + this.instance.options.revert = false; + + // The out event needs to be triggered independently + this.instance._trigger('out', event, this.instance._uiHash(this.instance)); + + this.instance._mouseStop(event, true); + this.instance.options.helper = this.instance.options._helper; + + //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size + this.instance.currentItem.remove(); + if(this.instance.placeholder) this.instance.placeholder.remove(); + + inst._trigger("fromSortable", event); + inst.dropped = false; //draggable revert needs that + } + + }; + + }); + + } +}); + +$.ui.plugin.add("draggable", "cursor", { + start: function(event, ui) { + var t = $('body'), o = $(this).data('draggable').options; + if (t.css("cursor")) o._cursor = t.css("cursor"); + t.css("cursor", o.cursor); + }, + stop: function(event, ui) { + var o = $(this).data('draggable').options; + if (o._cursor) $('body').css("cursor", o._cursor); + } +}); + +$.ui.plugin.add("draggable", "iframeFix", { + start: function(event, ui) { + var o = $(this).data('draggable').options; + $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { + $('
') + .css({ + width: this.offsetWidth+"px", height: this.offsetHeight+"px", + position: "absolute", opacity: "0.001", zIndex: 1000 + }) + .css($(this).offset()) + .appendTo("body"); + }); + }, + stop: function(event, ui) { + $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers + } +}); + +$.ui.plugin.add("draggable", "opacity", { + start: function(event, ui) { + var t = $(ui.helper), o = $(this).data('draggable').options; + if(t.css("opacity")) o._opacity = t.css("opacity"); + t.css('opacity', o.opacity); + }, + stop: function(event, ui) { + var o = $(this).data('draggable').options; + if(o._opacity) $(ui.helper).css('opacity', o._opacity); + } +}); + +$.ui.plugin.add("draggable", "scroll", { + start: function(event, ui) { + var i = $(this).data("draggable"); + if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset(); + }, + drag: function(event, ui) { + + var i = $(this).data("draggable"), o = i.options, scrolled = false; + + if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') { + + if(!o.axis || o.axis != 'x') { + if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) + i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; + else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) + i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; + } + + if(!o.axis || o.axis != 'y') { + if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) + i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; + else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) + i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; + } + + } else { + + if(!o.axis || o.axis != 'x') { + if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); + else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); + } + + if(!o.axis || o.axis != 'y') { + if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); + else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); + } + + } + + if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(i, event); + + } +}); + +$.ui.plugin.add("draggable", "snap", { + start: function(event, ui) { + + var i = $(this).data("draggable"), o = i.options; + i.snapElements = []; + + $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() { + var $t = $(this); var $o = $t.offset(); + if(this != i.element[0]) i.snapElements.push({ + item: this, + width: $t.outerWidth(), height: $t.outerHeight(), + top: $o.top, left: $o.left + }); + }); + + }, + drag: function(event, ui) { + + var inst = $(this).data("draggable"), o = inst.options; + var d = o.snapTolerance; + + var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, + y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; + + for (var i = inst.snapElements.length - 1; i >= 0; i--){ + + var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width, + t = inst.snapElements[i].top, b = t + inst.snapElements[i].height; + + //Yes, I know, this is insane ;) + if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) { + if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); + inst.snapElements[i].snapping = false; + continue; + } + + if(o.snapMode != 'inner') { + var ts = Math.abs(t - y2) <= d; + var bs = Math.abs(b - y1) <= d; + var ls = Math.abs(l - x2) <= d; + var rs = Math.abs(r - x1) <= d; + if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; + if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; + if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; + if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; + } + + var first = (ts || bs || ls || rs); + + if(o.snapMode != 'outer') { + var ts = Math.abs(t - y1) <= d; + var bs = Math.abs(b - y2) <= d; + var ls = Math.abs(l - x1) <= d; + var rs = Math.abs(r - x2) <= d; + if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; + if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; + if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; + if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; + } + + if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) + (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); + inst.snapElements[i].snapping = (ts || bs || ls || rs || first); + + }; + + } +}); + +$.ui.plugin.add("draggable", "stack", { + start: function(event, ui) { + + var o = $(this).data("draggable").options; + + var group = $.makeArray($(o.stack.group)).sort(function(a,b) { + return (parseInt($(a).css("zIndex"),10) || o.stack.min) - (parseInt($(b).css("zIndex"),10) || o.stack.min); + }); + + $(group).each(function(i) { + this.style.zIndex = o.stack.min + i; + }); + + this[0].style.zIndex = o.stack.min + group.length; + + } +}); + +$.ui.plugin.add("draggable", "zIndex", { + start: function(event, ui) { + var t = $(ui.helper), o = $(this).data("draggable").options; + if(t.css("zIndex")) o._zIndex = t.css("zIndex"); + t.css('zIndex', o.zIndex); + }, + stop: function(event, ui) { + var o = $(this).data("draggable").options; + if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex); + } +}); + +})(jQuery); +/* + * jQuery UI Droppable 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Droppables + * + * Depends: + * ui.core.js + * ui.draggable.js + */ +(function($) { + +$.widget("ui.droppable", { + + _init: function() { + + var o = this.options, accept = o.accept; + this.isover = 0; this.isout = 1; + + this.options.accept = this.options.accept && $.isFunction(this.options.accept) ? this.options.accept : function(d) { + return d.is(accept); + }; + + //Store the droppable's proportions + this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight }; + + // Add the reference and positions to the manager + $.ui.ddmanager.droppables[this.options.scope] = $.ui.ddmanager.droppables[this.options.scope] || []; + $.ui.ddmanager.droppables[this.options.scope].push(this); + + (this.options.addClasses && this.element.addClass("ui-droppable")); + + }, + + destroy: function() { + var drop = $.ui.ddmanager.droppables[this.options.scope]; + for ( var i = 0; i < drop.length; i++ ) + if ( drop[i] == this ) + drop.splice(i, 1); + + this.element + .removeClass("ui-droppable ui-droppable-disabled") + .removeData("droppable") + .unbind(".droppable"); + }, + + _setData: function(key, value) { + + if(key == 'accept') { + this.options.accept = value && $.isFunction(value) ? value : function(d) { + return d.is(value); + }; + } else { + $.widget.prototype._setData.apply(this, arguments); + } + + }, + + _activate: function(event) { + var draggable = $.ui.ddmanager.current; + if(this.options.activeClass) this.element.addClass(this.options.activeClass); + (draggable && this._trigger('activate', event, this.ui(draggable))); + }, + + _deactivate: function(event) { + var draggable = $.ui.ddmanager.current; + if(this.options.activeClass) this.element.removeClass(this.options.activeClass); + (draggable && this._trigger('deactivate', event, this.ui(draggable))); + }, + + _over: function(event) { + + var draggable = $.ui.ddmanager.current; + if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element + + if (this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + if(this.options.hoverClass) this.element.addClass(this.options.hoverClass); + this._trigger('over', event, this.ui(draggable)); + } + + }, + + _out: function(event) { + + var draggable = $.ui.ddmanager.current; + if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element + + if (this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); + this._trigger('out', event, this.ui(draggable)); + } + + }, + + _drop: function(event,custom) { + + var draggable = custom || $.ui.ddmanager.current; + if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element + + var childrenIntersection = false; + this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() { + var inst = $.data(this, 'droppable'); + if(inst.options.greedy && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)) { + childrenIntersection = true; return false; + } + }); + if(childrenIntersection) return false; + + if(this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + if(this.options.activeClass) this.element.removeClass(this.options.activeClass); + if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); + this._trigger('drop', event, this.ui(draggable)); + return this.element; + } + + return false; + + }, + + ui: function(c) { + return { + draggable: (c.currentItem || c.element), + helper: c.helper, + position: c.position, + absolutePosition: c.positionAbs, //deprecated + offset: c.positionAbs + }; + } + +}); + +$.extend($.ui.droppable, { + version: "1.7.2", + eventPrefix: 'drop', + defaults: { + accept: '*', + activeClass: false, + addClasses: true, + greedy: false, + hoverClass: false, + scope: 'default', + tolerance: 'intersect' + } +}); + +$.ui.intersect = function(draggable, droppable, toleranceMode) { + + if (!droppable.offset) return false; + + var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, + y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height; + var l = droppable.offset.left, r = l + droppable.proportions.width, + t = droppable.offset.top, b = t + droppable.proportions.height; + + switch (toleranceMode) { + case 'fit': + return (l < x1 && x2 < r + && t < y1 && y2 < b); + break; + case 'intersect': + return (l < x1 + (draggable.helperProportions.width / 2) // Right Half + && x2 - (draggable.helperProportions.width / 2) < r // Left Half + && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half + && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half + break; + case 'pointer': + var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left), + draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top), + isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width); + return isOver; + break; + case 'touch': + return ( + (y1 >= t && y1 <= b) || // Top edge touching + (y2 >= t && y2 <= b) || // Bottom edge touching + (y1 < t && y2 > b) // Surrounded vertically + ) && ( + (x1 >= l && x1 <= r) || // Left edge touching + (x2 >= l && x2 <= r) || // Right edge touching + (x1 < l && x2 > r) // Surrounded horizontally + ); + break; + default: + return false; + break; + } + +}; + +/* + This manager tracks offsets of draggables and droppables +*/ +$.ui.ddmanager = { + current: null, + droppables: { 'default': [] }, + prepareOffsets: function(t, event) { + + var m = $.ui.ddmanager.droppables[t.options.scope]; + var type = event ? event.type : null; // workaround for #2317 + var list = (t.currentItem || t.element).find(":data(droppable)").andSelf(); + + droppablesLoop: for (var i = 0; i < m.length; i++) { + + if(m[i].options.disabled || (t && !m[i].options.accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted + for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item + m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue + + m[i].offset = m[i].element.offset(); + m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight }; + + if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables + + } + + }, + drop: function(draggable, event) { + + var dropped = false; + $.each($.ui.ddmanager.droppables[draggable.options.scope], function() { + + if(!this.options) return; + if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) + dropped = this._drop.call(this, event); + + if (!this.options.disabled && this.visible && this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + this.isout = 1; this.isover = 0; + this._deactivate.call(this, event); + } + + }); + return dropped; + + }, + drag: function(draggable, event) { + + //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. + if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event); + + //Run through all droppables and check their positions based on specific tolerance options + + $.each($.ui.ddmanager.droppables[draggable.options.scope], function() { + + if(this.options.disabled || this.greedyChild || !this.visible) return; + var intersects = $.ui.intersect(draggable, this, this.options.tolerance); + + var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null); + if(!c) return; + + var parentInstance; + if (this.options.greedy) { + var parent = this.element.parents(':data(droppable):eq(0)'); + if (parent.length) { + parentInstance = $.data(parent[0], 'droppable'); + parentInstance.greedyChild = (c == 'isover' ? 1 : 0); + } + } + + // we just moved into a greedy child + if (parentInstance && c == 'isover') { + parentInstance['isover'] = 0; + parentInstance['isout'] = 1; + parentInstance._out.call(parentInstance, event); + } + + this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0; + this[c == "isover" ? "_over" : "_out"].call(this, event); + + // we just moved out of a greedy child + if (parentInstance && c == 'isout') { + parentInstance['isout'] = 0; + parentInstance['isover'] = 1; + parentInstance._over.call(parentInstance, event); + } + }); + + } +}; + +})(jQuery); +/* + * jQuery UI Resizable 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Resizables + * + * Depends: + * ui.core.js + */ +(function($) { + +$.widget("ui.resizable", $.extend({}, $.ui.mouse, { + + _init: function() { + + var self = this, o = this.options; + this.element.addClass("ui-resizable"); + + $.extend(this, { + _aspectRatio: !!(o.aspectRatio), + aspectRatio: o.aspectRatio, + originalElement: this.element, + _proportionallyResizeElements: [], + _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null + }); + + //Wrap the element if it cannot hold child nodes + if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { + + //Opera fix for relative positioning + if (/relative/.test(this.element.css('position')) && $.browser.opera) + this.element.css({ position: 'relative', top: 'auto', left: 'auto' }); + + //Create a wrapper element and set the wrapper to the new current internal element + this.element.wrap( + $('
').css({ + position: this.element.css('position'), + width: this.element.outerWidth(), + height: this.element.outerHeight(), + top: this.element.css('top'), + left: this.element.css('left') + }) + ); + + //Overwrite the original this.element + this.element = this.element.parent().data( + "resizable", this.element.data('resizable') + ); + + this.elementIsWrapper = true; + + //Move margins to the wrapper + this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); + this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); + + //Prevent Safari textarea resize + this.originalResizeStyle = this.originalElement.css('resize'); + this.originalElement.css('resize', 'none'); + + //Push the actual element to our proportionallyResize internal array + this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' })); + + // avoid IE jump (hard set the margin) + this.originalElement.css({ margin: this.originalElement.css('margin') }); + + // fix handlers offset + this._proportionallyResize(); + + } + + this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' }); + if(this.handles.constructor == String) { + + if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw'; + var n = this.handles.split(","); this.handles = {}; + + for(var i = 0; i < n.length; i++) { + + var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle; + var axis = $('
'); + + // increase zIndex of sw, se, ne, nw axis + //TODO : this modifies original option + if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex }); + + //TODO : What's going on here? + if ('se' == handle) { + axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se'); + }; + + //Insert into internal handles object and append to element + this.handles[handle] = '.ui-resizable-'+handle; + this.element.append(axis); + } + + } + + this._renderAxis = function(target) { + + target = target || this.element; + + for(var i in this.handles) { + + if(this.handles[i].constructor == String) + this.handles[i] = $(this.handles[i], this.element).show(); + + //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) + if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { + + var axis = $(this.handles[i], this.element), padWrapper = 0; + + //Checking the correct pad and border + padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); + + //The padding type i have to apply... + var padPos = [ 'padding', + /ne|nw|n/.test(i) ? 'Top' : + /se|sw|s/.test(i) ? 'Bottom' : + /^e$/.test(i) ? 'Right' : 'Left' ].join(""); + + target.css(padPos, padWrapper); + + this._proportionallyResize(); + + } + + //TODO: What's that good for? There's not anything to be executed left + if(!$(this.handles[i]).length) + continue; + + } + }; + + //TODO: make renderAxis a prototype function + this._renderAxis(this.element); + + this._handles = $('.ui-resizable-handle', this.element) + .disableSelection(); + + //Matching axis name + this._handles.mouseover(function() { + if (!self.resizing) { + if (this.className) + var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); + //Axis, default = se + self.axis = axis && axis[1] ? axis[1] : 'se'; + } + }); + + //If we want to auto hide the elements + if (o.autoHide) { + this._handles.hide(); + $(this.element) + .addClass("ui-resizable-autohide") + .hover(function() { + $(this).removeClass("ui-resizable-autohide"); + self._handles.show(); + }, + function(){ + if (!self.resizing) { + $(this).addClass("ui-resizable-autohide"); + self._handles.hide(); + } + }); + } + + //Initialize the mouse interaction + this._mouseInit(); + + }, + + destroy: function() { + + this._mouseDestroy(); + + var _destroy = function(exp) { + $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") + .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove(); + }; + + //TODO: Unwrap at same DOM position + if (this.elementIsWrapper) { + _destroy(this.element); + var wrapper = this.element; + wrapper.parent().append( + this.originalElement.css({ + position: wrapper.css('position'), + width: wrapper.outerWidth(), + height: wrapper.outerHeight(), + top: wrapper.css('top'), + left: wrapper.css('left') + }) + ).end().remove(); + } + + this.originalElement.css('resize', this.originalResizeStyle); + _destroy(this.originalElement); + + }, + + _mouseCapture: function(event) { + + var handle = false; + for(var i in this.handles) { + if($(this.handles[i])[0] == event.target) handle = true; + } + + return this.options.disabled || !!handle; + + }, + + _mouseStart: function(event) { + + var o = this.options, iniPos = this.element.position(), el = this.element; + + this.resizing = true; + this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() }; + + // bugfix for http://dev.jquery.com/ticket/1749 + if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) { + el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left }); + } + + //Opera fixing relative position + if ($.browser.opera && (/relative/).test(el.css('position'))) + el.css({ position: 'relative', top: 'auto', left: 'auto' }); + + this._renderProxy(); + + var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top')); + + if (o.containment) { + curleft += $(o.containment).scrollLeft() || 0; + curtop += $(o.containment).scrollTop() || 0; + } + + //Store needed variables + this.offset = this.helper.offset(); + this.position = { left: curleft, top: curtop }; + this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; + this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; + this.originalPosition = { left: curleft, top: curtop }; + this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; + this.originalMousePosition = { left: event.pageX, top: event.pageY }; + + //Aspect Ratio + this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); + + var cursor = $('.ui-resizable-' + this.axis).css('cursor'); + $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor); + + el.addClass("ui-resizable-resizing"); + this._propagate("start", event); + return true; + }, + + _mouseDrag: function(event) { + + //Increase performance, avoid regex + var el = this.helper, o = this.options, props = {}, + self = this, smp = this.originalMousePosition, a = this.axis; + + var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0; + var trigger = this._change[a]; + if (!trigger) return false; + + // Calculate the attrs that will be change + var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff; + + if (this._aspectRatio || event.shiftKey) + data = this._updateRatio(data, event); + + data = this._respectSize(data, event); + + // plugins callbacks need to be called first + this._propagate("resize", event); + + el.css({ + top: this.position.top + "px", left: this.position.left + "px", + width: this.size.width + "px", height: this.size.height + "px" + }); + + if (!this._helper && this._proportionallyResizeElements.length) + this._proportionallyResize(); + + this._updateCache(data); + + // calling the user callback at the end + this._trigger('resize', event, this.ui()); + + return false; + }, + + _mouseStop: function(event) { + + this.resizing = false; + var o = this.options, self = this; + + if(this._helper) { + var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), + soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height, + soffsetw = ista ? 0 : self.sizeDiff.width; + + var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) }, + left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null, + top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null; + + if (!o.animate) + this.element.css($.extend(s, { top: top, left: left })); + + self.helper.height(self.size.height); + self.helper.width(self.size.width); + + if (this._helper && !o.animate) this._proportionallyResize(); + } + + $('body').css('cursor', 'auto'); + + this.element.removeClass("ui-resizable-resizing"); + + this._propagate("stop", event); + + if (this._helper) this.helper.remove(); + return false; + + }, + + _updateCache: function(data) { + var o = this.options; + this.offset = this.helper.offset(); + if (isNumber(data.left)) this.position.left = data.left; + if (isNumber(data.top)) this.position.top = data.top; + if (isNumber(data.height)) this.size.height = data.height; + if (isNumber(data.width)) this.size.width = data.width; + }, + + _updateRatio: function(data, event) { + + var o = this.options, cpos = this.position, csize = this.size, a = this.axis; + + if (data.height) data.width = (csize.height * this.aspectRatio); + else if (data.width) data.height = (csize.width / this.aspectRatio); + + if (a == 'sw') { + data.left = cpos.left + (csize.width - data.width); + data.top = null; + } + if (a == 'nw') { + data.top = cpos.top + (csize.height - data.height); + data.left = cpos.left + (csize.width - data.width); + } + + return data; + }, + + _respectSize: function(data, event) { + + var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis, + ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), + isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height); + + if (isminw) data.width = o.minWidth; + if (isminh) data.height = o.minHeight; + if (ismaxw) data.width = o.maxWidth; + if (ismaxh) data.height = o.maxHeight; + + var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height; + var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); + + if (isminw && cw) data.left = dw - o.minWidth; + if (ismaxw && cw) data.left = dw - o.maxWidth; + if (isminh && ch) data.top = dh - o.minHeight; + if (ismaxh && ch) data.top = dh - o.maxHeight; + + // fixing jump error on top/left - bug #2330 + var isNotwh = !data.width && !data.height; + if (isNotwh && !data.left && data.top) data.top = null; + else if (isNotwh && !data.top && data.left) data.left = null; + + return data; + }, + + _proportionallyResize: function() { + + var o = this.options; + if (!this._proportionallyResizeElements.length) return; + var element = this.helper || this.element; + + for (var i=0; i < this._proportionallyResizeElements.length; i++) { + + var prel = this._proportionallyResizeElements[i]; + + if (!this.borderDif) { + var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')], + p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')]; + + this.borderDif = $.map(b, function(v, i) { + var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0; + return border + padding; + }); + } + + if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length))) + continue; + + prel.css({ + height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, + width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 + }); + + }; + + }, + + _renderProxy: function() { + + var el = this.element, o = this.options; + this.elementOffset = el.offset(); + + if(this._helper) { + + this.helper = this.helper || $('
'); + + // fix ie6 offset TODO: This seems broken + var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0), + pxyoffset = ( ie6 ? 2 : -1 ); + + this.helper.addClass(this._helper).css({ + width: this.element.outerWidth() + pxyoffset, + height: this.element.outerHeight() + pxyoffset, + position: 'absolute', + left: this.elementOffset.left - ie6offset +'px', + top: this.elementOffset.top - ie6offset +'px', + zIndex: ++o.zIndex //TODO: Don't modify option + }); + + this.helper + .appendTo("body") + .disableSelection(); + + } else { + this.helper = this.element; + } + + }, + + _change: { + e: function(event, dx, dy) { + return { width: this.originalSize.width + dx }; + }, + w: function(event, dx, dy) { + var o = this.options, cs = this.originalSize, sp = this.originalPosition; + return { left: sp.left + dx, width: cs.width - dx }; + }, + n: function(event, dx, dy) { + var o = this.options, cs = this.originalSize, sp = this.originalPosition; + return { top: sp.top + dy, height: cs.height - dy }; + }, + s: function(event, dx, dy) { + return { height: this.originalSize.height + dy }; + }, + se: function(event, dx, dy) { + return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); + }, + sw: function(event, dx, dy) { + return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); + }, + ne: function(event, dx, dy) { + return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); + }, + nw: function(event, dx, dy) { + return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); + } + }, + + _propagate: function(n, event) { + $.ui.plugin.call(this, n, [event, this.ui()]); + (n != "resize" && this._trigger(n, event, this.ui())); + }, + + plugins: {}, + + ui: function() { + return { + originalElement: this.originalElement, + element: this.element, + helper: this.helper, + position: this.position, + size: this.size, + originalSize: this.originalSize, + originalPosition: this.originalPosition + }; + } + +})); + +$.extend($.ui.resizable, { + version: "1.7.2", + eventPrefix: "resize", + defaults: { + alsoResize: false, + animate: false, + animateDuration: "slow", + animateEasing: "swing", + aspectRatio: false, + autoHide: false, + cancel: ":input,option", + containment: false, + delay: 0, + distance: 1, + ghost: false, + grid: false, + handles: "e,s,se", + helper: false, + maxHeight: null, + maxWidth: null, + minHeight: 10, + minWidth: 10, + zIndex: 1000 + } +}); + +/* + * Resizable Extensions + */ + +$.ui.plugin.add("resizable", "alsoResize", { + + start: function(event, ui) { + + var self = $(this).data("resizable"), o = self.options; + + _store = function(exp) { + $(exp).each(function() { + $(this).data("resizable-alsoresize", { + width: parseInt($(this).width(), 10), height: parseInt($(this).height(), 10), + left: parseInt($(this).css('left'), 10), top: parseInt($(this).css('top'), 10) + }); + }); + }; + + if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) { + if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); } + else { $.each(o.alsoResize, function(exp, c) { _store(exp); }); } + }else{ + _store(o.alsoResize); + } + }, + + resize: function(event, ui){ + var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition; + + var delta = { + height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0, + top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0 + }, + + _alsoResize = function(exp, c) { + $(exp).each(function() { + var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, css = c && c.length ? c : ['width', 'height', 'top', 'left']; + + $.each(css || ['width', 'height', 'top', 'left'], function(i, prop) { + var sum = (start[prop]||0) + (delta[prop]||0); + if (sum && sum >= 0) + style[prop] = sum || null; + }); + + //Opera fixing relative position + if (/relative/.test(el.css('position')) && $.browser.opera) { + self._revertToRelativePosition = true; + el.css({ position: 'absolute', top: 'auto', left: 'auto' }); + } + + el.css(style); + }); + }; + + if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) { + $.each(o.alsoResize, function(exp, c) { _alsoResize(exp, c); }); + }else{ + _alsoResize(o.alsoResize); + } + }, + + stop: function(event, ui){ + var self = $(this).data("resizable"); + + //Opera fixing relative position + if (self._revertToRelativePosition && $.browser.opera) { + self._revertToRelativePosition = false; + el.css({ position: 'relative' }); + } + + $(this).removeData("resizable-alsoresize-start"); + } +}); + +$.ui.plugin.add("resizable", "animate", { + + stop: function(event, ui) { + var self = $(this).data("resizable"), o = self.options; + + var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), + soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height, + soffsetw = ista ? 0 : self.sizeDiff.width; + + var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) }, + left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null, + top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null; + + self.element.animate( + $.extend(style, top && left ? { top: top, left: left } : {}), { + duration: o.animateDuration, + easing: o.animateEasing, + step: function() { + + var data = { + width: parseInt(self.element.css('width'), 10), + height: parseInt(self.element.css('height'), 10), + top: parseInt(self.element.css('top'), 10), + left: parseInt(self.element.css('left'), 10) + }; + + if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height }); + + // propagating resize, and updating values for each animation step + self._updateCache(data); + self._propagate("resize", event); + + } + } + ); + } + +}); + +$.ui.plugin.add("resizable", "containment", { + + start: function(event, ui) { + var self = $(this).data("resizable"), o = self.options, el = self.element; + var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; + if (!ce) return; + + self.containerElement = $(ce); + + if (/document/.test(oc) || oc == document) { + self.containerOffset = { left: 0, top: 0 }; + self.containerPosition = { left: 0, top: 0 }; + + self.parentData = { + element: $(document), left: 0, top: 0, + width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight + }; + } + + // i'm a node, so compute top, left, right, bottom + else { + var element = $(ce), p = []; + $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); }); + + self.containerOffset = element.offset(); + self.containerPosition = element.position(); + self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; + + var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width, + width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); + + self.parentData = { + element: ce, left: co.left, top: co.top, width: width, height: height + }; + } + }, + + resize: function(event, ui) { + var self = $(this).data("resizable"), o = self.options, + ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position, + pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement; + + if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co; + + if (cp.left < (self._helper ? co.left : 0)) { + self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left)); + if (pRatio) self.size.height = self.size.width / o.aspectRatio; + self.position.left = o.helper ? co.left : 0; + } + + if (cp.top < (self._helper ? co.top : 0)) { + self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top); + if (pRatio) self.size.width = self.size.height * o.aspectRatio; + self.position.top = self._helper ? co.top : 0; + } + + self.offset.left = self.parentData.left+self.position.left; + self.offset.top = self.parentData.top+self.position.top; + + var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ), + hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height ); + + var isParent = self.containerElement.get(0) == self.element.parent().get(0), + isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position')); + + if(isParent && isOffsetRelative) woset -= self.parentData.left; + + if (woset + self.size.width >= self.parentData.width) { + self.size.width = self.parentData.width - woset; + if (pRatio) self.size.height = self.size.width / self.aspectRatio; + } + + if (hoset + self.size.height >= self.parentData.height) { + self.size.height = self.parentData.height - hoset; + if (pRatio) self.size.width = self.size.height * self.aspectRatio; + } + }, + + stop: function(event, ui){ + var self = $(this).data("resizable"), o = self.options, cp = self.position, + co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement; + + var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height; + + if (self._helper && !o.animate && (/relative/).test(ce.css('position'))) + $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); + + if (self._helper && !o.animate && (/static/).test(ce.css('position'))) + $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); + + } +}); + +$.ui.plugin.add("resizable", "ghost", { + + start: function(event, ui) { + + var self = $(this).data("resizable"), o = self.options, cs = self.size; + + self.ghost = self.originalElement.clone(); + self.ghost + .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) + .addClass('ui-resizable-ghost') + .addClass(typeof o.ghost == 'string' ? o.ghost : ''); + + self.ghost.appendTo(self.helper); + + }, + + resize: function(event, ui){ + var self = $(this).data("resizable"), o = self.options; + if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width }); + }, + + stop: function(event, ui){ + var self = $(this).data("resizable"), o = self.options; + if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0)); + } + +}); + +$.ui.plugin.add("resizable", "grid", { + + resize: function(event, ui) { + var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey; + o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid; + var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1); + + if (/^(se|s|e)$/.test(a)) { + self.size.width = os.width + ox; + self.size.height = os.height + oy; + } + else if (/^(ne)$/.test(a)) { + self.size.width = os.width + ox; + self.size.height = os.height + oy; + self.position.top = op.top - oy; + } + else if (/^(sw)$/.test(a)) { + self.size.width = os.width + ox; + self.size.height = os.height + oy; + self.position.left = op.left - ox; + } + else { + self.size.width = os.width + ox; + self.size.height = os.height + oy; + self.position.top = op.top - oy; + self.position.left = op.left - ox; + } + } + +}); + +var num = function(v) { + return parseInt(v, 10) || 0; +}; + +var isNumber = function(value) { + return !isNaN(parseInt(value, 10)); +}; + +})(jQuery); +/* + * jQuery UI Selectable 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Selectables + * + * Depends: + * ui.core.js + */ +(function($) { + +$.widget("ui.selectable", $.extend({}, $.ui.mouse, { + + _init: function() { + var self = this; + + this.element.addClass("ui-selectable"); + + this.dragged = false; + + // cache selectee children based on filter + var selectees; + this.refresh = function() { + selectees = $(self.options.filter, self.element[0]); + selectees.each(function() { + var $this = $(this); + var pos = $this.offset(); + $.data(this, "selectable-item", { + element: this, + $element: $this, + left: pos.left, + top: pos.top, + right: pos.left + $this.outerWidth(), + bottom: pos.top + $this.outerHeight(), + startselected: false, + selected: $this.hasClass('ui-selected'), + selecting: $this.hasClass('ui-selecting'), + unselecting: $this.hasClass('ui-unselecting') + }); + }); + }; + this.refresh(); + + this.selectees = selectees.addClass("ui-selectee"); + + this._mouseInit(); + + this.helper = $(document.createElement('div')) + .css({border:'1px dotted black'}) + .addClass("ui-selectable-helper"); + }, + + destroy: function() { + this.element + .removeClass("ui-selectable ui-selectable-disabled") + .removeData("selectable") + .unbind(".selectable"); + this._mouseDestroy(); + }, + + _mouseStart: function(event) { + var self = this; + + this.opos = [event.pageX, event.pageY]; + + if (this.options.disabled) + return; + + var options = this.options; + + this.selectees = $(options.filter, this.element[0]); + + this._trigger("start", event); + + $(options.appendTo).append(this.helper); + // position helper (lasso) + this.helper.css({ + "z-index": 100, + "position": "absolute", + "left": event.clientX, + "top": event.clientY, + "width": 0, + "height": 0 + }); + + if (options.autoRefresh) { + this.refresh(); + } + + this.selectees.filter('.ui-selected').each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.startselected = true; + if (!event.metaKey) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + // selectable UNSELECTING callback + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + }); + + $(event.target).parents().andSelf().each(function() { + var selectee = $.data(this, "selectable-item"); + if (selectee) { + selectee.$element.removeClass("ui-unselecting").addClass('ui-selecting'); + selectee.unselecting = false; + selectee.selecting = true; + selectee.selected = true; + // selectable SELECTING callback + self._trigger("selecting", event, { + selecting: selectee.element + }); + return false; + } + }); + + }, + + _mouseDrag: function(event) { + var self = this; + this.dragged = true; + + if (this.options.disabled) + return; + + var options = this.options; + + var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY; + if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; } + if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; } + this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); + + this.selectees.each(function() { + var selectee = $.data(this, "selectable-item"); + //prevent helper from being selected if appendTo: selectable + if (!selectee || selectee.element == self.element[0]) + return; + var hit = false; + if (options.tolerance == 'touch') { + hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); + } else if (options.tolerance == 'fit') { + hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); + } + + if (hit) { + // SELECT + if (selectee.selected) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + } + if (selectee.unselecting) { + selectee.$element.removeClass('ui-unselecting'); + selectee.unselecting = false; + } + if (!selectee.selecting) { + selectee.$element.addClass('ui-selecting'); + selectee.selecting = true; + // selectable SELECTING callback + self._trigger("selecting", event, { + selecting: selectee.element + }); + } + } else { + // UNSELECT + if (selectee.selecting) { + if (event.metaKey && selectee.startselected) { + selectee.$element.removeClass('ui-selecting'); + selectee.selecting = false; + selectee.$element.addClass('ui-selected'); + selectee.selected = true; + } else { + selectee.$element.removeClass('ui-selecting'); + selectee.selecting = false; + if (selectee.startselected) { + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + } + // selectable UNSELECTING callback + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + } + if (selectee.selected) { + if (!event.metaKey && !selectee.startselected) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + // selectable UNSELECTING callback + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + } + } + }); + + return false; + }, + + _mouseStop: function(event) { + var self = this; + + this.dragged = false; + + var options = this.options; + + $('.ui-unselecting', this.element[0]).each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.$element.removeClass('ui-unselecting'); + selectee.unselecting = false; + selectee.startselected = false; + self._trigger("unselected", event, { + unselected: selectee.element + }); + }); + $('.ui-selecting', this.element[0]).each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.$element.removeClass('ui-selecting').addClass('ui-selected'); + selectee.selecting = false; + selectee.selected = true; + selectee.startselected = true; + self._trigger("selected", event, { + selected: selectee.element + }); + }); + this._trigger("stop", event); + + this.helper.remove(); + + return false; + } + +})); + +$.extend($.ui.selectable, { + version: "1.7.2", + defaults: { + appendTo: 'body', + autoRefresh: true, + cancel: ":input,option", + delay: 0, + distance: 0, + filter: '*', + tolerance: 'touch' + } +}); + +})(jQuery); +/* + * jQuery UI Sortable 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Sortables + * + * Depends: + * ui.core.js + */ +(function($) { + +$.widget("ui.sortable", $.extend({}, $.ui.mouse, { + _init: function() { + + var o = this.options; + this.containerCache = {}; + this.element.addClass("ui-sortable"); + + //Get the items + this.refresh(); + + //Let's determine if the items are floating + this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) : false; + + //Let's determine the parent's offset + this.offset = this.element.offset(); + + //Initialize mouse events for interaction + this._mouseInit(); + + }, + + destroy: function() { + this.element + .removeClass("ui-sortable ui-sortable-disabled") + .removeData("sortable") + .unbind(".sortable"); + this._mouseDestroy(); + + for ( var i = this.items.length - 1; i >= 0; i-- ) + this.items[i].item.removeData("sortable-item"); + }, + + _mouseCapture: function(event, overrideHandle) { + + if (this.reverting) { + return false; + } + + if(this.options.disabled || this.options.type == 'static') return false; + + //We have to refresh the items data once first + this._refreshItems(event); + + //Find out if the clicked node (or one of its parents) is a actual item in this.items + var currentItem = null, self = this, nodes = $(event.target).parents().each(function() { + if($.data(this, 'sortable-item') == self) { + currentItem = $(this); + return false; + } + }); + if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target); + + if(!currentItem) return false; + if(this.options.handle && !overrideHandle) { + var validHandle = false; + + $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; }); + if(!validHandle) return false; + } + + this.currentItem = currentItem; + this._removeCurrentsFromItems(); + return true; + + }, + + _mouseStart: function(event, overrideHandle, noActivation) { + + var o = this.options, self = this; + this.currentContainer = this; + + //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture + this.refreshPositions(); + + //Create and append the visible helper + this.helper = this._createHelper(event); + + //Cache the helper size + this._cacheHelperProportions(); + + /* + * - Position generation - + * This block generates everything position related - it's the core of draggables. + */ + + //Cache the margins of the original element + this._cacheMargins(); + + //Get the next scrolling parent + this.scrollParent = this.helper.scrollParent(); + + //The element's absolute position on the page minus margins + this.offset = this.currentItem.offset(); + this.offset = { + top: this.offset.top - this.margins.top, + left: this.offset.left - this.margins.left + }; + + // Only after we got the offset, we can change the helper's position to absolute + // TODO: Still need to figure out a way to make relative sorting possible + this.helper.css("position", "absolute"); + this.cssPosition = this.helper.css("position"); + + $.extend(this.offset, { + click: { //Where the click happened, relative to the element + left: event.pageX - this.offset.left, + top: event.pageY - this.offset.top + }, + parent: this._getParentOffset(), + relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper + }); + + //Generate the original position + this.originalPosition = this._generatePosition(event); + this.originalPageX = event.pageX; + this.originalPageY = event.pageY; + + //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied + if(o.cursorAt) + this._adjustOffsetFromHelper(o.cursorAt); + + //Cache the former DOM position + this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; + + //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way + if(this.helper[0] != this.currentItem[0]) { + this.currentItem.hide(); + } + + //Create the placeholder + this._createPlaceholder(); + + //Set a containment if given in the options + if(o.containment) + this._setContainment(); + + if(o.cursor) { // cursor option + if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor"); + $('body').css("cursor", o.cursor); + } + + if(o.opacity) { // opacity option + if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity"); + this.helper.css("opacity", o.opacity); + } + + if(o.zIndex) { // zIndex option + if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex"); + this.helper.css("zIndex", o.zIndex); + } + + //Prepare scrolling + if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') + this.overflowOffset = this.scrollParent.offset(); + + //Call callbacks + this._trigger("start", event, this._uiHash()); + + //Recache the helper size + if(!this._preserveHelperProportions) + this._cacheHelperProportions(); + + + //Post 'activate' events to possible containers + if(!noActivation) { + for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); } + } + + //Prepare possible droppables + if($.ui.ddmanager) + $.ui.ddmanager.current = this; + + if ($.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + + this.dragging = true; + + this.helper.addClass("ui-sortable-helper"); + this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position + return true; + + }, + + _mouseDrag: function(event) { + + //Compute the helpers position + this.position = this._generatePosition(event); + this.positionAbs = this._convertPositionTo("absolute"); + + if (!this.lastPositionAbs) { + this.lastPositionAbs = this.positionAbs; + } + + //Do scrolling + if(this.options.scroll) { + var o = this.options, scrolled = false; + if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') { + + if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) + this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; + else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) + this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; + + if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) + this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; + else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) + this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; + + } else { + + if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); + else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); + + if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); + else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); + + } + + if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + } + + //Regenerate the absolute position used for position checks + this.positionAbs = this._convertPositionTo("absolute"); + + //Set the helper position + if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; + if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; + + //Rearrange + for (var i = this.items.length - 1; i >= 0; i--) { + + //Cache variables and intersection, continue if no intersection + var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item); + if (!intersection) continue; + + if(itemElement != this.currentItem[0] //cannot intersect with itself + && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before + && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked + && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true) + ) { + + this.direction = intersection == 1 ? "down" : "up"; + + if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) { + this._rearrange(event, item); + } else { + break; + } + + this._trigger("change", event, this._uiHash()); + break; + } + } + + //Post events to containers + this._contactContainers(event); + + //Interconnect with droppables + if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); + + //Call callbacks + this._trigger('sort', event, this._uiHash()); + + this.lastPositionAbs = this.positionAbs; + return false; + + }, + + _mouseStop: function(event, noPropagation) { + + if(!event) return; + + //If we are using droppables, inform the manager about the drop + if ($.ui.ddmanager && !this.options.dropBehaviour) + $.ui.ddmanager.drop(this, event); + + if(this.options.revert) { + var self = this; + var cur = self.placeholder.offset(); + + self.reverting = true; + + $(this.helper).animate({ + left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft), + top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop) + }, parseInt(this.options.revert, 10) || 500, function() { + self._clear(event); + }); + } else { + this._clear(event, noPropagation); + } + + return false; + + }, + + cancel: function() { + + var self = this; + + if(this.dragging) { + + this._mouseUp(); + + if(this.options.helper == "original") + this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); + else + this.currentItem.show(); + + //Post deactivating events to containers + for (var i = this.containers.length - 1; i >= 0; i--){ + this.containers[i]._trigger("deactivate", null, self._uiHash(this)); + if(this.containers[i].containerCache.over) { + this.containers[i]._trigger("out", null, self._uiHash(this)); + this.containers[i].containerCache.over = 0; + } + } + + } + + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! + if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]); + if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove(); + + $.extend(this, { + helper: null, + dragging: false, + reverting: false, + _noFinalSort: null + }); + + if(this.domPosition.prev) { + $(this.domPosition.prev).after(this.currentItem); + } else { + $(this.domPosition.parent).prepend(this.currentItem); + } + + return true; + + }, + + serialize: function(o) { + + var items = this._getItemsAsjQuery(o && o.connected); + var str = []; o = o || {}; + + $(items).each(function() { + var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/)); + if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2])); + }); + + return str.join('&'); + + }, + + toArray: function(o) { + + var items = this._getItemsAsjQuery(o && o.connected); + var ret = []; o = o || {}; + + items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); }); + return ret; + + }, + + /* Be careful with the following core functions */ + _intersectsWith: function(item) { + + var x1 = this.positionAbs.left, + x2 = x1 + this.helperProportions.width, + y1 = this.positionAbs.top, + y2 = y1 + this.helperProportions.height; + + var l = item.left, + r = l + item.width, + t = item.top, + b = t + item.height; + + var dyClick = this.offset.click.top, + dxClick = this.offset.click.left; + + var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r; + + if( this.options.tolerance == "pointer" + || this.options.forcePointerForContainers + || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height']) + ) { + return isOverElement; + } else { + + return (l < x1 + (this.helperProportions.width / 2) // Right Half + && x2 - (this.helperProportions.width / 2) < r // Left Half + && t < y1 + (this.helperProportions.height / 2) // Bottom Half + && y2 - (this.helperProportions.height / 2) < b ); // Top Half + + } + }, + + _intersectsWithPointer: function(item) { + + var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), + isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), + isOverElement = isOverElementHeight && isOverElementWidth, + verticalDirection = this._getDragVerticalDirection(), + horizontalDirection = this._getDragHorizontalDirection(); + + if (!isOverElement) + return false; + + return this.floating ? + ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 ) + : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) ); + + }, + + _intersectsWithSides: function(item) { + + var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), + isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), + verticalDirection = this._getDragVerticalDirection(), + horizontalDirection = this._getDragHorizontalDirection(); + + if (this.floating && horizontalDirection) { + return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf)); + } else { + return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf)); + } + + }, + + _getDragVerticalDirection: function() { + var delta = this.positionAbs.top - this.lastPositionAbs.top; + return delta != 0 && (delta > 0 ? "down" : "up"); + }, + + _getDragHorizontalDirection: function() { + var delta = this.positionAbs.left - this.lastPositionAbs.left; + return delta != 0 && (delta > 0 ? "right" : "left"); + }, + + refresh: function(event) { + this._refreshItems(event); + this.refreshPositions(); + }, + + _connectWith: function() { + var options = this.options; + return options.connectWith.constructor == String + ? [options.connectWith] + : options.connectWith; + }, + + _getItemsAsjQuery: function(connected) { + + var self = this; + var items = []; + var queries = []; + var connectWith = this._connectWith(); + + if(connectWith && connected) { + for (var i = connectWith.length - 1; i >= 0; i--){ + var cur = $(connectWith[i]); + for (var j = cur.length - 1; j >= 0; j--){ + var inst = $.data(cur[j], 'sortable'); + if(inst && inst != this && !inst.options.disabled) { + queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper"), inst]); + } + }; + }; + } + + queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper"), this]); + + for (var i = queries.length - 1; i >= 0; i--){ + queries[i][0].each(function() { + items.push(this); + }); + }; + + return $(items); + + }, + + _removeCurrentsFromItems: function() { + + var list = this.currentItem.find(":data(sortable-item)"); + + for (var i=0; i < this.items.length; i++) { + + for (var j=0; j < list.length; j++) { + if(list[j] == this.items[i].item[0]) + this.items.splice(i,1); + }; + + }; + + }, + + _refreshItems: function(event) { + + this.items = []; + this.containers = [this]; + var items = this.items; + var self = this; + var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]]; + var connectWith = this._connectWith(); + + if(connectWith) { + for (var i = connectWith.length - 1; i >= 0; i--){ + var cur = $(connectWith[i]); + for (var j = cur.length - 1; j >= 0; j--){ + var inst = $.data(cur[j], 'sortable'); + if(inst && inst != this && !inst.options.disabled) { + queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); + this.containers.push(inst); + } + }; + }; + } + + for (var i = queries.length - 1; i >= 0; i--) { + var targetData = queries[i][1]; + var _queries = queries[i][0]; + + for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) { + var item = $(_queries[j]); + + item.data('sortable-item', targetData); // Data for target checking (mouse manager) + + items.push({ + item: item, + instance: targetData, + width: 0, height: 0, + left: 0, top: 0 + }); + }; + }; + + }, + + refreshPositions: function(fast) { + + //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change + if(this.offsetParent && this.helper) { + this.offset.parent = this._getParentOffset(); + } + + for (var i = this.items.length - 1; i >= 0; i--){ + var item = this.items[i]; + + //We ignore calculating positions of all connected containers when we're not over them + if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0]) + continue; + + var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; + + if (!fast) { + item.width = t.outerWidth(); + item.height = t.outerHeight(); + } + + var p = t.offset(); + item.left = p.left; + item.top = p.top; + }; + + if(this.options.custom && this.options.custom.refreshContainers) { + this.options.custom.refreshContainers.call(this); + } else { + for (var i = this.containers.length - 1; i >= 0; i--){ + var p = this.containers[i].element.offset(); + this.containers[i].containerCache.left = p.left; + this.containers[i].containerCache.top = p.top; + this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); + this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); + }; + } + + }, + + _createPlaceholder: function(that) { + + var self = that || this, o = self.options; + + if(!o.placeholder || o.placeholder.constructor == String) { + var className = o.placeholder; + o.placeholder = { + element: function() { + + var el = $(document.createElement(self.currentItem[0].nodeName)) + .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder") + .removeClass("ui-sortable-helper")[0]; + + if(!className) + el.style.visibility = "hidden"; + + return el; + }, + update: function(container, p) { + + // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that + // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified + if(className && !o.forcePlaceholderSize) return; + + //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item + if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); }; + if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); }; + } + }; + } + + //Create the placeholder + self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem)); + + //Append it after the actual current item + self.currentItem.after(self.placeholder); + + //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) + o.placeholder.update(self, self.placeholder); + + }, + + _contactContainers: function(event) { + for (var i = this.containers.length - 1; i >= 0; i--){ + + if(this._intersectsWith(this.containers[i].containerCache)) { + if(!this.containers[i].containerCache.over) { + + if(this.currentContainer != this.containers[i]) { + + //When entering a new container, we will find the item with the least distance and append our item near it + var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[i].floating ? 'left' : 'top']; + for (var j = this.items.length - 1; j >= 0; j--) { + if(!$.ui.contains(this.containers[i].element[0], this.items[j].item[0])) continue; + var cur = this.items[j][this.containers[i].floating ? 'left' : 'top']; + if(Math.abs(cur - base) < dist) { + dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; + } + } + + if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled + continue; + + this.currentContainer = this.containers[i]; + itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[i].element, true); + this._trigger("change", event, this._uiHash()); + this.containers[i]._trigger("change", event, this._uiHash(this)); + + //Update the placeholder + this.options.placeholder.update(this.currentContainer, this.placeholder); + + } + + this.containers[i]._trigger("over", event, this._uiHash(this)); + this.containers[i].containerCache.over = 1; + } + } else { + if(this.containers[i].containerCache.over) { + this.containers[i]._trigger("out", event, this._uiHash(this)); + this.containers[i].containerCache.over = 0; + } + } + + }; + }, + + _createHelper: function(event) { + + var o = this.options; + var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem); + + if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already + $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); + + if(helper[0] == this.currentItem[0]) + this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") }; + + if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width()); + if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height()); + + return helper; + + }, + + _adjustOffsetFromHelper: function(obj) { + if(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left; + if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; + if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top; + if(obj.bottom != undefined) this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; + }, + + _getParentOffset: function() { + + + //Get the offsetParent and cache its position + this.offsetParent = this.helper.offsetParent(); + var po = this.offsetParent.offset(); + + // This is a special case where we need to modify a offset calculated on start, since the following happened: + // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that + // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag + if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) { + po.left += this.scrollParent.scrollLeft(); + po.top += this.scrollParent.scrollTop(); + } + + if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information + || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix + po = { top: 0, left: 0 }; + + return { + top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), + left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) + }; + + }, + + _getRelativeOffset: function() { + + if(this.cssPosition == "relative") { + var p = this.currentItem.position(); + return { + top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), + left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() + }; + } else { + return { top: 0, left: 0 }; + } + + }, + + _cacheMargins: function() { + this.margins = { + left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), + top: (parseInt(this.currentItem.css("marginTop"),10) || 0) + }; + }, + + _cacheHelperProportions: function() { + this.helperProportions = { + width: this.helper.outerWidth(), + height: this.helper.outerHeight() + }; + }, + + _setContainment: function() { + + var o = this.options; + if(o.containment == 'parent') o.containment = this.helper[0].parentNode; + if(o.containment == 'document' || o.containment == 'window') this.containment = [ + 0 - this.offset.relative.left - this.offset.parent.left, + 0 - this.offset.relative.top - this.offset.parent.top, + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top + ]; + + if(!(/^(document|window|parent)$/).test(o.containment)) { + var ce = $(o.containment)[0]; + var co = $(o.containment).offset(); + var over = ($(ce).css("overflow") != 'hidden'); + + this.containment = [ + co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, + co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, + co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left, + co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top + ]; + } + + }, + + _convertPositionTo: function(d, pos) { + + if(!pos) pos = this.position; + var mod = d == "absolute" ? 1 : -1; + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + return { + top: ( + pos.top // The absolute mouse position + + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) + ), + left: ( + pos.left // The absolute mouse position + + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) + ) + }; + + }, + + _generatePosition: function(event) { + + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + // This is another very weird special case that only happens for relative elements: + // 1. If the css position is relative + // 2. and the scroll parent is the document or similar to the offset parent + // we have to refresh the relative offset during the scroll so there are no jumps + if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) { + this.offset.relative = this._getRelativeOffset(); + } + + var pageX = event.pageX; + var pageY = event.pageY; + + /* + * - Position constraining - + * Constrain the position to a mix of grid, containment. + */ + + if(this.originalPosition) { //If we are not dragging yet, we won't check for options + + if(this.containment) { + if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left; + if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top; + if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left; + if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top; + } + + if(o.grid) { + var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; + pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; + + var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; + pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; + } + + } + + return { + top: ( + pageY // The absolute mouse position + - this.offset.click.top // Click offset (relative to the element) + - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.top // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) + ), + left: ( + pageX // The absolute mouse position + - this.offset.click.left // Click offset (relative to the element) + - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.left // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) + ) + }; + + }, + + _rearrange: function(event, i, a, hardRefresh) { + + a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling)); + + //Various things done here to improve the performance: + // 1. we create a setTimeout, that calls refreshPositions + // 2. on the instance, we have a counter variable, that get's higher after every append + // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same + // 4. this lets only the last addition to the timeout stack through + this.counter = this.counter ? ++this.counter : 1; + var self = this, counter = this.counter; + + window.setTimeout(function() { + if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove + },0); + + }, + + _clear: function(event, noPropagation) { + + this.reverting = false; + // We delay all events that have to be triggered to after the point where the placeholder has been removed and + // everything else normalized again + var delayedTriggers = [], self = this; + + // We first have to update the dom position of the actual currentItem + // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) + if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem); + this._noFinalSort = null; + + if(this.helper[0] == this.currentItem[0]) { + for(var i in this._storedCSS) { + if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = ''; + } + this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); + } else { + this.currentItem.show(); + } + + if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); + if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed + if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element + if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); + for (var i = this.containers.length - 1; i >= 0; i--){ + if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) { + delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + } + }; + }; + + //Post events to containers + for (var i = this.containers.length - 1; i >= 0; i--){ + if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + if(this.containers[i].containerCache.over) { + delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + this.containers[i].containerCache.over = 0; + } + } + + //Do what was originally in plugins + if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor + if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset cursor + if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index + + this.dragging = false; + if(this.cancelHelperRemoval) { + if(!noPropagation) { + this._trigger("beforeStop", event, this._uiHash()); + for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events + this._trigger("stop", event, this._uiHash()); + } + return false; + } + + if(!noPropagation) this._trigger("beforeStop", event, this._uiHash()); + + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! + this.placeholder[0].parentNode.removeChild(this.placeholder[0]); + + if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null; + + if(!noPropagation) { + for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events + this._trigger("stop", event, this._uiHash()); + } + + this.fromOutside = false; + return true; + + }, + + _trigger: function() { + if ($.widget.prototype._trigger.apply(this, arguments) === false) { + this.cancel(); + } + }, + + _uiHash: function(inst) { + var self = inst || this; + return { + helper: self.helper, + placeholder: self.placeholder || $([]), + position: self.position, + absolutePosition: self.positionAbs, //deprecated + offset: self.positionAbs, + item: self.currentItem, + sender: inst ? inst.element : null + }; + } + +})); + +$.extend($.ui.sortable, { + getter: "serialize toArray", + version: "1.7.2", + eventPrefix: "sort", + defaults: { + appendTo: "parent", + axis: false, + cancel: ":input,option", + connectWith: false, + containment: false, + cursor: 'auto', + cursorAt: false, + delay: 0, + distance: 1, + dropOnEmpty: true, + forcePlaceholderSize: false, + forceHelperSize: false, + grid: false, + handle: false, + helper: "original", + items: '> *', + opacity: false, + placeholder: false, + revert: false, + scroll: true, + scrollSensitivity: 20, + scrollSpeed: 20, + scope: "default", + tolerance: "intersect", + zIndex: 1000 + } +}); + +})(jQuery); +/* + * jQuery UI Accordion 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Accordion + * + * Depends: + * ui.core.js + */ +(function($) { + +$.widget("ui.accordion", { + + _init: function() { + + var o = this.options, self = this; + this.running = 0; + + // if the user set the alwaysOpen option on init + // then we need to set the collapsible option + // if they set both on init, collapsible will take priority + if (o.collapsible == $.ui.accordion.defaults.collapsible && + o.alwaysOpen != $.ui.accordion.defaults.alwaysOpen) { + o.collapsible = !o.alwaysOpen; + } + + if ( o.navigation ) { + var current = this.element.find("a").filter(o.navigationFilter); + if ( current.length ) { + if ( current.filter(o.header).length ) { + this.active = current; + } else { + this.active = current.parent().parent().prev(); + current.addClass("ui-accordion-content-active"); + } + } + } + + this.element.addClass("ui-accordion ui-widget ui-helper-reset"); + + // in lack of child-selectors in CSS we need to mark top-LIs in a UL-accordion for some IE-fix + if (this.element[0].nodeName == "UL") { + this.element.children("li").addClass("ui-accordion-li-fix"); + } + + this.headers = this.element.find(o.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all") + .bind("mouseenter.accordion", function(){ $(this).addClass('ui-state-hover'); }) + .bind("mouseleave.accordion", function(){ $(this).removeClass('ui-state-hover'); }) + .bind("focus.accordion", function(){ $(this).addClass('ui-state-focus'); }) + .bind("blur.accordion", function(){ $(this).removeClass('ui-state-focus'); }); + + this.headers + .next() + .addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom"); + + this.active = this._findActive(this.active || o.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top"); + this.active.next().addClass('ui-accordion-content-active'); + + //Append icon elements + $("").addClass("ui-icon " + o.icons.header).prependTo(this.headers); + this.active.find(".ui-icon").toggleClass(o.icons.header).toggleClass(o.icons.headerSelected); + + // IE7-/Win - Extra vertical space in lists fixed + if ($.browser.msie) { + this.element.find('a').css('zoom', '1'); + } + + this.resize(); + + //ARIA + this.element.attr('role','tablist'); + + this.headers + .attr('role','tab') + .bind('keydown', function(event) { return self._keydown(event); }) + .next() + .attr('role','tabpanel'); + + this.headers + .not(this.active || "") + .attr('aria-expanded','false') + .attr("tabIndex", "-1") + .next() + .hide(); + + // make sure at least one header is in the tab order + if (!this.active.length) { + this.headers.eq(0).attr('tabIndex','0'); + } else { + this.active + .attr('aria-expanded','true') + .attr('tabIndex', '0'); + } + + // only need links in taborder for Safari + if (!$.browser.safari) + this.headers.find('a').attr('tabIndex','-1'); + + if (o.event) { + this.headers.bind((o.event) + ".accordion", function(event) { return self._clickHandler.call(self, event, this); }); + } + + }, + + destroy: function() { + var o = this.options; + + this.element + .removeClass("ui-accordion ui-widget ui-helper-reset") + .removeAttr("role") + .unbind('.accordion') + .removeData('accordion'); + + this.headers + .unbind(".accordion") + .removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top") + .removeAttr("role").removeAttr("aria-expanded").removeAttr("tabindex"); + + this.headers.find("a").removeAttr("tabindex"); + this.headers.children(".ui-icon").remove(); + var contents = this.headers.next().css("display", "").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active"); + if (o.autoHeight || o.fillHeight) { + contents.css("height", ""); + } + }, + + _setData: function(key, value) { + if(key == 'alwaysOpen') { key = 'collapsible'; value = !value; } + $.widget.prototype._setData.apply(this, arguments); + }, + + _keydown: function(event) { + + var o = this.options, keyCode = $.ui.keyCode; + + if (o.disabled || event.altKey || event.ctrlKey) + return; + + var length = this.headers.length; + var currentIndex = this.headers.index(event.target); + var toFocus = false; + + switch(event.keyCode) { + case keyCode.RIGHT: + case keyCode.DOWN: + toFocus = this.headers[(currentIndex + 1) % length]; + break; + case keyCode.LEFT: + case keyCode.UP: + toFocus = this.headers[(currentIndex - 1 + length) % length]; + break; + case keyCode.SPACE: + case keyCode.ENTER: + return this._clickHandler({ target: event.target }, event.target); + } + + if (toFocus) { + $(event.target).attr('tabIndex','-1'); + $(toFocus).attr('tabIndex','0'); + toFocus.focus(); + return false; + } + + return true; + + }, + + resize: function() { + + var o = this.options, maxHeight; + + if (o.fillSpace) { + + if($.browser.msie) { var defOverflow = this.element.parent().css('overflow'); this.element.parent().css('overflow', 'hidden'); } + maxHeight = this.element.parent().height(); + if($.browser.msie) { this.element.parent().css('overflow', defOverflow); } + + this.headers.each(function() { + maxHeight -= $(this).outerHeight(); + }); + + var maxPadding = 0; + this.headers.next().each(function() { + maxPadding = Math.max(maxPadding, $(this).innerHeight() - $(this).height()); + }).height(Math.max(0, maxHeight - maxPadding)) + .css('overflow', 'auto'); + + } else if ( o.autoHeight ) { + maxHeight = 0; + this.headers.next().each(function() { + maxHeight = Math.max(maxHeight, $(this).outerHeight()); + }).height(maxHeight); + } + + }, + + activate: function(index) { + // call clickHandler with custom event + var active = this._findActive(index)[0]; + this._clickHandler({ target: active }, active); + }, + + _findActive: function(selector) { + return selector + ? typeof selector == "number" + ? this.headers.filter(":eq(" + selector + ")") + : this.headers.not(this.headers.not(selector)) + : selector === false + ? $([]) + : this.headers.filter(":eq(0)"); + }, + + _clickHandler: function(event, target) { + + var o = this.options; + if (o.disabled) return false; + + // called only when using activate(false) to close all parts programmatically + if (!event.target && o.collapsible) { + this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all") + .find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header); + this.active.next().addClass('ui-accordion-content-active'); + var toHide = this.active.next(), + data = { + options: o, + newHeader: $([]), + oldHeader: o.active, + newContent: $([]), + oldContent: toHide + }, + toShow = (this.active = $([])); + this._toggle(toShow, toHide, data); + return false; + } + + // get the click target + var clicked = $(event.currentTarget || target); + var clickedIsActive = clicked[0] == this.active[0]; + + // if animations are still active, or the active header is the target, ignore click + if (this.running || (!o.collapsible && clickedIsActive)) { + return false; + } + + // switch classes + this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all") + .find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header); + this.active.next().addClass('ui-accordion-content-active'); + if (!clickedIsActive) { + clicked.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top") + .find(".ui-icon").removeClass(o.icons.header).addClass(o.icons.headerSelected); + clicked.next().addClass('ui-accordion-content-active'); + } + + // find elements to show and hide + var toShow = clicked.next(), + toHide = this.active.next(), + data = { + options: o, + newHeader: clickedIsActive && o.collapsible ? $([]) : clicked, + oldHeader: this.active, + newContent: clickedIsActive && o.collapsible ? $([]) : toShow.find('> *'), + oldContent: toHide.find('> *') + }, + down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] ); + + this.active = clickedIsActive ? $([]) : clicked; + this._toggle(toShow, toHide, data, clickedIsActive, down); + + return false; + + }, + + _toggle: function(toShow, toHide, data, clickedIsActive, down) { + + var o = this.options, self = this; + + this.toShow = toShow; + this.toHide = toHide; + this.data = data; + + var complete = function() { if(!self) return; return self._completed.apply(self, arguments); }; + + // trigger changestart event + this._trigger("changestart", null, this.data); + + // count elements to animate + this.running = toHide.size() === 0 ? toShow.size() : toHide.size(); + + if (o.animated) { + + var animOptions = {}; + + if ( o.collapsible && clickedIsActive ) { + animOptions = { + toShow: $([]), + toHide: toHide, + complete: complete, + down: down, + autoHeight: o.autoHeight || o.fillSpace + }; + } else { + animOptions = { + toShow: toShow, + toHide: toHide, + complete: complete, + down: down, + autoHeight: o.autoHeight || o.fillSpace + }; + } + + if (!o.proxied) { + o.proxied = o.animated; + } + + if (!o.proxiedDuration) { + o.proxiedDuration = o.duration; + } + + o.animated = $.isFunction(o.proxied) ? + o.proxied(animOptions) : o.proxied; + + o.duration = $.isFunction(o.proxiedDuration) ? + o.proxiedDuration(animOptions) : o.proxiedDuration; + + var animations = $.ui.accordion.animations, + duration = o.duration, + easing = o.animated; + + if (!animations[easing]) { + animations[easing] = function(options) { + this.slide(options, { + easing: easing, + duration: duration || 700 + }); + }; + } + + animations[easing](animOptions); + + } else { + + if (o.collapsible && clickedIsActive) { + toShow.toggle(); + } else { + toHide.hide(); + toShow.show(); + } + + complete(true); + + } + + toHide.prev().attr('aria-expanded','false').attr("tabIndex", "-1").blur(); + toShow.prev().attr('aria-expanded','true').attr("tabIndex", "0").focus(); + + }, + + _completed: function(cancel) { + + var o = this.options; + + this.running = cancel ? 0 : --this.running; + if (this.running) return; + + if (o.clearStyle) { + this.toShow.add(this.toHide).css({ + height: "", + overflow: "" + }); + } + + this._trigger('change', null, this.data); + } + +}); + + +$.extend($.ui.accordion, { + version: "1.7.2", + defaults: { + active: null, + alwaysOpen: true, //deprecated, use collapsible + animated: 'slide', + autoHeight: true, + clearStyle: false, + collapsible: false, + event: "click", + fillSpace: false, + header: "> li > :first-child,> :not(li):even", + icons: { + header: "ui-icon-triangle-1-e", + headerSelected: "ui-icon-triangle-1-s" + }, + navigation: false, + navigationFilter: function() { + return this.href.toLowerCase() == location.href.toLowerCase(); + } + }, + animations: { + slide: function(options, additions) { + options = $.extend({ + easing: "swing", + duration: 300 + }, options, additions); + if ( !options.toHide.size() ) { + options.toShow.animate({height: "show"}, options); + return; + } + if ( !options.toShow.size() ) { + options.toHide.animate({height: "hide"}, options); + return; + } + var overflow = options.toShow.css('overflow'), + percentDone, + showProps = {}, + hideProps = {}, + fxAttrs = [ "height", "paddingTop", "paddingBottom" ], + originalWidth; + // fix width before calculating height of hidden element + var s = options.toShow; + originalWidth = s[0].style.width; + s.width( parseInt(s.parent().width(),10) - parseInt(s.css("paddingLeft"),10) - parseInt(s.css("paddingRight"),10) - (parseInt(s.css("borderLeftWidth"),10) || 0) - (parseInt(s.css("borderRightWidth"),10) || 0) ); + + $.each(fxAttrs, function(i, prop) { + hideProps[prop] = 'hide'; + + var parts = ('' + $.css(options.toShow[0], prop)).match(/^([\d+-.]+)(.*)$/); + showProps[prop] = { + value: parts[1], + unit: parts[2] || 'px' + }; + }); + options.toShow.css({ height: 0, overflow: 'hidden' }).show(); + options.toHide.filter(":hidden").each(options.complete).end().filter(":visible").animate(hideProps,{ + step: function(now, settings) { + // only calculate the percent when animating height + // IE gets very inconsistent results when animating elements + // with small values, which is common for padding + if (settings.prop == 'height') { + percentDone = (settings.now - settings.start) / (settings.end - settings.start); + } + + options.toShow[0].style[settings.prop] = + (percentDone * showProps[settings.prop].value) + showProps[settings.prop].unit; + }, + duration: options.duration, + easing: options.easing, + complete: function() { + if ( !options.autoHeight ) { + options.toShow.css("height", ""); + } + options.toShow.css("width", originalWidth); + options.toShow.css({overflow: overflow}); + options.complete(); + } + }); + }, + bounceslide: function(options) { + this.slide(options, { + easing: options.down ? "easeOutBounce" : "swing", + duration: options.down ? 1000 : 200 + }); + }, + easeslide: function(options) { + this.slide(options, { + easing: "easeinout", + duration: 700 + }); + } + } +}); + +})(jQuery); +/* + * jQuery UI Dialog 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Dialog + * + * Depends: + * ui.core.js + * ui.draggable.js + * ui.resizable.js + */ +(function($) { + +var setDataSwitch = { + dragStart: "start.draggable", + drag: "drag.draggable", + dragStop: "stop.draggable", + maxHeight: "maxHeight.resizable", + minHeight: "minHeight.resizable", + maxWidth: "maxWidth.resizable", + minWidth: "minWidth.resizable", + resizeStart: "start.resizable", + resize: "drag.resizable", + resizeStop: "stop.resizable" + }, + + uiDialogClasses = + 'ui-dialog ' + + 'ui-widget ' + + 'ui-widget-content ' + + 'ui-corner-all '; + +$.widget("ui.dialog", { + + _init: function() { + this.originalTitle = this.element.attr('title'); + + var self = this, + options = this.options, + + title = options.title || this.originalTitle || ' ', + titleId = $.ui.dialog.getTitleId(this.element), + + uiDialog = (this.uiDialog = $('
')) + .appendTo(document.body) + .hide() + .addClass(uiDialogClasses + options.dialogClass) + .css({ + position: 'absolute', + overflow: 'hidden', + zIndex: options.zIndex + }) + // setting tabIndex makes the div focusable + // setting outline to 0 prevents a border on focus in Mozilla + .attr('tabIndex', -1).css('outline', 0).keydown(function(event) { + (options.closeOnEscape && event.keyCode + && event.keyCode == $.ui.keyCode.ESCAPE && self.close(event)); + }) + .attr({ + role: 'dialog', + 'aria-labelledby': titleId + }) + .mousedown(function(event) { + self.moveToTop(false, event); + }), + + uiDialogContent = this.element + .show() + .removeAttr('title') + .addClass( + 'ui-dialog-content ' + + 'ui-widget-content') + .appendTo(uiDialog), + + uiDialogTitlebar = (this.uiDialogTitlebar = $('
')) + .addClass( + 'ui-dialog-titlebar ' + + 'ui-widget-header ' + + 'ui-corner-all ' + + 'ui-helper-clearfix' + ) + .prependTo(uiDialog), + + uiDialogTitlebarClose = $('') + .addClass( + 'ui-dialog-titlebar-close ' + + 'ui-corner-all' + ) + .attr('role', 'button') + .hover( + function() { + uiDialogTitlebarClose.addClass('ui-state-hover'); + }, + function() { + uiDialogTitlebarClose.removeClass('ui-state-hover'); + } + ) + .focus(function() { + uiDialogTitlebarClose.addClass('ui-state-focus'); + }) + .blur(function() { + uiDialogTitlebarClose.removeClass('ui-state-focus'); + }) + .mousedown(function(ev) { + ev.stopPropagation(); + }) + .click(function(event) { + self.close(event); + return false; + }) + .appendTo(uiDialogTitlebar), + + uiDialogTitlebarCloseText = (this.uiDialogTitlebarCloseText = $('')) + .addClass( + 'ui-icon ' + + 'ui-icon-closethick' + ) + .text(options.closeText) + .appendTo(uiDialogTitlebarClose), + + uiDialogTitle = $('') + .addClass('ui-dialog-title') + .attr('id', titleId) + .html(title) + .prependTo(uiDialogTitlebar); + + uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection(); + + (options.draggable && $.fn.draggable && this._makeDraggable()); + (options.resizable && $.fn.resizable && this._makeResizable()); + + this._createButtons(options.buttons); + this._isOpen = false; + + (options.bgiframe && $.fn.bgiframe && uiDialog.bgiframe()); + (options.autoOpen && this.open()); + + }, + + destroy: function() { + (this.overlay && this.overlay.destroy()); + this.uiDialog.hide(); + this.element + .unbind('.dialog') + .removeData('dialog') + .removeClass('ui-dialog-content ui-widget-content') + .hide().appendTo('body'); + this.uiDialog.remove(); + + (this.originalTitle && this.element.attr('title', this.originalTitle)); + }, + + close: function(event) { + var self = this; + + if (false === self._trigger('beforeclose', event)) { + return; + } + + (self.overlay && self.overlay.destroy()); + self.uiDialog.unbind('keypress.ui-dialog'); + + (self.options.hide + ? self.uiDialog.hide(self.options.hide, function() { + self._trigger('close', event); + }) + : self.uiDialog.hide() && self._trigger('close', event)); + + $.ui.dialog.overlay.resize(); + + self._isOpen = false; + + // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) + if (self.options.modal) { + var maxZ = 0; + $('.ui-dialog').each(function() { + if (this != self.uiDialog[0]) { + maxZ = Math.max(maxZ, $(this).css('z-index')); + } + }); + $.ui.dialog.maxZ = maxZ; + } + }, + + isOpen: function() { + return this._isOpen; + }, + + // the force parameter allows us to move modal dialogs to their correct + // position on open + moveToTop: function(force, event) { + + if ((this.options.modal && !force) + || (!this.options.stack && !this.options.modal)) { + return this._trigger('focus', event); + } + + if (this.options.zIndex > $.ui.dialog.maxZ) { + $.ui.dialog.maxZ = this.options.zIndex; + } + (this.overlay && this.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = ++$.ui.dialog.maxZ)); + + //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed. + // http://ui.jquery.com/bugs/ticket/3193 + var saveScroll = { scrollTop: this.element.attr('scrollTop'), scrollLeft: this.element.attr('scrollLeft') }; + this.uiDialog.css('z-index', ++$.ui.dialog.maxZ); + this.element.attr(saveScroll); + this._trigger('focus', event); + }, + + open: function() { + if (this._isOpen) { return; } + + var options = this.options, + uiDialog = this.uiDialog; + + this.overlay = options.modal ? new $.ui.dialog.overlay(this) : null; + (uiDialog.next().length && uiDialog.appendTo('body')); + this._size(); + this._position(options.position); + uiDialog.show(options.show); + this.moveToTop(true); + + // prevent tabbing out of modal dialogs + (options.modal && uiDialog.bind('keypress.ui-dialog', function(event) { + if (event.keyCode != $.ui.keyCode.TAB) { + return; + } + + var tabbables = $(':tabbable', this), + first = tabbables.filter(':first')[0], + last = tabbables.filter(':last')[0]; + + if (event.target == last && !event.shiftKey) { + setTimeout(function() { + first.focus(); + }, 1); + } else if (event.target == first && event.shiftKey) { + setTimeout(function() { + last.focus(); + }, 1); + } + })); + + // set focus to the first tabbable element in the content area or the first button + // if there are no tabbable elements, set focus on the dialog itself + $([]) + .add(uiDialog.find('.ui-dialog-content :tabbable:first')) + .add(uiDialog.find('.ui-dialog-buttonpane :tabbable:first')) + .add(uiDialog) + .filter(':first') + .focus(); + + this._trigger('open'); + this._isOpen = true; + }, + + _createButtons: function(buttons) { + var self = this, + hasButtons = false, + uiDialogButtonPane = $('
') + .addClass( + 'ui-dialog-buttonpane ' + + 'ui-widget-content ' + + 'ui-helper-clearfix' + ); + + // if we already have a button pane, remove it + this.uiDialog.find('.ui-dialog-buttonpane').remove(); + + (typeof buttons == 'object' && buttons !== null && + $.each(buttons, function() { return !(hasButtons = true); })); + if (hasButtons) { + $.each(buttons, function(name, fn) { + $('') + .addClass( + 'ui-state-default ' + + 'ui-corner-all' + ) + .text(name) + .click(function() { fn.apply(self.element[0], arguments); }) + .hover( + function() { + $(this).addClass('ui-state-hover'); + }, + function() { + $(this).removeClass('ui-state-hover'); + } + ) + .focus(function() { + $(this).addClass('ui-state-focus'); + }) + .blur(function() { + $(this).removeClass('ui-state-focus'); + }) + .appendTo(uiDialogButtonPane); + }); + uiDialogButtonPane.appendTo(this.uiDialog); + } + }, + + _makeDraggable: function() { + var self = this, + options = this.options, + heightBeforeDrag; + + this.uiDialog.draggable({ + cancel: '.ui-dialog-content', + handle: '.ui-dialog-titlebar', + containment: 'document', + start: function() { + heightBeforeDrag = options.height; + $(this).height($(this).height()).addClass("ui-dialog-dragging"); + (options.dragStart && options.dragStart.apply(self.element[0], arguments)); + }, + drag: function() { + (options.drag && options.drag.apply(self.element[0], arguments)); + }, + stop: function() { + $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag); + (options.dragStop && options.dragStop.apply(self.element[0], arguments)); + $.ui.dialog.overlay.resize(); + } + }); + }, + + _makeResizable: function(handles) { + handles = (handles === undefined ? this.options.resizable : handles); + var self = this, + options = this.options, + resizeHandles = typeof handles == 'string' + ? handles + : 'n,e,s,w,se,sw,ne,nw'; + + this.uiDialog.resizable({ + cancel: '.ui-dialog-content', + alsoResize: this.element, + maxWidth: options.maxWidth, + maxHeight: options.maxHeight, + minWidth: options.minWidth, + minHeight: options.minHeight, + start: function() { + $(this).addClass("ui-dialog-resizing"); + (options.resizeStart && options.resizeStart.apply(self.element[0], arguments)); + }, + resize: function() { + (options.resize && options.resize.apply(self.element[0], arguments)); + }, + handles: resizeHandles, + stop: function() { + $(this).removeClass("ui-dialog-resizing"); + options.height = $(this).height(); + options.width = $(this).width(); + (options.resizeStop && options.resizeStop.apply(self.element[0], arguments)); + $.ui.dialog.overlay.resize(); + } + }) + .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se'); + }, + + _position: function(pos) { + var wnd = $(window), doc = $(document), + pTop = doc.scrollTop(), pLeft = doc.scrollLeft(), + minTop = pTop; + + if ($.inArray(pos, ['center','top','right','bottom','left']) >= 0) { + pos = [ + pos == 'right' || pos == 'left' ? pos : 'center', + pos == 'top' || pos == 'bottom' ? pos : 'middle' + ]; + } + if (pos.constructor != Array) { + pos = ['center', 'middle']; + } + if (pos[0].constructor == Number) { + pLeft += pos[0]; + } else { + switch (pos[0]) { + case 'left': + pLeft += 0; + break; + case 'right': + pLeft += wnd.width() - this.uiDialog.outerWidth(); + break; + default: + case 'center': + pLeft += (wnd.width() - this.uiDialog.outerWidth()) / 2; + } + } + if (pos[1].constructor == Number) { + pTop += pos[1]; + } else { + switch (pos[1]) { + case 'top': + pTop += 0; + break; + case 'bottom': + pTop += wnd.height() - this.uiDialog.outerHeight(); + break; + default: + case 'middle': + pTop += (wnd.height() - this.uiDialog.outerHeight()) / 2; + } + } + + // prevent the dialog from being too high (make sure the titlebar + // is accessible) + pTop = Math.max(pTop, minTop); + this.uiDialog.css({top: pTop, left: pLeft}); + }, + + _setData: function(key, value){ + (setDataSwitch[key] && this.uiDialog.data(setDataSwitch[key], value)); + switch (key) { + case "buttons": + this._createButtons(value); + break; + case "closeText": + this.uiDialogTitlebarCloseText.text(value); + break; + case "dialogClass": + this.uiDialog + .removeClass(this.options.dialogClass) + .addClass(uiDialogClasses + value); + break; + case "draggable": + (value + ? this._makeDraggable() + : this.uiDialog.draggable('destroy')); + break; + case "height": + this.uiDialog.height(value); + break; + case "position": + this._position(value); + break; + case "resizable": + var uiDialog = this.uiDialog, + isResizable = this.uiDialog.is(':data(resizable)'); + + // currently resizable, becoming non-resizable + (isResizable && !value && uiDialog.resizable('destroy')); + + // currently resizable, changing handles + (isResizable && typeof value == 'string' && + uiDialog.resizable('option', 'handles', value)); + + // currently non-resizable, becoming resizable + (isResizable || this._makeResizable(value)); + break; + case "title": + $(".ui-dialog-title", this.uiDialogTitlebar).html(value || ' '); + break; + case "width": + this.uiDialog.width(value); + break; + } + + $.widget.prototype._setData.apply(this, arguments); + }, + + _size: function() { + /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content + * divs will both have width and height set, so we need to reset them + */ + var options = this.options; + + // reset content sizing + this.element.css({ + height: 0, + minHeight: 0, + width: 'auto' + }); + + // reset wrapper sizing + // determine the height of all the non-content elements + var nonContentHeight = this.uiDialog.css({ + height: 'auto', + width: options.width + }) + .height(); + + this.element + .css({ + minHeight: Math.max(options.minHeight - nonContentHeight, 0), + height: options.height == 'auto' + ? 'auto' + : Math.max(options.height - nonContentHeight, 0) + }); + } +}); + +$.extend($.ui.dialog, { + version: "1.7.2", + defaults: { + autoOpen: true, + bgiframe: false, + buttons: {}, + closeOnEscape: true, + closeText: 'close', + dialogClass: '', + draggable: true, + hide: null, + height: 'auto', + maxHeight: false, + maxWidth: false, + minHeight: 150, + minWidth: 150, + modal: false, + position: 'center', + resizable: true, + show: null, + stack: true, + title: '', + width: 300, + zIndex: 1000 + }, + + getter: 'isOpen', + + uuid: 0, + maxZ: 0, + + getTitleId: function($el) { + return 'ui-dialog-title-' + ($el.attr('id') || ++this.uuid); + }, + + overlay: function(dialog) { + this.$el = $.ui.dialog.overlay.create(dialog); + } +}); + +$.extend($.ui.dialog.overlay, { + instances: [], + maxZ: 0, + events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','), + function(event) { return event + '.dialog-overlay'; }).join(' '), + create: function(dialog) { + if (this.instances.length === 0) { + // prevent use of anchors and inputs + // we use a setTimeout in case the overlay is created from an + // event that we're going to be cancelling (see #2804) + setTimeout(function() { + // handle $(el).dialog().dialog('close') (see #4065) + if ($.ui.dialog.overlay.instances.length) { + $(document).bind($.ui.dialog.overlay.events, function(event) { + var dialogZ = $(event.target).parents('.ui-dialog').css('zIndex') || 0; + return (dialogZ > $.ui.dialog.overlay.maxZ); + }); + } + }, 1); + + // allow closing by pressing the escape key + $(document).bind('keydown.dialog-overlay', function(event) { + (dialog.options.closeOnEscape && event.keyCode + && event.keyCode == $.ui.keyCode.ESCAPE && dialog.close(event)); + }); + + // handle window resize + $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize); + } + + var $el = $('
').appendTo(document.body) + .addClass('ui-widget-overlay').css({ + width: this.width(), + height: this.height() + }); + + (dialog.options.bgiframe && $.fn.bgiframe && $el.bgiframe()); + + this.instances.push($el); + return $el; + }, + + destroy: function($el) { + this.instances.splice($.inArray(this.instances, $el), 1); + + if (this.instances.length === 0) { + $([document, window]).unbind('.dialog-overlay'); + } + + $el.remove(); + + // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) + var maxZ = 0; + $.each(this.instances, function() { + maxZ = Math.max(maxZ, this.css('z-index')); + }); + this.maxZ = maxZ; + }, + + height: function() { + // handle IE 6 + if ($.browser.msie && $.browser.version < 7) { + var scrollHeight = Math.max( + document.documentElement.scrollHeight, + document.body.scrollHeight + ); + var offsetHeight = Math.max( + document.documentElement.offsetHeight, + document.body.offsetHeight + ); + + if (scrollHeight < offsetHeight) { + return $(window).height() + 'px'; + } else { + return scrollHeight + 'px'; + } + // handle "good" browsers + } else { + return $(document).height() + 'px'; + } + }, + + width: function() { + // handle IE 6 + if ($.browser.msie && $.browser.version < 7) { + var scrollWidth = Math.max( + document.documentElement.scrollWidth, + document.body.scrollWidth + ); + var offsetWidth = Math.max( + document.documentElement.offsetWidth, + document.body.offsetWidth + ); + + if (scrollWidth < offsetWidth) { + return $(window).width() + 'px'; + } else { + return scrollWidth + 'px'; + } + // handle "good" browsers + } else { + return $(document).width() + 'px'; + } + }, + + resize: function() { + /* If the dialog is draggable and the user drags it past the + * right edge of the window, the document becomes wider so we + * need to stretch the overlay. If the user then drags the + * dialog back to the left, the document will become narrower, + * so we need to shrink the overlay to the appropriate size. + * This is handled by shrinking the overlay before setting it + * to the full document size. + */ + var $overlays = $([]); + $.each($.ui.dialog.overlay.instances, function() { + $overlays = $overlays.add(this); + }); + + $overlays.css({ + width: 0, + height: 0 + }).css({ + width: $.ui.dialog.overlay.width(), + height: $.ui.dialog.overlay.height() + }); + } +}); + +$.extend($.ui.dialog.overlay.prototype, { + destroy: function() { + $.ui.dialog.overlay.destroy(this.$el); + } +}); + +})(jQuery); +/* + * jQuery UI Slider 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Slider + * + * Depends: + * ui.core.js + */ + +(function($) { + +$.widget("ui.slider", $.extend({}, $.ui.mouse, { + + _init: function() { + + var self = this, o = this.options; + this._keySliding = false; + this._handleIndex = null; + this._detectOrientation(); + this._mouseInit(); + + this.element + .addClass("ui-slider" + + " ui-slider-" + this.orientation + + " ui-widget" + + " ui-widget-content" + + " ui-corner-all"); + + this.range = $([]); + + if (o.range) { + + if (o.range === true) { + this.range = $('
'); + if (!o.values) o.values = [this._valueMin(), this._valueMin()]; + if (o.values.length && o.values.length != 2) { + o.values = [o.values[0], o.values[0]]; + } + } else { + this.range = $('
'); + } + + this.range + .appendTo(this.element) + .addClass("ui-slider-range"); + + if (o.range == "min" || o.range == "max") { + this.range.addClass("ui-slider-range-" + o.range); + } + + // note: this isn't the most fittingly semantic framework class for this element, + // but worked best visually with a variety of themes + this.range.addClass("ui-widget-header"); + + } + + if ($(".ui-slider-handle", this.element).length == 0) + $('
') + .appendTo(this.element) + .addClass("ui-slider-handle"); + + if (o.values && o.values.length) { + while ($(".ui-slider-handle", this.element).length < o.values.length) + $('') + .appendTo(this.element) + .addClass("ui-slider-handle"); + } + + this.handles = $(".ui-slider-handle", this.element) + .addClass("ui-state-default" + + " ui-corner-all"); + + this.handle = this.handles.eq(0); + + this.handles.add(this.range).filter("a") + .click(function(event) { + event.preventDefault(); + }) + .hover(function() { + if (!o.disabled) { + $(this).addClass('ui-state-hover'); + } + }, function() { + $(this).removeClass('ui-state-hover'); + }) + .focus(function() { + if (!o.disabled) { + $(".ui-slider .ui-state-focus").removeClass('ui-state-focus'); $(this).addClass('ui-state-focus'); + } else { + $(this).blur(); + } + }) + .blur(function() { + $(this).removeClass('ui-state-focus'); + }); + + this.handles.each(function(i) { + $(this).data("index.ui-slider-handle", i); + }); + + this.handles.keydown(function(event) { + + var ret = true; + + var index = $(this).data("index.ui-slider-handle"); + + if (self.options.disabled) + return; + + switch (event.keyCode) { + case $.ui.keyCode.HOME: + case $.ui.keyCode.END: + case $.ui.keyCode.UP: + case $.ui.keyCode.RIGHT: + case $.ui.keyCode.DOWN: + case $.ui.keyCode.LEFT: + ret = false; + if (!self._keySliding) { + self._keySliding = true; + $(this).addClass("ui-state-active"); + self._start(event, index); + } + break; + } + + var curVal, newVal, step = self._step(); + if (self.options.values && self.options.values.length) { + curVal = newVal = self.values(index); + } else { + curVal = newVal = self.value(); + } + + switch (event.keyCode) { + case $.ui.keyCode.HOME: + newVal = self._valueMin(); + break; + case $.ui.keyCode.END: + newVal = self._valueMax(); + break; + case $.ui.keyCode.UP: + case $.ui.keyCode.RIGHT: + if(curVal == self._valueMax()) return; + newVal = curVal + step; + break; + case $.ui.keyCode.DOWN: + case $.ui.keyCode.LEFT: + if(curVal == self._valueMin()) return; + newVal = curVal - step; + break; + } + + self._slide(event, index, newVal); + + return ret; + + }).keyup(function(event) { + + var index = $(this).data("index.ui-slider-handle"); + + if (self._keySliding) { + self._stop(event, index); + self._change(event, index); + self._keySliding = false; + $(this).removeClass("ui-state-active"); + } + + }); + + this._refreshValue(); + + }, + + destroy: function() { + + this.handles.remove(); + this.range.remove(); + + this.element + .removeClass("ui-slider" + + " ui-slider-horizontal" + + " ui-slider-vertical" + + " ui-slider-disabled" + + " ui-widget" + + " ui-widget-content" + + " ui-corner-all") + .removeData("slider") + .unbind(".slider"); + + this._mouseDestroy(); + + }, + + _mouseCapture: function(event) { + + var o = this.options; + + if (o.disabled) + return false; + + this.elementSize = { + width: this.element.outerWidth(), + height: this.element.outerHeight() + }; + this.elementOffset = this.element.offset(); + + var position = { x: event.pageX, y: event.pageY }; + var normValue = this._normValueFromMouse(position); + + var distance = this._valueMax() - this._valueMin() + 1, closestHandle; + var self = this, index; + this.handles.each(function(i) { + var thisDistance = Math.abs(normValue - self.values(i)); + if (distance > thisDistance) { + distance = thisDistance; + closestHandle = $(this); + index = i; + } + }); + + // workaround for bug #3736 (if both handles of a range are at 0, + // the first is always used as the one with least distance, + // and moving it is obviously prevented by preventing negative ranges) + if(o.range == true && this.values(1) == o.min) { + closestHandle = $(this.handles[++index]); + } + + this._start(event, index); + + self._handleIndex = index; + + closestHandle + .addClass("ui-state-active") + .focus(); + + var offset = closestHandle.offset(); + var mouseOverHandle = !$(event.target).parents().andSelf().is('.ui-slider-handle'); + this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { + left: event.pageX - offset.left - (closestHandle.width() / 2), + top: event.pageY - offset.top + - (closestHandle.height() / 2) + - (parseInt(closestHandle.css('borderTopWidth'),10) || 0) + - (parseInt(closestHandle.css('borderBottomWidth'),10) || 0) + + (parseInt(closestHandle.css('marginTop'),10) || 0) + }; + + normValue = this._normValueFromMouse(position); + this._slide(event, index, normValue); + return true; + + }, + + _mouseStart: function(event) { + return true; + }, + + _mouseDrag: function(event) { + + var position = { x: event.pageX, y: event.pageY }; + var normValue = this._normValueFromMouse(position); + + this._slide(event, this._handleIndex, normValue); + + return false; + + }, + + _mouseStop: function(event) { + + this.handles.removeClass("ui-state-active"); + this._stop(event, this._handleIndex); + this._change(event, this._handleIndex); + this._handleIndex = null; + this._clickOffset = null; + + return false; + + }, + + _detectOrientation: function() { + this.orientation = this.options.orientation == 'vertical' ? 'vertical' : 'horizontal'; + }, + + _normValueFromMouse: function(position) { + + var pixelTotal, pixelMouse; + if ('horizontal' == this.orientation) { + pixelTotal = this.elementSize.width; + pixelMouse = position.x - this.elementOffset.left - (this._clickOffset ? this._clickOffset.left : 0); + } else { + pixelTotal = this.elementSize.height; + pixelMouse = position.y - this.elementOffset.top - (this._clickOffset ? this._clickOffset.top : 0); + } + + var percentMouse = (pixelMouse / pixelTotal); + if (percentMouse > 1) percentMouse = 1; + if (percentMouse < 0) percentMouse = 0; + if ('vertical' == this.orientation) + percentMouse = 1 - percentMouse; + + var valueTotal = this._valueMax() - this._valueMin(), + valueMouse = percentMouse * valueTotal, + valueMouseModStep = valueMouse % this.options.step, + normValue = this._valueMin() + valueMouse - valueMouseModStep; + + if (valueMouseModStep > (this.options.step / 2)) + normValue += this.options.step; + + // Since JavaScript has problems with large floats, round + // the final value to 5 digits after the decimal point (see #4124) + return parseFloat(normValue.toFixed(5)); + + }, + + _start: function(event, index) { + var uiHash = { + handle: this.handles[index], + value: this.value() + }; + if (this.options.values && this.options.values.length) { + uiHash.value = this.values(index); + uiHash.values = this.values(); + } + this._trigger("start", event, uiHash); + }, + + _slide: function(event, index, newVal) { + + var handle = this.handles[index]; + + if (this.options.values && this.options.values.length) { + + var otherVal = this.values(index ? 0 : 1); + + if ((this.options.values.length == 2 && this.options.range === true) && + ((index == 0 && newVal > otherVal) || (index == 1 && newVal < otherVal))){ + newVal = otherVal; + } + + if (newVal != this.values(index)) { + var newValues = this.values(); + newValues[index] = newVal; + // A slide can be canceled by returning false from the slide callback + var allowed = this._trigger("slide", event, { + handle: this.handles[index], + value: newVal, + values: newValues + }); + var otherVal = this.values(index ? 0 : 1); + if (allowed !== false) { + this.values(index, newVal, ( event.type == 'mousedown' && this.options.animate ), true); + } + } + + } else { + + if (newVal != this.value()) { + // A slide can be canceled by returning false from the slide callback + var allowed = this._trigger("slide", event, { + handle: this.handles[index], + value: newVal + }); + if (allowed !== false) { + this._setData('value', newVal, ( event.type == 'mousedown' && this.options.animate )); + } + + } + + } + + }, + + _stop: function(event, index) { + var uiHash = { + handle: this.handles[index], + value: this.value() + }; + if (this.options.values && this.options.values.length) { + uiHash.value = this.values(index); + uiHash.values = this.values(); + } + this._trigger("stop", event, uiHash); + }, + + _change: function(event, index) { + var uiHash = { + handle: this.handles[index], + value: this.value() + }; + if (this.options.values && this.options.values.length) { + uiHash.value = this.values(index); + uiHash.values = this.values(); + } + this._trigger("change", event, uiHash); + }, + + value: function(newValue) { + + if (arguments.length) { + this._setData("value", newValue); + this._change(null, 0); + } + + return this._value(); + + }, + + values: function(index, newValue, animated, noPropagation) { + + if (arguments.length > 1) { + this.options.values[index] = newValue; + this._refreshValue(animated); + if(!noPropagation) this._change(null, index); + } + + if (arguments.length) { + if (this.options.values && this.options.values.length) { + return this._values(index); + } else { + return this.value(); + } + } else { + return this._values(); + } + + }, + + _setData: function(key, value, animated) { + + $.widget.prototype._setData.apply(this, arguments); + + switch (key) { + case 'disabled': + if (value) { + this.handles.filter(".ui-state-focus").blur(); + this.handles.removeClass("ui-state-hover"); + this.handles.attr("disabled", "disabled"); + } else { + this.handles.removeAttr("disabled"); + } + case 'orientation': + + this._detectOrientation(); + + this.element + .removeClass("ui-slider-horizontal ui-slider-vertical") + .addClass("ui-slider-" + this.orientation); + this._refreshValue(animated); + break; + case 'value': + this._refreshValue(animated); + break; + } + + }, + + _step: function() { + var step = this.options.step; + return step; + }, + + _value: function() { + + var val = this.options.value; + if (val < this._valueMin()) val = this._valueMin(); + if (val > this._valueMax()) val = this._valueMax(); + + return val; + + }, + + _values: function(index) { + + if (arguments.length) { + var val = this.options.values[index]; + if (val < this._valueMin()) val = this._valueMin(); + if (val > this._valueMax()) val = this._valueMax(); + + return val; + } else { + return this.options.values; + } + + }, + + _valueMin: function() { + var valueMin = this.options.min; + return valueMin; + }, + + _valueMax: function() { + var valueMax = this.options.max; + return valueMax; + }, + + _refreshValue: function(animate) { + + var oRange = this.options.range, o = this.options, self = this; + + if (this.options.values && this.options.values.length) { + var vp0, vp1; + this.handles.each(function(i, j) { + var valPercent = (self.values(i) - self._valueMin()) / (self._valueMax() - self._valueMin()) * 100; + var _set = {}; _set[self.orientation == 'horizontal' ? 'left' : 'bottom'] = valPercent + '%'; + $(this).stop(1,1)[animate ? 'animate' : 'css'](_set, o.animate); + if (self.options.range === true) { + if (self.orientation == 'horizontal') { + (i == 0) && self.range.stop(1,1)[animate ? 'animate' : 'css']({ left: valPercent + '%' }, o.animate); + (i == 1) && self.range[animate ? 'animate' : 'css']({ width: (valPercent - lastValPercent) + '%' }, { queue: false, duration: o.animate }); + } else { + (i == 0) && self.range.stop(1,1)[animate ? 'animate' : 'css']({ bottom: (valPercent) + '%' }, o.animate); + (i == 1) && self.range[animate ? 'animate' : 'css']({ height: (valPercent - lastValPercent) + '%' }, { queue: false, duration: o.animate }); + } + } + lastValPercent = valPercent; + }); + } else { + var value = this.value(), + valueMin = this._valueMin(), + valueMax = this._valueMax(), + valPercent = valueMax != valueMin + ? (value - valueMin) / (valueMax - valueMin) * 100 + : 0; + var _set = {}; _set[self.orientation == 'horizontal' ? 'left' : 'bottom'] = valPercent + '%'; + this.handle.stop(1,1)[animate ? 'animate' : 'css'](_set, o.animate); + + (oRange == "min") && (this.orientation == "horizontal") && this.range.stop(1,1)[animate ? 'animate' : 'css']({ width: valPercent + '%' }, o.animate); + (oRange == "max") && (this.orientation == "horizontal") && this.range[animate ? 'animate' : 'css']({ width: (100 - valPercent) + '%' }, { queue: false, duration: o.animate }); + (oRange == "min") && (this.orientation == "vertical") && this.range.stop(1,1)[animate ? 'animate' : 'css']({ height: valPercent + '%' }, o.animate); + (oRange == "max") && (this.orientation == "vertical") && this.range[animate ? 'animate' : 'css']({ height: (100 - valPercent) + '%' }, { queue: false, duration: o.animate }); + } + + } + +})); + +$.extend($.ui.slider, { + getter: "value values", + version: "1.7.2", + eventPrefix: "slide", + defaults: { + animate: false, + delay: 0, + distance: 0, + max: 100, + min: 0, + orientation: 'horizontal', + range: false, + step: 1, + value: 0, + values: null + } +}); + +})(jQuery); +/* + * jQuery UI Tabs 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Tabs + * + * Depends: + * ui.core.js + */ +(function($) { + +$.widget("ui.tabs", { + + _init: function() { + if (this.options.deselectable !== undefined) { + this.options.collapsible = this.options.deselectable; + } + this._tabify(true); + }, + + _setData: function(key, value) { + if (key == 'selected') { + if (this.options.collapsible && value == this.options.selected) { + return; + } + this.select(value); + } + else { + this.options[key] = value; + if (key == 'deselectable') { + this.options.collapsible = value; + } + this._tabify(); + } + }, + + _tabId: function(a) { + return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '') || + this.options.idPrefix + $.data(a); + }, + + _sanitizeSelector: function(hash) { + return hash.replace(/:/g, '\\:'); // we need this because an id may contain a ":" + }, + + _cookie: function() { + var cookie = this.cookie || (this.cookie = this.options.cookie.name || 'ui-tabs-' + $.data(this.list[0])); + return $.cookie.apply(null, [cookie].concat($.makeArray(arguments))); + }, + + _ui: function(tab, panel) { + return { + tab: tab, + panel: panel, + index: this.anchors.index(tab) + }; + }, + + _cleanup: function() { + // restore all former loading tabs labels + this.lis.filter('.ui-state-processing').removeClass('ui-state-processing') + .find('span:data(label.tabs)') + .each(function() { + var el = $(this); + el.html(el.data('label.tabs')).removeData('label.tabs'); + }); + }, + + _tabify: function(init) { + + this.list = this.element.children('ul:first'); + this.lis = $('li:has(a[href])', this.list); + this.anchors = this.lis.map(function() { return $('a', this)[0]; }); + this.panels = $([]); + + var self = this, o = this.options; + + var fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash + this.anchors.each(function(i, a) { + var href = $(a).attr('href'); + + // For dynamically created HTML that contains a hash as href IE < 8 expands + // such href to the full page url with hash and then misinterprets tab as ajax. + // Same consideration applies for an added tab with a fragment identifier + // since a[href=#fragment-identifier] does unexpectedly not match. + // Thus normalize href attribute... + var hrefBase = href.split('#')[0], baseEl; + if (hrefBase && (hrefBase === location.toString().split('#')[0] || + (baseEl = $('base')[0]) && hrefBase === baseEl.href)) { + href = a.hash; + a.href = href; + } + + // inline tab + if (fragmentId.test(href)) { + self.panels = self.panels.add(self._sanitizeSelector(href)); + } + + // remote tab + else if (href != '#') { // prevent loading the page itself if href is just "#" + $.data(a, 'href.tabs', href); // required for restore on destroy + + // TODO until #3808 is fixed strip fragment identifier from url + // (IE fails to load from such url) + $.data(a, 'load.tabs', href.replace(/#.*$/, '')); // mutable data + + var id = self._tabId(a); + a.href = '#' + id; + var $panel = $('#' + id); + if (!$panel.length) { + $panel = $(o.panelTemplate).attr('id', id).addClass('ui-tabs-panel ui-widget-content ui-corner-bottom') + .insertAfter(self.panels[i - 1] || self.list); + $panel.data('destroy.tabs', true); + } + self.panels = self.panels.add($panel); + } + + // invalid tab href + else { + o.disabled.push(i); + } + }); + + // initialization from scratch + if (init) { + + // attach necessary classes for styling + this.element.addClass('ui-tabs ui-widget ui-widget-content ui-corner-all'); + this.list.addClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all'); + this.lis.addClass('ui-state-default ui-corner-top'); + this.panels.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom'); + + // Selected tab + // use "selected" option or try to retrieve: + // 1. from fragment identifier in url + // 2. from cookie + // 3. from selected class attribute on
  • + if (o.selected === undefined) { + if (location.hash) { + this.anchors.each(function(i, a) { + if (a.hash == location.hash) { + o.selected = i; + return false; // break + } + }); + } + if (typeof o.selected != 'number' && o.cookie) { + o.selected = parseInt(self._cookie(), 10); + } + if (typeof o.selected != 'number' && this.lis.filter('.ui-tabs-selected').length) { + o.selected = this.lis.index(this.lis.filter('.ui-tabs-selected')); + } + o.selected = o.selected || 0; + } + else if (o.selected === null) { // usage of null is deprecated, TODO remove in next release + o.selected = -1; + } + + // sanity check - default to first tab... + o.selected = ((o.selected >= 0 && this.anchors[o.selected]) || o.selected < 0) ? o.selected : 0; + + // Take disabling tabs via class attribute from HTML + // into account and update option properly. + // A selected tab cannot become disabled. + o.disabled = $.unique(o.disabled.concat( + $.map(this.lis.filter('.ui-state-disabled'), + function(n, i) { return self.lis.index(n); } ) + )).sort(); + + if ($.inArray(o.selected, o.disabled) != -1) { + o.disabled.splice($.inArray(o.selected, o.disabled), 1); + } + + // highlight selected tab + this.panels.addClass('ui-tabs-hide'); + this.lis.removeClass('ui-tabs-selected ui-state-active'); + if (o.selected >= 0 && this.anchors.length) { // check for length avoids error when initializing empty list + this.panels.eq(o.selected).removeClass('ui-tabs-hide'); + this.lis.eq(o.selected).addClass('ui-tabs-selected ui-state-active'); + + // seems to be expected behavior that the show callback is fired + self.element.queue("tabs", function() { + self._trigger('show', null, self._ui(self.anchors[o.selected], self.panels[o.selected])); + }); + + this.load(o.selected); + } + + // clean up to avoid memory leaks in certain versions of IE 6 + $(window).bind('unload', function() { + self.lis.add(self.anchors).unbind('.tabs'); + self.lis = self.anchors = self.panels = null; + }); + + } + // update selected after add/remove + else { + o.selected = this.lis.index(this.lis.filter('.ui-tabs-selected')); + } + + // update collapsible + this.element[o.collapsible ? 'addClass' : 'removeClass']('ui-tabs-collapsible'); + + // set or update cookie after init and add/remove respectively + if (o.cookie) { + this._cookie(o.selected, o.cookie); + } + + // disable tabs + for (var i = 0, li; (li = this.lis[i]); i++) { + $(li)[$.inArray(i, o.disabled) != -1 && + !$(li).hasClass('ui-tabs-selected') ? 'addClass' : 'removeClass']('ui-state-disabled'); + } + + // reset cache if switching from cached to not cached + if (o.cache === false) { + this.anchors.removeData('cache.tabs'); + } + + // remove all handlers before, tabify may run on existing tabs after add or option change + this.lis.add(this.anchors).unbind('.tabs'); + + if (o.event != 'mouseover') { + var addState = function(state, el) { + if (el.is(':not(.ui-state-disabled)')) { + el.addClass('ui-state-' + state); + } + }; + var removeState = function(state, el) { + el.removeClass('ui-state-' + state); + }; + this.lis.bind('mouseover.tabs', function() { + addState('hover', $(this)); + }); + this.lis.bind('mouseout.tabs', function() { + removeState('hover', $(this)); + }); + this.anchors.bind('focus.tabs', function() { + addState('focus', $(this).closest('li')); + }); + this.anchors.bind('blur.tabs', function() { + removeState('focus', $(this).closest('li')); + }); + } + + // set up animations + var hideFx, showFx; + if (o.fx) { + if ($.isArray(o.fx)) { + hideFx = o.fx[0]; + showFx = o.fx[1]; + } + else { + hideFx = showFx = o.fx; + } + } + + // Reset certain styles left over from animation + // and prevent IE's ClearType bug... + function resetStyle($el, fx) { + $el.css({ display: '' }); + if ($.browser.msie && fx.opacity) { + $el[0].style.removeAttribute('filter'); + } + } + + // Show a tab... + var showTab = showFx ? + function(clicked, $show) { + $(clicked).closest('li').removeClass('ui-state-default').addClass('ui-tabs-selected ui-state-active'); + $show.hide().removeClass('ui-tabs-hide') // avoid flicker that way + .animate(showFx, showFx.duration || 'normal', function() { + resetStyle($show, showFx); + self._trigger('show', null, self._ui(clicked, $show[0])); + }); + } : + function(clicked, $show) { + $(clicked).closest('li').removeClass('ui-state-default').addClass('ui-tabs-selected ui-state-active'); + $show.removeClass('ui-tabs-hide'); + self._trigger('show', null, self._ui(clicked, $show[0])); + }; + + // Hide a tab, $show is optional... + var hideTab = hideFx ? + function(clicked, $hide) { + $hide.animate(hideFx, hideFx.duration || 'normal', function() { + self.lis.removeClass('ui-tabs-selected ui-state-active').addClass('ui-state-default'); + $hide.addClass('ui-tabs-hide'); + resetStyle($hide, hideFx); + self.element.dequeue("tabs"); + }); + } : + function(clicked, $hide, $show) { + self.lis.removeClass('ui-tabs-selected ui-state-active').addClass('ui-state-default'); + $hide.addClass('ui-tabs-hide'); + self.element.dequeue("tabs"); + }; + + // attach tab event handler, unbind to avoid duplicates from former tabifying... + this.anchors.bind(o.event + '.tabs', function() { + var el = this, $li = $(this).closest('li'), $hide = self.panels.filter(':not(.ui-tabs-hide)'), + $show = $(self._sanitizeSelector(this.hash)); + + // If tab is already selected and not collapsible or tab disabled or + // or is already loading or click callback returns false stop here. + // Check if click handler returns false last so that it is not executed + // for a disabled or loading tab! + if (($li.hasClass('ui-tabs-selected') && !o.collapsible) || + $li.hasClass('ui-state-disabled') || + $li.hasClass('ui-state-processing') || + self._trigger('select', null, self._ui(this, $show[0])) === false) { + this.blur(); + return false; + } + + o.selected = self.anchors.index(this); + + self.abort(); + + // if tab may be closed + if (o.collapsible) { + if ($li.hasClass('ui-tabs-selected')) { + o.selected = -1; + + if (o.cookie) { + self._cookie(o.selected, o.cookie); + } + + self.element.queue("tabs", function() { + hideTab(el, $hide); + }).dequeue("tabs"); + + this.blur(); + return false; + } + else if (!$hide.length) { + if (o.cookie) { + self._cookie(o.selected, o.cookie); + } + + self.element.queue("tabs", function() { + showTab(el, $show); + }); + + self.load(self.anchors.index(this)); // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171 + + this.blur(); + return false; + } + } + + if (o.cookie) { + self._cookie(o.selected, o.cookie); + } + + // show new tab + if ($show.length) { + if ($hide.length) { + self.element.queue("tabs", function() { + hideTab(el, $hide); + }); + } + self.element.queue("tabs", function() { + showTab(el, $show); + }); + + self.load(self.anchors.index(this)); + } + else { + throw 'jQuery UI Tabs: Mismatching fragment identifier.'; + } + + // Prevent IE from keeping other link focussed when using the back button + // and remove dotted border from clicked link. This is controlled via CSS + // in modern browsers; blur() removes focus from address bar in Firefox + // which can become a usability and annoying problem with tabs('rotate'). + if ($.browser.msie) { + this.blur(); + } + + }); + + // disable click in any case + this.anchors.bind('click.tabs', function(){return false;}); + + }, + + destroy: function() { + var o = this.options; + + this.abort(); + + this.element.unbind('.tabs') + .removeClass('ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible') + .removeData('tabs'); + + this.list.removeClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all'); + + this.anchors.each(function() { + var href = $.data(this, 'href.tabs'); + if (href) { + this.href = href; + } + var $this = $(this).unbind('.tabs'); + $.each(['href', 'load', 'cache'], function(i, prefix) { + $this.removeData(prefix + '.tabs'); + }); + }); + + this.lis.unbind('.tabs').add(this.panels).each(function() { + if ($.data(this, 'destroy.tabs')) { + $(this).remove(); + } + else { + $(this).removeClass([ + 'ui-state-default', + 'ui-corner-top', + 'ui-tabs-selected', + 'ui-state-active', + 'ui-state-hover', + 'ui-state-focus', + 'ui-state-disabled', + 'ui-tabs-panel', + 'ui-widget-content', + 'ui-corner-bottom', + 'ui-tabs-hide' + ].join(' ')); + } + }); + + if (o.cookie) { + this._cookie(null, o.cookie); + } + }, + + add: function(url, label, index) { + if (index === undefined) { + index = this.anchors.length; // append by default + } + + var self = this, o = this.options, + $li = $(o.tabTemplate.replace(/#\{href\}/g, url).replace(/#\{label\}/g, label)), + id = !url.indexOf('#') ? url.replace('#', '') : this._tabId($('a', $li)[0]); + + $li.addClass('ui-state-default ui-corner-top').data('destroy.tabs', true); + + // try to find an existing element before creating a new one + var $panel = $('#' + id); + if (!$panel.length) { + $panel = $(o.panelTemplate).attr('id', id).data('destroy.tabs', true); + } + $panel.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide'); + + if (index >= this.lis.length) { + $li.appendTo(this.list); + $panel.appendTo(this.list[0].parentNode); + } + else { + $li.insertBefore(this.lis[index]); + $panel.insertBefore(this.panels[index]); + } + + o.disabled = $.map(o.disabled, + function(n, i) { return n >= index ? ++n : n; }); + + this._tabify(); + + if (this.anchors.length == 1) { // after tabify + $li.addClass('ui-tabs-selected ui-state-active'); + $panel.removeClass('ui-tabs-hide'); + this.element.queue("tabs", function() { + self._trigger('show', null, self._ui(self.anchors[0], self.panels[0])); + }); + + this.load(0); + } + + // callback + this._trigger('add', null, this._ui(this.anchors[index], this.panels[index])); + }, + + remove: function(index) { + var o = this.options, $li = this.lis.eq(index).remove(), + $panel = this.panels.eq(index).remove(); + + // If selected tab was removed focus tab to the right or + // in case the last tab was removed the tab to the left. + if ($li.hasClass('ui-tabs-selected') && this.anchors.length > 1) { + this.select(index + (index + 1 < this.anchors.length ? 1 : -1)); + } + + o.disabled = $.map($.grep(o.disabled, function(n, i) { return n != index; }), + function(n, i) { return n >= index ? --n : n; }); + + this._tabify(); + + // callback + this._trigger('remove', null, this._ui($li.find('a')[0], $panel[0])); + }, + + enable: function(index) { + var o = this.options; + if ($.inArray(index, o.disabled) == -1) { + return; + } + + this.lis.eq(index).removeClass('ui-state-disabled'); + o.disabled = $.grep(o.disabled, function(n, i) { return n != index; }); + + // callback + this._trigger('enable', null, this._ui(this.anchors[index], this.panels[index])); + }, + + disable: function(index) { + var self = this, o = this.options; + if (index != o.selected) { // cannot disable already selected tab + this.lis.eq(index).addClass('ui-state-disabled'); + + o.disabled.push(index); + o.disabled.sort(); + + // callback + this._trigger('disable', null, this._ui(this.anchors[index], this.panels[index])); + } + }, + + select: function(index) { + if (typeof index == 'string') { + index = this.anchors.index(this.anchors.filter('[href$=' + index + ']')); + } + else if (index === null) { // usage of null is deprecated, TODO remove in next release + index = -1; + } + if (index == -1 && this.options.collapsible) { + index = this.options.selected; + } + + this.anchors.eq(index).trigger(this.options.event + '.tabs'); + }, + + load: function(index) { + var self = this, o = this.options, a = this.anchors.eq(index)[0], url = $.data(a, 'load.tabs'); + + this.abort(); + + // not remote or from cache + if (!url || this.element.queue("tabs").length !== 0 && $.data(a, 'cache.tabs')) { + this.element.dequeue("tabs"); + return; + } + + // load remote from here on + this.lis.eq(index).addClass('ui-state-processing'); + + if (o.spinner) { + var span = $('span', a); + span.data('label.tabs', span.html()).html(o.spinner); + } + + this.xhr = $.ajax($.extend({}, o.ajaxOptions, { + url: url, + success: function(r, s) { + $(self._sanitizeSelector(a.hash)).html(r); + + // take care of tab labels + self._cleanup(); + + if (o.cache) { + $.data(a, 'cache.tabs', true); // if loaded once do not load them again + } + + // callbacks + self._trigger('load', null, self._ui(self.anchors[index], self.panels[index])); + try { + o.ajaxOptions.success(r, s); + } + catch (e) {} + + // last, so that load event is fired before show... + self.element.dequeue("tabs"); + } + })); + }, + + abort: function() { + // stop possibly running animations + this.element.queue([]); + this.panels.stop(false, true); + + // terminate pending requests from other tabs + if (this.xhr) { + this.xhr.abort(); + delete this.xhr; + } + + // take care of tab labels + this._cleanup(); + + }, + + url: function(index, url) { + this.anchors.eq(index).removeData('cache.tabs').data('load.tabs', url); + }, + + length: function() { + return this.anchors.length; + } + +}); + +$.extend($.ui.tabs, { + version: '1.7.2', + getter: 'length', + defaults: { + ajaxOptions: null, + cache: false, + cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true } + collapsible: false, + disabled: [], + event: 'click', + fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 } + idPrefix: 'ui-tabs-', + panelTemplate: '
    ', + spinner: 'Loading…', + tabTemplate: '
  • #{label}
  • ' + } +}); + +/* + * Tabs Extensions + */ + +/* + * Rotate + */ +$.extend($.ui.tabs.prototype, { + rotation: null, + rotate: function(ms, continuing) { + + var self = this, o = this.options; + + var rotate = self._rotate || (self._rotate = function(e) { + clearTimeout(self.rotation); + self.rotation = setTimeout(function() { + var t = o.selected; + self.select( ++t < self.anchors.length ? t : 0 ); + }, ms); + + if (e) { + e.stopPropagation(); + } + }); + + var stop = self._unrotate || (self._unrotate = !continuing ? + function(e) { + if (e.clientX) { // in case of a true click + self.rotate(null); + } + } : + function(e) { + t = o.selected; + rotate(); + }); + + // start rotation + if (ms) { + this.element.bind('tabsshow', rotate); + this.anchors.bind(o.event + '.tabs', stop); + rotate(); + } + // stop rotation + else { + clearTimeout(self.rotation); + this.element.unbind('tabsshow', rotate); + this.anchors.unbind(o.event + '.tabs', stop); + delete this._rotate; + delete this._unrotate; + } + } +}); + +})(jQuery); +/* + * jQuery UI Datepicker 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Datepicker + * + * Depends: + * ui.core.js + */ + +(function($) { // hide the namespace + +$.extend($.ui, { datepicker: { version: "1.7.2" } }); + +var PROP_NAME = 'datepicker'; + +/* Date picker manager. + Use the singleton instance of this class, $.datepicker, to interact with the date picker. + Settings for (groups of) date pickers are maintained in an instance object, + allowing multiple different settings on the same page. */ + +function Datepicker() { + this.debug = false; // Change this to true to start debugging + this._curInst = null; // The current instance in use + this._keyEvent = false; // If the last event was a key event + this._disabledInputs = []; // List of date picker inputs that have been disabled + this._datepickerShowing = false; // True if the popup picker is showing , false if not + this._inDialog = false; // True if showing within a "dialog", false if not + this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division + this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class + this._appendClass = 'ui-datepicker-append'; // The name of the append marker class + this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class + this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class + this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class + this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class + this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class + this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class + this.regional = []; // Available regional settings, indexed by language code + this.regional[''] = { // Default regional settings + closeText: 'Done', // Display text for close link + prevText: 'Prev', // Display text for previous month link + nextText: 'Next', // Display text for next month link + currentText: 'Today', // Display text for current month link + monthNames: ['January','February','March','April','May','June', + 'July','August','September','October','November','December'], // Names of months for drop-down and formatting + monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting + dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting + dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting + dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday + dateFormat: 'mm/dd/yy', // See format options on parseDate + firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... + isRTL: false // True if right-to-left language, false if left-to-right + }; + this._defaults = { // Global defaults for all the date picker instances + showOn: 'focus', // 'focus' for popup on focus, + // 'button' for trigger button, or 'both' for either + showAnim: 'show', // Name of jQuery animation for popup + showOptions: {}, // Options for enhanced animations + defaultDate: null, // Used when field is blank: actual date, + // +/-number for offset from today, null for today + appendText: '', // Display text following the input box, e.g. showing the format + buttonText: '...', // Text for trigger button + buttonImage: '', // URL for trigger button image + buttonImageOnly: false, // True if the image appears alone, false if it appears on a button + hideIfNoPrevNext: false, // True to hide next/previous month links + // if not applicable, false to just disable them + navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links + gotoCurrent: false, // True if today link goes back to current selection instead + changeMonth: false, // True if month can be selected directly, false if only prev/next + changeYear: false, // True if year can be selected directly, false if only prev/next + showMonthAfterYear: false, // True if the year select precedes month, false for month then year + yearRange: '-10:+10', // Range of years to display in drop-down, + // either relative to current year (-nn:+nn) or absolute (nnnn:nnnn) + showOtherMonths: false, // True to show dates in other months, false to leave blank + calculateWeek: this.iso8601Week, // How to calculate the week of the year, + // takes a Date and returns the number of the week for it + shortYearCutoff: '+10', // Short year values < this are in the current century, + // > this are in the previous century, + // string value starting with '+' for current year + value + minDate: null, // The earliest selectable date, or null for no limit + maxDate: null, // The latest selectable date, or null for no limit + duration: 'normal', // Duration of display/closure + beforeShowDay: null, // Function that takes a date and returns an array with + // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '', + // [2] = cell title (optional), e.g. $.datepicker.noWeekends + beforeShow: null, // Function that takes an input field and + // returns a set of custom settings for the date picker + onSelect: null, // Define a callback function when a date is selected + onChangeMonthYear: null, // Define a callback function when the month or year is changed + onClose: null, // Define a callback function when the datepicker is closed + numberOfMonths: 1, // Number of months to show at a time + showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) + stepMonths: 1, // Number of months to step back/forward + stepBigMonths: 12, // Number of months to step back/forward for the big links + altField: '', // Selector for an alternate field to store selected dates into + altFormat: '', // The date format to use for the alternate field + constrainInput: true, // The input is constrained by the current date format + showButtonPanel: false // True to show button panel, false to not show it + }; + $.extend(this._defaults, this.regional['']); + this.dpDiv = $('
    '); +} + +$.extend(Datepicker.prototype, { + /* Class name added to elements to indicate already configured with a date picker. */ + markerClassName: 'hasDatepicker', + + /* Debug logging (if enabled). */ + log: function () { + if (this.debug) + console.log.apply('', arguments); + }, + + /* Override the default settings for all instances of the date picker. + @param settings object - the new settings to use as defaults (anonymous object) + @return the manager object */ + setDefaults: function(settings) { + extendRemove(this._defaults, settings || {}); + return this; + }, + + /* Attach the date picker to a jQuery selection. + @param target element - the target input field or division or span + @param settings object - the new settings to use for this date picker instance (anonymous) */ + _attachDatepicker: function(target, settings) { + // check for settings on the control itself - in namespace 'date:' + var inlineSettings = null; + for (var attrName in this._defaults) { + var attrValue = target.getAttribute('date:' + attrName); + if (attrValue) { + inlineSettings = inlineSettings || {}; + try { + inlineSettings[attrName] = eval(attrValue); + } catch (err) { + inlineSettings[attrName] = attrValue; + } + } + } + var nodeName = target.nodeName.toLowerCase(); + var inline = (nodeName == 'div' || nodeName == 'span'); + if (!target.id) + target.id = 'dp' + (++this.uuid); + var inst = this._newInst($(target), inline); + inst.settings = $.extend({}, settings || {}, inlineSettings || {}); + if (nodeName == 'input') { + this._connectDatepicker(target, inst); + } else if (inline) { + this._inlineDatepicker(target, inst); + } + }, + + /* Create a new instance object. */ + _newInst: function(target, inline) { + var id = target[0].id.replace(/([:\[\]\.])/g, '\\\\$1'); // escape jQuery meta chars + return {id: id, input: target, // associated target + selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection + drawMonth: 0, drawYear: 0, // month being drawn + inline: inline, // is datepicker inline or not + dpDiv: (!inline ? this.dpDiv : // presentation div + $('
    '))}; + }, + + /* Attach the date picker to an input field. */ + _connectDatepicker: function(target, inst) { + var input = $(target); + inst.append = $([]); + inst.trigger = $([]); + if (input.hasClass(this.markerClassName)) + return; + var appendText = this._get(inst, 'appendText'); + var isRTL = this._get(inst, 'isRTL'); + if (appendText) { + inst.append = $('' + appendText + ''); + input[isRTL ? 'before' : 'after'](inst.append); + } + var showOn = this._get(inst, 'showOn'); + if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field + input.focus(this._showDatepicker); + if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked + var buttonText = this._get(inst, 'buttonText'); + var buttonImage = this._get(inst, 'buttonImage'); + inst.trigger = $(this._get(inst, 'buttonImageOnly') ? + $('').addClass(this._triggerClass). + attr({ src: buttonImage, alt: buttonText, title: buttonText }) : + $('').addClass(this._triggerClass). + html(buttonImage == '' ? buttonText : $('').attr( + { src:buttonImage, alt:buttonText, title:buttonText }))); + input[isRTL ? 'before' : 'after'](inst.trigger); + inst.trigger.click(function() { + if ($.datepicker._datepickerShowing && $.datepicker._lastInput == target) + $.datepicker._hideDatepicker(); + else + $.datepicker._showDatepicker(target); + return false; + }); + } + input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress). + bind("setData.datepicker", function(event, key, value) { + inst.settings[key] = value; + }).bind("getData.datepicker", function(event, key) { + return this._get(inst, key); + }); + $.data(target, PROP_NAME, inst); + }, + + /* Attach an inline date picker to a div. */ + _inlineDatepicker: function(target, inst) { + var divSpan = $(target); + if (divSpan.hasClass(this.markerClassName)) + return; + divSpan.addClass(this.markerClassName).append(inst.dpDiv). + bind("setData.datepicker", function(event, key, value){ + inst.settings[key] = value; + }).bind("getData.datepicker", function(event, key){ + return this._get(inst, key); + }); + $.data(target, PROP_NAME, inst); + this._setDate(inst, this._getDefaultDate(inst)); + this._updateDatepicker(inst); + this._updateAlternate(inst); + }, + + /* Pop-up the date picker in a "dialog" box. + @param input element - ignored + @param dateText string - the initial date to display (in the current format) + @param onSelect function - the function(dateText) to call when a date is selected + @param settings object - update the dialog date picker instance's settings (anonymous object) + @param pos int[2] - coordinates for the dialog's position within the screen or + event - with x/y coordinates or + leave empty for default (screen centre) + @return the manager object */ + _dialogDatepicker: function(input, dateText, onSelect, settings, pos) { + var inst = this._dialogInst; // internal instance + if (!inst) { + var id = 'dp' + (++this.uuid); + this._dialogInput = $(''); + this._dialogInput.keydown(this._doKeyDown); + $('body').append(this._dialogInput); + inst = this._dialogInst = this._newInst(this._dialogInput, false); + inst.settings = {}; + $.data(this._dialogInput[0], PROP_NAME, inst); + } + extendRemove(inst.settings, settings || {}); + this._dialogInput.val(dateText); + + this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); + if (!this._pos) { + var browserWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; + var browserHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; + var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; + var scrollY = document.documentElement.scrollTop || document.body.scrollTop; + this._pos = // should use actual width/height below + [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; + } + + // move input on screen for focus, but hidden behind dialog + this._dialogInput.css('left', this._pos[0] + 'px').css('top', this._pos[1] + 'px'); + inst.settings.onSelect = onSelect; + this._inDialog = true; + this.dpDiv.addClass(this._dialogClass); + this._showDatepicker(this._dialogInput[0]); + if ($.blockUI) + $.blockUI(this.dpDiv); + $.data(this._dialogInput[0], PROP_NAME, inst); + return this; + }, + + /* Detach a datepicker from its control. + @param target element - the target input field or division or span */ + _destroyDatepicker: function(target) { + var $target = $(target); + var inst = $.data(target, PROP_NAME); + if (!$target.hasClass(this.markerClassName)) { + return; + } + var nodeName = target.nodeName.toLowerCase(); + $.removeData(target, PROP_NAME); + if (nodeName == 'input') { + inst.append.remove(); + inst.trigger.remove(); + $target.removeClass(this.markerClassName). + unbind('focus', this._showDatepicker). + unbind('keydown', this._doKeyDown). + unbind('keypress', this._doKeyPress); + } else if (nodeName == 'div' || nodeName == 'span') + $target.removeClass(this.markerClassName).empty(); + }, + + /* Enable the date picker to a jQuery selection. + @param target element - the target input field or division or span */ + _enableDatepicker: function(target) { + var $target = $(target); + var inst = $.data(target, PROP_NAME); + if (!$target.hasClass(this.markerClassName)) { + return; + } + var nodeName = target.nodeName.toLowerCase(); + if (nodeName == 'input') { + target.disabled = false; + inst.trigger.filter('button'). + each(function() { this.disabled = false; }).end(). + filter('img').css({opacity: '1.0', cursor: ''}); + } + else if (nodeName == 'div' || nodeName == 'span') { + var inline = $target.children('.' + this._inlineClass); + inline.children().removeClass('ui-state-disabled'); + } + this._disabledInputs = $.map(this._disabledInputs, + function(value) { return (value == target ? null : value); }); // delete entry + }, + + /* Disable the date picker to a jQuery selection. + @param target element - the target input field or division or span */ + _disableDatepicker: function(target) { + var $target = $(target); + var inst = $.data(target, PROP_NAME); + if (!$target.hasClass(this.markerClassName)) { + return; + } + var nodeName = target.nodeName.toLowerCase(); + if (nodeName == 'input') { + target.disabled = true; + inst.trigger.filter('button'). + each(function() { this.disabled = true; }).end(). + filter('img').css({opacity: '0.5', cursor: 'default'}); + } + else if (nodeName == 'div' || nodeName == 'span') { + var inline = $target.children('.' + this._inlineClass); + inline.children().addClass('ui-state-disabled'); + } + this._disabledInputs = $.map(this._disabledInputs, + function(value) { return (value == target ? null : value); }); // delete entry + this._disabledInputs[this._disabledInputs.length] = target; + }, + + /* Is the first field in a jQuery collection disabled as a datepicker? + @param target element - the target input field or division or span + @return boolean - true if disabled, false if enabled */ + _isDisabledDatepicker: function(target) { + if (!target) { + return false; + } + for (var i = 0; i < this._disabledInputs.length; i++) { + if (this._disabledInputs[i] == target) + return true; + } + return false; + }, + + /* Retrieve the instance data for the target control. + @param target element - the target input field or division or span + @return object - the associated instance data + @throws error if a jQuery problem getting data */ + _getInst: function(target) { + try { + return $.data(target, PROP_NAME); + } + catch (err) { + throw 'Missing instance data for this datepicker'; + } + }, + + /* Update or retrieve the settings for a date picker attached to an input field or division. + @param target element - the target input field or division or span + @param name object - the new settings to update or + string - the name of the setting to change or retrieve, + when retrieving also 'all' for all instance settings or + 'defaults' for all global defaults + @param value any - the new value for the setting + (omit if above is an object or to retrieve a value) */ + _optionDatepicker: function(target, name, value) { + var inst = this._getInst(target); + if (arguments.length == 2 && typeof name == 'string') { + return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) : + (inst ? (name == 'all' ? $.extend({}, inst.settings) : + this._get(inst, name)) : null)); + } + var settings = name || {}; + if (typeof name == 'string') { + settings = {}; + settings[name] = value; + } + if (inst) { + if (this._curInst == inst) { + this._hideDatepicker(null); + } + var date = this._getDateDatepicker(target); + extendRemove(inst.settings, settings); + this._setDateDatepicker(target, date); + this._updateDatepicker(inst); + } + }, + + // change method deprecated + _changeDatepicker: function(target, name, value) { + this._optionDatepicker(target, name, value); + }, + + /* Redraw the date picker attached to an input field or division. + @param target element - the target input field or division or span */ + _refreshDatepicker: function(target) { + var inst = this._getInst(target); + if (inst) { + this._updateDatepicker(inst); + } + }, + + /* Set the dates for a jQuery selection. + @param target element - the target input field or division or span + @param date Date - the new date + @param endDate Date - the new end date for a range (optional) */ + _setDateDatepicker: function(target, date, endDate) { + var inst = this._getInst(target); + if (inst) { + this._setDate(inst, date, endDate); + this._updateDatepicker(inst); + this._updateAlternate(inst); + } + }, + + /* Get the date(s) for the first entry in a jQuery selection. + @param target element - the target input field or division or span + @return Date - the current date or + Date[2] - the current dates for a range */ + _getDateDatepicker: function(target) { + var inst = this._getInst(target); + if (inst && !inst.inline) + this._setDateFromField(inst); + return (inst ? this._getDate(inst) : null); + }, + + /* Handle keystrokes. */ + _doKeyDown: function(event) { + var inst = $.datepicker._getInst(event.target); + var handled = true; + var isRTL = inst.dpDiv.is('.ui-datepicker-rtl'); + inst._keyEvent = true; + if ($.datepicker._datepickerShowing) + switch (event.keyCode) { + case 9: $.datepicker._hideDatepicker(null, ''); + break; // hide on tab out + case 13: var sel = $('td.' + $.datepicker._dayOverClass + + ', td.' + $.datepicker._currentClass, inst.dpDiv); + if (sel[0]) + $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); + else + $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration')); + return false; // don't submit the form + break; // select the value on enter + case 27: $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration')); + break; // hide on escape + case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? + -$.datepicker._get(inst, 'stepBigMonths') : + -$.datepicker._get(inst, 'stepMonths')), 'M'); + break; // previous month/year on page up/+ ctrl + case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? + +$.datepicker._get(inst, 'stepBigMonths') : + +$.datepicker._get(inst, 'stepMonths')), 'M'); + break; // next month/year on page down/+ ctrl + case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target); + handled = event.ctrlKey || event.metaKey; + break; // clear on ctrl or command +end + case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target); + handled = event.ctrlKey || event.metaKey; + break; // current on ctrl or command +home + case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D'); + handled = event.ctrlKey || event.metaKey; + // -1 day on ctrl or command +left + if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? + -$.datepicker._get(inst, 'stepBigMonths') : + -$.datepicker._get(inst, 'stepMonths')), 'M'); + // next month/year on alt +left on Mac + break; + case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D'); + handled = event.ctrlKey || event.metaKey; + break; // -1 week on ctrl or command +up + case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D'); + handled = event.ctrlKey || event.metaKey; + // +1 day on ctrl or command +right + if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? + +$.datepicker._get(inst, 'stepBigMonths') : + +$.datepicker._get(inst, 'stepMonths')), 'M'); + // next month/year on alt +right + break; + case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D'); + handled = event.ctrlKey || event.metaKey; + break; // +1 week on ctrl or command +down + default: handled = false; + } + else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home + $.datepicker._showDatepicker(this); + else { + handled = false; + } + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } + }, + + /* Filter entered characters - based on date format. */ + _doKeyPress: function(event) { + var inst = $.datepicker._getInst(event.target); + if ($.datepicker._get(inst, 'constrainInput')) { + var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')); + var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode); + return event.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1); + } + }, + + /* Pop-up the date picker for a given input field. + @param input element - the input field attached to the date picker or + event - if triggered by focus */ + _showDatepicker: function(input) { + input = input.target || input; + if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger + input = $('input', input.parentNode)[0]; + if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here + return; + var inst = $.datepicker._getInst(input); + var beforeShow = $.datepicker._get(inst, 'beforeShow'); + extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {})); + $.datepicker._hideDatepicker(null, ''); + $.datepicker._lastInput = input; + $.datepicker._setDateFromField(inst); + if ($.datepicker._inDialog) // hide cursor + input.value = ''; + if (!$.datepicker._pos) { // position below input + $.datepicker._pos = $.datepicker._findPos(input); + $.datepicker._pos[1] += input.offsetHeight; // add the height + } + var isFixed = false; + $(input).parents().each(function() { + isFixed |= $(this).css('position') == 'fixed'; + return !isFixed; + }); + if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled + $.datepicker._pos[0] -= document.documentElement.scrollLeft; + $.datepicker._pos[1] -= document.documentElement.scrollTop; + } + var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; + $.datepicker._pos = null; + inst.rangeStart = null; + // determine sizing offscreen + inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'}); + $.datepicker._updateDatepicker(inst); + // fix width for dynamic number of date pickers + // and adjust position before showing + offset = $.datepicker._checkOffset(inst, offset, isFixed); + inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? + 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none', + left: offset.left + 'px', top: offset.top + 'px'}); + if (!inst.inline) { + var showAnim = $.datepicker._get(inst, 'showAnim') || 'show'; + var duration = $.datepicker._get(inst, 'duration'); + var postProcess = function() { + $.datepicker._datepickerShowing = true; + if ($.browser.msie && parseInt($.browser.version,10) < 7) // fix IE < 7 select problems + $('iframe.ui-datepicker-cover').css({width: inst.dpDiv.width() + 4, + height: inst.dpDiv.height() + 4}); + }; + if ($.effects && $.effects[showAnim]) + inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess); + else + inst.dpDiv[showAnim](duration, postProcess); + if (duration == '') + postProcess(); + if (inst.input[0].type != 'hidden') + inst.input[0].focus(); + $.datepicker._curInst = inst; + } + }, + + /* Generate the date picker content. */ + _updateDatepicker: function(inst) { + var dims = {width: inst.dpDiv.width() + 4, + height: inst.dpDiv.height() + 4}; + var self = this; + inst.dpDiv.empty().append(this._generateHTML(inst)) + .find('iframe.ui-datepicker-cover'). + css({width: dims.width, height: dims.height}) + .end() + .find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a') + .bind('mouseout', function(){ + $(this).removeClass('ui-state-hover'); + if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover'); + if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover'); + }) + .bind('mouseover', function(){ + if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) { + $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover'); + $(this).addClass('ui-state-hover'); + if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover'); + if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover'); + } + }) + .end() + .find('.' + this._dayOverClass + ' a') + .trigger('mouseover') + .end(); + var numMonths = this._getNumberOfMonths(inst); + var cols = numMonths[1]; + var width = 17; + if (cols > 1) { + inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em'); + } else { + inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width(''); + } + inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') + + 'Class']('ui-datepicker-multi'); + inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') + + 'Class']('ui-datepicker-rtl'); + if (inst.input && inst.input[0].type != 'hidden' && inst == $.datepicker._curInst) + $(inst.input[0]).focus(); + }, + + /* Check positioning to remain on screen. */ + _checkOffset: function(inst, offset, isFixed) { + var dpWidth = inst.dpDiv.outerWidth(); + var dpHeight = inst.dpDiv.outerHeight(); + var inputWidth = inst.input ? inst.input.outerWidth() : 0; + var inputHeight = inst.input ? inst.input.outerHeight() : 0; + var viewWidth = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) + $(document).scrollLeft(); + var viewHeight = (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) + $(document).scrollTop(); + + offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0); + offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0; + offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; + + // now check if datepicker is showing outside window viewport - move to a better place if so. + offset.left -= (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? Math.abs(offset.left + dpWidth - viewWidth) : 0; + offset.top -= (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? Math.abs(offset.top + dpHeight + inputHeight*2 - viewHeight) : 0; + + return offset; + }, + + /* Find an object's position on the screen. */ + _findPos: function(obj) { + while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) { + obj = obj.nextSibling; + } + var position = $(obj).offset(); + return [position.left, position.top]; + }, + + /* Hide the date picker from view. + @param input element - the input field attached to the date picker + @param duration string - the duration over which to close the date picker */ + _hideDatepicker: function(input, duration) { + var inst = this._curInst; + if (!inst || (input && inst != $.data(input, PROP_NAME))) + return; + if (inst.stayOpen) + this._selectDate('#' + inst.id, this._formatDate(inst, + inst.currentDay, inst.currentMonth, inst.currentYear)); + inst.stayOpen = false; + if (this._datepickerShowing) { + duration = (duration != null ? duration : this._get(inst, 'duration')); + var showAnim = this._get(inst, 'showAnim'); + var postProcess = function() { + $.datepicker._tidyDialog(inst); + }; + if (duration != '' && $.effects && $.effects[showAnim]) + inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), + duration, postProcess); + else + inst.dpDiv[(duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' : + (showAnim == 'fadeIn' ? 'fadeOut' : 'hide')))](duration, postProcess); + if (duration == '') + this._tidyDialog(inst); + var onClose = this._get(inst, 'onClose'); + if (onClose) + onClose.apply((inst.input ? inst.input[0] : null), + [(inst.input ? inst.input.val() : ''), inst]); // trigger custom callback + this._datepickerShowing = false; + this._lastInput = null; + if (this._inDialog) { + this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' }); + if ($.blockUI) { + $.unblockUI(); + $('body').append(this.dpDiv); + } + } + this._inDialog = false; + } + this._curInst = null; + }, + + /* Tidy up after a dialog display. */ + _tidyDialog: function(inst) { + inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar'); + }, + + /* Close date picker if clicked elsewhere. */ + _checkExternalClick: function(event) { + if (!$.datepicker._curInst) + return; + var $target = $(event.target); + if (($target.parents('#' + $.datepicker._mainDivId).length == 0) && + !$target.hasClass($.datepicker.markerClassName) && + !$target.hasClass($.datepicker._triggerClass) && + $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI)) + $.datepicker._hideDatepicker(null, ''); + }, + + /* Adjust one of the date sub-fields. */ + _adjustDate: function(id, offset, period) { + var target = $(id); + var inst = this._getInst(target[0]); + if (this._isDisabledDatepicker(target[0])) { + return; + } + this._adjustInstDate(inst, offset + + (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning + period); + this._updateDatepicker(inst); + }, + + /* Action for current link. */ + _gotoToday: function(id) { + var target = $(id); + var inst = this._getInst(target[0]); + if (this._get(inst, 'gotoCurrent') && inst.currentDay) { + inst.selectedDay = inst.currentDay; + inst.drawMonth = inst.selectedMonth = inst.currentMonth; + inst.drawYear = inst.selectedYear = inst.currentYear; + } + else { + var date = new Date(); + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + } + this._notifyChange(inst); + this._adjustDate(target); + }, + + /* Action for selecting a new month/year. */ + _selectMonthYear: function(id, select, period) { + var target = $(id); + var inst = this._getInst(target[0]); + inst._selectingMonthYear = false; + inst['selected' + (period == 'M' ? 'Month' : 'Year')] = + inst['draw' + (period == 'M' ? 'Month' : 'Year')] = + parseInt(select.options[select.selectedIndex].value,10); + this._notifyChange(inst); + this._adjustDate(target); + }, + + /* Restore input focus after not changing month/year. */ + _clickMonthYear: function(id) { + var target = $(id); + var inst = this._getInst(target[0]); + if (inst.input && inst._selectingMonthYear && !$.browser.msie) + inst.input[0].focus(); + inst._selectingMonthYear = !inst._selectingMonthYear; + }, + + /* Action for selecting a day. */ + _selectDay: function(id, month, year, td) { + var target = $(id); + if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { + return; + } + var inst = this._getInst(target[0]); + inst.selectedDay = inst.currentDay = $('a', td).html(); + inst.selectedMonth = inst.currentMonth = month; + inst.selectedYear = inst.currentYear = year; + if (inst.stayOpen) { + inst.endDay = inst.endMonth = inst.endYear = null; + } + this._selectDate(id, this._formatDate(inst, + inst.currentDay, inst.currentMonth, inst.currentYear)); + if (inst.stayOpen) { + inst.rangeStart = this._daylightSavingAdjust( + new Date(inst.currentYear, inst.currentMonth, inst.currentDay)); + this._updateDatepicker(inst); + } + }, + + /* Erase the input field and hide the date picker. */ + _clearDate: function(id) { + var target = $(id); + var inst = this._getInst(target[0]); + inst.stayOpen = false; + inst.endDay = inst.endMonth = inst.endYear = inst.rangeStart = null; + this._selectDate(target, ''); + }, + + /* Update the input field with the selected date. */ + _selectDate: function(id, dateStr) { + var target = $(id); + var inst = this._getInst(target[0]); + dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); + if (inst.input) + inst.input.val(dateStr); + this._updateAlternate(inst); + var onSelect = this._get(inst, 'onSelect'); + if (onSelect) + onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback + else if (inst.input) + inst.input.trigger('change'); // fire the change event + if (inst.inline) + this._updateDatepicker(inst); + else if (!inst.stayOpen) { + this._hideDatepicker(null, this._get(inst, 'duration')); + this._lastInput = inst.input[0]; + if (typeof(inst.input[0]) != 'object') + inst.input[0].focus(); // restore focus + this._lastInput = null; + } + }, + + /* Update any alternate field to synchronise with the main field. */ + _updateAlternate: function(inst) { + var altField = this._get(inst, 'altField'); + if (altField) { // update alternate field too + var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat'); + var date = this._getDate(inst); + dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); + $(altField).each(function() { $(this).val(dateStr); }); + } + }, + + /* Set as beforeShowDay function to prevent selection of weekends. + @param date Date - the date to customise + @return [boolean, string] - is this date selectable?, what is its CSS class? */ + noWeekends: function(date) { + var day = date.getDay(); + return [(day > 0 && day < 6), '']; + }, + + /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. + @param date Date - the date to get the week for + @return number - the number of the week within the year that contains this date */ + iso8601Week: function(date) { + var checkDate = new Date(date.getFullYear(), date.getMonth(), date.getDate()); + var firstMon = new Date(checkDate.getFullYear(), 1 - 1, 4); // First week always contains 4 Jan + var firstDay = firstMon.getDay() || 7; // Day of week: Mon = 1, ..., Sun = 7 + firstMon.setDate(firstMon.getDate() + 1 - firstDay); // Preceding Monday + if (firstDay < 4 && checkDate < firstMon) { // Adjust first three days in year if necessary + checkDate.setDate(checkDate.getDate() - 3); // Generate for previous year + return $.datepicker.iso8601Week(checkDate); + } else if (checkDate > new Date(checkDate.getFullYear(), 12 - 1, 28)) { // Check last three days in year + firstDay = new Date(checkDate.getFullYear() + 1, 1 - 1, 4).getDay() || 7; + if (firstDay > 4 && (checkDate.getDay() || 7) < firstDay - 3) { // Adjust if necessary + return 1; + } + } + return Math.floor(((checkDate - firstMon) / 86400000) / 7) + 1; // Weeks to given date + }, + + /* Parse a string value into a date object. + See formatDate below for the possible formats. + + @param format string - the expected format of the date + @param value string - the date in the above format + @param settings Object - attributes include: + shortYearCutoff number - the cutoff year for determining the century (optional) + dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) + dayNames string[7] - names of the days from Sunday (optional) + monthNamesShort string[12] - abbreviated names of the months (optional) + monthNames string[12] - names of the months (optional) + @return Date - the extracted date value or null if value is blank */ + parseDate: function (format, value, settings) { + if (format == null || value == null) + throw 'Invalid arguments'; + value = (typeof value == 'object' ? value.toString() : value + ''); + if (value == '') + return null; + var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff; + var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; + var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; + var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; + var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; + var year = -1; + var month = -1; + var day = -1; + var doy = -1; + var literal = false; + // Check whether a format character is doubled + var lookAhead = function(match) { + var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); + if (matches) + iFormat++; + return matches; + }; + // Extract a number from the string value + var getNumber = function(match) { + lookAhead(match); + var origSize = (match == '@' ? 14 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2))); + var size = origSize; + var num = 0; + while (size > 0 && iValue < value.length && + value.charAt(iValue) >= '0' && value.charAt(iValue) <= '9') { + num = num * 10 + parseInt(value.charAt(iValue++),10); + size--; + } + if (size == origSize) + throw 'Missing number at position ' + iValue; + return num; + }; + // Extract a name from the string value and convert to an index + var getName = function(match, shortNames, longNames) { + var names = (lookAhead(match) ? longNames : shortNames); + var size = 0; + for (var j = 0; j < names.length; j++) + size = Math.max(size, names[j].length); + var name = ''; + var iInit = iValue; + while (size > 0 && iValue < value.length) { + name += value.charAt(iValue++); + for (var i = 0; i < names.length; i++) + if (name == names[i]) + return i + 1; + size--; + } + throw 'Unknown name at position ' + iInit; + }; + // Confirm that a literal character matches the string value + var checkLiteral = function() { + if (value.charAt(iValue) != format.charAt(iFormat)) + throw 'Unexpected literal at position ' + iValue; + iValue++; + }; + var iValue = 0; + for (var iFormat = 0; iFormat < format.length; iFormat++) { + if (literal) + if (format.charAt(iFormat) == "'" && !lookAhead("'")) + literal = false; + else + checkLiteral(); + else + switch (format.charAt(iFormat)) { + case 'd': + day = getNumber('d'); + break; + case 'D': + getName('D', dayNamesShort, dayNames); + break; + case 'o': + doy = getNumber('o'); + break; + case 'm': + month = getNumber('m'); + break; + case 'M': + month = getName('M', monthNamesShort, monthNames); + break; + case 'y': + year = getNumber('y'); + break; + case '@': + var date = new Date(getNumber('@')); + year = date.getFullYear(); + month = date.getMonth() + 1; + day = date.getDate(); + break; + case "'": + if (lookAhead("'")) + checkLiteral(); + else + literal = true; + break; + default: + checkLiteral(); + } + } + if (year == -1) + year = new Date().getFullYear(); + else if (year < 100) + year += new Date().getFullYear() - new Date().getFullYear() % 100 + + (year <= shortYearCutoff ? 0 : -100); + if (doy > -1) { + month = 1; + day = doy; + do { + var dim = this._getDaysInMonth(year, month - 1); + if (day <= dim) + break; + month++; + day -= dim; + } while (true); + } + var date = this._daylightSavingAdjust(new Date(year, month - 1, day)); + if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day) + throw 'Invalid date'; // E.g. 31/02/* + return date; + }, + + /* Standard date formats. */ + ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601) + COOKIE: 'D, dd M yy', + ISO_8601: 'yy-mm-dd', + RFC_822: 'D, d M y', + RFC_850: 'DD, dd-M-y', + RFC_1036: 'D, d M y', + RFC_1123: 'D, d M yy', + RFC_2822: 'D, d M yy', + RSS: 'D, d M y', // RFC 822 + TIMESTAMP: '@', + W3C: 'yy-mm-dd', // ISO 8601 + + /* Format a date object into a string value. + The format can be combinations of the following: + d - day of month (no leading zero) + dd - day of month (two digit) + o - day of year (no leading zeros) + oo - day of year (three digit) + D - day name short + DD - day name long + m - month of year (no leading zero) + mm - month of year (two digit) + M - month name short + MM - month name long + y - year (two digit) + yy - year (four digit) + @ - Unix timestamp (ms since 01/01/1970) + '...' - literal text + '' - single quote + + @param format string - the desired format of the date + @param date Date - the date value to format + @param settings Object - attributes include: + dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) + dayNames string[7] - names of the days from Sunday (optional) + monthNamesShort string[12] - abbreviated names of the months (optional) + monthNames string[12] - names of the months (optional) + @return string - the date in the above format */ + formatDate: function (format, date, settings) { + if (!date) + return ''; + var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; + var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; + var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; + var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; + // Check whether a format character is doubled + var lookAhead = function(match) { + var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); + if (matches) + iFormat++; + return matches; + }; + // Format a number, with leading zero if necessary + var formatNumber = function(match, value, len) { + var num = '' + value; + if (lookAhead(match)) + while (num.length < len) + num = '0' + num; + return num; + }; + // Format a name, short or long as requested + var formatName = function(match, value, shortNames, longNames) { + return (lookAhead(match) ? longNames[value] : shortNames[value]); + }; + var output = ''; + var literal = false; + if (date) + for (var iFormat = 0; iFormat < format.length; iFormat++) { + if (literal) + if (format.charAt(iFormat) == "'" && !lookAhead("'")) + literal = false; + else + output += format.charAt(iFormat); + else + switch (format.charAt(iFormat)) { + case 'd': + output += formatNumber('d', date.getDate(), 2); + break; + case 'D': + output += formatName('D', date.getDay(), dayNamesShort, dayNames); + break; + case 'o': + var doy = date.getDate(); + for (var m = date.getMonth() - 1; m >= 0; m--) + doy += this._getDaysInMonth(date.getFullYear(), m); + output += formatNumber('o', doy, 3); + break; + case 'm': + output += formatNumber('m', date.getMonth() + 1, 2); + break; + case 'M': + output += formatName('M', date.getMonth(), monthNamesShort, monthNames); + break; + case 'y': + output += (lookAhead('y') ? date.getFullYear() : + (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100); + break; + case '@': + output += date.getTime(); + break; + case "'": + if (lookAhead("'")) + output += "'"; + else + literal = true; + break; + default: + output += format.charAt(iFormat); + } + } + return output; + }, + + /* Extract all possible characters from the date format. */ + _possibleChars: function (format) { + var chars = ''; + var literal = false; + for (var iFormat = 0; iFormat < format.length; iFormat++) + if (literal) + if (format.charAt(iFormat) == "'" && !lookAhead("'")) + literal = false; + else + chars += format.charAt(iFormat); + else + switch (format.charAt(iFormat)) { + case 'd': case 'm': case 'y': case '@': + chars += '0123456789'; + break; + case 'D': case 'M': + return null; // Accept anything + case "'": + if (lookAhead("'")) + chars += "'"; + else + literal = true; + break; + default: + chars += format.charAt(iFormat); + } + return chars; + }, + + /* Get a setting value, defaulting if necessary. */ + _get: function(inst, name) { + return inst.settings[name] !== undefined ? + inst.settings[name] : this._defaults[name]; + }, + + /* Parse existing date and initialise date picker. */ + _setDateFromField: function(inst) { + var dateFormat = this._get(inst, 'dateFormat'); + var dates = inst.input ? inst.input.val() : null; + inst.endDay = inst.endMonth = inst.endYear = null; + var date = defaultDate = this._getDefaultDate(inst); + var settings = this._getFormatConfig(inst); + try { + date = this.parseDate(dateFormat, dates, settings) || defaultDate; + } catch (event) { + this.log(event); + date = defaultDate; + } + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + inst.currentDay = (dates ? date.getDate() : 0); + inst.currentMonth = (dates ? date.getMonth() : 0); + inst.currentYear = (dates ? date.getFullYear() : 0); + this._adjustInstDate(inst); + }, + + /* Retrieve the default date shown on opening. */ + _getDefaultDate: function(inst) { + var date = this._determineDate(this._get(inst, 'defaultDate'), new Date()); + var minDate = this._getMinMaxDate(inst, 'min', true); + var maxDate = this._getMinMaxDate(inst, 'max'); + date = (minDate && date < minDate ? minDate : date); + date = (maxDate && date > maxDate ? maxDate : date); + return date; + }, + + /* A date may be specified as an exact value or a relative one. */ + _determineDate: function(date, defaultDate) { + var offsetNumeric = function(offset) { + var date = new Date(); + date.setDate(date.getDate() + offset); + return date; + }; + var offsetString = function(offset, getDaysInMonth) { + var date = new Date(); + var year = date.getFullYear(); + var month = date.getMonth(); + var day = date.getDate(); + var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g; + var matches = pattern.exec(offset); + while (matches) { + switch (matches[2] || 'd') { + case 'd' : case 'D' : + day += parseInt(matches[1],10); break; + case 'w' : case 'W' : + day += parseInt(matches[1],10) * 7; break; + case 'm' : case 'M' : + month += parseInt(matches[1],10); + day = Math.min(day, getDaysInMonth(year, month)); + break; + case 'y': case 'Y' : + year += parseInt(matches[1],10); + day = Math.min(day, getDaysInMonth(year, month)); + break; + } + matches = pattern.exec(offset); + } + return new Date(year, month, day); + }; + date = (date == null ? defaultDate : + (typeof date == 'string' ? offsetString(date, this._getDaysInMonth) : + (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date))); + date = (date && date.toString() == 'Invalid Date' ? defaultDate : date); + if (date) { + date.setHours(0); + date.setMinutes(0); + date.setSeconds(0); + date.setMilliseconds(0); + } + return this._daylightSavingAdjust(date); + }, + + /* Handle switch to/from daylight saving. + Hours may be non-zero on daylight saving cut-over: + > 12 when midnight changeover, but then cannot generate + midnight datetime, so jump to 1AM, otherwise reset. + @param date (Date) the date to check + @return (Date) the corrected date */ + _daylightSavingAdjust: function(date) { + if (!date) return null; + date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); + return date; + }, + + /* Set the date(s) directly. */ + _setDate: function(inst, date, endDate) { + var clear = !(date); + var origMonth = inst.selectedMonth; + var origYear = inst.selectedYear; + date = this._determineDate(date, new Date()); + inst.selectedDay = inst.currentDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear(); + if (origMonth != inst.selectedMonth || origYear != inst.selectedYear) + this._notifyChange(inst); + this._adjustInstDate(inst); + if (inst.input) { + inst.input.val(clear ? '' : this._formatDate(inst)); + } + }, + + /* Retrieve the date(s) directly. */ + _getDate: function(inst) { + var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null : + this._daylightSavingAdjust(new Date( + inst.currentYear, inst.currentMonth, inst.currentDay))); + return startDate; + }, + + /* Generate the HTML for the current state of the date picker. */ + _generateHTML: function(inst) { + var today = new Date(); + today = this._daylightSavingAdjust( + new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time + var isRTL = this._get(inst, 'isRTL'); + var showButtonPanel = this._get(inst, 'showButtonPanel'); + var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext'); + var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat'); + var numMonths = this._getNumberOfMonths(inst); + var showCurrentAtPos = this._get(inst, 'showCurrentAtPos'); + var stepMonths = this._get(inst, 'stepMonths'); + var stepBigMonths = this._get(inst, 'stepBigMonths'); + var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1); + var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : + new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); + var minDate = this._getMinMaxDate(inst, 'min', true); + var maxDate = this._getMinMaxDate(inst, 'max'); + var drawMonth = inst.drawMonth - showCurrentAtPos; + var drawYear = inst.drawYear; + if (drawMonth < 0) { + drawMonth += 12; + drawYear--; + } + if (maxDate) { + var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), + maxDate.getMonth() - numMonths[1] + 1, maxDate.getDate())); + maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); + while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { + drawMonth--; + if (drawMonth < 0) { + drawMonth = 11; + drawYear--; + } + } + } + inst.drawMonth = drawMonth; + inst.drawYear = drawYear; + var prevText = this._get(inst, 'prevText'); + prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, + this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), + this._getFormatConfig(inst))); + var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? + '' + prevText + '' : + (hideIfNoPrevNext ? '' : '' + prevText + '')); + var nextText = this._get(inst, 'nextText'); + nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, + this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), + this._getFormatConfig(inst))); + var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? + '' + nextText + '' : + (hideIfNoPrevNext ? '' : '' + nextText + '')); + var currentText = this._get(inst, 'currentText'); + var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today); + currentText = (!navigationAsDateFormat ? currentText : + this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); + var controls = (!inst.inline ? '' : ''); + var buttonPanel = (showButtonPanel) ? '
    ' + (isRTL ? controls : '') + + (this._isInRange(inst, gotoDate) ? '' : '') + (isRTL ? '' : controls) + '
    ' : ''; + var firstDay = parseInt(this._get(inst, 'firstDay'),10); + firstDay = (isNaN(firstDay) ? 0 : firstDay); + var dayNames = this._get(inst, 'dayNames'); + var dayNamesShort = this._get(inst, 'dayNamesShort'); + var dayNamesMin = this._get(inst, 'dayNamesMin'); + var monthNames = this._get(inst, 'monthNames'); + var monthNamesShort = this._get(inst, 'monthNamesShort'); + var beforeShowDay = this._get(inst, 'beforeShowDay'); + var showOtherMonths = this._get(inst, 'showOtherMonths'); + var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week; + var endDate = inst.endDay ? this._daylightSavingAdjust( + new Date(inst.endYear, inst.endMonth, inst.endDay)) : currentDate; + var defaultDate = this._getDefaultDate(inst); + var html = ''; + for (var row = 0; row < numMonths[0]; row++) { + var group = ''; + for (var col = 0; col < numMonths[1]; col++) { + var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); + var cornerClass = ' ui-corner-all'; + var calender = ''; + if (isMultiMonth) { + calender += '
    '; + } + calender += '
    ' + + (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') + + (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') + + this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, + selectedDate, row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers + '
    ' + + ''; + var thead = ''; + for (var dow = 0; dow < 7; dow++) { // days of the week + var day = (dow + firstDay) % 7; + thead += '= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' + + '' + dayNamesMin[day] + ''; + } + calender += thead + ''; + var daysInMonth = this._getDaysInMonth(drawYear, drawMonth); + if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth) + inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); + var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; + var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate + var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); + for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows + calender += ''; + var tbody = ''; + for (var dow = 0; dow < 7; dow++) { // create date picker days + var daySettings = (beforeShowDay ? + beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']); + var otherMonth = (printDate.getMonth() != drawMonth); + var unselectable = otherMonth || !daySettings[0] || + (minDate && printDate < minDate) || (maxDate && printDate > maxDate); + tbody += ''; // display for this month + printDate.setDate(printDate.getDate() + 1); + printDate = this._daylightSavingAdjust(printDate); + } + calender += tbody + ''; + } + drawMonth++; + if (drawMonth > 11) { + drawMonth = 0; + drawYear++; + } + calender += '
    ' + // actions + (otherMonth ? (showOtherMonths ? printDate.getDate() : ' ') : // display for other months + (unselectable ? '' + printDate.getDate() + '' : '' + printDate.getDate() + '')) + '
    ' + (isMultiMonth ? '
    ' + + ((numMonths[0] > 0 && col == numMonths[1]-1) ? '
    ' : '') : ''); + group += calender; + } + html += group; + } + html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ? + '' : ''); + inst._keyEvent = false; + return html; + }, + + /* Generate the month and year header. */ + _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, + selectedDate, secondary, monthNames, monthNamesShort) { + minDate = (inst.rangeStart && minDate && selectedDate < minDate ? selectedDate : minDate); + var changeMonth = this._get(inst, 'changeMonth'); + var changeYear = this._get(inst, 'changeYear'); + var showMonthAfterYear = this._get(inst, 'showMonthAfterYear'); + var html = '
    '; + var monthHtml = ''; + // month selection + if (secondary || !changeMonth) + monthHtml += '' + monthNames[drawMonth] + ' '; + else { + var inMinYear = (minDate && minDate.getFullYear() == drawYear); + var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear); + monthHtml += ''; + } + if (!showMonthAfterYear) + html += monthHtml + ((secondary || changeMonth || changeYear) && (!(changeMonth && changeYear)) ? ' ' : ''); + // year selection + if (secondary || !changeYear) + html += '' + drawYear + ''; + else { + // determine range of years to display + var years = this._get(inst, 'yearRange').split(':'); + var year = 0; + var endYear = 0; + if (years.length != 2) { + year = drawYear - 10; + endYear = drawYear + 10; + } else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') { + year = drawYear + parseInt(years[0], 10); + endYear = drawYear + parseInt(years[1], 10); + } else { + year = parseInt(years[0], 10); + endYear = parseInt(years[1], 10); + } + year = (minDate ? Math.max(year, minDate.getFullYear()) : year); + endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); + html += ''; + } + if (showMonthAfterYear) + html += (secondary || changeMonth || changeYear ? ' ' : '') + monthHtml; + html += '
    '; // Close datepicker_header + return html; + }, + + /* Adjust one of the date sub-fields. */ + _adjustInstDate: function(inst, offset, period) { + var year = inst.drawYear + (period == 'Y' ? offset : 0); + var month = inst.drawMonth + (period == 'M' ? offset : 0); + var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + + (period == 'D' ? offset : 0); + var date = this._daylightSavingAdjust(new Date(year, month, day)); + // ensure it is within the bounds set + var minDate = this._getMinMaxDate(inst, 'min', true); + var maxDate = this._getMinMaxDate(inst, 'max'); + date = (minDate && date < minDate ? minDate : date); + date = (maxDate && date > maxDate ? maxDate : date); + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + if (period == 'M' || period == 'Y') + this._notifyChange(inst); + }, + + /* Notify change of month/year. */ + _notifyChange: function(inst) { + var onChange = this._get(inst, 'onChangeMonthYear'); + if (onChange) + onChange.apply((inst.input ? inst.input[0] : null), + [inst.selectedYear, inst.selectedMonth + 1, inst]); + }, + + /* Determine the number of months to show. */ + _getNumberOfMonths: function(inst) { + var numMonths = this._get(inst, 'numberOfMonths'); + return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths)); + }, + + /* Determine the current maximum date - ensure no time components are set - may be overridden for a range. */ + _getMinMaxDate: function(inst, minMax, checkRange) { + var date = this._determineDate(this._get(inst, minMax + 'Date'), null); + return (!checkRange || !inst.rangeStart ? date : + (!date || inst.rangeStart > date ? inst.rangeStart : date)); + }, + + /* Find the number of days in a given month. */ + _getDaysInMonth: function(year, month) { + return 32 - new Date(year, month, 32).getDate(); + }, + + /* Find the day of the week of the first of a month. */ + _getFirstDayOfMonth: function(year, month) { + return new Date(year, month, 1).getDay(); + }, + + /* Determines if we should allow a "next/prev" month display change. */ + _canAdjustMonth: function(inst, offset, curYear, curMonth) { + var numMonths = this._getNumberOfMonths(inst); + var date = this._daylightSavingAdjust(new Date( + curYear, curMonth + (offset < 0 ? offset : numMonths[1]), 1)); + if (offset < 0) + date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); + return this._isInRange(inst, date); + }, + + /* Is the given date in the accepted range? */ + _isInRange: function(inst, date) { + // during range selection, use minimum of selected date and range start + var newMinDate = (!inst.rangeStart ? null : this._daylightSavingAdjust( + new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay))); + newMinDate = (newMinDate && inst.rangeStart < newMinDate ? inst.rangeStart : newMinDate); + var minDate = newMinDate || this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate)); + }, + + /* Provide the configuration settings for formatting/parsing. */ + _getFormatConfig: function(inst) { + var shortYearCutoff = this._get(inst, 'shortYearCutoff'); + shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : + new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); + return {shortYearCutoff: shortYearCutoff, + dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'), + monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')}; + }, + + /* Format the given date for display. */ + _formatDate: function(inst, day, month, year) { + if (!day) { + inst.currentDay = inst.selectedDay; + inst.currentMonth = inst.selectedMonth; + inst.currentYear = inst.selectedYear; + } + var date = (day ? (typeof day == 'object' ? day : + this._daylightSavingAdjust(new Date(year, month, day))) : + this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); + return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst)); + } +}); + +/* jQuery extend now ignores nulls! */ +function extendRemove(target, props) { + $.extend(target, props); + for (var name in props) + if (props[name] == null || props[name] == undefined) + target[name] = props[name]; + return target; +}; + +/* Determine whether an object is an array. */ +function isArray(a) { + return (a && (($.browser.safari && typeof a == 'object' && a.length) || + (a.constructor && a.constructor.toString().match(/\Array\(\)/)))); +}; + +/* Invoke the datepicker functionality. + @param options string - a command, optionally followed by additional parameters or + Object - settings for attaching new datepicker functionality + @return jQuery object */ +$.fn.datepicker = function(options){ + + /* Initialise the date picker. */ + if (!$.datepicker.initialized) { + $(document).mousedown($.datepicker._checkExternalClick). + find('body').append($.datepicker.dpDiv); + $.datepicker.initialized = true; + } + + var otherArgs = Array.prototype.slice.call(arguments, 1); + if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate')) + return $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this[0]].concat(otherArgs)); + if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string') + return $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this[0]].concat(otherArgs)); + return this.each(function() { + typeof options == 'string' ? + $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this].concat(otherArgs)) : + $.datepicker._attachDatepicker(this, options); + }); +}; + +$.datepicker = new Datepicker(); // singleton instance +$.datepicker.initialized = false; +$.datepicker.uuid = new Date().getTime(); +$.datepicker.version = "1.7.2"; + +// Workaround for #4055 +// Add another global to avoid noConflict issues with inline event handlers +window.DP_jQuery = $; + +})(jQuery); +/* + * jQuery UI Progressbar 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Progressbar + * + * Depends: + * ui.core.js + */ +(function($) { + +$.widget("ui.progressbar", { + + _init: function() { + + this.element + .addClass("ui-progressbar" + + " ui-widget" + + " ui-widget-content" + + " ui-corner-all") + .attr({ + role: "progressbar", + "aria-valuemin": this._valueMin(), + "aria-valuemax": this._valueMax(), + "aria-valuenow": this._value() + }); + + this.valueDiv = $('
    ').appendTo(this.element); + + this._refreshValue(); + + }, + + destroy: function() { + + this.element + .removeClass("ui-progressbar" + + " ui-widget" + + " ui-widget-content" + + " ui-corner-all") + .removeAttr("role") + .removeAttr("aria-valuemin") + .removeAttr("aria-valuemax") + .removeAttr("aria-valuenow") + .removeData("progressbar") + .unbind(".progressbar"); + + this.valueDiv.remove(); + + $.widget.prototype.destroy.apply(this, arguments); + + }, + + value: function(newValue) { + if (newValue === undefined) { + return this._value(); + } + + this._setData('value', newValue); + return this; + }, + + _setData: function(key, value) { + + switch (key) { + case 'value': + this.options.value = value; + this._refreshValue(); + this._trigger('change', null, {}); + break; + } + + $.widget.prototype._setData.apply(this, arguments); + + }, + + _value: function() { + + var val = this.options.value; + if (val < this._valueMin()) val = this._valueMin(); + if (val > this._valueMax()) val = this._valueMax(); + + return val; + + }, + + _valueMin: function() { + var valueMin = 0; + return valueMin; + }, + + _valueMax: function() { + var valueMax = 100; + return valueMax; + }, + + _refreshValue: function() { + var value = this.value(); + this.valueDiv[value == this._valueMax() ? 'addClass' : 'removeClass']("ui-corner-right"); + this.valueDiv.width(value + '%'); + this.element.attr("aria-valuenow", value); + } + +}); + +$.extend($.ui.progressbar, { + version: "1.7.2", + defaults: { + value: 0 + } +}); + +})(jQuery); +/* + * jQuery UI Effects 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/ + */ +;jQuery.effects || (function($) { + +$.effects = { + version: "1.7.2", + + // Saves a set of properties in a data storage + save: function(element, set) { + for(var i=0; i < set.length; i++) { + if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]); + } + }, + + // Restores a set of previously saved properties from a data storage + restore: function(element, set) { + for(var i=0; i < set.length; i++) { + if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i])); + } + }, + + setMode: function(el, mode) { + if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle + return mode; + }, + + getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value + // this should be a little more flexible in the future to handle a string & hash + var y, x; + switch (origin[0]) { + case 'top': y = 0; break; + case 'middle': y = 0.5; break; + case 'bottom': y = 1; break; + default: y = origin[0] / original.height; + }; + switch (origin[1]) { + case 'left': x = 0; break; + case 'center': x = 0.5; break; + case 'right': x = 1; break; + default: x = origin[1] / original.width; + }; + return {x: x, y: y}; + }, + + // Wraps the element around a wrapper that copies position properties + createWrapper: function(element) { + + //if the element is already wrapped, return it + if (element.parent().is('.ui-effects-wrapper')) + return element.parent(); + + //Cache width,height and float properties of the element, and create a wrapper around it + var props = { width: element.outerWidth(true), height: element.outerHeight(true), 'float': element.css('float') }; + element.wrap('
    '); + var wrapper = element.parent(); + + //Transfer the positioning of the element to the wrapper + if (element.css('position') == 'static') { + wrapper.css({ position: 'relative' }); + element.css({ position: 'relative'} ); + } else { + var top = element.css('top'); if(isNaN(parseInt(top,10))) top = 'auto'; + var left = element.css('left'); if(isNaN(parseInt(left,10))) left = 'auto'; + wrapper.css({ position: element.css('position'), top: top, left: left, zIndex: element.css('z-index') }).show(); + element.css({position: 'relative', top: 0, left: 0 }); + } + + wrapper.css(props); + return wrapper; + }, + + removeWrapper: function(element) { + if (element.parent().is('.ui-effects-wrapper')) + return element.parent().replaceWith(element); + return element; + }, + + setTransition: function(element, list, factor, value) { + value = value || {}; + $.each(list, function(i, x){ + unit = element.cssUnit(x); + if (unit[0] > 0) value[x] = unit[0] * factor + unit[1]; + }); + return value; + }, + + //Base function to animate from one class to another in a seamless transition + animateClass: function(value, duration, easing, callback) { + + var cb = (typeof easing == "function" ? easing : (callback ? callback : null)); + var ea = (typeof easing == "string" ? easing : null); + + return this.each(function() { + + var offset = {}; var that = $(this); var oldStyleAttr = that.attr("style") || ''; + if(typeof oldStyleAttr == 'object') oldStyleAttr = oldStyleAttr["cssText"]; /* Stupidly in IE, style is a object.. */ + if(value.toggle) { that.hasClass(value.toggle) ? value.remove = value.toggle : value.add = value.toggle; } + + //Let's get a style offset + var oldStyle = $.extend({}, (document.defaultView ? document.defaultView.getComputedStyle(this,null) : this.currentStyle)); + if(value.add) that.addClass(value.add); if(value.remove) that.removeClass(value.remove); + var newStyle = $.extend({}, (document.defaultView ? document.defaultView.getComputedStyle(this,null) : this.currentStyle)); + if(value.add) that.removeClass(value.add); if(value.remove) that.addClass(value.remove); + + // The main function to form the object for animation + for(var n in newStyle) { + if( typeof newStyle[n] != "function" && newStyle[n] /* No functions and null properties */ + && n.indexOf("Moz") == -1 && n.indexOf("length") == -1 /* No mozilla spezific render properties. */ + && newStyle[n] != oldStyle[n] /* Only values that have changed are used for the animation */ + && (n.match(/color/i) || (!n.match(/color/i) && !isNaN(parseInt(newStyle[n],10)))) /* Only things that can be parsed to integers or colors */ + && (oldStyle.position != "static" || (oldStyle.position == "static" && !n.match(/left|top|bottom|right/))) /* No need for positions when dealing with static positions */ + ) offset[n] = newStyle[n]; + } + + that.animate(offset, duration, ea, function() { // Animate the newly constructed offset object + // Change style attribute back to original. For stupid IE, we need to clear the damn object. + if(typeof $(this).attr("style") == 'object') { $(this).attr("style")["cssText"] = ""; $(this).attr("style")["cssText"] = oldStyleAttr; } else $(this).attr("style", oldStyleAttr); + if(value.add) $(this).addClass(value.add); if(value.remove) $(this).removeClass(value.remove); + if(cb) cb.apply(this, arguments); + }); + + }); + } +}; + + +function _normalizeArguments(a, m) { + + var o = a[1] && a[1].constructor == Object ? a[1] : {}; if(m) o.mode = m; + var speed = a[1] && a[1].constructor != Object ? a[1] : (o.duration ? o.duration : a[2]); //either comes from options.duration or the secon/third argument + speed = $.fx.off ? 0 : typeof speed === "number" ? speed : $.fx.speeds[speed] || $.fx.speeds._default; + var callback = o.callback || ( $.isFunction(a[1]) && a[1] ) || ( $.isFunction(a[2]) && a[2] ) || ( $.isFunction(a[3]) && a[3] ); + + return [a[0], o, speed, callback]; + +} + +//Extend the methods of jQuery +$.fn.extend({ + + //Save old methods + _show: $.fn.show, + _hide: $.fn.hide, + __toggle: $.fn.toggle, + _addClass: $.fn.addClass, + _removeClass: $.fn.removeClass, + _toggleClass: $.fn.toggleClass, + + // New effect methods + effect: function(fx, options, speed, callback) { + return $.effects[fx] ? $.effects[fx].call(this, {method: fx, options: options || {}, duration: speed, callback: callback }) : null; + }, + + show: function() { + if(!arguments[0] || (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0]))) + return this._show.apply(this, arguments); + else { + return this.effect.apply(this, _normalizeArguments(arguments, 'show')); + } + }, + + hide: function() { + if(!arguments[0] || (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0]))) + return this._hide.apply(this, arguments); + else { + return this.effect.apply(this, _normalizeArguments(arguments, 'hide')); + } + }, + + toggle: function(){ + if(!arguments[0] || + (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])) || + ($.isFunction(arguments[0]) || typeof arguments[0] == 'boolean')) { + return this.__toggle.apply(this, arguments); + } else { + return this.effect.apply(this, _normalizeArguments(arguments, 'toggle')); + } + }, + + addClass: function(classNames, speed, easing, callback) { + return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames); + }, + removeClass: function(classNames,speed,easing,callback) { + return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames); + }, + toggleClass: function(classNames,speed,easing,callback) { + return ( (typeof speed !== "boolean") && speed ) ? $.effects.animateClass.apply(this, [{ toggle: classNames },speed,easing,callback]) : this._toggleClass(classNames, speed); + }, + morph: function(remove,add,speed,easing,callback) { + return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]); + }, + switchClass: function() { + return this.morph.apply(this, arguments); + }, + + // helper functions + cssUnit: function(key) { + var style = this.css(key), val = []; + $.each( ['em','px','%','pt'], function(i, unit){ + if(style.indexOf(unit) > 0) + val = [parseFloat(style), unit]; + }); + return val; + } +}); + +/* + * jQuery Color Animations + * Copyright 2007 John Resig + * Released under the MIT and GPL licenses. + */ + +// We override the animation for all of these color styles +$.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'], function(i,attr){ + $.fx.step[attr] = function(fx) { + if ( fx.state == 0 ) { + fx.start = getColor( fx.elem, attr ); + fx.end = getRGB( fx.end ); + } + + fx.elem.style[attr] = "rgb(" + [ + Math.max(Math.min( parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0],10), 255), 0), + Math.max(Math.min( parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1],10), 255), 0), + Math.max(Math.min( parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2],10), 255), 0) + ].join(",") + ")"; + }; +}); + +// Color Conversion functions from highlightFade +// By Blair Mitchelmore +// http://jquery.offput.ca/highlightFade/ + +// Parse strings looking for color tuples [255,255,255] +function getRGB(color) { + var result; + + // Check if we're already dealing with an array of colors + if ( color && color.constructor == Array && color.length == 3 ) + return color; + + // Look for rgb(num,num,num) + if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) + return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)]; + + // Look for rgb(num%,num%,num%) + if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) + return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55]; + + // Look for #a0b1c2 + if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) + return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)]; + + // Look for #fff + if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) + return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)]; + + // Look for rgba(0, 0, 0, 0) == transparent in Safari 3 + if (result = /rgba\(0, 0, 0, 0\)/.exec(color)) + return colors['transparent']; + + // Otherwise, we're most likely dealing with a named color + return colors[$.trim(color).toLowerCase()]; +} + +function getColor(elem, attr) { + var color; + + do { + color = $.curCSS(elem, attr); + + // Keep going until we find an element that has color, or we hit the body + if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") ) + break; + + attr = "backgroundColor"; + } while ( elem = elem.parentNode ); + + return getRGB(color); +}; + +// Some named colors to work with +// From Interface by Stefan Petre +// http://interface.eyecon.ro/ + +var colors = { + aqua:[0,255,255], + azure:[240,255,255], + beige:[245,245,220], + black:[0,0,0], + blue:[0,0,255], + brown:[165,42,42], + cyan:[0,255,255], + darkblue:[0,0,139], + darkcyan:[0,139,139], + darkgrey:[169,169,169], + darkgreen:[0,100,0], + darkkhaki:[189,183,107], + darkmagenta:[139,0,139], + darkolivegreen:[85,107,47], + darkorange:[255,140,0], + darkorchid:[153,50,204], + darkred:[139,0,0], + darksalmon:[233,150,122], + darkviolet:[148,0,211], + fuchsia:[255,0,255], + gold:[255,215,0], + green:[0,128,0], + indigo:[75,0,130], + khaki:[240,230,140], + lightblue:[173,216,230], + lightcyan:[224,255,255], + lightgreen:[144,238,144], + lightgrey:[211,211,211], + lightpink:[255,182,193], + lightyellow:[255,255,224], + lime:[0,255,0], + magenta:[255,0,255], + maroon:[128,0,0], + navy:[0,0,128], + olive:[128,128,0], + orange:[255,165,0], + pink:[255,192,203], + purple:[128,0,128], + violet:[128,0,128], + red:[255,0,0], + silver:[192,192,192], + white:[255,255,255], + yellow:[255,255,0], + transparent: [255,255,255] +}; + +/* + * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ + * + * Uses the built in easing capabilities added In jQuery 1.1 + * to offer multiple easing options + * + * TERMS OF USE - jQuery Easing + * + * Open source under the BSD License. + * + * Copyright 2008 George McGinley Smith + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * Neither the name of the author nor the names of contributors may be used to endorse + * or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * +*/ + +// t: current time, b: begInnIng value, c: change In value, d: duration +$.easing.jswing = $.easing.swing; + +$.extend($.easing, +{ + def: 'easeOutQuad', + swing: function (x, t, b, c, d) { + //alert($.easing.default); + return $.easing[$.easing.def](x, t, b, c, d); + }, + easeInQuad: function (x, t, b, c, d) { + return c*(t/=d)*t + b; + }, + easeOutQuad: function (x, t, b, c, d) { + return -c *(t/=d)*(t-2) + b; + }, + easeInOutQuad: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t + b; + return -c/2 * ((--t)*(t-2) - 1) + b; + }, + easeInCubic: function (x, t, b, c, d) { + return c*(t/=d)*t*t + b; + }, + easeOutCubic: function (x, t, b, c, d) { + return c*((t=t/d-1)*t*t + 1) + b; + }, + easeInOutCubic: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t*t + b; + return c/2*((t-=2)*t*t + 2) + b; + }, + easeInQuart: function (x, t, b, c, d) { + return c*(t/=d)*t*t*t + b; + }, + easeOutQuart: function (x, t, b, c, d) { + return -c * ((t=t/d-1)*t*t*t - 1) + b; + }, + easeInOutQuart: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t*t*t + b; + return -c/2 * ((t-=2)*t*t*t - 2) + b; + }, + easeInQuint: function (x, t, b, c, d) { + return c*(t/=d)*t*t*t*t + b; + }, + easeOutQuint: function (x, t, b, c, d) { + return c*((t=t/d-1)*t*t*t*t + 1) + b; + }, + easeInOutQuint: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; + return c/2*((t-=2)*t*t*t*t + 2) + b; + }, + easeInSine: function (x, t, b, c, d) { + return -c * Math.cos(t/d * (Math.PI/2)) + c + b; + }, + easeOutSine: function (x, t, b, c, d) { + return c * Math.sin(t/d * (Math.PI/2)) + b; + }, + easeInOutSine: function (x, t, b, c, d) { + return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; + }, + easeInExpo: function (x, t, b, c, d) { + return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; + }, + easeOutExpo: function (x, t, b, c, d) { + return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; + }, + easeInOutExpo: function (x, t, b, c, d) { + if (t==0) return b; + if (t==d) return b+c; + if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; + return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; + }, + easeInCirc: function (x, t, b, c, d) { + return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; + }, + easeOutCirc: function (x, t, b, c, d) { + return c * Math.sqrt(1 - (t=t/d-1)*t) + b; + }, + easeInOutCirc: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; + return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; + }, + easeInElastic: function (x, t, b, c, d) { + var s=1.70158;var p=0;var a=c; + if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; + if (a < Math.abs(c)) { a=c; var s=p/4; } + else var s = p/(2*Math.PI) * Math.asin (c/a); + return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; + }, + easeOutElastic: function (x, t, b, c, d) { + var s=1.70158;var p=0;var a=c; + if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; + if (a < Math.abs(c)) { a=c; var s=p/4; } + else var s = p/(2*Math.PI) * Math.asin (c/a); + return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; + }, + easeInOutElastic: function (x, t, b, c, d) { + var s=1.70158;var p=0;var a=c; + if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); + if (a < Math.abs(c)) { a=c; var s=p/4; } + else var s = p/(2*Math.PI) * Math.asin (c/a); + if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; + return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; + }, + easeInBack: function (x, t, b, c, d, s) { + if (s == undefined) s = 1.70158; + return c*(t/=d)*t*((s+1)*t - s) + b; + }, + easeOutBack: function (x, t, b, c, d, s) { + if (s == undefined) s = 1.70158; + return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; + }, + easeInOutBack: function (x, t, b, c, d, s) { + if (s == undefined) s = 1.70158; + if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; + return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; + }, + easeInBounce: function (x, t, b, c, d) { + return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b; + }, + easeOutBounce: function (x, t, b, c, d) { + if ((t/=d) < (1/2.75)) { + return c*(7.5625*t*t) + b; + } else if (t < (2/2.75)) { + return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; + } else if (t < (2.5/2.75)) { + return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; + } else { + return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; + } + }, + easeInOutBounce: function (x, t, b, c, d) { + if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; + return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; + } +}); + +/* + * + * TERMS OF USE - EASING EQUATIONS + * + * Open source under the BSD License. + * + * Copyright 2001 Robert Penner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * Neither the name of the author nor the names of contributors may be used to endorse + * or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +})(jQuery); +/* + * jQuery UI Effects Blind 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/Blind + * + * Depends: + * effects.core.js + */ +(function($) { + +$.effects.blind = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','left']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode + var direction = o.options.direction || 'vertical'; // Default direction + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper + var ref = (direction == 'vertical') ? 'height' : 'width'; + var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width(); + if(mode == 'show') wrapper.css(ref, 0); // Shift + + // Animation + var animation = {}; + animation[ref] = mode == 'show' ? distance : 0; + + // Animate + wrapper.animate(animation, o.duration, o.options.easing, function() { + if(mode == 'hide') el.hide(); // Hide + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(el[0], arguments); // Callback + el.dequeue(); + }); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Bounce 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/Bounce + * + * Depends: + * effects.core.js + */ +(function($) { + +$.effects.bounce = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','left']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode + var direction = o.options.direction || 'up'; // Default direction + var distance = o.options.distance || 20; // Default distance + var times = o.options.times || 5; // Default # of times + var speed = o.duration || 250; // Default speed per bounce + if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + $.effects.createWrapper(el); // Create Wrapper + var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; + var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; + var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3); + if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift + if (mode == 'hide') distance = distance / (times * 2); + if (mode != 'hide') times--; + + // Animate + if (mode == 'show') { // Show Bounce + var animation = {opacity: 1}; + animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance; + el.animate(animation, speed / 2, o.options.easing); + distance = distance / 2; + times--; + }; + for (var i = 0; i < times; i++) { // Bounces + var animation1 = {}, animation2 = {}; + animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance; + animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance; + el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing); + distance = (mode == 'hide') ? distance * 2 : distance / 2; + }; + if (mode == 'hide') { // Last Bounce + var animation = {opacity: 0}; + animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance; + el.animate(animation, speed / 2, o.options.easing, function(){ + el.hide(); // Hide + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(this, arguments); // Callback + }); + } else { + var animation1 = {}, animation2 = {}; + animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance; + animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance; + el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){ + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(this, arguments); // Callback + }); + }; + el.queue('fx', function() { el.dequeue(); }); + el.dequeue(); + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Clip 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/Clip + * + * Depends: + * effects.core.js + */ +(function($) { + +$.effects.clip = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','left','height','width']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode + var direction = o.options.direction || 'vertical'; // Default direction + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper + var animate = el[0].tagName == 'IMG' ? wrapper : el; + var ref = { + size: (direction == 'vertical') ? 'height' : 'width', + position: (direction == 'vertical') ? 'top' : 'left' + }; + var distance = (direction == 'vertical') ? animate.height() : animate.width(); + if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift + + // Animation + var animation = {}; + animation[ref.size] = mode == 'show' ? distance : 0; + animation[ref.position] = mode == 'show' ? 0 : distance / 2; + + // Animate + animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { + if(mode == 'hide') el.hide(); // Hide + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(el[0], arguments); // Callback + el.dequeue(); + }}); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Drop 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/Drop + * + * Depends: + * effects.core.js + */ +(function($) { + +$.effects.drop = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','left','opacity']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode + var direction = o.options.direction || 'left'; // Default Direction + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + $.effects.createWrapper(el); // Create Wrapper + var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; + var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; + var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2); + if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift + + // Animation + var animation = {opacity: mode == 'show' ? 1 : 0}; + animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance; + + // Animate + el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { + if(mode == 'hide') el.hide(); // Hide + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(this, arguments); // Callback + el.dequeue(); + }}); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Explode 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/Explode + * + * Depends: + * effects.core.js + */ +(function($) { + +$.effects.explode = function(o) { + + return this.queue(function() { + + var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3; + var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3; + + o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode; + var el = $(this).show().css('visibility', 'hidden'); + var offset = el.offset(); + + //Substract the margins - not fixing the problem yet. + offset.top -= parseInt(el.css("marginTop"),10) || 0; + offset.left -= parseInt(el.css("marginLeft"),10) || 0; + + var width = el.outerWidth(true); + var height = el.outerHeight(true); + + for(var i=0;i
    ') + .css({ + position: 'absolute', + visibility: 'visible', + left: -j*(width/cells), + top: -i*(height/rows) + }) + .parent() + .addClass('ui-effects-explode') + .css({ + position: 'absolute', + overflow: 'hidden', + width: width/cells, + height: height/rows, + left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0), + top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0), + opacity: o.options.mode == 'show' ? 0 : 1 + }).animate({ + left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)), + top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)), + opacity: o.options.mode == 'show' ? 1 : 0 + }, o.duration || 500); + } + } + + // Set a timeout, to call the callback approx. when the other animations have finished + setTimeout(function() { + + o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide(); + if(o.callback) o.callback.apply(el[0]); // Callback + el.dequeue(); + + $('div.ui-effects-explode').remove(); + + }, o.duration || 500); + + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Fold 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/Fold + * + * Depends: + * effects.core.js + */ +(function($) { + +$.effects.fold = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','left']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode + var size = o.options.size || 15; // Default fold size + var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value + var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2; + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper + var widthFirst = ((mode == 'show') != horizFirst); + var ref = widthFirst ? ['width', 'height'] : ['height', 'width']; + var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()]; + var percent = /([0-9]+)%/.exec(size); + if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1]; + if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift + + // Animation + var animation1 = {}, animation2 = {}; + animation1[ref[0]] = mode == 'show' ? distance[0] : size; + animation2[ref[1]] = mode == 'show' ? distance[1] : 0; + + // Animate + wrapper.animate(animation1, duration, o.options.easing) + .animate(animation2, duration, o.options.easing, function() { + if(mode == 'hide') el.hide(); // Hide + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(el[0], arguments); // Callback + el.dequeue(); + }); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Highlight 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/Highlight + * + * Depends: + * effects.core.js + */ +(function($) { + +$.effects.highlight = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['backgroundImage','backgroundColor','opacity']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode + var color = o.options.color || "#ffff99"; // Default highlight color + var oldColor = el.css("backgroundColor"); + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + el.css({backgroundImage: 'none', backgroundColor: color}); // Shift + + // Animation + var animation = {backgroundColor: oldColor }; + if (mode == "hide") animation['opacity'] = 0; + + // Animate + el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { + if(mode == "hide") el.hide(); + $.effects.restore(el, props); + if (mode == "show" && $.browser.msie) this.style.removeAttribute('filter'); + if(o.callback) o.callback.apply(this, arguments); + el.dequeue(); + }}); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Pulsate 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/Pulsate + * + * Depends: + * effects.core.js + */ +(function($) { + +$.effects.pulsate = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this); + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode + var times = o.options.times || 5; // Default # of times + var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2; + + // Adjust + if (mode == 'hide') times--; + if (el.is(':hidden')) { // Show fadeIn + el.css('opacity', 0); + el.show(); // Show + el.animate({opacity: 1}, duration, o.options.easing); + times = times-2; + } + + // Animate + for (var i = 0; i < times; i++) { // Pulsate + el.animate({opacity: 0}, duration, o.options.easing).animate({opacity: 1}, duration, o.options.easing); + }; + if (mode == 'hide') { // Last Pulse + el.animate({opacity: 0}, duration, o.options.easing, function(){ + el.hide(); // Hide + if(o.callback) o.callback.apply(this, arguments); // Callback + }); + } else { + el.animate({opacity: 0}, duration, o.options.easing).animate({opacity: 1}, duration, o.options.easing, function(){ + if(o.callback) o.callback.apply(this, arguments); // Callback + }); + }; + el.queue('fx', function() { el.dequeue(); }); + el.dequeue(); + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Scale 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/Scale + * + * Depends: + * effects.core.js + */ +(function($) { + +$.effects.puff = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this); + + // Set options + var options = $.extend(true, {}, o.options); + var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode + var percent = parseInt(o.options.percent,10) || 150; // Set default puff percent + options.fade = true; // It's not a puff if it doesn't fade! :) + var original = {height: el.height(), width: el.width()}; // Save original + + // Adjust + var factor = percent / 100; + el.from = (mode == 'hide') ? original : {height: original.height * factor, width: original.width * factor}; + + // Animation + options.from = el.from; + options.percent = (mode == 'hide') ? percent : 100; + options.mode = mode; + + // Animate + el.effect('scale', options, o.duration, o.callback); + el.dequeue(); + }); + +}; + +$.effects.scale = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this); + + // Set options + var options = $.extend(true, {}, o.options); + var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode + var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent + var direction = o.options.direction || 'both'; // Set default axis + var origin = o.options.origin; // The origin of the scaling + if (mode != 'effect') { // Set default origin and restore for show/hide + options.origin = origin || ['middle','center']; + options.restore = true; + } + var original = {height: el.height(), width: el.width()}; // Save original + el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state + + // Adjust + var factor = { // Set scaling factor + y: direction != 'horizontal' ? (percent / 100) : 1, + x: direction != 'vertical' ? (percent / 100) : 1 + }; + el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state + + if (o.options.fade) { // Fade option to support puff + if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;}; + if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;}; + }; + + // Animation + options.from = el.from; options.to = el.to; options.mode = mode; + + // Animate + el.effect('size', options, o.duration, o.callback); + el.dequeue(); + }); + +}; + +$.effects.size = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','left','width','height','overflow','opacity']; + var props1 = ['position','top','left','overflow','opacity']; // Always restore + var props2 = ['width','height','overflow']; // Copy for children + var cProps = ['fontSize']; + var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom']; + var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode + var restore = o.options.restore || false; // Default restore + var scale = o.options.scale || 'both'; // Default scale mode + var origin = o.options.origin; // The origin of the sizing + var original = {height: el.height(), width: el.width()}; // Save original + el.from = o.options.from || original; // Default from state + el.to = o.options.to || original; // Default to state + // Adjust + if (origin) { // Calculate baseline shifts + var baseline = $.effects.getBaseline(origin, original); + el.from.top = (original.height - el.from.height) * baseline.y; + el.from.left = (original.width - el.from.width) * baseline.x; + el.to.top = (original.height - el.to.height) * baseline.y; + el.to.left = (original.width - el.to.width) * baseline.x; + }; + var factor = { // Set scaling factor + from: {y: el.from.height / original.height, x: el.from.width / original.width}, + to: {y: el.to.height / original.height, x: el.to.width / original.width} + }; + if (scale == 'box' || scale == 'both') { // Scale the css box + if (factor.from.y != factor.to.y) { // Vertical props scaling + props = props.concat(vProps); + el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from); + el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to); + }; + if (factor.from.x != factor.to.x) { // Horizontal props scaling + props = props.concat(hProps); + el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from); + el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to); + }; + }; + if (scale == 'content' || scale == 'both') { // Scale the content + if (factor.from.y != factor.to.y) { // Vertical props scaling + props = props.concat(cProps); + el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from); + el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to); + }; + }; + $.effects.save(el, restore ? props : props1); el.show(); // Save & Show + $.effects.createWrapper(el); // Create Wrapper + el.css('overflow','hidden').css(el.from); // Shift + + // Animate + if (scale == 'content' || scale == 'both') { // Scale the children + vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size + hProps = hProps.concat(['marginLeft','marginRight']); // Add margins + props2 = props.concat(vProps).concat(hProps); // Concat + el.find("*[width]").each(function(){ + child = $(this); + if (restore) $.effects.save(child, props2); + var c_original = {height: child.height(), width: child.width()}; // Save original + child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x}; + child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x}; + if (factor.from.y != factor.to.y) { // Vertical props scaling + child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from); + child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to); + }; + if (factor.from.x != factor.to.x) { // Horizontal props scaling + child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from); + child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to); + }; + child.css(child.from); // Shift children + child.animate(child.to, o.duration, o.options.easing, function(){ + if (restore) $.effects.restore(child, props2); // Restore children + }); // Animate children + }); + }; + + // Animate + el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { + if(mode == 'hide') el.hide(); // Hide + $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(this, arguments); // Callback + el.dequeue(); + }}); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Shake 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/Shake + * + * Depends: + * effects.core.js + */ +(function($) { + +$.effects.shake = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','left']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode + var direction = o.options.direction || 'left'; // Default direction + var distance = o.options.distance || 20; // Default distance + var times = o.options.times || 3; // Default # of times + var speed = o.duration || o.options.duration || 140; // Default speed per shake + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + $.effects.createWrapper(el); // Create Wrapper + var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; + var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; + + // Animation + var animation = {}, animation1 = {}, animation2 = {}; + animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance; + animation1[ref] = (motion == 'pos' ? '+=' : '-=') + distance * 2; + animation2[ref] = (motion == 'pos' ? '-=' : '+=') + distance * 2; + + // Animate + el.animate(animation, speed, o.options.easing); + for (var i = 1; i < times; i++) { // Shakes + el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing); + }; + el.animate(animation1, speed, o.options.easing). + animate(animation, speed / 2, o.options.easing, function(){ // Last shake + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(this, arguments); // Callback + }); + el.queue('fx', function() { el.dequeue(); }); + el.dequeue(); + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Slide 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/Slide + * + * Depends: + * effects.core.js + */ +(function($) { + +$.effects.slide = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','left']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode + var direction = o.options.direction || 'left'; // Default Direction + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper + var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; + var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; + var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true})); + if (mode == 'show') el.css(ref, motion == 'pos' ? -distance : distance); // Shift + + // Animation + var animation = {}; + animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance; + + // Animate + el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { + if(mode == 'hide') el.hide(); // Hide + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(this, arguments); // Callback + el.dequeue(); + }}); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Transfer 1.7.2 + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI/Effects/Transfer + * + * Depends: + * effects.core.js + */ +(function($) { + +$.effects.transfer = function(o) { + return this.queue(function() { + var elem = $(this), + target = $(o.options.to), + endPosition = target.offset(), + animation = { + top: endPosition.top, + left: endPosition.left, + height: target.innerHeight(), + width: target.innerWidth() + }, + startPosition = elem.offset(), + transfer = $('
    ') + .appendTo(document.body) + .addClass(o.options.className) + .css({ + top: startPosition.top, + left: startPosition.left, + height: elem.innerHeight(), + width: elem.innerWidth(), + position: 'absolute' + }) + .animate(animation, o.duration, o.options.easing, function() { + transfer.remove(); + (o.callback && o.callback.apply(elem[0], arguments)); + elem.dequeue(); + }); + }); +}; + +})(jQuery); diff --git a/site/vendors/js/jquery/jquery.js b/site/vendors/js/jquery/jquery.js new file mode 100644 index 0000000..9263574 --- /dev/null +++ b/site/vendors/js/jquery/jquery.js @@ -0,0 +1,4376 @@ +/*! + * jQuery JavaScript Library v1.3.2 + * http://jquery.com/ + * + * Copyright (c) 2009 John Resig + * Dual licensed under the MIT and GPL licenses. + * http://docs.jquery.com/License + * + * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) + * Revision: 6246 + */ +(function(){ + +var + // Will speed up references to window, and allows munging its name. + window = this, + // Will speed up references to undefined, and allows munging its name. + undefined, + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + // Map over the $ in case of overwrite + _$ = window.$, + + jQuery = window.jQuery = window.$ = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context ); + }, + + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/, + // Is it a simple selector + isSimple = /^.[^:#\[\.,]*$/; + +jQuery.fn = jQuery.prototype = { + init: function( selector, context ) { + // Make sure that a selection was provided + selector = selector || document; + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this[0] = selector; + this.length = 1; + this.context = selector; + return this; + } + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + var match = quickExpr.exec( selector ); + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) + selector = jQuery.clean( [ match[1] ], context ); + + // HANDLE: $("#id") + else { + var elem = document.getElementById( match[3] ); + + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem && elem.id != match[3] ) + return jQuery().find( selector ); + + // Otherwise, we inject the element directly into the jQuery object + var ret = jQuery( elem || [] ); + ret.context = document; + ret.selector = selector; + return ret; + } + + // HANDLE: $(expr, [context]) + // (which is just equivalent to: $(content).find(expr) + } else + return jQuery( context ).find( selector ); + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) + return jQuery( document ).ready( selector ); + + // Make sure that old selector state is passed along + if ( selector.selector && selector.context ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return this.setArray(jQuery.isArray( selector ) ? + selector : + jQuery.makeArray(selector)); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.3.2", + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num === undefined ? + + // Return a 'clean' array + Array.prototype.slice.call( this ) : + + // Return just the object + this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = jQuery( elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) + ret.selector = this.selector + (this.selector ? " " : "") + selector; + else if ( name ) + ret.selector = this.selector + "." + name + "(" + selector + ")"; + + // Return the newly-formed element set + return ret; + }, + + // Force the current matched set of elements to become + // the specified array of elements (destroying the stack in the process) + // You should use pushStack() in order to do this, but maintain the stack + setArray: function( elems ) { + // Resetting the length to 0, then using the native Array push + // is a super-fast way to populate an object with array-like properties + this.length = 0; + Array.prototype.push.apply( this, elems ); + + return this; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem && elem.jquery ? elem[0] : elem + , this ); + }, + + attr: function( name, value, type ) { + var options = name; + + // Look for the case where we're accessing a style value + if ( typeof name === "string" ) + if ( value === undefined ) + return this[0] && jQuery[ type || "attr" ]( this[0], name ); + + else { + options = {}; + options[ name ] = value; + } + + // Check to see if we're setting style values + return this.each(function(i){ + // Set all the styles + for ( name in options ) + jQuery.attr( + type ? + this.style : + this, + name, jQuery.prop( this, options[ name ], type, i, name ) + ); + }); + }, + + css: function( key, value ) { + // ignore negative width and height values + if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 ) + value = undefined; + return this.attr( key, value, "curCSS" ); + }, + + text: function( text ) { + if ( typeof text !== "object" && text != null ) + return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); + + var ret = ""; + + jQuery.each( text || this, function(){ + jQuery.each( this.childNodes, function(){ + if ( this.nodeType != 8 ) + ret += this.nodeType != 1 ? + this.nodeValue : + jQuery.fn.text( [ this ] ); + }); + }); + + return ret; + }, + + wrapAll: function( html ) { + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).clone(); + + if ( this[0].parentNode ) + wrap.insertBefore( this[0] ); + + wrap.map(function(){ + var elem = this; + + while ( elem.firstChild ) + elem = elem.firstChild; + + return elem; + }).append(this); + } + + return this; + }, + + wrapInner: function( html ) { + return this.each(function(){ + jQuery( this ).contents().wrapAll( html ); + }); + }, + + wrap: function( html ) { + return this.each(function(){ + jQuery( this ).wrapAll( html ); + }); + }, + + append: function() { + return this.domManip(arguments, true, function(elem){ + if (this.nodeType == 1) + this.appendChild( elem ); + }); + }, + + prepend: function() { + return this.domManip(arguments, true, function(elem){ + if (this.nodeType == 1) + this.insertBefore( elem, this.firstChild ); + }); + }, + + before: function() { + return this.domManip(arguments, false, function(elem){ + this.parentNode.insertBefore( elem, this ); + }); + }, + + after: function() { + return this.domManip(arguments, false, function(elem){ + this.parentNode.insertBefore( elem, this.nextSibling ); + }); + }, + + end: function() { + return this.prevObject || jQuery( [] ); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: [].push, + sort: [].sort, + splice: [].splice, + + find: function( selector ) { + if ( this.length === 1 ) { + var ret = this.pushStack( [], "find", selector ); + ret.length = 0; + jQuery.find( selector, this[0], ret ); + return ret; + } else { + return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){ + return jQuery.find( selector, elem ); + })), "find", selector ); + } + }, + + clone: function( events ) { + // Do the clone + var ret = this.map(function(){ + if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) { + // IE copies events bound via attachEvent when + // using cloneNode. Calling detachEvent on the + // clone will also remove the events from the orignal + // In order to get around this, we use innerHTML. + // Unfortunately, this means some modifications to + // attributes in IE that are actually only stored + // as properties will not be copied (such as the + // the name attribute on an input). + var html = this.outerHTML; + if ( !html ) { + var div = this.ownerDocument.createElement("div"); + div.appendChild( this.cloneNode(true) ); + html = div.innerHTML; + } + + return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0]; + } else + return this.cloneNode(true); + }); + + // Copy the events from the original to the clone + if ( events === true ) { + var orig = this.find("*").andSelf(), i = 0; + + ret.find("*").andSelf().each(function(){ + if ( this.nodeName !== orig[i].nodeName ) + return; + + var events = jQuery.data( orig[i], "events" ); + + for ( var type in events ) { + for ( var handler in events[ type ] ) { + jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data ); + } + } + + i++; + }); + } + + // Return the cloned set + return ret; + }, + + filter: function( selector ) { + return this.pushStack( + jQuery.isFunction( selector ) && + jQuery.grep(this, function(elem, i){ + return selector.call( elem, i ); + }) || + + jQuery.multiFilter( selector, jQuery.grep(this, function(elem){ + return elem.nodeType === 1; + }) ), "filter", selector ); + }, + + closest: function( selector ) { + var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null, + closer = 0; + + return this.map(function(){ + var cur = this; + while ( cur && cur.ownerDocument ) { + if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) { + jQuery.data(cur, "closest", closer); + return cur; + } + cur = cur.parentNode; + closer++; + } + }); + }, + + not: function( selector ) { + if ( typeof selector === "string" ) + // test special case where just one selector is passed in + if ( isSimple.test( selector ) ) + return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector ); + else + selector = jQuery.multiFilter( selector, this ); + + var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType; + return this.filter(function() { + return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector; + }); + }, + + add: function( selector ) { + return this.pushStack( jQuery.unique( jQuery.merge( + this.get(), + typeof selector === "string" ? + jQuery( selector ) : + jQuery.makeArray( selector ) + ))); + }, + + is: function( selector ) { + return !!selector && jQuery.multiFilter( selector, this ).length > 0; + }, + + hasClass: function( selector ) { + return !!selector && this.is( "." + selector ); + }, + + val: function( value ) { + if ( value === undefined ) { + var elem = this[0]; + + if ( elem ) { + if( jQuery.nodeName( elem, 'option' ) ) + return (elem.attributes.value || {}).specified ? elem.value : elem.text; + + // We need to handle select boxes special + if ( jQuery.nodeName( elem, "select" ) ) { + var index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type == "select-one"; + + // Nothing was selected + if ( index < 0 ) + return null; + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + if ( option.selected ) { + // Get the specifc value for the option + value = jQuery(option).val(); + + // We don't need an array for one selects + if ( one ) + return value; + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + } + + // Everything else, we just grab the value + return (elem.value || "").replace(/\r/g, ""); + + } + + return undefined; + } + + if ( typeof value === "number" ) + value += ''; + + return this.each(function(){ + if ( this.nodeType != 1 ) + return; + + if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) ) + this.checked = (jQuery.inArray(this.value, value) >= 0 || + jQuery.inArray(this.name, value) >= 0); + + else if ( jQuery.nodeName( this, "select" ) ) { + var values = jQuery.makeArray(value); + + jQuery( "option", this ).each(function(){ + this.selected = (jQuery.inArray( this.value, values ) >= 0 || + jQuery.inArray( this.text, values ) >= 0); + }); + + if ( !values.length ) + this.selectedIndex = -1; + + } else + this.value = value; + }); + }, + + html: function( value ) { + return value === undefined ? + (this[0] ? + this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") : + null) : + this.empty().append( value ); + }, + + replaceWith: function( value ) { + return this.after( value ).remove(); + }, + + eq: function( i ) { + return this.slice( i, +i + 1 ); + }, + + slice: function() { + return this.pushStack( Array.prototype.slice.apply( this, arguments ), + "slice", Array.prototype.slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function(elem, i){ + return callback.call( elem, i, elem ); + })); + }, + + andSelf: function() { + return this.add( this.prevObject ); + }, + + domManip: function( args, table, callback ) { + if ( this[0] ) { + var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(), + scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ), + first = fragment.firstChild; + + if ( first ) + for ( var i = 0, l = this.length; i < l; i++ ) + callback.call( root(this[i], first), this.length > 1 || i > 0 ? + fragment.cloneNode(true) : fragment ); + + if ( scripts ) + jQuery.each( scripts, evalScript ); + } + + return this; + + function root( elem, cur ) { + return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ? + (elem.getElementsByTagName("tbody")[0] || + elem.appendChild(elem.ownerDocument.createElement("tbody"))) : + elem; + } + } +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +function evalScript( i, elem ) { + if ( elem.src ) + jQuery.ajax({ + url: elem.src, + async: false, + dataType: "script" + }); + + else + jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); + + if ( elem.parentNode ) + elem.parentNode.removeChild( elem ); +} + +function now(){ + return +new Date; +} + +jQuery.extend = jQuery.fn.extend = function() { + // copy reference to target object + var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) + target = {}; + + // extend jQuery itself if only one argument is passed + if ( length == i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) + // Extend the base object + for ( var name in options ) { + var src = target[ name ], copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) + continue; + + // Recurse if we're merging object values + if ( deep && copy && typeof copy === "object" && !copy.nodeType ) + target[ name ] = jQuery.extend( deep, + // Never move original objects, clone them + src || ( copy.length != null ? [ ] : { } ) + , copy ); + + // Don't bring in undefined values + else if ( copy !== undefined ) + target[ name ] = copy; + + } + + // Return the modified object + return target; +}; + +// exclude the following css properties to add px +var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i, + // cache defaultView + defaultView = document.defaultView || {}, + toString = Object.prototype.toString; + +jQuery.extend({ + noConflict: function( deep ) { + window.$ = _$; + + if ( deep ) + window.jQuery = _jQuery; + + return jQuery; + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return toString.call(obj) === "[object Function]"; + }, + + isArray: function( obj ) { + return toString.call(obj) === "[object Array]"; + }, + + // check if an element is in a (or is an) XML document + isXMLDoc: function( elem ) { + return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" || + !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument ); + }, + + // Evalulates a script in a global context + globalEval: function( data ) { + if ( data && /\S/.test(data) ) { + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.getElementsByTagName("head")[0] || document.documentElement, + script = document.createElement("script"); + + script.type = "text/javascript"; + if ( jQuery.support.scriptEval ) + script.appendChild( document.createTextNode( data ) ); + else + script.text = data; + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709). + head.insertBefore( script, head.firstChild ); + head.removeChild( script ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, length = object.length; + + if ( args ) { + if ( length === undefined ) { + for ( name in object ) + if ( callback.apply( object[ name ], args ) === false ) + break; + } else + for ( ; i < length; ) + if ( callback.apply( object[ i++ ], args ) === false ) + break; + + // A special, fast, case for the most common use of each + } else { + if ( length === undefined ) { + for ( name in object ) + if ( callback.call( object[ name ], name, object[ name ] ) === false ) + break; + } else + for ( var value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} + } + + return object; + }, + + prop: function( elem, value, type, i, name ) { + // Handle executable functions + if ( jQuery.isFunction( value ) ) + value = value.call( elem, i ); + + // Handle passing in a number to a CSS property + return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ? + value + "px" : + value; + }, + + className: { + // internal only, use addClass("class") + add: function( elem, classNames ) { + jQuery.each((classNames || "").split(/\s+/), function(i, className){ + if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) ) + elem.className += (elem.className ? " " : "") + className; + }); + }, + + // internal only, use removeClass("class") + remove: function( elem, classNames ) { + if (elem.nodeType == 1) + elem.className = classNames !== undefined ? + jQuery.grep(elem.className.split(/\s+/), function(className){ + return !jQuery.className.has( classNames, className ); + }).join(" ") : + ""; + }, + + // internal only, use hasClass("class") + has: function( elem, className ) { + return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1; + } + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations + swap: function( elem, options, callback ) { + var old = {}; + // Remember the old values, and insert the new ones + for ( var name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + callback.call( elem ); + + // Revert the old values + for ( var name in options ) + elem.style[ name ] = old[ name ]; + }, + + css: function( elem, name, force, extra ) { + if ( name == "width" || name == "height" ) { + var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ]; + + function getWH() { + val = name == "width" ? elem.offsetWidth : elem.offsetHeight; + + if ( extra === "border" ) + return; + + jQuery.each( which, function() { + if ( !extra ) + val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0; + if ( extra === "margin" ) + val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0; + else + val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0; + }); + } + + if ( elem.offsetWidth !== 0 ) + getWH(); + else + jQuery.swap( elem, props, getWH ); + + return Math.max(0, Math.round(val)); + } + + return jQuery.curCSS( elem, name, force ); + }, + + curCSS: function( elem, name, force ) { + var ret, style = elem.style; + + // We need to handle opacity special in IE + if ( name == "opacity" && !jQuery.support.opacity ) { + ret = jQuery.attr( style, "opacity" ); + + return ret == "" ? + "1" : + ret; + } + + // Make sure we're using the right name for getting the float value + if ( name.match( /float/i ) ) + name = styleFloat; + + if ( !force && style && style[ name ] ) + ret = style[ name ]; + + else if ( defaultView.getComputedStyle ) { + + // Only "float" is needed here + if ( name.match( /float/i ) ) + name = "float"; + + name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase(); + + var computedStyle = defaultView.getComputedStyle( elem, null ); + + if ( computedStyle ) + ret = computedStyle.getPropertyValue( name ); + + // We should always get a number back from opacity + if ( name == "opacity" && ret == "" ) + ret = "1"; + + } else if ( elem.currentStyle ) { + var camelCase = name.replace(/\-(\w)/g, function(all, letter){ + return letter.toUpperCase(); + }); + + ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ]; + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { + // Remember the original values + var left = style.left, rsLeft = elem.runtimeStyle.left; + + // Put in the new values to get a computed value out + elem.runtimeStyle.left = elem.currentStyle.left; + style.left = ret || 0; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + elem.runtimeStyle.left = rsLeft; + } + } + + return ret; + }, + + clean: function( elems, context, fragment ) { + context = context || document; + + // !context.createElement fails in IE with an error but returns typeof 'object' + if ( typeof context.createElement === "undefined" ) + context = context.ownerDocument || context[0] && context[0].ownerDocument || document; + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) { + var match = /^<(\w+)\s*\/?>$/.exec(elems[0]); + if ( match ) + return [ context.createElement( match[1] ) ]; + } + + var ret = [], scripts = [], div = context.createElement("div"); + + jQuery.each(elems, function(i, elem){ + if ( typeof elem === "number" ) + elem += ''; + + if ( !elem ) + return; + + // Convert html string into DOM nodes + if ( typeof elem === "string" ) { + // Fix "XHTML"-style tags in all browsers + elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){ + return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? + all : + front + ">"; + }); + + // Trim whitespace, otherwise indexOf won't work as expected + var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase(); + + var wrap = + // option or optgroup + !tags.indexOf("", "" ] || + + !tags.indexOf("", "" ] || + + tags.match(/^<(thead|tbody|tfoot|colg|cap)/) && + [ 1, "", "
    " ] || + + !tags.indexOf("", "" ] || + + // matched above + (!tags.indexOf("", "" ] || + + !tags.indexOf("", "" ] || + + // IE can't serialize and + +
    +Payments + +
    +
    + Add Another Payment +
    +
    + +inputs(); +echo '
    ' . "\n"; +echo $form->end('Send'); + +echo '
    ' . "\n"; + +?> +Clear Debug Output +
    + + + + + + +
    + + diff --git a/site/views/layouts/default.ctp b/site/views/layouts/default.ctp index f8ece79..0481e80 100644 --- a/site/views/layouts/default.ctp +++ b/site/views/layouts/default.ctp @@ -40,6 +40,8 @@ echo $html->css('jquery/start/ui.all') . "\n"; echo $javascript->link('jquery/jquery') . "\n"; echo $javascript->link('jquery/jquery-ui') . "\n"; + echo $javascript->link('jquery.form') . "\n"; + echo $javascript->link('pmgr') . "\n"; echo $scripts_for_layout . "\n"; ?> diff --git a/site/webroot/css/layout.css b/site/webroot/css/layout.css index 0a4bd8a..edf2314 100644 --- a/site/webroot/css/layout.css +++ b/site/webroot/css/layout.css @@ -136,6 +136,61 @@ table.list.ledger td.date.receipt { padding-left: 1em; } table.list.ledger td.evnrow { background: #f4f4f4; } + +/************************************************************ + ************************************************************ + * Forms + */ + +form { + margin-right: 20px; + padding: 0; + width: 80%; +} +fieldset { + border: 1px solid #ccc; + margin-top: 4px; +/* padding: 4px 4px; */ +} +fieldset legend { +/* background:#fff; */ +/* color: #e32; */ +/* font-size: 120%; */ + font-weight: bold; +} +fieldset fieldset { + margin: 4px 4px; +/* margin-bottom: 20px; */ + padding: 4px 4px; +} +fieldset fieldset legend { + font-size: 100%; + font-weight: normal; +} +fieldset fieldset div { + clear: left; +/* margin: 0 20px; */ +} +form div { + clear: both; +/* margin-bottom: 1em; */ +/* padding: .5em; */ + vertical-align: text-top; +} +form div.input { + color: #444; +} +form div.required { + color: #333; + font-weight: bold; +} +form div.submit { + border: 0; + clear: both; + margin-top: 10px; + margin-left: 140px; +} + /************************************************************ ************************************************************ * General Style Info @@ -189,17 +244,3 @@ h4 { } - -/* Forms */ -} -input[type=checkbox] { - clear: left; - float: left; - margin: 0px 6px 7px 2px; - width: auto; -} -input[type=radio] { - float:left; - width:auto; - margin: 0 3px 7px 0; -} diff --git a/site/webroot/js/pmgr.js b/site/webroot/js/pmgr.js new file mode 100644 index 0000000..d45892d --- /dev/null +++ b/site/webroot/js/pmgr.js @@ -0,0 +1,116 @@ +/** + * Function : dump() + * Arguments: The data - array,hash(associative array),object + * The level - OPTIONAL + * Returns : The textual representation of the array. + * This function was inspired by the print_r function of PHP. + * This will accept some data as the argument and return a + * text that will be a more readable version of the + * array/hash/object that is given. + * Docs: http://www.openjs.com/scripts/others/dump_function_php_print_r.php + */ +function dump(arr,level) { + var dumped_text = ""; + if(!level) level = 0; + + //The padding given at the beginning of the line. + var level_padding = ""; + for(var j=0;j \"" + value + "\"\n"; + } + } + } else { //Stings/Chars/Numbers etc. + dumped_text = "===>"+arr+"<===("+typeof(arr)+")"; + } + return dumped_text; +} + + +function var_dump(element, limit, depth) +{ + depth = depth?depth:0; + limit = limit?limit:1; + + returnString = '
      '; + + for(property in element) + { + //Property domConfig isn't accessable + if (property != 'domConfig') + { + returnString += '
    1. '+ property + ' (' + (typeof element[property]) +')'; + + if (typeof element[property] == 'number' || typeof element[property] == 'boolean') + returnString += ' : ' + element[property] + ''; + if (typeof element[property] == 'string' && element[property]) + returnString += ':
      ' + + element[property].replace(//g, '&gt;') + '
      '; + + if ((typeof element[property] == 'object') && (depth < limit)) + returnString += var_dump(element[property], limit, (depth + 1)); + + returnString += '
    2. '; + } + } + returnString += '
    '; + + if(depth == 0) + { + winpop = window.open("", "","width=800,height=600,scrollbars,resizable"); + winpop.document.write('
    '+returnString+ '
    '); + winpop.document.close(); + } + + return returnString; +} + + +function htmlEncode(s) +{ + //return s; + return s.replace(/&(?!\w+([;\s]|$))/g, "&") + .replace(//g, ">"); +} + +function addDiv(id_name, div_name, into_div_name, flash, html, script) { + var id = $('#'+id_name).val(); + + html = '
    ' + + html.replace(/%{id}/g, id) + .replace(/%{remove(:([^}]*))?}/g, + '' + + '' + + ("$2" == "" ? "$2" : 'remove') + '' + '') + + '
    '; + + if (script != "") { + html += ''; + } + +$("#debug").append(htmlEncode(html)); + $("#"+into_div_name).append(html); + + if (flash) { + $('#'+div_name+'-'+id) + .animate({ backgroundColor: "yellow" }, 300) + .animate({ backgroundColor: "white" }, 500); + } + + id = id - 0 + 1; + $('#'+id_name).val(id); +} + +function removeElement(elem_id) { + $('#'+elem_id).remove(); +} From 839d9c1697af6bb612f9aacbea62401f528d6503 Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 12 Jun 2009 02:35:13 +0000 Subject: [PATCH 099/717] cleaned up and put the different payment types into a loop for reuse. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@100 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/customers/payment.ctp | 207 +++++++------------------------ site/webroot/js/pmgr.js | 2 +- 2 files changed, 48 insertions(+), 161 deletions(-) diff --git a/site/views/customers/payment.ctp b/site/views/customers/payment.ctp index 5b0fb43..def1d22 100644 --- a/site/views/customers/payment.ctp +++ b/site/views/customers/payment.ctp @@ -127,36 +127,23 @@ echo $form->create(null, array('id' => 'payment-form', 'action' => 'payment')); '
    ' + 'Payment #%{id} (%{remove})' + - '
    ' - + ( - '
    ' - + ( - '' + - '' + - '' ) + - '
    ' + + '
    ' + + ' - + ( - '' + - '' + - '' ) + - '
    ' + - - '
    ' - + ( - '' + - '' + - '' ) + - '
    ' + - - '' ) + + foreach ($types AS $type => $name) { + $div = '
    '; + $div .= ''; + $div .= ' '; + $div .= '
    '; + echo "'$div' +\n"; + } + ?> '
    ' + '
    ' @@ -167,121 +154,26 @@ echo $form->create(null, array('id' => 'payment-form', 'action' => 'payment')); '' ) + '
    ' + - '' + + $name) { + if ($type == 'cash') + continue; - '' + + $div = ' - '' + - - '' + - - '
    ', - - // Javascript section -/* '$("#payment-type-cash-%{id}").click(function () {' + */ -/* ' $("#payment-check-div-%{id}").slideUp();' + */ -/* ' $("#payment-moneyorder-div-%{id}").slideUp();' + */ -/* ' $("#payment-ach-div-%{id}").slideUp();' + */ -/* ' $("#payment-creditcard-div-%{id}").slideUp();' + */ -/* ' $("#payment-cash-div-%{id}").slideDown();' + */ -/* '});' + */ - -/* '$("#payment-type-check-%{id}").click(function () {' + */ -/* ' $("#payment-cash-div-%{id}").slideUp();' + */ -/* ' $("#payment-moneyorder-div-%{id}").slideUp();' + */ -/* ' $("#payment-ach-div-%{id}").slideUp();' + */ -/* ' $("#payment-creditcard-div-%{id}").slideUp();' + */ -/* ' $("#payment-check-div-%{id}").slideDown();' + */ -/* '});' + */ - -/* '$("#payment-type-moneyorder-%{id}").click(function () {' + */ -/* ' $("#payment-cash-div-%{id}").slideUp();' + */ -/* ' $("#payment-check-div-%{id}").slideUp();' + */ -/* ' $("#payment-ach-div-%{id}").slideUp();' + */ -/* ' $("#payment-creditcard-div-%{id}").slideUp();' + */ - -/* ' $("#payment-moneyorder-div-%{id}").html(\'' + */ -/* '
    ' + */ -/* ' ' + */ -/* ' ' + */ -/* '
    \');' + */ -/* ' $("#payment-moneyorder-div-%{id}").slideDown();' + */ -/* '});' + */ - -/* '$(".payment-type-%{id}").click(function () {' + */ -/* ' switchPaymentType(%{id}, this);' + */ -/* '});' + */ - -/* '$(".payment-type-%{id}").click(function () {' + */ -/* 'alert("hello");' + */ -/* '});' + */ - - '' + '' ); @@ -291,14 +183,13 @@ function switchPaymentType(paymentid, type) { $(".payment-type-div-"+paymentid).slideUp(); $(".payment-type-div-"+paymentid).html(''); - html = ''; // '
    '; // STYLE="display:inline;" switch(type) { case 'cash': break; case 'check': - html += + html = '
    ' + ' ' + ' Money Order Number' + ' Routing Number' + ' Account Number' + ' ' + '
    ' + - '
    ' + '
    ' + ' ' + ' ' + '
    ' + - '
    ' + '
    ' + ' ' + ' ' + '
    '; + break; default: + html = '

    INVALID TYPE ('+type+')

    '; break; } - //html += '
    '; $("#payment-"+type+"-div-"+paymentid).html(html); $("#payment-"+type+"-div-"+paymentid).slideDown(); @@ -363,12 +255,12 @@ function switchPaymentType(paymentid, type) { -->
    -Payments - -
    -
    - Add Another Payment -
    + Payments + +
    +
    + Add Another Payment +
    ' . "\n"; $('#payment-id').val(1); addPaymentSource(false); $("#datepicker").datepicker(); - //$("#debug").html(htmlEncode($("#datepicker").html())); }); - -
    diff --git a/site/webroot/js/pmgr.js b/site/webroot/js/pmgr.js index d45892d..4586006 100644 --- a/site/webroot/js/pmgr.js +++ b/site/webroot/js/pmgr.js @@ -92,7 +92,7 @@ function addDiv(id_name, div_name, into_div_name, flash, html, script) { ("$2" == "" ? "$2" : 'remove') + '' + '') + '
    '; - if (script != "") { + if (script) { html += ''; From cca48fe86aed7a38b827cd7856406a74ee3ce21a Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 12 Jun 2009 02:45:48 +0000 Subject: [PATCH 100/717] More minor cleanup git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@101 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/customers/payment.ctp | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/site/views/customers/payment.ctp b/site/views/customers/payment.ctp index def1d22..b3c2b88 100644 --- a/site/views/customers/payment.ctp +++ b/site/views/customers/payment.ctp @@ -86,7 +86,12 @@ echo $form->create(null, array('id' => 'payment-form', 'action' => 'payment')); // $.ajax options can be used here too, for example: //timeout: 3000 }; - + + // Get a clean slate for our payments + $('#payments').html(''); + $('#payment-id').val(1); + addPaymentSource(false); + // bind form using 'ajaxForm' $('#payment-form').ajaxForm(options); }); @@ -146,12 +151,11 @@ echo $form->create(null, array('id' => 'payment-form', 'action' => 'payment')); ?> '
    ' + - '
    ' - + ( - '' + - '' + - '' ) + + '
    ' + + ' ' + + ' ' + '
    ' + create(null, array('id' => 'payment-form', 'action' => 'payment')); } ?> -/* '' + */ -/* '' + */ -/* '' + */ -/* '' + */ - '' ); @@ -269,8 +268,6 @@ function switchPaymentType(paymentid, type) { echo '
    ' . "\n"; echo $form->end('Send'); -echo '
    ' . "\n"; - ?> Clear Debug Output
    @@ -281,9 +278,6 @@ echo '
    ' . "\n"; From e32a5e5d4cad4bb887b08669871a51a8e411f0c6 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 13 Jun 2009 03:46:17 +0000 Subject: [PATCH 101/717] Check in a version of the debug toolkit that I've added debug prints to. They're commented out at the moment, but may come in handy later. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@102 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/plugins/debug_kit/views/debug.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/site/plugins/debug_kit/views/debug.php b/site/plugins/debug_kit/views/debug.php index d296bc6..ed2a2a4 100644 --- a/site/plugins/debug_kit/views/debug.php +++ b/site/plugins/debug_kit/views/debug.php @@ -50,6 +50,10 @@ class DebugView extends DoppelGangerView { * @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; } @@ -62,6 +66,10 @@ class DebugView extends DoppelGangerView { 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; } @@ -76,16 +84,29 @@ class DebugView extends DoppelGangerView { * @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; } From 2f91dd456a07f25a4fc35ef573d5b43d1b2db79f Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 13 Jun 2009 03:51:29 +0000 Subject: [PATCH 102/717] Added jqGrid 3.4.4 and started the work to upgrade our table to use it. The work is by no means done, but it is at leasting working to some degree. I have some customer changes in mind and want to switch gears, so I'm checking in. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@103 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/customers_controller.php | 151 +- site/vendors/css/jqGrid/basic/grid.css | 447 +++++ .../css/jqGrid/basic/images/cd_run.gif | Bin 0 -> 1025 bytes .../vendors/css/jqGrid/basic/images/dirty.gif | Bin 0 -> 832 bytes site/vendors/css/jqGrid/basic/images/down.gif | Bin 0 -> 309 bytes site/vendors/css/jqGrid/basic/images/find.gif | Bin 0 -> 986 bytes .../vendors/css/jqGrid/basic/images/first.gif | Bin 0 -> 925 bytes .../css/jqGrid/basic/images/folder.png | Bin 0 -> 229 bytes .../css/jqGrid/basic/images/grid-blue-ft.gif | Bin 0 -> 821 bytes .../css/jqGrid/basic/images/grid-blue-hd.gif | Bin 0 -> 821 bytes .../css/jqGrid/basic/images/headerbg.gif | Bin 0 -> 87 bytes .../css/jqGrid/basic/images/headerleft.gif | Bin 0 -> 425 bytes .../css/jqGrid/basic/images/headerright.gif | Bin 0 -> 87 bytes .../css/jqGrid/basic/images/ico-close.gif | Bin 0 -> 957 bytes site/vendors/css/jqGrid/basic/images/last.gif | Bin 0 -> 923 bytes .../vendors/css/jqGrid/basic/images/line3.gif | Bin 0 -> 70 bytes .../css/jqGrid/basic/images/loading.gif | Bin 0 -> 771 bytes .../vendors/css/jqGrid/basic/images/minus.gif | Bin 0 -> 85 bytes site/vendors/css/jqGrid/basic/images/next.gif | Bin 0 -> 875 bytes .../css/jqGrid/basic/images/nochild.gif | Bin 0 -> 66 bytes .../css/jqGrid/basic/images/off-first.gif | Bin 0 -> 925 bytes .../css/jqGrid/basic/images/off-last.gif | Bin 0 -> 923 bytes .../css/jqGrid/basic/images/off-next.gif | Bin 0 -> 875 bytes .../css/jqGrid/basic/images/off-prev.gif | Bin 0 -> 879 bytes site/vendors/css/jqGrid/basic/images/plus.gif | Bin 0 -> 89 bytes site/vendors/css/jqGrid/basic/images/prev.gif | Bin 0 -> 879 bytes .../css/jqGrid/basic/images/refresh.gif | Bin 0 -> 581 bytes .../css/jqGrid/basic/images/resize.gif | Bin 0 -> 862 bytes .../css/jqGrid/basic/images/row_add.gif | Bin 0 -> 635 bytes .../css/jqGrid/basic/images/row_delete.gif | Bin 0 -> 634 bytes .../css/jqGrid/basic/images/row_edit.gif | Bin 0 -> 996 bytes .../css/jqGrid/basic/images/sort_asc.gif | Bin 0 -> 830 bytes .../css/jqGrid/basic/images/sort_desc.gif | Bin 0 -> 833 bytes .../css/jqGrid/basic/images/spacer.gif | Bin 0 -> 43 bytes .../css/jqGrid/basic/images/tab_close-on.gif | Bin 0 -> 351 bytes .../css/jqGrid/basic/images/tree_leaf.gif | Bin 0 -> 134 bytes .../css/jqGrid/basic/images/tree_minus.gif | Bin 0 -> 132 bytes .../css/jqGrid/basic/images/tree_plus.gif | Bin 0 -> 138 bytes site/vendors/css/jqGrid/basic/images/up.gif | Bin 0 -> 312 bytes site/vendors/css/jqGrid/coffee/grid.css | 457 +++++ .../css/jqGrid/coffee/images/cd_run.gif | Bin 0 -> 1025 bytes .../css/jqGrid/coffee/images/dirty.gif | Bin 0 -> 832 bytes .../vendors/css/jqGrid/coffee/images/down.gif | Bin 0 -> 683 bytes .../vendors/css/jqGrid/coffee/images/find.gif | Bin 0 -> 986 bytes .../css/jqGrid/coffee/images/first.gif | Bin 0 -> 734 bytes .../css/jqGrid/coffee/images/folder.png | Bin 0 -> 229 bytes .../css/jqGrid/coffee/images/grid-blue-ft.gif | Bin 0 -> 165 bytes .../css/jqGrid/coffee/images/grid-blue-hd.gif | Bin 0 -> 165 bytes .../css/jqGrid/coffee/images/headerbg.gif | Bin 0 -> 105 bytes .../css/jqGrid/coffee/images/headerleft.gif | Bin 0 -> 236 bytes .../css/jqGrid/coffee/images/headerright.gif | Bin 0 -> 235 bytes .../css/jqGrid/coffee/images/ico-close.gif | Bin 0 -> 854 bytes .../vendors/css/jqGrid/coffee/images/last.gif | Bin 0 -> 737 bytes .../css/jqGrid/coffee/images/line3.gif | Bin 0 -> 70 bytes .../css/jqGrid/coffee/images/loading.gif | Bin 0 -> 771 bytes .../css/jqGrid/coffee/images/minus.gif | Bin 0 -> 85 bytes .../vendors/css/jqGrid/coffee/images/next.gif | Bin 0 -> 483 bytes .../css/jqGrid/coffee/images/nochild.gif | Bin 0 -> 66 bytes .../css/jqGrid/coffee/images/off-first.gif | Bin 0 -> 483 bytes .../css/jqGrid/coffee/images/off-last.gif | Bin 0 -> 485 bytes .../css/jqGrid/coffee/images/off-next.gif | Bin 0 -> 476 bytes .../css/jqGrid/coffee/images/off-prev.gif | Bin 0 -> 479 bytes .../vendors/css/jqGrid/coffee/images/plus.gif | Bin 0 -> 89 bytes .../vendors/css/jqGrid/coffee/images/prev.gif | Bin 0 -> 483 bytes .../css/jqGrid/coffee/images/refresh.gif | Bin 0 -> 581 bytes .../css/jqGrid/coffee/images/resize.gif | Bin 0 -> 862 bytes .../css/jqGrid/coffee/images/row_add.gif | Bin 0 -> 635 bytes .../css/jqGrid/coffee/images/row_delete.gif | Bin 0 -> 634 bytes .../css/jqGrid/coffee/images/row_edit.gif | Bin 0 -> 996 bytes .../css/jqGrid/coffee/images/sort_asc.gif | Bin 0 -> 114 bytes .../css/jqGrid/coffee/images/sort_desc.gif | Bin 0 -> 113 bytes .../css/jqGrid/coffee/images/spacer.gif | Bin 0 -> 43 bytes .../css/jqGrid/coffee/images/tab_close-on.gif | Bin 0 -> 351 bytes .../css/jqGrid/coffee/images/tree_leaf.gif | Bin 0 -> 134 bytes .../css/jqGrid/coffee/images/tree_minus.gif | Bin 0 -> 132 bytes .../css/jqGrid/coffee/images/tree_plus.gif | Bin 0 -> 138 bytes site/vendors/css/jqGrid/coffee/images/up.gif | Bin 0 -> 673 bytes site/vendors/css/jqGrid/green/grid.css | 459 +++++ .../css/jqGrid/green/images/cd_run.gif | Bin 0 -> 1025 bytes .../vendors/css/jqGrid/green/images/dirty.gif | Bin 0 -> 832 bytes site/vendors/css/jqGrid/green/images/down.gif | Bin 0 -> 734 bytes site/vendors/css/jqGrid/green/images/find.gif | Bin 0 -> 986 bytes .../vendors/css/jqGrid/green/images/first.gif | Bin 0 -> 763 bytes .../css/jqGrid/green/images/folder.png | Bin 0 -> 229 bytes .../css/jqGrid/green/images/grid-blue-ft.gif | Bin 0 -> 165 bytes .../css/jqGrid/green/images/grid-blue-hd.gif | Bin 0 -> 165 bytes .../css/jqGrid/green/images/headerbg.gif | Bin 0 -> 105 bytes .../css/jqGrid/green/images/headerleft.gif | Bin 0 -> 236 bytes .../css/jqGrid/green/images/headerright.gif | Bin 0 -> 235 bytes .../css/jqGrid/green/images/ico-close.gif | Bin 0 -> 854 bytes site/vendors/css/jqGrid/green/images/last.gif | Bin 0 -> 760 bytes site/vendors/css/jqGrid/green/images/leaf.gif | Bin 0 -> 203 bytes .../vendors/css/jqGrid/green/images/line3.gif | Bin 0 -> 70 bytes .../css/jqGrid/green/images/loading.gif | Bin 0 -> 771 bytes .../vendors/css/jqGrid/green/images/minus.gif | Bin 0 -> 85 bytes site/vendors/css/jqGrid/green/images/next.gif | Bin 0 -> 1177 bytes .../css/jqGrid/green/images/nochild.gif | Bin 0 -> 66 bytes .../css/jqGrid/green/images/off-first.gif | Bin 0 -> 763 bytes .../css/jqGrid/green/images/off-last.gif | Bin 0 -> 760 bytes .../css/jqGrid/green/images/off-next.gif | Bin 0 -> 1177 bytes .../css/jqGrid/green/images/off-prev.gif | Bin 0 -> 1175 bytes site/vendors/css/jqGrid/green/images/plus.gif | Bin 0 -> 89 bytes site/vendors/css/jqGrid/green/images/prev.gif | Bin 0 -> 1175 bytes .../css/jqGrid/green/images/refresh.gif | Bin 0 -> 581 bytes .../css/jqGrid/green/images/resize.gif | Bin 0 -> 862 bytes .../css/jqGrid/green/images/row_add.gif | Bin 0 -> 635 bytes .../css/jqGrid/green/images/row_delete.gif | Bin 0 -> 634 bytes .../css/jqGrid/green/images/row_edit.gif | Bin 0 -> 996 bytes .../css/jqGrid/green/images/sort_asc.gif | Bin 0 -> 71 bytes .../css/jqGrid/green/images/sort_desc.gif | Bin 0 -> 55 bytes .../css/jqGrid/green/images/spacer.gif | Bin 0 -> 43 bytes .../css/jqGrid/green/images/tab_close-on.gif | Bin 0 -> 351 bytes .../css/jqGrid/green/images/tree_leaf.gif | Bin 0 -> 134 bytes .../css/jqGrid/green/images/tree_minus.gif | Bin 0 -> 132 bytes .../css/jqGrid/green/images/tree_plus.gif | Bin 0 -> 138 bytes site/vendors/css/jqGrid/green/images/up.gif | Bin 0 -> 735 bytes site/vendors/css/jqGrid/jqModal.css | 31 + site/vendors/css/jqGrid/sand/grid.css | 460 +++++ .../vendors/css/jqGrid/sand/images/cd_run.gif | Bin 0 -> 1025 bytes site/vendors/css/jqGrid/sand/images/dirty.gif | Bin 0 -> 832 bytes site/vendors/css/jqGrid/sand/images/down.gif | Bin 0 -> 379 bytes site/vendors/css/jqGrid/sand/images/find.gif | Bin 0 -> 986 bytes site/vendors/css/jqGrid/sand/images/first.gif | Bin 0 -> 399 bytes .../vendors/css/jqGrid/sand/images/folder.png | Bin 0 -> 229 bytes .../css/jqGrid/sand/images/grid-blue-ft.gif | Bin 0 -> 165 bytes .../css/jqGrid/sand/images/grid-blue-hd.gif | Bin 0 -> 165 bytes .../css/jqGrid/sand/images/headerbg.gif | Bin 0 -> 105 bytes .../css/jqGrid/sand/images/headerleft.gif | Bin 0 -> 197 bytes .../css/jqGrid/sand/images/headerright.gif | Bin 0 -> 258 bytes .../css/jqGrid/sand/images/ico-close.gif | Bin 0 -> 957 bytes site/vendors/css/jqGrid/sand/images/last.gif | Bin 0 -> 398 bytes site/vendors/css/jqGrid/sand/images/line3.gif | Bin 0 -> 70 bytes .../css/jqGrid/sand/images/loading.gif | Bin 0 -> 771 bytes site/vendors/css/jqGrid/sand/images/minus.gif | Bin 0 -> 85 bytes site/vendors/css/jqGrid/sand/images/next.gif | Bin 0 -> 392 bytes .../css/jqGrid/sand/images/nochild.gif | Bin 0 -> 66 bytes .../css/jqGrid/sand/images/off-first.gif | Bin 0 -> 399 bytes .../css/jqGrid/sand/images/off-last.gif | Bin 0 -> 398 bytes .../css/jqGrid/sand/images/off-next.gif | Bin 0 -> 392 bytes .../css/jqGrid/sand/images/off-prev.gif | Bin 0 -> 389 bytes site/vendors/css/jqGrid/sand/images/plus.gif | Bin 0 -> 89 bytes site/vendors/css/jqGrid/sand/images/prev.gif | Bin 0 -> 389 bytes .../css/jqGrid/sand/images/refresh.gif | Bin 0 -> 581 bytes .../vendors/css/jqGrid/sand/images/resize.gif | Bin 0 -> 862 bytes .../css/jqGrid/sand/images/row_add.gif | Bin 0 -> 635 bytes .../css/jqGrid/sand/images/row_delete.gif | Bin 0 -> 634 bytes .../css/jqGrid/sand/images/row_edit.gif | Bin 0 -> 996 bytes .../css/jqGrid/sand/images/sort_asc.gif | Bin 0 -> 56 bytes .../css/jqGrid/sand/images/sort_desc.gif | Bin 0 -> 55 bytes .../vendors/css/jqGrid/sand/images/spacer.gif | Bin 0 -> 43 bytes .../css/jqGrid/sand/images/tab_close-on.gif | Bin 0 -> 351 bytes .../css/jqGrid/sand/images/tree_leaf.gif | Bin 0 -> 134 bytes .../css/jqGrid/sand/images/tree_minus.gif | Bin 0 -> 132 bytes .../css/jqGrid/sand/images/tree_plus.gif | Bin 0 -> 138 bytes site/vendors/css/jqGrid/sand/images/up.gif | Bin 0 -> 382 bytes site/vendors/css/jqGrid/steel/grid.css | 599 ++++++ .../css/jqGrid/steel/images/._sprite5.png | Bin 0 -> 70 bytes .../css/jqGrid/steel/images/._sprite5.psd | Bin 0 -> 24138 bytes .../css/jqGrid/steel/images/Arrow2 Down.png | Bin 0 -> 387 bytes .../css/jqGrid/steel/images/Arrow2 Up.png | Bin 0 -> 428 bytes site/vendors/css/jqGrid/steel/images/bg.gif | Bin 0 -> 854 bytes .../css/jqGrid/steel/images/cd_run.gif | Bin 0 -> 1025 bytes .../css/jqGrid/steel/images/control_090.png | Bin 0 -> 393 bytes .../css/jqGrid/steel/images/control_270.png | Bin 0 -> 446 bytes .../vendors/css/jqGrid/steel/images/dirty.gif | Bin 0 -> 832 bytes site/vendors/css/jqGrid/steel/images/down.gif | Bin 0 -> 291 bytes site/vendors/css/jqGrid/steel/images/fhbg.gif | Bin 0 -> 836 bytes site/vendors/css/jqGrid/steel/images/find.gif | Bin 0 -> 1008 bytes .../vendors/css/jqGrid/steel/images/find1.gif | Bin 0 -> 986 bytes .../vendors/css/jqGrid/steel/images/first.gif | Bin 0 -> 925 bytes .../vendors/css/jqGrid/steel/images/first.png | Bin 0 -> 591 bytes .../css/jqGrid/steel/images/folder.png | Bin 0 -> 229 bytes .../css/jqGrid/steel/images/headerleft1.gif | Bin 0 -> 197 bytes .../css/jqGrid/steel/images/headerright1.gif | Bin 0 -> 258 bytes .../css/jqGrid/steel/images/ico-close.gif | Bin 0 -> 957 bytes site/vendors/css/jqGrid/steel/images/last.gif | Bin 0 -> 923 bytes site/vendors/css/jqGrid/steel/images/last.png | Bin 0 -> 583 bytes .../vendors/css/jqGrid/steel/images/line3.gif | Bin 0 -> 70 bytes .../css/jqGrid/steel/images/loading.gif | Bin 0 -> 771 bytes .../vendors/css/jqGrid/steel/images/minus.gif | Bin 0 -> 85 bytes site/vendors/css/jqGrid/steel/images/next.gif | Bin 0 -> 875 bytes site/vendors/css/jqGrid/steel/images/next.png | Bin 0 -> 469 bytes .../css/jqGrid/steel/images/nochild.gif | Bin 0 -> 66 bytes .../vendors/css/jqGrid/steel/images/odown.gif | Bin 0 -> 379 bytes .../css/jqGrid/steel/images/off-first.gif | Bin 0 -> 925 bytes .../css/jqGrid/steel/images/off-last.gif | Bin 0 -> 923 bytes .../css/jqGrid/steel/images/off-next.gif | Bin 0 -> 875 bytes .../css/jqGrid/steel/images/off-prev.gif | Bin 0 -> 879 bytes site/vendors/css/jqGrid/steel/images/oup.gif | Bin 0 -> 382 bytes site/vendors/css/jqGrid/steel/images/plus.gif | Bin 0 -> 89 bytes site/vendors/css/jqGrid/steel/images/prev.gif | Bin 0 -> 879 bytes site/vendors/css/jqGrid/steel/images/prev.png | Bin 0 -> 460 bytes .../css/jqGrid/steel/images/refresh.gif | Bin 0 -> 1015 bytes .../css/jqGrid/steel/images/refresh1.gif | Bin 0 -> 581 bytes .../css/jqGrid/steel/images/resize.gif | Bin 0 -> 862 bytes .../css/jqGrid/steel/images/row_add.gif | Bin 0 -> 994 bytes .../css/jqGrid/steel/images/row_add1.gif | Bin 0 -> 635 bytes .../css/jqGrid/steel/images/row_delete.gif | Bin 0 -> 989 bytes .../css/jqGrid/steel/images/row_delete1.gif | Bin 0 -> 634 bytes .../css/jqGrid/steel/images/row_edit.gif | Bin 0 -> 946 bytes .../css/jqGrid/steel/images/row_edit1.gif | Bin 0 -> 996 bytes .../css/jqGrid/steel/images/sort_asc.gif | Bin 0 -> 56 bytes .../css/jqGrid/steel/images/sort_desc.gif | Bin 0 -> 55 bytes .../css/jqGrid/steel/images/spacer.gif | Bin 0 -> 43 bytes .../css/jqGrid/steel/images/sprite.png | Bin 0 -> 3745 bytes .../css/jqGrid/steel/images/sprite5.png | Bin 0 -> 2823 bytes .../css/jqGrid/steel/images/sprite5.psd | Bin 0 -> 107682 bytes .../css/jqGrid/steel/images/tab_close-on.gif | Bin 0 -> 351 bytes .../css/jqGrid/steel/images/tree_leaf.gif | Bin 0 -> 134 bytes .../css/jqGrid/steel/images/tree_minus.gif | Bin 0 -> 132 bytes .../css/jqGrid/steel/images/tree_plus.gif | Bin 0 -> 138 bytes site/vendors/css/jqGrid/steel/images/up.gif | Bin 0 -> 297 bytes site/vendors/css/jqGrid/steel/images/wbg.gif | Bin 0 -> 868 bytes site/vendors/js/jqGrid/jquery.jqGrid.js | 68 + site/vendors/js/jqGrid/js/JsonXml.js | 345 ++++ site/vendors/js/jqGrid/js/grid.base.js | 1598 +++++++++++++++++ site/vendors/js/jqGrid/js/grid.celledit.js | 445 +++++ site/vendors/js/jqGrid/js/grid.common.js | 356 ++++ site/vendors/js/jqGrid/js/grid.custom.js | 437 +++++ site/vendors/js/jqGrid/js/grid.formedit.js | 1307 ++++++++++++++ site/vendors/js/jqGrid/js/grid.import.js | 132 ++ site/vendors/js/jqGrid/js/grid.inlinedit.js | 194 ++ site/vendors/js/jqGrid/js/grid.locale-bg.js | 113 ++ .../js/jqGrid/js/grid.locale-bg1251.js | 113 ++ site/vendors/js/jqGrid/js/grid.locale-cat.js | 107 ++ site/vendors/js/jqGrid/js/grid.locale-cs.js | 113 ++ site/vendors/js/jqGrid/js/grid.locale-de.js | 111 ++ site/vendors/js/jqGrid/js/grid.locale-dk.js | 109 ++ site/vendors/js/jqGrid/js/grid.locale-el.js | 112 ++ site/vendors/js/jqGrid/js/grid.locale-en.js | 120 ++ site/vendors/js/jqGrid/js/grid.locale-fa.js | 110 ++ site/vendors/js/jqGrid/js/grid.locale-fi.js | 109 ++ site/vendors/js/jqGrid/js/grid.locale-fr.js | 128 ++ site/vendors/js/jqGrid/js/grid.locale-is.js | 106 ++ site/vendors/js/jqGrid/js/grid.locale-it.js | 107 ++ site/vendors/js/jqGrid/js/grid.locale-jp.js | 113 ++ site/vendors/js/jqGrid/js/grid.locale-pl.js | 108 ++ .../vendors/js/jqGrid/js/grid.locale-pt-br.js | 108 ++ site/vendors/js/jqGrid/js/grid.locale-pt.js | 107 ++ site/vendors/js/jqGrid/js/grid.locale-ru.js | 108 ++ site/vendors/js/jqGrid/js/grid.locale-sp.js | 108 ++ site/vendors/js/jqGrid/js/grid.locale-sv.js | 110 ++ site/vendors/js/jqGrid/js/grid.locale-tr.js | 108 ++ site/vendors/js/jqGrid/js/grid.postext.js | 64 + site/vendors/js/jqGrid/js/grid.setcolumns.js | 78 + site/vendors/js/jqGrid/js/grid.subgrid.js | 255 +++ site/vendors/js/jqGrid/js/grid.tbltogrid.js | 105 ++ site/vendors/js/jqGrid/js/grid.treegrid.js | 428 +++++ site/vendors/js/jqGrid/js/jqDnR.js | 52 + site/vendors/js/jqGrid/js/jqModal.js | 69 + site/vendors/js/jqGrid/js/jquery.fmatter.js | 426 +++++ site/vendors/js/jqGrid/js/jquery.tablednd.js | 383 ++++ site/vendors/js/jqGrid/js/json2.js | 104 ++ site/vendors/js/jqGrid/js/min/JsonXml-min.js | 1 + .../vendors/js/jqGrid/js/min/grid.base-min.js | 1 + .../js/jqGrid/js/min/grid.celledit-min.js | 1 + .../js/jqGrid/js/min/grid.common-min.js | 1 + .../js/jqGrid/js/min/grid.custom-min.js | 1 + .../js/jqGrid/js/min/grid.formedit-min.js | 1 + .../js/jqGrid/js/min/grid.import-min.js | 1 + .../js/jqGrid/js/min/grid.inlinedit-min.js | 1 + .../js/jqGrid/js/min/grid.locale-bg-min.js | 1 + .../jqGrid/js/min/grid.locale-bg1251-min.js | 1 + .../js/jqGrid/js/min/grid.locale-cat-min.js | 1 + .../js/jqGrid/js/min/grid.locale-cs-min.js | 1 + .../js/jqGrid/js/min/grid.locale-de-min.js | 1 + .../js/jqGrid/js/min/grid.locale-dk-min.js | 1 + .../js/jqGrid/js/min/grid.locale-el-min.js | 1 + .../js/jqGrid/js/min/grid.locale-en-min.js | 1 + .../js/jqGrid/js/min/grid.locale-fi-min.js | 1 + .../js/jqGrid/js/min/grid.locale-fr-min.js | 1 + .../js/jqGrid/js/min/grid.locale-is-min.js | 1 + .../js/jqGrid/js/min/grid.locale-it-min.js | 1 + .../js/jqGrid/js/min/grid.locale-jp-min.js | 1 + .../js/jqGrid/js/min/grid.locale-pl-min.js | 1 + .../js/jqGrid/js/min/grid.locale-pt-br-min.js | 1 + .../js/jqGrid/js/min/grid.locale-pt-min.js | 1 + .../js/jqGrid/js/min/grid.locale-ru-min.js | 1 + .../js/jqGrid/js/min/grid.locale-sp-min.js | 1 + .../js/jqGrid/js/min/grid.locale-tr-min.js | 1 + .../js/jqGrid/js/min/grid.postext-min.js | 1 + .../js/jqGrid/js/min/grid.setcolumns-min.js | 1 + .../js/jqGrid/js/min/grid.subgrid-min.js | 1 + .../js/jqGrid/js/min/grid.tbltogrid-min.js | 1 + .../js/jqGrid/js/min/grid.treegrid-min.js | 1 + site/vendors/js/jqGrid/js/min/jqDnR-min.js | 1 + site/vendors/js/jqGrid/js/min/jqModal-min.js | 1 + .../js/jqGrid/js/min/jquery.fmatter-min.js | 1 + .../js/jqGrid/js/min/jquery.tablednd-min.js | 1 + site/vendors/js/jqGrid/js/min/json2-min.js | 1 + site/views/elements/customers.ctp | 214 ++- 291 files changed, 11977 insertions(+), 52 deletions(-) create mode 100644 site/vendors/css/jqGrid/basic/grid.css create mode 100644 site/vendors/css/jqGrid/basic/images/cd_run.gif create mode 100644 site/vendors/css/jqGrid/basic/images/dirty.gif create mode 100644 site/vendors/css/jqGrid/basic/images/down.gif create mode 100644 site/vendors/css/jqGrid/basic/images/find.gif create mode 100644 site/vendors/css/jqGrid/basic/images/first.gif create mode 100644 site/vendors/css/jqGrid/basic/images/folder.png create mode 100644 site/vendors/css/jqGrid/basic/images/grid-blue-ft.gif create mode 100644 site/vendors/css/jqGrid/basic/images/grid-blue-hd.gif create mode 100644 site/vendors/css/jqGrid/basic/images/headerbg.gif create mode 100644 site/vendors/css/jqGrid/basic/images/headerleft.gif create mode 100644 site/vendors/css/jqGrid/basic/images/headerright.gif create mode 100644 site/vendors/css/jqGrid/basic/images/ico-close.gif create mode 100644 site/vendors/css/jqGrid/basic/images/last.gif create mode 100644 site/vendors/css/jqGrid/basic/images/line3.gif create mode 100644 site/vendors/css/jqGrid/basic/images/loading.gif create mode 100644 site/vendors/css/jqGrid/basic/images/minus.gif create mode 100644 site/vendors/css/jqGrid/basic/images/next.gif create mode 100644 site/vendors/css/jqGrid/basic/images/nochild.gif create mode 100644 site/vendors/css/jqGrid/basic/images/off-first.gif create mode 100644 site/vendors/css/jqGrid/basic/images/off-last.gif create mode 100644 site/vendors/css/jqGrid/basic/images/off-next.gif create mode 100644 site/vendors/css/jqGrid/basic/images/off-prev.gif create mode 100644 site/vendors/css/jqGrid/basic/images/plus.gif create mode 100644 site/vendors/css/jqGrid/basic/images/prev.gif create mode 100644 site/vendors/css/jqGrid/basic/images/refresh.gif create mode 100644 site/vendors/css/jqGrid/basic/images/resize.gif create mode 100644 site/vendors/css/jqGrid/basic/images/row_add.gif create mode 100644 site/vendors/css/jqGrid/basic/images/row_delete.gif create mode 100644 site/vendors/css/jqGrid/basic/images/row_edit.gif create mode 100644 site/vendors/css/jqGrid/basic/images/sort_asc.gif create mode 100644 site/vendors/css/jqGrid/basic/images/sort_desc.gif create mode 100644 site/vendors/css/jqGrid/basic/images/spacer.gif create mode 100644 site/vendors/css/jqGrid/basic/images/tab_close-on.gif create mode 100644 site/vendors/css/jqGrid/basic/images/tree_leaf.gif create mode 100644 site/vendors/css/jqGrid/basic/images/tree_minus.gif create mode 100644 site/vendors/css/jqGrid/basic/images/tree_plus.gif create mode 100644 site/vendors/css/jqGrid/basic/images/up.gif create mode 100644 site/vendors/css/jqGrid/coffee/grid.css create mode 100644 site/vendors/css/jqGrid/coffee/images/cd_run.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/dirty.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/down.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/find.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/first.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/folder.png create mode 100644 site/vendors/css/jqGrid/coffee/images/grid-blue-ft.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/grid-blue-hd.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/headerbg.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/headerleft.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/headerright.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/ico-close.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/last.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/line3.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/loading.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/minus.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/next.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/nochild.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/off-first.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/off-last.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/off-next.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/off-prev.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/plus.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/prev.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/refresh.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/resize.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/row_add.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/row_delete.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/row_edit.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/sort_asc.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/sort_desc.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/spacer.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/tab_close-on.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/tree_leaf.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/tree_minus.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/tree_plus.gif create mode 100644 site/vendors/css/jqGrid/coffee/images/up.gif create mode 100644 site/vendors/css/jqGrid/green/grid.css create mode 100644 site/vendors/css/jqGrid/green/images/cd_run.gif create mode 100644 site/vendors/css/jqGrid/green/images/dirty.gif create mode 100644 site/vendors/css/jqGrid/green/images/down.gif create mode 100644 site/vendors/css/jqGrid/green/images/find.gif create mode 100644 site/vendors/css/jqGrid/green/images/first.gif create mode 100644 site/vendors/css/jqGrid/green/images/folder.png create mode 100644 site/vendors/css/jqGrid/green/images/grid-blue-ft.gif create mode 100644 site/vendors/css/jqGrid/green/images/grid-blue-hd.gif create mode 100644 site/vendors/css/jqGrid/green/images/headerbg.gif create mode 100644 site/vendors/css/jqGrid/green/images/headerleft.gif create mode 100644 site/vendors/css/jqGrid/green/images/headerright.gif create mode 100644 site/vendors/css/jqGrid/green/images/ico-close.gif create mode 100644 site/vendors/css/jqGrid/green/images/last.gif create mode 100644 site/vendors/css/jqGrid/green/images/leaf.gif create mode 100644 site/vendors/css/jqGrid/green/images/line3.gif create mode 100644 site/vendors/css/jqGrid/green/images/loading.gif create mode 100644 site/vendors/css/jqGrid/green/images/minus.gif create mode 100644 site/vendors/css/jqGrid/green/images/next.gif create mode 100644 site/vendors/css/jqGrid/green/images/nochild.gif create mode 100644 site/vendors/css/jqGrid/green/images/off-first.gif create mode 100644 site/vendors/css/jqGrid/green/images/off-last.gif create mode 100644 site/vendors/css/jqGrid/green/images/off-next.gif create mode 100644 site/vendors/css/jqGrid/green/images/off-prev.gif create mode 100644 site/vendors/css/jqGrid/green/images/plus.gif create mode 100644 site/vendors/css/jqGrid/green/images/prev.gif create mode 100644 site/vendors/css/jqGrid/green/images/refresh.gif create mode 100644 site/vendors/css/jqGrid/green/images/resize.gif create mode 100644 site/vendors/css/jqGrid/green/images/row_add.gif create mode 100644 site/vendors/css/jqGrid/green/images/row_delete.gif create mode 100644 site/vendors/css/jqGrid/green/images/row_edit.gif create mode 100644 site/vendors/css/jqGrid/green/images/sort_asc.gif create mode 100644 site/vendors/css/jqGrid/green/images/sort_desc.gif create mode 100644 site/vendors/css/jqGrid/green/images/spacer.gif create mode 100644 site/vendors/css/jqGrid/green/images/tab_close-on.gif create mode 100644 site/vendors/css/jqGrid/green/images/tree_leaf.gif create mode 100644 site/vendors/css/jqGrid/green/images/tree_minus.gif create mode 100644 site/vendors/css/jqGrid/green/images/tree_plus.gif create mode 100644 site/vendors/css/jqGrid/green/images/up.gif create mode 100644 site/vendors/css/jqGrid/jqModal.css create mode 100644 site/vendors/css/jqGrid/sand/grid.css create mode 100644 site/vendors/css/jqGrid/sand/images/cd_run.gif create mode 100644 site/vendors/css/jqGrid/sand/images/dirty.gif create mode 100644 site/vendors/css/jqGrid/sand/images/down.gif create mode 100644 site/vendors/css/jqGrid/sand/images/find.gif create mode 100644 site/vendors/css/jqGrid/sand/images/first.gif create mode 100644 site/vendors/css/jqGrid/sand/images/folder.png create mode 100644 site/vendors/css/jqGrid/sand/images/grid-blue-ft.gif create mode 100644 site/vendors/css/jqGrid/sand/images/grid-blue-hd.gif create mode 100644 site/vendors/css/jqGrid/sand/images/headerbg.gif create mode 100644 site/vendors/css/jqGrid/sand/images/headerleft.gif create mode 100644 site/vendors/css/jqGrid/sand/images/headerright.gif create mode 100644 site/vendors/css/jqGrid/sand/images/ico-close.gif create mode 100644 site/vendors/css/jqGrid/sand/images/last.gif create mode 100644 site/vendors/css/jqGrid/sand/images/line3.gif create mode 100644 site/vendors/css/jqGrid/sand/images/loading.gif create mode 100644 site/vendors/css/jqGrid/sand/images/minus.gif create mode 100644 site/vendors/css/jqGrid/sand/images/next.gif create mode 100644 site/vendors/css/jqGrid/sand/images/nochild.gif create mode 100644 site/vendors/css/jqGrid/sand/images/off-first.gif create mode 100644 site/vendors/css/jqGrid/sand/images/off-last.gif create mode 100644 site/vendors/css/jqGrid/sand/images/off-next.gif create mode 100644 site/vendors/css/jqGrid/sand/images/off-prev.gif create mode 100644 site/vendors/css/jqGrid/sand/images/plus.gif create mode 100644 site/vendors/css/jqGrid/sand/images/prev.gif create mode 100644 site/vendors/css/jqGrid/sand/images/refresh.gif create mode 100644 site/vendors/css/jqGrid/sand/images/resize.gif create mode 100644 site/vendors/css/jqGrid/sand/images/row_add.gif create mode 100644 site/vendors/css/jqGrid/sand/images/row_delete.gif create mode 100644 site/vendors/css/jqGrid/sand/images/row_edit.gif create mode 100644 site/vendors/css/jqGrid/sand/images/sort_asc.gif create mode 100644 site/vendors/css/jqGrid/sand/images/sort_desc.gif create mode 100644 site/vendors/css/jqGrid/sand/images/spacer.gif create mode 100644 site/vendors/css/jqGrid/sand/images/tab_close-on.gif create mode 100644 site/vendors/css/jqGrid/sand/images/tree_leaf.gif create mode 100644 site/vendors/css/jqGrid/sand/images/tree_minus.gif create mode 100644 site/vendors/css/jqGrid/sand/images/tree_plus.gif create mode 100644 site/vendors/css/jqGrid/sand/images/up.gif create mode 100644 site/vendors/css/jqGrid/steel/grid.css create mode 100644 site/vendors/css/jqGrid/steel/images/._sprite5.png create mode 100644 site/vendors/css/jqGrid/steel/images/._sprite5.psd create mode 100644 site/vendors/css/jqGrid/steel/images/Arrow2 Down.png create mode 100644 site/vendors/css/jqGrid/steel/images/Arrow2 Up.png create mode 100644 site/vendors/css/jqGrid/steel/images/bg.gif create mode 100644 site/vendors/css/jqGrid/steel/images/cd_run.gif create mode 100644 site/vendors/css/jqGrid/steel/images/control_090.png create mode 100644 site/vendors/css/jqGrid/steel/images/control_270.png create mode 100644 site/vendors/css/jqGrid/steel/images/dirty.gif create mode 100644 site/vendors/css/jqGrid/steel/images/down.gif create mode 100644 site/vendors/css/jqGrid/steel/images/fhbg.gif create mode 100644 site/vendors/css/jqGrid/steel/images/find.gif create mode 100644 site/vendors/css/jqGrid/steel/images/find1.gif create mode 100644 site/vendors/css/jqGrid/steel/images/first.gif create mode 100644 site/vendors/css/jqGrid/steel/images/first.png create mode 100644 site/vendors/css/jqGrid/steel/images/folder.png create mode 100644 site/vendors/css/jqGrid/steel/images/headerleft1.gif create mode 100644 site/vendors/css/jqGrid/steel/images/headerright1.gif create mode 100644 site/vendors/css/jqGrid/steel/images/ico-close.gif create mode 100644 site/vendors/css/jqGrid/steel/images/last.gif create mode 100644 site/vendors/css/jqGrid/steel/images/last.png create mode 100644 site/vendors/css/jqGrid/steel/images/line3.gif create mode 100644 site/vendors/css/jqGrid/steel/images/loading.gif create mode 100644 site/vendors/css/jqGrid/steel/images/minus.gif create mode 100644 site/vendors/css/jqGrid/steel/images/next.gif create mode 100644 site/vendors/css/jqGrid/steel/images/next.png create mode 100644 site/vendors/css/jqGrid/steel/images/nochild.gif create mode 100644 site/vendors/css/jqGrid/steel/images/odown.gif create mode 100644 site/vendors/css/jqGrid/steel/images/off-first.gif create mode 100644 site/vendors/css/jqGrid/steel/images/off-last.gif create mode 100644 site/vendors/css/jqGrid/steel/images/off-next.gif create mode 100644 site/vendors/css/jqGrid/steel/images/off-prev.gif create mode 100644 site/vendors/css/jqGrid/steel/images/oup.gif create mode 100644 site/vendors/css/jqGrid/steel/images/plus.gif create mode 100644 site/vendors/css/jqGrid/steel/images/prev.gif create mode 100644 site/vendors/css/jqGrid/steel/images/prev.png create mode 100644 site/vendors/css/jqGrid/steel/images/refresh.gif create mode 100644 site/vendors/css/jqGrid/steel/images/refresh1.gif create mode 100644 site/vendors/css/jqGrid/steel/images/resize.gif create mode 100644 site/vendors/css/jqGrid/steel/images/row_add.gif create mode 100644 site/vendors/css/jqGrid/steel/images/row_add1.gif create mode 100644 site/vendors/css/jqGrid/steel/images/row_delete.gif create mode 100644 site/vendors/css/jqGrid/steel/images/row_delete1.gif create mode 100644 site/vendors/css/jqGrid/steel/images/row_edit.gif create mode 100644 site/vendors/css/jqGrid/steel/images/row_edit1.gif create mode 100644 site/vendors/css/jqGrid/steel/images/sort_asc.gif create mode 100644 site/vendors/css/jqGrid/steel/images/sort_desc.gif create mode 100644 site/vendors/css/jqGrid/steel/images/spacer.gif create mode 100644 site/vendors/css/jqGrid/steel/images/sprite.png create mode 100644 site/vendors/css/jqGrid/steel/images/sprite5.png create mode 100644 site/vendors/css/jqGrid/steel/images/sprite5.psd create mode 100644 site/vendors/css/jqGrid/steel/images/tab_close-on.gif create mode 100644 site/vendors/css/jqGrid/steel/images/tree_leaf.gif create mode 100644 site/vendors/css/jqGrid/steel/images/tree_minus.gif create mode 100644 site/vendors/css/jqGrid/steel/images/tree_plus.gif create mode 100644 site/vendors/css/jqGrid/steel/images/up.gif create mode 100644 site/vendors/css/jqGrid/steel/images/wbg.gif create mode 100644 site/vendors/js/jqGrid/jquery.jqGrid.js create mode 100644 site/vendors/js/jqGrid/js/JsonXml.js create mode 100644 site/vendors/js/jqGrid/js/grid.base.js create mode 100644 site/vendors/js/jqGrid/js/grid.celledit.js create mode 100644 site/vendors/js/jqGrid/js/grid.common.js create mode 100644 site/vendors/js/jqGrid/js/grid.custom.js create mode 100644 site/vendors/js/jqGrid/js/grid.formedit.js create mode 100644 site/vendors/js/jqGrid/js/grid.import.js create mode 100644 site/vendors/js/jqGrid/js/grid.inlinedit.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-bg.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-bg1251.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-cat.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-cs.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-de.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-dk.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-el.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-en.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-fa.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-fi.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-fr.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-is.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-it.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-jp.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-pl.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-pt-br.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-pt.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-ru.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-sp.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-sv.js create mode 100644 site/vendors/js/jqGrid/js/grid.locale-tr.js create mode 100644 site/vendors/js/jqGrid/js/grid.postext.js create mode 100644 site/vendors/js/jqGrid/js/grid.setcolumns.js create mode 100644 site/vendors/js/jqGrid/js/grid.subgrid.js create mode 100644 site/vendors/js/jqGrid/js/grid.tbltogrid.js create mode 100644 site/vendors/js/jqGrid/js/grid.treegrid.js create mode 100644 site/vendors/js/jqGrid/js/jqDnR.js create mode 100644 site/vendors/js/jqGrid/js/jqModal.js create mode 100644 site/vendors/js/jqGrid/js/jquery.fmatter.js create mode 100644 site/vendors/js/jqGrid/js/jquery.tablednd.js create mode 100644 site/vendors/js/jqGrid/js/json2.js create mode 100644 site/vendors/js/jqGrid/js/min/JsonXml-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.base-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.celledit-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.common-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.custom-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.formedit-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.import-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.inlinedit-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-bg-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-bg1251-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-cat-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-cs-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-de-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-dk-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-el-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-en-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-fi-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-fr-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-is-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-it-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-jp-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-pl-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-pt-br-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-pt-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-ru-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-sp-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.locale-tr-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.postext-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.setcolumns-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.subgrid-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.tbltogrid-min.js create mode 100644 site/vendors/js/jqGrid/js/min/grid.treegrid-min.js create mode 100644 site/vendors/js/jqGrid/js/min/jqDnR-min.js create mode 100644 site/vendors/js/jqGrid/js/min/jqModal-min.js create mode 100644 site/vendors/js/jqGrid/js/min/jquery.fmatter-min.js create mode 100644 site/vendors/js/jqGrid/js/min/jquery.tablednd-min.js create mode 100644 site/vendors/js/jqGrid/js/min/json2-min.js diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 07088c6..8c713b9 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -102,11 +102,160 @@ class CustomersController extends AppController { function all() { $title = 'All Customers'; $this->set('title', $title); $this->set('heading', $title); - $this->set('customers', $this->paginate()); $this->render('index'); } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: data + * - + */ + + function data($fields_str) { +/* pr(array('fields' => $fields, */ +/* 'explode' => explode(";", $fields_str))); */ + + $fields = explode(";", $fields_str); + + //$fields=array(); +/* foreach (explode(";", $fields_str) AS $i => $field) { */ +/* pr(array('field' => $field, */ +/* 'explode' => explode(".", $field))); */ +/* list($tbl, $col) = explode(".", $field); */ +/* unset($fields[$i]); */ +/* $fields[$tbl][] = $field; */ +/* } */ + + //pr(array('fields' => $fields)); + + $debug = true; + if (isset($this->passedArgs['debug'])) + $debug = $this->passedArgs['debug']; + + $this->autoRender = false; + if (!$debug) { + $this->layout = null; + $this->autoLayout = false; + $this->autoRender = false; + Configure::write('debug', '0'); + } + + $page = 1; // page number + $rows = 20; // rows in the grid - rowNum parameter + $sidx = 'Customer.id'; // sort column - index from colModel + $sord = 'ASC'; // sort order + + if (isset($this->params['url']) && is_array($this->params['url'])) + extract($this->params['url']); + + // calculate the number of rows for the query. We need this for paging the result + $row = $this->Customer->findCount(); + $count = $row; + + // calculate the total pages for the query + if( $count > 0 ) { + $total_pages = ceil($count/$rows); + } else { + $total_pages = 0; + } + + // if for some reasons the requested page is greater than the total + // set the requested page to total page + if ($page > $total_pages) $page=$total_pages; + + // calculate the starting position of the rows + $start = $rows*$page - $rows; + + // if for some reasons start position is negative set it to 0 + // typical case is that the user type 0 for the requested page + if($start <0) $start = 0; + + // the actual query for the grid data + $customers = $this->Customer->find + ('all', + array('contain' => array + (// Models +/* 'Contact' => */ +/* array(// Models */ +/* 'ContactPhone', */ +/* 'ContactEmail', */ +/* 'ContactAddress', */ +/* ), */ + + 'Account' => + array('fields' => array('Account.id')), + + 'CurrentLease' => + array('fields' => array(), + 'Unit' => + array('fields' => array('name')), + ), + ), + //'link' => array('fields' => $fields), + 'order' => "$sidx $sord", + 'limit' => "$start, $rows", + )); + + //pr($customers); + + if ($debug) { + ob_start(); + } + else { + if ( stristr($_SERVER["HTTP_ACCEPT"],"application/xhtml+xml") ) { + header("Content-type: application/xhtml+xml;charset=utf-8"); + } else { + header("Content-type: text/xml;charset=utf-8"); + } + + echo "\n"; + } + + echo "\n"; +/* echo " \n"; */ +/* echo " \n"; */ +/* echo " \n"; */ +/* echo " \n"; */ +/* echo " \n"; */ +/* echo " params, true) . "]]>\n"; */ +/* echo " passedArgs, true) . "]]>\n"; */ +/* echo " \n"; */ + echo " ".$page."\n"; + echo " ".$total_pages."\n"; + echo " ".$count."\n"; + + // be sure to put text data in CDATA + foreach ($customers AS $customer) { + $customer['Customer']['units'] = + implode("; ", + array_map(create_function + ('$lease', 'return $lease["Unit"]["name"];'), + $customer['CurrentLease'])); + + echo " \n"; + foreach ($fields AS $field) { + list($tbl, $col) = explode(".", $field); + echo " \n"; + } + echo " \n"; + } + echo "\n"; + + if ($debug) { + $xml = ob_get_contents(); + ob_end_clean(); + + $xml = preg_replace("/&/", "&", $xml); + $xml = preg_replace("//", ">", $xml); + + echo ("\n
    \n$xml\n
    \n"); + } + } + + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/vendors/css/jqGrid/basic/grid.css b/site/vendors/css/jqGrid/basic/grid.css new file mode 100644 index 0000000..84ed2c4 --- /dev/null +++ b/site/vendors/css/jqGrid/basic/grid.css @@ -0,0 +1,447 @@ +.GridHeader { +} +.Header { + width: 100%; + } + +.Header th { + font-size: 100%; font-weight: bold; text-align: left; + padding: 2px; + background-image: url(images/headerbg.gif) ; + color: #FFFFFF; + width: 100%; + white-space: nowrap; + } + +.HeaderLeft { + background-image: url(images/headerleft.gif); + } + +.HeaderRight { + background-image: url(images/headerright.gif); + } +.HeaderButton { + background-image: url(images/headerbg.gif); +} +.HeaderButton img{ + width: 17px; +} + +.HeaderLeft img{ + width: 14px; + } + +.HeaderRight img{ + width: 10px; + } + +.GridHeader table {margin:0;} +.GridHeader td, tr {padding:0;} +/* Grid */ +table.scroll { + table-layout: fixed; + /*border-right: 1px solid #D4D0C8;*/ + margin-bottom:0; +} +table.scroll tbody tr { + background-color: #ffffff; +} + +table.scroll tbody tr.alt { + background-color: #F9F9F9; +} + +table.scroll tr.over td{ + background-color: #E1DCF4; +} + + table.scroll tr.selected td { + background: #3d84cc; + color: White; +} + + table.scroll tbody td { + padding: 2px; + text-align: left; + border-bottom: 1px solid #D4D0C8; + border-left: 1px solid #D4D0C8; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + height : auto; +} + + table.scroll thead th { + padding: 2px; + border-bottom: 1px solid #CBC7B8; + border-left: 1px solid #D4D0C8; + text-align: left; + font-weight: normal; + overflow: hidden; + white-space: nowrap; + background-image: url(images/grid-blue-hd.gif); + height : 17px; +} + + table.scroll th div { + overflow: hidden; +/* white-space: nowrap;*/ + word-wrap: break-word; + height : 17px; +} + table.scroll th span { + cursor: e-resize; +/* border-right: 1px solid #D6D2C2; */ + width: 10px; + float: right; + display: block; + margin: -2px -1px -2px 0px; + height: 17px; + overflow: hidden; + white-space: nowrap; +} + +/* End Grid */ + +/* Pager */ +div.scroll { + vertical-align: top; + height: 23px; + white-space: nowrap; + text-align: center; + background-image: url(images/grid-blue-ft.gif); +} +div.scroll span { + vertical-align : top; +} +.selbox { + font-size: x-small; + vertical-align : top; +} +input.selbox{ + font-size: x-small; + vertical-align : top; +} +.pgbuttons { + margin-top :2px; +} +.nav-table-left { + padding:1px; + float: left; +/* position:absolute;*/ +} +.nav-table-right { + padding:1px; + float: right; +} + +table.navtable {margin-bottom:0; width: auto;} +table.navtable tr{ + background-image: url(images/grid-blue-ft.gif); +} + +table.navtable td.nav-button { + border: 1px solid #E2ECF8; + white-space: nowrap; +} + +table.navtable td.nav-hover { + border: 1px solid #83B4D8; +} + +table.tbutton tr td{ + border : none; + padding:0px; +} + +img.jsHover { /*not used */ + border: 1px solid #99CCFF; +} +/* End Pager */ +/*multiselect checkbox */ +.cbox { + height: 10px; + width: 10px; + /*border:1px solid #999;*/ +} +/* end multiselect */ + + +/* loading div */ +div.loading { + position: absolute; + padding: 3px; + text-align: center; + font-weight: bold; + background: red; + color: white; + display: none; +} + +div.loadingui { + display:none; + z-index:6000; + position:absolute; +} + + +div.loadingui div.msgbox { + position: relative; + z-index:6001; + left: 35%; + top:45%; + background: url(images/loading.gif) no-repeat left; + width: 100px; + border: 2px solid #B2D2FF; + text-align: right; + height: auto; + padding:2px; + margin: 0px; +} +/* end loading div */ +/* toolbar */ +div.userdata { + margin-top: 0px; + background-color : #EAF9F9; + height : 20px; + overflow: hidden; +} +/* end toolbar */ +/*Subgrid text mode*/ +.subgrid { + height: 100%; + overflow: auto; +} +.tablediv { + background-color: White; + border-spacing: 1px; /*cellspacing:poor IE support for this*/ + border-collapse: separate; + width:100%; /* FF hack poor when scroling subgrid */ +} +.celldiv { + float: left; + display: table-cell; + border: 1px dotted #CCCCCC; + overflow: auto; + white-space: normal; +} +.celldivth { + float: left; /*fix for buggy browsers*/ + border: 1px solid #CCCCCC; + background-color: #99CCFF; + border-bottom: 1px solid #CBC7B8; + text-align: left; + overflow: auto; +} +.rowdiv { + display: table-row; + background: #F9F9F9 none; + color: #000000; + width: 100%; + overflow:auto; +} +/* End Subgrid */ + +/* InLine editing */ +input.editable[type="text"] { + font-size: x-small; + overflow: hidden; + height : 15px; +} +input.editable[type="checkbox"] { +} + +textarea.editable { + overflow: hidden; +} + +select.editable { + font-size: x-small; +} +/* End Inline Editing */ + +/*Modal Window */ +.modaltext{ + text-align : left; +} +.modalwin{ + border:1px solid #555555; + background:#F9F9F9; + text-align:left; + margin: 0 auto; + overflow: auto; +} + + +.modalhead { + background-image: url(images/grid-blue-hd.gif); + height: 20px; + +} +.modalcontent { + overflow: auto; + margin-bottom: 9px; + margin-left: 5px; +} +/* end Modal window*/ +/* Search window */ +input.search { + margin: 2px; + width: 70px; + font-size: 10px; + color: #15428B; +} + +select.search { + margin: 2px; + width: 70px; + font-size: 10px; + color: #15428B; +} +.buttonsearch { + width : 50px; + font-size: 10px; + color: #15428B; +} +/*End search */ + +/* Form edit */ + +.FormGrid { + margin: 0px; +} +.EditTable { + width: 100%; +} + +.FormData { /* tr */ + +} + +#FormError td { + font-size: 90%; + color: #FF0000; + vertical-align: top; + background-color: #f7f7f7; +} + +.CaptionTD{ /* td */ + font-weight: normal; text-align: left; vertical-align: top; + padding: 1px; + border-top: 1px solid #D4D0C8; + white-space: nowrap; + color: #000000; +} +.DataTD { /* td */ + padding: 1px; + border-top: 1px solid #D4D0C8; + vertical-align: top; +} +.navButton{ + border-top: 1px solid #D4D0C8; + border-bottom: 1px solid #D4D0C8; + text-align: center; +} +.navButton input{ + width:17px; +} +input.EditButton { /* buttons are at footer tr */ + font-size: 10px; + color: #15428B; +} +td.EditButton { + text-align: right; + border-top: 1px solid #D4D0C8; + border-bottom: 1px solid #D4D0C8; +} + +.FormElement { /* form element - input -text,textarea,checkbox - select */ + +} +.FormElement { + font-size: 10px; +} +input[type="text"].FormElement{ + color: #15428B; +} +input[type="checkbox"].FormElement{ + width: 15px; + color: #15428B; +} +input[type="textarea"].FormElement{ + color: #15428B; +} +select.FormElement { + font-size: 10px; + color: #15428B; +} +/* End Eorm edit */ + +/* Delete Dialog */ +.DelButton > input { /* buttons are at footer tr */ + font-size: 10px; + color: #15428B; +} +.DelButton { + text-align: right; +} +/* End Delete Dialog */ + +img.jqResize { + position:absolute; + bottom: 0px; + right: 0px; + cursor :se-resize; +} +.dirty-cell { + background: transparent url(images/dirty.gif) no-repeat 0 0; +} +#DelError td { + font-size: 90%; + color: #FF0000; + vertical-align: top; + background-color: #f7f7f7; +} +/* Tree Grid */ +.tree-wrap +{ + float: left; + position: relative; + height: 18px; + white-space: nowrap; + overflow: hidden; +} +.tree-minus +{ + position: absolute; + height: 18px; + width: 16px; + overflow: hidden; + background: url(images/tree_minus.gif) no-repeat; +} +.tree-plus +{ + position: absolute; + height: 18px; + width: 16px; + overflow: hidden; + background: url(images/tree_plus.gif) no-repeat; +} +.tree-leaf +{ + position: absolute; + height: 18px; + width: 16px; + overflow: hidden; + background: url(images/tree_leaf.gif) no-repeat; +} +.treeclick +{ + cursor: pointer; +} +.edit-cell { + background-color: #E1DCF4 !important; +} +.selected-row, .selected-row TD { + background-color: #3d84cc; +} \ No newline at end of file diff --git a/site/vendors/css/jqGrid/basic/images/cd_run.gif b/site/vendors/css/jqGrid/basic/images/cd_run.gif new file mode 100644 index 0000000000000000000000000000000000000000..c2b8f4edabad00e11a69889bae33c9b91717c6f6 GIT binary patch literal 1025 zcmeH`?=RGG0LMQU8fEQ@HZxmSY}CT(N~kT4B&L>@)!OVlX_bChJ@KTaU)ItX!ktsO z!+3x!r-*Ru<{W3byVdBr)7^bJ9Ot;>zOJu#{0Tkp{owuV{owt2?|trkYFvCSo3P2c zkch^xB`dHDxLj)kR%`^ZuInMX}|&SUUO;Y553``C@OE_#M6>@q6ruc7M;dQ0V8%8 ze$9T+qxlEKUqx@`1P!t&@muMm;aussL}kUI)mp2?%8Elqp>eExewNCUr&kRwXE$Xr z4D+z_?gLe-)`N;_X>+&w)a$qzCtaz2Hn|Fk4hn_oadB<06~a-BtM$i zl(u_1UbzZ-z2$gm^ssv2R_p!mORF@!DO6(`NUV?U`7)s0fXlhgeHmF*Cv&?ujD~4x z+sG7y*3Myt!dSd`vFWo>vxKfblWYn@mhBPAfBidwgS0n`5Ft6b9o_x}@imYbzmT+c zfjlXvD&^zqZ@>lyj2t2o f3la`CGVn;rtSCr4)W)vpHOFJ)qNAORj11NQ63h`c literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/down.gif b/site/vendors/css/jqGrid/basic/images/down.gif new file mode 100644 index 0000000000000000000000000000000000000000..808d921109cc45d98a755011cd02a6ab4c3c8e66 GIT binary patch literal 309 zcmZ?wbhEHb6krfwSZd9n;xR$PcbabSJmbh^776R^Gq%g7ebrAnub+BZC+&to(h0+? z+ZK6u?22#Om)=#$`lM6%&ZOvtUENQY`~yz8SG-D3_*Y->sJic0{m|jRLvX{j;Fi0g zt@k3@@B4Rs^Y8o{*!(cO{XtmE%gC-r@!b#NdmbkAJW1_;ojLJw#+0YolV9ggdy_l! zS^AvcnX~?9%=uY3>v`S$cTEePx32r&yZS@Ny8qL*ykEHQ!=kd5>5s6g>2 z3nK%AJ%bJd5P)v+tO2Y= Bm5TrX literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/find.gif b/site/vendors/css/jqGrid/basic/images/find.gif new file mode 100644 index 0000000000000000000000000000000000000000..39a0dac9ddcce982cb99dd4229089a0a810cd371 GIT binary patch literal 986 zcmZ?wbhEHb6krfw_};{@bm`4|_x^9)dVBixQ`4rMYX2PF^(|)Q%8SdE-L_w0f9Kv; zjp>H<^_vzgy71-qm*vZEuUK*Jz=3y*7oT-GsGGPup{#6nRn@BH%g^-p@6XL$(BHqO zw|C#=%g;7%zIo~D(>Zev{Q3Lm|NsBXmtUSU=h%`Z7x?PA&!7Khzshdix*H1f#7>?1 zps`%NzJ9}zBah`5h@Cm}pu2n9(xtaHZ+`gc*QctgwQjXBr%%7|nip~F*7sAVp5MCl z^Zon(=1XjE-TKhmyLR#7Q)_qZ-MaOHjZN(x(>lDzVyj1NZbJrhO!IOgpSmfH~m+o1We# z15FOb3!)5$Y)4K8JMnci`QC~+d2vy5yOcwh#GVG_3(O2GuUHC;k0eZy^4ag{ zZHv4+cEz{tOYf>=ebOm>XHxXSuI{Hx{sE`lD_*51{Hrf`RNeQhe(3PuA-LgMaLe7$ z)_W1{_x-!R`FH*eYuz6C>RX^ z>V<&fPZnkd21y1TkddG~!N5_)V9X)ov0=f%X7@MtwUbVx|CCuD_3M1(}kL@rTAt`?@NJD7g1T-cVt+{lozLxII0fq`Ms9dUP2 S4@VK8*$kepelF{r5}E+oVobaM literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/grid-blue-ft.gif b/site/vendors/css/jqGrid/basic/images/grid-blue-ft.gif new file mode 100644 index 0000000000000000000000000000000000000000..cd094e9671ae64690869967e5079549e55f1eb51 GIT binary patch literal 821 zcmZ?wbhEHbWMmL!_|Cv^v*lLz=6id7 o^S3?nnD(r5*{f6A-fDZ_uA=K5H7NRlhVmDjn1+k{blZ5X6^D|cw6R0k)7n5yb zZE29zl^5qxm(!AvR^sPlmXuOa6%de@&{2>P=HXLRX5PdsF0H`N#3anm z!@6%DkCF_Nps1k8&XYSmL`50SU$}Vb@|COCuHU$M>-L?y_wGM<_~`MIr_Y|hc=_t} qo44=YfB5+6^OvvRzW@07>o+jS|1&Ui$#`s7aIl#}_#HPBgEau)H?u4N literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/headerright.gif b/site/vendors/css/jqGrid/basic/images/headerright.gif new file mode 100644 index 0000000000000000000000000000000000000000..3ef5e02449a2d8023f8ae24ee2806887e938de25 GIT binary patch literal 87 zcmZ?wbhEHbv*lLz=6id7 o^S3?nnD(r5*{f6A-fz>x6;A zVHOq!Hjfa6LWZNAV%#Aq5rqw{ZGtLZ5)4d-82hC89V8eU65E*h#SH#LC>&^J7E=wV zseF*)Jk>5bZ;NCCQ(zyLTiBC=28YWG8m(S`IvAcYvdC$_idl8(2_v6a4ag{ zZHv4+cEz{tOYf>=ebOm>XHxXSuI{Hx{sE`lD_*51{Hrf`RNeQhe(3PuA-LgMaLe7$ z)_W1{_x-!R`FH*eYuz6C>RX^ z>V<&fPZnkd21y1TkddG~!N5_$V9X)ov0=f%X7)sh7DeV(M==$yO&0_YC2+|IvM<}Q z@ZbVY8B+}&lf=VK2L;XIwg}8jWa;H%bG(qjsCck}MX*~6o0a?iZC!S=m6P3Ss?}nCh;l#D>+~DyLOwL V>$-Y2<`-MpBadm%W{NOa0{{&)7qb8W literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/loading.gif b/site/vendors/css/jqGrid/basic/images/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..e846e1d6c58796558015ffee1fdec546bc207ee8 GIT binary patch literal 771 zcmZ?wbhEHb6krfw*v!MQYQ=(yeQk4RPu{+D?cCXuwr^cCp}%d_ius2R?!0jBXnAQ) zOH<|l|Nj|aK=D7fpKD04vtxj(k)8oFBT!uNCkrbB0}q1^NDatX1{VJbCr|b)oWWMT zS%hVC ~NwO_yO%;SvZ5MdNYf|QNy-I*%yJaj+uTdt+qbZ z4E`Fzb8m}I&!N8OKmWEcCmrLs^Hs&3i)mt@hQVdcqghkaBs*D}tG_lKew4?rTjzIZ z9tSone1TS+TR7tu^CunG)Y7Jg#sw#)sG9C!c0I%LEzP)9;hqRf&)s$D8d5Db{TBs% zgl0~5QQ91luq4Q9tJgt4QLbaxZvAaKeCM9!oy85dg4k>TdBSVqjHub_PG=PO&J-rx z7oYTuF+kH|tG-UK+EkUhDjYx?zW?T|lx>+aOQm zzL$v$zBLo4Cj=G&tw{H}dW?tlTkS)SY4<#NS92z*EY-MMB6Ftp`R=*=*Ev7cS+X%W zMCur^FdlokL}1Y+&aasU2J4#EOuNlnb9CmqgLCGTSY!1BD42pkHY^XidQ5=>YQx%` z*%Pm9D!CkBu&tMWm(%-ejACVWGS2RX5=QOJ$1*tr7F}F+*-OA+Ly&Isg|AEuUYicA z#%IG6kPXkHt{zk2M6zK@Vu^4Q(1zE$?yY6M!^&jQ+2^E?!p7{g*|X6}vuRC3p@jk0 W117c83?+LXEZI4G$p&LV25SKE>nb+@ literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/minus.gif b/site/vendors/css/jqGrid/basic/images/minus.gif new file mode 100644 index 0000000000000000000000000000000000000000..ef04a54696e17442f7d3a858b18e2da9db1c2e34 GIT binary patch literal 85 zcmZ?wbhEHb6k-r!n8?8J|NsA%mKFvuL-8jIs|W)#gAR}jloeuNU{agYzw-23{>5Bd lu8B3=Q%KlX>BCkwzhTj{h;`hYUHRJn(^Q}S;uB@C1^}ss9ftq_ literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/next.gif b/site/vendors/css/jqGrid/basic/images/next.gif new file mode 100644 index 0000000000000000000000000000000000000000..960163530132545abe690cb8e49c5fef0f923344 GIT binary patch literal 875 zcmZ?wbhEHb6krfwXlGzh@tC0DJ54uuo^j+di-h&|8QW#kzUrr(*H68ylXk-(>4ag{ zZHv4+cEz{tOYf>=ebOm>XHxXSuI{Hx{sE`lD_*51{Hrf`RNeQhe(3PuA-LgMaLe7$ z)_W1{_x-!R`FH*eYuz6C>RX^ z>V<&fPZnkd21y1TkddG~!NB3cV9X)ov0=f%W)9;69vKr@Ionu*A5?G{Hgn3DYJ|un wK6d5q<#D`_!KiqUp-ntt3Jb$U#ts%8MWY1*!jGC}2?&SWIk{Q=U;~3S0KQg&YXATM literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/nochild.gif b/site/vendors/css/jqGrid/basic/images/nochild.gif new file mode 100644 index 0000000000000000000000000000000000000000..cf6c61ce9550a7c2a8b546151b7349027979b35f GIT binary patch literal 66 zcmZ?wbhEHb%@85yhrgPhY%v@z$+dw{PFR zd-v{x2M-uV!Dt8!L;Mq+#E6<8x|aFW_O4e+3))3Q*|Q=94?bWMk!6jGP<+(r$fM>Xwqe7gmNr&4?FkK$jz>EMMFb>zJ~*Z~ zvMU=|C?p6pu`gocw@ENKkig96%Ptk5a9{xwcPOV4M}k2k%Q{v@i4+D0okN>5F7xql HFjxZs_zi%( literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/off-last.gif b/site/vendors/css/jqGrid/basic/images/off-last.gif new file mode 100644 index 0000000000000000000000000000000000000000..869706777ce1e5c8350e0086f6febc18aa2bf814 GIT binary patch literal 923 zcmZ?wbhEHb6krfwXlGzZPfyRu$tfx-s;H=_udjFb@6guP*52OU-QC^W+uPUI*Wcei zY0{+0lP6D^GG*q>nX_llo;Ppa!i5VLFJ8Q4$&%&Em#6pV(z;0OW5pDfG_ z46F<~Am@Pc1OrC}12>0^$A$$5o7t@;-Y_UNJMxKf6&W}lT+k*Y$eyJjc<@21kdg?` z9)m}X2f37ODg+`IICZeGskVGL@ZdlLlaQT?!H)&bz6?zAIR*(A8e5nhSgkHN9C*OQ m>dC5ipkT8?(+Va*AAy7q4&fY(0%9#)p=)k#W@Tbxum%8@3U^Ha literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/off-next.gif b/site/vendors/css/jqGrid/basic/images/off-next.gif new file mode 100644 index 0000000000000000000000000000000000000000..90a7756f6fd77f74fd2b5786dd3586b5c50c8d89 GIT binary patch literal 875 zcmZ?wbhEHb6krfwXlGzZPfxF?sBrl2(B9tO-QC^S*Vo_QKWWmWDO0A*oH=vh!iCG1 zFJG}@#i~`SHg4Rwb?esc+qduBx%1@7lc!IgzIgHC?c28*M!{$Z4A~G+{K>+|z`(?y z1M&eVPcU$JFtBpScx+g3u$hC^!6V}XBXb*zY)A!1phGj4Fjq*7gQ62lFOR54M?r!E kLmQ{U6cz@-#wJD`MJWvdVWq}d0_-7oPHt8|*uY>70KTb0MF0Q* literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/off-prev.gif b/site/vendors/css/jqGrid/basic/images/off-prev.gif new file mode 100644 index 0000000000000000000000000000000000000000..37154d62406ddc064dba311b95f554e49ad38003 GIT binary patch literal 879 zcmZ?wbhEHb6krfwXlGzZPfyRu$tfx-s;H=_udjFb@6g=b+}hgO*4EbD-QC;U+t=4O zY0{+0lPAxdIdk5;dGqJbU$}7L;>C-XELpN*#fp_HSMJ!cW9QDDr%#{0ef##^yLTBz z!Dt8!oe)s`$->OQz{;Qlaxy4SFmU)VaC69bY*=uxnSOV literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/plus.gif b/site/vendors/css/jqGrid/basic/images/plus.gif new file mode 100644 index 0000000000000000000000000000000000000000..abb84bdfbfa5fbd6f188a3a65eec7b077229eef3 GIT binary patch literal 89 zcmZ?wbhEHb6k-r!n8?8J|NsA%mKFvuL-8jIs|W)#gAR}jloeuNVA7h?zw-23{>5Bd pu8B3=Q+S}8BR4s7p_$&y1Do!qcNrAyQ&FEhP4(+PeoY1jYXCC)AI<;( literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/prev.gif b/site/vendors/css/jqGrid/basic/images/prev.gif new file mode 100644 index 0000000000000000000000000000000000000000..eb70cf8f6a3b7f524bbeb3656d875a823b27fd7c GIT binary patch literal 879 zcmZ?wbhEHb6krfwXlGzh@tC0DJ54uuo^j+di-h&|8QW#kzUrr(*H68ylXk-(>4ag{ zZHv4+cEz{tOYf>=ebOm>XHxXSuI{Hx{sE`lD_*51{Hrf`RNeQhe(3PuA-LgMaLe7$ z)_W1{_x-!R`FH*eYuz6C>RX^ z>V<&fPZnkd21y1TkddG~!NB3eV9X)ov0=f%W)AK)kBA8^Y;DZmPc|?ZI=9Q{X*oQZ zkbJD2lgIqQijPiCj2*mD6%7sx9yN0CvxS^laG;@KrlbJNftid9=jS`{vav8&0{~Hw Bh1385 literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/refresh.gif b/site/vendors/css/jqGrid/basic/images/refresh.gif new file mode 100644 index 0000000000000000000000000000000000000000..fb74a02ad4fb7d0fe7ad2070ff5dad786bdf417d GIT binary patch literal 581 zcmV-L0=oT2Nk%w1VGsZi0Oo%HS+f74(f_^H^St8!pws{6^#85G9r?e+XDgwaf&=_-KIbiV&XdBcje<1CBig{9V;%>LHl^u^-;dBOj%-~Sqb?D+Zo zq169wr`*on^GL1#QhvfJm;ZIX{}gn_DwX_CiPpO0|4N42OQGS`=Jxjc|4**}g{k0g zs^mnP;GMqakiO?Mi{iZH|0;RV5LmHmv+rx1)$8*7Wt-jo{{J_3$x@@?L#O|CxA+{8 z_+X~&B7oMa%r~jYN|0jFZ#NGCY%KwPx!A^8LW004ggEC2ui z01yBW000M~fPaF6goTDME!3Lt_(C_8KpQC&7}GEM^~Z-N~M7f&2nV;(pqTytgy zf_n&kMhy}Sg&TuvVF^S(ez1a6Un5HpX?cTQEQEGfDXQQBphXHDCRWfm5>RHvhaw>~ TY>_8q${jvKpvc=OC=dWU{>VZe literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/resize.gif b/site/vendors/css/jqGrid/basic/images/resize.gif new file mode 100644 index 0000000000000000000000000000000000000000..05c807bbcee95410e01fed7a9900bba24ba3a339 GIT binary patch literal 862 zcmZ?wbhEHb6krfw_|Cx4($aG6+PVLuU^E0qWC$q!WMO1rU}Vr?00K~+VBoN3VCInV z*s$PWGl#HN%n5^rhBiJ%6A=c7M^0U0qDdtyHYOcukv5m(d0DvR_yjgjuO$%ysYiPB Klk<2u7_0#kRTRwt literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/row_add.gif b/site/vendors/css/jqGrid/basic/images/row_add.gif new file mode 100644 index 0000000000000000000000000000000000000000..847ea1d9bde19af1c36349ff7d9c413d986002eb GIT binary patch literal 635 zcmaKp+e_1N7>D2KR7R!CW1e-1qE1RP@epY=b()!#n2B0ak;RU>FF~S3iUWh2X=|9kO{keHQPkupOdPWT!*ziXV>+5)M zfMa81YYR;#Q-41JJt&n*P=ijV0|`hZ5^BF%zgK~;_*$)2uh)Ydy1Tpaa|KRT;`d%8 zH|=(^w}%u(;fH%R8^QNwjg5_?qolpPoit_8G|^}@DwS$y2Sp;0!C=5Q#h`-iZ3GJN zTbspVIXc1@zxh_H6`k4826)U5dUX|@PAATq#bWXPJ`N2L&;h=^O`5Zy85|BWGD0>s z@bD02G8uFLQCz^O2S%f@W%KUtE^cljP8;yk{jRPqnx=80#OWkNlUZ9^i}p-V0#0`> zFC)GyU0g(*dkI1SE!b=}#Uc-17eO6JrBbumED#8ULLtug;dtT9%mOrk%S99l1=49? zf`(tY3#1bafMfYRJw5ofYG8mYE#cZ4uB@DRz<-H8U^3wNQSQm=qzQQaY?5=i;)hIT zUU0B)Y-|x*E@!4BG2G6@xP!D_Ru@V6CS9}i_R%&L#bz+lBlz(yYn=}j>E;%Zo$>V6 zRga+1Xb#27^$)p{757-gyLjhWIOQYp3o9uO^ez{ql_s92IQ}=nqT;H&1D+>%CVElf zej#O1ftMZy2u~*$UgqdquaD=bQ?^@D|EeL^;a<N^h$ISJ6 ys5|1%`ty7_t|zUDIRH6drcPOdsE^!o$smuFTr=UAosTJW4DwA0Rl})l$odBY{~Kli literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/row_delete.gif b/site/vendors/css/jqGrid/basic/images/row_delete.gif new file mode 100644 index 0000000000000000000000000000000000000000..bd6e784c5f61c4dcde504e280a2c8bebc629dfc9 GIT binary patch literal 634 zcmV-=0)_oYNk%w1VGsZi0Oo%HnVGYblaqdae#AO8d3kwlZEcj4l*J?ykB^V<@Bjb3 zS88f%XlQ8vqdldiv!S80ot?A)XD#{p|E;aF;^P19?f=);|K;WXqN20v>i^&0|Nope z*x3Jyii(z&mY$xohlhv%nKPQ2v-9)+|DHJT@c;jyI{&Fd;NbuK{Qr@Wk=51ztgN$* zjg5qagpiPscXxNUBq7?`|FSbIr>C>76bZYKP_uV0up}e@tw(Wjar8+XzakLvsD|^i zp8v{%|J9+hbuRy1CEniu+1da1_y4FSC)1{iw03sAprFpW!RON7)6@U^`~R^jD5j>l z|7|(HFDd_}KmXsZ|E@^F!ovT3KmW#l|I2jLG!@+3|J}B}!W|R;t3|*mA^(~*|8gw< z|Nq@T9H*zJ|4tXdKRy4rRR3Wqvx7VTZ7affc+Yxt|FBB`v`({fE4aA0yt=yo!d(Bw zU#O_FtE;pB*`@#7q_cD^#5E!RTOf3FbnNW^|6CQjAQkfR|NsC0A^8LW004ggEC2ui z01yBW000NqfPWqy1_l9#Dk?7sj4gkE0bwZ;6C))R85kE78Xb=>DNU4?n3|j*k1Y}s zMJ#>^rJEWqj~x>eEOc`;4h|0w9}u*EAaZdEXl89}IX6-!8v>6mSau3Fbw5;HK@B8d z(tid$15-y)K36Aq-XR2!Ra{VOGihExCvMOoFpqCWR>Yh+pyWv~5dZ+_c{FAVj|e-| zBtS7lgbWTAbUadXAcBxQeU_lm0s!NR0*`Qj$%2Orp8P14gdfE literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/row_edit.gif b/site/vendors/css/jqGrid/basic/images/row_edit.gif new file mode 100644 index 0000000000000000000000000000000000000000..12cc7e6fbb0215bbafaea389043a9eeb2aa674c3 GIT binary patch literal 996 zcmZ?wbhEHb6krfw_&$xHv~8F-0yB!+ZZex?%*0$^a!S&6qXJwUj>c`3c{%yVg;#*p__x_Hps;&R{@qc6E=GCju zZr}bm>a<1dQR~HvFTHy8Yw3x&SBEDYIr4Jl$_tAZpZfjx_o-7KE?#`{;>G`p9cf#( zJnZh?+uOVL*yOqp5Z!cYXv#@Y!SXf)<*O=wYFW`^SNvK16TW98cPn(t$7!G{`{x@^R<`PWZj8$x_$eMZ2j05%^VY6ivG*MIJSv+q)dOjy9sz!=Up?PM}1D+i1FjypFGGqLkF@@@0ku&}9PhFbuW1>=Mh6CEUsXT*3s zUN}LHkx|ElaYKT_LcL&#A1@7-otkA)px`0F(bg_**?)*-V=$+uh$=5v9i!9ACI!!w zc^L*S3l{LWHab0cXv}hf+noLPpA(4=F8o&J3bG#h)yUAf^t80Ld^gF}W}@SOWlZ0R#L1 literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/tab_close-on.gif b/site/vendors/css/jqGrid/basic/images/tab_close-on.gif new file mode 100644 index 0000000000000000000000000000000000000000..822726888b5dec2b575c81f700a8ede0922d9033 GIT binary patch literal 351 zcmZ?wbhEHbQ=gxgiOWV%C@c;k+Pobd~85s64Fnsj!Il{p3IWu!F z1H&^0hPM(D|I5qY>*;-Pbo>+^{)U_TV?e+L28L@uHQCwkb#*^_d+%ppc*?-=!N%sD zqT*!+hIcwT+ZY%wF))0Ji`&J(unBBF1GRzTPZmZ71{DS!kij57F|gG*Oe*lu;bT0J zvWa6ui&E>0l*d0UX0C3q`TL1t6 literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/tree_leaf.gif b/site/vendors/css/jqGrid/basic/images/tree_leaf.gif new file mode 100644 index 0000000000000000000000000000000000000000..febfda63651a83fd2614e6fb61e973c5330fbb40 GIT binary patch literal 134 zcmZ?wbhEHb6lM@-*v!KaP`15m{XrJ9x%Z!a?Av@OsAg0C+)chETbWJgzW?&ir|MAA zg3Sy_K=CIFBLf2ugAPaxWCjC^@r09}tM^*GKD+z>0~47J2A;bUB^((`IyMS4UeIK8 dye$*JvQ|8uL10F}!X-r~bFAiH@MdAK1^}~nFHQge literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/tree_minus.gif b/site/vendors/css/jqGrid/basic/images/tree_minus.gif new file mode 100644 index 0000000000000000000000000000000000000000..bdfa2ecfc397e0665a8c7bdb746b1ba7a9f64a40 GIT binary patch literal 132 zcmZ?wbhEHb6lM@-Sj5Wk|NsBwIp>nk{hu>uPI7WGkjnrDia%Kx85md@bU-|iS_Wp% zh+TL78B8-=BFzx6yFl&El-hs;6_2m6tg+a)N{EB$_dSLkXSVb{=aE}0w&P{f;dvJi gdR=pKU$((xlF9tQ)w+Z^fq{)d2gqgs zsbygH&)9Wm-xE()md?$giG_TO$18&w8e#%d+BoMdTre%a_tfFX*YsyuTi^5ikj+xL pQ0Z}o@~al#r%WueUek}Obl)o86s7hyoKdOw{EIDBdp#H!tO1AYH}e1h literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/basic/images/up.gif b/site/vendors/css/jqGrid/basic/images/up.gif new file mode 100644 index 0000000000000000000000000000000000000000..13f75f0e36d8276404ea02ab6c26bae607cd26c3 GIT binary patch literal 312 zcmZ?wbhEHb6krfwSZd9n;xR$PcbabSJmbh^776R^Gq%g7ebrAnub+BZC+&to(h0+? z+ZK6u?22#Om)=#$`lM6%&ZOvtUENQY`~yz8SG-D3_*Y->sJic0{m|jRLvX{j;Fi0g zt@k3@@B4Rs^Y8o{*!(cO{XtmE%gC-r@!b#NdmbkAJW1_;ojLJw#+0YolV9ggdy_l! zS^AvcnX~?9%=uY3>v`S$cTEePx32r&yZS@Ny8qL*ykEHQ!=kd5>5s6g>2 z3nK%AJ%bJd5P^o=c5Jvi9-1%%}FELGeX(lWAg@=9mU@^ECZ F1_1I2nbH6N literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/grid.css b/site/vendors/css/jqGrid/coffee/grid.css new file mode 100644 index 0000000..0d146a2 --- /dev/null +++ b/site/vendors/css/jqGrid/coffee/grid.css @@ -0,0 +1,457 @@ +.GridHeader { +} +.Header { + width: 100%; + } + +.Header th { + font-size: 100%; font-weight: bold; text-align: left; + padding: 2px; + background-image: url(images/headerbg.gif); color: #ffffff; + width: 100%; + white-space: nowrap; + } + +.HeaderLeft { + background-image: url(images/headerleft.gif); + } + +.HeaderRight { + background-image: url(images/headerright.gif); + } +.HeaderButton { + background-image: url(images/headerbg.gif); +} +.HeaderButton img{ + width: 21px; +} + +.HeaderLeft img{ + width: 4px; + } + +.HeaderRight img{ + width: 9px; + } +.GridHeader table {margin:0;} +.GridHeader td, tr {padding:0;} + + +/* Grid */ +table.scroll { + border-right: 1px solid #FFFFFF; + table-layout: fixed; + margin-bottom:0; +} +table.scroll tbody tr { + background-color: #eceae3; +} + +table.scroll tbody tr.alt{ + background-color: #e3dfd1; +} + +table.scroll tr.over td{ + background-color: #D2B48C; +} + + +table.scroll tr.selected td { + background-color: #c9b9b1; + color: Black; +} + +table.scroll tbody tr td { + font-size: 90%; + padding: 2px; + text-align: left; + border-left: 1px solid #FFFFFF; + border-bottom: 1px solid #FFFFFF; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + height : auto; +} + +table.scroll thead tr th { + font-size: 90%; + font-weight: normal; + padding: 2px; + border-left: 1px solid #FFFFFF; + border-bottom: 1px solid #FFFFFF; + text-align: left; + overflow: hidden; + white-space: nowrap; + background: url(images/grid-blue-hd.gif) transparent repeat-x; + height : 18px; +} +table.scroll thead tr th div img { + width: 9px; +} + +table.scroll th div { + overflow: hidden; +/* white-space: nowrap;*/ + word-wrap: break-word; + height : 18px; +} + table.scroll th span { + cursor: e-resize; +/* border-right: 1px solid #D6D2C2; */ + width: 5px; + float: right; + position: relative; + display: block; + margin: -1px -1px -1px 0px; + height: 18px; + overflow: hidden; + white-space: nowrap; +} + +table.scroll thead { +} + +/* End Grid */ + +/* Pager */ +div.scroll { + vertical-align: top; + height: 23px; + text-align: center; + white-space: nowrap; + background-image: url(images/grid-blue-ft.gif); + border-right: 1px solid #FFFFFF; + border-left: 1px solid #FFFFFF; + border-bottom: 1px solid #FFFFFF; +} +div.scroll span { + vertical-align : top; +} +.selbox { + font-size: x-small; + vertical-align : top; +} +input.selbox{ + font-size: x-small; + vertical-align : top; +} +.pgbuttons { + margin-top :1px; +} +.nav-table-left { + padding:1px; + float: left; + margin-top:2px; +/* position:absolute;*/ +} +.nav-table-right { + padding:1px; + float: right; + margin-top:2px; +} +table.navtable {margin-bottom:0; width: auto;} +table.navtable tbody tr { + background-image: url(images/grid-blue-ft.gif); +} +table.navtable tbody tr td.nav-button { + border: 1px solid #FFFFFF; + white-space: nowrap; +} +table.navtable tbody tr td.nav-hover { + border: 1px solid #c9b9b1; +} +table.tbutton tbody tr td { + border : none; + padding:0px; +} +img.jsHover { /*not used */ + border: 1px solid #99CCFF; +} +/* End Pager */ +/*multiselect checkbox */ +.cbox { + height: 10px; + width: 10px; +/* text-align: center;*/ +/*border:1px solid #999;*/ +} +/* end multiselect */ + + +/* loading div */ +div.loading { + position: absolute; + padding: 3px; + text-align: center; + font-weight: bold; + background: red; + color: white; + display: none; +} +div.loadingui { + display:none; + z-index:6000; + position:absolute; +} + + +div.loadingui div.msgbox { + position: relative; + z-index:6001; + left: 35%; + top:45%; + background: url(images/loading.gif) no-repeat left; + width: 100px; + border: 2px solid #B2D2FF; + text-align: right; + height: auto; + padding:2px; + margin: 0px; +} + +/* end loading div */ +/*toolbar */ +div.userdata { + margin-top: 0px; + background-color : #e3dfd1; + height : 20px; + overflow: hidden; +} +/* end toolbar */ +/*Subgrid text mode*/ +.subgrid { + height: 100%; + overflow: auto; +} +.tablediv { + background-color: White; + border-spacing: 1px; /*cellspacing:poor IE support for this*/ + border-collapse: separate; + width:100%; /* FF hack poor when scroling subgrid */ +} +.celldiv { + float: left; + display: table-cell; + border: 1px dotted #CCCCCC; + overflow: auto; + white-space: normal; +} +.celldivth { + float: left; /*fix for buggy browsers*/ + border: 1px solid #CCCCCC; + background-color: #99CCFF; + border-bottom: 1px solid #CBC7B8; + text-align: left; + overflow: auto; +} +.rowdiv { + display: table-row; + background: #F9F9F9 none; + color: #000000; + width: 100%; + overflow:auto; +} +/* End Subgrid */ + +/* InLine editing */ +input.editable[type="text"] { + font-size: x-small; + overflow: hidden; +} +input.editable[type="checkbox"] { +} + +textarea.editable { + overflow: hidden; +} + +select.editable { + font-size: x-small; +} +/* End Inline Editing */ + +/*Modal Window */ +.modaltext{ + text-align : left; +} +.modalwin{ + border:1px solid #555555; + background:#F9F9F9; + text-align:left; + margin: 0 auto; + overflow: auto; +} + + +.modalhead { + background-image: url(images/grid-blue-hd.gif); + height: 20px; + +} +.modalcontent { + overflow: auto; + margin-bottom: 9px; + margin-left: 5px; +} +/* end Modal window*/ +/* Search window */ +input.search { + margin: 2px; + width: 70px; + font-size: 10px; + color: #15428B; +} + +select.search { + margin: 2px; + width: 70px; + font-size: 10px; + color: #15428B; +} +.buttonsearch { + width : 50px; + font-size: 10px; + color: #15428B; +} +/*End search */ + +/* Form edit */ + +.FormGrid { + margin: 0px; +} +.EditTable { + width: 100%; +} + +.FormData { /* tr */ + +} + +#FormError td { + font-size: 90%; + color: #FF0000; + vertical-align: top; + background-color: #f7f7f7; +} + +.CaptionTD{ /* td */ + font-weight: normal; text-align: left; vertical-align: top; + padding: 1px; + border-top: 1px solid #D4D0C8; + white-space: nowrap; + color: #000000; +} +.DataTD { /* td */ + padding: 1px; + border-top: 1px solid #D4D0C8; + vertical-align: top; +} +.navButton{ + border-top: 1px solid #D4D0C8; + border-bottom: 1px solid #D4D0C8; + text-align: center; +} +.navButton input{ + width:19px; +} +input.EditButton { /* buttons are at footer tr */ + font-size: 10px; + color: #15428B; +} +td.EditButton { + text-align: right; + border-top: 1px solid #D4D0C8; + border-bottom: 1px solid #D4D0C8; +} + +.FormElement { /* form element - input -text,textarea,checkbox - select */ + +} +.FormElement { + font-size: 10px; +} +input[type="text"].FormElement{ + color: #15428B; +} +input[type="checkbox"].FormElement{ + width: 15px; + color: #15428B; +} +input[type="textarea"].FormElement{ + color: #15428B; +} +select.FormElement { + font-size: 10px; + color: #15428B; +} +/* End Eorm edit */ + +/* Delete Dialog */ +.DelButton > input { /* buttons are at footer tr */ + font-size: 10px; + color: #15428B; +} +.DelButton { + text-align: right; +} +/* End Delete Dialog */ + +img.jqResize { + position:absolute; + bottom: 0px; + right: 0px; + cursor :se-resize; +} +.dirty-cell { + background: transparent url(images/dirty.gif) no-repeat 0 0; +} +#DelError td { + font-size: 90%; + color: #FF0000; + vertical-align: top; + background-color: #f7f7f7; +} +/* Tree Grid */ +.tree-wrap +{ + float: left; + position: relative; + height: 18px; + white-space: nowrap; + overflow: hidden; +} +.tree-minus +{ + position: absolute; + height: 18px; + width: 16px; + overflow: hidden; + background: url(images/tree_minus.gif) no-repeat; +} +.tree-plus +{ + position: absolute; + height: 18px; + width: 16px; + overflow: hidden; + background: url(images/tree_plus.gif) no-repeat; +} +.tree-leaf +{ + position: absolute; + height: 18px; + width: 16px; + overflow: hidden; + background: url(images/tree_leaf.gif) no-repeat; +} +.treeclick +{ + cursor: pointer; +} +.edit-cell { + background-color: #D2B48C !important; +} +.selected-row, .selected-row TD { + background-color: #c9b9b1; +} \ No newline at end of file diff --git a/site/vendors/css/jqGrid/coffee/images/cd_run.gif b/site/vendors/css/jqGrid/coffee/images/cd_run.gif new file mode 100644 index 0000000000000000000000000000000000000000..c2b8f4edabad00e11a69889bae33c9b91717c6f6 GIT binary patch literal 1025 zcmeH`?=RGG0LMQU8fEQ@HZxmSY}CT(N~kT4B&L>@)!OVlX_bChJ@KTaU)ItX!ktsO z!+3x!r-*Ru<{W3byVdBr)7^bJ9Ot;>zOJu#{0Tkp{owuV{owt2?|trkYFvCSo3P2c zkch^xB`dHDxLj)kR%`^ZuInMX}|&SUUO;Y553``C@OE_#M6>@q6ruc7M;dQ0V8%8 ze$9T+qxlEKUqx@`1P!t&@muMm;aussL}kUI)mp2?%8Elqp>eExewNCUr&kRwXE$Xr z4D+z_?gLe-)`N;_X>+&w)a$qzCtaz2Hn|Fk4hn_oadB<06~a-BtM$i zl(u_1UbzZ-z2$gm^ssv2R_p!mORF@!DO6(`NUV?U`7)s0fXlhgeHmF*Cv&?ujD~4x z+sG7y*3Myt!dSd`vFWo>vxKfblWYn@mhBPAfBidwgS0n`5Ft6b9o_x}@imYbzmT+c zfjlXvD&^zqZ@>lyj2t2o f3la`CGVn;rtSCr4)W)vpHOFJ)qNAORj11NQ63h`c literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/down.gif b/site/vendors/css/jqGrid/coffee/images/down.gif new file mode 100644 index 0000000000000000000000000000000000000000..2b88b365010addc8c963519197e932ffafdaaf5c GIT binary patch literal 683 zcmZ?wbhEHb6lD-)I2Owg=V{%V9^9G{+@2NIksa2V6W*B<(Ulv~l^4~W7uA^`+npcX z14IQt6w_N6+gljdR}|M*oX}qaM2Qp2k|tNCPpM3sQk5~a8i+Ed)n-qx&6-h{GowCt zW&;rA&2BE7*H*Huy>M}F&Eme=C4F_P`zn`Cs9)1xwQOS3+6mQbC)Tc;RJUPD!^UYX z>t=Uvoz<~*cIWoF-P`B&Y+g8N>yl}^7fsr|bn0FpS~hk6iW&P?&fL9v?!nb_4y~Pc zc>lYqgH~+}`g-16mI=XSuu}w=(Y*}_{`>NABR-fLn=Jd|BXLheUw`aq-y&KQ( z+jQyB_A5tsT|2Sw`pE+~P93~?`q0fYhi{)ddiUbV` zcMl)`fWV+&3vLOm)_6Lb2YPnzvkNWqMx&!`=v`?i~C2m9{aodd@mmr zjJ9+XUf^l1rY9#L*vu!u>|Xq6GW$e3feogcqt>gjReAghXgDe`Z_SDi2?5Gi<_mBz itvRsdrF##9NK=LAl7z#p?3}E6ZXW`i!j?ENSOWkKt$g$V literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/find.gif b/site/vendors/css/jqGrid/coffee/images/find.gif new file mode 100644 index 0000000000000000000000000000000000000000..39a0dac9ddcce982cb99dd4229089a0a810cd371 GIT binary patch literal 986 zcmZ?wbhEHb6krfw_};{@bm`4|_x^9)dVBixQ`4rMYX2PF^(|)Q%8SdE-L_w0f9Kv; zjp>H<^_vzgy71-qm*vZEuUK*Jz=3y*7oT-GsGGPup{#6nRn@BH%g^-p@6XL$(BHqO zw|C#=%g;7%zIo~D(>Zev{Q3Lm|NsBXmtUSU=h%`Z7x?PA&!7Khzshdix*H1f#7>?1 zps`%NzJ9}zBah`5h@Cm}pu2n9(xtaHZ+`gc*QctgwQjXBr%%7|nip~F*7sAVp5MCl z^Zon(=1XjE-TKhmyLR#7Q)_qZ-MaOHjZN(x(>lDzVyj1NZbJrhO!IOgpSmfH~m+o1We# z15FOb3!)5$Y)4K8JMnci`QC~+d2vy5yOcwh#GVG_3(O2GuUHC;k0eZy^ssDnG@cb6Va6$(VZ97lONqv5ZzlC+gB9V zUy?ATGHq&g#`M~(8Fe``>T_o{91Nlp?brVhIO;Mx6bO= zI=gfG-0to3dNwVXxOw5E70VXxUNmX%(y4owO zd53{$-Tb2)79HKV=-8$uhqf#~v1QrrotsZ>Uv+xN>NC67o!hhF+}@4n_iZ|IXwR90 zTQ42je&y({(K=Gfbb5UwyNotBhd1gt5LP$ocg1e`00E6OB7Dg_HdIlW^ zAOJ-c1N*;*`ljY4MFCDm4u0vD-d=GgWph_wS94`1k-ioi9$jyrg^PT=b-6TW+pt@C ztzEa?%ZgR8*OSM>W9P2jyDT`2TEsQnjvPI9T!YWP$(_l``GPY8!^O)Not>BzT4fyW z-MjqY;e7`gLF;+}9lJMgF56vZc>7j|+r*#K%=Y*1kC*>2`c!v}^oTqnOa7pe|yvBjVJSmBG9`E<8$$9yE8Yj@X>^H(`O(Vi8uWITGI6-gNRY ztK@JsGB9@vDHlARrqFn>;g)Zc49A8A2M=@bOX+YVG+YmCVP#@MtwUbVx|CCuD_3M1(}kL@rTAt`?@NJD7g1T-cVt+{lozLxII0fq`Ms9dUP2 S4@VK8*$kepelF{r5}E+oVobaM literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/grid-blue-ft.gif b/site/vendors/css/jqGrid/coffee/images/grid-blue-ft.gif new file mode 100644 index 0000000000000000000000000000000000000000..317d17250a97150b7b6addd8f6823c5281db905e GIT binary patch literal 165 zcmZ?wbhEHbWMr7eaD;(j-|B@we|*1p^}_eBU%r0&@cF~Lk8j_+e0=};gFCOEJwCo| z-NTz#p4_>yf9>M4`?ue|aQf|wXQy^;x^m*+q4mpdoH_R6+t>H6UtT=C=i8T0M>elw zzyOLrS-@gCAQEIJ1FKR(0Ix)#gxC}rj?EnWsyf9>M4`?ue|aQf|wXQy^;x^m*+q4mpdoH_R6+t>H6UtT=C=i8T0M>elw zzyOLrS-@gCAQEIJ1FKR(0Ix)#gxC}rj?EnWsn`gA{nAbbG xD0)^!0s{;v{$v3&bwDJ@3M5UJo4TMr{m|wW>nGR$|NozX5K#Qd!pOiN!k`0E2(pubHB-UW zk~d-26cJya+g2AgoGJOtQ(?#8^!|H8LxBd1K;H>vg@ZXpjIAq7xEvzZhczUgzRSe- zz(8Vw#_ZF}w^W_Y+kOATjvBx9x8MKRQ+NLT@Ba;rP0cN>ZS5VMUEMvsef<+APMSPr K>a+qy25SI)OM5UJo4TMr{m|wW>nGR$|NozX5K#Qd!pOiN!k`0E2(pubHA6w6 ztJgWuXO`bY7u^CIhjR({4`1e}InUg0}HO*98rch80n(8Jf#hv&!sy zpzq+QH`)Egma4OPyYGM4QRBD%_WK`u>dwFa{lB5Hskx=Kt-YhOtGlPSuYbbCNt35c JEl^~z1^~M|T`B+o literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/ico-close.gif b/site/vendors/css/jqGrid/coffee/images/ico-close.gif new file mode 100644 index 0000000000000000000000000000000000000000..e4c743e2b23c118fae6775d488796140257df1b1 GIT binary patch literal 854 zcmZ?wbhEHb6krfwXlG!U!@#hVfnhBJ!&U}{y$lS;7#PkmF#P}jpJ5b?hQJ620mYvz zKwti6&;j`slqVQCj2Rd?WIQ%3IM~b~tQDj2;Q(V3pP*F@M?%t}PBGD>lpTS}Ze8rg TX(ked37%~l!K+dv1Q@IV#VZ{# literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/last.gif b/site/vendors/css/jqGrid/coffee/images/last.gif new file mode 100644 index 0000000000000000000000000000000000000000..061006fe2342173fac9891c41e1e4793b8f7ffc7 GIT binary patch literal 737 zcmZ?wbhEHb6lV}+I2OPV=V{%V9^9G{+>ssDnG@cb6Va6$(VZ97lONqv5ZzlC+gB9V zUy?ATGHq&g#`M~(8Fe``>T_o{91Nlp?brVhIO;Mx6bO= zI=gfG-0to3dNwVXxOw5E70VXxUNmX%(y4owO zd53{$-Tb2)79HKV=-8$uhqf#~v1QrrotsZ>Uv+xN>NC67o!hhF+}@4n_iZ|IXwR90 zTQ42je&y({(K=Gfbb5UwyNotBhd1gt5LP$ocg1e`00E6OB7Dg_HdIlW^ zAOJ-c1N*;*`ljY4MFCDm4u0vD-d=GgWph_wS94`1k-ioi9$jyrg^PT=b-6TW+pt@C ztzEa?%ZgR8*OSM>W9P2jyDT`2TEsQnjvPI9T!YWP$(_l``GPY8!^O)Not>BzT4fyW z-Mh^2;L&{t8A0oM0Uf)y?;hG+e)m>~+r*#K%=Y&m+lQC`R^3q8@W``4#!5)b=STj+ zJ{d+I8%Kf1ZAZJ!|1ln@P-bK7%`pXCKfj49COYhg#%4&{K_^N8x$HEX*~6o0a?iZC!S=m6P3Ss?}nCh;l#D>+~DyLOwL V>$-Y2<`-MpBadm%W{NOa0{{&)7qb8W literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/loading.gif b/site/vendors/css/jqGrid/coffee/images/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..e846e1d6c58796558015ffee1fdec546bc207ee8 GIT binary patch literal 771 zcmZ?wbhEHb6krfw*v!MQYQ=(yeQk4RPu{+D?cCXuwr^cCp}%d_ius2R?!0jBXnAQ) zOH<|l|Nj|aK=D7fpKD04vtxj(k)8oFBT!uNCkrbB0}q1^NDatX1{VJbCr|b)oWWMT zS%hVC ~NwO_yO%;SvZ5MdNYf|QNy-I*%yJaj+uTdt+qbZ z4E`Fzb8m}I&!N8OKmWEcCmrLs^Hs&3i)mt@hQVdcqghkaBs*D}tG_lKew4?rTjzIZ z9tSone1TS+TR7tu^CunG)Y7Jg#sw#)sG9C!c0I%LEzP)9;hqRf&)s$D8d5Db{TBs% zgl0~5QQ91luq4Q9tJgt4QLbaxZvAaKeCM9!oy85dg4k>TdBSVqjHub_PG=PO&J-rx z7oYTuF+kH|tG-UK+EkUhDjYx?zW?T|lx>+aOQm zzL$v$zBLo4Cj=G&tw{H}dW?tlTkS)SY4<#NS92z*EY-MMB6Ftp`R=*=*Ev7cS+X%W zMCur^FdlokL}1Y+&aasU2J4#EOuNlnb9CmqgLCGTSY!1BD42pkHY^XidQ5=>YQx%` z*%Pm9D!CkBu&tMWm(%-ejACVWGS2RX5=QOJ$1*tr7F}F+*-OA+Ly&Isg|AEuUYicA z#%IG6kPXkHt{zk2M6zK@Vu^4Q(1zE$?yY6M!^&jQ+2^E?!p7{g*|X6}vuRC3p@jk0 W117c83?+LXEZI4G$p&LV25SKE>nb+@ literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/minus.gif b/site/vendors/css/jqGrid/coffee/images/minus.gif new file mode 100644 index 0000000000000000000000000000000000000000..ef04a54696e17442f7d3a858b18e2da9db1c2e34 GIT binary patch literal 85 zcmZ?wbhEHb6k-r!n8?8J|NsA%mKFvuL-8jIs|W)#gAR}jloeuNU{agYzw-23{>5Bd lu8B3=Q%KlX>BCkwzhTj{h;`hYUHRJn(^Q}S;uB@C1^}ss9ftq_ literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/next.gif b/site/vendors/css/jqGrid/coffee/images/next.gif new file mode 100644 index 0000000000000000000000000000000000000000..dd6d89a98c66a70b6b889e2aff71a612eeee2151 GIT binary patch literal 483 zcmV<90UZ8ENk%w1VHE%s0Hr+uUP(KJXH$h}Q;2I;iELMiY*>nISc`62jBi_va9fRW zU5;{Ik91&^d1jS+XqSCzn0{=Se{G(Ibf$-Kqm6v5k9w_;d$5#%uA7UsnuxWViMO4L zx1Nl%p_03zlD(ysy{47FsF=U0nZc`^!mXaet)9cKpT)4E#j&EsvZTngrpmXf%ebq| zyROc>u+F`)&%UzK!nf4Ly4J|P*vi4#%fi{r!`sfq-O_CX>@2HRA^-&M@dak03rDV0SW*=04x9i000#L6#xJR=fIzE z`0GFt0mK7CYz`>`Ps_%$wLAiebI2&^cHr<%S5j;bu$+3$&cO;zh6_ip+v_gGQ*`V5 z|9~P6LIN~3hlcSHf0!0}!laz`8l$bLa5fCIYpP(|9p`auS2`n+HtE!f)sw@Nn zFEF*XwwAXrFG(pazreqi!M`a44<0MZ%PW@5%N`0C7An=&me$!S77afFCn(|JisI!c zCy+l97bflQ@9-B4Lkb)t_xSnv90pAV8X*D-92i2wfGr3rd;r0)A&3tZ`fd5)K){3x Z8$4{dFhRh)i9;eRkVQa2Hzz>=06Q9e=G6cI literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/nochild.gif b/site/vendors/css/jqGrid/coffee/images/nochild.gif new file mode 100644 index 0000000000000000000000000000000000000000..cf6c61ce9550a7c2a8b546151b7349027979b35f GIT binary patch literal 66 zcmZ?wbhEHb%@85yhr?yqt6 z+`IPt-i;UcZ@qkY`}LFiZ=O7O`|Q!X7mwe)c=G<`(~oane17-(>&JKBK7aiF<wc6hbmm72G|20~i#4vM_Qn z*fZ!b00GFe3~bL2%rE%iEy2Oqr0AH#$KS-k@zkkNsi`@bLo+2}?S>skPl+h_o=Dh| zwfp|+iwwF~M4VRbsawx4YU0E$s@c-o)-D<)!KB{X%fQe#p|6)of|FNm)~pG0=FV2* zbrV-zx^#l-1cqhH#NFjpHf~%sVbeBw4<+T@ySMDwudL)Lqj2=-7KUS|WV{6B&Yzzk zx9Y+LL2qu^Tel|MxqDldo3mT`>C*|%UObbYX3x$e`SH`|FFaB9W&C2l|NQ;KU*EQ( z&|%?%gUuo`XFP))8e2F8l>H_wcyLCnoJqi-Lf|1IGfSkNkYSSxr?9#s1A{dHm6R0g literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/off-last.gif b/site/vendors/css/jqGrid/coffee/images/off-last.gif new file mode 100644 index 0000000000000000000000000000000000000000..280affb194c9e9ec659a65726e09e17428e5a069 GIT binary patch literal 485 zcmZ?wbhEHb6lD-)SgOx3e^Te3MHBZdp0t1YwEfGcA6zx-=!ONScC0$TcjKkQ+pZkm zaplO)YsdHAI(zu`*&}z(AG>?yqt6 z+`IPt-i;UcZ@qkY`}LFiZ=O7O`|Q!X7mwe)c=G<`(~oane17-(>&JKBK7aiF<wc6hbmm72G|20~i#4vM_Qn z*fZ!b00GFe3~VnC%rE%iEy2Oqr0AH#$KS-k@zkkNsi`@bLo+2}?S>skPl+h_o=Dh| zwfp|+iwwF~M4VRbsawx4YU0E$s@c-o)-D<)!KB{X%fQe#p|6)of|FNm)~pE(bLP!f z<8>2PUABC#>V)OX#NFjpHf~axJ7KemyoZwVp1pgv?o(Fslu?yqt6 z+`IPt-i;UcZ@qkY`}LFiZ=O7O`|Q!X7mwe)c=G<`(~oane17-(>&JKBK7aiF<wc6hbmm72G|20~i#4vM_Qn z*fZ!b00GFe3~Ub$%rE%iEy2Oqr0AH#$KS-k@zkkNsi`@bLo+2}?S>skPl+h_o=Dh| zwfp|+iwwF~M4VRbsawx4YU0E$s@c-o)-D<)!KB{X$H34xsh3HDlUHr#tO*RW=Be?z ziK{MIsyb)cQgL^Am38aa&DpR{-a|=w$IhK|b}1`)$|xK?yqt6 z+`IPt-i;UcZ@qkY`}LFiZ=O7O`|Q!X7mwe)c=G<`(~oane17-(>&JKBK7aiF<wc6hbmm72G|20~i#4vM_Qn z*fZ!b00GFe3~Y}N%rEHhl;B`&Qf!p8YM<4tz~rB)Fot3efT~N-zVMFQ#7k9S_8i|ioIT)+~mR%Hk literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/plus.gif b/site/vendors/css/jqGrid/coffee/images/plus.gif new file mode 100644 index 0000000000000000000000000000000000000000..abb84bdfbfa5fbd6f188a3a65eec7b077229eef3 GIT binary patch literal 89 zcmZ?wbhEHb6k-r!n8?8J|NsA%mKFvuL-8jIs|W)#gAR}jloeuNVA7h?zw-23{>5Bd pu8B3=Q+S}8BR4s7p_$&y1Do!qcNrAyQ&FEhP4(+PeoY1jYXCC)AI<;( literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/prev.gif b/site/vendors/css/jqGrid/coffee/images/prev.gif new file mode 100644 index 0000000000000000000000000000000000000000..6ea081390805b75ce76bcc318bb8745089b8c10c GIT binary patch literal 483 zcmV<90UZ8ENk%w1VHE%s0Hr+uUP(KJXH$h}Q;2I;iELMiY*>nISc`62jBi_va9fRW zU5;{Ik91&^d1jS+XqSCzn0{=Se{G(Ibf$-Kqm6v5k9w_;d$5#%uA7UsnuxWViMO4L zx1Nl%p_03zlD(ysy{47FsF=U0nZc`^!mXaet)9cKpT)4E#j&EsvZTngrpmXf%ebq| zyROc>u+F`)&%UzK!nf4Ly4J|P*vi4#%fi{r!`sfq-O_CX>@2HRA^-&M@dak03rDV0SW*=04x9i000#L6#xJR=fIzE z`0GFt0mK7CYz`>`Ps_%$wLAiebI2&^cHr<%S5j;bu$+3$&cO;zh6_ip+v_gGQ*`V5 z|9~P6LIN~3hlqy&0Esm;0!0}!la!N-0F{#&5fCIYpP(|Ap`auS2`n+HtCy>;F)RcD zFEF*Wm$tdJFG(pazrdHk!!0QU4<0MZ%PW`6%N`0C7An=&)tA@R77afFCn(|K;fv!a zCy+l97bflQ@9-B4Lkb)t_xSnv90pAV8X*D-92i2wfGr3rd;r0)A&3tZ`fd5)K){3x Z8$4{dFhRh)i9;eRkVQa2Hzz>=06S8#=Uo5* literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/refresh.gif b/site/vendors/css/jqGrid/coffee/images/refresh.gif new file mode 100644 index 0000000000000000000000000000000000000000..fb74a02ad4fb7d0fe7ad2070ff5dad786bdf417d GIT binary patch literal 581 zcmV-L0=oT2Nk%w1VGsZi0Oo%HS+f74(f_^H^St8!pws{6^#85G9r?e+XDgwaf&=_-KIbiV&XdBcje<1CBig{9V;%>LHl^u^-;dBOj%-~Sqb?D+Zo zq169wr`*on^GL1#QhvfJm;ZIX{}gn_DwX_CiPpO0|4N42OQGS`=Jxjc|4**}g{k0g zs^mnP;GMqakiO?Mi{iZH|0;RV5LmHmv+rx1)$8*7Wt-jo{{J_3$x@@?L#O|CxA+{8 z_+X~&B7oMa%r~jYN|0jFZ#NGCY%KwPx!A^8LW004ggEC2ui z01yBW000M~fPaF6goTDME!3Lt_(C_8KpQC&7}GEM^~Z-N~M7f&2nV;(pqTytgy zf_n&kMhy}Sg&TuvVF^S(ez1a6Un5HpX?cTQEQEGfDXQQBphXHDCRWfm5>RHvhaw>~ TY>_8q${jvKpvc=OC=dWU{>VZe literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/resize.gif b/site/vendors/css/jqGrid/coffee/images/resize.gif new file mode 100644 index 0000000000000000000000000000000000000000..05c807bbcee95410e01fed7a9900bba24ba3a339 GIT binary patch literal 862 zcmZ?wbhEHb6krfw_|Cx4($aG6+PVLuU^E0qWC$q!WMO1rU}Vr?00K~+VBoN3VCInV z*s$PWGl#HN%n5^rhBiJ%6A=c7M^0U0qDdtyHYOcukv5m(d0DvR_yjgjuO$%ysYiPB Klk<2u7_0#kRTRwt literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/row_add.gif b/site/vendors/css/jqGrid/coffee/images/row_add.gif new file mode 100644 index 0000000000000000000000000000000000000000..847ea1d9bde19af1c36349ff7d9c413d986002eb GIT binary patch literal 635 zcmaKp+e_1N7>D2KR7R!CW1e-1qE1RP@epY=b()!#n2B0ak;RU>FF~S3iUWh2X=|9kO{keHQPkupOdPWT!*ziXV>+5)M zfMa81YYR;#Q-41JJt&n*P=ijV0|`hZ5^BF%zgK~;_*$)2uh)Ydy1Tpaa|KRT;`d%8 zH|=(^w}%u(;fH%R8^QNwjg5_?qolpPoit_8G|^}@DwS$y2Sp;0!C=5Q#h`-iZ3GJN zTbspVIXc1@zxh_H6`k4826)U5dUX|@PAATq#bWXPJ`N2L&;h=^O`5Zy85|BWGD0>s z@bD02G8uFLQCz^O2S%f@W%KUtE^cljP8;yk{jRPqnx=80#OWkNlUZ9^i}p-V0#0`> zFC)GyU0g(*dkI1SE!b=}#Uc-17eO6JrBbumED#8ULLtug;dtT9%mOrk%S99l1=49? zf`(tY3#1bafMfYRJw5ofYG8mYE#cZ4uB@DRz<-H8U^3wNQSQm=qzQQaY?5=i;)hIT zUU0B)Y-|x*E@!4BG2G6@xP!D_Ru@V6CS9}i_R%&L#bz+lBlz(yYn=}j>E;%Zo$>V6 zRga+1Xb#27^$)p{757-gyLjhWIOQYp3o9uO^ez{ql_s92IQ}=nqT;H&1D+>%CVElf zej#O1ftMZy2u~*$UgqdquaD=bQ?^@D|EeL^;a<N^h$ISJ6 ys5|1%`ty7_t|zUDIRH6drcPOdsE^!o$smuFTr=UAosTJW4DwA0Rl})l$odBY{~Kli literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/row_delete.gif b/site/vendors/css/jqGrid/coffee/images/row_delete.gif new file mode 100644 index 0000000000000000000000000000000000000000..bd6e784c5f61c4dcde504e280a2c8bebc629dfc9 GIT binary patch literal 634 zcmV-=0)_oYNk%w1VGsZi0Oo%HnVGYblaqdae#AO8d3kwlZEcj4l*J?ykB^V<@Bjb3 zS88f%XlQ8vqdldiv!S80ot?A)XD#{p|E;aF;^P19?f=);|K;WXqN20v>i^&0|Nope z*x3Jyii(z&mY$xohlhv%nKPQ2v-9)+|DHJT@c;jyI{&Fd;NbuK{Qr@Wk=51ztgN$* zjg5qagpiPscXxNUBq7?`|FSbIr>C>76bZYKP_uV0up}e@tw(Wjar8+XzakLvsD|^i zp8v{%|J9+hbuRy1CEniu+1da1_y4FSC)1{iw03sAprFpW!RON7)6@U^`~R^jD5j>l z|7|(HFDd_}KmXsZ|E@^F!ovT3KmW#l|I2jLG!@+3|J}B}!W|R;t3|*mA^(~*|8gw< z|Nq@T9H*zJ|4tXdKRy4rRR3Wqvx7VTZ7affc+Yxt|FBB`v`({fE4aA0yt=yo!d(Bw zU#O_FtE;pB*`@#7q_cD^#5E!RTOf3FbnNW^|6CQjAQkfR|NsC0A^8LW004ggEC2ui z01yBW000NqfPWqy1_l9#Dk?7sj4gkE0bwZ;6C))R85kE78Xb=>DNU4?n3|j*k1Y}s zMJ#>^rJEWqj~x>eEOc`;4h|0w9}u*EAaZdEXl89}IX6-!8v>6mSau3Fbw5;HK@B8d z(tid$15-y)K36Aq-XR2!Ra{VOGihExCvMOoFpqCWR>Yh+pyWv~5dZ+_c{FAVj|e-| zBtS7lgbWTAbUadXAcBxQeU_lm0s!NR0*`Qj$%2Orp8P14gdfE literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/row_edit.gif b/site/vendors/css/jqGrid/coffee/images/row_edit.gif new file mode 100644 index 0000000000000000000000000000000000000000..12cc7e6fbb0215bbafaea389043a9eeb2aa674c3 GIT binary patch literal 996 zcmZ?wbhEHb6krfw_&$xHv~8F-0yB!+ZZex?%*0$^a!S&6qXJwUj>c`3c{%yVg;#*p__x_Hps;&R{@qc6E=GCju zZr}bm>a<1dQR~HvFTHy8Yw3x&SBEDYIr4Jl$_tAZpZfjx_o-7KE?#`{;>G`p9cf#( zJnZh?+uOVL*yOqp5Z!cYXv#@Y!SXf)<*O=wYFW`^SNvK16TW98cPn(t$7!G{`{x@^R<`PWZj8$x_$eMZ2j05%^VY6ivG*MIJSv+q)dOjy9sz!=Up?PM}1D+i1FjypFGGqLkF@@@0ku&}9PhFbuW1>=Mh6CEUsXT*3s zUN}LHkx|ElaYKT_LcL&#A1@7-otkA)px`0F(bg_**?)*-V=$+uh$=5v9i!9ACI!!w zc^L*S3l{LWHab0cXv}hf+noLPpA(4=F8o&J3bG zP=Vr47DkYW4u}Am!N4Lf;32te>B=|(k-%Fb60Vso2Nl=64rD!{aGqJ{PDPzNgEasG Cwj|^L literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/sort_desc.gif b/site/vendors/css/jqGrid/coffee/images/sort_desc.gif new file mode 100644 index 0000000000000000000000000000000000000000..490adfb701f4b08bb1675fe337116a3103872d60 GIT binary patch literal 113 zcmZ?wbhEHb-r5N@t9vUL zP=Vr47DkYW4u}Am!N4LHaKclS(}G>8!NXNTP4#h)yUAf^t80Ld^gF}W}@SOWlZ0R#L1 literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/tab_close-on.gif b/site/vendors/css/jqGrid/coffee/images/tab_close-on.gif new file mode 100644 index 0000000000000000000000000000000000000000..822726888b5dec2b575c81f700a8ede0922d9033 GIT binary patch literal 351 zcmZ?wbhEHbQ=gxgiOWV%C@c;k+Pobd~85s64Fnsj!Il{p3IWu!F z1H&^0hPM(D|I5qY>*;-Pbo>+^{)U_TV?e+L28L@uHQCwkb#*^_d+%ppc*?-=!N%sD zqT*!+hIcwT+ZY%wF))0Ji`&J(unBBF1GRzTPZmZ71{DS!kij57F|gG*Oe*lu;bT0J zvWa6ui&E>0l*d0UX0C3q`TL1t6 literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/tree_leaf.gif b/site/vendors/css/jqGrid/coffee/images/tree_leaf.gif new file mode 100644 index 0000000000000000000000000000000000000000..febfda63651a83fd2614e6fb61e973c5330fbb40 GIT binary patch literal 134 zcmZ?wbhEHb6lM@-*v!KaP`15m{XrJ9x%Z!a?Av@OsAg0C+)chETbWJgzW?&ir|MAA zg3Sy_K=CIFBLf2ugAPaxWCjC^@r09}tM^*GKD+z>0~47J2A;bUB^((`IyMS4UeIK8 dye$*JvQ|8uL10F}!X-r~bFAiH@MdAK1^}~nFHQge literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/tree_minus.gif b/site/vendors/css/jqGrid/coffee/images/tree_minus.gif new file mode 100644 index 0000000000000000000000000000000000000000..bdfa2ecfc397e0665a8c7bdb746b1ba7a9f64a40 GIT binary patch literal 132 zcmZ?wbhEHb6lM@-Sj5Wk|NsBwIp>nk{hu>uPI7WGkjnrDia%Kx85md@bU-|iS_Wp% zh+TL78B8-=BFzx6yFl&El-hs;6_2m6tg+a)N{EB$_dSLkXSVb{=aE}0w&P{f;dvJi gdR=pKU$((xlF9tQ)w+Z^fq{)d2gqgs zsbygH&)9Wm-xE()md?$giG_TO$18&w8e#%d+BoMdTre%a_tfFX*YsyuTi^5ikj+xL pQ0Z}o@~al#r%WueUek}Obl)o86s7hyoKdOw{EIDBdp#H!tO1AYH}e1h literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/coffee/images/up.gif b/site/vendors/css/jqGrid/coffee/images/up.gif new file mode 100644 index 0000000000000000000000000000000000000000..b49eaa97043ab88b42ac33307e34fa6f1d998f6b GIT binary patch literal 673 zcmZ?wbhEHb6lD-)I2Oqe=V{%V9^9G{+>ssDnG@cb6VaI)(FH_#kzILFJ^9f+1<}2Q zv3*5xy~S~T#qoV53H>0H*k77Bu{?QFdGh3nv?-NoldICFR%cAD$(&Z3HN7@#MqSQ~ z`rMffxicFJ7BuJ0Yb%-8Ub?KkaB*+Vn*OR~lN#4ftlcoBVbk>1b+fy-&hFekw|o1% zp6&DccFgbFyl~QrWec|~p0ab%q}_`q?Oi%`@3N`;SIpSIa^~*Ua}Tbbb7<|n!)xd5 zTfgw|y7@;pEIPVz(XmZSPHb6rc-zWT+gF|1zWVfz)n|6EJGW=UxxE|D@7r|g(Do}w zcU?QN@A`@TH%=YAdHT@JGly@VJ9_ux$@`a2Ke&4K!PRpQubuxt5J2%K3nLdpJ%bJd z5P;%@f&E`YeN&SJAFC)ABe$%&aC3jNkO-5afs>cJjTV!%!h|McP7McVR}XI=Uq62n zPW}mota|p2OP8+~JEm zj)#UZ)yt`v-(h(9>eZFda8pBG&F6<+e|sD5Alb}_MizOZ!n(L6;VKJhb|U#_Xh?vv8~m+_eGZP0U!seGjLYQ~vu1O*n7+)T46j|b7)i}x7vB$sO&1J!tM?uSc1!@vRRh*j{ RSXgAtHY6n6S?s`I4FJeff$jhR literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/grid.css b/site/vendors/css/jqGrid/green/grid.css new file mode 100644 index 0000000..6f28c5c --- /dev/null +++ b/site/vendors/css/jqGrid/green/grid.css @@ -0,0 +1,459 @@ +.GridHeader { +} +.Header { + width: 100%; + } + +.Header th { + font-size: 100%; font-weight: bold; text-align: left; + padding: 3px; + background-image: url('images/headerbg.gif'); color: #ffffff; + width: 100%; + white-space: nowrap; + } + +.HeaderLeft { + background-image: url(images/headerleft.gif); + } + +.HeaderRight { + background-image: url(images/headerright.gif); + } +.HeaderButton { + background-image: url(images/headerbg.gif); +} +.HeaderButton img{ + width: 20px; +} + +.HeaderLeft img{ + width: 4px; + } + +.HeaderRight img{ + width: 9px; + } +.GridHeader table {margin:0;} +.GridHeader td, tr {padding:0;} + +/* Grid */ +table.scroll { + table-layout: fixed; + margin-bottom :0px; +} +table.scroll tbody tr { + background-color: #fffcf2; +} + +table.scroll tbody tr.alt { + background-color: #ecf7e4; +} + +table.scroll tr.over td{ + background-color: #FFDEAD; +} + + table.scroll tbody tr.selected td { + background: #3c964b; + color: #ecf7e4; +} + + table.scroll tbody td { + + padding: 2px; + text-align: left; + border-bottom: 1px solid #3c964b; + border-left: 1px solid #3c964b; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + height : auto; +} + +table.scroll thead th { + + padding: 2px; + border-bottom: 1px solid #3c964b; + border-left: 1px solid #3c964b; + text-align: left; + font-weight: normal; + overflow: hidden; + white-space: nowrap; + background-image: url(images/grid-blue-hd.gif); + height : 17px; +} + +table.scroll th div { + overflow: hidden; +/* white-space: nowrap;*/ + word-wrap: break-word; + height : 17px; +} +table.scroll th span { + cursor: e-resize; + width: 10px; + float: right; + display: block; + margin: -2px -1px -2px 0px; + height: 18px; + overflow: hidden; + white-space: nowrap; +} + +table.scroll thead { +} + +/* End Grid */ + +/* Pager */ +div.scroll { + vertical-align: top; + height: 23px; + white-space: nowrap; + text-align: center; + background-image: url(images/grid-blue-ft.gif); +/* + border-left: 1px solid #3c964b; + border-right: 1px solid #3c964b; + border-bottom: 1px solid #3c964b; +*/ +} +div.scroll span { + vertical-align : top; +} +.selbox { + font-size: x-small; + vertical-align : top; +} +input.selbox{ + font-size: x-small; + vertical-align : top; +} +.pgbuttons { + margin-top :2px; + width: 19px; +} +.nav-table-left { + padding:1px; + float: left; +/* position:absolute;*/ +} +.nav-table-right { + padding:1px; + float: right; +} +table.navtable {margin-bottom:0; width: auto;} + +table.navtable tr{ + background-image: url(images/grid-blue-ft.gif); +} + +table.navtable td.nav-button { +/* margin-top:2px;*/ + border: 1px solid #E2ECF8; + white-space: nowrap; +} + +table.navtable td.nav-hover { + border: 1px solid #3c964b; +} + +table.tbutton tr td{ + border : none; + padding:0px; +} + + +img.jsHover { /*not used */ + border: 1px solid #99CCFF; +} +/* End Pager */ +/*multiselect checkbox */ +.cbox { + height: 10px; + width: 10px; + /*border:1px solid #999;*/ +} +/* end multiselect */ + + +/* loading div */ +div.loading { + position: absolute; + padding: 3px; + text-align: center; + font-weight: bold; + background: red; + color: white; + display: none; +} + +div.loadingui { + display:none; + z-index:6000; + position:absolute; +} + + +div.loadingui div.msgbox { + position: relative; + z-index:6001; + left: 35%; + top:45%; + background: url(images/loading.gif) no-repeat left; + width: 100px; + border: 2px solid #B2D2FF; + text-align: right; + height: auto; + padding:2px; + margin: 0px; +} + +/* end loading div */ +/* toolbar */ +div.userdata { + margin-top: 0px; + background-color : #fffcf2; + height : 20px; + border-left: 1px solid #3c964b; + border-right: 1px solid #3c964b; + overflow: hidden; +} +/* end toolbar */ +/*Subgrid text mode*/ +.subgrid { + height: 100%; + overflow: auto; +} +.tablediv { + background-color: White; + border-spacing: 1px; /*cellspacing:poor IE support for this*/ + border-collapse: separate; + width:100%; /* FF hack poor when scroling subgrid */ +} +.celldiv { + float: left; + display: table-cell; + border: 1px dotted #CCCCCC; + overflow: auto; + white-space: normal; +} +.celldivth { + float: left; /*fix for buggy browsers*/ + border: 1px solid #CCCCCC; + background-color: #99CCFF; + border-bottom: 1px solid #CBC7B8; + text-align: left; + overflow: auto; +} +.rowdiv { + display: table-row; + background: #F9F9F9 none; + color: #000000; + width: 100%; + overflow:auto; +} +/* End Subgrid */ + +/* InLine editing */ +input.editable[type="text"] { + font-size: x-small; + overflow: hidden; +} +input.editable[type="checkbox"] { +} + +textarea.editable { + overflow-y: auto; +} + +select.editable { + font-size: x-small; +} +/* End Inline Editing */ + + +/* Modal window */ +.modaltext{ /*caption */ + text-align : left; +} +.modalwin{ + border:1px solid #555555; + text-align:left; + margin: 0 auto; + background: #F9F9F9; + overflow: auto; +} + +.modalhead{ + background-image: url(images/grid-blue-hd.gif); + height: 20px; +} +.modalcontent { + overflow : auto; + background:#F9F9F9; + margin-bottom: 10px; + margin-left: 5px; +} +/* End modal window */ +/*search dialog */ +input.search { + margin: 2px; + width: 70px; + font-size: 10px; + color: #15428B; +} + +select.search { + margin: 2px; + width: 70px; + font-size: 10px; + color: #15428B; +} +.buttonsearch { + width : 50px; + font-size: 10px; + color: #15428B; +} +/*End search */ + +/* Form edit */ + +.FormGrid { + margin: 0px; +} +.EditTable { + width: 100%; +} + +.FormData { /* tr */ + +} +#FormError td { + font-size: 90%; + color: #FF0000; + vertical-align: top; + background-color: #f7f7f7; +} + +.CaptionTD{ /* td */ + font-weight: normal; text-align: left; vertical-align: top; + padding: 1px; + border-top: 1px solid #D4D0C8; + white-space: nowrap; + color: #000000; +} +.DataTD { /* td */ + padding: 1px; + border-top: 1px solid #D4D0C8; + vertical-align: top; +} +.navButton{ + border-top: 1px solid #D4D0C8; + border-bottom: 1px solid #D4D0C8; + text-align: center; +} +.navButton input { + width:18px; +} +input.EditButton { /* buttons are at footer tr */ + font-size: 10px; + color: #15428B; +} +td.EditButton { + text-align: right; + border-top: 1px solid #D4D0C8; + border-bottom: 1px solid #D4D0C8; +} + +.FormElement { /* form element - input -text,textarea,checkbox - select */ + +} +.FormElement { + font-size: 10px; +} +input[type="text"].FormElement{ + color: #15428B; +} +input[type="checkbox"].FormElement{ + width: 15px; + color: #15428B; +} +input[type="textarea"].FormElement{ + color: #15428B; +} +select.FormElement { + font-size: 10px; + color: #15428B; +} +/* End Eorm edit */ + +/*delete dialog */ +.DelButton > input { /* buttons are at footer tr */ + font-size: 10px; + color: #15428B; +} +.DelButton { + text-align: right; +} +/* End Delete Dialog */ +/* Resizing corner */ +img.jqResize { + position:absolute; + bottom: 0px; + right: 0px; + cursor :se-resize; +} +.dirty-cell { + background: transparent url(images/dirty.gif) no-repeat 0 0; +} +#DelError td { + font-size: 90%; + color: #FF0000; + vertical-align: top; + background-color: #f7f7f7; +} + +/* Tree Grid */ +.tree-wrap +{ + float: left; + position: relative; + height: 18px; + white-space: nowrap; + overflow: hidden; +} +.tree-minus +{ + position: absolute; + height: 18px; + width: 16px; + overflow: hidden; + background: url(images/tree_minus.gif) no-repeat; +} +.tree-plus +{ + position: absolute; + height: 18px; + width: 16px; + overflow: hidden; + background: url(images/tree_plus.gif) no-repeat; +} +.tree-leaf +{ + position: absolute; + height: 18px; + width: 16px; + overflow: hidden; + background: url(images/tree_leaf.gif) no-repeat; +} +.treeclick +{ + cursor: pointer; +} +.edit-cell { + background-color: #FFDEAD !important; +} +.selected-row, .selected-row TD { + background-color: #3c964b; +} diff --git a/site/vendors/css/jqGrid/green/images/cd_run.gif b/site/vendors/css/jqGrid/green/images/cd_run.gif new file mode 100644 index 0000000000000000000000000000000000000000..c2b8f4edabad00e11a69889bae33c9b91717c6f6 GIT binary patch literal 1025 zcmeH`?=RGG0LMQU8fEQ@HZxmSY}CT(N~kT4B&L>@)!OVlX_bChJ@KTaU)ItX!ktsO z!+3x!r-*Ru<{W3byVdBr)7^bJ9Ot;>zOJu#{0Tkp{owuV{owt2?|trkYFvCSo3P2c zkch^xB`dHDxLj)kR%`^ZuInMX}|&SUUO;Y553``C@OE_#M6>@q6ruc7M;dQ0V8%8 ze$9T+qxlEKUqx@`1P!t&@muMm;aussL}kUI)mp2?%8Elqp>eExewNCUr&kRwXE$Xr z4D+z_?gLe-)`N;_X>+&w)a$qzCtaz2Hn|Fk4hn_oadB<06~a-BtM$i zl(u_1UbzZ-z2$gm^ssv2R_p!mORF@!DO6(`NUV?U`7)s0fXlhgeHmF*Cv&?ujD~4x z+sG7y*3Myt!dSd`vFWo>vxKfblWYn@mhBPAfBidwgS0n`5Ft6b9o_x}@imYbzmT+c zfjlXvD&^zqZ@>lyj2t2o f3la`CGVn;rtSCr4)W)vpHOFJ)qNAORj11NQ63h`c literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/down.gif b/site/vendors/css/jqGrid/green/images/down.gif new file mode 100644 index 0000000000000000000000000000000000000000..4fc7f661166f982c90b243de2e18f98d944f00d0 GIT binary patch literal 734 zcmZ?wbhEHb6lD-)_{PBS|MSWJ|NkGjvS8Bwrr4zkR+BwlW(HVI@^qUW=(r@vdWx6t zyfBwp0k$)I>d*8{x;)oqO<3oJsW#KS-8V&+Y{)O(kng-A#JtPZdwZ6!^LS?Fi@rMj`;pdv$`)#x0~x{H`~`?VSvx}IL~d-QG2t(cBcU?vY+RF z^WlcOk2hOS_AEW#RCugDWLIjy&LsQ!{y_C92TM{87ANcn*%i1m$!|vjP?=@FJJ2ye zhuO^V0U8Lj#dTdc&?Oe#ZehFAf!eJmdRX?k15F00ndV)2vaReyOTzvFpdnt{Vm!7+ z0Tnnc4RTx@Xwl~m)Me4@2Gnle?V5O?Fn)hN&~Tu4a*xzxAE^Rr2L?s^`N^&4CeFIH zWX9D+vHNnP_vWM@DoZ<93bX>~NNb=PpsRpJ^|+a}JDavTnY1{WG&=&3ag(FZ_E?~$ zE~`VGSB1K*4+lCG80+Z^fuWv3hXDvcal*jF3n{6@6lNfi}h!vRg2!7u~boB*d?jN6czdC**%#ujsr(Hnw5Ev zX?`im;cY3yV0tr{5Aeqab{+k*DoT-8sV`51*Or{3jIV zF5eQMC!>63j;3(hQ4u?v@NHMxPadAkp6+JhsLYykzOT@FLSmADG7~4eMa74U%uXH7 z7TYB>UlbfZIa%8JSIx>pZJazin>61<8Z!5b3wSp~?7HH?*ks7T5s@mw!C(ylj!i3~ literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/find.gif b/site/vendors/css/jqGrid/green/images/find.gif new file mode 100644 index 0000000000000000000000000000000000000000..39a0dac9ddcce982cb99dd4229089a0a810cd371 GIT binary patch literal 986 zcmZ?wbhEHb6krfw_};{@bm`4|_x^9)dVBixQ`4rMYX2PF^(|)Q%8SdE-L_w0f9Kv; zjp>H<^_vzgy71-qm*vZEuUK*Jz=3y*7oT-GsGGPup{#6nRn@BH%g^-p@6XL$(BHqO zw|C#=%g;7%zIo~D(>Zev{Q3Lm|NsBXmtUSU=h%`Z7x?PA&!7Khzshdix*H1f#7>?1 zps`%NzJ9}zBah`5h@Cm}pu2n9(xtaHZ+`gc*QctgwQjXBr%%7|nip~F*7sAVp5MCl z^Zon(=1XjE-TKhmyLR#7Q)_qZ-MaOHjZN(x(>lDzVyj1NZbJrhO!IOgpSmfH~m+o1We# z15FOb3!)5$Y)4K8JMnci`QC~+d2vy5yOcwh#GVG_3(O2GuUHC;k0eZy^BM|}UKS=|?=+s*Z}o9*kcFu-SfoaeUasJ&TXyVHOc+0XO8 z`EbMC$D6GudzKz=Dm+#nvMV)UXOjJVf1vu5gC!{kixc*P>ayr{18O(#c1=7`7{5OsXgJV2xkqZUk5mD*1B0Ud{N&bi6K7pp zGUMu^*nPRtdvnqcm8Bgl1zG`gq%}|t&{aUAdfd#~olRSvOj?{wnjL}2xXICHdo0jW zm(`)pt3ut@hXb9;00xRbSr|bK9S{ME69)GG4Gc}qddw^w$s8=qdd+>!`l3n3<_Shw znU!3k`u$Bzau%s6e1?h3vn(aKnfjS{{FV6y{Svdco5xBEv#o8?mo?;1yDPYiKc*=D1%QiGx(bAV0aB6l&DxL+S4 zC5;k9#B^1DT$sdhMBLWCZo_5CiLSiTteZpvw=Ch}khQv@*c-9fF+f*bj4@I9NSA0? z*!oS`MGw3L`3fa86E3Bl6e>%bz9n(`5p8z9?-2|k4IhvBPS{<3cTeSFmebd*@MtwUbVx|CCuD_3M1(}kL@rTAt`?@NJD7g1T-cVt+{lozLxII0fq`Ms9dUP2 S4@VK8*$kepelF{r5}E+oVobaM literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/grid-blue-ft.gif b/site/vendors/css/jqGrid/green/images/grid-blue-ft.gif new file mode 100644 index 0000000000000000000000000000000000000000..801cb7ab84ff050da7d56996237cbb01f28c2a0e GIT binary patch literal 165 zcmZ?wbhEHbWMr7eaD;*3|A&45|Ni{{{oen--~a#l`tQ%@|9?LI`}OkQ&*%Stz5e&< z`2Qad|NVUO@5BE8U(Wvje*6FLxBow%`v3LHzmJFhf4lMj?~nh#-~an^@&Dg%|2_fD zLkEgKS-?U%AQEIJ1FKR(0Ix)#gxC}rj?EnWsPx# literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/grid-blue-hd.gif b/site/vendors/css/jqGrid/green/images/grid-blue-hd.gif new file mode 100644 index 0000000000000000000000000000000000000000..801cb7ab84ff050da7d56996237cbb01f28c2a0e GIT binary patch literal 165 zcmZ?wbhEHbWMr7eaD;*3|A&45|Ni{{{oen--~a#l`tQ%@|9?LI`}OkQ&*%Stz5e&< z`2Qad|NVUO@5BE8U(Wvje*6FLxBow%`v3LHzmJFhf4lMj?~nh#-~an^@&Dg%|2_fD zLkEgKS-?U%AQEIJ1FKR(0Ix)#gxC}rj?EnWsPx# literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/headerbg.gif b/site/vendors/css/jqGrid/green/images/headerbg.gif new file mode 100644 index 0000000000000000000000000000000000000000..13ec9692105714f409ddd31475f0fcf2c9de833e GIT binary patch literal 105 zcmZ?wbhEHbWMr7eu$h6udYX6L>2CYEejb~n689JQ??{Z;lW8-skV5@bKu&t-L}|BghP89o&! z+v-ktr>xA_cz$8zo-FrGkse#4diS;^9VmM6>@Wi%p!k!8k%2*kK?kG|WG4e_rh=;_ zZ^Eo8BECMituAahQ}UUo!j8e|{r8530u2^{z7xs{2Xl-VTUVHHIYg`vYe+nOmx=Fz zfy4rh*{7FpsXCjt`~HU=HGb=FzyGnP?)>}T{~H>cnp;}i+B-VCx_f&2`X@}BGskV5@bKu&t-L}|BghP89o&! z+v-ktr>xA_cz$8zo-FrGkse#4diS;^9VmM6>@Wi%p!k!8k%2*kK?kG|WG4e_hJr#@ zuXCW!EWe2^x&<~4=MwH8zRXc`p1E;>0f&M_zneqS$rvWC3mPH~E2362G?%SrmD%?| z-@#FDviplIRcG^d-~X_q#&7-Y_doX3oqzxPe?wzab4zPmdq-zicTaC$|AdK?CQq4K IpvYhi0FO3U+yDRo literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/ico-close.gif b/site/vendors/css/jqGrid/green/images/ico-close.gif new file mode 100644 index 0000000000000000000000000000000000000000..e4c743e2b23c118fae6775d488796140257df1b1 GIT binary patch literal 854 zcmZ?wbhEHb6krfwXlG!U!@#hVfnhBJ!&U}{y$lS;7#PkmF#P}jpJ5b?hQJ620mYvz zKwti6&;j`slqVQCj2Rd?WIQ%3IM~b~tQDj2;Q(V3pP*F@M?%t}PBGD>lpTS}Ze8rg TX(ked37%~l!K+dv1Q@IV#VZ{# literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/last.gif b/site/vendors/css/jqGrid/green/images/last.gif new file mode 100644 index 0000000000000000000000000000000000000000..4f635292cb7622ad2a151f15a80d2c88021a2373 GIT binary patch literal 760 zcmZ?wbhEHb6lD-)Xk%db|M}$q|NjqMSukmTQ|!_N+ZjG~vwdA=1z1h?beS38xFpDG zlBe73KA5YsWJ7-OhJ5E0A!!Fo zJvK+VtO_-4b1psJRCugD_ec#;FAzB`3pVd^HS2JR-Ip7&C$s<3tnLfb?dJLcZ4B9! z3be~%VZhCY8}2^dY(3f2V`~&pFkoj=!v2EnBUR~#%7BI^?9T^ES@yfTtq%t}1L#_t z89uJ-!hsqCcP4pnk9AocYCqrKex5(jB8xtEi*7edFbT8*sJQZETiJ;gtBD?o2MXi& z=Q}M8a$Fo}(d!0OY~Jl^GtC?5&Gz$?ThC3Lb#2LvtBa!d=0xqy3fr9?wmZ!lC=0Y2 zXj+dO(0m{=Yj-wnb@JL414QndBZ1)nbP3Q^CM`}T&5l51+~k;Yuq5SRvEPma-yQMJ zt3rXn!hi}Cf3h%wM07v|C{7sI|2Hr+H5)Lq@I>*jFdH=YH5*Dsnv^OkSj6Y>N*eYz zF)5eDMDxp=FSoFg;bZD&Vh_+15cW5h-d-B4A;!73$xumNAXb21vCQnGnYyl!EZs$s)gM#hZ^8=XWcM zRK$3?IQa|8TiCzKOkcvur0pRxccGI~dtkfDiY>*TK6`b#+F#&U>2x(-R59b0u1C|6 zW=S_*E(r_gZL*QfthWlkK6ohCz+)78qKDCG`a21ulxYSpwT`n`G8oECi4LgnPFLHm OIf^b_5|vym4AuZPQ7B6Q literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/leaf.gif b/site/vendors/css/jqGrid/green/images/leaf.gif new file mode 100644 index 0000000000000000000000000000000000000000..bc5934e14b002ae664a10099d3cba0210e73b9c0 GIT binary patch literal 203 zcmZ?wbhEHb6k-r!IKsg2|NsBrzkfe__UzH4N4IX>x_0f_!Gi}^u3R}|#*8UbrgU_4 z`1$#{xw$zxImyb(N=izKii)zZumE*25C;^0vapH(tajqjFC}wc#;SFz zC+*QMTEUrc-(})8a|InX*~6o0a?iZC!S=m6P3Ss?}nCh;l#D>+~DyLOwL V>$-Y2<`-MpBadm%W{NOa0{{&)7qb8W literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/loading.gif b/site/vendors/css/jqGrid/green/images/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..e846e1d6c58796558015ffee1fdec546bc207ee8 GIT binary patch literal 771 zcmZ?wbhEHb6krfw*v!MQYQ=(yeQk4RPu{+D?cCXuwr^cCp}%d_ius2R?!0jBXnAQ) zOH<|l|Nj|aK=D7fpKD04vtxj(k)8oFBT!uNCkrbB0}q1^NDatX1{VJbCr|b)oWWMT zS%hVC ~NwO_yO%;SvZ5MdNYf|QNy-I*%yJaj+uTdt+qbZ z4E`Fzb8m}I&!N8OKmWEcCmrLs^Hs&3i)mt@hQVdcqghkaBs*D}tG_lKew4?rTjzIZ z9tSone1TS+TR7tu^CunG)Y7Jg#sw#)sG9C!c0I%LEzP)9;hqRf&)s$D8d5Db{TBs% zgl0~5QQ91luq4Q9tJgt4QLbaxZvAaKeCM9!oy85dg4k>TdBSVqjHub_PG=PO&J-rx z7oYTuF+kH|tG-UK+EkUhDjYx?zW?T|lx>+aOQm zzL$v$zBLo4Cj=G&tw{H}dW?tlTkS)SY4<#NS92z*EY-MMB6Ftp`R=*=*Ev7cS+X%W zMCur^FdlokL}1Y+&aasU2J4#EOuNlnb9CmqgLCGTSY!1BD42pkHY^XidQ5=>YQx%` z*%Pm9D!CkBu&tMWm(%-ejACVWGS2RX5=QOJ$1*tr7F}F+*-OA+Ly&Isg|AEuUYicA z#%IG6kPXkHt{zk2M6zK@Vu^4Q(1zE$?yY6M!^&jQ+2^E?!p7{g*|X6}vuRC3p@jk0 W117c83?+LXEZI4G$p&LV25SKE>nb+@ literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/minus.gif b/site/vendors/css/jqGrid/green/images/minus.gif new file mode 100644 index 0000000000000000000000000000000000000000..ef04a54696e17442f7d3a858b18e2da9db1c2e34 GIT binary patch literal 85 zcmZ?wbhEHb6k-r!n8?8J|NsA%mKFvuL-8jIs|W)#gAR}jloeuNU{agYzw-23{>5Bd lu8B3=Q%KlX>BCkwzhTj{h;`hYUHRJn(^Q}S;uB@C1^}ss9ftq_ literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/next.gif b/site/vendors/css/jqGrid/green/images/next.gif new file mode 100644 index 0000000000000000000000000000000000000000..f611e6fb5fc410c56669de244b3884cd6228dc14 GIT binary patch literal 1177 zcmZ?wbhEHb6lD-)XlG#f|M}$q|NjqMSzzAfYSHUv+3#MmA%D{Trs56xu}c$t=Y?5M z_H>&a=rSw7WoCf=e1DfUVJ@pe>(BH|x;)orhL6=GPpiqERuesd+D)1rJ1nUD9?H1i`rftrSOM>j?`gw1UjoO=KJHy9%ns@ZxoQOS{rN^5JkJaZM zsR7yrL^jjCJ+?;q?uZZBmD+!4R`-SJK#dLy1AMl}d2Wlo`EbMC$D4st0XvgSTb;6x zRHYv(3*4FHw<7^)5zrYxd)?NDyKjzkT^H`LISR-%>u@n^cedzr2f7gGFuU2lPRoLU z4zQW#4Mac}IxP)yTpVcG=kB~B1c)k6ww0Y|0V)Hk0eZIm{N&bi6K7ppGUMtZuWd15 zyVJvVrvcpqG%8_#e*FG?h%TUZiyk-QCP$!W&AVNJ+JPwXKw-lE0-#HP=A;}fNjX^T zyeiaZdo0i#lNKjnaJj4w1qLR=C>Xd9Q2fcl2(n!VM1b-H1IK>`Mh=-3j~$rUV0ZqR8BnFKiT1uN~Pk1g$-;m89o;_JZ*2E zU2$baz@r6A56E(b`3M+0I(6HWPP%r}fZ4r8T$WMdz~aO+5(YXimKYqo>M~Q#QlZ3= z!J&Pgu4zWgNht+}{_QqRQv!q9*{JSC)9=Is7YX@G_h-bces+m2mjsL)g4=l5c!#BnMtY$kqM^ki`MVa8kwnS0Q zB8wHzFHCEe(G2eB5LbMp$H1b{wqU`5`Sx9k&Iy8tDkOCr#TcyjTwoIuH@Tr8#*}ox zMPBj;!&L_+iwA6MGG!-@w21t=FxgxG$iu^(>c1Wym(JHYILVzuDS%bR`^Seie(xh2 T149g^r3yH489oVgV6X-Nqt{HN literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/nochild.gif b/site/vendors/css/jqGrid/green/images/nochild.gif new file mode 100644 index 0000000000000000000000000000000000000000..cf6c61ce9550a7c2a8b546151b7349027979b35f GIT binary patch literal 66 zcmZ?wbhEHb%@85yhr4qh^AbhUvsW=;hoj1Z7;^cwn$5-Cpxa{8g-YYYJ>bE`KyY=zjO^g0&@n)VwO^VHG!SUZ%$tjWE~!1=wfg?%mG?I_UFd5#-vcxOs0QfZuD%J&10p7+157c z%Np{h@$)5E1e^@W@X(Orp35L&E|{L4Vic39bw|tHL{q>_ltHiBPenPEkkr^FWa`sX|x{zpQrTn`>3PfLAC%;auzK8BZFD0|05!i@g8< literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/off-last.gif b/site/vendors/css/jqGrid/green/images/off-last.gif new file mode 100644 index 0000000000000000000000000000000000000000..79e7176700bf94f2e5d6617b6ba8c3ad3fcd04d1 GIT binary patch literal 760 zcmZ?wbhEHb6lD-)Xk%db|M}$q|NpPQ*uMM0s#(`(cU+p%b$M#{o3y0d!jtz`>tuUv6^ArMWuK7ad@ zee-TFpLSzG<=M8wFHRnKethq-*R!n{M##6-ruZY=}41n8>rGp*%kT7anZO!KzKd$&H` zyX5ZL#dp^L!vu&JP=Vr47DkYW4u}B72?P8828O0)17;SUC>|DOgXX?wL&->!Qbh%e z_#9qI!~P~F<+7M)etGld7FIHRO#Mvk0h$8B{^ru#OM^AUIM+5AD#;7P3h*nInVmFK z*AHSa3>+rR9w(klEI+TUrRGafsxVVy~$e_FBh??Vd1<@HjybfF)pz5GnemG?I`Jlp|P zHs{u|?N9ar^#W1t`L4>dZ4Ao_3;hoiMA8hToG^Op*r1cNCuX(WL@QafNo*&=) z>h1oO_ct!Px4zBouDG%y;L(Dm2V}Xzd<2Xgow{vGCtbT~!0g^4F3Tu!U~%FZ2?L!M zOAHQPb(tw=sZip`;Ltu#*EFN$q?7_f|8|?EDFH%_E>oM*c6hAV+30?o!HDUzr_e#R zPDM7&XEzhvIA-o=Ogi$S!R0isgec!T&PNuFhsi9 zGzKO(9MWj`S99~Ps>y6Y{#_9Y4_p-4wF9qd#53PK)yy8(#(!YL2bNjJ;hW-rRIu{o_L$zxR=ifguLdQU#p244(u#FjxZs=~JwC literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/off-prev.gif b/site/vendors/css/jqGrid/green/images/off-prev.gif new file mode 100644 index 0000000000000000000000000000000000000000..4a3b5e468308f63da350eb2673262e90ea0af965 GIT binary patch literal 1175 zcmZ?wbhEHb6lD-)XlG#f|M}$q|NpPQ*j{t4v;KTf!-d`zw-@eyunI`dx;}ftm1!*( zC-hvN+I@Kn5H(-ypK)W+nKu`2f4tXqd20Km$xRpfff~!tv|M?AW5dH8{a0u8UYRlT z=Hh8L7RTEmEvp|ccNj9(;bh@Xo4Dk9KW(v=iuApnHJ2fC#9i?tFLYnP#9LYtMDfy|oU{uq?W>8fZfKnO0z+O~0`aD8eub1}+2?f3h%wY}Wx1pgh6A z@t=W_L*~b02PQTp2^EVE$qNoQItWAvHXV2ER?_+r+op8VwUZZ?xU);hGD;k1Ug#rf zsQY4t$3aup$trdVHI57q+UM!nl=YlE<Mfw4ux@Z*xhz1pl3D>?&=n`WhOF1{s z#TE!iDJ}~r(R|qUP*lL!Y(@NjM!jCuN8VEoa5Eg_P}R_QalPNEQ%Fyxr`%B_g^_`U zC$}K*U=w!{;{w*8FNFsM0(ey#nDZhQJZuYc(Re6eyOYIP#(7G_BKf*KAKgTBDpM4g e!Vd@@70Blibd`~IeVP=>rnp4FS&o&3!5RP=%B9Z$ literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/plus.gif b/site/vendors/css/jqGrid/green/images/plus.gif new file mode 100644 index 0000000000000000000000000000000000000000..abb84bdfbfa5fbd6f188a3a65eec7b077229eef3 GIT binary patch literal 89 zcmZ?wbhEHb6k-r!n8?8J|NsA%mKFvuL-8jIs|W)#gAR}jloeuNVA7h?zw-23{>5Bd pu8B3=Q+S}8BR4s7p_$&y1Do!qcNrAyQ&FEhP4(+PeoY1jYXCC)AI<;( literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/prev.gif b/site/vendors/css/jqGrid/green/images/prev.gif new file mode 100644 index 0000000000000000000000000000000000000000..fd845ac60e9d8d9796fdf6852fca711a82129e28 GIT binary patch literal 1175 zcmZ?wbhEHb6lD-)XlG#f|M}$q|NjqMSzzAfYSHUv+3#MmA%D{Trs56xu}c$t=Y?5M z_H>&a=rSw7WoCfYWKWkhVfANvCS9IuH`~`{hL6=m51>YqX2;G8Q)Bn#IxGyZpXcwo zF5G2RsQaeKw1cI#KsA#*t*3Ya&9UfqGi`JB-X04Sw4UZ2wKpqzZ%)LX%+ljcg~#f1 zkJJFI10tL0-X2?{K;}>Lc3U6rxFpDKuAlFYcpw94c>kqY-4~|&Y>)HY7Jc*KhP#h9 z1679XN;PeD%05z+eyA*PXOiEJgs|Od0Xvg`mI7TEwmTiDz+-b1&`I|5{mnXD%-WqT z`rLsocUl$QG=nF^qzN3jxKSEQ}!AbwC6tPcU%&XJF)z`SI9+iA_mD#o|Nq zg2Rmt0uh2u$6dRXw0^`mGCW!6z^MPJM^Lztb>d{#a~6$?4;D7C#g%y+xX^l{eRjo# zH5HE*EOk)eittcSR&46FDV=of=Lq!5(k_bhxa4rJHtWQS&H&@)3Cb1^*bW>#?#V7~K1E{540Yy7%4sPa zd$f(6-p0RS%vdYgV0~RzG+8sD_NI2_K&dqbN1p-ov%K}O?AGSRd6)-ki z5x<{NuUGYv_ml(N3H8fsa?|14H(o^XvcN9rsWMJXREeJf=#9hR=fHmk#;X#1_ zUX=#syod!4+k#v)9tzm*WO0^po)WQ0zHZM)HxZr66a}X61A<2d@_7VZWu#r7CPlI- NE)j5+V`X8m1^{(TMf?B& literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/refresh.gif b/site/vendors/css/jqGrid/green/images/refresh.gif new file mode 100644 index 0000000000000000000000000000000000000000..fb74a02ad4fb7d0fe7ad2070ff5dad786bdf417d GIT binary patch literal 581 zcmV-L0=oT2Nk%w1VGsZi0Oo%HS+f74(f_^H^St8!pws{6^#85G9r?e+XDgwaf&=_-KIbiV&XdBcje<1CBig{9V;%>LHl^u^-;dBOj%-~Sqb?D+Zo zq169wr`*on^GL1#QhvfJm;ZIX{}gn_DwX_CiPpO0|4N42OQGS`=Jxjc|4**}g{k0g zs^mnP;GMqakiO?Mi{iZH|0;RV5LmHmv+rx1)$8*7Wt-jo{{J_3$x@@?L#O|CxA+{8 z_+X~&B7oMa%r~jYN|0jFZ#NGCY%KwPx!A^8LW004ggEC2ui z01yBW000M~fPaF6goTDME!3Lt_(C_8KpQC&7}GEM^~Z-N~M7f&2nV;(pqTytgy zf_n&kMhy}Sg&TuvVF^S(ez1a6Un5HpX?cTQEQEGfDXQQBphXHDCRWfm5>RHvhaw>~ TY>_8q${jvKpvc=OC=dWU{>VZe literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/resize.gif b/site/vendors/css/jqGrid/green/images/resize.gif new file mode 100644 index 0000000000000000000000000000000000000000..05c807bbcee95410e01fed7a9900bba24ba3a339 GIT binary patch literal 862 zcmZ?wbhEHb6krfw_|Cx4($aG6+PVLuU^E0qWC$q!WMO1rU}Vr?00K~+VBoN3VCInV z*s$PWGl#HN%n5^rhBiJ%6A=c7M^0U0qDdtyHYOcukv5m(d0DvR_yjgjuO$%ysYiPB Klk<2u7_0#kRTRwt literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/row_add.gif b/site/vendors/css/jqGrid/green/images/row_add.gif new file mode 100644 index 0000000000000000000000000000000000000000..847ea1d9bde19af1c36349ff7d9c413d986002eb GIT binary patch literal 635 zcmaKp+e_1N7>D2KR7R!CW1e-1qE1RP@epY=b()!#n2B0ak;RU>FF~S3iUWh2X=|9kO{keHQPkupOdPWT!*ziXV>+5)M zfMa81YYR;#Q-41JJt&n*P=ijV0|`hZ5^BF%zgK~;_*$)2uh)Ydy1Tpaa|KRT;`d%8 zH|=(^w}%u(;fH%R8^QNwjg5_?qolpPoit_8G|^}@DwS$y2Sp;0!C=5Q#h`-iZ3GJN zTbspVIXc1@zxh_H6`k4826)U5dUX|@PAATq#bWXPJ`N2L&;h=^O`5Zy85|BWGD0>s z@bD02G8uFLQCz^O2S%f@W%KUtE^cljP8;yk{jRPqnx=80#OWkNlUZ9^i}p-V0#0`> zFC)GyU0g(*dkI1SE!b=}#Uc-17eO6JrBbumED#8ULLtug;dtT9%mOrk%S99l1=49? zf`(tY3#1bafMfYRJw5ofYG8mYE#cZ4uB@DRz<-H8U^3wNQSQm=qzQQaY?5=i;)hIT zUU0B)Y-|x*E@!4BG2G6@xP!D_Ru@V6CS9}i_R%&L#bz+lBlz(yYn=}j>E;%Zo$>V6 zRga+1Xb#27^$)p{757-gyLjhWIOQYp3o9uO^ez{ql_s92IQ}=nqT;H&1D+>%CVElf zej#O1ftMZy2u~*$UgqdquaD=bQ?^@D|EeL^;a<N^h$ISJ6 ys5|1%`ty7_t|zUDIRH6drcPOdsE^!o$smuFTr=UAosTJW4DwA0Rl})l$odBY{~Kli literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/row_delete.gif b/site/vendors/css/jqGrid/green/images/row_delete.gif new file mode 100644 index 0000000000000000000000000000000000000000..bd6e784c5f61c4dcde504e280a2c8bebc629dfc9 GIT binary patch literal 634 zcmV-=0)_oYNk%w1VGsZi0Oo%HnVGYblaqdae#AO8d3kwlZEcj4l*J?ykB^V<@Bjb3 zS88f%XlQ8vqdldiv!S80ot?A)XD#{p|E;aF;^P19?f=);|K;WXqN20v>i^&0|Nope z*x3Jyii(z&mY$xohlhv%nKPQ2v-9)+|DHJT@c;jyI{&Fd;NbuK{Qr@Wk=51ztgN$* zjg5qagpiPscXxNUBq7?`|FSbIr>C>76bZYKP_uV0up}e@tw(Wjar8+XzakLvsD|^i zp8v{%|J9+hbuRy1CEniu+1da1_y4FSC)1{iw03sAprFpW!RON7)6@U^`~R^jD5j>l z|7|(HFDd_}KmXsZ|E@^F!ovT3KmW#l|I2jLG!@+3|J}B}!W|R;t3|*mA^(~*|8gw< z|Nq@T9H*zJ|4tXdKRy4rRR3Wqvx7VTZ7affc+Yxt|FBB`v`({fE4aA0yt=yo!d(Bw zU#O_FtE;pB*`@#7q_cD^#5E!RTOf3FbnNW^|6CQjAQkfR|NsC0A^8LW004ggEC2ui z01yBW000NqfPWqy1_l9#Dk?7sj4gkE0bwZ;6C))R85kE78Xb=>DNU4?n3|j*k1Y}s zMJ#>^rJEWqj~x>eEOc`;4h|0w9}u*EAaZdEXl89}IX6-!8v>6mSau3Fbw5;HK@B8d z(tid$15-y)K36Aq-XR2!Ra{VOGihExCvMOoFpqCWR>Yh+pyWv~5dZ+_c{FAVj|e-| zBtS7lgbWTAbUadXAcBxQeU_lm0s!NR0*`Qj$%2Orp8P14gdfE literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/row_edit.gif b/site/vendors/css/jqGrid/green/images/row_edit.gif new file mode 100644 index 0000000000000000000000000000000000000000..12cc7e6fbb0215bbafaea389043a9eeb2aa674c3 GIT binary patch literal 996 zcmZ?wbhEHb6krfw_&$xHv~8F-0yB!+ZZex?%*0$^a!S&6qXJwUj>c`3c{%yVg;#*p__x_Hps;&R{@qc6E=GCju zZr}bm>a<1dQR~HvFTHy8Yw3x&SBEDYIr4Jl$_tAZpZfjx_o-7KE?#`{;>G`p9cf#( zJnZh?+uOVL*yOqp5Z!cYXv#@Y!SXf)<*O=wYFW`^SNvK16TW98cPn(t$7!G{`{x@^R<`PWZj8$x_$eMZ2j05%^VY6ivG*MIJSv+q)dOjy9sz!=Up?PM}1D+i1FjypFGGqLkF@@@0ku&}9PhFbuW1>=Mh6CEUsXT*3s zUN}LHkx|ElaYKT_LcL&#A1@7-otkA)px`0F(bg_**?)*-V=$+uh$=5v9i!9ACI!!w zc^L*S3l{LWHab0cXv}hf+noLPpA(4=F8o&J3bGDLRwuPJ~Ql006h`7a9Nn literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/sort_desc.gif b/site/vendors/css/jqGrid/green/images/sort_desc.gif new file mode 100644 index 0000000000000000000000000000000000000000..b21e55eeeba355f3f8b225d8f09440d777685b46 GIT binary patch literal 55 zcmZ?wbhEHbgvl+zaWZp_P-ptBi F4FGR`4K4rx literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/spacer.gif b/site/vendors/css/jqGrid/green/images/spacer.gif new file mode 100644 index 0000000000000000000000000000000000000000..5bfd67a2d6f72ac3a55cbfcea5866e841d22f5d9 GIT binary patch literal 43 mcmZ?wbhEHbWMp7uXkdT>#h)yUAf^t80Ld^gF}W}@SOWlZ0R#L1 literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/tab_close-on.gif b/site/vendors/css/jqGrid/green/images/tab_close-on.gif new file mode 100644 index 0000000000000000000000000000000000000000..822726888b5dec2b575c81f700a8ede0922d9033 GIT binary patch literal 351 zcmZ?wbhEHbQ=gxgiOWV%C@c;k+Pobd~85s64Fnsj!Il{p3IWu!F z1H&^0hPM(D|I5qY>*;-Pbo>+^{)U_TV?e+L28L@uHQCwkb#*^_d+%ppc*?-=!N%sD zqT*!+hIcwT+ZY%wF))0Ji`&J(unBBF1GRzTPZmZ71{DS!kij57F|gG*Oe*lu;bT0J zvWa6ui&E>0l*d0UX0C3q`TL1t6 literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/tree_leaf.gif b/site/vendors/css/jqGrid/green/images/tree_leaf.gif new file mode 100644 index 0000000000000000000000000000000000000000..febfda63651a83fd2614e6fb61e973c5330fbb40 GIT binary patch literal 134 zcmZ?wbhEHb6lM@-*v!KaP`15m{XrJ9x%Z!a?Av@OsAg0C+)chETbWJgzW?&ir|MAA zg3Sy_K=CIFBLf2ugAPaxWCjC^@r09}tM^*GKD+z>0~47J2A;bUB^((`IyMS4UeIK8 dye$*JvQ|8uL10F}!X-r~bFAiH@MdAK1^}~nFHQge literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/tree_minus.gif b/site/vendors/css/jqGrid/green/images/tree_minus.gif new file mode 100644 index 0000000000000000000000000000000000000000..bdfa2ecfc397e0665a8c7bdb746b1ba7a9f64a40 GIT binary patch literal 132 zcmZ?wbhEHb6lM@-Sj5Wk|NsBwIp>nk{hu>uPI7WGkjnrDia%Kx85md@bU-|iS_Wp% zh+TL78B8-=BFzx6yFl&El-hs;6_2m6tg+a)N{EB$_dSLkXSVb{=aE}0w&P{f;dvJi gdR=pKU$((xlF9tQ)w+Z^fq{)d2gqgs zsbygH&)9Wm-xE()md?$giG_TO$18&w8e#%d+BoMdTre%a_tfFX*YsyuTi^5ikj+xL pQ0Z}o@~al#r%WueUek}Obl)o86s7hyoKdOw{EIDBdp#H!tO1AYH}e1h literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/green/images/up.gif b/site/vendors/css/jqGrid/green/images/up.gif new file mode 100644 index 0000000000000000000000000000000000000000..d2a0ee8e6003dc3b4693e65328032d5e150c3345 GIT binary patch literal 735 zcmZ?wbhEHb6lD-)IL65E|MSWJ|NkGjvS8Bwrr4zkR+BwlW(HVI@^qUW=(r@vdWx6t zyfBwp0k$)I>d*8{x;)oqO<3oJsW#KS-8V&+Y{)O(kng-A#JtPZdwZ6!^LS?Fi@rMj`;pdv$`)#x0~x{H`~`?VSvx}IL~d-QG2t(cBcU?vY+RF z^WlcOk2hOS_AEW#RCugDWLIjy&LsQ!{y_C92TM{87ANcn*%i1m$!|vjP?=@FJJ2ye zhuO^V0U8Lj#dTdc&?Oe#ZehFAf!eJmdRX?k15F00ndV)2vaReyOTzvFpdnt{Vm!7+ z0Tnnc4RTx@Xwl~m)Me4@2Gnle?V5O?Fn)hN&~Tu4a*xzxAE^Rr2L?s^`N^&4CeFIH zWX9D+vHNnP_vWM@DoZ<93bX>~NNb=PpsRpJ^|+a}JDavTnY1{WG&=&3ag(FZ_E?~$ zE~`VGSB1K*4+lCG80+Z^fuWv3hXDvcal*jtGTzO)xldK zuEJQmTBN71o{QVSCnq$%*4o_P&s=s^3tK^cu9HGljg1ALil8CS>bZqpdEQ}G_BBBn ze#+_m{&KUpqQyfT4<4=w)=o@KPgAz&X)V6!$oS;x(-eOG)TCCohnJpxG~yFXF>aNA zfBBF-qjRuLUjgIeBL{hzxSqXO9G2JBA(>gw(#hy{ac;r>rlZv>m`=?yFgm8PMcMu2 z>WU|6C4W}9U1XmWac_anb|W9DmgsjEb}mR!+u3J+aN89;SfJY7FDK+RWkX}R@N%a@J(0|s2WOQ|_j7grd7~k~U=08R CVLKH7 literal 0 HcmV?d00001 diff --git a/site/vendors/css/jqGrid/jqModal.css b/site/vendors/css/jqGrid/jqModal.css new file mode 100644 index 0000000..5d37b21 --- /dev/null +++ b/site/vendors/css/jqGrid/jqModal.css @@ -0,0 +1,31 @@ +/* jqModal base Styling courtesy of; + Brice Burgess */ + +/* The Window's CSS z-index value is respected (takes priority). If none is supplied, + the Window's z-index value will be set to 3000 by default (in jqModal.js). You + can change this value by either; + a) supplying one via CSS + b) passing the "zIndex" parameter. E.g. (window).jqm({zIndex: 500}); */ + +.jqmWindow { + display: none; + + position: fixed; + width: 600px; +} + +.jqmOverlay { background-color: #000; } + +/* Background iframe styling for IE6. Prevents ActiveX bleed-through ("); + row.appendChild(td[0]); + gi = 1; + } + if(t.p.subGrid ) { try {$(t).addSubGrid(t.grid.bDiv,row,gi);} catch(e){} si=1;} + for(i = gi+si; i < this.p.colModel.length;i++){ + nm = this.p.colModel[i].name; + td = $(''); + t.formatter(td, row, data[nm], i, 'add'); + t.formatCol($(td[0],t.grid.bDiv),i); + row.appendChild(td[0]); + } + switch (pos) { + case 'last': + $(t.rows[t.rows.length-1]).after(row); + break; + case 'first': + $(t.rows[0]).after(row); + break; + case 'after': + sind = $(t).getInd(t.rows,src); + sind >= 0 ? $(t.rows[sind]).after(row): ""; + break; + case 'before': + sind = $(t).getInd(t.rows,src); + sind > 0 ? $(t.rows[sind-1]).after(row): ""; + break; + } + t.p.records++; + if($.browser.safari || $.browser.opera) { + t.scrollLeft = t.scrollLeft; + $("td",t.rows[1]).each( function( k ) { + $(this).css("width",t.grid.headers[k].width+"px"); + t.grid.cols[k] = this; + }); + } + if( t.p.altRows === true ) { + if (pos == "last") { + if (t.rows.length % 2 == 1) {$(row).addClass('alt');} + } else { + $(t.rows).slice(1).each(function(i){ + if(i % 2 ==1) {$(this).addClass('alt');} + else {$(this).removeClass('alt');} + }); + } + } + try {t.p.afterInsertRow(row.id,data); } catch(e){} + t.updatepager(); + success = true; + }); + } + return success; + }; + $.fn.hideCol = function(colname) { + return this.each(function() { + var $t = this,w=0, fndh=false, gtw; + if (!$t.grid ) {return;} + if( typeof colname == 'string') {colname=[colname];} + $(this.p.colModel).each(function(i) { + if ($.inArray(this.name,colname) != -1 && !this.hidden) { + w = parseInt($("tr th:eq("+i+")",$t.grid.hDiv).css("width"),10); + $("tr th:eq("+i+")",$t.grid.hDiv).css({display:"none"}); + $($t.rows).each(function(j){ + $("td:eq("+i+")",$t.rows[j]).css({display:"none"}); + }); + $t.grid.cols[i].style.width = 0; + $t.grid.headers[i].width = 0; + $t.grid.width -= w; + this.hidden=true; + fndh=true; + } + }); + if(fndh===true) { + gtw = Math.min($t.p._width,$t.grid.width); + $("table:first",$t.grid.hDiv).width(gtw); + $("table:first",$t.grid.bDiv).width(gtw); + $($t.grid.hDiv).width(gtw); + $($t.grid.bDiv).width(gtw); + if($t.p.pager && $($t.p.pager).hasClass("scroll") ) { + $($t.p.pager).width(gtw); + } + if($t.p.caption) {$($t.grid.cDiv).width(gtw);} + if($t.p.toolbar[0]) {$($t.grid.uDiv).width(gtw);} + $t.grid.hDiv.scrollLeft = $t.grid.bDiv.scrollLeft; + } + }); + }; + $.fn.showCol = function(colname) { + return this.each(function() { + var $t = this, w = 0, fdns=false, gtw, ofl; + if (!$t.grid ) {return;} + if( typeof colname == 'string') {colname=[colname];} + $($t.p.colModel).each(function(i) { + if ($.inArray(this.name,colname) != -1 && this.hidden) { + w = parseInt($("tr th:eq("+i+")",$t.grid.hDiv).css("width"),10); + $("tr th:eq("+i+")",$t.grid.hDiv).css("display",""); + $($t.rows).each(function(j){ + $("td:eq("+i+")",$t.rows[j]).css("display","").width(w); + }); + this.hidden=false; + $t.grid.cols[i].style.width = w; + $t.grid.headers[i].width = w; + $t.grid.width += w; + fdns=true; + } + }); + if(fdns===true) { + gtw = Math.min($t.p._width,$t.grid.width); + ofl = ($t.grid.width <= $t.p._width) ? "hidden" : "auto"; + $("table:first",$t.grid.hDiv).width(gtw); + $("table:first",$t.grid.bDiv).width(gtw); + $($t.grid.hDiv).width(gtw); + $($t.grid.bDiv).width(gtw).css("overflow-x",ofl); + if($t.p.pager && $($t.p.pager).hasClass("scroll") ) { + $($t.p.pager).width(gtw); + } + if($t.p.caption) {$($t.grid.cDiv).width(gtw);} + if($t.p.toolbar[0]) {$($t.grid.uDiv).width(gtw);} + $t.grid.hDiv.scrollLeft = $t.grid.bDiv.scrollLeft; + } + }); + }; + $.fn.setGridWidth = function(nwidth, shrink) { + return this.each(function(){ + var $t = this, chw=0,w,cw,ofl; + if (!$t.grid ) {return;} + if(typeof shrink != 'boolean') {shrink=true;} + var testdata = getScale(); + if(shrink !== true) {testdata[0] = Math.min($t.p._width,$t.grid.width); testdata[2]=0;} + else {testdata[2]= testdata[1]} + $.each($t.p.colModel,function(i,v){ + if(!this.hidden && this.name != 'cb' && this.name!='subgrid') { + cw = shrink !== true ? $("tr:first th:eq("+i+")",$t.grid.hDiv).css("width") : this.width; + w = Math.floor((IENum(nwidth)-IENum(testdata[2]))/IENum(testdata[0])*IENum(cw)); + chw += w; + $("table thead tr:first th:eq("+i+")",$t.grid.hDiv).css("width",w+"px"); + $("table:first tbody tr:first td:eq("+i+")",$t.grid.bDiv).css("width",w+"px"); + $t.grid.cols[i].style.width = w; + $t.grid.headers[i].width = w; + } + if(this.name=='cb' || this.name == 'subgrid'){chw += IENum(this.width);} + }); + if(chw + testdata[1] <= nwidth || $t.p.forceFit === true){ ofl = "hidden"; tw = nwidth;} + else { ofl= "auto"; tw = chw + testdata[1];} + $("table:first",$t.grid.hDiv).width(tw); + $("table:first",$t.grid.bDiv).width(tw); + $($t.grid.hDiv).width(nwidth); + $($t.grid.bDiv).width(nwidth).css("overflow-x",ofl); + if($t.p.pager && $($t.p.pager).hasClass("scroll") ) { + $($t.p.pager).width(nwidth); + } + if($t.p.caption) {$($t.grid.cDiv).width(nwidth);} + if($t.p.toolbar[0]) {$($t.grid.uDiv).width(nwidth);} + $t.p._width = nwidth; $t.grid.width = tw; + if($.browser.safari || $.browser.opera ) { + $("table tbody tr:eq(1) td",$t.grid.bDiv).each( function( k ) { + $(this).css("width",$t.grid.headers[k].width+"px"); + $t.grid.cols[k] = this; + }); + } + $t.grid.hDiv.scrollLeft = $t.grid.bDiv.scrollLeft; + function IENum(val) { + val = parseInt(val,10); + return isNaN(val) ? 0 : val; + } + function getScale(){ + var testcell = $("table tr:first th:eq(1)", $t.grid.hDiv); + var addpix = IENum($(testcell).css("padding-left")) + + IENum($(testcell).css("padding-right"))+ + IENum($(testcell).css("border-left-width"))+ + IENum($(testcell).css("border-right-width")); + var w =0,ap=0; + $.each($t.p.colModel,function(i,v){ + if(!this.hidden) { + w += parseInt(this.width); + ap += addpix; + } + }); + return [w,ap,0]; + } + }); + }; + $.fn.setGridHeight = function (nh) { + return this.each(function (){ + var ovfl, ovfl2, $t = this; + if(!$t.grid) {return;} + if($t.p.forceFit === true) { ovfl2='hidden'; } else {ovfl2=$($t.grid.bDiv).css("overflow-x");} + ovfl = (isNaN(nh) && $.browser.mozilla && (nh.indexOf("%")!=-1 || nh=="auto")) ? "hidden" : "auto"; + $($t.grid.bDiv).css({height: nh+(isNaN(nh)?"":"px"),"overflow-y":ovfl,"overflow-x": ovfl2}); + $t.p.height = nh; + }); + }; + $.fn.setCaption = function (newcap){ + return this.each(function(){ + this.p.caption=newcap; + $("table:first th",this.grid.cDiv).html(newcap); + $(this.grid.cDiv).show(); + }); + }; + $.fn.setLabel = function(colname, nData, prop, attrp ){ + return this.each(function(){ + var $t = this, pos=-1; + if(!$t.grid) {return;} + if(isNaN(colname)) { + $($t.p.colModel).each(function(i){ + if (this.name == colname) { + pos = i;return false; + } + }); + } else {pos = parseInt(colname,10);} + if(pos>=0) { + var thecol = $("table:first th:eq("+pos+")",$t.grid.hDiv); + if (nData){ + $("div",thecol).html(nData); + } + if (prop) { + if(typeof prop == 'string') {$(thecol).addClass(prop);} else {$(thecol).css(prop);} + } + if(typeof attrp == 'object') {$(thecol).attr(attrp);} + } + }); + }; + $.fn.setCell = function(rowid,colname,nData,cssp,attrp) { + return this.each(function(){ + var $t = this, pos =-1; + if(!$t.grid) {return;} + if(isNaN(colname)) { + $($t.p.colModel).each(function(i){ + if (this.name == colname) { + pos = i;return false; + } + }); + } else {pos = parseInt(colname,10);} + if(pos>=0) { + var ind = $($t).getInd($t.rows,rowid); + if (ind>=0){ + var tcell = $("td:eq("+pos+")",$t.rows[ind]); + if(nData != "") { + $t.formatter(tcell, $t.rows[ind], nData, pos,'edit'); + } + if (cssp){ + if(typeof cssp == 'string') {$(tcell).addClass(cssp);} else {$(tcell).css(cssp);} + } + if(typeof attrp == 'object') {$(tcell).attr(attrp);} + } + } + }); + }; + $.fn.getCell = function(rowid,col) { + var ret = false; + this.each(function(){ + var $t=this, pos=-1; + if(!$t.grid) {return;} + if(isNaN(col)) { + $($t.p.colModel).each(function(i){ + if (this.name == col) { + pos = i;return false; + } + }); + } else {pos = parseInt(col,10);} + if(pos>=0) { + var ind = $($t).getInd($t.rows,rowid); + if(ind>=0) { + ret = $.htmlDecode($("td:eq("+pos+")",$t.rows[ind]).html()); + } + } + }); + return ret; + }; + $.fn.clearGridData = function() { + return this.each(function(){ + var $t = this; + if(!$t.grid) {return;} + $("tbody tr:gt(0)", $t.grid.bDiv).remove(); + $t.p.selrow = null; $t.p.selarrrow= []; $t.p.savedRow = []; + $t.p.records = '0';$t.p.page='0';$t.p.lastpage='0'; + $t.updatepager(); + }); + }; + $.fn.getInd = function(obj,rowid,rc){ + var ret =false; + $(obj).each(function(i){ + if(this.id==rowid) { + ret = rc===true ? this : i; + return false; + } + }); + return ret; + }; + $.htmlDecode = function(value){ + if(value==' ' || value==' ' || (value.length==1 && value.charCodeAt(0)==160)) { return "";} + return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"'); + }; + return this.each( function() { + if(this.grid) {return;} + this.p = p ; + if(this.p.colNames.length === 0) { + for (var i=0;i
    "+this.p.loadtext+"
    ").insertBefore(this); + $(this).attr({cellSpacing:"0",cellPadding:"0",border:"0"}); + var ts = this, + bSR = $.isFunction(this.p.beforeSelectRow) ? this.p.beforeSelectRow :false, + onSelectRow = $.isFunction(this.p.onSelectRow) ? this.p.onSelectRow :false, + ondblClickRow = $.isFunction(this.p.ondblClickRow) ? this.p.ondblClickRow :false, + onSortCol = $.isFunction(this.p.onSortCol) ? this.p.onSortCol : false, + loadComplete = $.isFunction(this.p.loadComplete) ? this.p.loadComplete : false, + loadError = $.isFunction(this.p.loadError) ? this.p.loadError : false, + loadBeforeSend = $.isFunction(this.p.loadBeforeSend) ? this.p.loadBeforeSend : false, + onRightClickRow = $.isFunction(this.p.onRightClickRow) ? this.p.onRightClickRow : false, + afterInsRow = $.isFunction(this.p.afterInsertRow) ? this.p.afterInsertRow : false, + onHdCl = $.isFunction(this.p.onHeaderClick) ? this.p.onHeaderClick : false, + beReq = $.isFunction(this.p.beforeRequest) ? this.p.beforeRequest : false, + onSC = $.isFunction(this.p.onCellSelect) ? this.p.onCellSelect : false, + sortkeys = ["shiftKey","altKey","ctrlKey"]; + if ($.inArray(ts.p.multikey,sortkeys) == -1 ) {ts.p.multikey = false;} + var IntNum = function(val,defval) { + val = parseInt(val,10); + if (isNaN(val)) { return (defval) ? defval : 0;} + else {return val;} + }; + var formatCol = function (elem, pos){ + var ral = ts.p.colModel[pos].align; + if(ral) { $(elem).css("text-align",ral);} + if(ts.p.colModel[pos].hidden) {$(elem).css("display","none");} + }; + var resizeFirstRow = function (t,er){ + $("tbody tr:eq("+er+") td",t).each( function( k ) { + $(this).css("width",grid.headers[k].width+"px"); + grid.cols[k] = this; + }); + }; + var addCell = function(t,row,cell,pos) { + var td; + td = document.createElement("td"); + formatter($(td,t),row,cell,pos,'add'); + row.appendChild(td); + formatCol($(td,t), pos); + }; + var formatter = function (elem, row, cellval , colpos, act){ + var cm = ts.p.colModel[colpos]; + if(cm.formatter) { + var opts= {rowId: row.id, colModel:cm,rowData:row}; + if($.isFunction( cm.formatter ) ) { + cm.formatter(elem,cellval,opts,act); + } else if($.fmatter){ + $(elem).fmatter(cm.formatter, cellval,opts, act); + } else { + $(elem).html(cellval || ' '); + } + }else { + $(elem).html(cellval || ' '); + } + elem[0].title = elem[0].textContent || elem[0].innerText; + }; + var addMulti = function(t,row){ + var cbid,td; + td = document.createElement("td"); + cbid = "jqg_"+row.id; + $(td,t).html(""); + formatCol($(td,t), 0); + row.appendChild(td); + }; + var reader = function (datatype) { + var field, f=[], j=0, i; + for(i =0; i= ts.p.keyIndex) ? $(f[ts.p.keyIndex],trow).text() : $(ts.p.xmlReader.cell+":eq("+ts.p.keyIndex+")",trow).text(); }; + } + $(ts.p.xmlReader.page,xml).each(function() {ts.p.page = this.textContent || this.text ; }); + $(ts.p.xmlReader.total,xml).each(function() {ts.p.lastpage = this.textContent || this.text ; } ); + $(ts.p.xmlReader.records,xml).each(function() {ts.p.records = this.textContent || this.text ; } ); + $(ts.p.xmlReader.userdata,xml).each(function() {ts.p.userData[this.getAttribute("name")]=this.textContent || this.text;}); + $(ts.p.xmlReader.root+" "+ts.p.xmlReader.row,xml).each( function( j ) { + row = document.createElement("tr"); + row.id = getId(this,j+1); + if(ts.p.multiselect) { + addMulti(t,row); + gi = 1; + } + if (ts.p.subGrid) { + try {$(ts).addSubGrid(t,row,gi,this);} catch (e){} + si= 1; + } + if(ts.p.xmlReader.repeatitems===true){ + $(ts.p.xmlReader.cell,this).each( function (i) { + v = this.textContent || this.text; + addCell(t,row,v,i+gi+si); + rd[ts.p.colModel[i+gi+si].name] = v; + }); + } else { + for(var i = 0; i < f.length;i++) { + v = $(f[i],this).text(); + addCell(t, row, v , i+gi+si); + rd[ts.p.colModel[i+gi+si].name] = v; + } + } + if(j%2 == 1) {row.className = cn;} $(row).addClass("jqgrow"); + if( ts.p.treeGrid === true) { + try {$(ts).setTreeNode(rd,row);} catch (e) {} + ts.p.treeANode = 0; + } + $(ts.rows[j+fpos+rcnt]).after(row); + if(afterInsRow) {ts.p.afterInsertRow(row.id,rd,this);} + rd=[]; + }); + if(isSafari || isOpera) {resizeFirstRow(t,1);} + if(!ts.p.treeGrid && !ts.p.scroll) {ts.grid.bDiv.scrollTop = 0;} + endReq(); + updatepager(); + }; + var addJSONData = function(data,t, rcnt) { + if(data) { var fpos = ts.p.treeANode || 0; rcnt = rcnt || 0; if(fpos===0 && rcnt===0) {$("tbody tr:gt(0)", t).remove();} } else { return; } + var v,i,j,row,f=[],cur,gi=0,si=0,drows,idn,rd=[],cn=(ts.p.altRows===true) ? 'alt':''; + ts.p.page = data[ts.p.jsonReader.page]; + ts.p.lastpage= data[ts.p.jsonReader.total]; + ts.p.records= data[ts.p.jsonReader.records]; + ts.p.userData = data[ts.p.jsonReader.userdata] || {}; + if(!ts.p.jsonReader.repeatitems) {f = reader("json");} + if( ts.p.keyIndex===false ) { + idn = ts.p.jsonReader.id; + if(f.length>0 && !isNaN(idn)) {idn=f[idn];} + } else { + idn = f.length>0 ? f[ts.p.keyIndex] : ts.p.keyIndex; + } + drows = data[ts.p.jsonReader.root]; + if (drows) { + for (i=0;i 0) { + try { sv = $.unformat($(row).children('td').eq(col),{colModel:ts.p.colModel[col]},col,true);} + catch (_) { sv = $(row).children('td').eq(col).text(); } + row.sortKey = findSortKey(sv); + rows[index-1] = this; + } + }); + if(ts.p.treeGrid) { + $(ts).SortTree( newDir); + } else { + rows.sort(function(a, b) { + if (a.sortKey < b.sortKey) {return -newDir;} + if (a.sortKey > b.sortKey) {return newDir;} + return 0; + }); + $.each(rows, function(index, row) { + $('tbody',ts.grid.bDiv).append(row); + row.sortKey = null; + }); + } + if(isSafari || isOpera) {resizeFirstRow(ts.grid.bDiv,1);} + if(ts.p.multiselect) { + $("tbody tr:gt(0)", ts.grid.bDiv).removeClass("selected"); + $("[id^=jqg_]",ts.rows).attr("checked",false); + $("#cb_jqg",ts.grid.hDiv).attr("checked",false); + ts.p.selarrrow = []; + } + if( ts.p.altRows === true ) { + $("tbody tr:gt(0)", ts.grid.bDiv).removeClass("alt"); + $("tbody tr:odd", ts.grid.bDiv).addClass("alt"); + } + ts.grid.bDiv.scrollTop = 0; + endReq(); + }; + var parseDate = function(format, date) { + var tsp = {m : 1, d : 1, y : 1970, h : 0, i : 0, s : 0}; + format = format.toLowerCase(); + date = date.split(/[\\\/:_;.\s-]/); + format = format.split(/[\\\/:_;.\s-]/); + for(var i=0;i= 70 && ty <= 99) {tsp.y = 1900+tsp.y;} + else if (ty >=0 && ty <=69) {tsp.y= 2000+tsp.y;} + return new Date(tsp.y, tsp.m, tsp.d, tsp.h, tsp.i, tsp.s,0); + }; + var setPager = function (){ + var inpt = "" : "", + pgl="", pgr="", str, + clearVals = function(){ + ts.p.selrow = null; + if(ts.p.multiselect) {ts.p.selarrrow =[];$('#cb_jqg',ts.grid.hDiv).attr("checked",false);} + ts.p.savedRow = []; + }; + if(ts.p.viewrecords===true) {pginp += " ";} + if(ts.p.pgbuttons===true) { + pgl = inpt+" id='first'/>  "+inpt+" id='prev'/> "; + pgr = inpt+" id='next' />  "+inpt+" id='last'/>"; + } + $(ts.p.pager).append(pgl+pginp+pgr); + if(ts.p.rowList.length >0){ + str=""; + $(ts.p.pager).append(" "+str+" "); + $(ts.p.pager).find("select").bind('change',function() { + ts.p.rowNum = this.value; + if (typeof ts.p.onPaging =='function') {ts.p.onPaging('records');} + clearVals(); + populate(); + }); + } else { $(ts.p.pager).append(" ");} + if(ts.p.pgbuttons===true) { + $(".pgbuttons",ts.p.pager).mouseover(function(e){ + if($(this).attr('disabled') == 'true') { this.style.cursor='auto';} + else {this.style.cursor= "pointer";} + return false; + }).mouseout(function(e) { + this.style.cursor= "default"; + return false; + }); + $("#first, #prev, #next, #last",ts.p.pager).click( function(e) { + var cp = IntNum(ts.p.page), + last = IntNum(ts.p.lastpage), selclick = false, + fp=true, pp=true, np=true,lp=true; + if(last ===0 || last===1) {fp=false;pp=false;np=false;lp=false; } + else if( last>1 && cp >=1) { + if( cp === 1) { fp=false; pp=false; } + else if( cp>1 && cp 1 && cp===0 ) { np=false;lp=false; cp=last-1;} + if( this.id === 'first' && fp ) { ts.p.page=1; selclick=true;} + if( this.id === 'prev' && pp) { ts.p.page=(cp-1); selclick=true;} + if( this.id === 'next' && np) { ts.p.page=(cp+1); selclick=true;} + if( this.id === 'last' && lp) { ts.p.page=last; selclick=true;} + if(selclick) { + if (typeof ts.p.onPaging =='function') {ts.p.onPaging(this.id);} + clearVals(); + populate(); + } + e.stopPropagation(); + return false; + }); + } + if(ts.p.pginput===true) { + $('input.selbox',ts.p.pager).keypress( function(e) { + var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0; + if(key == 13) { + ts.p.page = ($(this).val()>0) ? $(this).val():ts.p.page; + if (typeof ts.p.onPaging =='function') {ts.p.onPaging( 'user');} + clearVals(); + populate(); + return false; + } + return this; + }); + } + }; + var sortData = function (index, idxcol,reload){ + var imgs, so, scg, ls, iId; + if(ts.p.savedRow.length > 0) {return;} + if(!reload) { + if( ts.p.lastsort === idxcol ) { + if( ts.p.sortorder === 'asc') { + ts.p.sortorder = 'desc'; + } else if(ts.p.sortorder === 'desc') { ts.p.sortorder='asc';} + } else { ts.p.sortorder='asc';} + ts.p.page = 1; + } + imgs = (ts.p.sortorder==='asc') ? ts.p.sortascimg : ts.p.sortdescimg; + imgs = ""; + var thd= $("thead:first",grid.hDiv).get(0); + ls = ts.p.colModel[ts.p.lastsort].name.replace('.',"\\."); + $("tr th div#jqgh_"+ls+" img",thd).remove(); + $("tr th div#jqgh_"+ls,thd).parent().removeClass(ts.p.sortclass); + iId = index.replace('.',"\\."); + $("tr th div#"+iId,thd).append(imgs).parent().addClass(ts.p.sortclass); + ts.p.lastsort = idxcol; + index = index.substring(5); + ts.p.sortname = ts.p.colModel[idxcol].index || index; + so = ts.p.sortorder; + if(onSortCol) {onSortCol(index,idxcol,so);} + if(ts.p.datatype == "local") { + if(ts.p.deselectAfterSort) {$(ts).resetSelection();} + } else { + ts.p.selrow = null; + if(ts.p.multiselect){$("#cb_jqg",ts.grid.hDiv).attr("checked",false);} + ts.p.selarrrow =[]; + ts.p.savedRow =[]; + } + scg = ts.p.scroll; if(ts.p.scroll===true) {ts.p.scroll=false;} + if(ts.p.subGrid && ts.p.datatype=='local') { + $("td.sgexpanded","#"+ts.p.id).each(function(){ + $(this).trigger("click"); + }); + } + populate(); + if(ts.p.sortname != index && idxcol) {ts.p.lastsort = idxcol;} + setTimeout(function() {ts.p.scroll=scg;},500); + }; + var setColWidth = function () { + var initwidth = 0; + for(var l=0;l"); + this.p.colModel.unshift({name:'cb',width:27,sortable:false,resizable:false,hidedlg:true,search:false}); + } + var xReader = { + root: "rows", + row: "row", + page: "rows>page", + total: "rows>total", + records : "rows>records", + repeatitems: true, + cell: "cell", + id: "[id]", + userdata: "userdata", + subgrid: {root:"rows", row: "row", repeatitems: true, cell:"cell"} + }; + var jReader = { + root: "rows", + page: "page", + total: "total", + records: "records", + repeatitems: true, + cell: "cell", + id: "id", + userdata: "userdata", + subgrid: {root:"rows", repeatitems: true, cell:"cell"} + }; + if(ts.p.scroll===true){ + ts.p.pgbuttons = false; ts.p.pginput=false; ts.p.pgtext = false; ts.p.rowList=[]; + } + ts.p.xmlReader = $.extend(xReader, ts.p.xmlReader); + ts.p.jsonReader = $.extend(jReader, ts.p.jsonReader); + $.each(ts.p.colModel, function(i){this.width= IntNum(this.width,150);}); + if (ts.p.width) {setColWidth();} + var thead = document.createElement("thead"); + var trow = document.createElement("tr"); + thead.appendChild(trow); + var i=0, th, idn, thdiv; + if(ts.p.shrinkToFit===true && ts.p.forceFit===true) { + for (i=ts.p.colModel.length-1;i>=0;i--){ + if(!ts.p.colModel[i].hidden) { + ts.p.colModel[i].resizable=false; + break; + } + } + } + for(i=0;i"; + $(thdiv).append(imgs); + ts.p.lastsort = i; + $(th).addClass(ts.p.sortclass); + } + thdiv.id = "jqgh_"+idn; + th.appendChild(thdiv); + trow.appendChild(th); + } + if(this.p.multiselect) { + var onSA = true, chk, emp=[]; + if(typeof ts.p.onSelectAll !== 'function') {onSA=false;} + $('#cb_jqg',trow).bind('click',function(){ + if (this.checked) { + $("[id^=jqg_]",ts.rows).attr("checked",true); + $(ts.rows).slice(1).each(function(i) { + if(!$(this).hasClass("subgrid")){ + $(this).addClass("selected"); + ts.p.selarrrow[i]= ts.p.selrow = this.id; + } + }); + chk=true; + emp=[]; + } + else { + $("[id^=jqg_]",ts.rows).attr("checked",false); + $(ts.rows).slice(1).each(function(i) { + if(!$(this).hasClass("subgrid")){ + $(this).removeClass("selected"); + emp[i] = this.id; + } + }); + ts.p.selarrrow = []; ts.p.selrow = null; + chk=false; + } + if(onSA) {ts.p.onSelectAll(chk ? ts.p.selarrrow : emp,chk);} + }); + } + this.appendChild(thead); + thead = $("thead:first",ts).get(0); + var w, res, sort; + $("tr:first th",thead).each(function ( j ) { + w = ts.p.colModel[j].width; + if(typeof ts.p.colModel[j].resizable === 'undefined') {ts.p.colModel[j].resizable = true;} + res = document.createElement("span"); + $(res).html(" "); + if(ts.p.colModel[j].resizable){ + $(this).addClass(ts.p.resizeclass); + $(res).mousedown(function (e) { + if(ts.p.forceFit===true) {ts.p.nv= nextVisible(j);} + grid.dragStart(j, e.clientX); + e.preventDefault(); + return false; + }); + } else {res="";} + $(this).css("width",w+"px").prepend(res); + if( ts.p.colModel[j].hidden) {$(this).css("display","none");} + grid.headers[j] = { width: w, el: this }; + sort = ts.p.colModel[j].sortable; + if( typeof sort !== 'boolean') {sort = true;} + if(sort) { + $("div",this).css("cursor","pointer") + .click(function(){sortData(this.id,j);return false;}); + } + }); + var isMSIE = $.browser.msie ? true:false, + isMoz = $.browser.mozilla ? true:false, + isOpera = $.browser.opera ? true:false, + isSafari = $.browser.safari ? true : false, + td, ptr, gw=0,hdc=0, tbody = document.createElement("tbody"); + trow = document.createElement("tr"); + trow.id = "_empty"; + tbody.appendChild(trow); + for(i=0;i"+ts.p.loadtext+"
    ") + .addClass("grid_hdiv") + .append(grid.hTable) + .bind("selectstart", function () { return false; }); + if(hg) {$(grid.hDiv).hide(); ts.p.gridstate = 'hidden'} + if(ts.p.pager){ + if(typeof ts.p.pager == "string") {if(ts.p.pager.substr(0,1) !="#") ts.p.pager = "#"+ts.p.pager;} + if( $(ts.p.pager).hasClass("scroll")) { $(ts.p.pager).css({ width: grid.width+"px", overflow: "hidden"}).show(); ts.p._height= parseInt($(ts.p.pager).height(),10); if(hg) {$(ts.p.pager).hide();}} + setPager(); + } + if( ts.p.cellEdit === false) { + $(ts).mouseover(function(e) { + td = (e.target || e.srcElement); + ptr = $(td,ts.rows).parents("tr:first"); + if($(ptr).hasClass("jqgrow")) { + $(ptr).addClass("over"); + } + return false; + }).mouseout(function(e) { + td = (e.target || e.srcElement); + ptr = $(td,ts.rows).parents("tr:first"); + $(ptr).removeClass("over"); + return false; + }); + } + var ri,ci; + + $(ts).before(grid.hDiv).css("width", grid.width+"px").click(function(e) { + td = (e.target || e.srcElement); + if (td.href) { return true; } + var scb = $(td).hasClass("cbox"); + ptr = $(td,ts.rows).parents("tr.jqgrow"); + if($(ptr).length === 0 ) {return false;} + var cSel = true; + if(bSR) { cSel = bSR(ptr.attr("id"));} + if(cSel === true) { + if(ts.p.cellEdit === true) { + if(ts.p.multiselect && scb){ + $(ts).setSelection(false,true,ptr); + } else { + ri = ptr[0].rowIndex; + ci = !$(td).is('td') ? $(td).parents("td:first")[0].cellIndex : td.cellIndex; + try {$(ts).editCell(ri,ci,true,true);} catch (e) {} + } + } else if ( !ts.p.multikey ) { + if(ts.p.multiselect && ts.p.multiboxonly) { + if(scb){$(ts).setSelection(false,true,ptr);} + } else { + $(ts).setSelection(false,true,ptr); + } + } else { + if(e[ts.p.multikey]) { + $(ts).setSelection(false,true,ptr); + } else if(ts.p.multiselect && scb) { + scb = $("[id^=jqg_]",ptr).attr("checked"); + $("[id^=jqg_]",ptr).attr("checked",!scb); + } + } + if(onSC) { + ri = ptr[0].id; + ci = !$(td).is('td') ? $(td).parents("td:first")[0].cellIndex : td.cellIndex; + onSC(ri,ci,$(td).html(),td); + } + } + e.stopPropagation(); + }).bind('reloadGrid', function(e) { + if(ts.p.treeGrid ===true) { ts.p.datatype = ts.p.treedatatype;} + if(ts.p.datatype=="local"){ $(ts).resetSelection();} + else if(!ts.p.treeGrid){ + ts.p.selrow=null; + if(ts.p.multiselect) {ts.p.selarrrow =[];$('#cb_jqg',ts.grid.hDiv).attr("checked",false);} + if(ts.p.cellEdit) {ts.p.savedRow = []; } + } + populate(); + }); + if( ondblClickRow ) { + $(this).dblclick(function(e) { + td = (e.target || e.srcElement); + ptr = $(td,ts.rows).parents("tr.jqgrow"); + if($(ptr).length === 0 ){return false;} + ts.p.ondblClickRow($(ptr).attr("id")); + return false; + }); + } + if (onRightClickRow) { + $(this).bind('contextmenu', function(e) { + td = (e.target || e.srcElement); + ptr = $(td,ts.rows).parents("tr.jqgrow"); + if($(ptr).length === 0 ){return false;} + if(!ts.p.multiselect) { $(ts).setSelection(false,true,ptr); } + ri = ptr[0].id; + ci = !$(td).is('td') ? $(td).parents("td:first")[0].cellIndex : td.cellIndex; + ts.p.onRightClickRow($(ptr).attr("id"),ri,ci); + return false; + }); + } + grid.bDiv = document.createElement("div"); + var ofl2 = (isNaN(ts.p.height) && isMoz && (ts.p.height.indexOf("%")!=-1 || ts.p.height=="auto")) ? "hidden" : "auto"; + $(grid.bDiv) + .addClass("grid_bdiv") + .scroll(function (e) {grid.scrollGrid();}) + .css({ height: ts.p.height+(isNaN(ts.p.height)?"":"px"), padding: "0px", margin: "0px", overflow: ofl2,width: (grid.width)+"px"} ).css("overflow-x","hidden") + .append(this); + $("table:first",grid.bDiv).css({width:grid.width+"px"}); + if( isMSIE ) { + if( $("tbody",this).size() === 2 ) { $("tbody:first",this).remove();} + if( ts.p.multikey) {$(grid.bDiv).bind("selectstart",function(){return false;});} + if(ts.p.treeGrid) {$(grid.bDiv).css("position","relative");} + } else { + if( ts.p.multikey) {$(grid.bDiv).bind("mousedown",function(){return false;});} + } + if(hg) {$(grid.bDiv).hide();} + grid.cDiv = document.createElement("div"); + $(grid.cDiv).append(""+ ((ts.p.hidegrid===true) ? "" :"") +"
    "+ts.p.caption+"
    ") + .addClass("GridHeader").width(grid.width); + $(grid.cDiv).insertBefore(grid.hDiv); + if( ts.p.toolbar[0] ) { + grid.uDiv = document.createElement("div"); + if(ts.p.toolbar[1] == "top") {$(grid.uDiv).insertBefore(grid.hDiv);} + else {$(grid.uDiv).insertAfter(grid.hDiv);} + $(grid.uDiv).width(grid.width).addClass("userdata").attr("id","t_"+this.id); + ts.p._height += parseInt($(grid.uDiv).height(),10); + if(hg) {$(grid.uDiv).hide();} + } + if(ts.p.caption) { + ts.p._height += parseInt($(grid.cDiv,ts).height(),10); + var tdt = ts.p.datatype; + if(ts.p.hidegrid===true) { + $(".HeaderButton",grid.cDiv).toggle( function(){ + if(ts.p.pager) {$(ts.p.pager).slideUp();} + if(ts.p.toolbar[0]) {$(grid.uDiv,ts).slideUp();} + $(grid.bDiv).hide(); + $(grid.hDiv).slideUp(); + $("img",this).attr("src",ts.p.imgpath+"down.gif"); + ts.p.gridstate = 'hidden'; + if(onHdCl) {if(!hg) {ts.p.onHeaderClick(ts.p.gridstate);}} + }, + function() { + $(grid.hDiv).slideDown(); + $(grid.bDiv).show(); + if(ts.p.pager) {$(ts.p.pager).slideDown();} + if(ts.p.toolbar[0]) {$(grid.uDiv).slideDown();} + $("img",this).attr("src",ts.p.imgpath+"up.gif"); + if(hg) {ts.p.datatype = tdt;populate();hg=false;} + ts.p.gridstate = 'visible'; + if(onHdCl) {ts.p.onHeaderClick(ts.p.gridstate)} + } + ); + if(hg) { $(".HeaderButton",grid.cDiv).trigger("click"); ts.p.datatype="local";} + } + } else {$(grid.cDiv).hide();} + ts.p._height += parseInt($(grid.hDiv,ts).height(),10); + $(grid.hDiv).mousemove(function (e) {grid.dragMove(e.clientX); return false;}).after(grid.bDiv); + $(document).mouseup(function (e) { + if(grid.resizing) { + grid.dragEnd(); + if(grid.newWidth && ts.p.forceFit===false){ + var gwdt = (grid.width <= ts.p._width) ? grid.width: ts.p._width; + var overfl = (grid.width <= ts.p._width) ? "hidden" : "auto"; + if(ts.p.pager && $(ts.p.pager).hasClass("scroll") ) { + $(ts.p.pager).width(gwdt); + } + if(ts.p.caption) {$(grid.cDiv).width(gwdt);} + if(ts.p.toolbar[0]) {$(grid.uDiv).width(gwdt);} + $(grid.bDiv).width(gwdt).css("overflow-x",overfl); + $(grid.hDiv).width(gwdt); + } + return false; + } + return true; + }); + ts.formatCol = function(a,b) {formatCol(a,b);}; + ts.sortData = function(a,b,c){sortData(a,b,c);}; + ts.updatepager = function(){updatepager();}; + ts.formatter = function (elem, row, cellval , colpos, act){formatter(elem, row, cellval , colpos,act);}; + $.extend(grid,{populate : function(){populate();}}); + this.grid = grid; + ts.addXmlData = function(d) {addXmlData(d,ts.grid.bDiv);}; + ts.addJSONData = function(d) {addJSONData(d,ts.grid.bDiv);}; + populate(); + if (!ts.p.shrinkToFit) { + ts.p.forceFit = false; + $("tr:first th", thead).each(function(j){ + var w = ts.p.colModel[j].owidth; + var diff = w - ts.p.colModel[j].width; + if (diff > 0 && !ts.p.colModel[j].hidden) { + grid.headers[j].width = w; + $(this).add(grid.cols[j]).width(w); + $('table:first',grid.bDiv).add(grid.hTable).width(ts.grid.width); + ts.grid.width += diff; + grid.hDiv.scrollLeft = grid.bDiv.scrollLeft; + } + }); + ofl2 = (grid.width <= ts.p._width) ? "hidden" : "auto"; + $(grid.bDiv).css({"overflow-x":ofl2}); + } + $(window).unload(function () { + $(this).unbind("*"); + this.grid = null; + this.p = null; + }); + }); +}; +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.celledit.js b/site/vendors/js/jqGrid/js/grid.celledit.js new file mode 100644 index 0000000..bed010a --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.celledit.js @@ -0,0 +1,445 @@ +;(function($){ +/* +** + * jqGrid extension for cellediting Grid Data + * Tony Tomov tony@trirand.com + * http://trirand.com/blog/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +/** + * all events and options here are aded anonynous and not in the base grid + * since the array is to big. Here is the order of execution. + * From this point we use jQuery isFunction + * formatCell + * beforeEditCell, + * onSelectCell (used only for noneditable cels) + * afterEditCell, + * beforeSaveCell, (called before validation of values if any) + * beforeSubmitCell (if cellsubmit remote (ajax)) + * afterSubmitCell(if cellsubmit remote (ajax)), + * afterSaveCell, + * errorCell, + * Options + * cellsubmit (remote,clientArray) (added in grid options) + * cellurl +* */ +$.fn.extend({ + editCell : function (iRow,iCol, ed, fg){ + return this.each(function (){ + var $t = this, nm, tmp,cc; + if (!$t.grid || $t.p.cellEdit !== true) {return;} + var currentFocus = null; + // I HATE IE + if ($.browser.msie && $.browser.version <=7 && ed===true && fg===true) { + iCol = getAbsoluteIndex($t.rows[iRow],iCol); + } + iCol = parseInt(iCol,10); + // select the row that can be used for other methods + $t.p.selrow = $t.rows[iRow].id; + if (!$t.p.knv) {$($t).GridNav();} + // check to see if we have already edited cell + if ($t.p.savedRow.length>0) { + // prevent second click on that field and enable selects + if (ed===true ) { + if(iRow == $t.p.iRow && iCol == $t.p.iCol){ + return; + } + } + // if so check to see if the content is changed + var vl = $("td:eq("+$t.p.savedRow[0].ic+")>#"+$t.p.savedRow[0].id+"_"+$t.p.savedRow[0].name.replace('.',"\\."),$t.rows[$t.p.savedRow[0].id]).val(); + if ($t.p.savedRow[0].v != vl) { + // save it + $($t).saveCell($t.p.savedRow[0].id,$t.p.savedRow[0].ic) + } else { + // restore it + $($t).restoreCell($t.p.savedRow[0].id,$t.p.savedRow[0].ic); + } + } else { + window.setTimeout(function () { $("#"+$t.p.knv).attr("tabindex","-1").focus();},0); + } + nm = $t.p.colModel[iCol].name; + if (nm=='subgrid') {return;} + if ($t.p.colModel[iCol].editable===true && ed===true) { + cc = $("td:eq("+iCol+")",$t.rows[iRow]); + if(parseInt($t.p.iCol)>=0 && parseInt($t.p.iRow)>=0) { + $("td:eq("+$t.p.iCol+")",$t.rows[$t.p.iRow]).removeClass("edit-cell"); + $($t.rows[$t.p.iRow]).removeClass("selected-row"); + } + $(cc).addClass("edit-cell"); + $($t.rows[iRow]).addClass("selected-row"); + try { + tmp = $.unformat(cc,{colModel:$t.p.colModel[iCol]},iCol); + } catch (_) { + tmp = $(cc).html(); + } + var opt = $.extend($t.p.colModel[iCol].editoptions || {} ,{id:iRow+"_"+nm,name:nm}); + if (!$t.p.colModel[iCol].edittype) {$t.p.colModel[iCol].edittype = "text";} + $t.p.savedRow[0] = {id:iRow,ic:iCol,name:nm,v:tmp}; + if($.isFunction($t.p.formatCell)) { + var tmp2 = $t.p.formatCell($t.rows[iRow].id,nm,tmp,iRow,iCol); + if(tmp2) {tmp = tmp2;} + } + var elc = createEl($t.p.colModel[iCol].edittype,opt,tmp,cc); + if ($.isFunction($t.p.beforeEditCell)) { + $t.p.beforeEditCell($t.rows[iRow].id,nm,tmp,iRow,iCol); + } + $(cc).html("").append(elc); + window.setTimeout(function () { $(elc).focus();},0); + $("input, select, textarea",cc).bind("keydown",function(e) { + if (e.keyCode === 27) {$($t).restoreCell(iRow,iCol);} //ESC + if (e.keyCode === 13) {$($t).saveCell(iRow,iCol);}//Enter + if (e.keyCode == 9) { + if (e.shiftKey) {$($t).prevCell(iRow,iCol);} //Shift TAb + else {$($t).nextCell(iRow,iCol);} //Tab + } + e.stopPropagation(); + }); + if ($.isFunction($t.p.afterEditCell)) { + $t.p.afterEditCell($t.rows[iRow].id,nm,tmp,iRow,iCol); + } + } else { + if (parseInt($t.p.iCol)>=0 && parseInt($t.p.iRow)>=0) { + $("td:eq("+$t.p.iCol+")",$t.rows[$t.p.iRow]).removeClass("edit-cell"); + $($t.rows[$t.p.iRow]).removeClass("selected-row"); + } + $("td:eq("+iCol+")",$t.rows[iRow]).addClass("edit-cell"); + $($t.rows[iRow]).addClass("selected-row"); + if ($.isFunction($t.p.onSelectCell)) { + tmp = $("td:eq("+iCol+")",$t.rows[iRow]).html().replace(/\ \;/ig,''); + $t.p.onSelectCell($t.rows[iRow].id,nm,tmp,iRow,iCol); + } + } + $t.p.iCol = iCol; $t.p.iRow = iRow; + // IE 6 bug + function getAbsoluteIndex(t,relIndex) + { + var countnotvisible=0; + var countvisible=0; + for (i=0;irelIndex) return i; + } + return i; + } + }); + }, + saveCell : function (iRow, iCol){ + return this.each(function(){ + var $t= this, nm, fr; + if (!$t.grid || $t.p.cellEdit !== true) {return;} + if ( $t.p.savedRow.length == 1) {fr = 0;} else {fr=null;} + if(fr != null) { + var cc = $("td:eq("+iCol+")",$t.rows[iRow]),v,v2; + nm = $t.p.colModel[iCol].name; + switch ($t.p.colModel[iCol].edittype) { + case "select": + v = $("#"+iRow+"_"+nm.replace('.',"\\.")+">option:selected",$t.rows[iRow]).val(); + v2 = $("#"+iRow+"_"+nm.replace('.',"\\.")+">option:selected",$t.rows[iRow]).text(); + break; + case "checkbox": + var cbv = ["Yes","No"]; + if($t.p.colModel[iCol].editoptions){ + cbv = $t.p.colModel[iCol].editoptions.value.split(":"); + } + v = $("#"+iRow+"_"+nm.replace('.',"\\."),$t.rows[iRow]).attr("checked") ? cbv[0] : cbv[1]; + v2=v; + break; + case "password": + case "text": + case "textarea": + v = !$t.p.autoencode ? $("#"+iRow+"_"+nm.replace('.',"\\."),$t.rows[iRow]).val() : htmlEncode($("#"+iRow+"_"+nm.replace('.',"\\."),$t.rows[iRow]).val()); + v2=v; + break; + } + // The common approach is if nothing changed do not do anything + if (v2 != $t.p.savedRow[fr].v){ + if ($.isFunction($t.p.beforeSaveCell)) { + var vv = $t.p.beforeSaveCell($t.rows[iRow].id,nm, v, iRow,iCol); + if (vv) {v = vv;} + } + var cv = checkValues(v,iCol,$t); + if(cv[0] === true) { + var addpost = {}; + if ($.isFunction($t.p.beforeSubmitCell)) { + addpost = $t.p.beforeSubmitCell($t.rows[iRow].id,nm, v, iRow,iCol); + if (!addpost) {addpost={};} + } + if ($t.p.cellsubmit == 'remote') { + if ($t.p.cellurl) { + var postdata = {}; + postdata[nm] = v; + postdata["id"] = $t.rows[iRow].id; + postdata = $.extend(addpost,postdata); + $.ajax({ + url: $t.p.cellurl, + data :postdata, + type: "POST", + complete: function (result, stat) { + if (stat == 'success') { + if ($.isFunction($t.p.afterSubmitCell)) { + var ret = $t.p.afterSubmitCell(result,postdata.id,nm,v,iRow,iCol); + if(ret[0] === true) { + $(cc).empty(); + $($t).setCell($t.rows[iRow].id, iCol, v2); + $(cc).addClass("dirty-cell"); + $($t.rows[iRow]).addClass("edited"); + if ($.isFunction($t.p.afterSaveCell)) { + $t.p.afterSaveCell($t.rows[iRow].id,nm, v, iRow,iCol); + } + $t.p.savedRow = []; + } else { + info_dialog($.jgrid.errors.errcap,ret[1],$.jgrid.edit.bClose, $t.p.imgpath); + $($t).restoreCell(iRow,iCol); + } + } else { + $(cc).empty(); + $($t).setCell($t.rows[iRow].id, iCol, v2); + $(cc).addClass("dirty-cell"); + $($t.rows[iRow]).addClass("edited"); + if ($.isFunction($t.p.afterSaveCell)) { + $t.p.afterSaveCell($t.rows[iRow].id,nm, v, iRow,iCol); + } + $t.p.savedRow = []; + } + } + }, + error:function(res,stat){ + if ($.isFunction($t.p.errorCell)) { + $t.p.errorCell(res,stat); + $($t).restoreCell(iRow,iCol); + } else { + info_dialog($.jgrid.errors.errcap,res.status+" : "+res.statusText+"
    "+stat,$.jgrid.edit.bClose, $t.p.imgpath); + $($t).restoreCell(iRow,iCol); + } + } + }); + } else { + try { + info_dialog($.jgrid.errors.errcap,$.jgrid.errors.nourl,$.jgrid.edit.bClose, $t.p.imgpath); + $($t).restoreCell(iRow,iCol); + } catch (e) {} + } + } + if ($t.p.cellsubmit == 'clientArray') { + $(cc).empty(); + $($t).setCell($t.rows[iRow].id,iCol, v2); + $(cc).addClass("dirty-cell"); + $($t.rows[iRow]).addClass("edited"); + if ($.isFunction($t.p.afterSaveCell)) { + $t.p.afterSaveCell($t.rows[iRow].id,nm, v, iRow,iCol); + } + $t.p.savedRow = []; + } + } else { + try { + window.setTimeout(function(){info_dialog($.jgrid.errors.errcap,v+" "+cv[1],$.jgrid.edit.bClose, $t.p.imgpath)},100); + $($t).restoreCell(iRow,iCol); + } catch (e) {} + } + } else { + $($t).restoreCell(iRow,iCol); + } + } + if ($.browser.opera) { + $("#"+$t.p.knv).attr("tabindex","-1").focus(); + } else { + window.setTimeout(function () { $("#"+$t.p.knv).attr("tabindex","-1").focus();},0); + } + }); + }, + restoreCell : function(iRow, iCol) { + return this.each(function(){ + var $t= this, nm, fr; + if (!$t.grid || $t.p.cellEdit !== true ) {return;} + if ( $t.p.savedRow.length == 1) {fr = 0;} else {fr=null;} + if(fr != null) { + var cc = $("td:eq("+iCol+")",$t.rows[iRow]); + if($.isFunction($.fn['datepicker'])) { + try { + $.datepicker('hide'); + } catch (e) { + try { + $.datepicker.hideDatepicker(); + } catch (e) {} + } + } + $(cc).empty(); + $($t).setCell($t.rows[iRow].id, iCol, $t.p.savedRow[fr].v); + $t.p.savedRow = []; + + } + window.setTimeout(function () { $("#"+$t.p.knv).attr("tabindex","-1").focus();},0); + }); + }, + nextCell : function (iRow,iCol) { + return this.each(function (){ + var $t = this, nCol=false, tmp; + if (!$t.grid || $t.p.cellEdit !== true) {return;} + // try to find next editable cell + for (var i=iCol+1; i<$t.p.colModel.length; i++) { + if ( $t.p.colModel[i].editable ===true) { + nCol = i; break; + } + } + if(nCol !== false) { + $($t).saveCell(iRow,iCol); + $($t).editCell(iRow,nCol,true); + } else { + if ($t.p.savedRow.length >0) { + $($t).saveCell(iRow,iCol); + } + } + }); + }, + prevCell : function (iRow,iCol) { + return this.each(function (){ + var $t = this, nCol=false, tmp; + if (!$t.grid || $t.p.cellEdit !== true) {return;} + // try to find next editable cell + for (var i=iCol-1; i>=0; i--) { + if ( $t.p.colModel[i].editable ===true) { + nCol = i; break; + } + } + if(nCol !== false) { + $($t).saveCell(iRow,iCol); + $($t).editCell(iRow,nCol,true); + } else { + if ($t.p.savedRow.length >0) { + $($t).saveCell(iRow,iCol); + } + } + }); + }, + GridNav : function() { + return this.each(function () { + var $t = this; + if (!$t.grid || $t.p.cellEdit !== true ) {return;} + // trick to process keydown on non input elements + $t.p.knv = $("table:first",$t.grid.bDiv).attr("id") + "_kn"; + var selection = $(""); + $(selection).insertBefore($t.grid.cDiv); + $("#"+$t.p.knv).focus(); + $("#"+$t.p.knv).keydown(function (e){ + switch (e.keyCode) { + case 38: + if ($t.p.iRow-1 >=1 ) { + scrollGrid($t.p.iRow-1,$t.p.iCol,'vu'); + $($t).editCell($t.p.iRow-1,$t.p.iCol,false); + } + break; + case 40 : + if ($t.p.iRow+1 <= $t.rows.length-1) { + scrollGrid($t.p.iRow+1,$t.p.iCol,'vd'); + $($t).editCell($t.p.iRow+1,$t.p.iCol,false); + } + break; + case 37 : + if ($t.p.iCol -1 >= 0) { + var i = findNextVisible($t.p.iCol-1,'lft'); + scrollGrid($t.p.iRow, i,'h'); + $($t).editCell($t.p.iRow, i,false); + } + break; + case 39 : + if ($t.p.iCol +1 <= $t.p.colModel.length-1) { + var i = findNextVisible($t.p.iCol+1,'rgt'); + scrollGrid($t.p.iRow,i,'h'); + $($t).editCell($t.p.iRow,i,false); + } + break; + case 13: + if (parseInt($t.p.iCol,10)>=0 && parseInt($t.p.iRow,10)>=0) { + $($t).editCell($t.p.iRow,$t.p.iCol,true); + } + break; + } + return false; + }); + function scrollGrid(iR, iC, tp){ + if (tp.substr(0,1)=='v') { + var ch = $($t.grid.bDiv)[0].clientHeight, + st = $($t.grid.bDiv)[0].scrollTop, + nROT = $t.rows[iR].offsetTop+$t.rows[iR].clientHeight, + pROT = $t.rows[iR].offsetTop; + if(tp == 'vd') { + if(nROT >= ch) { + $($t.grid.bDiv)[0].scrollTop = $($t.grid.bDiv)[0].scrollTop + $t.rows[iR].clientHeight; + } + } + if(tp == 'vu'){ + if (pROT < st) { + $($t.grid.bDiv)[0].scrollTop = $($t.grid.bDiv)[0].scrollTop - $t.rows[iR].clientHeight; + } + } + } + if(tp=='h') { + var cw = $($t.grid.bDiv)[0].clientWidth, + sl = $($t.grid.bDiv)[0].scrollLeft, + nCOL = $t.rows[iR].cells[iC].offsetLeft+$t.rows[iR].cells[iC].clientWidth, + pCOL = $t.rows[iR].cells[iC].offsetLeft; + if(nCOL >= cw+parseInt(sl)) { + $($t.grid.bDiv)[0].scrollLeft = $($t.grid.bDiv)[0].scrollLeft + $t.rows[iR].cells[iC].clientWidth; + } else if (pCOL < sl) { + $($t.grid.bDiv)[0].scrollLeft = $($t.grid.bDiv)[0].scrollLeft - $t.rows[iR].cells[iC].clientWidth; + } + } + }; + function findNextVisible(iC,act){ + var ind, i; + if(act == 'lft') { + ind = iC+1; + for (i=iC;i>=0;i--){ + if ($t.p.colModel[i].hidden !== true) { + ind = i; + break; + } + } + } + if(act == 'rgt') { + ind = iC-1; + for (i=iC; i<$t.p.colModel.length;i++){ + if ($t.p.colModel[i].hidden !== true) { + ind = i; + break; + } + } + } + return ind; + }; + }); + }, + getChangedCells : function (mthd) { + var ret=[]; + if (!mthd) {mthd='all';} + this.each(function(){ + var $t= this; + if (!$t.grid || $t.p.cellEdit !== true ) {return;} + $($t.rows).slice(1).each(function(j){ + var res = {}; + if ($(this).hasClass("edited")) { + $('td',this).each( function(i) { + nm = $t.p.colModel[i].name; + if ( nm !== 'cb' && nm !== 'subgrid') { + if (mthd=='dirty') { + if ($(this).hasClass('dirty-cell')) { + res[nm] = $.htmlDecode($(this).html()); + } + } else { + res[nm] = $.htmlDecode($(this).html()); + } + } + }); + res["id"] = this.id; + ret.push(res); + } + }) + }); + return ret; + } +/// end cell editing +}); +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.common.js b/site/vendors/js/jqGrid/js/grid.common.js new file mode 100644 index 0000000..0d62df9 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.common.js @@ -0,0 +1,356 @@ +/** + * jqGrid common function + * Tony Tomov tony@trirand.com + * http://trirand.com/blog/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +// Modal functions +var showModal = function(h) { + h.w.show(); +}; +var closeModal = function(h) { + h.w.hide(); + if(h.o) { h.o.remove(); } +}; +function createModal(aIDs, content, p, insertSelector, posSelector, appendsel) { + var clicon = p.imgpath ? p.imgpath+p.closeicon : p.closeicon; + var mw = document.createElement('div'); + jQuery(mw).addClass("modalwin").attr("id",aIDs.themodal); + var mh = jQuery('').addClass("modalhead"); + var mc = document.createElement('div'); + jQuery(mc).addClass("modalcontent").attr("id",aIDs.modalcontent).css("width","97%"); + jQuery(mc).append(content); + mw.appendChild(mc); + var loading = document.createElement("div"); + jQuery(loading).addClass("loading").html(p.processData||""); + jQuery(mw).prepend(loading); + jQuery(mw).prepend(mh); + jQuery(mw).addClass("jqmWindow"); + if (p.drag) { + jQuery(mw).append(""); + } + if(appendsel===true) { jQuery('body').append(mw); } //append as first child in body -for alert dialog + else { jQuery(mw).insertBefore(insertSelector); } + if(p.left ==0 && p.top==0) { + var pos = []; + pos = findPos(posSelector) ; + p.left = pos[0] + 4; + p.top = pos[1] + 4; + } + if (p.width == 0 || !p.width) {p.width = 300;} + if(p.height==0 || !p.width) {p.height =200;} + if(!p.zIndex) {p.zIndex = 950;} + jQuery(mw).css({top: p.top+"px",left: p.left+"px",width: p.width+"px",height: p.height+"px", zIndex:p.zIndex}) + .attr({tabIndex: "-1"}); + if(p.closeOnEscape && p.closeOnEscape === true){ + jQuery(mw).keydown( function( e ) { + if( e.which == 27 ) { // escape, close box + hideModal(this); + } + }); + } + return false; +}; + +function viewModal(selector,o){ + o = jQuery.extend({ + toTop: true, + overlay: 10, + modal: false, + onShow: showModal, + onHide: closeModal + }, o || {}); + jQuery(selector).jqm(o).jqmShow(); + return false; +}; +function hideModal(selector) { + jQuery(selector).jqmHide(); +} + +function DnRModal(modwin,handler){ + jQuery(handler).css('cursor','move'); + jQuery(modwin).jqDrag(handler).jqResize(".jqResize"); + return false; +}; + +function info_dialog(caption, content,c_b, pathimg) { + var cnt = "
    "; + cnt += "

    "+content+"

    "; + cnt += ""; + cnt += "
    "; + createModal({ + themodal:'info_dialog', + modalhead:'info_head', + modalcontent:'info_content'}, + cnt, + { width:290, + height:120,drag: false, + caption:""+caption+"", + imgpath: pathimg, + closeicon: 'ico-close.gif', + left:250, + top:170, + closeOnEscape : true + }, + '','',true + ); + viewModal("#info_dialog",{ + onShow: function(h) { + h.w.show(); + }, + onHide: function(h) { + h.w.hide().remove(); + if(h.o) { h.o.remove(); } + }, + modal :true + }); +}; +//Helper functions +function findPos(obj) { + var curleft = curtop = 0; + if (obj.offsetParent) { + do { + curleft += obj.offsetLeft; + curtop += obj.offsetTop; + } while (obj = obj.offsetParent); + //do not change obj == obj.offsetParent + } + return [curleft,curtop]; +}; +function isArray(obj) { + if (obj.constructor.toString().indexOf("Array") == -1) { + return false; + } else { + return true; + } +}; +// Form Functions +function createEl(eltype,options,vl) { + var elem = ""; + switch (eltype) + { + case "textarea" : + elem = document.createElement("textarea"); + if(!options.cols) {jQuery(elem).css("width","98%");} + jQuery(elem).attr(options); + if(vl==' ' || vl==' ' || (vl.length==1 && vl.charCodeAt(0)==160)) {vl="";} + jQuery(elem).val(vl); + break; + case "checkbox" : //what code for simple checkbox + elem = document.createElement("input"); + elem.type = "checkbox"; + jQuery(elem).attr({id:options.id,name:options.name}); + if( !options.value) { + vl=vl.toLowerCase(); + if(vl.search(/(false|0|no|off|undefined)/i)<0 && vl!=="") { + elem.checked=true; + elem.defaultChecked=true; + elem.value = vl; + } else { + elem.value = "on"; + } + jQuery(elem).attr("offval","off"); + } else { + var cbval = options.value.split(":"); + if(vl == cbval[0]) { + elem.checked=true; + elem.defaultChecked=true; + } + elem.value = cbval[0]; + jQuery(elem).attr("offval",cbval[1]); + } + break; + case "select" : + vl = jQuery.htmlDecode(vl); + elem = document.createElement("select"); + var msl = options.multiple==true ? true : false; + if(options.value) { + var ovm = []; + if(msl) {jQuery(elem).attr({multiple:"multiple"}); ovm = vl.split(","); ovm = jQuery.map(ovm,function(n){return jQuery.trim(n)});} + if(typeof options.size === 'undefined') {options.size =1;} + if(typeof options.value == 'string') { + var so = options.value.split(";"),sv, ov; + jQuery(elem).attr({id:options.id,name:options.name,size:Math.min(options.size,so.length)}); + for(var i=0; i-1) {ov.selected ="selected";} + elem.appendChild(ov); + } + } else if (typeof options.value == 'object') { + var oSv = options.value; + var i=0; + for ( var key in oSv) { + i++; + ov = document.createElement("option"); + ov.value = key; ov.innerHTML = oSv[key]; + if (!msl && oSv[key]==vl) {ov.selected ="selected";} + if (msl && jQuery.inArray(jQuery.trim(oSv[key]),ovm)>-1) {ov.selected ="selected";} + elem.appendChild(ov); + } + jQuery(elem).attr({id:options.id,name:options.name,size:Math.min(options.size,i) }); + } + } + break; + case "text" : + elem = document.createElement("input"); + elem.type = "text"; + vl = jQuery.htmlDecode(vl); + elem.value = vl; + if(!options.size) { + jQuery(elem).css({width:"98%"}); + } + jQuery(elem).attr(options); + break; + case "password" : + elem = document.createElement("input"); + elem.type = "password"; + vl = jQuery.htmlDecode(vl); + elem.value = vl; + if(!options.size) { jQuery(elem).css("width","98%"); } + jQuery(elem).attr(options); + break; + case "image" : + elem = document.createElement("input"); + elem.type = "image"; + jQuery(elem).attr(options); + break; + } + return elem; +}; +function checkValues(val, valref,g) { + if(valref >=0) { + var edtrul = g.p.colModel[valref].editrules; + } + if(edtrul) { + if(edtrul.required === true) { + if( val.match(/^s+$/) || val == "" ) return [false,g.p.colNames[valref]+": "+jQuery.jgrid.edit.msg.required,""]; + } + // force required + var rqfield = edtrul.required === false ? false : true; + if(edtrul.number === true) { + if( !(rqfield === false && isEmpty(val)) ) { + if(isNaN(val)) return [false,g.p.colNames[valref]+": "+jQuery.jgrid.edit.msg.number,""]; + } + } + if(edtrul.minValue && !isNaN(edtrul.minValue)) { + if (parseFloat(val) < parseFloat(edtrul.minValue) ) return [false,g.p.colNames[valref]+": "+jQuery.jgrid.edit.msg.minValue+" "+edtrul.minValue,""]; + } + if(edtrul.maxValue && !isNaN(edtrul.maxValue)) { + if (parseFloat(val) > parseFloat(edtrul.maxValue) ) return [false,g.p.colNames[valref]+": "+jQuery.jgrid.edit.msg.maxValue+" "+edtrul.maxValue,""]; + } + if(edtrul.email === true) { + if( !(rqfield === false && isEmpty(val)) ) { + // taken from jquery Validate plugin + var filter = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i; + if(!filter.test(val)) {return [false,g.p.colNames[valref]+": "+jQuery.jgrid.edit.msg.email,""];} + } + } + if(edtrul.integer === true) { + if( !(rqfield === false && isEmpty(val)) ) { + if(isNaN(val)) return [false,g.p.colNames[valref]+": "+jQuery.jgrid.edit.msg.integer,""]; + if ((val % 1 != 0) || (val.indexOf('.') != -1)) return [false,g.p.colNames[valref]+": "+jQuery.jgrid.edit.msg.integer,""]; + } + } + if(edtrul.date === true) { + if( !(rqfield === false && isEmpty(val)) ) { + var dft = g.p.colModel[valref].datefmt || "Y-m-d"; + if(!checkDate (dft, val)) return [false,g.p.colNames[valref]+": "+jQuery.jgrid.edit.msg.date+" - "+dft,""]; + } + } + } + return [true,"",""]; +}; +// Date Validation Javascript +function checkDate (format, date) { + var tsp = {}; + var result = false; + var sep; + format = format.toLowerCase(); + //we search for /,-,. for the date separator + if(format.indexOf("/") != -1) { + sep = "/"; + } else if(format.indexOf("-") != -1) { + sep = "-"; + } else if(format.indexOf(".") != -1) { + sep = "."; + } else { + sep = "/"; + } + format = format.split(sep); + date = date.split(sep); + if (date.length != 3) return false; + var j=-1,yln, dln=-1, mln=-1; + for(var i=0;i12){ + return false; + } + } + if(dln === -1) { + return false; + } else { + strDate = tsp[format[dln]].toString(); + if (strDate.length<1 || tsp[format[dln]]<1 || tsp[format[dln]]>31 || (tsp[format[mln]]==2 && tsp[format[dln]]>daysInFebruary(tsp[format[j]])) || tsp[format[dln]] > daysInMonth[tsp[format[mln]]]){ + return false; + } + } + return true; +} +function daysInFebruary (year){ + // February has 29 days in any year evenly divisible by four, + // EXCEPT for centurial years which are not also divisible by 400. + return (((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28 ); +} +function DaysArray(n) { + for (var i = 1; i <= n; i++) { + this[i] = 31; + if (i==4 || i==6 || i==9 || i==11) {this[i] = 30;} + if (i==2) {this[i] = 29;} + } + return this; +} + +function isEmpty(val) +{ + if (val.match(/^s+$/) || val == "") { + return true; + } else { + return false; + } +} +function htmlEncode (value){ + return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/0 ? true : false; + gr.p.postData = $.extend(gr.p.postData,sdata); + var saveurl; + if(self.p.url) { + saveurl = $(gr).getGridParam('url'); + $(gr).setGridParam({url:self.p.url}); + } + $(gr).setGridParam({search:sd,page:1}).trigger("reloadGrid"); + if(saveurl) {$(gr).setGridParam({url:saveurl});} + if($.isFunction(self.p.afterSearch)){self.p.afterSearch();} + }; + var clearSearch = function(){ + var sdata={}, v, j=0; + var gr = $(self.p.gridid)[0]; + if($.isFunction(self.p.beforeClear)){self.p.beforeClear();} + $.each(self.p.filterModel,function(i,n){ + v = (this.defval) ? this.defval : ""; + if(!this.stype){this.stype=='text';} + switch (this.stype) { + case 'select' : + if(v) { + var v1; + $("select[name="+this.name+"] option",self).each(function (){ + if ($(this).text() == v) { + this.selected = true; + v1 = $(this).val(); + return false; + } + }); + // post the key and not the text + sdata[this.index] = v1 || ""; + if(self.p.marksearched){ + $("#jqgh_"+this.name,gr.grid.hDiv).addClass("dirty-cell"); + } + j++; + } else { + if(self.p.marksearched){ + $("#jqgh_"+this.name,gr.grid.hDiv).removeClass("dirty-cell"); + } + // remove from postdata + try { + delete gr.p.postData[this.index]; + } catch(e) {} + } + break; + case 'text': + $("input[name="+this.name+"]",self).val(v); + if(v) { + sdata[this.index] = v; + if(self.p.marksearched){ + $("#jqgh_"+this.name,gr.grid.hDiv).addClass("dirty-cell"); + } + j++; + } else { + if(self.p.marksearched){ + $("#jqgh_"+this.name,gr.grid.hDiv).removeClass("dirty-cell"); + } + // remove from postdata + try { + delete gr.p.postData[this.index]; + } catch(e) {} + } + } + }); + var sd = j>0 ? true : false; + gr.p.postData = $.extend(gr.p.postData,sdata); + var saveurl; + if(self.p.url) { + saveurl = $(gr).getGridParam('url'); + $(gr).setGridParam({url:self.p.url}); + } + $(gr).setGridParam({search:sd,page:1}).trigger("reloadGrid"); + if(saveurl) {$(gr).setGridParam({url:saveurl});} + if($.isFunction(self.p.afterClear)){self.p.afterClear();} + }; + var formFill = function(){ + var tr = document.createElement("tr"); + var tr1, sb, cb,tl,td, td1; + if(self.p.formtype=='horizontal'){ + $(tbl).append(tr); + } + $.each(self.p.filterModel,function(i,n){ + tl = document.createElement("td"); + $(tl).append(""); + td = document.createElement("td"); + var $t=this; + if(!this.stype) { this.stype='text';} + switch (this.stype) + { + case "select": + if(this.surl) { + // data returned should have already constructed html select + $(td).load(this.surl,function(){ + if($t.defval) $("select",this).val($t.defval); + $("select",this).attr({name:$t.name, id: "sg_"+$t.name}); + if($t.sopt) $("select",this).attr($t.sopt); + if(self.p.gridToolbar===true && $t.width) { + $("select",this).width($t.width); + } + if(self.p.autosearch===true){ + $("select",this).change(function(e){ + triggerSearch(); + return false; + }); + } + }); + } else { + // sopt to construct the values + if($t.sopt.value) { + var so = $t.sopt.value.split(";"), sv, ov; + var elem = document.createElement("select"); + $(elem).attr({name:$t.name, id: "sg_"+$t.name}).attr($t.sopt); + for(var k=0; k"); + if($t.sopt) $("input",td).attr($t.sopt); + if(self.p.gridToolbar===true && $t.width) { + if($.browser.msie) { + $("input",td).width($t.width-4); + } else { + $("input",td).width($t.width-2); + } + } + if(self.p.autosearch===true){ + $("input",td).keypress(function(e){ + var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0; + if(key == 13){ + triggerSearch(); + return false; + } + return this; + }); + } + break; + } + if(self.p.formtype=='horizontal'){ + if(self.p.gridToolbar===true && self.p.gridNames===false) { + $(tr).append(td); + } else { + $(tr).append(tl).append(td); + } + $(tr).append(td); + } else { + tr1 = document.createElement("tr"); + $(tr1).append(tl).append(td); + $(tbl).append(tr1); + } + }); + td = document.createElement("td"); + if(self.p.enableSearch === true){ + sb = ""; + $(td).append(sb); + $("input#sButton",td).click(function(){ + triggerSearch(); + return false; + }); + } + if(self.p.enableClear === true) { + cb = ""; + $(td).append(cb); + $("input#cButton",td).click(function(){ + clearSearch(); + return false; + }); + } + if(self.p.enableClear === true || self.p.enableSearch === true) { + if(self.p.formtype=='horizontal') { + $(tr).append(td); + } else { + tr1 = document.createElement("tr"); + $(tr1).append(" ").append(td); + $(tbl).append(tr1); + } + } + }; + var frm = $("
    "); + var tbl =$("
    "); + $(frm).append(tbl); + formFill(); + $(this).append(frm); + this.triggerSearch = function () {triggerSearch();}; + this.clearSearch = function () {clearSearch();}; + }); + } +}); +})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/grid.formedit.js b/site/vendors/js/jqGrid/js/grid.formedit.js new file mode 100644 index 0000000..6cc09bf --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.formedit.js @@ -0,0 +1,1307 @@ +;(function($){ +/** + * jqGrid extension for form editing Grid Data + * Tony Tomov tony@trirand.com + * http://trirand.com/blog/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +var rp_ge = null; +$.fn.extend({ + searchGrid : function ( p ) { + p = $.extend({ + top : 0, + left: 0, + width: 360, + height: 80, + modal: false, + drag: true, + closeicon: 'ico-close.gif', + dirty: false, + sField:'searchField', + sValue:'searchString', + sOper: 'searchOper', + processData: "", + checkInput :false, + beforeShowSearch: null, + afterShowSearch : null, + onInitializeSearch: null, + closeAfterSearch : false, + closeOnEscape : false, + // translation + // if you want to change or remove the order change it in sopt + // ['bw','eq','ne','lt','le','gt','ge','ew','cn'] + sopt: null + }, $.jgrid.search, p || {}); + return this.each(function(){ + var $t = this; + if( !$t.grid ) { return; } + if(!p.imgpath) { p.imgpath= $t.p.imgpath; } + var gID = $("table:first",$t.grid.bDiv).attr("id"); + var IDs = { themodal:'srchmod'+gID,modalhead:'srchhead'+gID,modalcontent:'srchcnt'+gID }; + if ( $("#"+IDs.themodal).html() != null ) { + if( $.isFunction(p.beforeShowSearch) ) { p.beforeShowSearch($("#srchcnt"+gID)); } + viewModal("#"+IDs.themodal,{modal: p.modal}); + if( $.isFunction(p.afterShowSearch) ) { p.afterShowSearch($("#srchcnt"+gID)); } + } else { + var cM = $t.p.colModel; + var cNames = ""; + var getopt = p.sopt || ['bw','eq','ne','lt','le','gt','ge','ew','cn']; + var sOpt = ""; + // field and buttons + var sField = ""; + var bSearch = ""; + var bReset = ""; + var cnt = $("
    "+cNames+""+sOpt+""+sField+""+bSearch+""+bReset+"
    "); + createModal(IDs,cnt,p,$t.grid.hDiv,$t.grid.hDiv); + if ( $.isFunction(p.onInitializeSearch) ) { p.onInitializeSearch( $("#srchcnt"+gID) ); }; + if ( $.isFunction(p.beforeShowSearch) ) { p.beforeShowSearch($("#srchcnt"+gID)); }; + viewModal("#"+IDs.themodal,{modal:p.modal}); + if($.isFunction(p.afterShowSearch)) { p.afterShowSearch($("#srchcnt"+gID)); } + if(p.drag) { DnRModal("#"+IDs.themodal,"#"+IDs.modalhead+" td.modaltext"); } + $("#sbut","#"+IDs.themodal).click(function(){ + if( $("#sval","#"+IDs.themodal).val() !="" ) { + var es=[true,"",""]; + $("#srcherr >td","#srchcnt"+gID).html("").hide(); + $t.p.searchdata[p.sField] = $("option[selected]","#snames").val(); + $t.p.searchdata[p.sOper] = $("option[selected]","#sopt").val(); + $t.p.searchdata[p.sValue] = $("#sval","#"+IDs.modalcontent).val(); + if(p.checkInput) { + for(var i=0; i< cM.length;i++) { + var sname = (cM[i].index) ? cM[i].index : nm; + if (sname == $t.p.searchdata[p.sField]) { + break; + } + } + es = checkValues($t.p.searchdata[p.sValue],i,$t); + } + if (es[0]===true) { + $t.p.search = true; // initialize the search + // construct array of data which is passed in populate() see jqGrid + if(p.dirty) { $(".no-dirty-cell",$t.p.pager).addClass("dirty-cell"); } + $t.p.page= 1; + $($t).trigger("reloadGrid"); + if(p.closeAfterSearch === true) { + hideModal("#"+IDs.themodal); + } + } else { + $("#srcherr >td","#srchcnt"+gID).html(es[1]).show(); + } + } + }); + $("#sreset","#"+IDs.themodal).click(function(){ + if ($t.p.search) { + $("#srcherr >td","#srchcnt"+gID).html("").hide(); + $t.p.search = false; + $t.p.searchdata = {}; + $t.p.page= 1; + $("#sval","#"+IDs.themodal).val(""); + if(p.dirty) { $(".no-dirty-cell",$t.p.pager).removeClass("dirty-cell"); } + $($t).trigger("reloadGrid"); + } + }); + } + }); + }, + editGridRow : function(rowid, p){ + p = $.extend({ + top : 0, + left: 0, + width: 0, + height: 0, + modal: false, + drag: true, + closeicon: 'ico-close.gif', + imgpath: '', + url: null, + mtype : "POST", + closeAfterAdd : false, + clearAfterAdd : true, + closeAfterEdit : false, + reloadAfterSubmit : true, + onInitializeForm: null, + beforeInitData: null, + beforeShowForm: null, + afterShowForm: null, + beforeSubmit: null, + afterSubmit: null, + onclickSubmit: null, + afterComplete: null, + onclickPgButtons : null, + afterclickPgButtons: null, + editData : {}, + recreateForm : false, + closeOnEscape : false, + addedrow : "first" + }, $.jgrid.edit, p || {}); + rp_ge = p; + return this.each(function(){ + var $t = this; + if (!$t.grid || !rowid) { return; } + if(!p.imgpath) { p.imgpath= $t.p.imgpath; } + // I hate to rewrite code, but ... + var gID = $("table:first",$t.grid.bDiv).attr("id"), + IDs = {themodal:'editmod'+gID,modalhead:'edithd'+gID,modalcontent:'editcnt'+gID}, + onBeforeShow = $.isFunction(rp_ge.beforeShowForm) ? rp_ge.beforeShowForm : false, + onAfterShow = $.isFunction(rp_ge.afterShowForm) ? rp_ge.afterShowForm : false, + onBeforeInit = $.isFunction(rp_ge.beforeInitData) ? rp_ge.beforeInitData : false, + onInitializeForm = $.isFunction(rp_ge.onInitializeForm) ? rp_ge.onInitializeForm : false, + maxCols = 1, copydata, + frmgr = "FrmGrid_"+gID , frmtb = "TblGrid_"+gID; + if (rowid=="new") { + rowid = "_empty"; + p.caption=p.addCaption; + } else { + p.caption=p.editCaption; + }; + if(p.recreateForm===true && $("#"+IDs.themodal).html() != null) { + $("#"+IDs.themodal).remove(); + } + if ( $("#"+IDs.themodal).html() != null ) { + $(".modaltext","#"+IDs.modalhead).html(p.caption); + $("#FormError","#"+frmtb).hide(); + if(onBeforeInit) { onBeforeInit($("#"+frmgr)); } + fillData(rowid,$t); + if(rowid=="_empty") { $("#pData, #nData","#"+frmtb).hide(); } else { $("#pData, #nData","#"+frmtb).show(); } + if(onBeforeShow) { onBeforeShow($("#"+frmgr)); } + if(p.processing === true) { // in case of error from server + p.processing=false; + $("#sData", "#"+frmtb).attr("disabled",false); + $("div.loading","#"+IDs.themodal).hide(); + } + viewModal("#"+IDs.themodal,{modal:p.modal}); + if(onAfterShow) { onAfterShow($("#"+frmgr)); } + } else { + $($t.p.colModel).each( function(i) { + maxCols = Math.max(maxCols, this.formoptions ? this.formoptions.colpos || 0 : 0 ); + }); + var flr, frm = $("
    "), + tbl =$("
    "); + $(frm).append(tbl); + flr = $(""); + flr[0].rp = 0; + $(tbl).append(flr); + // set the id. + // use carefull only to change here colproperties. + if(onBeforeInit) { onBeforeInit($("#"+frmgr)); } + var valref = createData(rowid, $t, tbl, maxCols), + // buttons at footer + imp = $t.p.imgpath, + bP ="", + bN ="", + bS ="", + bC =""; + flr = $(""+bP+" "+bN+""+bS+" "+bC+""); + flr[0].rp = valref.length + 100; + $(tbl).append(flr); + if(maxCols > 1) { + var sd=[]; + $.each($(tbl)[0].rows,function(i,r){ + sd[i] = r; + }); + sd.sort(function(a,b){ + if(a.rp > b.rp) {return 1;} + if(a.rp < b.rp) {return -1;} + return 0; + }); + $.each(sd, function(index, row) { + $('tbody',tbl).append(row); + }); + } + // beforeinitdata after creation of the form + createModal(IDs,frm,p,$t.grid.hDiv,$t.grid.hDiv); + // here initform - only once + if(onInitializeForm) { onInitializeForm($("#"+frmgr)); } + if( p.drag ) { DnRModal("#"+IDs.themodal,"#"+IDs.modalhead+" td.modaltext"); } + if(rowid=="_empty") { $("#pData,#nData","#"+frmtb).hide(); } else { $("#pData,#nData","#"+frmtb).show(); } + if(onBeforeShow) { onBeforeShow($("#"+frmgr)); } + viewModal("#"+IDs.themodal,{modal:p.modal}); + if(onAfterShow) { onAfterShow($("#"+frmgr)); } + $("#sData", "#"+frmtb).click(function(e){ + var postdata = {}, ret=[true,"",""], extpost={}; + $("#FormError","#"+frmtb).hide(); + // all depend on ret array + //ret[0] - succes + //ret[1] - msg if not succes + //ret[2] - the id that will be set if reload after submit false + var j =0; + $(".FormElement", "#"+frmtb).each(function(i){ + var suc = true; + switch ($(this).get(0).type) { + case "checkbox": + if($(this).attr("checked")) { + postdata[this.name]= $(this).val(); + }else { + var ofv = $(this).attr("offval"); + postdata[this.name]= ofv; + extpost[this.name] = ofv; + } + break; + case "select-one": + postdata[this.name]= $("option:selected",this).val(); + extpost[this.name]= $("option:selected",this).text(); + break; + case "select-multiple": + postdata[this.name]= $(this).val(); + var selectedText = []; + $("option:selected",this).each( + function(i,selected){ + selectedText[i] = $(selected).text(); + } + ); + extpost[this.name]= selectedText.join(","); + break; + case "password": + case "text": + case "textarea": + postdata[this.name] = $(this).val(); + ret = checkValues(postdata[this.name],valref[i],$t); + if(ret[0] === false) { + suc=false; + } else { + postdata[this.name] = !$t.p.autoencode ? postdata[this.name] : htmlEncode(postdata[this.name]); + } + break; + } + j++; + if(!suc) { return false; } + }); + if(j==0) { ret[0] = false; ret[1] = $.jgrid.errors.norecords; } + if( $.isFunction( rp_ge.onclickSubmit)) { rp_ge.editData = rp_ge.onclickSubmit(p) || {}; } + if(ret[0]) { + if( $.isFunction(rp_ge.beforeSubmit)) { ret = rp_ge.beforeSubmit(postdata,$("#"+frmgr)); } + } + var gurl = rp_ge.url ? rp_ge.url : $t.p.editurl; + if(ret[0]) { + if(!gurl) { ret[0]=false; ret[1] += " "+$.jgrid.errors.nourl; } + } + if(ret[0] === false) { + $("#FormError>td","#"+frmtb).html(ret[1]); + $("#FormError","#"+frmtb).show(); + } else { + if(!p.processing) { + p.processing = true; + $("div.loading","#"+IDs.themodal).show(); + $(this).attr("disabled",true); + // we add to pos data array the action - the name is oper + postdata.oper = postdata.id == "_empty" ? "add" : "edit"; + postdata = $.extend(postdata,rp_ge.editData); + $.ajax({ + url:gurl, + type: rp_ge.mtype, + data:postdata, + complete:function(data,Status){ + if(Status != "success") { + ret[0] = false; + ret[1] = Status+" Status: "+data.statusText +" Error code: "+data.status; + } else { + // data is posted successful + // execute aftersubmit with the returned data from server + if( $.isFunction(rp_ge.afterSubmit) ) { + ret = rp_ge.afterSubmit(data,postdata); + } + } + if(ret[0] === false) { + $("#FormError>td","#"+frmtb).html(ret[1]); + $("#FormError","#"+frmtb).show(); + } else { + postdata = $.extend(postdata,extpost); + // the action is add + if(postdata.id=="_empty" ) { + //id processing + // user not set the id ret[2] + if(!ret[2]) { ret[2] = parseInt($($t).getGridParam('records'))+1; } + postdata.id = ret[2]; + if(rp_ge.closeAfterAdd) { + if(rp_ge.reloadAfterSubmit) { $($t).trigger("reloadGrid"); } + else { + $($t).addRowData(ret[2],postdata,p.addedrow); + $($t).setSelection(ret[2]); + } + hideModal("#"+IDs.themodal); + } else if (rp_ge.clearAfterAdd) { + if(rp_ge.reloadAfterSubmit) { $($t).trigger("reloadGrid"); } + else { $($t).addRowData(ret[2],postdata,p.addedrow); } + $(".FormElement", "#"+frmtb).each(function(i){ + switch ($(this).get(0).type) { + case "checkbox": + $(this).attr("checked",0); + break; + case "select-one": + case "select-multiple": + $("option",this).attr("selected",""); + break; + case "password": + case "text": + case "textarea": + if(this.name =='id') { $(this).val("_empty"); } + else { $(this).val(""); } + break; + } + }); + fillData("_empty",$t); + } else { + if(rp_ge.reloadAfterSubmit) { $($t).trigger("reloadGrid");} + else { $($t).addRowData(ret[2],postdata,p.addedrow); } + } + } else { + // the action is update + if(rp_ge.reloadAfterSubmit) { + $($t).trigger("reloadGrid"); + if( !rp_ge.closeAfterEdit ) { $($t).setSelection(postdata.id); } + } else { + if($t.p.treeGrid === true) { + $($t).setTreeRow(postdata.id,postdata); + } else { + $($t).setRowData(postdata.id,postdata); + } + } + if(rp_ge.closeAfterEdit) { hideModal("#"+IDs.themodal); } + } + if($.isFunction(rp_ge.afterComplete)) { + copydata = data; + setTimeout(function(){rp_ge.afterComplete(copydata,postdata,$("#"+frmgr));copydata=null},500); + } + } + p.processing=false; + $("#sData", "#"+frmtb).attr("disabled",false); + $("div.loading","#"+IDs.themodal).hide(); + }, + error:function(xhr,st,err){ + $("#FormError>td","#"+frmtb).html(st+ " : "+err); + $("#FormError","#"+frmtb).show(); + p.processing=false; + $("#sData", "#"+frmtb).attr("disabled",false); + $("div.loading","#"+IDs.themodal).hide(); + } + }); + } + } + e.stopPropagation(); + return false; + }); + $("#cData", "#"+frmtb).click(function(e){ + hideModal("#"+IDs.themodal); + e.stopPropagation(); + return false; + }); + $("#nData", "#"+frmtb).click(function(e){ + $("#FormError","#"+frmtb).hide(); + var npos = getCurrPos(); + npos[0] = parseInt(npos[0]); + if(npos[0] != -1 && npos[1][npos[0]+1]) { + if($.isFunction(p.onclickPgButtons)) { + p.onclickPgButtons('next',$("#"+frmgr),npos[1][npos[0]]); + } + fillData(npos[1][npos[0]+1],$t); + $($t).setSelection(npos[1][npos[0]+1]); + if($.isFunction(p.afterclickPgButtons)) { + p.afterclickPgButtons('next',$("#"+frmgr),npos[1][npos[0]+1]); + } + updateNav(npos[0]+1,npos[1].length-1); + }; + return false; + }); + $("#pData", "#"+frmtb).click(function(e){ + $("#FormError","#"+frmtb).hide(); + var ppos = getCurrPos(); + if(ppos[0] != -1 && ppos[1][ppos[0]-1]) { + if($.isFunction(p.onclickPgButtons)) { + p.onclickPgButtons('prev',$("#"+frmgr),ppos[1][ppos[0]]); + } + fillData(ppos[1][ppos[0]-1],$t); + $($t).setSelection(ppos[1][ppos[0]-1]); + if($.isFunction(p.afterclickPgButtons)) { + p.afterclickPgButtons('prev',$("#"+frmgr),ppos[1][ppos[0]-1]); + } + updateNav(ppos[0]-1,ppos[1].length-1); + }; + return false; + }); + }; + var posInit =getCurrPos(); + updateNav(posInit[0],posInit[1].length-1); + function updateNav(cr,totr,rid){ + var imp = $t.p.imgpath; + if (cr==0) { $("#pData","#"+frmtb).attr("src",imp+"off-"+$t.p.previmg); } else { $("#pData","#"+frmtb).attr("src",imp+$t.p.previmg); } + if (cr==totr) { $("#nData","#"+frmtb).attr("src",imp+"off-"+$t.p.nextimg); } else { $("#nData","#"+frmtb).attr("src",imp+$t.p.nextimg); } + }; + function getCurrPos() { + var rowsInGrid = $($t).getDataIDs(); + var selrow = $("#id_g","#"+frmtb).val(); + var pos = $.inArray(selrow,rowsInGrid); + return [pos,rowsInGrid]; + }; + function createData(rowid,obj,tb,maxcols){ + var nm, hc,trdata, tdl, tde, cnt=0,tmp, dc,elc, retpos=[], ind=false, + tdtmpl = "  ", tmpl=""; //*2 + for (var i =1;i<=maxcols;i++) { + tmpl += tdtmpl; + } + ind = $(obj).getInd(obj.rows,rowid); + $(obj.p.colModel).each( function(i) { + nm = this.name; + // hidden fields are included in the form + if(this.editrules && this.editrules.edithidden == true) { + hc = false; + } else { + hc = this.hidden === true ? true : false; + } + dc = hc ? "style='display:none'" : ""; + if ( nm !== 'cb' && nm !== 'subgrid' && this.editable===true) { + if(ind === false) { + tmp = ""; + } else { + if(nm == obj.p.ExpandColumn && obj.p.treeGrid === true) { + tmp = $("td:eq("+i+")",obj.rows[ind]).text(); + } else { + try { + tmp = $.unformat($("td:eq("+i+")",obj.rows[ind]),{colModel:this},i); + } catch (_) { + tmp = $("td:eq("+i+")",obj.rows[ind]).html(); + } + } + } + var opt = $.extend({}, this.editoptions || {} ,{id:nm,name:nm}), + frmopt = $.extend({}, {elmprefix:'',elmsuffix:''}, this.formoptions || {}), + rp = parseInt(frmopt.rowpos) || cnt+1, + cp = parseInt((parseInt(frmopt.colpos) || 1)*2); + if(rowid == "_empty" && opt.defaultValue ) { + tmp = $.isFunction(opt.defaultValue) ? opt.defaultValue() : opt.defaultValue; + } + if(!this.edittype) this.edittype = "text"; + elc = createEl(this.edittype,opt,tmp); + $(elc).addClass("FormElement"); + // try to find the element + trdata = $(tbl).find("tr[rowpos="+rp+"]"); + if ( trdata.length==0 ) { + trdata = $("").addClass("FormData").attr("id","tr_"+nm); + $(trdata).append(tmpl); + $(tb).append(trdata); + trdata[0].rp = rp; + } + $("td:eq("+(cp-2)+")",trdata[0]).html( typeof frmopt.label === 'undefined' ? obj.p.colNames[i]: frmopt.label); + $("td:eq("+(cp-1)+")",trdata[0]).append(frmopt.elmprefix).append(elc).append(frmopt.elmsuffix); + //$(tb).append(trdata); + retpos[cnt] = i; + cnt++; + }; + }); + if( cnt > 0) { + var idrow = $(""); + idrow[0].rp = cnt+99; + $(tb).append(idrow); + } + return retpos; + }; + function fillData(rowid,obj){ + var nm, hc,cnt=0,tmp, opt; + $('#'+rowid+' td',obj.grid.bDiv).each( function(i) { + nm = obj.p.colModel[i].name; + // hidden fields are included in the form + if(obj.p.colModel[i].editrules && obj.p.colModel[i].editrules.edithidden === true) { + hc = false; + } else { + hc = obj.p.colModel[i].hidden === true ? true : false; + } + if ( nm !== 'cb' && nm !== 'subgrid' && obj.p.colModel[i].editable===true) { + if(nm == obj.p.ExpandColumn && obj.p.treeGrid === true) { + tmp = $(this).text(); + } else { + try { + tmp = $.unformat(this,{colModel:obj.p.colModel[i]},i); + } catch (_) { + tmp = $(this).html(); + } + } + nm= nm.replace('.',"\\."); + opt = $.extend({},obj.p.colModel[i].editoptions || {}); + if(rowid == "_empty" && opt.defaultValue ) { + tmp = $.isFunction(opt.defaultValue) ? opt.defaultValue() : opt.defaultValue; + } + switch (obj.p.colModel[i].edittype) { + case "password": + case "text": + $("#"+nm,"#"+frmtb).val(tmp); + break; + case "textarea": + if(tmp == " " || tmp == " " || (tmp.length==1 && tmp.charCodeAt(0)==160) ) {tmp='';} + $("#"+nm,"#"+frmtb).val(tmp); + break; + case "select": + $("#"+nm+" option","#"+frmtb).each(function(j){ + if (!opt.multiple && tmp == $(this).text() ){ + this.selected= true; + } else if (opt.multiple){ + if( $.inArray($(this).text(), tmp.split(",") ) > -1 ){ + this.selected = true; + }else{ + this.selected = false; + } + } else { + this.selected = false; + } + }); + break; + case "checkbox": + if(tmp==$("#"+nm,"#"+frmtb).val()) { + $("#"+nm,"#"+frmtb).attr("checked",true); + $("#"+nm,"#"+frmtb).attr("defaultChecked",true); //ie + } else { + $("#"+nm,"#"+frmtb).attr("checked",false); + $("#"+nm,"#"+frmtb).attr("defaultChecked",""); //ie + } + break; + } + if (hc) { $("#"+nm,"#"+frmtb).parents("tr:first").hide(); } + cnt++; + } + }); + if(cnt>0) { $("#id_g","#"+frmtb).val(rowid); } + else { $("#id_g","#"+frmtb).val(""); } + return cnt; + }; + }); + }, + viewGridRow : function(rowid, p){ + p = $.extend({ + top : 0, + left: 0, + width: 0, + height: 0, + modal: false, + drag: true, + closeicon: 'ico-close.gif', + imgpath: '', + closeOnEscape : false, + labelswidth: '30%' + }, $.jgrid.view, p || {}); + return this.each(function(){ + var $t = this; + if (!$t.grid || !rowid) { return; } + if(!p.imgpath) { p.imgpath= $t.p.imgpath; } + // I hate to rewrite code, but ... + var gID = $("table:first",$t.grid.bDiv).attr("id"), + IDs = {themodal:'viewmod'+gID,modalhead:'viewhd'+gID,modalcontent:'viewcnt'+gID}, + maxCols = 1, + frmgr = "ViewGrid_"+gID , frmtb = "ViewTbl_"+gID; + if ( $("#"+IDs.themodal).html() != null ) { + $(".modaltext","#"+IDs.modalhead).html(p.caption); + $("#FormError","#"+frmtb).hide(); + fillData(rowid,$t); + viewModal("#"+IDs.themodal,{modal:p.modal}); + focusaref(); + } else { + $($t.p.colModel).each( function(i) { + maxCols = Math.max(maxCols, this.formoptions ? this.formoptions.colpos || 0 : 0 ); + }); + var flr, frm = $("
    "), + tbl =$("
    "); + $(frm).append(tbl); + // set the id. + var valref = createData(rowid, $t, tbl, maxCols), + // buttons at footer + imp = $t.p.imgpath, + bP ="", + bN ="", + bC =""; + flr = $(""+bP+" "+bN+""+bC+""); + flr[0].rp = valref.length + 100; + $(tbl).append(flr); + if(maxCols > 1) { + var sd=[]; + $.each($(tbl)[0].rows,function(i,r){ + sd[i] = r; + }); + sd.sort(function(a,b){ + if(a.rp > b.rp) {return 1;} + if(a.rp < b.rp) {return -1;} + return 0; + }); + $.each(sd, function(index, row) { + $('tbody',tbl).append(row); + }); + } + createModal(IDs,frm,p,$t.grid.hDiv,$t.grid.hDiv); + if( p.drag ) { DnRModal("#"+IDs.themodal,"#"+IDs.modalhead+" td.modaltext"); } + viewModal("#"+IDs.themodal,{modal:p.modal}); + focusaref(); + $("#cData", "#"+frmtb).click(function(e){ + hideModal("#"+IDs.themodal); + e.stopPropagation(); + return false; + }); + $("#nData", "#"+frmtb).click(function(e){ + $("#FormError","#"+frmtb).hide(); + var npos = getCurrPos(); + npos[0] = parseInt(npos[0]); + if(npos[0] != -1 && npos[1][npos[0]+1]) { + if($.isFunction(p.onclickPgButtons)) { + p.onclickPgButtons('next',$("#"+frmgr),npos[1][npos[0]]); + } + fillData(npos[1][npos[0]+1],$t); + $($t).setSelection(npos[1][npos[0]+1]); + if($.isFunction(p.afterclickPgButtons)) { + p.afterclickPgButtons('next',$("#"+frmgr),npos[1][npos[0]+1]); + } + updateNav(npos[0]+1,npos[1].length-1); + }; + focusaref(); + return false; + }); + $("#pData", "#"+frmtb).click(function(e){ + $("#FormError","#"+frmtb).hide(); + var ppos = getCurrPos(); + if(ppos[0] != -1 && ppos[1][ppos[0]-1]) { + if($.isFunction(p.onclickPgButtons)) { + p.onclickPgButtons('prev',$("#"+frmgr),ppos[1][ppos[0]]); + } + fillData(ppos[1][ppos[0]-1],$t); + $($t).setSelection(ppos[1][ppos[0]-1]); + if($.isFunction(p.afterclickPgButtons)) { + p.afterclickPgButtons('prev',$("#"+frmgr),ppos[1][ppos[0]-1]); + } + updateNav(ppos[0]-1,ppos[1].length-1); + }; + focusaref(); + return false; + }); + }; + function focusaref(){ //Sfari 3 issues + if(p.closeOnEscape===true) { + setTimeout(function(){$(".jqmClose","#"+IDs.modalhead).focus()},0); + } + } + var posInit =getCurrPos(); + updateNav(posInit[0],posInit[1].length-1); + function updateNav(cr,totr,rid){ + var imp = $t.p.imgpath; + if (cr==0) { $("#pData","#"+frmtb).attr("src",imp+"off-"+$t.p.previmg); } else { $("#pData","#"+frmtb).attr("src",imp+$t.p.previmg); } + if (cr==totr) { $("#nData","#"+frmtb).attr("src",imp+"off-"+$t.p.nextimg); } else { $("#nData","#"+frmtb).attr("src",imp+$t.p.nextimg); } + }; + function getCurrPos() { + var rowsInGrid = $($t).getDataIDs(); + var selrow = $("#id_g","#"+frmtb).val(); + var pos = $.inArray(selrow,rowsInGrid); + return [pos,rowsInGrid]; + }; + function createData(rowid,obj,tb,maxcols){ + var nm, hc,trdata, tdl, tde, cnt=0,tmp, dc,elc, retpos=[], ind=false, + tdtmpl = "  ", tmpl="", + tdtmpl2 = "  ", + fmtnum = ['integer','number','currency'],max1 =0, max2=0 ,maxw,setme; + for (var i =1;i<=maxcols;i++) { + tmpl += i == 1 ? tdtmpl : tdtmpl2; + } + // find max number align rigth with property formatter + $(obj.p.colModel).each( function(i) { + if(this.editrules && this.editrules.edithidden === true) { + hc = false; + } else { + hc = this.hidden === true ? true : false; + } + if(!hc && this.align==='right') { + if(this.formatter && $.inArray(this.formatter,fmtnum) !== -1 ) { + max1 = Math.max(max1,parseInt(this.width,10)); + } else { + max2 = Math.max(max2,parseInt(this.width,10)); + } + } + }); + maxw = max1 !==0 ? max1 : max2 !==0 ? max2 : 0; + ind = $(obj).getInd(obj.rows,rowid); + $(obj.p.colModel).each( function(i) { + nm = this.name; + setme = false; + // hidden fields are included in the form + if(this.editrules && this.editrules.edithidden === true) { + hc = false; + } else { + hc = this.hidden === true ? true : false; + } + dc = hc ? "style='display:none'" : ""; + if ( nm !== 'cb' && nm !== 'subgrid' && this.editable===true) { + if(ind === false) { + tmp = ""; + } else { + if(nm == obj.p.ExpandColumn && obj.p.treeGrid === true) { + tmp = $("td:eq("+i+")",obj.rows[ind]).text(); + } else { + tmp = $("td:eq("+i+")",obj.rows[ind]).html(); + } + } + setme = this.align === 'right' && maxw !==0 ? true : false; + var opt = $.extend({}, this.editoptions || {} ,{id:nm,name:nm}), + frmopt = $.extend({}, {elmprefix:'',elmsuffix:''}, this.formoptions || {}), + rp = parseInt(frmopt.rowpos) || cnt+1, + cp = parseInt((parseInt(frmopt.colpos) || 1)*2); + if(!this.edittype) this.edittype = "text"; + trdata = $(tbl).find("tr[rowpos="+rp+"]"); + if ( trdata.length==0 ) { + trdata = $("").addClass("FormData").attr("id","tr_"+nm); + $(trdata).append(tmpl); + $(tb).append(trdata); + trdata[0].rp = rp; + } + $("td:eq("+(cp-2)+")",trdata[0]).html(''+ (typeof frmopt.label === 'undefined' ? obj.p.colNames[i]: frmopt.label)+''); + $("td:eq("+(cp-1)+")",trdata[0]).append(""+tmp+"").attr("id",nm); + if(setme){ + $("td:eq("+(cp-1)+") span",trdata[0]).css({'text-align':'right',width:maxw+"px"}); + } + retpos[cnt] = i; + cnt++; + }; + }); + if( cnt > 0) { + var idrow = $(""); + idrow[0].rp = cnt+99; + $(tb).append(idrow); + } + return retpos; + }; + function fillData(rowid,obj){ + var nm, hc,cnt=0,tmp, opt; + $('#'+rowid+' td',obj.grid.bDiv).each( function(i) { + nm = obj.p.colModel[i].name; + // hidden fields are included in the form + if(obj.p.colModel[i].editrules && obj.p.colModel[i].editrules.edithidden === true) { + hc = false; + } else { + hc = obj.p.colModel[i].hidden === true ? true : false; + } + if ( nm !== 'cb' && nm !== 'subgrid' && obj.p.colModel[i].editable===true) { + if(nm == obj.p.ExpandColumn && obj.p.treeGrid === true) { + tmp = $(this).text(); + } else { + tmp = $(this).html(); + } + nm= nm.replace('.',"\\."); + opt = $.extend({},obj.p.colModel[i].editoptions || {}); + $("#"+nm+" span","#"+frmtb).html(tmp); + if (hc) { $("#"+nm,"#"+frmtb).parents("tr:first").hide(); } + cnt++; + } + }); + if(cnt>0) { $("#id_g","#"+frmtb).val(rowid); } + else { $("#id_g","#"+frmtb).val(""); } + return cnt; + }; + }); + }, + delGridRow : function(rowids,p) { + p = $.extend({ + top : 0, + left: 0, + width: 240, + height: 90, + modal: false, + drag: true, + closeicon: 'ico-close.gif', + imgpath: '', + url : '', + mtype : "POST", + reloadAfterSubmit: true, + beforeShowForm: null, + afterShowForm: null, + beforeSubmit: null, + onclickSubmit: null, + afterSubmit: null, + onclickSubmit: null, + closeOnEscape : false, + delData: {} + }, $.jgrid.del, p ||{}); + return this.each(function(){ + var $t = this; + if (!$t.grid ) { return; } + if(!rowids) { return; } + if(!p.imgpath) { p.imgpath= $t.p.imgpath; } + var onBeforeShow = typeof p.beforeShowForm === 'function' ? true: false, + onAfterShow = typeof p.afterShowForm === 'function' ? true: false, + gID = $("table:first",$t.grid.bDiv).attr("id"), + IDs = {themodal:'delmod'+gID,modalhead:'delhd'+gID,modalcontent:'delcnt'+gID}, + dtbl = "DelTbl_"+gID, + copydata; + if (isArray(rowids)) { rowids = rowids.join(); } + if ( $("#"+IDs.themodal).html() != null ) { + $("#DelData>td","#"+dtbl).text(rowids); + $("#DelError","#"+dtbl).hide(); + if(p.processing===true) { // error case + p.processing=false; + $("#dData", "#"+dtbl).attr("disabled",false); + $("div.loading","#"+IDs.themodal).hide(); + } + if(onBeforeShow) { p.beforeShowForm($("#"+dtbl)); } + viewModal("#"+IDs.themodal,{modal:p.modal}); + if(onAfterShow) { p.afterShowForm($("#"+dtbl)); } + } else { + var tbl =$("
    "); + // error data + $(tbl).append(""+" "+""); + $(tbl).append(""+rowids+""); + $(tbl).append(""+p.msg+""); + // buttons at footer + var bS =""; + var bC =""; + $(tbl).append(""+bS+" "+bC+""); + createModal(IDs,tbl,p,$t.grid.hDiv,$t.grid.hDiv); + if( p.drag) { DnRModal("#"+IDs.themodal,"#"+IDs.modalhead+" td.modaltext"); } + $("#dData","#"+dtbl).click(function(e){ + var ret=[true,""]; + var postdata = $("#DelData>td","#"+dtbl).text(); //the pair is name=val1,val2,... + if( typeof p.onclickSubmit === 'function' ) { p.delData = p.onclickSubmit(p) || {}; } + if( typeof p.beforeSubmit === 'function' ) { ret = p.beforeSubmit(postdata); } + var gurl = p.url ? p.url : $t.p.editurl; + if(!gurl) { ret[0]=false;ret[1] += " "+$.jgrid.errors.nourl;} + if(ret[0] === false) { + $("#DelError>td","#"+dtbl).html(ret[1]); + $("#DelError","#"+dtbl).show(); + } else { + if(!p.processing) { + p.processing = true; + $("div.loading","#"+IDs.themodal).show(); + $(this).attr("disabled",true); + var postd = $.extend({oper:"del", id:postdata},p.delData); + $.ajax({ + url:gurl, + type: p.mtype, + data:postd, + complete:function(data,Status){ + if(Status != "success") { + ret[0] = false; + ret[1] = Status+" Status: "+data.statusText +" Error code: "+data.status; + } else { + // data is posted successful + // execute aftersubmit with the returned data from server + if( typeof p.afterSubmit === 'function' ) { + ret = p.afterSubmit(data,postdata); + } + } + if(ret[0] === false) { + $("#DelError>td","#"+dtbl).html(ret[1]); + $("#DelError","#"+dtbl).show(); + } else { + if(p.reloadAfterSubmit) { + if($t.p.treeGrid) { + $($t).setGridParam({treeANode:0,datatype:$t.p.treedatatype}); + } + $($t).trigger("reloadGrid"); + } else { + var toarr = []; + toarr = postdata.split(","); + if($t.p.treeGrid===true){ + try {$($t).delTreeNode(toarr[0])} catch(e){} + } else { + for(var i=0;itd","#"+dtbl).html(st+ " : "+err); + $("#DelError","#"+dtbl).show(); + p.processing=false; + $("#dData", "#"+dtbl).attr("disabled",false); + $("div.loading","#"+IDs.themodal).hide(); + } + }); + } + } + return false; + }); + $("#eData", "#"+dtbl).click(function(e){ + hideModal("#"+IDs.themodal); + return false; + }); + if(onBeforeShow) { p.beforeShowForm($("#"+dtbl)); } + viewModal("#"+IDs.themodal,{modal:p.modal}); + if(onAfterShow) { p.afterShowForm($("#"+dtbl)); } + } + }); + }, + navGrid : function (elem, o, pEdit,pAdd,pDel,pSearch, pView) { + o = $.extend({ + edit: true, + editicon: "row_edit.gif", + + add: true, + addicon:"row_add.gif", + + del: true, + delicon:"row_delete.gif", + + search: true, + searchicon:"find.gif", + + refresh: true, + refreshicon:"refresh.gif", + refreshstate: 'firstpage', + + position : "left", + closeicon: "ico-close.gif", + closeOnEscape : true, + view: true, + viewicon : "row_view.gif" + }, $.jgrid.nav, o ||{}); + return this.each(function() { + var alertIDs = {themodal:'alertmod',modalhead:'alerthd',modalcontent:'alertcnt'}; + var $t = this; + if(!$t.grid) { return; } + if ($("#"+alertIDs.themodal).html() == null) { + var vwidth; + var vheight; + if (typeof window.innerWidth != 'undefined') { + vwidth = window.innerWidth, + vheight = window.innerHeight + } else if (typeof document.documentElement != 'undefined' && typeof document.documentElement.clientWidth != 'undefined' && document.documentElement.clientWidth != 0) { + vwidth = document.documentElement.clientWidth, + vheight = document.documentElement.clientHeight + } else { + vwidth=1024; + vheight=768; + } + createModal(alertIDs,"
    "+o.alerttext+"
    ",{imgpath:$t.p.imgpath,closeicon:o.closeicon,caption:o.alertcap,top:vheight/2-25,left:vwidth/2-100,width:200,height:50,closeOnEscape:o.closeOnEscape},$t.grid.hDiv,$t.grid.hDiv,true); + DnRModal("#"+alertIDs.themodal,"#"+alertIDs.modalhead); + } + var navTbl = $("").height(20); + var trd = document.createElement("tr"); + $(trd).addClass("nav-row"); + var imp = $t.p.imgpath; + var tbd; + if (o.add) { + tbd = document.createElement("td"); + $(tbd).append(" ").css({border:"none",padding:"0px"}); + trd.appendChild(tbd); + tbd = document.createElement("td"); + tbd.title = o.addtitle || ""; + $(tbd).append("
    "+o.addtext+" 
    ") + .css("cursor","pointer") + .addClass("nav-button") + .click(function(){ + if (typeof o.addfunc == 'function') { + o.addfunc(); + } else { + $($t).editGridRow("new",pAdd || {}); + } + return false; + }) + .hover( + function () { + $(this).addClass("nav-hover"); + }, + function () { + $(this).removeClass("nav-hover"); + } + ); + trd.appendChild(tbd); + tbd = null; + } + if (o.edit) { + tbd = document.createElement("td"); + $(tbd).append(" ").css({border:"none",padding:"0px"}); + trd.appendChild(tbd); + tbd = document.createElement("td"); + tbd.title = o.edittitle || ""; + $(tbd).append("
    "+o.edittext+" 
    ") + .css("cursor","pointer") + .addClass("nav-button") + .click(function(){ + var sr = $($t).getGridParam('selrow'); + if (sr) { + if(typeof o.editfunc == 'function') { + o.editfunc(sr); + } else { + $($t).editGridRow(sr,pEdit || {}); + } + } else { + viewModal("#"+alertIDs.themodal,{toTop:false}); + $("#jqg_alrt").focus(); + } + return false; + }) + .hover( function () { + $(this).addClass("nav-hover"); + }, + function () { + $(this).removeClass("nav-hover"); + } + ); + trd.appendChild(tbd); + tbd = null; + } + if (o.view) { + tbd = document.createElement("td"); + $(tbd).append(" ").css({border:"none",padding:"0px"}); + trd.appendChild(tbd); + tbd = document.createElement("td"); + tbd.title = o.viewtitle || ""; + $(tbd).append("
    "+o.viewtext+" 
    ") + .css("cursor","pointer") + .addClass("nav-button") + .click(function(){ + var sr = $($t).getGridParam('selrow'); + if (sr) { + $($t).viewGridRow(sr,pView || {}); + } else { + viewModal("#"+alertIDs.themodal,{toTop:false}); + $("#jqg_alrt").focus(); + } + return false; + }) + .hover( function () { + $(this).addClass("nav-hover"); + }, + function () { + $(this).removeClass("nav-hover"); + } + ); + trd.appendChild(tbd); + tbd = null; + } + if (o.del) { + tbd = document.createElement("td"); + $(tbd).append(" ").css({border:"none",padding:"0px"}); + trd.appendChild(tbd); + tbd = document.createElement("td"); + tbd.title = o.deltitle || ""; + $(tbd).append("
    "+o.deltext+" 
    ") + .css("cursor","pointer") + .addClass("nav-button") + .click(function(){ + var dr; + if($t.p.multiselect) { + dr = $($t).getGridParam('selarrrow'); + if(dr.length==0) { dr = null; } + } else { + dr = $($t).getGridParam('selrow'); + } + if (dr) { $($t).delGridRow(dr,pDel || {}); } + else { viewModal("#"+alertIDs.themodal,{toTop:false}); $("#jqg_alrt").focus(); } + return false; + }) + .hover( + function () { + $(this).addClass("nav-hover"); + }, + function () { + $(this).removeClass("nav-hover"); + } + ); + trd.appendChild(tbd); + tbd = null; + } + if (o.search) { + tbd = document.createElement("td"); + $(tbd).append(" ").css({border:"none",padding:"0px"}); + trd.appendChild(tbd); + tbd = document.createElement("td"); + if( $(elem)[0] == $t.p.pager[0] ) { pSearch = $.extend(pSearch,{dirty:true}); } + tbd.title = o.searchtitle || ""; + $(tbd).append("
    "+o.searchtext+" 
    ") + .css({cursor:"pointer"}) + .addClass("nav-button") + .click(function(){ + $($t).searchGrid(pSearch || {}); + return false; + }) + .hover( + function () { + $(this).addClass("nav-hover"); + }, + function () { + $(this).removeClass("nav-hover"); + } + ); + trd.appendChild(tbd); + tbd = null; + } + if (o.refresh) { + tbd = document.createElement("td"); + $(tbd).append(" ").css({border:"none",padding:"0px"}); + trd.appendChild(tbd); + tbd = document.createElement("td"); + tbd.title = o.refreshtitle || ""; + var dirtycell = ($(elem)[0] == $t.p.pager[0] ) ? true : false; + $(tbd).append("
    "+o.refreshtext+" 
    ") + .css("cursor","pointer") + .addClass("nav-button") + .click(function(){ + $t.p.search = false; + switch (o.refreshstate) { + case 'firstpage': + $t.p.page=1; + $($t).trigger("reloadGrid"); + break; + case 'current': + var sr = $t.p.multiselect===true ? selarrrow : $t.p.selrow; + $($t).setGridParam({gridComplete: function() { + if($t.p.multiselect===true) { + if(sr.length>0) { + for(var i=0;i" : " "; + $(tbd).append("
    "+im+""+p.caption+" 
    ") + .css("cursor","pointer") + .addClass("nav-button") + .click(function(e){ + if (typeof p.onClickButton == 'function') { p.onClickButton(); } + e.stopPropagation(); + return false; + }) + .hover( + function () { + $(this).addClass("nav-hover"); + }, + function () { + $(this).removeClass("nav-hover"); + } + ); + if(p.position != 'first') { + trd.appendChild(tbd); + } else { + $(trd).prepend(tbd); + $(trd).prepend(tbd1); + } + tbd=null;tbd1=null; + } + }); + }, + GridToForm : function( rowid, formid ) { + return this.each(function(){ + var $t = this; + if (!$t.grid) { return; } + var rowdata = $($t).getRowData(rowid); + if (rowdata) { + for(var i in rowdata) { + if ( $("[name="+i+"]",formid).is("input:radio") ) { + $("[name="+i+"]",formid).each( function() { + if( $(this).val() == rowdata[i] ) { + $(this).attr("checked","checked"); + } else { + $(this).attr("checked",""); + } + }); + } else { + // this is very slow on big table and form. + $("[name="+i+"]",formid).val(rowdata[i]); + } + } + } + }); + }, + FormToGrid : function(rowid, formid){ + return this.each(function() { + var $t = this; + if(!$t.grid) { return; } + var fields = $(formid).serializeArray(); + var griddata = {}; + $.each(fields, function(i, field){ + griddata[field.name] = field.value; + }); + $($t).setRowData(rowid,griddata); + }); + } +}); +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.import.js b/site/vendors/js/jqGrid/js/grid.import.js new file mode 100644 index 0000000..83ecbd8 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.import.js @@ -0,0 +1,132 @@ +;(function($){ +/* + * jqGrid extension for constructing Grid Data from external file + * Tony Tomov tony@trirand.com + * http://trirand.com/blog/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ + $.fn.extend({ + jqGridImport : function(o) { + o = $.extend({ + imptype : "xml", // xml, json, xmlstring, jsonstring + impstring: "", + impurl: "", + mtype: "GET", + impData : {}, + xmlGrid :{ + config : "roots>grid", + data: "roots>rows" + }, + jsonGrid :{ + config : "grid", + data: "data" + } + }, o || {}); + return this.each(function(){ + var $t = this; + var XmlConvert = function (xml,o) { + var cnfg = $(o.xmlGrid.config,xml)[0]; + var xmldata = $(o.xmlGrid.data,xml)[0]; + if(xmlJsonClass.xml2json && JSON.parse) { + var jstr = xmlJsonClass.xml2json(cnfg," "); + var jstr = JSON.parse(jstr); + for(var key in jstr) { var jstr1=jstr[key];} + if(xmldata) { + // save the datatype + var svdatatype = jstr.grid.datatype; + jstr.grid.datatype = 'xmlstring'; + jstr.grid.datastr = xml; + $($t).jqGrid( jstr1 ).setGridParam({datatype:svdatatype}); + } else { + $($t).jqGrid( jstr1 ); + } + jstr = null;jstr1=null; + } else { + alert("xml2json or json.parse are not present"); + } + }; + var JsonConvert = function (jsonstr,o){ + if (jsonstr && typeof jsonstr == 'string' && JSON.parse) { + var json = JSON.parse(jsonstr); + var gprm = json[o.jsonGrid.config]; + var jdata = json[o.jsonGrid.data]; + if(jdata) { + var svdatatype = gprm.datatype; + gprm.datatype = 'jsonstring'; + gprm.datastr = jdata; + $($t).jqGrid( gprm ).setGridParam({datatype:svdatatype}); + } else { + $($t).jqGrid( gprm ); + } + } + }; + switch (o.imptype){ + case 'xml': + $.ajax({ + url:o.impurl, + type:o.mtype, + data: o.impData, + dataType:"xml", + complete: function(xml,stat) { + if(stat == 'success') { + XmlConvert(xml.responseXML,o); + xml=null; + } + } + }); + break; + case 'xmlstring' : + // we need to make just the conversion and use the same code as xml + if(o.impstring && typeof o.impstring == 'string') { + var xmld = xmlJsonClass.parseXml(o.impstring); + if(xmld) { + XmlConvert(xmld,o); + xmld = null; + } + } + break; + case 'json': + $.ajax({ + url:o.impurl, + type:o.mtype, + data: o.impData, + dataType:"json", + complete: function(json,stat) { + if(stat == 'success') { + JsonConvert(json.responseText,o ); + json=null; + } + } + }); + break; + case 'jsonstring' : + if(o.impstring && typeof o.impstring == 'string') { + JsonConvert(o.impstring,o ); + } + break; + } + }); + }, + jqGridExport : function(o) { + o = $.extend({ + exptype : "xmlstring" + }, o || {}); + var ret = null; + this.each(function () { + if(!this.grid) { return;} + var gprm = $(this).getGridParam(); + switch (o.exptype) { + case 'xmlstring' : + ret = xmlJsonClass.json2xml(gprm," "); + break; + case 'jsonstring' : + ret = JSON.stringify(gprm); + break; + } + }); + return ret; + } + }); +})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/grid.inlinedit.js b/site/vendors/js/jqGrid/js/grid.inlinedit.js new file mode 100644 index 0000000..e5d9c14 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.inlinedit.js @@ -0,0 +1,194 @@ +;(function($){ +/** + * jqGrid extension for manipulating Grid Data + * Tony Tomov tony@trirand.com + * http://trirand.com/blog/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.fn.extend({ +//Editing + editRow : function(rowid,keys,oneditfunc,succesfunc, url, extraparam, aftersavefunc,errorfunc) { + return this.each(function(){ + var $t = this, nm, tmp, editable, cnt=0, focus=null, svr=[], ind; + if (!$t.grid ) { return; } + var sz, ml,hc; + if( !$t.p.multiselect ) { + ind = $($t).getInd($t.rows,rowid); + if( ind === false ) {return;} + editable = $($t.rows[ind]).attr("editable") || "0"; + if (editable == "0") { + $('td',$t.rows[ind]).each( function(i) { + nm = $t.p.colModel[i].name; + hc = $t.p.colModel[i].hidden===true ? true : false; + try { + tmp = $.unformat(this,{colModel:$t.p.colModel[i]},i); + } catch (_) { + tmp = $(this).html(); + } + svr[nm]=tmp; + if ( nm !== 'cb' && nm !== 'subgrid' && $t.p.colModel[i].editable===true && !hc) { + if(focus===null) { focus = i; } + $(this).html(""); + var opt = $.extend($t.p.colModel[i].editoptions || {} ,{id:rowid+"_"+nm,name:nm}); + if(!$t.p.colModel[i].edittype) { $t.p.colModel[i].edittype = "text"; } + var elc = createEl($t.p.colModel[i].edittype,opt,tmp,$(this)); + $(elc).addClass("editable"); + $(this).append(elc); + //Agin IE + if($t.p.colModel[i].edittype == "select" && $t.p.colModel[i].editoptions.multiple===true && $.browser.msie) { + $(elc).width($(elc).width()); + } + cnt++; + } + }); + if(cnt > 0) { + svr['id'] = rowid; $t.p.savedRow.push(svr); + $($t.rows[ind]).attr("editable","1"); + $("td:eq("+focus+") input",$t.rows[ind]).focus(); + if(keys===true) { + $($t.rows[ind]).bind("keydown",function(e) { + if (e.keyCode === 27) { $($t).restoreRow(rowid);} + if (e.keyCode === 13) { + $($t).saveRow(rowid,succesfunc, url, extraparam, aftersavefunc,errorfunc); + return false; + } + e.stopPropagation(); + }); + } + if( $.isFunction(oneditfunc)) { oneditfunc(rowid); } + } + } + } + }); + }, + saveRow : function(rowid, succesfunc, url, extraparam, aftersavefunc,errorfunc) { + return this.each(function(){ + var $t = this, nm, tmp={}, tmp2={}, editable, fr, cv, ms, ind; + if (!$t.grid ) { return; } + ind = $($t).getInd($t.rows,rowid); + if(ind === false) {return;} + editable = $($t.rows[ind]).attr("editable"); + url = url ? url : $t.p.editurl; + if (editable==="1" && url) { + $("td",$t.rows[ind]).each(function(i) { + nm = $t.p.colModel[i].name; + if ( nm !== 'cb' && nm !== 'subgrid' && $t.p.colModel[i].editable===true) { + if( $t.p.colModel[i].hidden===true) { tmp[nm] = $(this).html(); } + else { + switch ($t.p.colModel[i].edittype) { + case "checkbox": + var cbv = ["Yes","No"]; + if($t.p.colModel[i].editoptions ) { + cbv = $t.p.colModel[i].editoptions.value.split(":"); + } + tmp[nm]= $("input",this).attr("checked") ? cbv[0] : cbv[1]; + break; + case 'text': + case 'password': + case 'textarea': + tmp[nm]= !$t.p.autoencode ? $("input, textarea",this).val() : htmlEncode($("input, textarea",this).val()); + break; + case 'select': + if(!$t.p.colModel[i].editoptions.multiple) { + tmp[nm] = $("select>option:selected",this).val(); + tmp2[nm] = $("select>option:selected", this).text(); + } else { + var sel = $("select",this); + tmp[nm] = $(sel).val(); + var selectedText = []; + $("select > option:selected",this).each( + function(i,selected){ + selectedText[i] = $(selected).text(); + } + ); + tmp2[nm] = selectedText.join(","); + } + break; + } + cv = checkValues(tmp[nm],i,$t); + if(cv[0] === false) { + cv[1] = tmp[nm] + " " + cv[1]; + return false; + } + } + } + }); + if (cv[0] === false){ + try { + info_dialog($.jgrid.errors.errcap,cv[1],$.jgrid.edit.bClose, $t.p.imgpath); + } catch (e) { + alert(cv[1]); + } + return; + } + if(tmp) { tmp["id"] = rowid; if(extraparam) { tmp = $.extend({},tmp,extraparam);} } + if(!$t.grid.hDiv.loading) { + $t.grid.hDiv.loading = true; + $("div.loading",$t.grid.hDiv).fadeIn("fast"); + if (url == 'clientArray') { + tmp = $.extend({},tmp, tmp2); + $($t).setRowData(rowid,tmp); + $($t.rows[ind]).attr("editable","0"); + for( var k=0;k<$t.p.savedRow.length;k++) { + if( $t.p.savedRow[k].id===rowid) {fr = k; break;} + } + if(fr >= 0) { $t.p.savedRow.splice(fr,1); } + if( $.isFunction(aftersavefunc) ) { aftersavefunc(rowid,res.responseText); } + } else { + $.ajax({url:url, + data: tmp, + type: "POST", + complete: function(res,stat){ + if (stat === "success"){ + var ret; + if( $.isFunction(succesfunc)) { ret = succesfunc(res);} + else ret = true; + if (ret===true) { + tmp = $.extend({},tmp, tmp2); + $($t).setRowData(rowid,tmp); + $($t.rows[ind]).attr("editable","0"); + for( var k=0;k<$t.p.savedRow.length;k++) { + if( $t.p.savedRow[k].id===rowid) {fr = k; break;} + }; + if(fr >= 0) { $t.p.savedRow.splice(fr,1); } + if( $.isFunction(aftersavefunc) ) { aftersavefunc(rowid,res.responseText); } + } else { $($t).restoreRow(rowid); } + } + }, + error:function(res,stat){ + if($.isFunction(errorfunc) ) { + errorfunc(res,stat); + } else { + alert("Error Row: "+rowid+" Result: " +res.status+":"+res.statusText+" Status: "+stat); + } + } + }); + } + $t.grid.hDiv.loading = false; + $("div.loading",$t.grid.hDiv).fadeOut("fast"); + $($t.rows[ind]).unbind("keydown"); + } + } + }); + }, + restoreRow : function(rowid) { + return this.each(function(){ + var $t= this, nm, fr,ind; + if (!$t.grid ) { return; } + ind = $($t).getInd($t.rows,rowid); + if(ind === false) {return;} + for( var k=0;k<$t.p.savedRow.length;k++) { + if( $t.p.savedRow[k].id===rowid) {fr = k; break;} + } + if(fr >= 0) { + $($t).setRowData(rowid,$t.p.savedRow[fr]); + $($t.rows[ind]).attr("editable","0"); + $t.p.savedRow.splice(fr,1); + } + }); + } +//end inline edit +}); +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-bg.js b/site/vendors/js/jqGrid/js/grid.locale-bg.js new file mode 100644 index 0000000..e902b17 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-bg.js @@ -0,0 +1,113 @@ +;(function($){ +/** + * jqGrid Bulgarian Translation + * Tony Tomov tony@trirand.com + * http://trirand.com/blog/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "запиÑ(а)", + loadtext: "Зареждам...", + pgtext : "от" +} +$.jgrid.search = { + caption: "ТърÑене...", + Find: "Ðамери", + Reset: "ИзчиÑти", + odata : ['равно', 'различно', 'по-малко', 'по-малко или=','по-голÑмо','по-голÑмо или =', 'започва Ñ','завършва Ñ','Ñъдържа' ] +}; +$.jgrid.edit = { + addCaption: "Ðов ЗапиÑ", + editCaption: "Ð ÐµÐ´Ð°ÐºÑ†Ð¸Ñ Ð—Ð°Ð¿Ð¸Ñ", + bSubmit: "Запиши", + bCancel: "Изход", + bClose: "Затвори", + processData: "Обработка...", + msg: { + required:"Полето е задължително", + number:"Въведете валидно чиÑло!", + minValue:"ÑтойноÑтта трÑбва да е по-голÑма или равна от", + maxValue:"ÑтойноÑтта трÑбва да е по-малка или равна от", + email: "не е валиден ел. адреÑ", + integer: "Въведете валидно цÑло чиÑло", + date: "Въведете валидна дата" + } +}; +$.jgrid.del = { + caption: "Изтриване", + msg: "Да Ð¸Ð·Ñ‚Ñ€Ð¸Ñ Ð»Ð¸ избраниÑÑ‚ запиÑ?", + bSubmit: "Изтрий", + bCancel: "Отказ", + processData: "Обработка..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "Ð ÐµÐ´Ð°ÐºÑ†Ð¸Ñ Ð¸Ð·Ð±Ñ€Ð°Ð½ запиÑ", + addtext:" ", + addtitle: "ДобавÑне нов запиÑ", + deltext: " ", + deltitle: "Изтриване избран запиÑ", + searchtext: " ", + searchtitle: "ТърÑене запиÑ(и)", + refreshtext: "", + refreshtitle: "Обнови таблица", + alertcap: "Предупреждение", + alerttext: "МолÑ, изберете запиÑ" +}; +// set column module +$.jgrid.col ={ + caption: "Колони", + bSubmit: "ЗапиÑ", + bCancel: "Изход" +}; +$.jgrid.errors = { + errcap : "Грешка", + nourl : "ÐÑма поÑочен url адреÑ", + norecords: "ÐÑма Ð·Ð°Ð¿Ð¸Ñ Ð·Ð° обработка", + model : "Модела не ÑъответÑтва на имената!" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: " ", defaulValue: 0}, + number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: 0}, + currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:" лв.", defaultValue: 0}, + date : { + dayNames: [ + "Ðед", "Пон", "Ð’Ñ‚", "Ср", "Чет", "Пет", "Съб", + "ÐеделÑ", "Понеделник", "Вторник", "СрÑда", "Четвъртък", "Петък", "Събота" + ], + monthNames: [ + "Ян", "Фев", "Март", "Ðпр", "Май", "Юни", "Юли", "Ðвг", "Сеп", "Окт", "Ðоем", "Дек", + "Януари", "Февруари", "Март", "Ðприл", "Май", "Юни", "Юли", "ÐвгуÑÑ‚", "Септември", "Октомври", "Ðоември", "Декември" + ], + AmPm : ["","","",""], + S: function (j) { + if(j==7 || j==8 || j== 27 || j== 28) { + return 'ми'; + } + return ['ви', 'ри', 'ти'][Math.min((j - 1) % 10, 2)]; + }, + srcformat: 'Y-m-d', + newformat: 'd/m/Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n/j/Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'show' +}; +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-bg1251.js b/site/vendors/js/jqGrid/js/grid.locale-bg1251.js new file mode 100644 index 0000000..595806c --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-bg1251.js @@ -0,0 +1,113 @@ +;(function($){ +/** + * jqGrid Bulgarian Translation + * Tony Tomov tony@trirand.com + * http://trirand.com/blog/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "çàïèñ(à)", + loadtext: "Çàðåæäàì...", + pgtext : "îò" +} +$.jgrid.search = { + caption: "Òúðñåíå...", + Find: "Íàìåðè", + Reset: "Èç÷èñòè", + odata : ['ðàâíî', 'ðàçëè÷íî', 'ïî-ìàëêî', 'ïî-ìàëêî èëè=','ïî-ãîëÿìî','ïî-ãîëÿìî èëè =', 'çàïî÷âà ñ','çàâúðøâà ñ','ñúäúðæà' ] +}; +$.jgrid.edit = { + addCaption: "Íîâ çàïèñ", + editCaption: "Ðåäàêöèÿ Çàïèñ", + bSubmit: "Çàïèøè", + bCancel: "Èçõîä", + bClose: "Çàòâîðè", + processData: "Îáðàáîòêà...", + msg: { + required:"Ïîëåòî å çàäúëæèòåëíî", + number:"Âúâåäåòå âàëèäíî ÷èñëî!", + minValue:"ñòîéíîñòòà òðÿáâà äà å ïî-ãîëÿìà èëè ðàâíà íà", + maxValue:"ñòîéíîñòòà òðÿáâà äà å ïî-ìàëêà èëè ðàâíà íà", + email: "íå å âàëèäåí e-mail àäðåñ", + integer: "Âúâåäåòå âàëèäíî öÿëî ÷èñëî", + date: "Âúâåäåòå âàëèäíà äàòà" + } +}; +$.jgrid.del = { + caption: "Èçòðèâàíå", + msg: "Äà èçòðèÿ ëè èçáðàíèÿ çàïèñ?", + bSubmit: "Èçòðèé", + bCancel: "Îòêàç", + processData: "Îáðàáîòêà..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "Ðåäàêöèÿ íà èçáðàí çàïèñ", + addtext:" ", + addtitle: "Äîáàâÿíå íà íîâ çàïèñ", + deltext: " ", + deltitle: "Èçòðèâíàå íà èçáðàí çàïèñ", + searchtext: " ", + searchtitle: "Òúðñåíå çàïèñ(è) ", + refreshtext: "", + refreshtitle: "Îáíîâè òàáëèöà", + alertcap: "Ïðåäóïðåæäåíèå", + alerttext: "Ìîëÿ, èçáåðåòå çàïèñ" +}; +// set column module +$.jgrid.col ={ + caption: "Êîëîíè", + bSubmit: "Çàïèñ", + bCancel: "Èçõîä" +}; +$.jgrid.errors = { + errcap : "Ãðåøêà", + nourl : "Íÿìà ïîñî÷åí URL àäðåñ", + norecords: "Íÿìà çàïèñ çà îáðàáîòêà", + model : "Ìîäåëúò íå ñúîòâåòñòâà íà èìåíàòà!" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: " ", defaulValue: 0}, + number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaultValue: 0}, + currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:" ??.", defaultValue: 0}, + date : { + dayNames: [ + "Íåä", "Ïîí", "Âò", "Ñð", "×åò", "Ïåò", "Ñúá", + "Íåäåëÿ", "Ïîíåäåëíèê", "Âòîðíèê", "Ñðÿäà", "×åòâúðòúê", "Ïåòúê", "Ñúáîòà" + ], + monthNames: [ + "ßí", "Ôåâ", "Ìàðò", "Àïð", "Ìàé", "Þíè", "Þëè", "Àâã", "Ñåï", "Îêò", "Íîåì", "Äåê", + "ßíóàðè", "Ôåâðóàðè", "Ìàðò", "Àïðèë", "Ìàé", "Þíè", "Þëè", "Àâãóñò", "Ñåïòåìâðè", "Îêòîìâðè", "Íîåìâðè", "Äåêåìâðè" + ], + AmPm : ["","","",""], + S: function (j) { + if(j==7 || j==8 || j== 27 || j== 28) { + return 'ìè'; + } + return ['âè', 'ðè', 'òè'][Math.min((j - 1) % 10, 2)]; + }, + srcformat: 'Y-m-d', + newformat: 'd/m/Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n/j/Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'show' +}; +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-cat.js b/site/vendors/js/jqGrid/js/grid.locale-cat.js new file mode 100644 index 0000000..e8ba8bf --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-cat.js @@ -0,0 +1,107 @@ +;(function($){ +/** + * jqGrid Catalan Translation + * Traducció jqGrid en Catatà per Faserline, S.L. - http://www.faserline.com + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "file(s)", + loadtext: "Carregant...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "Cerca...", + Find: "Cercar", + Reset: "Buidar", + odata : ['igual', 'no igual', 'menor', 'menor o igual', 'major', 'major o igual', 'comença amb', 'acaba amb','conté' ] +}; +$.jgrid.edit = { + addCaption: "Afegir registre", + editCaption: "Modificar registre", + bSubmit: "Enviar", + bCancel: "Cancelar", + bClose: "Tancar", + processData: "Processant...", + msg: { + required:"Camp obligatori", + number:"Introdueixi un nombre", + minValue:"El valor ha de ser major o igual que ", + maxValue:"El valor ha de ser menor o igual a ", + email: "no és una direcció de correu vàlida", + integer: "Introdueixi un valor enter", + date: "Introdueixi una data correcta " + } +}; +$.jgrid.del = { + caption: "Eliminar", + msg: "¿Desitja eliminar els registres seleccionats?", + bSubmit: "Eliminar", + bCancel: "Cancelar", + processData: "Processant..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "Modificar fila seleccionada", + addtext:" ", + addtitle: "Agregar nova fila", + deltext: " ", + deltitle: "Eliminar fila seleccionada", + searchtext: " ", + searchtitle: "Cercar informació", + refreshtext: "", + refreshtitle: "Refrescar taula", + alertcap: "Avís", + alerttext: "Seleccioni una fila" +}; +// setcolumns module +$.jgrid.col ={ + caption: "Mostrar/ocultar columnes", + bSubmit: "Enviar", + bCancel: "Cancelar" +}; +$.jgrid.errors = { + errcap : "Error", + nourl : "No s'ha especificat una URL", + norecords: "No hi ha dades per processar", + model : "Les columnes de noms són diferents de les columnes del model" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: ".", defaulValue: 0}, + number : {decimalSeparator:",", thousandsSeparator: ".", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:",", thousandsSeparator: ".", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "Dg", "Dl", "Dt", "Dc", "Dj", "Dv", "Ds", + "Diumenge", "Dilluns", "Dimarts", "Dimecres", "Dijous", "Divendres", "Dissabte" + ], + monthNames: [ + "Gen", "Febr", "Març", "Abr", "Maig", "Juny", "Jul", "Ag", "Set", "Oct", "Nov", "Des", + "Gener", "Febrer", "Març", "Abril", "Maig", "Juny", "Juliol", "Agost", "Setembre", "Octubre", "Novembre", "Desembre" + ], + AmPm : ["am","pm","AM","PM"], + S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, + srcformat: 'Y-m-d', + newformat: 'd-m-Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n/j/Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'show' +}; +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-cs.js b/site/vendors/js/jqGrid/js/grid.locale-cs.js new file mode 100644 index 0000000..cbb91a9 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-cs.js @@ -0,0 +1,113 @@ +;(function($){ +/** + * jqGrid Czech Translation + * Pavel Jirak pavel.jirak@jipas.cz + * http://trirand.com/blog/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "Řádek(ů)", + loadtext: "NaÄítám...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "Vyhledávám...", + Find: "Hledat", + Reset: "Reset", + odata : ['rovno', 'není rovno', 'menší', 'menší nebo rovno', 'vÄ›tší', 'vÄ›tší nebo rovno', 'zaÄíná na', 'konÄí na', 'obsahuje' ] +}; +$.jgrid.edit = { + addCaption: "PÅ™idat záznam", + editCaption: "Editace záznamu", + bSubmit: "Uložit", + bCancel: "Storno", + bClose: "Zavřít", + processData: "Zpracovávám...", + msg: { + required:"Pole je vyžadováno", + number:"Prosím, vložte validní Äíslo", + minValue:"hodnota musí být vÄ›tší než nebo rovná ", + maxValue:"hodnota musí být menší než nebo rovná ", + email: "není validní e-mail", + integer: "Prosím, vložte celé Äíslo", + date: "Prosím, vložte validní datum" + } +}; +$.jgrid.del = { + caption: "Smazat", + msg: "Smazat vybraný(é) záznam(y)?", + bSubmit: "Smazat", + bCancel: "Storno", + processData: "Zpracovávám..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "Editovat vybraný řádek", + addtext:" ", + addtitle: "PÅ™idat nový řádek", + deltext: " ", + deltitle: "Smazat vybraný záznam ", + searchtext: " ", + searchtitle: "Najít záznamy", + refreshtext: "", + refreshtitle: "Obnovit tabulku", + alertcap: "Varování", + alerttext: "Prosím, vyberte řádek" +}; +// setcolumns module +$.jgrid.col ={ + caption: "Zobrazit/Skrýt sloupce", + bSubmit: "Uložit", + bCancel: "Storno" +}; +$.jgrid.errors = { + errcap : "Chyba", + nourl : "Není nastavena url", + norecords: "Žádné záznamy ke zpracování", + model : "Length colNames <> colModel!" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: " ", defaulValue: 0}, + number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "Ne", "Po", "Út", "St", "ÄŒt", "Pá", "So", + "NedÄ›le", "PondÄ›lí", "Úterý", "StÅ™eda", "ÄŒtvrtek", "Pátek", "Sobota" + ], + monthNames: [ + "Led", "Úno", "BÅ™e", "Dub", "KvÄ›", "ÄŒer", "ÄŒvc", "Srp", "Zář", "Říj", "Lis", "Pro", + "Leden", "Únor", "BÅ™ezen", "Duben", "KvÄ›ten", "ÄŒerven", "ÄŒervenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec" + ], + AmPm : ["do","od","DO","OD"], + S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, + srcformat: 'Y-m-d', + newformat: 'd/m/Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n/j/Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'show', + addParam : '' +}; +// US +// GB +// CA +// AU +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-de.js b/site/vendors/js/jqGrid/js/grid.locale-de.js new file mode 100644 index 0000000..18e1bdc --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-de.js @@ -0,0 +1,111 @@ +;(function($){ +/** + * jqGrid German Translation + * Version 1.0.0 (developed for jQuery Grid 3.3.1) + * Olaf Klöppel opensource@blue-hit.de + * http://blue-hit.de/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ + +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "Zeile(n)", + loadtext: "Lädt...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "Suche...", + Find: "Finden", + Reset: "Zurücksetzen", + odata : ['gleich', 'ungleich', 'kleiner', 'kleiner oder gleich','größer','größer oder gleich', 'beginnt mit','endet mit','beinhaltet' ] +}; +$.jgrid.edit = { + addCaption: "Datensatz hinzufügen", + editCaption: "Datensatz bearbeiten", + bSubmit: "Speichern", + bCancel: "Abbrechen", + bClose: "Schließen", + processData: "Verarbeitung läuft...", + msg: { + required:"Feld ist erforderlich", + number: "Bitte geben Sie eine Zahl ein", + minValue:"Wert muss größer oder gleich sein, als ", + maxValue:"Wert muss kleiner oder gleich sein, als ", + email: "ist keine valide E-Mail Adresse", + integer: "Bitte geben Sie eine Ganzzahl ein", + date: "Please, enter valid date value" + } +}; +$.jgrid.del = { + caption: "Löschen", + msg: "Ausgewählte Datensätze löschen?", + bSubmit: "Löschen", + bCancel: "Abbrechen", + processData: "Verarbeitung läuft..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "Ausgewählten Zeile editieren", + addtext:" ", + addtitle: "Neuen Zeile einfügen", + deltext: " ", + deltitle: "Ausgewählte Zeile löschen", + searchtext: " ", + searchtitle: "Datensatz finden", + refreshtext: "", + refreshtitle: "Tabelle neu laden", + alertcap: "Warnung", + alerttext: "Bitte Zeile auswählen" +}; +// setcolumns module +$.jgrid.col ={ + caption: "Spalten anzeigen/verbergen", + bSubmit: "Speichern", + bCancel: "Abbrechen" +}; +$.jgrid.errors = { + errcap : "Fehler", + nourl : "Keine URL angegeben", + norecords: "Keine Datensätze zum verarbeiten", + model : "Length of colNames <> colModel!" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: " ", defaulValue: 0}, + number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat", + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" + ], + monthNames: [ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" + ], + AmPm : ["am","pm","AM","PM"], + S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, + srcformat: 'Y-m-d', + newformat: 'd/m/Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n/j/Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'show' +}; +})(jQuery); + diff --git a/site/vendors/js/jqGrid/js/grid.locale-dk.js b/site/vendors/js/jqGrid/js/grid.locale-dk.js new file mode 100644 index 0000000..064991b --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-dk.js @@ -0,0 +1,109 @@ +;(function($){ +/** + * jqGrid Danish Translation + * Kaare Rasmussen kjs@jasonic.dk + * http://jasonic.dk/blog + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "Række(r)", + loadtext: "Indlæser...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "Søg...", + Find: "Find", + Reset: "Nulstil", + odata : ['lig med', 'forskellig fra', 'mindre end', 'mindre end eller lig med','større end',' større end eller lig med', 'starter med','slutter med','indeholder' ] +}; +$.jgrid.edit = { + addCaption: "Tilføj", + editCaption: "Ret", + bSubmit: "Send", + bCancel: "Annuller", + bClose: "Luk", + processData: "Behandler...", + msg: { + required:"Felt er nødvendigt", + number:"Indtast venligst et validt tal", + minValue:"værdi skal være større end eller lig med", + maxValue:"værdi skal være mindre end eller lig med", + email: "er ikke en valid email", + integer: "Indtast venligst et validt heltalt", + date: "Indtast venligst en valid datoværdi" + } +}; +$.jgrid.del = { + caption: "Slet", + msg: "Slet valgte række(r)?", + bSubmit: "Slet", + bCancel: "Annuller", + processData: "Behandler..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "Rediger valgte række", + addtext:" ", + addtitle: "Tilføj ny række", + deltext: " ", + deltitle: "Slet valgte række", + searchtext: " ", + searchtitle: "Find poster", + refreshtext: "", + refreshtitle: "Indlæs igen", + alertcap: "Advarsel", + alerttext: "Vælg venligst række" +}; +// setcolumns module +$.jgrid.col ={ + caption: "Vis/skjul kolonner", + bSubmit: "Send", + bCancel: "Annuller" +}; +$.jgrid.errors = { + errcap : "Fejl", + nourl : "Ingel url valgt", + norecords: "Ingen poster at behandle", + model : "colNames og colModel har ikke samme længde!" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: " ", defaulValue: 0}, + number : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "Søn", "Man", "Tirs", "Ons", "Tors", "Fre", "Lør", + "Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag" + ], + monthNames: [ + "Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec", + "Januar", "Februar", "Marts", "April", "Maj", "Juni", "Juli", "August", "September", "Oktober", "November", "December" + ], + AmPm : ["","","",""], + S: function (j) {return '.'}, + srcformat: 'Y-m-d', + newformat: 'd/m/Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "j/n/Y", + LongDate: "l d. F Y", + FullDateTime: "l d F Y G:i:s", + MonthDay: "d. F", + ShortTime: "G:i", + LongTime: "G:i:s", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'show' +}; +// DK +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-el.js b/site/vendors/js/jqGrid/js/grid.locale-el.js new file mode 100644 index 0000000..e307e10 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-el.js @@ -0,0 +1,112 @@ +;(function($){ +/** + * jqGrid Greek (el) Translation + * Alex Cicovic + * http://www.alexcicovic.com + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "ΕγγÏαφές", + loadtext: "ΦόÏτωση...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "Αναζήτηση...", + Find: "ΕÏÏεση", + Reset: "ΕπαναφοÏά", + odata : ['ίσο', 'άνισο', 'μικÏότεÏο από', 'μικÏότεÏο ή ίσο','μεγαλÏτεÏο από','μεγαλÏτεÏο ή ίσο', 'ξεκινά με','τελειώνει με','εμπεÏιέχει' ] +}; +$.jgrid.edit = { + addCaption: "Εισαγωγή ΕγγÏαφής", + editCaption: "ΕπεξεÏγασία ΕγγÏαφής", + bSubmit: "ΚαταχώÏηση", + bCancel: "ΆκυÏο", + bClose: "Κλείσιμο", + processData: "Υπό επεξεÏγασία...", + msg: { + required:"Το πεδίο είναι απαÏαίτητο", + number:"Το πεδίο δέχεται μόνο αÏιθμοÏÏ‚", + minValue:"Η τιμή Ï€Ïέπει να είναι μεγαλÏτεÏη ή ίση του ", + maxValue:"Η τιμή Ï€Ïέπει να είναι μικÏότεÏη ή ίση του ", + email: "Η διεÏθυνση e-mail δεν είναι έγκυÏη", + integer: "Το πεδίο δέχεται μόνο ακέÏαιους αÏιθμοÏÏ‚", + date: "Ή ημεÏομηνία δεν είναι έγκυÏη" + } +}; +$.jgrid.del = { + caption: "ΔιαγÏαφή", + msg: "ΔιαγÏαφή των επιλεγμένων εγγÏαφών;", + bSubmit: "Îαι", + bCancel: "ΆκυÏο", + processData: "Υπό επεξεÏγασία..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "ΕπεξεÏγασία επιλεγμένης εγγÏαφής", + addtext:" ", + addtitle: "Εισαγωγή νέας εγγÏαφής", + deltext: " ", + deltitle: "ΔιαγÏαφή επιλεγμένης εγγÏαφής", + searchtext: " ", + searchtitle: "ΕÏÏεση ΕγγÏαφών", + refreshtext: "", + refreshtitle: "Ανανέωση Πίνακα", + alertcap: "ΠÏοσοχή", + alerttext: "Δεν έχετε επιλέξει εγγÏαφή" +}; +// setcolumns module +$.jgrid.col ={ + caption: "Εμφάνιση / ΑπόκÏυψη Στηλών", + bSubmit: "ΟΚ", + bCancel: "ΆκυÏο" +}; +$.jgrid.errors = { + errcap : "Σφάλμα", + nourl : "Δεν έχει δοθεί διεÏθυνση χειÏÎ¹ÏƒÎ¼Î¿Ï Î³Î¹Î± τη συγκεκÏιμένη ενέÏγεια", + norecords: "Δεν υπάÏχουν εγγÏαφές Ï€Ïος επεξεÏγασία", + model : "Άνισος αÏιθμός πεδίων colNames/colModel!" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: " ", defaulValue: 0}, + number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "ΚυÏ", "Δευ", "ΤÏι", "Τετ", "Πεμ", "ΠαÏ", "Σαβ", + "ΚυÏιακή", "ΔευτέÏα", "ΤÏίτη", "ΤετάÏτη", "Πέμπτη", "ΠαÏασκευή", "Σάββατο" + ], + monthNames: [ + "Ιαν", "Φεβ", "ΜαÏ", "ΑπÏ", "Μαι", "Ιουν", "Ιουλ", "Αυγ", "Σεπ", "Οκτ", "Îοε", "Δεκ", + "ΙανουάÏιος", "ΦεβÏουάÏιος", "ΜάÏτιος", "ΑπÏίλιος", "Μάιος", "ΙοÏνιος", "ΙοÏλιος", "ΑÏγουστος", "ΣεπτέμβÏιος", "ΟκτώβÏιος", "ÎοέμβÏιος", "ΔεκέμβÏιος" + ], + AmPm : ["πμ","μμ","ΠΜ","ΜΜ"], + S: function (j) {return j == 1 || j > 1 ? ['η'][Math.min((j - 1) % 10, 3)] : ''}, + srcformat: 'Y-m-d', + newformat: 'd/m/Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n/j/Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', // showlink + showAction: 'show' // showlink +}; +// US +// GB +// CA +// AU +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-en.js b/site/vendors/js/jqGrid/js/grid.locale-en.js new file mode 100644 index 0000000..e0dbfc2 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-en.js @@ -0,0 +1,120 @@ +;(function($){ +/** + * jqGrid English Translation + * Tony Tomov tony@trirand.com + * http://trirand.com/blog/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "Row(s)", + loadtext: "Loading...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "Search...", + Find: "Find", + Reset: "Reset", + odata : ['equal', 'not equal', 'less', 'less or equal','greater','greater or equal', 'begins with','ends with','contains' ] +}; +$.jgrid.edit = { + addCaption: "Add Record", + editCaption: "Edit Record", + bSubmit: "Submit", + bCancel: "Cancel", + bClose: "Close", + processData: "Processing...", + msg: { + required:"Field is required", + number:"Please, enter valid number", + minValue:"value must be greater than or equal to ", + maxValue:"value must be less than or equal to", + email: "is not a valid e-mail", + integer: "Please, enter valid integer value", + date: "Please, enter valid date value" + } +}; +$.jgrid.view = { + caption: "View Record", + bClose: "Close" +} +$.jgrid.del = { + caption: "Delete", + msg: "Delete selected record(s)?", + bSubmit: "Delete", + bCancel: "Cancel", + processData: "Processing..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "Edit selected row", + addtext:" ", + addtitle: "Add new row", + deltext: " ", + deltitle: "Delete selected row", + searchtext: " ", + searchtitle: "Find records", + refreshtext: "", + refreshtitle: "Reload Grid", + alertcap: "Warning", + alerttext: "Please, select row", + viewtext: " ", + viewtitle: "View selected row" +}; +// setcolumns module +$.jgrid.col ={ + caption: "Show/Hide Columns", + bSubmit: "Submit", + bCancel: "Cancel" +}; +$.jgrid.errors = { + errcap : "Error", + nourl : "No url is set", + norecords: "No records to process", + model : "Length of colNames <> colModel!" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: " ", defaulValue: 0}, + number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat", + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" + ], + monthNames: [ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" + ], + AmPm : ["am","pm","AM","PM"], + S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, + srcformat: 'Y-m-d', + newformat: 'd/m/Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n/j/Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'show', + addParam : '', + checkbox : {disabled:true} +}; +// US +// GB +// CA +// AU +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-fa.js b/site/vendors/js/jqGrid/js/grid.locale-fa.js new file mode 100644 index 0000000..674add6 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-fa.js @@ -0,0 +1,110 @@ +;(function($){ +/** + * jqGrid Persian Translation + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "رديÙ", + loadtext: "بارگزاري...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "جستجو...", + Find: "ÙŠØ§ÙØªÙ‡ ها", + Reset: "نتايج", + odata : ['مساوي', 'نا مساوي', 'کمتر از', 'کمتر يا مساوي','بزرگتر','بزرگتر يا مساوي', 'شروع با','خاتمه با','شامل' ] +}; +$.jgrid.edit = { + addCaption: "اضاÙÙ‡ کردن رکورد", + editCaption: "ويرايش رکورد", + bSubmit: "ثبت", + bCancel: "انصراÙ", + bClose: "بستن", + processData: "پردازش...", + msg: { + required:"Ùيلدها بايد ختما پر شوند", + number:"Ù„Ø·ÙØ§ عدد وعتبر وارد کنيد", + minValue:"مقدار وارد شده بايد بزرگتر يا مساوي با", + maxValue:"مقدار وارد شده بايد کوچکتر يا مساوي", + email: "پست الکترونيک وارد شده معتبر نيست", + integer: "Ù„Ø·ÙØ§ ÙŠÚ© عدد صحيح وارد کنيد", + date: "Ù„Ø·ÙØ§ ÙŠÚ© تاريخ معتبر وارد کنيد" + } +}; +$.jgrid.del = { + caption: "حذÙ", + msg: "از حذ٠گزينه هاي انتخاب شده مطمئن هستيد؟", + bSubmit: "حذÙ", + bCancel: "ابطال", + processData: "پردازش..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "ويرايش ردي٠هاي انتخاب شده", + addtext:" ", + addtitle: "Ø§ÙØ²ÙˆØ¯Ù† ردي٠جديد", + deltext: " ", + deltitle: "حذ٠ردب٠هاي انتخاب شده", + searchtext: " ", + searchtitle: "جستجوي رديÙ", + refreshtext: "", + refreshtitle: "بازيابي مجدد ØµÙØ­Ù‡", + alertcap: "اخطار", + alerttext: "Ù„Ø·ÙØ§ ÙŠÚ© ردي٠انتخاب کنيد" +}; +// setcolumns module +$.jgrid.col ={ + caption: "نمايش/عدم نمايش ستون", + bSubmit: "ثبت", + bCancel: "انصراÙ" +}; +$.jgrid.errors = { + errcap : "خطا", + nourl : "هيچ آدرسي تنظيم نشده است", + norecords: "هيچ رکوردي براي پردازش موجود نيست", + model : "طول نام ستون ها محال٠ستون هاي مدل مي باشد!" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: " ", defaulValue: 0}, + number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "ÙŠÚ©", "دو", "سه", "چهار", "پنج", "جمع", "شنب", + "يکشنبه", "دوشنبه", "سه شنبه", "چهارشنبه", "پنجشنبه", "جمعه", "شنبه" + ], + monthNames: [ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + "ژانويه", "Ùوريه", "مارس", "آوريل", "مه", "ژوئن", "ژوئيه", "اوت", "سپتامبر", "اکتبر", "نوامبر", "December" + ], + AmPm : ["ب.ظ","ب.ظ","Ù‚.ظ","Ù‚.ظ"], + S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, + srcformat: 'Y-m-d', + newformat: 'd/m/Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n/j/Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'نمايش' +}; +// US +// GB +// CA +// AU +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-fi.js b/site/vendors/js/jqGrid/js/grid.locale-fi.js new file mode 100644 index 0000000..ae0218a --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-fi.js @@ -0,0 +1,109 @@ +;(function($){ +/** + * jqGrid (fi) Finnish Translation + * Jukka Inkeri awot.fi + * http://awot.fi + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "Rivejä", + loadtext: "Haetaan...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "Etsi...", + Find: "Etsi", + Reset: "Tyhjää", + odata : ['=', '<>', '<', '<=','>','>=', 'alkaa','loppuu','sisätää' ] +}; +$.jgrid.edit = { + addCaption: "Uusi rivi", + editCaption: "Muokkaa rivi", + bSubmit: "OK", + bCancel: "Peru", + bClose: "Sulje", + processData: "Suoritetaan...", + msg: { + required:"pakollinen", + number:"Anna kelvollinen nro", + minValue:"arvo oltava >= ", + maxValue:"arvo oltava <= ", + email: "virheellinen sposti ", + integer: "Anna kelvollinen kokonaisluku", + date: "Anna kelvollinen pvm" + } +}; +$.jgrid.del = { + caption: "Poista", + msg: "Poista valitut rivi(t)?", + bSubmit: "Poista", + bCancel: "Peru", + processData: "Suoritetaan..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "Muokkaa valittu rivi", + addtext:" ", + addtitle: "Uusi rivi", + deltext: " ", + deltitle: "Poista valittu rivi", + searchtext: " ", + searchtitle: "Etsi tietoja", + refreshtext: "", + refreshtitle: "Lataa uudelleen", + alertcap: "Varoitus", + alerttext: "Valitse rivi" +}; +// setcolumns module +$.jgrid.col ={ + caption: "Nayta/Piilota sarakkeet", + bSubmit: "OK", + bCancel: "Peru" +}; +$.jgrid.errors = { + errcap : "Virhe", + nourl : "url asettamatta", + norecords: "Ei muokattavia tietoja", + model : "Pituus colNames <> colModel!" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: "", defaulValue: 0}, + number : {decimalSeparator:",", thousandsSeparator: "", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:",", thousandsSeparator: "", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "Su", "Ma", "Ti", "Ke", "To", "Pe", "La", + "Sunnuntai", "Maanantai", "Tiista", "Keskiviikko", "Torstai", "Perjantai", "Lauantai" + ], + monthNames: [ + "Tam", "Hel", "Maa", "Huh", "Tou", "Kes", "Hei", "Elo", "Syy", "Lok", "Mar", "Jou", + "Tammikuu", "Helmikuu", "Maaliskuu", "Huhtikuu", "Toukokuu", "Kesäkuu", "Heinäkuu", "Elokuu", "Syyskuu", "Lokakuu", "Marraskuu", "Joulukuu" + ], + AmPm : ["am","pm","AM","PM"], + S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, + srcformat: 'Y-m-d', + newformat: 'd/m/Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "d.m.Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'nayta' +}; +// FI +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-fr.js b/site/vendors/js/jqGrid/js/grid.locale-fr.js new file mode 100644 index 0000000..b09ba65 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-fr.js @@ -0,0 +1,128 @@ +;(function($){ +/** + * jqGrid French Translation + * Tony Tomov tony@trirand.com + * http://trirand.com/blog/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "Ligne(s)", + loadtext: "Chargement...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "Recherche...", + Find: "Chercher", + Reset: "Annuler", + odata : ['égal', 'différent', 'inférieur', 'inférieur ou égal','supérieur','supérieur ou égal', 'débute par','termine par','contient'] +}; +$.jgrid.edit = { + addCaption: "Ajouter", + editCaption: "Editer", + bSubmit: "Valider", + bCancel: "Annuler", + bClose: "Fermer", + processData: "Traitement...", + msg: { + required:"Champ obligatoire", + number:"Saisissez un nombre valide", + minValue:"La valeur doit être supérieure ou égal à 0 ", + maxValue:"La valeur doit être inférieure ou égal à 0", + email: "n'est pas un email valide", + integer: "Saisissez un entier valide", + date: "Saisissez une date valide" + } +}; +$.jgrid.del = { + caption: "Supprimer", + msg: "Supprimer les enregistrements sélectionnés ?", + bSubmit: "Supprimer", + bCancel: "Annuler", + processData: "Traitement..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "Editer la ligne sélectionnée", + addtext:" ", + addtitle: "Ajouter une ligne", + deltext: " ", + deltitle: "Supprimer la ligne sélectionnée", + searchtext: " ", + searchtitle: "Chercher un enregistrement", + refreshtext: "", + refreshtitle: "Recharger le tableau", + alertcap: "Avertissement", + alerttext: "Veuillez sélectionner une ligne" +}; +// setcolumns module +$.jgrid.col ={ + caption: "Afficher/Masquer les colonnes", + bSubmit: "Valider", + bCancel: "Annuler" +}; +$.jgrid.errors = { + errcap : "Erreur", + nourl : "Aucune url paramétrée", + norecords: "Aucun enregistrement à traiter", + model : "Nombre de titres (colNames) <> Nombre de données (colModel)!" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: " ", defaulValue: 0}, + number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", + "Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi" + ], + monthNames: [ + "Jan", "Fev", "Mar", "Avr", "Mai", "Jui", "Jul", "Aou", "Sep", "Oct", "Nov", "Dec", + "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Saptembre", "Octobre", "Novembre", "Décembre" + ], + AmPm : ["am","pm","AM","PM"], + S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, + /* + // Original version + srcformat: 'Y-m-d', + newformat: 'd/m/Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n/j/Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + */ + srcformat: 'Y-m-d', + newformat: 'd/m/Y', + masks : { + ISO8601Long:"d-m-Y H:i:s", + ISO8601Short:"d-m-Y", + ShortDate: "j/n/Y", + LongDate: "l d F Y", + FullDateTime: "l d F Y, G:i:s", + MonthDay: "d F", + ShortTime: "G:i", + LongTime: "G:i:s", + SortableDateTime: "d-m-Y\\TH:i:s", + UniversalSortableDateTime: "d-m-Y H:i:sO", + YearMonth: "F Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'show' +}; +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-is.js b/site/vendors/js/jqGrid/js/grid.locale-is.js new file mode 100644 index 0000000..aef8389 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-is.js @@ -0,0 +1,106 @@ +;(function($){ +/** + * jqGrid Icelandic Translation + * jtm@hi.is Univercity of Iceland + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "Raðir(s)", + loadtext: "Hleður...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "Leita...", + Find: "Leita", + Reset: "Endursetja", + odata : ['sama og', 'ekki sama og', 'minna en', 'minna en eða jafnt og','meira en','meira en eða jafnt og', 'byrjar á','endar á','inniheldur' ] +}; +$.jgrid.edit = { + addCaption: "Add Record", + editCaption: "Edit Record", + bSubmit: "Vista", + bCancel: "Hætta við", + bClose: "Loka", + processData: "Vinnur...", + msg: { + required:"Reitur er nauðsynlegur", + number:"Vinsamlega settu inn tölu", + minValue:"gildi verður að vera meira en eða jafnt og ", + maxValue:"gildi verður að vera minna en eða jafnt og ", + email: "er ekki löglegt email", + integer: "Vinsamlega settu inn tölu" + } +}; +$.jgrid.del = { + caption: "Eyða", + msg: "Eyða völdum færslum ?", + bSubmit: "Eyða", + bCancel: "Hætta við", + processData: "Vinnur..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "Breyta færslu", + addtext:" ", + addtitle: "Ný færsla", + deltext: " ", + deltitle: "Eyða færslu", + searchtext: " ", + searchtitle: "Leita", + refreshtext: "", + refreshtitle: "Endurhlaða", + alertcap: "Viðvörun", + alerttext: "Vinsamlega veldu færslu" +}; +// setcolumns module +$.jgrid.col ={ + caption: "Sýna / fela dálka", + bSubmit: "Vista", + bCancel: "Hætta við" +}; +$.jgrid.errors = { + errcap : "Villa", + nourl : "Vantar slóð", + norecords: "Engar færslur valdar", + model : "Length of colNames <> colModel!" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: " ", defaulValue: 0}, + number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat", + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" + ], + monthNames: [ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" + ], + AmPm : ["am","pm","AM","PM"], + S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, + srcformat: 'Y-m-d', + newformat: 'd/m/Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n/j/Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'show' +}; +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-it.js b/site/vendors/js/jqGrid/js/grid.locale-it.js new file mode 100644 index 0000000..e20c3db --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-it.js @@ -0,0 +1,107 @@ +;(function($){ +/** + * jqGrid Italian Translation + * Vincenzo Solomita vincenzosolomita@gmail.com + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "Record", + loadtext: "Caricamento...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "Ricerca...", + Find: "Cerca", + Reset: "Pulisci", + odata : ['uguale', 'diverso', 'minore', 'minore o uguale','maggiore','maggiore o uguale', 'inizia con','finisce con','contiene' ] +}; +$.jgrid.edit = { + addCaption: "Aggiungi Record", + editCaption: "Modifica Record", + bSubmit: "Invia", + bCancel: "Annulla", + bClose: "Chiudi", + processData: "In elaborazione...", + msg: { + required:"Campo richiesto", + number:"Per favore, inserisci un valore valido", + minValue:"il valore deve essere maggiore o uguale a ", + maxValue:"il valore deve essere minore o uguale a", + email: "e-mail non corretta", + integer: "Please, enter valid integer value", + date: "Please, enter valid date value" + } +}; +$.jgrid.del = { + caption: "Cancella", + msg: "Cancellare record selezionato/i?", + bSubmit: "Cancella", + bCancel: "Annulla", + processData: "In elaborazione..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "Modifica record selezionato", + addtext:" ", + addtitle: "Aggiungi nuovo record", + deltext: " ", + deltitle: "Cancella record selezionato", + searchtext: " ", + searchtitle: "Ricerca record", + refreshtext: "", + refreshtitle: "Aggiorna griglia", + alertcap: "Attenzione", + alerttext: "Per favore, seleziona un record" +}; +// setcolumns module +$.jgrid.col ={ + caption: "Mostra/Nascondi Colonne", + bSubmit: "Invia", + bCancel: "Annulla" +}; +$.jgrid.errors = { + errcap : "Errore", + nourl : "Url non settata", + norecords: "Nessun record da elaborare", + model : "Length of colNames <> colModel!" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: " ", defaulValue: 0}, + number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat", + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" + ], + monthNames: [ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" + ], + AmPm : ["am","pm","AM","PM"], + S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, + srcformat: 'Y-m-d', + newformat: 'd/m/Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n/j/Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'show' +}; +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-jp.js b/site/vendors/js/jqGrid/js/grid.locale-jp.js new file mode 100644 index 0000000..24713d1 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-jp.js @@ -0,0 +1,113 @@ +;(function($){ +/** + * jqGrid Japanese Translation + * OKADA Yoshitada okada.dev@sth.jp + * http://trirand.com/blog/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "\u884c", + loadtext: "\u8aad\u307f\u8fbc\u307f\u4e2d...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "\u691c\u7d22...", + Find: "\u691c\u7d22", + Reset: "\u30ea\u30bb\u30c3\u30c8", + odata : ['=', '!=', '<', '<=','>','>=', '\u6b21\u306e\u8a00\u8449\u3067\u59cb\u307e\u308b','\u6b21\u306e\u8a00\u8449\u3067\u7d42\u308f\u308b','\u6b21\u306e\u8a00\u8449\u3092\u542b\u3080' ] +}; +$.jgrid.edit = { + addCaption: "\u30ec\u30b3\u30fc\u30c9\u8ffd\u52a0", + editCaption: "\u30ec\u30b3\u30fc\u30c9\u7de8\u96c6", + bSubmit: "\u9001\u4fe1", + bCancel: "\u30ad\u30e3\u30f3\u30bb\u30eb", + bClose: "\u9589\u3058\u308b", + processData: "\u51e6\u7406\u4e2d...", + msg: { + required:"\u3053\u306e\u9805\u76ee\u306f\u5fc5\u9808\u3067\u3059\u3002", + number:"\u6b63\u3057\u3044\u6570\u5024\u3092\u5165\u529b\u3057\u3066\u4e0b\u3055\u3044\u3002", + minValue:"\u6b21\u306e\u5024\u4ee5\u4e0a\u3067\u5165\u529b\u3057\u3066\u4e0b\u3055\u3044\u3002", + maxValue:"\u6b21\u306e\u5024\u4ee5\u4e0b\u3067\u5165\u529b\u3057\u3066\u4e0b\u3055\u3044\u3002", + email: "e-mail\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002", + integer: "\u6b63\u3057\u3044\u6574\u6570\u5024\u3092\u5165\u529b\u3057\u3066\u4e0b\u3055\u3044\u3002", + date: "\u6b63\u3057\u3044\u5024\u3092\u5165\u529b\u3057\u3066\u4e0b\u3055\u3044\u3002" + } +}; +$.jgrid.del = { + caption: "\u524a\u9664", + msg: "\u9078\u629e\u3057\u305f\u30ec\u30b3\u30fc\u30c9\u3092\u524a\u9664\u3057\u307e\u3059\u304b\uff1f", + bSubmit: "\u524a\u9664", + bCancel: "\u30ad\u30e3\u30f3\u30bb\u30eb", + processData: "\u51e6\u7406\u4e2d..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "\u9078\u629e\u3057\u305f\u884c\u3092\u7de8\u96c6", + addtext:" ", + addtitle: "\u884c\u3092\u65b0\u898f\u8ffd\u52a0", + deltext: " ", + deltitle: "\u9078\u629e\u3057\u305f\u884c\u3092\u524a\u9664", + searchtext: " ", + searchtitle: "\u30ec\u30b3\u30fc\u30c9\u691c\u7d22", + refreshtext: "", + refreshtitle: "\u30b0\u30ea\u30c3\u30c9\u3092\u30ea\u30ed\u30fc\u30c9", + alertcap: "\u8b66\u544a", + alerttext: "\u884c\u3092\u9078\u629e\u3057\u3066\u4e0b\u3055\u3044\u3002" +}; +// setcolumns module +$.jgrid.col ={ + caption: "\u5217\u3092\u8868\u793a\uff0f\u96a0\u3059", + bSubmit: "\u9001\u4fe1", + bCancel: "\u30ad\u30e3\u30f3\u30bb\u30eb" +}; +$.jgrid.errors = { + errcap : "\u30a8\u30e9\u30fc", + nourl : "URL\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002", + norecords: "\u51e6\u7406\u5bfe\u8c61\u306e\u30ec\u30b3\u30fc\u30c9\u304c\u3042\u308a\u307e\u305b\u3093\u3002", + model : "colNames\u306e\u9577\u3055\u304ccolModel\u3068\u4e00\u81f4\u3057\u307e\u305b\u3093\u3002" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: " ", defaulValue: 0}, + number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "\u65e5", "\u6708", "\u706b", "\u6c34", "\u6728", "\u91d1", "\u571f", + "\u65e5", "\u6708", "\u706b", "\u6c34", "\u6728", "\u91d1", "\u571f" + ], + monthNames: [ + "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", + "1\u6708", "2\u6708", "3\u6708", "4\u6708", "5\u6708", "6\u6708", "7\u6708", "8\u6708", "9\u6708", "10\u6708", "11\u6708", "12\u6708" + ], + AmPm : ["am","pm","AM","PM"], + S: "\u756a\u76ee", + srcformat: 'Y-m-d', + newformat: 'd/m/Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n/j/Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: '\u8868\u793a', + addParam : '' +}; +// US +// GB +// CA +// AU +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-pl.js b/site/vendors/js/jqGrid/js/grid.locale-pl.js new file mode 100644 index 0000000..bc387a2 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-pl.js @@ -0,0 +1,108 @@ +;(function($){ +/** + * jqGrid Polish Translation + * Piotr Roznicki roznicki@o2.pl + * http://www.roznicki.prv.pl + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "Wiersz(y)", + loadtext: "Åadowanie...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "Wyszukiwanie...", + Find: "Szukaj", + Reset: "Czyść", + odata : ['dokÅ‚adnie', 'różne od', 'mniejsze od', 'mniejsze lub różne','wiÄ™ksze od','wiÄ™ksze lub różne', 'zacznij od','zakoÅ„cz na','zawiera' ] +}; +$.jgrid.edit = { + addCaption: "Dodaj rekord", + editCaption: "Edytuj rekord", + bSubmit: "Zapisz", + bCancel: "Anuluj", + bClose: "Zamknij", + processData: "Przetwarzanie...", + msg: { + required:"Pole jest wymagane", + number:"ProszÄ™ wpisać poprawnÄ… liczbÄ™", + minValue:"wartość musi być wiÄ™ksza lub równa", + maxValue:"wartość musi być mniejsza od", + email: "nie jest adresem e-mail", + integer: "ProszÄ™ wpisać poprawnÄ… liczbÄ™", + date: "Please, enter valid date value" + } +}; +$.jgrid.del = { + caption: "Usuwanie", + msg: "UsuÅ„ wybrany rekord(y)?", + bSubmit: "UsuÅ„", + bCancel: "Anuluj", + processData: "Przetwarzanie..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "Edytuj wybrany wiersz", + addtext:" ", + addtitle: "Dodaj nowy wiersz", + deltext: " ", + deltitle: "UsuÅ„ wybrany wiersz", + searchtext: " ", + searchtitle: "Wyszukaj rekord", + refreshtext: "", + refreshtitle: "PrzeÅ‚aduj", + alertcap: "Uwaga", + alerttext: "ProszÄ™ wybrać wiersz" +}; +// setcolumns module +$.jgrid.col ={ + caption: "Pokaż/Ukryj kolumny", + bSubmit: "Zatwierdź", + bCancel: "Anuluj" +}; +$.jgrid.errors = { + errcap : "Błąd", + nourl : "Brak adresu url", + norecords: "Brak danych", + model : "Length of colNames <> colModel!" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: " ", defaulValue: 0}, + number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat", + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" + ], + monthNames: [ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" + ], + AmPm : ["am","pm","AM","PM"], + S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, + srcformat: 'Y-m-d', + newformat: 'd/m/Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n/j/Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'show' +}; +})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/grid.locale-pt-br.js b/site/vendors/js/jqGrid/js/grid.locale-pt-br.js new file mode 100644 index 0000000..b43ed13 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-pt-br.js @@ -0,0 +1,108 @@ +;(function($){ +/** + * jqGrid Brazilian-Portuguese Translation + * Junior Gobira juniousbr@gmail.com + * http://jnsa.com.br + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "Registro(s)", + loadtext: "Carregando...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "Procurar...", + Find: "Procurar", + Reset: "Resetar", + odata : ['igual', 'diferente', 'menor', 'menor igual','maior','maior igual', 'começando com','terminando com','contém' ] +}; +$.jgrid.edit = { + addCaption: "Incluir", + editCaption: "Alterar", + bSubmit: "Enviar", + bCancel: "Cancelar", + bClose: "Fechar", + processData: "Carregando...", + msg: { + required:"Campo é requerido", + number:"Por favor, informe um número válido", + minValue:"valor deve ser igual ou maior que ", + maxValue:"valor deve ser menor ou igual a", + email: "este e-mail não é válido", + integer: "Por favor, informe um valor inteiro", + date: "Please, enter valid date value" + } +}; +$.jgrid.del = { + caption: "Delete", + msg: "Deletar registros selecionado(s)?", + bSubmit: "Delete", + bCancel: "Cancelar", + processData: "Carregando..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "Alterar registro selecionado", + addtext:" ", + addtitle: "Incluir novo registro", + deltext: " ", + deltitle: "Deletar registro selecionado", + searchtext: " ", + searchtitle: "Procurar registros", + refreshtext: "", + refreshtitle: "Recarrgando Tabela", + alertcap: "Aviso", + alerttext: "Por favor, selecione um registro" +}; +// setcolumns module +$.jgrid.col ={ + caption: "Mostrar/Esconder Colunas", + bSubmit: "Enviar", + bCancel: "Cancelar" +}; +$.jgrid.errors = { + errcap : "Erro", + nourl : "Nenhuma URL defenida", + norecords: "Sem registros para exibir", + model : "Length of colNames <> colModel!" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: " ", defaulValue: 0}, + number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat", + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" + ], + monthNames: [ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" + ], + AmPm : ["am","pm","AM","PM"], + S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, + srcformat: 'Y-m-d', + newformat: 'd/m/Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n/j/Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'show' +}; +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-pt.js b/site/vendors/js/jqGrid/js/grid.locale-pt.js new file mode 100644 index 0000000..25f94b8 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-pt.js @@ -0,0 +1,107 @@ +;(function($){ +/** + * jqGrid Portuguese Translation +* Tradução da jqGrid em Portugues por Frederico Carvalho, http://www.eyeviewdesign.pt + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "Registo(s)", + loadtext: "A carregar...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "Busca...", + Find: "Procurar", + Reset: "Limpar", + odata : ['igual', 'não igual', 'menor', 'menor ou igual', 'maior', 'maior ou igual', 'começa com', 'termina com','contém' ] +}; +$.jgrid.edit = { + addCaption: "Adicionar Registo", + editCaption: "Modificar Registo", + bSubmit: "Submeter", + bCancel: "Cancelar", + bClose: "Fechar", + processData: "A processar...", + msg: { + required:"Campo obrigatório", + number:"Por favor, introduza um numero", + minValue:"O valor deve ser maior ou igual que", + maxValue:"O valor deve ser menor ou igual a", + email: "Não é um endereço de email válido", + integer: "Por favor, introduza um numero inteiro", + date: "Por favor, introduza uma data válida." + } +}; +$.jgrid.del = { + caption: "Eliminar", + msg: "Deseja eliminar o(s) registo(s) seleccionado(s)?", + bSubmit: "Eliminar", + bCancel: "Cancelar", + processData: "A processar..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "Modificar registo seleccionado", + addtext:" ", + addtitle: "Adicionar novo registo", + deltext: " ", + deltitle: "Eliminar registo seleccionado", + searchtext: " ", + searchtitle: "Procurar", + refreshtext: "", + refreshtitle: "Actualizar", + alertcap: "Aviso", + alerttext: "Por favor, seleccione um registo" +}; +// setcolumns module +$.jgrid.col ={ + caption: "Mostrar/Ocultar Colunas", + bSubmit: "Enviar", + bCancel: "Cancelar" +}; +$.jgrid.errors = { + errcap : "Erro", + nourl : "Não especificou um url", + norecords: "Não existem dados para processar", + model : "Tamanho do colNames <> colModel!" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: " ", defaulValue: 0}, + number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab", + "Domingo", "Segunda-Feira", "Terça-Feira", "Quarta-Feira", "Quinta-Feira", "Sexta-Feira", "Sábado" + ], + monthNames: [ + "Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez", + "Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro" + ], + AmPm : ["am","pm","AM","PM"], + S: function (j) {return j < 11 || j > 13 ? ['º', 'º', 'º', 'º'][Math.min((j - 1) % 10, 3)] : 'º'}, + srcformat: 'Y-m-d', + newformat: 'd/m/Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n/j/Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'show' +}; +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-ru.js b/site/vendors/js/jqGrid/js/grid.locale-ru.js new file mode 100644 index 0000000..bd74c46 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-ru.js @@ -0,0 +1,108 @@ +;(function($){ +/** + * jqGrid Russian Translation v1.1 21.01.2009 + * Alexey Kanaev softcore@rambler.ru + * http://softcore.com.ru + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "ЗапиÑей", + loadtext: "Загрузка...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "ПоиÑк...", + Find: "Ðайти", + Reset: "СброÑ", + odata : ['равно', 'не равно', 'меньше', 'меньше или равно','больше','больше или равно', 'начинаетÑÑ Ñ','заканчиваетÑÑ Ð½Ð°','Ñодержит' ] +}; +$.jgrid.edit = { + addCaption: "Добавить запиÑÑŒ", + editCaption: "Редактировать запиÑÑŒ", + bSubmit: "Сохранить", + bCancel: "Отмена", + bClose: "Закрыть", + processData: "Обработка...", + msg: { + required:"Поле ÑвлÑетÑÑ Ð¾Ð±Ñзательным", + number:"ПожалуйÑта, введите правильное чиÑло", + minValue:"значение должно быть больше либо равно", + maxValue:"значение должно быть больше либо равно", + email: "некорректное значение e-mail", + integer: "ПожалуйÑта введите целое чиÑло", + date: "Please, enter valid date value" + } +}; +$.jgrid.del = { + caption: "Удалить", + msg: "Удалить выделенную запиÑÑŒ(и)?", + bSubmit: "Удвлить", + bCancel: "Отмена", + processData: "Обработка..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "Редактировать выделенную запиÑÑŒ", + addtext:" ", + addtitle: "Добавить новую запиÑÑŒ", + deltext: " ", + deltitle: "Удалить выделенную запиÑÑŒ", + searchtext: " ", + searchtitle: "Ðайти запиÑи", + refreshtext: "", + refreshtitle: "Обновить таблицу", + alertcap: "Внимание", + alerttext: "ПожалуйÑта, выделите запиÑÑŒ" +}; +// setcolumns module +$.jgrid.col ={ + caption: "Показать/Ñкрыть Ñтолбцы", + bSubmit: "Сохранить", + bCancel: "Отмена" +}; +$.jgrid.errors = { + errcap : "Ошибка", + nourl : "URL не уÑтановлен", + norecords: "Ðет запиÑей Ð´Ð»Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸", + model : "ЧиÑло полей не ÑоответÑтвует чиÑлу Ñтолбцов таблицы!" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: " ", defaulValue: 0}, + number : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "Ð’Ñ", "Пн", "Ð’Ñ‚", "Ср", "Чт", "Пт", "Сб", + "ВоÑкреÑение", "Понедельник", "Вторник", "Среда", "Четверг", "ПÑтница", "Суббота" + ], + monthNames: [ + "Янв", "Фев", "Мар", "Ðпр", "Май", "Июн", "Июл", "Ðвг", "Сен", "Окт", "ÐоÑ", "Дек", + "Январь", "Февраль", "Март", "Ðпрель", "Май", "Июнь", "Июль", "ÐвгуÑÑ‚", "СентÑбрь", "ОктÑбрь", "ÐоÑбрь", "Декабрь" + ], + AmPm : ["am","pm","AM","PM"], + S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, + srcformat: 'Y-m-d', + newformat: 'd.m.Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n.j.Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y G:i:s", + MonthDay: "F d", + ShortTime: "G:i", + LongTime: "G:i:s", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'show' +}; +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-sp.js b/site/vendors/js/jqGrid/js/grid.locale-sp.js new file mode 100644 index 0000000..f9eae93 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-sp.js @@ -0,0 +1,108 @@ +;(function($){ +/** + * jqGrid Spanish Translation + * Traduccion jqGrid en Español por Yamil Bracho + * Traduccion corregida y ampliada por Faserline, S.L. - http://www.faserline.com + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "fila(s)", + loadtext: "Cargando...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "Búsqueda...", + Find: "Buscar", + Reset: "Limpiar", + odata : ['igual', 'no igual', 'menor', 'menor o igual', 'mayor', 'mayor o igual', 'comienza con', 'termina con','contiene' ] +}; +$.jgrid.edit = { + addCaption: "Agregar registro", + editCaption: "Modificar registro", + bSubmit: "Enviar", + bCancel: "Cancelar", + bClose: "Cerrar", + processData: "Procesando...", + msg: { + required:"Campo obligatorio", + number:"Introduzca un número", + minValue:"El valor debe ser mayor o igual a ", + maxValue:"El valor debe ser menor o igual a ", + email: "no es una dirección de correo válida", + integer: "Introduzca un valor entero", + date: "Introduza una fecha correcta " + } +}; +$.jgrid.del = { + caption: "Eliminar", + msg: "¿Desea eliminar los registros seleccionados?", + bSubmit: "Eliminar", + bCancel: "Cancelar", + processData: "Procesando..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "Modificar fila seleccionada", + addtext:" ", + addtitle: "Agregar nueva fila", + deltext: " ", + deltitle: "Eliminar fila seleccionada", + searchtext: " ", + searchtitle: "Buscar información", + refreshtext: "", + refreshtitle: "Recargar datos", + alertcap: "Aviso", + alerttext: "Seleccione una fila" +}; +// setcolumns module +$.jgrid.col ={ + caption: "Mostrar/ocultar columnas", + bSubmit: "Enviar", + bCancel: "Cancelar" +}; +$.jgrid.errors = { + errcap : "Error", + nourl : "No se ha especificado una URL", + norecords: "No hay datos para procesar", + model : "Las columnas de nombres son diferentes de las columnas de modelo" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: ".", defaulValue: 0}, + number : {decimalSeparator:",", thousandsSeparator: ".", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:",", thousandsSeparator: ".", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa", + "Domingo", "Lunes", "Martes", "Miercoles", "Jueves", "Viernes", "Sabado" + ], + monthNames: [ + "Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic", + "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre" + ], + AmPm : ["am","pm","AM","PM"], + S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, + srcformat: 'Y-m-d', + newformat: 'd-m-Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n/j/Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'show' +}; +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-sv.js b/site/vendors/js/jqGrid/js/grid.locale-sv.js new file mode 100644 index 0000000..c3fdde2 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-sv.js @@ -0,0 +1,110 @@ +;(function($){ +/** + * jqGrid Swedish Translation + * Anders Nyberg anders.nyberg@alecta.com + * http://wwww.alecta.com + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "post(er)", + loadtext: "Laddar...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "Sök...", + Find: "Hitta", + Reset: "Ã…terställ", + odata : ['lika', 'ej lika', 'mindre', 'mindre eller lika','större','större eller lika', 'börjar med','slutar med','innehÃ¥ller' ] +}; +$.jgrid.edit = { + addCaption: "Skapa post", + editCaption: "Ändra post", + bSubmit: "Utför", + bCancel: "Avbryt", + bClose: "Stäng", + processData: "Processar...", + msg: { + required:"Fält är obligatoriskt", + number:"Välj korrekt nummer", + minValue:"värdet mÃ¥ste vara större än eller lika med", + maxValue:"värdet mÃ¥ste vara mindre än eller lika med", + email: "är inte korrekt e-mail adress", + integer: "Var god ange korrekt heltal", + date: "Var god att ange korrekt datum" + } +}; +$.jgrid.del = { + caption: "Ta bort", + msg: "Ta bort vald post(er)?", + bSubmit: "Utför", + bCancel: "Avbryt", + processData: "Processing..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "Ändra vald rad", + addtext:" ", + addtitle: "Skapa ny rad", + deltext: " ", + deltitle: "Ta bort vald rad", + searchtext: " ", + searchtitle: "Hitta poster", + refreshtext: "", + refreshtitle: "Ladda om Grid", + alertcap: "Varning", + alerttext: "Var god välj rad" +}; +// setcolumns module +$.jgrid.col ={ + caption: "Visa/Göm kolumner", + bSubmit: "Utför", + bCancel: "Avbryt" +}; +$.jgrid.errors = { + errcap : "Fel", + nourl : "Ingen URL är definierad", + norecords: "Inga poster att processa", + model : "Längden av colNames <> colModel!" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: " ", defaulValue: 0}, + number : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:",", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "Sön", "MÃ¥n", "Tis", "Ons", "Tor", "Fre", "Lör", + "Söndag", "MÃ¥ndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag" + ], + monthNames: [ + "Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec", + "Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December" + ], + AmPm : ["fm","em","FM","EM"], + S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, + srcformat: 'Y-m-d', + newformat: 'Y-m-d', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n/j/Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'show', + addParam : '' +}; +// SV +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.locale-tr.js b/site/vendors/js/jqGrid/js/grid.locale-tr.js new file mode 100644 index 0000000..47554ab --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.locale-tr.js @@ -0,0 +1,108 @@ +;(function($){ +/** + * jqGrid Turkish Translation + * H.İbrahim Yılmaz ibrahim.yilmaz@karmabilisim.net + * http://www.arkeoloji.web.tr + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.jgrid = {}; + +$.jgrid.defaults = { + recordtext: "Satır(lar)", + loadtext: "Yükleniyor...", + pgtext : "/" +}; +$.jgrid.search = { + caption: "Arama...", + Find: "Bul", + Reset: "Temizle", + odata : ['eÅŸittir', 'eÅŸit deÄŸildir', 'küçük', 'küçük veya eÅŸit','büyük','büyük veya eÅŸit', 'ile baÅŸlayan','ile biten','içeren' ] +}; +$.jgrid.edit = { + addCaption: "Kayıt Ekle", + editCaption: "Kayıt Düzenle", + bSubmit: "Gönder", + bCancel: "İptal", + bClose: "Kapat", + processData: "İşlem yapılıyor...", + msg: { + required:"Alan gerekli", + number:"Lütfen bir numara giriniz", + minValue:"girilen deÄŸer daha büyük ya da buna eÅŸit olmalıdır", + maxValue:"girilen deÄŸer daha küçük ya da buna eÅŸit olmalıdır", + email: "geçerli bir e-posta adresi deÄŸildir", + integer: "Lütfen bir tamsayı giriniz", + date: "Please, enter valid date value" + } +}; +$.jgrid.del = { + caption: "Sil", + msg: "Seçilen kayıtlar silinsin mi?", + bSubmit: "Sil", + bCancel: "İptal", + processData: "İşlem yapılıyor..." +}; +$.jgrid.nav = { + edittext: " ", + edittitle: "Seçili satırı düzenle", + addtext:" ", + addtitle: "Yeni satır ekle", + deltext: " ", + deltitle: "Seçili satırı sil", + searchtext: " ", + searchtitle: "Kayıtları bul", + refreshtext: "", + refreshtitle: "Tabloyu yenile", + alertcap: "Uyarı", + alerttext: "Lütfen bir satır seçiniz" +}; +// setcolumns module +$.jgrid.col ={ + caption: "Sütunları göster/gizle", + bSubmit: "Gönder", + bCancel: "İptal" +}; +$.jgrid.errors = { + errcap : "Hata", + nourl : "Bir url yapılandırılmamış", + norecords: "İşlem yapılacak bir kayıt yok", + model : "Length of colNames <> colModel!" +}; +$.jgrid.formatter = { + integer : {thousandsSeparator: " ", defaulValue: 0}, + number : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, defaulValue: 0}, + currency : {decimalSeparator:".", thousandsSeparator: " ", decimalPlaces: 2, prefix: "", suffix:"", defaulValue: 0}, + date : { + dayNames: [ + "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat", + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" + ], + monthNames: [ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" + ], + AmPm : ["am","pm","AM","PM"], + S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th'}, + srcformat: 'Y-m-d', + newformat: 'd/m/Y', + masks : { + ISO8601Long:"Y-m-d H:i:s", + ISO8601Short:"Y-m-d", + ShortDate: "n/j/Y", + LongDate: "l, F d, Y", + FullDateTime: "l, F d, Y g:i:s A", + MonthDay: "F d", + ShortTime: "g:i A", + LongTime: "g:i:s A", + SortableDateTime: "Y-m-d\\TH:i:s", + UniversalSortableDateTime: "Y-m-d H:i:sO", + YearMonth: "F, Y" + }, + reformatAfterEdit : false + }, + baseLinkUrl: '', + showAction: 'show' +}; +})(jQuery); diff --git a/site/vendors/js/jqGrid/js/grid.postext.js b/site/vendors/js/jqGrid/js/grid.postext.js new file mode 100644 index 0000000..ce53e88 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.postext.js @@ -0,0 +1,64 @@ +;(function($){ +/** + * jqGrid extension + * Paul Tiseo ptiseo@wasteconsultants.com + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.fn.extend({ + getPostData : function(){ + var $t = this[0]; + if(!$t.grid) { return; } + return $t.p.postData; + }, + setPostData : function( newdata ) { + var $t = this[0]; + if(!$t.grid) { return; } + // check if newdata is correct type + if ( typeof(newdata) === 'object' ) { + $t.p.postData = newdata; + } + else { + alert("Error: cannot add a non-object postData value. postData unchanged."); + } + }, + appendPostData : function( newdata ) { + var $t = this[0]; + if(!$t.grid) { return; } + // check if newdata is correct type + if ( typeof(newdata) === 'object' ) { + $.extend($t.p.postData, newdata); + } + else { + alert("Error: cannot append a non-object postData value. postData unchanged."); + } + }, + setPostDataItem : function( key, val ) { + var $t = this[0]; + if(!$t.grid) { return; } + $t.p.postData[key] = val; + }, + getPostDataItem : function( key ) { + var $t = this[0]; + if(!$t.grid) { return; } + return $t.p.postData[key]; + }, + removePostDataItem : function( key ) { + var $t = this[0]; + if(!$t.grid) { return; } + delete $t.p.postData[key]; + }, + getUserData : function(){ + var $t = this[0]; + if(!$t.grid) { return; } + return $t.p.userData; + }, + getUserDataItem : function( key ) { + var $t = this[0]; + if(!$t.grid) { return; } + return $t.p.userData[key]; + } +}); +})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/grid.setcolumns.js b/site/vendors/js/jqGrid/js/grid.setcolumns.js new file mode 100644 index 0000000..7b7f132 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.setcolumns.js @@ -0,0 +1,78 @@ +;(function($){ +/** + * jqGrid extension for manipulating columns properties + * Piotr Roznicki roznicki@o2.pl + * http://www.roznicki.prv.pl + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.fn.extend({ + setColumns : function(p) { + p = $.extend({ + top : 0, + left: 0, + width: 200, + height: 195, + modal: false, + drag: true, + closeicon: 'ico-close.gif', + beforeShowForm: null, + afterShowForm: null, + afterSubmitForm: null + }, $.jgrid.col, p ||{}); + return this.each(function(){ + var $t = this; + if (!$t.grid ) { return; } + var onBeforeShow = typeof p.beforeShowForm === 'function' ? true: false; + var onAfterShow = typeof p.afterShowForm === 'function' ? true: false; + var onAfterSubmit = typeof p.afterSubmitForm === 'function' ? true: false; + if(!p.imgpath) { p.imgpath= $t.p.imgpath; } // Added From Tony Tomov + var gID = $("table:first",$t.grid.bDiv).attr("id"); + var IDs = {themodal:'colmod'+gID,modalhead:'colhd'+gID,modalcontent:'colcnt'+gID}; + var dtbl = "ColTbl_"+gID; + if ( $("#"+IDs.themodal).html() != null ) { + if(onBeforeShow) { p.beforeShowForm($("#"+dtbl)); } + viewModal("#"+IDs.themodal,{modal:p.modal}); + if(onAfterShow) { p.afterShowForm($("#"+dtbl)); } + } else { + var tbl =$("
    "); + for(i=0;i" + ""); + } + } + var bS =""; + var bC =""; + $(tbl).append(""+bS+" "+bC+""); + createModal(IDs,tbl,p,$t.grid.hDiv,$t.grid.hDiv); + if( p.drag) { DnRModal("#"+IDs.themodal,"#"+IDs.modalhead+" td.modaltext"); } + $("#dData","#"+dtbl).click(function(e){ + for(i=0;i<$t.p.colModel.length;i++){ + if(!$t.p.colModel[i].hidedlg) { // added from T. Tomov + if($("#col_" + $t.p.colModel[i].name).attr("checked")) { + $($t).showCol($t.p.colModel[i].name); + $("#col_" + $t.p.colModel[i].name).attr("defaultChecked",true); // Added from T. Tomov IE BUG + } else { + $($t).hideCol($t.p.colModel[i].name); + $("#col_" + $t.p.colModel[i].name).attr("defaultChecked",""); // Added from T. Tomov IE BUG + } + } + } + $("#"+IDs.themodal).jqmHide(); + if (onAfterSubmit) { p.afterSubmitForm($("#"+dtbl)); } + return false; + }); + $("#eData", "#"+dtbl).click(function(e){ + $("#"+IDs.themodal).jqmHide(); + return false; + }); + if(onBeforeShow) { p.beforeShowForm($("#"+dtbl)); } + viewModal("#"+IDs.themodal,{modal:p.modal}); + if(onAfterShow) { p.afterShowForm($("#"+dtbl)); } + } + }); + } +}); +})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/grid.subgrid.js b/site/vendors/js/jqGrid/js/grid.subgrid.js new file mode 100644 index 0000000..1d68023 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.subgrid.js @@ -0,0 +1,255 @@ +;(function($){ +/** + * jqGrid extension for SubGrid Data + * Tony Tomov tony@trirand.com + * http://trirand.com/blog/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.fn.extend({ +addSubGrid : function(t,row,pos,rowelem) { + return this.each(function(){ + var ts = this; + if (!ts.grid ) { + return; + } + var td, res,_id, pID, nhc, bfsc; + td = document.createElement("td"); + $(td,t).html("").addClass("sgcollapsed") + .click( function(e) { + if($(this).hasClass("sgcollapsed")) { + pID = $("table:first",ts.grid.bDiv).attr("id"); + res = $(this).parent(); + var atd= pos==1?'':''; + _id = $(res).attr("id"); + bfsc =true; + if($.isFunction(ts.p.subGridBeforeExpand)) { + bfsc = ts.p.subGridBeforeExpand(pID+"_"+_id,_id); + } + if(bfsc === false) {return false;} + nhc = 0; + $.each(ts.p.colModel,function(i,v){ + if(this.hidden === true) { + nhc++; + } + }); + var subdata = ""+atd+"
    "; + $(this).parent().after( subdata+ "
    " ); + $(".tablediv",ts).css("width", ts.grid.width-20+"px"); + if( $.isFunction(ts.p.subGridRowExpanded) ) { + ts.p.subGridRowExpanded(pID+"_"+ _id,_id); + } else { + populatesubgrid(res); + } + $(this).html("").removeClass("sgcollapsed").addClass("sgexpanded"); + } else if($(this).hasClass("sgexpanded")) { + bfsc = true; + if( $.isFunction(ts.p.subGridRowColapsed)) { + res = $(this).parent(); + _id = $(res).attr("id"); + bfsc = ts.p.subGridRowColapsed(pID+"_"+_id,_id ); + }; + if(bfsc===false) {return false;} + $(this).parent().next().remove(".subgrid"); + $(this).html("").removeClass("sgexpanded").addClass("sgcollapsed"); + } + return false; + }); + row.appendChild(td); + //------------------------- + var populatesubgrid = function( rd ) { + var res,sid,dp; + sid = $(rd).attr("id"); + dp = {id:sid, nd_: (new Date().getTime())}; + if(!ts.p.subGridModel[0]) { + return false; + } + if(ts.p.subGridModel[0].params) { + for(var j=0; j < ts.p.subGridModel[0].params.length; j++) { + for(var i=0; i"+sgmap.row, sjxml).each( function(){ + trdiv = document.createElement("div"); + trdiv.className="rowdiv"; + if(sgmap.repeatitems === true) { + $(sgmap.cell,this).each( function(i) { + subGridCell(trdiv, this.textContent || this.text || ' ',i); + }); + } else { + var f = ts.p.subGridModel[0].mapping; + if (f) { + for (i=0;i + If the first column of the table contains checkboxes or + radiobuttons then the jqGrid is made selectable. +*/ +// Addition - selector can be a class or id +function tableToGrid(selector) { +$(selector).each(function() { + if(this.grid) {return;} //Adedd from Tony Tomov + // This is a small "hack" to make the width of the jqGrid 100% + $(this).width("99%"); + var w = $(this).width(); + + // Text whether we have single or multi select + var inputCheckbox = $('input[type=checkbox]:first', $(this)); + var inputRadio = $('input[type=radio]:first', $(this)); + var selectMultiple = inputCheckbox.length > 0; + var selectSingle = !selectMultiple && inputRadio.length > 0; + var selectable = selectMultiple || selectSingle; + var inputName = inputCheckbox.attr("name") || inputRadio.attr("name"); + + // Build up the columnModel and the data + var colModel = []; + var colNames = []; + $('th', $(this)).each(function() { + if (colModel.length == 0 && selectable) { + colModel.push({ + name: '__selection__', + index: '__selection__', + width: 0, + hidden: true + }); + colNames.push('__selection__'); + } else { + colModel.push({ + name: $(this).html(), + index: $(this).html(), + width: $(this).width() || 150 + }); + colNames.push($(this).html()); + } + }); + var data = []; + var rowIds = []; + var rowChecked = []; + $('tbody > tr', $(this)).each(function() { + var row = {}; + var rowPos = 0; + data.push(row); + $('td', $(this)).each(function() { + if (rowPos == 0 && selectable) { + var input = $('input', $(this)); + var rowId = input.attr("value"); + rowIds.push(rowId || data.length); + if (input.attr("checked")) { + rowChecked.push(rowId); + } + row[colModel[rowPos].name] = input.attr("value"); + } else { + row[colModel[rowPos].name] = $(this).html(); + } + rowPos++; + }); + }); + + // Clear the original HTML table + $(this).empty(); + + // Mark it as jqGrid + $(this).addClass("scroll"); + + $(this).jqGrid({ + datatype: "local", + width: w, + colNames: colNames, + colModel: colModel, + multiselect: selectMultiple + //inputName: inputName, + //inputValueCol: imputName != null ? "__selection__" : null + }); + + // Add data + for (var a = 0; a < data.length; a++) { + var id = null; + if (rowIds.length > 0) { + id = rowIds[a]; + if (id && id.replace) { + // We have to do this since the value of a checkbox + // or radio button can be anything + id = encodeURIComponent(id).replace(/[.\-%]/g, "_"); + } + } + if (id == null) { + id = a + 1; + } + $(this).addRowData(id, data[a]); + } + + // Set the selection + for (var a = 0; a < rowChecked.length; a++) { + $(this).setSelection(rowChecked[a]); + } +}); +}; diff --git a/site/vendors/js/jqGrid/js/grid.treegrid.js b/site/vendors/js/jqGrid/js/grid.treegrid.js new file mode 100644 index 0000000..fa398b1 --- /dev/null +++ b/site/vendors/js/jqGrid/js/grid.treegrid.js @@ -0,0 +1,428 @@ +;(function($) { +/* +** + * jqGrid extension - Tree Grid + * Tony Tomov tony@trirand.com + * http://trirand.com/blog/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +**/ +$.fn.extend({ + setTreeNode : function(rd, row){ + return this.each(function(){ + var $t = this; + if( !$t.grid || !$t.p.treeGrid ) { return; } + var expCol=0,i=0; + if(!$t.p.expColInd) { + for (var key in $t.p.colModel){ + if($t.p.colModel[key].name == $t.p.ExpandColumn) { + expCol = i; + $t.p.expColInd = expCol; + break; + } + i++; + } + if(!$t.p.expColInd ) {$t.p.expColInd = expCol;} + } else { + expCol = $t.p.expColInd; + } + var expanded = $t.p.treeReader.expanded_field; + var isLeaf = $t.p.treeReader.leaf_field; + var level = $t.p.treeReader.level_field; + row.level = rd[level]; + + if($t.p.treeGridModel == 'nested') { + row.lft = rd[$t.p.treeReader.left_field]; + row.rgt = rd[$t.p.treeReader.right_field]; + if(!rd[isLeaf]) { + // NS Model + rd[isLeaf] = (parseInt(row.rgt,10) === parseInt(row.lft,10)+1) ? 'true' : 'false'; + } + } else { + row.parent_id = rd[$t.p.treeReader.parent_id_field]; + } + + var curExpand = (rd[expanded] && rd[expanded] == "true") ? true : false; + var curLevel = parseInt(row.level,10); + var ident,lftpos; + if($t.p.tree_root_level === 0) { + ident = curLevel+1; + lftpos = curLevel; + } else { + ident = curLevel; + lftpos = curLevel -1; + } + var twrap = document.createElement("div"); + $(twrap).addClass("tree-wrap").width(ident*18); + var treeimg = document.createElement("div"); + $(treeimg).css("left",lftpos*18); + twrap.appendChild(treeimg); + + if(rd[isLeaf] == "true") { + $(treeimg).addClass("tree-leaf"); + row.isLeaf = true; + } else { + if(rd[expanded] == "true") { + $(treeimg).addClass("tree-minus treeclick"); + row.expanded = true; + } else { + $(treeimg).addClass("tree-plus treeclick"); + row.expanded = false; + } + } + if(parseInt(rd[level],10) !== parseInt($t.p.tree_root_level,10)) { + if(!$($t).isVisibleNode(row)){ + $(row).css("display","none"); + } + } + var mhtm = $("td:eq("+expCol+")",row).html(); + var thecell = $("td:eq("+expCol+")",row).html(""+mhtm+"").prepend(twrap); + $(".treeclick",thecell).click(function(e){ + var target = e.target || e.srcElement; + var ind =$(target,$t.rows).parents("tr:first")[0].rowIndex; + if(!$t.rows[ind].isLeaf){ + if($t.rows[ind].expanded){ + $($t).collapseRow($t.rows[ind]); + $($t).collapseNode($t.rows[ind]); + } else { + $($t).expandRow($t.rows[ind]); + $($t).expandNode($t.rows[ind]); + } + } + //e.stopPropagation(); + return false; + }); + if($t.p.ExpandColClick === true) { + $("span", thecell).css("cursor","pointer").click(function(e){ + var target = e.target || e.srcElement; + var ind =$(target,$t.rows).parents("tr:first")[0].rowIndex; + if(!$t.rows[ind].isLeaf){ + if($t.rows[ind].expanded){ + $($t).collapseRow($t.rows[ind]); + $($t).collapseNode($t.rows[ind]); + } else { + $($t).expandRow($t.rows[ind]); + $($t).expandNode($t.rows[ind]); + } + } + $($t).setSelection($t.rows[ind].id); + return false; + }); + } + }); + }, + setTreeGrid : function() { + return this.each(function (){ + var $t = this; + if(!$t.p.treeGrid) { return; } + $.extend($t.p,{treedatatype: null}); + if($t.p.treeGridModel == 'nested') { + $t.p.treeReader = $.extend({ + level_field: "level", + left_field:"lft", + right_field: "rgt", + leaf_field: "isLeaf", + expanded_field: "expanded" + },$t.p.treeReader); + } else + if($t.p.treeGridModel == 'adjacency') { + $t.p.treeReader = $.extend({ + level_field: "level", + parent_id_field: "parent", + leaf_field: "isLeaf", + expanded_field: "expanded" + },$t.p.treeReader ); + } + }); + }, + expandRow: function (record){ + this.each(function(){ + var $t = this; + if(!$t.grid || !$t.p.treeGrid) { return; } + var childern = $($t).getNodeChildren(record); + //if ($($t).isVisibleNode(record)) { + $(childern).each(function(i){ + $(this).css("display",""); + if(this.expanded) { + $($t).expandRow(this); + } + }); + //} + }); + }, + collapseRow : function (record) { + this.each(function(){ + var $t = this; + if(!$t.grid || !$t.p.treeGrid) { return; } + var childern = $($t).getNodeChildren(record); + $(childern).each(function(i){ + $(this).css("display","none"); + $($t).collapseRow(this); + }); + }); + }, + // NS ,adjacency models + getRootNodes : function() { + var result = []; + this.each(function(){ + var $t = this; + if(!$t.grid || !$t.p.treeGrid) { return; } + switch ($t.p.treeGridModel) { + case 'nested' : + var level = $t.p.treeReader.level_field; + $($t.rows).each(function(i){ + if(parseInt(this[level],10) === parseInt($t.p.tree_root_level,10)) { + result.push(this); + } + }); + break; + case 'adjacency' : + $($t.rows).each(function(i){ + if(this.parent_id.toLowerCase() == "null") { + result.push(this); + } + }); + break; + } + }); + return result; + }, + getNodeDepth : function(rc) { + var ret = null; + this.each(function(){ + var $t = this; + if(!this.grid || !this.p.treeGrid) { return; } + switch ($t.p.treeGridModel) { + case 'nested' : + ret = parseInt(rc.level,10) - parseInt(this.p.tree_root_level,10); + break; + case 'adjacency' : + ret = $($t).getNodeAncestors(rc).length; + break; + } + }); + return ret; + }, + getNodeParent : function(rc) { + var result = null; + this.each(function(){ + var $t = this; + if(!$t.grid || !$t.p.treeGrid) { return; } + switch ($t.p.treeGridModel) { + case 'nested' : + var lft = parseInt(rc.lft,10), rgt = parseInt(rc.rgt,10), level = parseInt(rc.level,10); + $(this.rows).each(function(){ + if(parseInt(this.level,10) === level-1 && parseInt(this.lft) < lft && parseInt(this.rgt) > rgt) { + result = this; + return false; + } + }); + break; + case 'adjacency' : + $(this.rows).each(function(){ + if(this.id === rc.parent_id ) { + result = this; + return false; + } + }); + break; + } + }); + return result; + }, + getNodeChildren : function(rc) { + var result = []; + this.each(function(){ + var $t = this; + if(!$t.grid || !$t.p.treeGrid) { return; } + switch ($t.p.treeGridModel) { + case 'nested' : + var lft = parseInt(rc.lft,10), rgt = parseInt(rc.rgt,10), level = parseInt(rc.level,10); + var ind = rc.rowIndex; + $(this.rows).slice(1).each(function(i){ + if(parseInt(this.level,10) === level+1 && parseInt(this.lft,10) > lft && parseInt(this.rgt,10) < rgt) { + result.push(this); + } + }); + break; + case 'adjacency' : + $(this.rows).slice(1).each(function(i){ + if(this.parent_id == rc.id) { + result.push(this); + } + }); + break; + } + }); + return result; + }, + getFullTreeNode : function(rc) { + var result = []; + this.each(function(){ + var $t = this; + if(!$t.grid || !$t.p.treeGrid) { return; } + switch ($t.p.treeGridModel) { + case 'nested' : + var lft = parseInt(rc.lft,10), rgt = parseInt(rc.rgt,10), level = parseInt(rc.level,10); + var ind = rc.rowIndex; + $(this.rows).slice(1).each(function(i){ + if(parseInt(this.level,10) >= level && parseInt(this.lft,10) >= lft && parseInt(this.lft,10) <= rgt) { + result.push(this); + } + }); + break; + case 'adjacency' : + break; + } + }); + return result; + }, + // End NS, adjacency Model + getNodeAncestors : function(rc) { + var ancestors = []; + this.each(function(){ + if(!this.grid || !this.p.treeGrid) { return; } + var parent = $(this).getNodeParent(rc); + while (parent) { + ancestors.push(parent); + parent = $(this).getNodeParent(parent); + } + }); + return ancestors; + }, + isVisibleNode : function(rc) { + var result = true; + this.each(function(){ + var $t = this; + if(!$t.grid || !$t.p.treeGrid) { return; } + var ancestors = $($t).getNodeAncestors(rc); + $(ancestors).each(function(){ + result = result && this.expanded; + if(!result) {return false;} + }); + }); + return result; + }, + isNodeLoaded : function(rc) { + var result; + this.each(function(){ + var $t = this; + if(!$t.grid || !$t.p.treeGrid) { return; } + if(rc.loaded !== undefined) { + result = rc.loaded; + } else if( rc.isLeaf || $($t).getNodeChildren(rc).length > 0){ + result = true; + } else { + result = false; + } + }); + return result; + }, + expandNode : function(rc) { + return this.each(function(){ + if(!this.grid || !this.p.treeGrid) { return; } + if(!rc.expanded) { + if( $(this).isNodeLoaded(rc) ) { + rc.expanded = true; + $("div.treeclick",rc).removeClass("tree-plus").addClass("tree-minus"); + } else { + rc.expanded = true; + $("div.treeclick",rc).removeClass("tree-plus").addClass("tree-minus"); + this.p.treeANode = rc.rowIndex; + this.p.datatype = this.p.treedatatype; + if(this.p.treeGridModel == 'nested') { + $(this).setGridParam({postData:{nodeid:rc.id,n_left:rc.lft,n_right:rc.rgt,n_level:rc.level}}); + } else { + $(this).setGridParam({postData:{nodeid:rc.id,parentid:rc.parent_id,n_level:rc.level}}); + } + $(this).trigger("reloadGrid"); + if(this.p.treeGridModel == 'nested') { + $(this).setGridParam({postData:{nodeid:'',n_left:'',n_right:'',n_level:''}}); + } else { + $(this).setGridParam({postData:{nodeid:'',parentid:'',n_level:''}}); + } + } + } + }); + }, + collapseNode : function(rc) { + return this.each(function(){ + if(!this.grid || !this.p.treeGrid) { return; } + if(rc.expanded) { + rc.expanded = false; + $("div.treeclick",rc).removeClass("tree-minus").addClass("tree-plus"); + } + }); + }, + SortTree : function( newDir) { + return this.each(function(){ + if(!this.grid || !this.p.treeGrid) { return; } + var i, len, + rec, records = [], + roots = $(this).getRootNodes(); + // Sorting roots + roots.sort(function(a, b) { + if (a.sortKey < b.sortKey) {return -newDir;} + if (a.sortKey > b.sortKey) {return newDir;} + return 0; + }); + // Sorting children + for (i = 0, len = roots.length; i < len; i++) { + rec = roots[i]; + records.push(rec); + $(this).collectChildrenSortTree(records, rec, newDir); + } + var $t = this; + $.each(records, function(index, row) { + $('tbody',$t.grid.bDiv).append(row); + row.sortKey = null; + }); + }); + }, + collectChildrenSortTree : function(records, rec, newDir) { + return this.each(function(){ + if(!this.grid || !this.p.treeGrid) { return; } + var i, len, + child, + children = $(this).getNodeChildren(rec); + children.sort(function(a, b) { + if (a.sortKey < b.sortKey) {return -newDir;} + if (a.sortKey > b.sortKey) {return newDir;} + return 0; + }); + for (i = 0, len = children.length; i < len; i++) { + child = children[i]; + records.push(child); + $(this).collectChildrenSortTree(records, child,newDir); + } + }); + }, + // experimental + setTreeRow : function(rowid, data) { + var nm, success=false; + this.each(function(){ + var t = this; + if(!t.grid || !t.p.treeGrid) { return; } + success = $(t).setRowData(rowid,data); + }); + return success; + }, + delTreeNode : function (rowid) { + return this.each(function () { + var $t = this; + if(!$t.grid || !$t.p.treeGrid) { return; } + var rc = $($t).getInd($t.rows,rowid,true); + if (rc) { + var dr = $($t).getNodeChildren(rc); + if(dr.length>0){ + for (var i=0;i, http://www.iceburg.net + * Licensed under the MIT License: + * http://www.opensource.org/licenses/mit-license.php + * + * $Version: 2007.08.19 +r2 + */ + +(function($){ +$.fn.jqDrag=function(h){return i(this,h,'d');}; +$.fn.jqResize=function(h){return i(this,h,'r');}; +$.jqDnR={ + dnr:{}, + e:0, + drag:function(v){ + if(M.k == 'd')E.css({left:M.X+v.pageX-M.pX,top:M.Y+v.pageY-M.pY}); + else E.css({width:Math.max(v.pageX-M.pX+M.W,0),height:Math.max(v.pageY-M.pY+M.H,0)}); + return false; + }, + stop:function(){ + //E.css('opacity',M.o); + $().unbind('mousemove',J.drag).unbind('mouseup',J.stop); + } +}; +var J=$.jqDnR,M=J.dnr,E=J.e, +i=function(e,h,k){ + return e.each(function(){ + h=(h)?$(h,e):e; + h.bind('mousedown',{e:e,k:k},function(v){ + var d=v.data,p={};E=d.e; + // attempt utilization of dimensions plugin to fix IE issues + if(E.css('position') != 'relative'){try{E.position(p);}catch(e){}} + M={ + X:p.left||f('left')||0, + Y:p.top||f('top')||0, + W:f('width')||E[0].scrollWidth||0, + H:f('height')||E[0].scrollHeight||0, + pX:v.pageX, + pY:v.pageY, + k:d.k + //o:E.css('opacity') + }; + //E.css({opacity:0.8}); + $().mousemove($.jqDnR.drag).mouseup($.jqDnR.stop); + return false; + }); + }); +}, +f=function(k){return parseInt(E.css(k))||false;}; +})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/jqModal.js b/site/vendors/js/jqGrid/js/jqModal.js new file mode 100644 index 0000000..3aac816 --- /dev/null +++ b/site/vendors/js/jqGrid/js/jqModal.js @@ -0,0 +1,69 @@ +/* + * jqModal - Minimalist Modaling with jQuery + * (http://dev.iceburg.net/jquery/jqModal/) + * + * Copyright (c) 2007,2008 Brice Burgess + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + * $Version: 03/01/2009 +r14 + */ +(function($) { +$.fn.jqm=function(o){ +var p={ +overlay: 50, +overlayClass: 'jqmOverlay', +closeClass: 'jqmClose', +trigger: '.jqModal', +ajax: F, +ajaxText: '', +target: F, +modal: F, +toTop: F, +onShow: F, +onHide: F, +onLoad: F +}; +return this.each(function(){if(this._jqm)return H[this._jqm].c=$.extend({},H[this._jqm].c,o);s++;this._jqm=s; +H[s]={c:$.extend(p,$.jqm.params,o),a:F,w:$(this).addClass('jqmID'+s),s:s}; +if(p.trigger)$(this).jqmAddTrigger(p.trigger); +});}; + +$.fn.jqmAddClose=function(e){return hs(this,e,'jqmHide');}; +$.fn.jqmAddTrigger=function(e){return hs(this,e,'jqmShow');}; +$.fn.jqmShow=function(t){return this.each(function(){t=t||window.event;$.jqm.open(this._jqm,t);});}; +$.fn.jqmHide=function(t){return this.each(function(){t=t||window.event;$.jqm.close(this._jqm,t)});}; + +$.jqm = { +hash:{}, +open:function(s,t){var h=H[s],c=h.c,cc='.'+c.closeClass,z=(parseInt(h.w.css('z-index'))),z=(z>0)?z:3000,o=$('
    ').css({height:'100%',width:'100%',position:'fixed',left:0,top:0,'z-index':z-1,opacity:c.overlay/100});if(h.a)return F;h.t=t;h.a=true;h.w.css('z-index',z); + if(c.modal) {if(!A[0])L('bind');A.push(s);} + else if(c.overlay > 0)h.w.jqmAddClose(o); + else o=F; + + h.o=(o)?o.addClass(c.overlayClass).prependTo('body'):F; + if(ie6){$('html,body').css({height:'100%',width:'100%'});if(o){o=o.css({position:'absolute'})[0];for(var y in {Top:1,Left:1})o.style.setExpression(y.toLowerCase(),"(_=(document.documentElement.scroll"+y+" || document.body.scroll"+y+"))+'px'");}} + + if(c.ajax) {var r=c.target||h.w,u=c.ajax,r=(typeof r == 'string')?$(r,h.w):$(r),u=(u.substr(0,1) == '@')?$(t).attr(u.substring(1)):u; + r.html(c.ajaxText).load(u,function(){if(c.onLoad)c.onLoad.call(this,h);if(cc)h.w.jqmAddClose($(cc,h.w));e(h);});} + else if(cc)h.w.jqmAddClose($(cc,h.w)); + + if(c.toTop&&h.o)h.w.before('').insertAfter(h.o); + (c.onShow)?c.onShow(h):h.w.show();e(h);return F; +}, +close:function(s){var h=H[s];if(!h.a)return F;h.a=F; + if(A[0]){A.pop();if(!A[0])L('unbind');} + if(h.c.toTop&&h.o)$('#jqmP'+h.w[0]._jqm).after(h.w).remove(); + if(h.c.onHide)h.c.onHide(h);else{h.w.hide();if(h.o)h.o.remove();} return F; +}, +params:{}}; +var s=0,H=$.jqm.hash,A=[],ie6=$.browser.msie&&($.browser.version == "6.0"),F=false, +i=$('').css({opacity:0}), +e=function(h){if(ie6)if(h.o)h.o.html('

    ').prepend(i);else if(!$('iframe.jqm',h.w)[0])h.w.prepend(i); f(h);}, +f=function(h){try{$(':input:visible',h.w)[0].focus();}catch(_){}}, +L=function(t){$()[t]("keypress",m)[t]("keydown",m)[t]("mousedown",m);}, +m=function(e){var h=H[A[A.length-1]],r=(!$(e.target).parents('.jqmID'+h.s)[0]);if(r)f(h);return !r;}, +hs=function(w,t,c){return w.each(function(){var s=this._jqm;$(t).each(function() { + if(!this[c]){this[c]=[];$(this).click(function(){for(var i in {jqmShow:1,jqmHide:1})for(var s in this[i])if(H[this[i][s]])H[this[i][s]].w[i](this);return F;});}this[c].push(s);});});}; +})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/jquery.fmatter.js b/site/vendors/js/jqGrid/js/jquery.fmatter.js new file mode 100644 index 0000000..601177b --- /dev/null +++ b/site/vendors/js/jqGrid/js/jquery.fmatter.js @@ -0,0 +1,426 @@ +/* +** + * formatter for values but most of the values if for jqGrid + * Some of this was inspired and based on how YUI does the table datagrid but in jQuery fashion + * we are trying to keep it as light as possible + * Joshua Burnett josh@9ci.com + * http://www.greenbill.com + * + * Changes from Tony Tomov tony@trirand.com + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * +**/ + +;(function($) { + $.fmatter = {}; + //opts can be id:row id for the row, rowdata:the data for the row, colmodel:the column model for this column + //example {id:1234,} + $.fn.fmatter = function(formatType, cellval, opts, act) { + //debug(this); + //debug(cellval); + // build main options before element iteration + opts = $.extend({}, $.jgrid.formatter, opts); + return this.each(function() { + //debug("in the each"); + $this = $(this); + //for the metaplugin if it exists + var o = $.meta ? $.extend({}, opts, $this.data()) : opts; + //debug("firing formatter"); + fireFormatter($this,formatType,cellval, opts, act); + }); + }; + $.fmatter.util = { + // Taken from YAHOO utils + NumberFormat : function(nData,opts) { + if(!isNumber(nData)) { + nData *= 1; + } + if(isNumber(nData)) { + var bNegative = (nData < 0); + var sOutput = nData + ""; + var sDecimalSeparator = (opts.decimalSeparator) ? opts.decimalSeparator : "."; + var nDotIndex; + if(isNumber(opts.decimalPlaces)) { + // Round to the correct decimal place + var nDecimalPlaces = opts.decimalPlaces; + var nDecimal = Math.pow(10, nDecimalPlaces); + sOutput = Math.round(nData*nDecimal)/nDecimal + ""; + nDotIndex = sOutput.lastIndexOf("."); + if(nDecimalPlaces > 0) { + // Add the decimal separator + if(nDotIndex < 0) { + sOutput += sDecimalSeparator; + nDotIndex = sOutput.length-1; + } + // Replace the "." + else if(sDecimalSeparator !== "."){ + sOutput = sOutput.replace(".",sDecimalSeparator); + } + // Add missing zeros + while((sOutput.length - 1 - nDotIndex) < nDecimalPlaces) { + sOutput += "0"; + } + } + } + if(opts.thousandsSeparator) { + var sThousandsSeparator = opts.thousandsSeparator; + nDotIndex = sOutput.lastIndexOf(sDecimalSeparator); + nDotIndex = (nDotIndex > -1) ? nDotIndex : sOutput.length; + var sNewOutput = sOutput.substring(nDotIndex); + var nCount = -1; + for (var i=nDotIndex; i>0; i--) { + nCount++; + if ((nCount%3 === 0) && (i !== nDotIndex) && (!bNegative || (i > 1))) { + sNewOutput = sThousandsSeparator + sNewOutput; + } + sNewOutput = sOutput.charAt(i-1) + sNewOutput; + } + sOutput = sNewOutput; + } + // Prepend prefix + sOutput = (opts.prefix) ? opts.prefix + sOutput : sOutput; + // Append suffix + sOutput = (opts.suffix) ? sOutput + opts.suffix : sOutput; + return sOutput; + + } else { + return nData; + } + }, + // Tony Tomov + // PHP implementation. Sorry not all options are supported. + // Feel free to add them if you want + DateFormat : function (format, date, newformat, opts) { + var token = /\\.|[dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU]/g, + timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, + timezoneClip = timezoneClip = /[^-+\dA-Z]/g, + pad = function (value, length) { + value = String(value); + length = parseInt(length) || 2; + while (value.length < length) value = '0' + value; + return value; + }, + ts = {m : 1, d : 1, y : 1970, h : 0, i : 0, s : 0}, + timestamp=0, + dateFormat=["i18n"]; + // Internationalization strings + dateFormat["i18n"] = { + dayNames: opts.dayNames, + monthNames: opts.monthNames + }; + format = format.toLowerCase(); + date = date.split(/[\\\/:_;.tT\s-]/); + format = format.split(/[\\\/:_;.tT\s-]/); + // !!!!!!!!!!!!!!!!!!!!!! + // Here additional code to parse for month names + // !!!!!!!!!!!!!!!!!!!!!! + for(var i=0;i= 70 && ty <= 99) ts.y = 1900+ts.y; + else if (ty >=0 && ty <=69) ts.y= 2000+ts.y; + timestamp = new Date(ts.y, ts.m, ts.d, ts.h, ts.i, ts.s,0); + if( opts.masks.newformat ) { + newformat = opts.masks.newformat; + } else if ( !newformat ) { + newformat = 'Y-m-d'; + } + var + G = timestamp.getHours(), + i = timestamp.getMinutes(), + j = timestamp.getDate(), + n = timestamp.getMonth() + 1, + o = timestamp.getTimezoneOffset(), + s = timestamp.getSeconds(), + u = timestamp.getMilliseconds(), + w = timestamp.getDay(), + Y = timestamp.getFullYear(), + N = (w + 6) % 7 + 1, + z = (new Date(Y, n - 1, j) - new Date(Y, 0, 1)) / 86400000, + flags = { + // Day + d: pad(j), + D: dateFormat.i18n.dayNames[w], + j: j, + l: dateFormat.i18n.dayNames[w + 7], + N: N, + S: opts.S(j), + //j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th', + w: w, + z: z, + // Week + W: N < 5 ? Math.floor((z + N - 1) / 7) + 1 : Math.floor((z + N - 1) / 7) || ((new Date(Y - 1, 0, 1).getDay() + 6) % 7 < 4 ? 53 : 52), + // Month + F: dateFormat.i18n.monthNames[n - 1 + 12], + m: pad(n), + M: dateFormat.i18n.monthNames[n - 1], + n: n, + t: '?', + // Year + L: '?', + o: '?', + Y: Y, + y: String(Y).substring(2), + // Time + a: G < 12 ? opts.AmPm[0] : opts.AmPm[1], + A: G < 12 ? opts.AmPm[2] : opts.AmPm[3], + B: '?', + g: G % 12 || 12, + G: G, + h: pad(G % 12 || 12), + H: pad(G), + i: pad(i), + s: pad(s), + u: u, + // Timezone + e: '?', + I: '?', + O: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), + P: '?', + T: (String(timestamp).match(timezone) || [""]).pop().replace(timezoneClip, ""), + Z: '?', + // Full Date/Time + c: '?', + r: '?', + U: Math.floor(timestamp / 1000) + }; + return newformat.replace(token, function ($0) { + return $0 in flags ? flags[$0] : $0.substring(1); + }); + } + }; + $.fn.fmatter.defaultFormat = function(el, cellval, opts) { + $(el).html((isValue(cellval) && cellval!=="" ) ? cellval : " "); + }; + $.fn.fmatter.email = function(el, cellval, opts) { + if(!isEmpty(cellval)) { + $(el).html("" + cellval + ""); + }else { + $.fn.fmatter.defaultFormat(el, cellval); + } + }; + $.fn.fmatter.checkbox =function(el,cval,opts) { + var op = $.extend({},opts.checkbox), ds; + if(!isUndefined(opts.colModel.formatoptions)) { + op = $.extend({},op,opts.colModel.formatoptions); + } + if(op.disabled===true) {ds = "disabled";} else {ds="";} + cval=cval+""; cval=cval.toLowerCase(); + var bchk = cval.search(/(false|0|no|off)/i)<0 ? " checked=\"checked\"" : ""; + $(el).html(""); + }, + $.fn.fmatter.link = function(el,cellval,opts) { + if(!isEmpty(cellval)) { + $(el).html("" + cellval + ""); + }else { + $(el).html(isValue(cellval) ? cellval : ""); + } + }; + $.fn.fmatter.showlink = function(el,cellval,opts) { + var op = {baseLinkUrl: opts.baseLinkUrl,showAction:opts.showAction, addParam: opts.addParam }; + if(!isUndefined(opts.colModel.formatoptions)) { + op = $.extend({},op,opts.colModel.formatoptions); + } + idUrl = op.baseLinkUrl+op.showAction + '?id='+opts.rowId+op.addParam; + if(isString(cellval)) { //add this one even if its blank string + $(el).html("" + cellval + ""); + }else { + $.fn.fmatter.defaultFormat(el, cellval); + } + }; + $.fn.fmatter.integer = function(el,cellval,opts) { + var op = $.extend({},opts.integer); + if(!isUndefined(opts.colModel.formatoptions)) { + op = $.extend({},op,opts.colModel.formatoptions); + } + if(isEmpty(cellval)) { + cellval = op.defaultValue || 0; + } + $(el).html($.fmatter.util.NumberFormat(cellval,op)); + }; + $.fn.fmatter.number = function (el,cellval, opts) { + var op = $.extend({},opts.number); + if(!isUndefined(opts.colModel.formatoptions)) { + op = $.extend({},op,opts.colModel.formatoptions); + } + if(isEmpty(cellval)) { + cellval = op.defaultValue || 0; + } + $(el).html($.fmatter.util.NumberFormat(cellval,op)); + }; + $.fn.fmatter.currency = function (el,cellval, opts) { + var op = $.extend({},opts.currency); + if(!isUndefined(opts.colModel.formatoptions)) { + op = $.extend({},op,opts.colModel.formatoptions); + } + if(isEmpty(cellval)) { + cellval = op.defaultValue || 0; + } + $(el).html($.fmatter.util.NumberFormat(cellval,op)); + }; + $.fn.fmatter.date = function (el, cellval, opts, act) { + var op = $.extend({},opts.date); + if(!isUndefined(opts.colModel.formatoptions)) { + op = $.extend({},op,opts.colModel.formatoptions); + } + if(!op.reformatAfterEdit && act=='edit'){ + $.fn.fmatter.defaultFormat(el,cellval); + } else if(!isEmpty(cellval)) { + var ndf = $.fmatter.util.DateFormat(op.srcformat,cellval,op.newformat,op); + $(el).html(ndf); + } else { + $.fn.fmatter.defaultFormat(el,cellval); + } + }; + $.fn.fmatter.select = function (el, cellval,opts, act) { + // jqGrid specific + if(act=='edit') { + $.fn.fmatter.defaultFormat(el,cellval); + } else if (!isEmpty(cellval)) { + var oSelect = false; + if(!isUndefined(opts.colModel.editoptions)){ + oSelect= opts.colModel.editoptions.value; + } + if (oSelect) { + var ret = []; + var msl = opts.colModel.editoptions.multiple === true ? true : false; + var scell = []; + if(msl) { scell = cellval.split(","); scell = $.map(scell,function(n){return $.trim(n);})} + if (isString(oSelect)) { + // mybe here we can use some caching with care ???? + var so = oSelect.split(";"), j=0; + for(var i=0; i-1) { + ret[j] = sv[1]; + j++; + } + } else if($.trim(sv[0])==$.trim(cellval)) { + ret[0] = sv[1]; + break; + } + } + } else if(isObject(oSelect)) { + // this is quicker + if(msl) { + ret = jQuery.map(scel, function(n, i){ + return oSelect[n]; + }); + } + ret[0] = oSelect[cellval] || ""; + } + $(el).html(ret.join(", ")); + } else { + $.fn.fmatter.defaultFormat(el,cellval); + } + } + }; + $.unformat = function (cellval,options,pos,cnt) { + // specific for jqGrid only + var ret, formatType = options.colModel.formatter, op =options.colModel.formatoptions || {}; + if(formatType !== 'undefined' && isString(formatType) ) { + var opts = $.jgrid.formatter || {}, stripTag; + switch(formatType) { + case 'link' : + case 'showlink' : + case 'email' : + ret= $(cellval).text(); + break; + case 'integer' : + op = $.extend({},opts.integer,op); + stripTag = eval("/"+op.thousandsSeparator+"/g"); + ret = $(cellval).text().replace(stripTag,''); + break; + case 'number' : + op = $.extend({},opts.number,op); + stripTag = eval("/"+op.thousandsSeparator+"/g"); + ret = $(cellval).text().replace(op.decimalSeparator,'.').replace(stripTag,""); + break; + case 'currency': + op = $.extend({},opts.currency,op); + stripTag = eval("/"+op.thousandsSeparator+"/g"); + ret = $(cellval).text().replace(op.decimalSeparator,'.').replace(op.prefix,'').replace(op.suffix,'').replace(stripTag,''); + break; + case 'checkbox' : + var cbv = (options.colModel.editoptions) ? options.colModel.editoptions.value.split(":") : ["Yes","No"]; + ret = $('input',cellval).attr("checked") ? cbv[0] : cbv[1]; + break; + } + } + //else { + // Here aditional code to run custom unformater + //} + return ret ? ret : cnt===true ? $(cellval).text() : $.htmlDecode($(cellval).html()); + }; + function fireFormatter(el,formatType,cellval, opts, act) { + //debug("in formatter with " +formatType); + formatType = formatType.toLowerCase(); + switch (formatType) { + case 'link': $.fn.fmatter.link(el, cellval, opts); break; + case 'showlink': $.fn.fmatter.showlink(el, cellval, opts); break; + case 'email': $.fn.fmatter.email(el, cellval, opts); break; + case 'currency': $.fn.fmatter.currency(el, cellval, opts); break; + case 'date': $.fn.fmatter.date(el, cellval, opts, act); break; + case 'number': $.fn.fmatter.number(el, cellval, opts) ; break; + case 'integer': $.fn.fmatter.integer(el, cellval, opts) ; break; + case 'checkbox': $.fn.fmatter.checkbox(el, cellval, opts); break; + case 'select': $.fn.fmatter.select(el, cellval, opts,act); break; + //case 'textbox': s.transparent = false; break; + } + }; + //private methods and data + function debug($obj) { + if (window.console && window.console.log) window.console.log($obj); + }; + /** + * A convenience method for detecting a legitimate non-null value. + * Returns false for null/undefined/NaN, true for other values, + * including 0/false/'' + * --taken from the yui.lang + */ + isValue= function(o) { + return (isObject(o) || isString(o) || isNumber(o) || isBoolean(o)); + }; + isBoolean= function(o) { + return typeof o === 'boolean'; + }; + isNull= function(o) { + return o === null; + }; + isNumber= function(o) { + return typeof o === 'number' && isFinite(o); + }; + isString= function(o) { + return typeof o === 'string'; + }; + /** + * check if its empty trim it and replace \  and \  with '' and check if its empty ==="" + * if its is not a string but has a value then it returns false, Returns true for null/undefined/NaN + essentailly this provdes a way to see if it has any value to format for things like links + */ + isEmpty= function(o) { + if(!isString(o) && isValue(o)) { + return false; + }else if (!isValue(o)){ + return true; + } + o = $.trim(o).replace(/\ \;/ig,'').replace(/\ \;/ig,''); + return o===""; + + }; + isUndefined= function(o) { + return typeof o === 'undefined'; + }; + isObject= function(o) { + return (o && (typeof o === 'object' || isFunction(o))) || false; + }; + isFunction= function(o) { + return typeof o === 'function'; + }; + +})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/jquery.tablednd.js b/site/vendors/js/jqGrid/js/jquery.tablednd.js new file mode 100644 index 0000000..c0e00f1 --- /dev/null +++ b/site/vendors/js/jqGrid/js/jquery.tablednd.js @@ -0,0 +1,383 @@ +/** + * TableDnD plug-in for JQuery, allows you to drag and drop table rows + * You can set up various options to control how the system will work + * Copyright (c) Denis Howlett + * Licensed like jQuery, see http://docs.jquery.com/License. + * + * Configuration options: + * + * onDragStyle + * This is the style that is assigned to the row during drag. There are limitations to the styles that can be + * associated with a row (such as you can't assign a border--well you can, but it won't be + * displayed). (So instead consider using onDragClass.) The CSS style to apply is specified as + * a map (as used in the jQuery css(...) function). + * onDropStyle + * This is the style that is assigned to the row when it is dropped. As for onDragStyle, there are limitations + * to what you can do. Also this replaces the original style, so again consider using onDragClass which + * is simply added and then removed on drop. + * onDragClass + * This class is added for the duration of the drag and then removed when the row is dropped. It is more + * flexible than using onDragStyle since it can be inherited by the row cells and other content. The default + * is class is tDnD_whileDrag. So to use the default, simply customise this CSS class in your + * stylesheet. + * onDrop + * Pass a function that will be called when the row is dropped. The function takes 2 parameters: the table + * and the row that was dropped. You can work out the new order of the rows by using + * table.rows. + * onDragStart + * Pass a function that will be called when the user starts dragging. The function takes 2 parameters: the + * table and the row which the user has started to drag. + * onAllowDrop + * Pass a function that will be called as a row is over another row. If the function returns true, allow + * dropping on that row, otherwise not. The function takes 2 parameters: the dragged row and the row under + * the cursor. It returns a boolean: true allows the drop, false doesn't allow it. + * scrollAmount + * This is the number of pixels to scroll if the user moves the mouse cursor to the top or bottom of the + * window. The page should automatically scroll up or down as appropriate (tested in IE6, IE7, Safari, FF2, + * FF3 beta + * dragHandle + * This is the name of a class that you assign to one or more cells in each row that is draggable. If you + * specify this class, then you are responsible for setting cursor: move in the CSS and only these cells + * will have the drag behaviour. If you do not specify a dragHandle, then you get the old behaviour where + * the whole row is draggable. + * + * Other ways to control behaviour: + * + * Add class="nodrop" to any rows for which you don't want to allow dropping, and class="nodrag" to any rows + * that you don't want to be draggable. + * + * Inside the onDrop method you can also call $.tableDnD.serialize() this returns a string of the form + * []=&[]= so that you can send this back to the server. The table must have + * an ID as must all the rows. + * + * Other methods: + * + * $("...").tableDnDUpdate() + * Will update all the matching tables, that is it will reapply the mousedown method to the rows (or handle cells). + * This is useful if you have updated the table rows using Ajax and you want to make the table draggable again. + * The table maintains the original configuration (so you don't have to specify it again). + * + * $("...").tableDnDSerialize() + * Will serialize and return the serialized string as above, but for each of the matching tables--so it can be + * called from anywhere and isn't dependent on the currentTable being set up correctly before calling + * + * Known problems: + * - Auto-scoll has some problems with IE7 (it scrolls even when it shouldn't), work-around: set scrollAmount to 0 + * + * Version 0.2: 2008-02-20 First public version + * Version 0.3: 2008-02-07 Added onDragStart option + * Made the scroll amount configurable (default is 5 as before) + * Version 0.4: 2008-03-15 Changed the noDrag/noDrop attributes to nodrag/nodrop classes + * Added onAllowDrop to control dropping + * Fixed a bug which meant that you couldn't set the scroll amount in both directions + * Added serialize method + * Version 0.5: 2008-05-16 Changed so that if you specify a dragHandle class it doesn't make the whole row + * draggable + * Improved the serialize method to use a default (and settable) regular expression. + * Added tableDnDupate() and tableDnDSerialize() to be called when you are outside the table + */ +jQuery.tableDnD = { + /** Keep hold of the current table being dragged */ + currentTable : null, + /** Keep hold of the current drag object if any */ + dragObject: null, + /** The current mouse offset */ + mouseOffset: null, + /** Remember the old value of Y so that we don't do too much processing */ + oldY: 0, + + /** Actually build the structure */ + build: function(options) { + // Set up the defaults if any + + this.each(function() { + // This is bound to each matching table, set up the defaults and override with user options + this.tableDnDConfig = jQuery.extend({ + onDragStyle: null, + onDropStyle: null, + // Add in the default class for whileDragging + onDragClass: "tDnD_whileDrag", + onDrop: null, + onDragStart: null, + scrollAmount: 5, + serializeRegexp: /[^\-]*$/, // The regular expression to use to trim row IDs + serializeParamName: null, // If you want to specify another parameter name instead of the table ID + dragHandle: null // If you give the name of a class here, then only Cells with this class will be draggable + }, options || {}); + // Now make the rows draggable + jQuery.tableDnD.makeDraggable(this); + }); + + // Now we need to capture the mouse up and mouse move event + // We can use bind so that we don't interfere with other event handlers + jQuery(document) + .bind('mousemove', jQuery.tableDnD.mousemove) + .bind('mouseup', jQuery.tableDnD.mouseup); + + // Don't break the chain + return this; + }, + + /** This function makes all the rows on the table draggable apart from those marked as "NoDrag" */ + makeDraggable: function(table) { + var config = table.tableDnDConfig; + if (table.tableDnDConfig.dragHandle) { + // We only need to add the event to the specified cells + var cells = jQuery("td."+table.tableDnDConfig.dragHandle, table); + cells.each(function() { + // The cell is bound to "this" + jQuery(this).mousedown(function(ev) { + jQuery.tableDnD.dragObject = this.parentNode; + jQuery.tableDnD.currentTable = table; + jQuery.tableDnD.mouseOffset = jQuery.tableDnD.getMouseOffset(this, ev); + if (config.onDragStart) { + // Call the onDrop method if there is one + config.onDragStart(table, this); + } + return false; + }); + }) + } else { + // For backwards compatibility, we add the event to the whole row + var rows = jQuery("tr", table); // get all the rows as a wrapped set + rows.each(function() { + // Iterate through each row, the row is bound to "this" + var row = jQuery(this); + if (! row.hasClass("nodrag")) { + row.mousedown(function(ev) { + if (ev.target.tagName == "TD") { + jQuery.tableDnD.dragObject = this; + jQuery.tableDnD.currentTable = table; + jQuery.tableDnD.mouseOffset = jQuery.tableDnD.getMouseOffset(this, ev); + if (config.onDragStart) { + // Call the onDrop method if there is one + config.onDragStart(table, this); + } + return false; + } + }).css("cursor", "move"); // Store the tableDnD object + } + }); + } + }, + + updateTables: function() { + this.each(function() { + // this is now bound to each matching table + if (this.tableDnDConfig) { + jQuery.tableDnD.makeDraggable(this); + } + }) + }, + + /** Get the mouse coordinates from the event (allowing for browser differences) */ + mouseCoords: function(ev){ + if(ev.pageX || ev.pageY){ + return {x:ev.pageX, y:ev.pageY}; + } + return { + x:ev.clientX + document.body.scrollLeft - document.body.clientLeft, + y:ev.clientY + document.body.scrollTop - document.body.clientTop + }; + }, + + /** Given a target element and a mouse event, get the mouse offset from that element. + To do this we need the element's position and the mouse position */ + getMouseOffset: function(target, ev) { + ev = ev || window.event; + + var docPos = this.getPosition(target); + var mousePos = this.mouseCoords(ev); + return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y}; + }, + + /** Get the position of an element by going up the DOM tree and adding up all the offsets */ + getPosition: function(e){ + var left = 0; + var top = 0; + /** Safari fix -- thanks to Luis Chato for this! */ + if (e.offsetHeight == 0) { + /** Safari 2 doesn't correctly grab the offsetTop of a table row + this is detailed here: + http://jacob.peargrove.com/blog/2006/technical/table-row-offsettop-bug-in-safari/ + the solution is likewise noted there, grab the offset of a table cell in the row - the firstChild. + note that firefox will return a text node as a first child, so designing a more thorough + solution may need to take that into account, for now this seems to work in firefox, safari, ie */ + e = e.firstChild; // a table cell + } + if (e && e.offsetParent) { + while (e.offsetParent){ + left += e.offsetLeft; + top += e.offsetTop; + e = e.offsetParent; + } + + left += e.offsetLeft; + top += e.offsetTop; + } + + return {x:left, y:top}; + }, + + mousemove: function(ev) { + if (jQuery.tableDnD.dragObject == null) { + return; + } + + var dragObj = jQuery(jQuery.tableDnD.dragObject); + var config = jQuery.tableDnD.currentTable.tableDnDConfig; + var mousePos = jQuery.tableDnD.mouseCoords(ev); + var y = mousePos.y - jQuery.tableDnD.mouseOffset.y; + //auto scroll the window + var yOffset = window.pageYOffset; + if (document.all) { + // Windows version + //yOffset=document.body.scrollTop; + if (typeof document.compatMode != 'undefined' && + document.compatMode != 'BackCompat') { + yOffset = document.documentElement.scrollTop; + } + else if (typeof document.body != 'undefined') { + yOffset=document.body.scrollTop; + } + + } + + if (mousePos.y-yOffset < config.scrollAmount) { + window.scrollBy(0, -config.scrollAmount); + } else { + var windowHeight = window.innerHeight ? window.innerHeight + : document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight; + if (windowHeight-(mousePos.y-yOffset) < config.scrollAmount) { + window.scrollBy(0, config.scrollAmount); + } + } + + + if (y != jQuery.tableDnD.oldY) { + // work out if we're going up or down... + var movingDown = y > jQuery.tableDnD.oldY; + // update the old value + jQuery.tableDnD.oldY = y; + // update the style to show we're dragging + if (config.onDragClass) { + dragObj.addClass(config.onDragClass); + } else { + dragObj.css(config.onDragStyle); + } + // If we're over a row then move the dragged row to there so that the user sees the + // effect dynamically + var currentRow = jQuery.tableDnD.findDropTargetRow(dragObj, y); + if (currentRow) { + // TODO worry about what happens when there are multiple TBODIES + if (movingDown && jQuery.tableDnD.dragObject != currentRow) { + jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow.nextSibling); + } else if (! movingDown && jQuery.tableDnD.dragObject != currentRow) { + jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow); + } + } + } + + return false; + }, + + /** We're only worried about the y position really, because we can only move rows up and down */ + findDropTargetRow: function(draggedRow, y) { + var rows = jQuery.tableDnD.currentTable.rows; + for (var i=0; i rowY - rowHeight) && (y < (rowY + rowHeight))) { + // that's the row we're over + // If it's the same as the current row, ignore it + if (row == draggedRow) {return null;} + var config = jQuery.tableDnD.currentTable.tableDnDConfig; + if (config.onAllowDrop) { + if (config.onAllowDrop(draggedRow, row)) { + return row; + } else { + return null; + } + } else { + // If a row has nodrop class, then don't allow dropping (inspired by John Tarr and Famic) + var nodrop = jQuery(row).hasClass("nodrop"); + if (! nodrop) { + return row; + } else { + return null; + } + } + return row; + } + } + return null; + }, + + mouseup: function(e) { + if (jQuery.tableDnD.currentTable && jQuery.tableDnD.dragObject) { + var droppedRow = jQuery.tableDnD.dragObject; + var config = jQuery.tableDnD.currentTable.tableDnDConfig; + // If we have a dragObject, then we need to release it, + // The row will already have been moved to the right place so we just reset stuff + if (config.onDragClass) { + jQuery(droppedRow).removeClass(config.onDragClass); + } else { + jQuery(droppedRow).css(config.onDropStyle); + } + jQuery.tableDnD.dragObject = null; + if (config.onDrop) { + // Call the onDrop method if there is one + config.onDrop(jQuery.tableDnD.currentTable, droppedRow); + } + jQuery.tableDnD.currentTable = null; // let go of the table too + } + }, + + serialize: function() { + if (jQuery.tableDnD.currentTable) { + return jQuery.tableDnD.serializeTable(jQuery.tableDnD.currentTable); + } else { + return "Error: No Table id set, you need to set an id on your table and every row"; + } + }, + + serializeTable: function(table) { + var result = ""; + var tableId = table.id; + var rows = table.rows; + for (var i=0; i 0) result += "&"; + var rowId = rows[i].id; + if (rowId && rowId && table.tableDnDConfig && table.tableDnDConfig.serializeRegexp) { + rowId = rowId.match(table.tableDnDConfig.serializeRegexp)[0]; + } + + result += tableId + '[]=' + rowId; + } + return result; + }, + + serializeTables: function() { + var result = ""; + this.each(function() { + // this is now bound to each matching table + result += jQuery.tableDnD.serializeTable(this); + }); + return result; + } + +} + +jQuery.fn.extend( + { + tableDnD : jQuery.tableDnD.build, + tableDnDUpdate : jQuery.tableDnD.updateTables, + tableDnDSerialize: jQuery.tableDnD.serializeTables + } +); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/json2.js b/site/vendors/js/jqGrid/js/json2.js new file mode 100644 index 0000000..fe8c416 --- /dev/null +++ b/site/vendors/js/jqGrid/js/json2.js @@ -0,0 +1,104 @@ +/* +org: 'http://www.JSON.org', + copyright: '(c)2005 JSON.org', + license: 'http://www.crockford.com/JSON/license.html', + + Some modifications and additions from Tony Tomov + Added parse function to prevent JSON Hijacking + Read below +*/ +var JSON = { + stringify: function stringify(arg) { + var c, i, l, s = '', v; + switch (typeof arg) { + case 'object': + if (arg) { + if (arg.constructor == Array) { + for (i = 0; i < arg.length; ++i) { + v = stringify(arg[i]); + if (s) { + s += ','; + } + s += v; + } + return '[' + s + ']'; + } else if (typeof arg.toString != 'undefined') { + for (i in arg) { + v = stringify(arg[i]); + if (typeof v != 'function') { + if (s) { + s += ','; + } + s += stringify(i) + ':' + v; + } + } + return '{' + s + '}'; + } + } + return 'null'; + case 'number': + return isFinite(arg) ? String(arg) : 'null'; + case 'string': + l = arg.length; + s = '"'; + for (i = 0; i < l; i += 1) { + c = arg.charAt(i); + if (c >= ' ') { + if (c == '\\' || c == '"') { + s += '\\'; + } + s += c; + } else { + switch (c) { + case '\b': + s += '\\b'; + break; + case '\f': + s += '\\f'; + break; + case '\n': + s += '\\n'; + break; + case '\r': + s += '\\r'; + break; + case '\t': + s += '\\t'; + break; + default: + c = c.charCodeAt(); + s += '\\u00' + Math.floor(c / 16).toString(16) + + (c % 16).toString(16); + } + } + } + return s + '"'; + case 'boolean': + return String(arg); + case 'function' : + // Added for use of jqGrid T. Tomov + return arg.toString(); + default: + return 'null'; + } + }, + // Read this if you want to protect your json return string + // http://safari.oreilly.com/9780596514839/recipe-1107 + // + // 1.The while(1); construct, located at the beginning of JSON text, + // 2.Comments at the beginning and end of the text. + // JSON data providers are encouraged to use one or both of these methods + // to prevent data execution. Such JSON response may then look like this: + // while(1);/*{[ + // {"name":"safe value 1"}, + // {"name":"safe value 2"}, + // ... + // ]}*/ + parse : function(jsonString) { + // filter out while statement + var js = jsonString; + if (js.substr(0,9) == "while(1);") { js = js.substr(9); } + if (js.substr(0,2) == "/*") { js = js.substr(2,js.length-4); } + return eval('('+js+')'); + } +} diff --git a/site/vendors/js/jqGrid/js/min/JsonXml-min.js b/site/vendors/js/jqGrid/js/min/JsonXml-min.js new file mode 100644 index 0000000..a186fef --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/JsonXml-min.js @@ -0,0 +1 @@ +var xmlJsonClass={xml2json:function(b,d){if(b.nodeType===9){b=b.documentElement}var a=this.removeWhite(b);var e=this.toObj(a);var c=this.toJson(e,b.nodeName,"\t");return"{\n"+d+(d?c.replace(/\t/g,d):c.replace(/\t|\n/g,""))+"\n}"},json2xml:function(d,c){var e=function(q,f,h){var o="";var l,g;if(q instanceof Array){if(q.length===0){o+=h+"<"+f+">__EMPTY_ARRAY_\n"}else{for(l=0,g=q.length;l":"/>";if(k){for(j in q){if(q.hasOwnProperty(j)){if(j==="#text"){o+=q[j]}else{if(j==="#cdata"){o+=""}else{if(j.charAt(0)!=="@"){o+=e(q[j],j,h+"\t")}}}}}o+=(o.charAt(o.length-1)==="\n"?h:"")+""}}else{if(typeof(q)==="function"){o+=h+"<"+f+">"}else{if(q.toString()==='""'||q.toString().length===0){o+=h+"<"+f+">__EMPTY_STRING_"}else{o+=h+"<"+f+">"+q.toString()+""}}}}return o};var b="";var a;for(a in d){if(d.hasOwnProperty(a)){b+=e(d[a],a,"")}}return c?b.replace(/\t/g,c):b.replace(/\t|\n/g,"")},parseXml:function(c){var a;try{var d=new DOMParser();a=d.parseFromString(c,"text/xml")}catch(b){a=new ActiveXObject("Microsoft.XMLDOM");a.async=false;a.loadXML(c)}return(a&&a.documentElement&&a.documentElement.tagName!="parsererror")?a:null},toObj:function(b){var g={};var f=/function/i;if(b.nodeType===1){if(b.attributes.length){var e;for(e=0;e1){g=this.escape(this.innerXml(b))}else{for(h=b.firstChild;h;h=h.nextSibling){if(f.test(b.firstChild.nodeValue)){g=b.firstChild.nodeValue;break}else{g["#cdata"]=this.escape(h.nodeValue)}}}}}}}if(!b.attributes.length&&!b.firstChild){g=null}}else{if(b.nodeType===9){g=this.toObj(b.documentElement)}else{alert("unhandled node type: "+b.nodeType)}}return g},toJson:function(b,a,d){var j=a?('"'+a+'"'):"";if(b==="[]"){j+=(a?":[]":"[]")}else{if(b instanceof Array){var c,f;for(f=0,c=b.length;f1?("\n"+d+"\t"+b.join(",\n"+d+"\t")+"\n"+d):b.join(""))+"]"}else{if(b===null){j+=(a&&":")+"null"}else{if(typeof(b)==="object"){var g=[];var e;for(e in b){if(b.hasOwnProperty(e)){g[g.length]=this.toJson(b[e],e,d+"\t")}}j+=(a?":{":"{")+(g.length>1?("\n"+d+"\t"+g.join(",\n"+d+"\t")+"\n"+d):g.join(""))+"}"}else{if(typeof(b)==="string"){var h=/(^-?\d+\.?\d*$)/;var k=/function/i;b=b.toString();if(h.test(b)||k.test(b)||b==="false"||b==="true"){j+=(a&&":")+b}else{j+=(a&&":")+'"'+b+'"'}}else{j+=(a&&":")+b.toString()}}}}}return j},innerXml:function(d){var b="";if("innerHTML" in d){b=d.innerHTML}else{var a=function(j){var g="",f;if(j.nodeType===1){g+="<"+j.nodeName;for(f=0;f"}else{g+="/>"}}else{if(j.nodeType===3){g+=j.nodeValue}else{if(j.nodeType===4){g+=""}}}return g};for(var e=d.firstChild;e;e=e.nextSibling){b+=a(e)}}return b},escape:function(a){return a.replace(/[\\]/g,"\\\\").replace(/[\"]/g,'\\"').replace(/[\n]/g,"\\n").replace(/[\r]/g,"\\r")},removeWhite:function(b){b.normalize();var c;for(c=b.firstChild;c;){if(c.nodeType===3){if(!c.nodeValue.match(/[^ \f\n\r\t\v]/)){var a=c.nextSibling;b.removeChild(c);c=a}else{c=c.nextSibling}}else{if(c.nodeType===1){this.removeWhite(c);c=c.nextSibling}else{c=c.nextSibling}}}return b}}; \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.base-min.js b/site/vendors/js/jqGrid/js/min/grid.base-min.js new file mode 100644 index 0000000..c134b2f --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.base-min.js @@ -0,0 +1 @@ +(function($){$.fn.jqGrid=function(p){p=$.extend(true,{url:"",height:150,page:1,rowNum:20,records:0,pager:"",pgbuttons:true,pginput:true,colModel:[],rowList:[],colNames:[],sortorder:"asc",sortname:"",datatype:"xml",mtype:"GET",imgpath:"",sortascimg:"sort_asc.gif",sortdescimg:"sort_desc.gif",firstimg:"first.gif",previmg:"prev.gif",nextimg:"next.gif",lastimg:"last.gif",altRows:true,selarrrow:[],savedRow:[],shrinkToFit:true,xmlReader:{},jsonReader:{},subGrid:false,subGridModel:[],lastpage:0,lastsort:0,selrow:null,beforeSelectRow:null,onSelectRow:null,onSortCol:null,ondblClickRow:null,onRightClickRow:null,onPaging:null,onSelectAll:null,loadComplete:null,gridComplete:null,loadError:null,loadBeforeSend:null,afterInsertRow:null,beforeRequest:null,onHeaderClick:null,viewrecords:false,loadonce:false,multiselect:false,multikey:false,editurl:null,search:false,searchdata:{},caption:"",hidegrid:true,hiddengrid:false,postData:{},userData:{},treeGrid:false,treeGridModel:"nested",treeReader:{},treeANode:0,ExpandColumn:null,tree_root_level:0,prmNames:{page:"page",rows:"rows",sort:"sidx",order:"sord"},sortclass:"grid_sort",resizeclass:"grid_resize",forceFit:false,gridstate:"visible",cellEdit:false,cellsubmit:"remote",nv:0,loadui:"enable",toolbar:[false,""],scroll:false,multiboxonly:false,scrollrows:false,deselectAfterSort:true},$.jgrid.defaults,p||{});var grid={headers:[],cols:[],dragStart:function(i,x){this.resizing={idx:i,startX:x};this.hDiv.style.cursor="e-resize"},dragMove:function(x){if(this.resizing){var diff=x-this.resizing.startX,h=this.headers[this.resizing.idx],newWidth=h.width+diff,hn,nWn;if(newWidth>25){if(p.forceFit===true){hn=this.headers[this.resizing.idx+p.nv];nWn=hn.width-diff;if(nWn>25){h.el.style.width=newWidth+"px";h.newWidth=newWidth;this.cols[this.resizing.idx].style.width=newWidth+"px";hn.el.style.width=nWn+"px";hn.newWidth=nWn;this.cols[this.resizing.idx+p.nv].style.width=nWn+"px";this.newWidth=this.width}}else{h.el.style.width=newWidth+"px";h.newWidth=newWidth;this.cols[this.resizing.idx].style.width=newWidth+"px";this.newWidth=this.width+diff;$("table:first",this.bDiv).css("width",this.newWidth+"px");$("table:first",this.hDiv).css("width",this.newWidth+"px");this.hDiv.scrollLeft=this.bDiv.scrollLeft}}}},dragEnd:function(){this.hDiv.style.cursor="default";if(this.resizing){var idx=this.resizing.idx;this.headers[idx].width=this.headers[idx].newWidth||this.headers[idx].width;this.cols[idx].style.width=this.headers[idx].newWidth||this.headers[idx].width;if(p.forceFit===true){this.headers[idx+p.nv].width=this.headers[idx+p.nv].newWidth||this.headers[idx+p.nv].width;this.cols[idx+p.nv].style.width=this.headers[idx+p.nv].newWidth||this.headers[idx+p.nv].width}if(this.newWidth){this.width=this.newWidth}this.resizing=false}},scrollGrid:function(){if(p.scroll===true){var scrollTop=this.bDiv.scrollTop;if(scrollTop!=this.scrollTop){this.scrollTop=scrollTop;if((this.bDiv.scrollHeight-scrollTop-$(this.bDiv).height())<=0){if(parseInt(p.page,10)+1<=parseInt(p.lastpage,10)){p.page=parseInt(p.page,10)+1;this.populate()}}}}this.hDiv.scrollLeft=this.bDiv.scrollLeft}};$.fn.getGridParam=function(pName){var $t=this[0];if(!$t.grid){return}if(!pName){return $t.p}else{return $t.p[pName]?$t.p[pName]:null}};$.fn.setGridParam=function(newParams){return this.each(function(){if(this.grid&&typeof(newParams)==="object"){$.extend(true,this.p,newParams)}})};$.fn.getDataIDs=function(){var ids=[];this.each(function(){$(this.rows).slice(1).each(function(i){ids[i]=this.id})});return ids};$.fn.setSortName=function(newsort){return this.each(function(){var $t=this;for(var i=0;i<$t.p.colModel.length;i++){if($t.p.colModel[i].name===newsort||$t.p.colModel[i].index===newsort){$("tr th:eq("+$t.p.lastsort+") div img",$t.grid.hDiv).remove();$t.p.lastsort=i;$t.p.sortname=newsort;break}}})};$.fn.setSelection=function(selection,onsr,sd){return this.each(function(){var $t=this,stat,pt,ind;onsr=onsr===false?false:true;if(selection===false){pt=sd}else{ind=$($t).getInd($t.rows,selection);pt=$($t.rows[ind])}selection=$(pt).attr("id");if(!pt.html()){return}if($t.p.selrow&&$t.p.scrollrows===true){var olr=$($t).getInd($t.rows,$t.p.selrow);var ner=$($t).getInd($t.rows,selection);if(ner>=0){if(ner>olr){scrGrid(ner,"d")}else{scrGrid(ner,"u")}}}if(!$t.p.multiselect){if($(pt).attr("class")!=="subgrid"){if($t.p.selrow){$("tr#"+$t.p.selrow.replace(".","\\."),$t.grid.bDiv).removeClass("selected")}$t.p.selrow=selection;$(pt).addClass("selected");if($t.p.onSelectRow&&onsr){$t.p.onSelectRow($t.p.selrow,true)}}}else{$t.p.selrow=selection;var ia=$.inArray($t.p.selrow,$t.p.selarrrow);if(ia===-1){if($(pt).attr("class")!=="subgrid"){$(pt).addClass("selected")}stat=true;$("#jqg_"+$t.p.selrow.replace(".","\\."),$t.rows).attr("checked",stat);$t.p.selarrrow.push($t.p.selrow);if($t.p.onSelectRow&&onsr){$t.p.onSelectRow($t.p.selrow,stat)}}else{if($(pt).attr("class")!=="subgrid"){$(pt).removeClass("selected")}stat=false;$("#jqg_"+$t.p.selrow.replace(".","\\."),$t.rows).attr("checked",stat);$t.p.selarrrow.splice(ia,1);if($t.p.onSelectRow&&onsr){$t.p.onSelectRow($t.p.selrow,stat)}var tpsr=$t.p.selarrrow[0];$t.p.selrow=(tpsr==undefined)?null:tpsr}}function scrGrid(iR,tp){var ch=$($t.grid.bDiv)[0].clientHeight,st=$($t.grid.bDiv)[0].scrollTop,nROT=$t.rows[iR].offsetTop+$t.rows[iR].clientHeight,pROT=$t.rows[iR].offsetTop;if(tp=="d"){if(nROT>=ch){$($t.grid.bDiv)[0].scrollTop=st+nROT-pROT}}if(tp=="u"){if(pROT span:first",t.rows[ind])}else{ttd=$("td:eq("+i+")",t.rows[ind])}t.formatter(ttd,t.rows[ind],vl,i,"edit");success=true}})}});return success};$.fn.addRowData=function(rowid,data,pos,src){if(!pos){pos="last"}var success=false,nm,row,td,gi=0,si=0,sind,i;if(data){this.each(function(){var t=this;row=document.createElement("tr");row.id=rowid||t.p.records+1;$(row).addClass("jqgrow");if(t.p.multiselect){td=$("");$(td[0],t.grid.bDiv).html("");row.appendChild(td[0]);gi=1}if(t.p.subGrid){try{$(t).addSubGrid(t.grid.bDiv,row,gi)}catch(e){}si=1}for(i=gi+si;i");t.formatter(td,row,data[nm],i,"add");t.formatCol($(td[0],t.grid.bDiv),i);row.appendChild(td[0])}switch(pos){case"last":$(t.rows[t.rows.length-1]).after(row);break;case"first":$(t.rows[0]).after(row);break;case"after":sind=$(t).getInd(t.rows,src);sind>=0?$(t.rows[sind]).after(row):"";break;case"before":sind=$(t).getInd(t.rows,src);sind>0?$(t.rows[sind-1]).after(row):"";break}t.p.records++;if($.browser.safari||$.browser.opera){t.scrollLeft=t.scrollLeft;$("td",t.rows[1]).each(function(k){$(this).css("width",t.grid.headers[k].width+"px");t.grid.cols[k]=this})}if(t.p.altRows===true){if(pos=="last"){if(t.rows.length%2==1){$(row).addClass("alt")}}else{$(t.rows).slice(1).each(function(i){if(i%2==1){$(this).addClass("alt")}else{$(this).removeClass("alt")}})}}try{t.p.afterInsertRow(row.id,data)}catch(e){}t.updatepager();success=true})}return success};$.fn.hideCol=function(colname){return this.each(function(){var $t=this,w=0,fndh=false,gtw;if(!$t.grid){return}if(typeof colname=="string"){colname=[colname]}$(this.p.colModel).each(function(i){if($.inArray(this.name,colname)!=-1&&!this.hidden){w=parseInt($("tr th:eq("+i+")",$t.grid.hDiv).css("width"),10);$("tr th:eq("+i+")",$t.grid.hDiv).css({display:"none"});$($t.rows).each(function(j){$("td:eq("+i+")",$t.rows[j]).css({display:"none"})});$t.grid.cols[i].style.width=0;$t.grid.headers[i].width=0;$t.grid.width-=w;this.hidden=true;fndh=true}});if(fndh===true){gtw=Math.min($t.p._width,$t.grid.width);$("table:first",$t.grid.hDiv).width(gtw);$("table:first",$t.grid.bDiv).width(gtw);$($t.grid.hDiv).width(gtw);$($t.grid.bDiv).width(gtw);if($t.p.pager&&$($t.p.pager).hasClass("scroll")){$($t.p.pager).width(gtw)}if($t.p.caption){$($t.grid.cDiv).width(gtw)}if($t.p.toolbar[0]){$($t.grid.uDiv).width(gtw)}$t.grid.hDiv.scrollLeft=$t.grid.bDiv.scrollLeft}})};$.fn.showCol=function(colname){return this.each(function(){var $t=this,w=0,fdns=false,gtw,ofl;if(!$t.grid){return}if(typeof colname=="string"){colname=[colname]}$($t.p.colModel).each(function(i){if($.inArray(this.name,colname)!=-1&&this.hidden){w=parseInt($("tr th:eq("+i+")",$t.grid.hDiv).css("width"),10);$("tr th:eq("+i+")",$t.grid.hDiv).css("display","");$($t.rows).each(function(j){$("td:eq("+i+")",$t.rows[j]).css("display","").width(w)});this.hidden=false;$t.grid.cols[i].style.width=w;$t.grid.headers[i].width=w;$t.grid.width+=w;fdns=true}});if(fdns===true){gtw=Math.min($t.p._width,$t.grid.width);ofl=($t.grid.width<=$t.p._width)?"hidden":"auto";$("table:first",$t.grid.hDiv).width(gtw);$("table:first",$t.grid.bDiv).width(gtw);$($t.grid.hDiv).width(gtw);$($t.grid.bDiv).width(gtw).css("overflow-x",ofl);if($t.p.pager&&$($t.p.pager).hasClass("scroll")){$($t.p.pager).width(gtw)}if($t.p.caption){$($t.grid.cDiv).width(gtw)}if($t.p.toolbar[0]){$($t.grid.uDiv).width(gtw)}$t.grid.hDiv.scrollLeft=$t.grid.bDiv.scrollLeft}})};$.fn.setGridWidth=function(nwidth,shrink){return this.each(function(){var $t=this,chw=0,w,cw,ofl;if(!$t.grid){return}if(typeof shrink!="boolean"){shrink=true}var testdata=getScale();if(shrink!==true){testdata[0]=Math.min($t.p._width,$t.grid.width);testdata[2]=0}else{testdata[2]=testdata[1]}$.each($t.p.colModel,function(i,v){if(!this.hidden&&this.name!="cb"&&this.name!="subgrid"){cw=shrink!==true?$("tr:first th:eq("+i+")",$t.grid.hDiv).css("width"):this.width;w=Math.floor((IENum(nwidth)-IENum(testdata[2]))/IENum(testdata[0])*IENum(cw));chw+=w;$("table thead tr:first th:eq("+i+")",$t.grid.hDiv).css("width",w+"px");$("table:first tbody tr:first td:eq("+i+")",$t.grid.bDiv).css("width",w+"px");$t.grid.cols[i].style.width=w;$t.grid.headers[i].width=w}if(this.name=="cb"||this.name=="subgrid"){chw+=IENum(this.width)}});if(chw+testdata[1]<=nwidth||$t.p.forceFit===true){ofl="hidden";tw=nwidth}else{ofl="auto";tw=chw+testdata[1]}$("table:first",$t.grid.hDiv).width(tw);$("table:first",$t.grid.bDiv).width(tw);$($t.grid.hDiv).width(nwidth);$($t.grid.bDiv).width(nwidth).css("overflow-x",ofl);if($t.p.pager&&$($t.p.pager).hasClass("scroll")){$($t.p.pager).width(nwidth)}if($t.p.caption){$($t.grid.cDiv).width(nwidth)}if($t.p.toolbar[0]){$($t.grid.uDiv).width(nwidth)}$t.p._width=nwidth;$t.grid.width=tw;if($.browser.safari||$.browser.opera){$("table tbody tr:eq(1) td",$t.grid.bDiv).each(function(k){$(this).css("width",$t.grid.headers[k].width+"px");$t.grid.cols[k]=this})}$t.grid.hDiv.scrollLeft=$t.grid.bDiv.scrollLeft;function IENum(val){val=parseInt(val,10);return isNaN(val)?0:val}function getScale(){var testcell=$("table tr:first th:eq(1)",$t.grid.hDiv);var addpix=IENum($(testcell).css("padding-left"))+IENum($(testcell).css("padding-right"))+IENum($(testcell).css("border-left-width"))+IENum($(testcell).css("border-right-width"));var w=0,ap=0;$.each($t.p.colModel,function(i,v){if(!this.hidden){w+=parseInt(this.width);ap+=addpix}});return[w,ap,0]}})};$.fn.setGridHeight=function(nh){return this.each(function(){var ovfl,ovfl2,$t=this;if(!$t.grid){return}if($t.p.forceFit===true){ovfl2="hidden"}else{ovfl2=$($t.grid.bDiv).css("overflow-x")}ovfl=(isNaN(nh)&&$.browser.mozilla&&(nh.indexOf("%")!=-1||nh=="auto"))?"hidden":"auto";$($t.grid.bDiv).css({height:nh+(isNaN(nh)?"":"px"),"overflow-y":ovfl,"overflow-x":ovfl2});$t.p.height=nh})};$.fn.setCaption=function(newcap){return this.each(function(){this.p.caption=newcap;$("table:first th",this.grid.cDiv).html(newcap);$(this.grid.cDiv).show()})};$.fn.setLabel=function(colname,nData,prop,attrp){return this.each(function(){var $t=this,pos=-1;if(!$t.grid){return}if(isNaN(colname)){$($t.p.colModel).each(function(i){if(this.name==colname){pos=i;return false}})}else{pos=parseInt(colname,10)}if(pos>=0){var thecol=$("table:first th:eq("+pos+")",$t.grid.hDiv);if(nData){$("div",thecol).html(nData)}if(prop){if(typeof prop=="string"){$(thecol).addClass(prop)}else{$(thecol).css(prop)}}if(typeof attrp=="object"){$(thecol).attr(attrp)}}})};$.fn.setCell=function(rowid,colname,nData,cssp,attrp){return this.each(function(){var $t=this,pos=-1;if(!$t.grid){return}if(isNaN(colname)){$($t.p.colModel).each(function(i){if(this.name==colname){pos=i;return false}})}else{pos=parseInt(colname,10)}if(pos>=0){var ind=$($t).getInd($t.rows,rowid);if(ind>=0){var tcell=$("td:eq("+pos+")",$t.rows[ind]);if(nData!=""){$t.formatter(tcell,$t.rows[ind],nData,pos,"edit")}if(cssp){if(typeof cssp=="string"){$(tcell).addClass(cssp)}else{$(tcell).css(cssp)}}if(typeof attrp=="object"){$(tcell).attr(attrp)}}}})};$.fn.getCell=function(rowid,col){var ret=false;this.each(function(){var $t=this,pos=-1;if(!$t.grid){return}if(isNaN(col)){$($t.p.colModel).each(function(i){if(this.name==col){pos=i;return false}})}else{pos=parseInt(col,10)}if(pos>=0){var ind=$($t).getInd($t.rows,rowid);if(ind>=0){ret=$.htmlDecode($("td:eq("+pos+")",$t.rows[ind]).html())}}});return ret};$.fn.clearGridData=function(){return this.each(function(){var $t=this;if(!$t.grid){return}$("tbody tr:gt(0)",$t.grid.bDiv).remove();$t.p.selrow=null;$t.p.selarrrow=[];$t.p.savedRow=[];$t.p.records="0";$t.p.page="0";$t.p.lastpage="0";$t.updatepager()})};$.fn.getInd=function(obj,rowid,rc){var ret=false;$(obj).each(function(i){if(this.id==rowid){ret=rc===true?this:i;return false}});return ret};$.htmlDecode=function(value){if(value==" "||value==" "||(value.length==1&&value.charCodeAt(0)==160)){return""}return !value?value:String(value).replace(/&/g,"&").replace(/>/g,">").replace(/</g,"<").replace(/"/g,'"')};return this.each(function(){if(this.grid){return}this.p=p;if(this.p.colNames.length===0){for(var i=0;i

    "+this.p.loadtext+"
    ").insertBefore(this);$(this).attr({cellSpacing:"0",cellPadding:"0",border:"0"});var ts=this,bSR=$.isFunction(this.p.beforeSelectRow)?this.p.beforeSelectRow:false,onSelectRow=$.isFunction(this.p.onSelectRow)?this.p.onSelectRow:false,ondblClickRow=$.isFunction(this.p.ondblClickRow)?this.p.ondblClickRow:false,onSortCol=$.isFunction(this.p.onSortCol)?this.p.onSortCol:false,loadComplete=$.isFunction(this.p.loadComplete)?this.p.loadComplete:false,loadError=$.isFunction(this.p.loadError)?this.p.loadError:false,loadBeforeSend=$.isFunction(this.p.loadBeforeSend)?this.p.loadBeforeSend:false,onRightClickRow=$.isFunction(this.p.onRightClickRow)?this.p.onRightClickRow:false,afterInsRow=$.isFunction(this.p.afterInsertRow)?this.p.afterInsertRow:false,onHdCl=$.isFunction(this.p.onHeaderClick)?this.p.onHeaderClick:false,beReq=$.isFunction(this.p.beforeRequest)?this.p.beforeRequest:false,onSC=$.isFunction(this.p.onCellSelect)?this.p.onCellSelect:false,sortkeys=["shiftKey","altKey","ctrlKey"];if($.inArray(ts.p.multikey,sortkeys)==-1){ts.p.multikey=false}var IntNum=function(val,defval){val=parseInt(val,10);if(isNaN(val)){return(defval)?defval:0}else{return val}};var formatCol=function(elem,pos){var ral=ts.p.colModel[pos].align;if(ral){$(elem).css("text-align",ral)}if(ts.p.colModel[pos].hidden){$(elem).css("display","none")}};var resizeFirstRow=function(t,er){$("tbody tr:eq("+er+") td",t).each(function(k){$(this).css("width",grid.headers[k].width+"px");grid.cols[k]=this})};var addCell=function(t,row,cell,pos){var td;td=document.createElement("td");formatter($(td,t),row,cell,pos,"add");row.appendChild(td);formatCol($(td,t),pos)};var formatter=function(elem,row,cellval,colpos,act){var cm=ts.p.colModel[colpos];if(cm.formatter){var opts={rowId:row.id,colModel:cm,rowData:row};if($.isFunction(cm.formatter)){cm.formatter(elem,cellval,opts,act)}else{if($.fmatter){$(elem).fmatter(cm.formatter,cellval,opts,act)}else{$(elem).html(cellval||" ")}}}else{$(elem).html(cellval||" ")}elem[0].title=elem[0].textContent||elem[0].innerText};var addMulti=function(t,row){var cbid,td;td=document.createElement("td");cbid="jqg_"+row.id;$(td,t).html("");formatCol($(td,t),0);row.appendChild(td)};var reader=function(datatype){var field,f=[],j=0,i;for(i=0;i=ts.p.keyIndex)?$(f[ts.p.keyIndex],trow).text():$(ts.p.xmlReader.cell+":eq("+ts.p.keyIndex+")",trow).text()}}$(ts.p.xmlReader.page,xml).each(function(){ts.p.page=this.textContent||this.text});$(ts.p.xmlReader.total,xml).each(function(){ts.p.lastpage=this.textContent||this.text});$(ts.p.xmlReader.records,xml).each(function(){ts.p.records=this.textContent||this.text});$(ts.p.xmlReader.userdata,xml).each(function(){ts.p.userData[this.getAttribute("name")]=this.textContent||this.text});$(ts.p.xmlReader.root+" "+ts.p.xmlReader.row,xml).each(function(j){row=document.createElement("tr");row.id=getId(this,j+1);if(ts.p.multiselect){addMulti(t,row);gi=1}if(ts.p.subGrid){try{$(ts).addSubGrid(t,row,gi,this)}catch(e){}si=1}if(ts.p.xmlReader.repeatitems===true){$(ts.p.xmlReader.cell,this).each(function(i){v=this.textContent||this.text;addCell(t,row,v,i+gi+si);rd[ts.p.colModel[i+gi+si].name]=v})}else{for(var i=0;i0&&!isNaN(idn)){idn=f[idn]}}else{idn=f.length>0?f[ts.p.keyIndex]:ts.p.keyIndex}drows=data[ts.p.jsonReader.root];if(drows){for(i=0;i0){try{sv=$.unformat($(row).children("td").eq(col),{colModel:ts.p.colModel[col]},col,true)}catch(_){sv=$(row).children("td").eq(col).text()}row.sortKey=findSortKey(sv);rows[index-1]=this}});if(ts.p.treeGrid){$(ts).SortTree(newDir)}else{rows.sort(function(a,b){if(a.sortKeyb.sortKey){return newDir}return 0});$.each(rows,function(index,row){$("tbody",ts.grid.bDiv).append(row);row.sortKey=null})}if(isSafari||isOpera){resizeFirstRow(ts.grid.bDiv,1)}if(ts.p.multiselect){$("tbody tr:gt(0)",ts.grid.bDiv).removeClass("selected");$("[id^=jqg_]",ts.rows).attr("checked",false);$("#cb_jqg",ts.grid.hDiv).attr("checked",false);ts.p.selarrrow=[]}if(ts.p.altRows===true){$("tbody tr:gt(0)",ts.grid.bDiv).removeClass("alt");$("tbody tr:odd",ts.grid.bDiv).addClass("alt")}ts.grid.bDiv.scrollTop=0;endReq()};var parseDate=function(format,date){var tsp={m:1,d:1,y:1970,h:0,i:0,s:0};format=format.toLowerCase();date=date.split(/[\\\/:_;.\s-]/);format=format.split(/[\\\/:_;.\s-]/);for(var i=0;i=70&&ty<=99){tsp.y=1900+tsp.y}else{if(ty>=0&&ty<=69){tsp.y=2000+tsp.y}}return new Date(tsp.y,tsp.m,tsp.d,tsp.h,tsp.i,tsp.s,0)};var setPager=function(){var inpt="":"",pgl="",pgr="",str,clearVals=function(){ts.p.selrow=null;if(ts.p.multiselect){ts.p.selarrrow=[];$("#cb_jqg",ts.grid.hDiv).attr("checked",false)}ts.p.savedRow=[]};if(ts.p.viewrecords===true){pginp+=" "}if(ts.p.pgbuttons===true){pgl=inpt+" id='first'/>  "+inpt+" id='prev'/> ";pgr=inpt+" id='next' />  "+inpt+" id='last'/>"}$(ts.p.pager).append(pgl+pginp+pgr);if(ts.p.rowList.length>0){str="";$(ts.p.pager).append(" "+str+" ");$(ts.p.pager).find("select").bind("change",function(){ts.p.rowNum=this.value;if(typeof ts.p.onPaging=="function"){ts.p.onPaging("records")}clearVals();populate()})}else{$(ts.p.pager).append(" ")}if(ts.p.pgbuttons===true){$(".pgbuttons",ts.p.pager).mouseover(function(e){if($(this).attr("disabled")=="true"){this.style.cursor="auto"}else{this.style.cursor="pointer"}return false}).mouseout(function(e){this.style.cursor="default";return false});$("#first, #prev, #next, #last",ts.p.pager).click(function(e){var cp=IntNum(ts.p.page),last=IntNum(ts.p.lastpage),selclick=false,fp=true,pp=true,np=true,lp=true;if(last===0||last===1){fp=false;pp=false;np=false;lp=false}else{if(last>1&&cp>=1){if(cp===1){fp=false;pp=false}else{if(cp>1&&cp1&&cp===0){np=false;lp=false;cp=last-1}}}if(this.id==="first"&&fp){ts.p.page=1;selclick=true}if(this.id==="prev"&&pp){ts.p.page=(cp-1);selclick=true}if(this.id==="next"&&np){ts.p.page=(cp+1);selclick=true}if(this.id==="last"&&lp){ts.p.page=last;selclick=true}if(selclick){if(typeof ts.p.onPaging=="function"){ts.p.onPaging(this.id)}clearVals();populate()}e.stopPropagation();return false})}if(ts.p.pginput===true){$("input.selbox",ts.p.pager).keypress(function(e){var key=e.charCode?e.charCode:e.keyCode?e.keyCode:0;if(key==13){ts.p.page=($(this).val()>0)?$(this).val():ts.p.page;if(typeof ts.p.onPaging=="function"){ts.p.onPaging("user")}clearVals();populate();return false}return this})}};var sortData=function(index,idxcol,reload){var imgs,so,scg,ls,iId;if(ts.p.savedRow.length>0){return}if(!reload){if(ts.p.lastsort===idxcol){if(ts.p.sortorder==="asc"){ts.p.sortorder="desc"}else{if(ts.p.sortorder==="desc"){ts.p.sortorder="asc"}}}else{ts.p.sortorder="asc"}ts.p.page=1}imgs=(ts.p.sortorder==="asc")?ts.p.sortascimg:ts.p.sortdescimg;imgs="";var thd=$("thead:first",grid.hDiv).get(0);ls=ts.p.colModel[ts.p.lastsort].name.replace(".","\\.");$("tr th div#jqgh_"+ls+" img",thd).remove();$("tr th div#jqgh_"+ls,thd).parent().removeClass(ts.p.sortclass);iId=index.replace(".","\\.");$("tr th div#"+iId,thd).append(imgs).parent().addClass(ts.p.sortclass);ts.p.lastsort=idxcol;index=index.substring(5);ts.p.sortname=ts.p.colModel[idxcol].index||index;so=ts.p.sortorder;if(onSortCol){onSortCol(index,idxcol,so)}if(ts.p.datatype=="local"){if(ts.p.deselectAfterSort){$(ts).resetSelection()}}else{ts.p.selrow=null;if(ts.p.multiselect){$("#cb_jqg",ts.grid.hDiv).attr("checked",false)}ts.p.selarrrow=[];ts.p.savedRow=[]}scg=ts.p.scroll;if(ts.p.scroll===true){ts.p.scroll=false}if(ts.p.subGrid&&ts.p.datatype=="local"){$("td.sgexpanded","#"+ts.p.id).each(function(){$(this).trigger("click")})}populate();if(ts.p.sortname!=index&&idxcol){ts.p.lastsort=idxcol}setTimeout(function(){ts.p.scroll=scg},500)};var setColWidth=function(){var initwidth=0;for(var l=0;l");this.p.colModel.unshift({name:"cb",width:27,sortable:false,resizable:false,hidedlg:true,search:false})}var xReader={root:"rows",row:"row",page:"rows>page",total:"rows>total",records:"rows>records",repeatitems:true,cell:"cell",id:"[id]",userdata:"userdata",subgrid:{root:"rows",row:"row",repeatitems:true,cell:"cell"}};var jReader={root:"rows",page:"page",total:"total",records:"records",repeatitems:true,cell:"cell",id:"id",userdata:"userdata",subgrid:{root:"rows",repeatitems:true,cell:"cell"}};if(ts.p.scroll===true){ts.p.pgbuttons=false;ts.p.pginput=false;ts.p.pgtext=false;ts.p.rowList=[]}ts.p.xmlReader=$.extend(xReader,ts.p.xmlReader);ts.p.jsonReader=$.extend(jReader,ts.p.jsonReader);$.each(ts.p.colModel,function(i){this.width=IntNum(this.width,150)});if(ts.p.width){setColWidth()}var thead=document.createElement("thead");var trow=document.createElement("tr");thead.appendChild(trow);var i=0,th,idn,thdiv;if(ts.p.shrinkToFit===true&&ts.p.forceFit===true){for(i=ts.p.colModel.length-1;i>=0;i--){if(!ts.p.colModel[i].hidden){ts.p.colModel[i].resizable=false;break}}}for(i=0;i";$(thdiv).append(imgs);ts.p.lastsort=i;$(th).addClass(ts.p.sortclass)}thdiv.id="jqgh_"+idn;th.appendChild(thdiv);trow.appendChild(th)}if(this.p.multiselect){var onSA=true,chk,emp=[];if(typeof ts.p.onSelectAll!=="function"){onSA=false}$("#cb_jqg",trow).bind("click",function(){if(this.checked){$("[id^=jqg_]",ts.rows).attr("checked",true);$(ts.rows).slice(1).each(function(i){if(!$(this).hasClass("subgrid")){$(this).addClass("selected");ts.p.selarrrow[i]=ts.p.selrow=this.id}});chk=true;emp=[]}else{$("[id^=jqg_]",ts.rows).attr("checked",false);$(ts.rows).slice(1).each(function(i){if(!$(this).hasClass("subgrid")){$(this).removeClass("selected");emp[i]=this.id}});ts.p.selarrrow=[];ts.p.selrow=null;chk=false}if(onSA){ts.p.onSelectAll(chk?ts.p.selarrrow:emp,chk)}})}this.appendChild(thead);thead=$("thead:first",ts).get(0);var w,res,sort;$("tr:first th",thead).each(function(j){w=ts.p.colModel[j].width;if(typeof ts.p.colModel[j].resizable==="undefined"){ts.p.colModel[j].resizable=true}res=document.createElement("span");$(res).html(" ");if(ts.p.colModel[j].resizable){$(this).addClass(ts.p.resizeclass);$(res).mousedown(function(e){if(ts.p.forceFit===true){ts.p.nv=nextVisible(j)}grid.dragStart(j,e.clientX);e.preventDefault();return false})}else{res=""}$(this).css("width",w+"px").prepend(res);if(ts.p.colModel[j].hidden){$(this).css("display","none")}grid.headers[j]={width:w,el:this};sort=ts.p.colModel[j].sortable;if(typeof sort!=="boolean"){sort=true}if(sort){$("div",this).css("cursor","pointer").click(function(){sortData(this.id,j);return false})}});var isMSIE=$.browser.msie?true:false,isMoz=$.browser.mozilla?true:false,isOpera=$.browser.opera?true:false,isSafari=$.browser.safari?true:false,td,ptr,gw=0,hdc=0,tbody=document.createElement("tbody");trow=document.createElement("tr");trow.id="_empty";tbody.appendChild(trow);for(i=0;i"+ts.p.loadtext+"
    ").addClass("grid_hdiv").append(grid.hTable).bind("selectstart",function(){return false});if(hg){$(grid.hDiv).hide();ts.p.gridstate="hidden"}if(ts.p.pager){if(typeof ts.p.pager=="string"){if(ts.p.pager.substr(0,1)!="#"){ts.p.pager="#"+ts.p.pager}}if($(ts.p.pager).hasClass("scroll")){$(ts.p.pager).css({width:grid.width+"px",overflow:"hidden"}).show();ts.p._height=parseInt($(ts.p.pager).height(),10);if(hg){$(ts.p.pager).hide()}}setPager()}if(ts.p.cellEdit===false){$(ts).mouseover(function(e){td=(e.target||e.srcElement);ptr=$(td,ts.rows).parents("tr:first");if($(ptr).hasClass("jqgrow")){$(ptr).addClass("over")}return false}).mouseout(function(e){td=(e.target||e.srcElement);ptr=$(td,ts.rows).parents("tr:first");$(ptr).removeClass("over");return false})}var ri,ci;$(ts).before(grid.hDiv).css("width",grid.width+"px").click(function(e){td=(e.target||e.srcElement);if(td.href){return true}var scb=$(td).hasClass("cbox");ptr=$(td,ts.rows).parents("tr.jqgrow");if($(ptr).length===0){return false}var cSel=true;if(bSR){cSel=bSR(ptr.attr("id"))}if(cSel===true){if(ts.p.cellEdit===true){if(ts.p.multiselect&&scb){$(ts).setSelection(false,true,ptr)}else{ri=ptr[0].rowIndex;ci=!$(td).is("td")?$(td).parents("td:first")[0].cellIndex:td.cellIndex;try{$(ts).editCell(ri,ci,true,true)}catch(e){}}}else{if(!ts.p.multikey){if(ts.p.multiselect&&ts.p.multiboxonly){if(scb){$(ts).setSelection(false,true,ptr)}}else{$(ts).setSelection(false,true,ptr)}}else{if(e[ts.p.multikey]){$(ts).setSelection(false,true,ptr)}else{if(ts.p.multiselect&&scb){scb=$("[id^=jqg_]",ptr).attr("checked");$("[id^=jqg_]",ptr).attr("checked",!scb)}}}}if(onSC){ri=ptr[0].id;ci=!$(td).is("td")?$(td).parents("td:first")[0].cellIndex:td.cellIndex;onSC(ri,ci,$(td).html(),td)}}e.stopPropagation()}).bind("reloadGrid",function(e){if(ts.p.treeGrid===true){ts.p.datatype=ts.p.treedatatype}if(ts.p.datatype=="local"){$(ts).resetSelection()}else{if(!ts.p.treeGrid){ts.p.selrow=null;if(ts.p.multiselect){ts.p.selarrrow=[];$("#cb_jqg",ts.grid.hDiv).attr("checked",false)}if(ts.p.cellEdit){ts.p.savedRow=[]}}}populate()});if(ondblClickRow){$(this).dblclick(function(e){td=(e.target||e.srcElement);ptr=$(td,ts.rows).parents("tr.jqgrow");if($(ptr).length===0){return false}ts.p.ondblClickRow($(ptr).attr("id"));return false})}if(onRightClickRow){$(this).bind("contextmenu",function(e){td=(e.target||e.srcElement);ptr=$(td,ts.rows).parents("tr.jqgrow");if($(ptr).length===0){return false}if(!ts.p.multiselect){$(ts).setSelection(false,true,ptr)}ri=ptr[0].id;ci=!$(td).is("td")?$(td).parents("td:first")[0].cellIndex:td.cellIndex;ts.p.onRightClickRow($(ptr).attr("id"),ri,ci);return false})}grid.bDiv=document.createElement("div");var ofl2=(isNaN(ts.p.height)&&isMoz&&(ts.p.height.indexOf("%")!=-1||ts.p.height=="auto"))?"hidden":"auto";$(grid.bDiv).addClass("grid_bdiv").scroll(function(e){grid.scrollGrid()}).css({height:ts.p.height+(isNaN(ts.p.height)?"":"px"),padding:"0px",margin:"0px",overflow:ofl2,width:(grid.width)+"px"}).css("overflow-x","hidden").append(this);$("table:first",grid.bDiv).css({width:grid.width+"px"});if(isMSIE){if($("tbody",this).size()===2){$("tbody:first",this).remove()}if(ts.p.multikey){$(grid.bDiv).bind("selectstart",function(){return false})}if(ts.p.treeGrid){$(grid.bDiv).css("position","relative")}}else{if(ts.p.multikey){$(grid.bDiv).bind("mousedown",function(){return false})}}if(hg){$(grid.bDiv).hide()}grid.cDiv=document.createElement("div");$(grid.cDiv).append(""+((ts.p.hidegrid===true)?"":"")+"
    "+ts.p.caption+"
    ").addClass("GridHeader").width(grid.width);$(grid.cDiv).insertBefore(grid.hDiv);if(ts.p.toolbar[0]){grid.uDiv=document.createElement("div");if(ts.p.toolbar[1]=="top"){$(grid.uDiv).insertBefore(grid.hDiv)}else{$(grid.uDiv).insertAfter(grid.hDiv)}$(grid.uDiv).width(grid.width).addClass("userdata").attr("id","t_"+this.id);ts.p._height+=parseInt($(grid.uDiv).height(),10);if(hg){$(grid.uDiv).hide()}}if(ts.p.caption){ts.p._height+=parseInt($(grid.cDiv,ts).height(),10);var tdt=ts.p.datatype;if(ts.p.hidegrid===true){$(".HeaderButton",grid.cDiv).toggle(function(){if(ts.p.pager){$(ts.p.pager).slideUp()}if(ts.p.toolbar[0]){$(grid.uDiv,ts).slideUp()}$(grid.bDiv).hide();$(grid.hDiv).slideUp();$("img",this).attr("src",ts.p.imgpath+"down.gif");ts.p.gridstate="hidden";if(onHdCl){if(!hg){ts.p.onHeaderClick(ts.p.gridstate)}}},function(){$(grid.hDiv).slideDown();$(grid.bDiv).show();if(ts.p.pager){$(ts.p.pager).slideDown()}if(ts.p.toolbar[0]){$(grid.uDiv).slideDown()}$("img",this).attr("src",ts.p.imgpath+"up.gif");if(hg){ts.p.datatype=tdt;populate();hg=false}ts.p.gridstate="visible";if(onHdCl){ts.p.onHeaderClick(ts.p.gridstate)}});if(hg){$(".HeaderButton",grid.cDiv).trigger("click");ts.p.datatype="local"}}}else{$(grid.cDiv).hide()}ts.p._height+=parseInt($(grid.hDiv,ts).height(),10);$(grid.hDiv).mousemove(function(e){grid.dragMove(e.clientX);return false}).after(grid.bDiv);$(document).mouseup(function(e){if(grid.resizing){grid.dragEnd();if(grid.newWidth&&ts.p.forceFit===false){var gwdt=(grid.width<=ts.p._width)?grid.width:ts.p._width;var overfl=(grid.width<=ts.p._width)?"hidden":"auto";if(ts.p.pager&&$(ts.p.pager).hasClass("scroll")){$(ts.p.pager).width(gwdt)}if(ts.p.caption){$(grid.cDiv).width(gwdt)}if(ts.p.toolbar[0]){$(grid.uDiv).width(gwdt)}$(grid.bDiv).width(gwdt).css("overflow-x",overfl);$(grid.hDiv).width(gwdt)}return false}return true});ts.formatCol=function(a,b){formatCol(a,b)};ts.sortData=function(a,b,c){sortData(a,b,c)};ts.updatepager=function(){updatepager()};ts.formatter=function(elem,row,cellval,colpos,act){formatter(elem,row,cellval,colpos,act)};$.extend(grid,{populate:function(){populate()}});this.grid=grid;ts.addXmlData=function(d){addXmlData(d,ts.grid.bDiv)};ts.addJSONData=function(d){addJSONData(d,ts.grid.bDiv)};populate();if(!ts.p.shrinkToFit){ts.p.forceFit=false;$("tr:first th",thead).each(function(j){var w=ts.p.colModel[j].owidth;var diff=w-ts.p.colModel[j].width;if(diff>0&&!ts.p.colModel[j].hidden){grid.headers[j].width=w;$(this).add(grid.cols[j]).width(w);$("table:first",grid.bDiv).add(grid.hTable).width(ts.grid.width);ts.grid.width+=diff;grid.hDiv.scrollLeft=grid.bDiv.scrollLeft}});ofl2=(grid.width<=ts.p._width)?"hidden":"auto";$(grid.bDiv).css({"overflow-x":ofl2})}$(window).unload(function(){$(this).unbind("*");this.grid=null;this.p=null})})}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.celledit-min.js b/site/vendors/js/jqGrid/js/min/grid.celledit-min.js new file mode 100644 index 0000000..0cdfb5b --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.celledit-min.js @@ -0,0 +1 @@ +(function(a){a.fn.extend({editCell:function(e,d,c,b){return this.each(function(){var m=this,q,n,j;if(!m.grid||m.p.cellEdit!==true){return}var f=null;if(a.browser.msie&&a.browser.version<=7&&c===true&&b===true){d=o(m.rows[e],d)}d=parseInt(d,10);m.p.selrow=m.rows[e].id;if(!m.p.knv){a(m).GridNav()}if(m.p.savedRow.length>0){if(c===true){if(e==m.p.iRow&&d==m.p.iCol){return}}var k=a("td:eq("+m.p.savedRow[0].ic+")>#"+m.p.savedRow[0].id+"_"+m.p.savedRow[0].name.replace(".","\\."),m.rows[m.p.savedRow[0].id]).val();if(m.p.savedRow[0].v!=k){a(m).saveCell(m.p.savedRow[0].id,m.p.savedRow[0].ic)}else{a(m).restoreCell(m.p.savedRow[0].id,m.p.savedRow[0].ic)}}else{window.setTimeout(function(){a("#"+m.p.knv).attr("tabindex","-1").focus()},0)}q=m.p.colModel[d].name;if(q=="subgrid"){return}if(m.p.colModel[d].editable===true&&c===true){j=a("td:eq("+d+")",m.rows[e]);if(parseInt(m.p.iCol)>=0&&parseInt(m.p.iRow)>=0){a("td:eq("+m.p.iCol+")",m.rows[m.p.iRow]).removeClass("edit-cell");a(m.rows[m.p.iRow]).removeClass("selected-row")}a(j).addClass("edit-cell");a(m.rows[e]).addClass("selected-row");try{n=a.unformat(j,{colModel:m.p.colModel[d]},d)}catch(p){n=a(j).html()}var h=a.extend(m.p.colModel[d].editoptions||{},{id:e+"_"+q,name:q});if(!m.p.colModel[d].edittype){m.p.colModel[d].edittype="text"}m.p.savedRow[0]={id:e,ic:d,name:q,v:n};if(a.isFunction(m.p.formatCell)){var l=m.p.formatCell(m.rows[e].id,q,n,e,d);if(l){n=l}}var g=createEl(m.p.colModel[d].edittype,h,n,j);if(a.isFunction(m.p.beforeEditCell)){m.p.beforeEditCell(m.rows[e].id,q,n,e,d)}a(j).html("").append(g);window.setTimeout(function(){a(g).focus()},0);a("input, select, textarea",j).bind("keydown",function(r){if(r.keyCode===27){a(m).restoreCell(e,d)}if(r.keyCode===13){a(m).saveCell(e,d)}if(r.keyCode==9){if(r.shiftKey){a(m).prevCell(e,d)}else{a(m).nextCell(e,d)}}r.stopPropagation()});if(a.isFunction(m.p.afterEditCell)){m.p.afterEditCell(m.rows[e].id,q,n,e,d)}}else{if(parseInt(m.p.iCol)>=0&&parseInt(m.p.iRow)>=0){a("td:eq("+m.p.iCol+")",m.rows[m.p.iRow]).removeClass("edit-cell");a(m.rows[m.p.iRow]).removeClass("selected-row")}a("td:eq("+d+")",m.rows[e]).addClass("edit-cell");a(m.rows[e]).addClass("selected-row");if(a.isFunction(m.p.onSelectCell)){n=a("td:eq("+d+")",m.rows[e]).html().replace(/\ \;/ig,"");m.p.onSelectCell(m.rows[e].id,q,n,e,d)}}m.p.iCol=d;m.p.iRow=e;function o(v,s){var w=0;var u=0;for(i=0;is){return i}}return i}})},saveCell:function(c,b){return this.each(function(){var h=this,q,k;if(!h.grid||h.p.cellEdit!==true){return}if(h.p.savedRow.length==1){k=0}else{k=null}if(k!=null){var d=a("td:eq("+b+")",h.rows[c]),p,n;q=h.p.colModel[b].name;switch(h.p.colModel[b].edittype){case"select":p=a("#"+c+"_"+q.replace(".","\\.")+">option:selected",h.rows[c]).val();n=a("#"+c+"_"+q.replace(".","\\.")+">option:selected",h.rows[c]).text();break;case"checkbox":var f=["Yes","No"];if(h.p.colModel[b].editoptions){f=h.p.colModel[b].editoptions.value.split(":")}p=a("#"+c+"_"+q.replace(".","\\."),h.rows[c]).attr("checked")?f[0]:f[1];n=p;break;case"password":case"text":case"textarea":p=!h.p.autoencode?a("#"+c+"_"+q.replace(".","\\."),h.rows[c]).val():htmlEncode(a("#"+c+"_"+q.replace(".","\\."),h.rows[c]).val());n=p;break}if(n!=h.p.savedRow[k].v){if(a.isFunction(h.p.beforeSaveCell)){var o=h.p.beforeSaveCell(h.rows[c].id,q,p,c,b);if(o){p=o}}var g=checkValues(p,b,h);if(g[0]===true){var j={};if(a.isFunction(h.p.beforeSubmitCell)){j=h.p.beforeSubmitCell(h.rows[c].id,q,p,c,b);if(!j){j={}}}if(h.p.cellsubmit=="remote"){if(h.p.cellurl){var m={};m[q]=p;m.id=h.rows[c].id;m=a.extend(j,m);a.ajax({url:h.p.cellurl,data:m,type:"POST",complete:function(e,s){if(s=="success"){if(a.isFunction(h.p.afterSubmitCell)){var r=h.p.afterSubmitCell(e,m.id,q,p,c,b);if(r[0]===true){a(d).empty();a(h).setCell(h.rows[c].id,b,n);a(d).addClass("dirty-cell");a(h.rows[c]).addClass("edited");if(a.isFunction(h.p.afterSaveCell)){h.p.afterSaveCell(h.rows[c].id,q,p,c,b)}h.p.savedRow=[]}else{info_dialog(a.jgrid.errors.errcap,r[1],a.jgrid.edit.bClose,h.p.imgpath);a(h).restoreCell(c,b)}}else{a(d).empty();a(h).setCell(h.rows[c].id,b,n);a(d).addClass("dirty-cell");a(h.rows[c]).addClass("edited");if(a.isFunction(h.p.afterSaveCell)){h.p.afterSaveCell(h.rows[c].id,q,p,c,b)}h.p.savedRow=[]}}},error:function(e,r){if(a.isFunction(h.p.errorCell)){h.p.errorCell(e,r);a(h).restoreCell(c,b)}else{info_dialog(a.jgrid.errors.errcap,e.status+" : "+e.statusText+"
    "+r,a.jgrid.edit.bClose,h.p.imgpath);a(h).restoreCell(c,b)}}})}else{try{info_dialog(a.jgrid.errors.errcap,a.jgrid.errors.nourl,a.jgrid.edit.bClose,h.p.imgpath);a(h).restoreCell(c,b)}catch(l){}}}if(h.p.cellsubmit=="clientArray"){a(d).empty();a(h).setCell(h.rows[c].id,b,n);a(d).addClass("dirty-cell");a(h.rows[c]).addClass("edited");if(a.isFunction(h.p.afterSaveCell)){h.p.afterSaveCell(h.rows[c].id,q,p,c,b)}h.p.savedRow=[]}}else{try{window.setTimeout(function(){info_dialog(a.jgrid.errors.errcap,p+" "+g[1],a.jgrid.edit.bClose,h.p.imgpath)},100);a(h).restoreCell(c,b)}catch(l){}}}else{a(h).restoreCell(c,b)}}if(a.browser.opera){a("#"+h.p.knv).attr("tabindex","-1").focus()}else{window.setTimeout(function(){a("#"+h.p.knv).attr("tabindex","-1").focus()},0)}})},restoreCell:function(c,b){return this.each(function(){var j=this,d,f;if(!j.grid||j.p.cellEdit!==true){return}if(j.p.savedRow.length==1){f=0}else{f=null}if(f!=null){var h=a("td:eq("+b+")",j.rows[c]);if(a.isFunction(a.fn.datepicker)){try{a.datepicker("hide")}catch(g){try{a.datepicker.hideDatepicker()}catch(g){}}}a(h).empty();a(j).setCell(j.rows[c].id,b,j.p.savedRow[f].v);j.p.savedRow=[]}window.setTimeout(function(){a("#"+j.p.knv).attr("tabindex","-1").focus()},0)})},nextCell:function(c,b){return this.each(function(){var g=this,f=false,e;if(!g.grid||g.p.cellEdit!==true){return}for(var d=b+1;d0){a(g).saveCell(c,b)}}})},prevCell:function(c,b){return this.each(function(){var g=this,f=false,e;if(!g.grid||g.p.cellEdit!==true){return}for(var d=b-1;d>=0;d--){if(g.p.colModel[d].editable===true){f=d;break}}if(f!==false){a(g).saveCell(c,b);a(g).editCell(c,f,true)}else{if(g.p.savedRow.length>0){a(g).saveCell(c,b)}}})},GridNav:function(){return this.each(function(){var e=this;if(!e.grid||e.p.cellEdit!==true){return}e.p.knv=a("table:first",e.grid.bDiv).attr("id")+"_kn";var d=a("");a(d).insertBefore(e.grid.cDiv);a("#"+e.p.knv).focus();a("#"+e.p.knv).keydown(function(g){switch(g.keyCode){case 38:if(e.p.iRow-1>=1){c(e.p.iRow-1,e.p.iCol,"vu");a(e).editCell(e.p.iRow-1,e.p.iCol,false)}break;case 40:if(e.p.iRow+1<=e.rows.length-1){c(e.p.iRow+1,e.p.iCol,"vd");a(e).editCell(e.p.iRow+1,e.p.iCol,false)}break;case 37:if(e.p.iCol-1>=0){var f=b(e.p.iCol-1,"lft");c(e.p.iRow,f,"h");a(e).editCell(e.p.iRow,f,false)}break;case 39:if(e.p.iCol+1<=e.p.colModel.length-1){var f=b(e.p.iCol+1,"rgt");c(e.p.iRow,f,"h");a(e).editCell(e.p.iRow,f,false)}break;case 13:if(parseInt(e.p.iCol,10)>=0&&parseInt(e.p.iRow,10)>=0){a(e).editCell(e.p.iRow,e.p.iCol,true)}break}return false});function c(o,m,n){if(n.substr(0,1)=="v"){var f=a(e.grid.bDiv)[0].clientHeight,p=a(e.grid.bDiv)[0].scrollTop,q=e.rows[o].offsetTop+e.rows[o].clientHeight,k=e.rows[o].offsetTop;if(n=="vd"){if(q>=f){a(e.grid.bDiv)[0].scrollTop=a(e.grid.bDiv)[0].scrollTop+e.rows[o].clientHeight}}if(n=="vu"){if(k=j+parseInt(h)){a(e.grid.bDiv)[0].scrollLeft=a(e.grid.bDiv)[0].scrollLeft+e.rows[o].cells[m].clientWidth}else{if(l=0;g--){if(e.p.colModel[g].hidden!==true){h=g;break}}}if(f=="rgt"){h=j-1;for(g=j;g
    '+a.caption+' '+(f!=""?'':"X")+"
    ").addClass("modalhead");var g=document.createElement("div");jQuery(g).addClass("modalcontent").attr("id",i.modalcontent).css("width","97%");jQuery(g).append(d);h.appendChild(g);var b=document.createElement("div");jQuery(b).addClass("loading").html(a.processData||"");jQuery(h).prepend(b);jQuery(h).prepend(c);jQuery(h).addClass("jqmWindow");if(a.drag){jQuery(h).append("")}if(k===true){jQuery("body").append(h)}else{jQuery(h).insertBefore(j)}if(a.left==0&&a.top==0){var e=[];e=findPos(l);a.left=e[0]+4;a.top=e[1]+4}if(a.width==0||!a.width){a.width=300}if(a.height==0||!a.width){a.height=200}if(!a.zIndex){a.zIndex=950}jQuery(h).css({top:a.top+"px",left:a.left+"px",width:a.width+"px",height:a.height+"px",zIndex:a.zIndex}).attr({tabIndex:"-1"});if(a.closeOnEscape&&a.closeOnEscape===true){jQuery(h).keydown(function(m){if(m.which==27){hideModal(this)}})}return false}function viewModal(a,b){b=jQuery.extend({toTop:true,overlay:10,modal:false,onShow:showModal,onHide:closeModal},b||{});jQuery(a).jqm(b).jqmShow();return false}function hideModal(a){jQuery(a).jqmHide()}function DnRModal(a,b){jQuery(b).css("cursor","move");jQuery(a).jqDrag(b).jqResize(".jqResize");return false}function info_dialog(b,e,c,a){var d="
    ";d+="

    "+e+"

    ";d+="";d+="
    ";createModal({themodal:"info_dialog",modalhead:"info_head",modalcontent:"info_content"},d,{width:290,height:120,drag:false,caption:""+b+"",imgpath:a,closeicon:"ico-close.gif",left:250,top:170,closeOnEscape:true},"","",true);viewModal("#info_dialog",{onShow:function(f){f.w.show()},onHide:function(f){f.w.hide().remove();if(f.o){f.o.remove()}},modal:true})}function findPos(a){var b=curtop=0;if(a.offsetParent){do{b+=a.offsetLeft;curtop+=a.offsetTop}while(a=a.offsetParent)}return[b,curtop]}function isArray(a){if(a.constructor.toString().indexOf("Array")==-1){return false}else{return true}}function createEl(g,n,e){var f="";switch(g){case"textarea":f=document.createElement("textarea");if(!n.cols){jQuery(f).css("width","98%")}jQuery(f).attr(n);if(e==" "||e==" "||(e.length==1&&e.charCodeAt(0)==160)){e=""}jQuery(f).val(e);break;case"checkbox":f=document.createElement("input");f.type="checkbox";jQuery(f).attr({id:n.id,name:n.name});if(!n.value){e=e.toLowerCase();if(e.search(/(false|0|no|off|undefined)/i)<0&&e!==""){f.checked=true;f.defaultChecked=true;f.value=e}else{f.value="on"}jQuery(f).attr("offval","off")}else{var a=n.value.split(":");if(e==a[0]){f.checked=true;f.defaultChecked=true}f.value=a[0];jQuery(f).attr("offval",a[1])}break;case"select":e=jQuery.htmlDecode(e);f=document.createElement("select");var m=n.multiple==true?true:false;if(n.value){var h=[];if(m){jQuery(f).attr({multiple:"multiple"});h=e.split(",");h=jQuery.map(h,function(i){return jQuery.trim(i)})}if(typeof n.size==="undefined"){n.size=1}if(typeof n.value=="string"){var c=n.value.split(";"),l,d;jQuery(f).attr({id:n.id,name:n.name,size:Math.min(n.size,c.length)});for(var j=0;j-1){d.selected="selected"}f.appendChild(d)}}else{if(typeof n.value=="object"){var b=n.value;var j=0;for(var k in b){j++;d=document.createElement("option");d.value=k;d.innerHTML=b[k];if(!m&&b[k]==e){d.selected="selected"}if(m&&jQuery.inArray(jQuery.trim(b[k]),h)>-1){d.selected="selected"}f.appendChild(d)}jQuery(f).attr({id:n.id,name:n.name,size:Math.min(n.size,j)})}}}break;case"text":f=document.createElement("input");f.type="text";e=jQuery.htmlDecode(e);f.value=e;if(!n.size){jQuery(f).css({width:"98%"})}jQuery(f).attr(n);break;case"password":f=document.createElement("input");f.type="password";e=jQuery.htmlDecode(e);f.value=e;if(!n.size){jQuery(f).css("width","98%")}jQuery(f).attr(n);break;case"image":f=document.createElement("input");f.type="image";jQuery(f).attr(n);break}return f}function checkValues(f,b,d){if(b>=0){var e=d.p.colModel[b].editrules}if(e){if(e.required===true){if(f.match(/^s+$/)||f==""){return[false,d.p.colNames[b]+": "+jQuery.jgrid.edit.msg.required,""]}}var h=e.required===false?false:true;if(e.number===true){if(!(h===false&&isEmpty(f))){if(isNaN(f)){return[false,d.p.colNames[b]+": "+jQuery.jgrid.edit.msg.number,""]}}}if(e.minValue&&!isNaN(e.minValue)){if(parseFloat(f)parseFloat(e.maxValue)){return[false,d.p.colNames[b]+": "+jQuery.jgrid.edit.msg.maxValue+" "+e.maxValue,""]}}if(e.email===true){if(!(h===false&&isEmpty(f))){var a=/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i;if(!a.test(f)){return[false,d.p.colNames[b]+": "+jQuery.jgrid.edit.msg.email,""]}}}if(e.integer===true){if(!(h===false&&isEmpty(f))){if(isNaN(f)){return[false,d.p.colNames[b]+": "+jQuery.jgrid.edit.msg.integer,""]}if((f%1!=0)||(f.indexOf(".")!=-1)){return[false,d.p.colNames[b]+": "+jQuery.jgrid.edit.msg.integer,""]}}}if(e.date===true){if(!(h===false&&isEmpty(f))){var c=d.p.colModel[b].datefmt||"Y-m-d";if(!checkDate(c,f)){return[false,d.p.colNames[b]+": "+jQuery.jgrid.edit.msg.date+" - "+c,""]}}}}return[true,"",""]}function checkDate(l,c){var e={};var o=false;var n;l=l.toLowerCase();if(l.indexOf("/")!=-1){n="/"}else{if(l.indexOf("-")!=-1){n="-"}else{if(l.indexOf(".")!=-1){n="."}else{n="/"}}}l=l.split(n);c=c.split(n);if(c.length!=3){return false}var f=-1,m,g=-1,d=-1;for(var h=0;h12){return false}}if(g===-1){return false}else{k=e[l[g]].toString();if(k.length<1||e[l[g]]<1||e[l[g]]>31||(e[l[d]]==2&&e[l[g]]>daysInFebruary(e[l[f]]))||e[l[g]]>a[e[l[d]]]){return false}}return true}function daysInFebruary(a){return(((a%4==0)&&((!(a%100==0))||(a%400==0)))?29:28)}function DaysArray(b){for(var a=1;a<=b;a++){this[a]=31;if(a==4||a==6||a==9||a==11){this[a]=30}if(a==2){this[a]=29}}return this}function isEmpty(a){if(a.match(/^s+$/)||a==""){return true}else{return false}}function htmlEncode(a){return !a?a:String(a).replace(/&/g,"&").replace(/>/g,">").replace(/0?true:false;n.p.postData=a.extend(n.p.postData,p);var r;if(l.p.url){r=a(n).getGridParam("url");a(n).setGridParam({url:l.p.url})}a(n).setGridParam({search:q,page:1}).trigger("reloadGrid");if(r){a(n).setGridParam({url:r})}if(a.isFunction(l.p.afterSearch)){l.p.afterSearch()}};var k=function(){var p={},m,o=0;var n=a(l.p.gridid)[0];if(a.isFunction(l.p.beforeClear)){l.p.beforeClear()}a.each(l.p.filterModel,function(s,v){m=(this.defval)?this.defval:"";if(!this.stype){this.stype=="text"}switch(this.stype){case"select":if(m){var u;a("select[name="+this.name+"] option",l).each(function(){if(a(this).text()==m){this.selected=true;u=a(this).val();return false}});p[this.index]=u||"";if(l.p.marksearched){a("#jqgh_"+this.name,n.grid.hDiv).addClass("dirty-cell")}o++}else{if(l.p.marksearched){a("#jqgh_"+this.name,n.grid.hDiv).removeClass("dirty-cell")}try{delete n.p.postData[this.index]}catch(t){}}break;case"text":a("input[name="+this.name+"]",l).val(m);if(m){p[this.index]=m;if(l.p.marksearched){a("#jqgh_"+this.name,n.grid.hDiv).addClass("dirty-cell")}o++}else{if(l.p.marksearched){a("#jqgh_"+this.name,n.grid.hDiv).removeClass("dirty-cell")}try{delete n.p.postData[this.index]}catch(t){}}}});var q=o>0?true:false;n.p.postData=a.extend(n.p.postData,p);var r;if(l.p.url){r=a(n).getGridParam("url");a(n).setGridParam({url:l.p.url})}a(n).setGridParam({search:q,page:1}).trigger("reloadGrid");if(r){a(n).setGridParam({url:r})}if(a.isFunction(l.p.afterClear)){l.p.afterClear()}};var i=function(){var q=document.createElement("tr");var n,s,m,o,r,p;if(l.p.formtype=="horizontal"){a(f).append(q)}a.each(l.p.filterModel,function(z,u){o=document.createElement("td");a(o).append("");r=document.createElement("td");var y=this;if(!this.stype){this.stype="text"}switch(this.stype){case"select":if(this.surl){a(r).load(this.surl,function(){if(y.defval){a("select",this).val(y.defval)}a("select",this).attr({name:y.name,id:"sg_"+y.name});if(y.sopt){a("select",this).attr(y.sopt)}if(l.p.gridToolbar===true&&y.width){a("select",this).width(y.width)}if(l.p.autosearch===true){a("select",this).change(function(C){h();return false})}})}else{if(y.sopt.value){var t=y.sopt.value.split(";"),B,w;var v=document.createElement("select");a(v).attr({name:y.name,id:"sg_"+y.name}).attr(y.sopt);for(var x=0;x");if(y.sopt){a("input",r).attr(y.sopt)}if(l.p.gridToolbar===true&&y.width){if(a.browser.msie){a("input",r).width(y.width-4)}else{a("input",r).width(y.width-2)}}if(l.p.autosearch===true){a("input",r).keypress(function(D){var C=D.charCode?D.charCode:D.keyCode?D.keyCode:0;if(C==13){h();return false}return this})}break}if(l.p.formtype=="horizontal"){if(l.p.gridToolbar===true&&l.p.gridNames===false){a(q).append(r)}else{a(q).append(o).append(r)}a(q).append(r)}else{n=document.createElement("tr");a(n).append(o).append(r);a(f).append(n)}});r=document.createElement("td");if(l.p.enableSearch===true){s="";a(r).append(s);a("input#sButton",r).click(function(){h();return false})}if(l.p.enableClear===true){m="";a(r).append(m);a("input#cButton",r).click(function(){k();return false})}if(l.p.enableClear===true||l.p.enableSearch===true){if(l.p.formtype=="horizontal"){a(q).append(r)}else{n=document.createElement("tr");a(n).append(" ").append(r);a(f).append(n)}}};var j=a("
    ");var f=a("
    ");a(j).append(f);i();a(this).append(j);this.triggerSearch=function(){h()};this.clearSearch=function(){k()}})}})})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.formedit-min.js b/site/vendors/js/jqGrid/js/min/grid.formedit-min.js new file mode 100644 index 0000000..8f9a427 --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.formedit-min.js @@ -0,0 +1 @@ +(function(b){var a=null;b.fn.extend({searchGrid:function(c){c=b.extend({top:0,left:0,width:360,height:80,modal:false,drag:true,closeicon:"ico-close.gif",dirty:false,sField:"searchField",sValue:"searchString",sOper:"searchOper",processData:"",checkInput:false,beforeShowSearch:null,afterShowSearch:null,onInitializeSearch:null,closeAfterSearch:false,closeOnEscape:false,sopt:null},b.jgrid.search,c||{});return this.each(function(){var n=this;if(!n.grid){return}if(!c.imgpath){c.imgpath=n.p.imgpath}var d=b("table:first",n.grid.bDiv).attr("id");var j={themodal:"srchmod"+d,modalhead:"srchhead"+d,modalcontent:"srchcnt"+d};if(b("#"+j.themodal).html()!=null){if(b.isFunction(c.beforeShowSearch)){c.beforeShowSearch(b("#srchcnt"+d))}viewModal("#"+j.themodal,{modal:c.modal});if(b.isFunction(c.afterShowSearch)){c.afterShowSearch(b("#srchcnt"+d))}}else{var h=n.p.colModel;var s="";var q=c.sopt||["bw","eq","ne","lt","le","gt","ge","ew","cn"];var f="";var r="";var k="";var l="";var g=b("
    "+s+""+f+""+r+""+k+""+l+"
    ");createModal(j,g,c,n.grid.hDiv,n.grid.hDiv);if(b.isFunction(c.onInitializeSearch)){c.onInitializeSearch(b("#srchcnt"+d))}if(b.isFunction(c.beforeShowSearch)){c.beforeShowSearch(b("#srchcnt"+d))}viewModal("#"+j.themodal,{modal:c.modal});if(b.isFunction(c.afterShowSearch)){c.afterShowSearch(b("#srchcnt"+d))}if(c.drag){DnRModal("#"+j.themodal,"#"+j.modalhead+" td.modaltext")}b("#sbut","#"+j.themodal).click(function(){if(b("#sval","#"+j.themodal).val()!=""){var w=[true,"",""];b("#srcherr >td","#srchcnt"+d).html("").hide();n.p.searchdata[c.sField]=b("option[selected]","#snames").val();n.p.searchdata[c.sOper]=b("option[selected]","#sopt").val();n.p.searchdata[c.sValue]=b("#sval","#"+j.modalcontent).val();if(c.checkInput){for(var v=0;vtd","#srchcnt"+d).html(w[1]).show()}}});b("#sreset","#"+j.themodal).click(function(){if(n.p.search){b("#srcherr >td","#srchcnt"+d).html("").hide();n.p.search=false;n.p.searchdata={};n.p.page=1;b("#sval","#"+j.themodal).val("");if(c.dirty){b(".no-dirty-cell",n.p.pager).removeClass("dirty-cell")}b(n).trigger("reloadGrid")}})}})},editGridRow:function(c,d){d=b.extend({top:0,left:0,width:0,height:0,modal:false,drag:true,closeicon:"ico-close.gif",imgpath:"",url:null,mtype:"POST",closeAfterAdd:false,clearAfterAdd:true,closeAfterEdit:false,reloadAfterSubmit:true,onInitializeForm:null,beforeInitData:null,beforeShowForm:null,afterShowForm:null,beforeSubmit:null,afterSubmit:null,onclickSubmit:null,afterComplete:null,onclickPgButtons:null,afterclickPgButtons:null,editData:{},recreateForm:false,closeOnEscape:false,addedrow:"first"},b.jgrid.edit,d||{});a=d;return this.each(function(){var x=this;if(!x.grid||!c){return}if(!d.imgpath){d.imgpath=x.p.imgpath}var p=b("table:first",x.grid.bDiv).attr("id"),h={themodal:"editmod"+p,modalhead:"edithd"+p,modalcontent:"editcnt"+p},D=b.isFunction(a.beforeShowForm)?a.beforeShowForm:false,n=b.isFunction(a.afterShowForm)?a.afterShowForm:false,z=b.isFunction(a.beforeInitData)?a.beforeInitData:false,u=b.isFunction(a.onInitializeForm)?a.onInitializeForm:false,f=1,i,A="FrmGrid_"+p,r="TblGrid_"+p;if(c=="new"){c="_empty";d.caption=d.addCaption}else{d.caption=d.editCaption}if(d.recreateForm===true&&b("#"+h.themodal).html()!=null){b("#"+h.themodal).remove()}if(b("#"+h.themodal).html()!=null){b(".modaltext","#"+h.modalhead).html(d.caption);b("#FormError","#"+r).hide();if(z){z(b("#"+A))}k(c,x);if(c=="_empty"){b("#pData, #nData","#"+r).hide()}else{b("#pData, #nData","#"+r).show()}if(D){D(b("#"+A))}if(d.processing===true){d.processing=false;b("#sData","#"+r).attr("disabled",false);b("div.loading","#"+h.themodal).hide()}viewModal("#"+h.themodal,{modal:d.modal});if(n){n(b("#"+A))}}else{b(x.p.colModel).each(function(E){f=Math.max(f,this.formoptions?this.formoptions.colpos||0:0)});var w,B=b("
    "),j=b("
    ");b(B).append(j);w=b("");w[0].rp=0;b(j).append(w);if(z){z(b("#"+A))}var v=l(c,x,j,f),y=x.p.imgpath,s="",t="",q="",C="";w=b(""+s+" "+t+""+q+" "+C+"");w[0].rp=v.length+100;b(j).append(w);if(f>1){var e=[];b.each(b(j)[0].rows,function(E,F){e[E]=F});e.sort(function(F,E){if(F.rp>E.rp){return 1}if(F.rptd","#"+r).html(G[1]);b("#FormError","#"+r).show()}else{if(!d.processing){d.processing=true;b("div.loading","#"+h.themodal).show();b(this).attr("disabled",true);H.oper=H.id=="_empty"?"add":"edit";H=b.extend(H,a.editData);b.ajax({url:E,type:a.mtype,data:H,complete:function(L,K){if(K!="success"){G[0]=false;G[1]=K+" Status: "+L.statusText+" Error code: "+L.status}else{if(b.isFunction(a.afterSubmit)){G=a.afterSubmit(L,H)}}if(G[0]===false){b("#FormError>td","#"+r).html(G[1]);b("#FormError","#"+r).show()}else{H=b.extend(H,J);if(H.id=="_empty"){if(!G[2]){G[2]=parseInt(b(x).getGridParam("records"))+1}H.id=G[2];if(a.closeAfterAdd){if(a.reloadAfterSubmit){b(x).trigger("reloadGrid")}else{b(x).addRowData(G[2],H,d.addedrow);b(x).setSelection(G[2])}hideModal("#"+h.themodal)}else{if(a.clearAfterAdd){if(a.reloadAfterSubmit){b(x).trigger("reloadGrid")}else{b(x).addRowData(G[2],H,d.addedrow)}b(".FormElement","#"+r).each(function(M){switch(b(this).get(0).type){case"checkbox":b(this).attr("checked",0);break;case"select-one":case"select-multiple":b("option",this).attr("selected","");break;case"password":case"text":case"textarea":if(this.name=="id"){b(this).val("_empty")}else{b(this).val("")}break}});k("_empty",x)}else{if(a.reloadAfterSubmit){b(x).trigger("reloadGrid")}else{b(x).addRowData(G[2],H,d.addedrow)}}}}else{if(a.reloadAfterSubmit){b(x).trigger("reloadGrid");if(!a.closeAfterEdit){b(x).setSelection(H.id)}}else{if(x.p.treeGrid===true){b(x).setTreeRow(H.id,H)}else{b(x).setRowData(H.id,H)}}if(a.closeAfterEdit){hideModal("#"+h.themodal)}}if(b.isFunction(a.afterComplete)){i=L;setTimeout(function(){a.afterComplete(i,H,b("#"+A));i=null},500)}}d.processing=false;b("#sData","#"+r).attr("disabled",false);b("div.loading","#"+h.themodal).hide()},error:function(M,K,L){b("#FormError>td","#"+r).html(K+" : "+L);b("#FormError","#"+r).show();d.processing=false;b("#sData","#"+r).attr("disabled",false);b("div.loading","#"+h.themodal).hide()}})}}I.stopPropagation();return false});b("#cData","#"+r).click(function(E){hideModal("#"+h.themodal);E.stopPropagation();return false});b("#nData","#"+r).click(function(E){b("#FormError","#"+r).hide();var F=g();F[0]=parseInt(F[0]);if(F[0]!=-1&&F[1][F[0]+1]){if(b.isFunction(d.onclickPgButtons)){d.onclickPgButtons("next",b("#"+A),F[1][F[0]])}k(F[1][F[0]+1],x);b(x).setSelection(F[1][F[0]+1]);if(b.isFunction(d.afterclickPgButtons)){d.afterclickPgButtons("next",b("#"+A),F[1][F[0]+1])}m(F[0]+1,F[1].length-1)}return false});b("#pData","#"+r).click(function(F){b("#FormError","#"+r).hide();var E=g();if(E[0]!=-1&&E[1][E[0]-1]){if(b.isFunction(d.onclickPgButtons)){d.onclickPgButtons("prev",b("#"+A),E[1][E[0]])}k(E[1][E[0]-1],x);b(x).setSelection(E[1][E[0]-1]);if(b.isFunction(d.afterclickPgButtons)){d.afterclickPgButtons("prev",b("#"+A),E[1][E[0]-1])}m(E[0]-1,E[1].length-1)}return false})}var o=g();m(o[0],o[1].length-1);function m(G,H,F){var E=x.p.imgpath;if(G==0){b("#pData","#"+r).attr("src",E+"off-"+x.p.previmg)}else{b("#pData","#"+r).attr("src",E+x.p.previmg)}if(G==H){b("#nData","#"+r).attr("src",E+"off-"+x.p.nextimg)}else{b("#nData","#"+r).attr("src",E+x.p.nextimg)}}function g(){var F=b(x).getDataIDs();var E=b("#id_g","#"+r).val();var G=b.inArray(E,F);return[G,F]}function l(H,M,K,R){var F,G,O,U,E,P=0,T,V,N,S=[],L=false,I="  ",J="";for(var Q=1;Q<=R;Q++){J+=I}L=b(M).getInd(M.rows,H);b(M.p.colModel).each(function(Z){F=this.name;if(this.editrules&&this.editrules.edithidden==true){G=false}else{G=this.hidden===true?true:false}V=G?"style='display:none'":"";if(F!=="cb"&&F!=="subgrid"&&this.editable===true){if(L===false){T=""}else{if(F==M.p.ExpandColumn&&M.p.treeGrid===true){T=b("td:eq("+Z+")",M.rows[L]).text()}else{try{T=b.unformat(b("td:eq("+Z+")",M.rows[L]),{colModel:this},Z)}catch(X){T=b("td:eq("+Z+")",M.rows[L]).html()}}}var Y=b.extend({},this.editoptions||{},{id:F,name:F}),ac=b.extend({},{elmprefix:"",elmsuffix:""},this.formoptions||{}),aa=parseInt(ac.rowpos)||P+1,ab=parseInt((parseInt(ac.colpos)||1)*2);if(H=="_empty"&&Y.defaultValue){T=b.isFunction(Y.defaultValue)?Y.defaultValue():Y.defaultValue}if(!this.edittype){this.edittype="text"}N=createEl(this.edittype,Y,T);b(N).addClass("FormElement");O=b(j).find("tr[rowpos="+aa+"]");if(O.length==0){O=b("").addClass("FormData").attr("id","tr_"+F);b(O).append(J);b(K).append(O);O[0].rp=aa}b("td:eq("+(ab-2)+")",O[0]).html(typeof ac.label==="undefined"?M.p.colNames[Z]:ac.label);b("td:eq("+(ab-1)+")",O[0]).append(ac.elmprefix).append(N).append(ac.elmsuffix);S[P]=Z;P++}});if(P>0){var W=b("");W[0].rp=P+99;b(K).append(W)}return S}function k(I,J){var E,K,H=0,G,F;b("#"+I+" td",J.grid.bDiv).each(function(M){E=J.p.colModel[M].name;if(J.p.colModel[M].editrules&&J.p.colModel[M].editrules.edithidden===true){K=false}else{K=J.p.colModel[M].hidden===true?true:false}if(E!=="cb"&&E!=="subgrid"&&J.p.colModel[M].editable===true){if(E==J.p.ExpandColumn&&J.p.treeGrid===true){G=b(this).text()}else{try{G=b.unformat(this,{colModel:J.p.colModel[M]},M)}catch(L){G=b(this).html()}}E=E.replace(".","\\.");F=b.extend({},J.p.colModel[M].editoptions||{});if(I=="_empty"&&F.defaultValue){G=b.isFunction(F.defaultValue)?F.defaultValue():F.defaultValue}switch(J.p.colModel[M].edittype){case"password":case"text":b("#"+E,"#"+r).val(G);break;case"textarea":if(G==" "||G==" "||(G.length==1&&G.charCodeAt(0)==160)){G=""}b("#"+E,"#"+r).val(G);break;case"select":b("#"+E+" option","#"+r).each(function(N){if(!F.multiple&&G==b(this).text()){this.selected=true}else{if(F.multiple){if(b.inArray(b(this).text(),G.split(","))>-1){this.selected=true}else{this.selected=false}}else{this.selected=false}}});break;case"checkbox":if(G==b("#"+E,"#"+r).val()){b("#"+E,"#"+r).attr("checked",true);b("#"+E,"#"+r).attr("defaultChecked",true)}else{b("#"+E,"#"+r).attr("checked",false);b("#"+E,"#"+r).attr("defaultChecked","")}break}if(K){b("#"+E,"#"+r).parents("tr:first").hide()}H++}});if(H>0){b("#id_g","#"+r).val(I)}else{b("#id_g","#"+r).val("")}return H}})},viewGridRow:function(c,d){d=b.extend({top:0,left:0,width:0,height:0,modal:false,drag:true,closeicon:"ico-close.gif",imgpath:"",closeOnEscape:false,labelswidth:"30%"},b.jgrid.view,d||{});return this.each(function(){var u=this;if(!u.grid||!c){return}if(!d.imgpath){d.imgpath=u.p.imgpath}var o=b("table:first",u.grid.bDiv).attr("id"),h={themodal:"viewmod"+o,modalhead:"viewhd"+o,modalcontent:"viewcnt"+o},f=1,w="ViewGrid_"+o,p="ViewTbl_"+o;if(b("#"+h.themodal).html()!=null){b(".modaltext","#"+h.modalhead).html(d.caption);b("#FormError","#"+p).hide();k(c,u);viewModal("#"+h.themodal,{modal:d.modal});i()}else{b(u.p.colModel).each(function(z){f=Math.max(f,this.formoptions?this.formoptions.colpos||0:0)});var t,x=b("
    "),j=b("
    ");b(x).append(j);var s=l(c,u,j,f),v=u.p.imgpath,q="",r="",y="";t=b(""+q+" "+r+""+y+"");t[0].rp=s.length+100;b(j).append(t);if(f>1){var e=[];b.each(b(j)[0].rows,function(z,A){e[z]=A});e.sort(function(A,z){if(A.rp>z.rp){return 1}if(A.rp  ",I="",C="  ",G=["integer","number","currency"],P=0,O=0,D,A;for(var R=1;R<=S;R++){I+=R==1?H:C}b(L.p.colModel).each(function(Y){if(this.editrules&&this.editrules.edithidden===true){E=false}else{E=this.hidden===true?true:false}if(!E&&this.align==="right"){if(this.formatter&&b.inArray(this.formatter,G)!==-1){P=Math.max(P,parseInt(this.width,10))}else{O=Math.max(O,parseInt(this.width,10))}}});D=P!==0?P:O!==0?O:0;K=b(L).getInd(L.rows,F);b(L.p.colModel).each(function(Z){B=this.name;A=false;if(this.editrules&&this.editrules.edithidden===true){E=false}else{E=this.hidden===true?true:false}W=E?"style='display:none'":"";if(B!=="cb"&&B!=="subgrid"&&this.editable===true){if(K===false){U=""}else{if(B==L.p.ExpandColumn&&L.p.treeGrid===true){U=b("td:eq("+Z+")",L.rows[K]).text()}else{U=b("td:eq("+Z+")",L.rows[K]).html()}}A=this.align==="right"&&D!==0?true:false;var Y=b.extend({},this.editoptions||{},{id:B,name:B}),ac=b.extend({},{elmprefix:"",elmsuffix:""},this.formoptions||{}),aa=parseInt(ac.rowpos)||Q+1,ab=parseInt((parseInt(ac.colpos)||1)*2);if(!this.edittype){this.edittype="text"}N=b(j).find("tr[rowpos="+aa+"]");if(N.length==0){N=b("").addClass("FormData").attr("id","tr_"+B);b(N).append(I);b(J).append(N);N[0].rp=aa}b("td:eq("+(ab-2)+")",N[0]).html(""+(typeof ac.label==="undefined"?L.p.colNames[Z]:ac.label)+"");b("td:eq("+(ab-1)+")",N[0]).append(""+U+"").attr("id",B);if(A){b("td:eq("+(ab-1)+") span",N[0]).css({"text-align":"right",width:D+"px"})}T[Q]=Z;Q++}});if(Q>0){var X=b("");X[0].rp=Q+99;b(J).append(X)}return T}function k(D,E){var z,F,C=0,B,A;b("#"+D+" td",E.grid.bDiv).each(function(G){z=E.p.colModel[G].name;if(E.p.colModel[G].editrules&&E.p.colModel[G].editrules.edithidden===true){F=false}else{F=E.p.colModel[G].hidden===true?true:false}if(z!=="cb"&&z!=="subgrid"&&E.p.colModel[G].editable===true){if(z==E.p.ExpandColumn&&E.p.treeGrid===true){B=b(this).text()}else{B=b(this).html()}z=z.replace(".","\\.");A=b.extend({},E.p.colModel[G].editoptions||{});b("#"+z+" span","#"+p).html(B);if(F){b("#"+z,"#"+p).parents("tr:first").hide()}C++}});if(C>0){b("#id_g","#"+p).val(D)}else{b("#id_g","#"+p).val("")}return C}})},delGridRow:function(c,d){d=b.extend({top:0,left:0,width:240,height:90,modal:false,drag:true,closeicon:"ico-close.gif",imgpath:"",url:"",mtype:"POST",reloadAfterSubmit:true,beforeShowForm:null,afterShowForm:null,beforeSubmit:null,onclickSubmit:null,afterSubmit:null,onclickSubmit:null,closeOnEscape:false,delData:{}},b.jgrid.del,d||{});return this.each(function(){var j=this;if(!j.grid){return}if(!c){return}if(!d.imgpath){d.imgpath=j.p.imgpath}var l=typeof d.beforeShowForm==="function"?true:false,f=typeof d.afterShowForm==="function"?true:false,e=b("table:first",j.grid.bDiv).attr("id"),g={themodal:"delmod"+e,modalhead:"delhd"+e,modalcontent:"delcnt"+e},i="DelTbl_"+e,m;if(isArray(c)){c=c.join()}if(b("#"+g.themodal).html()!=null){b("#DelData>td","#"+i).text(c);b("#DelError","#"+i).hide();if(d.processing===true){d.processing=false;b("#dData","#"+i).attr("disabled",false);b("div.loading","#"+g.themodal).hide()}if(l){d.beforeShowForm(b("#"+i))}viewModal("#"+g.themodal,{modal:d.modal});if(f){d.afterShowForm(b("#"+i))}}else{var k=b("
    ");b(k).append(" ");b(k).append(""+c+"");b(k).append(""+d.msg+"");var h="";var n="";b(k).append(""+h+" "+n+"");createModal(g,k,d,j.grid.hDiv,j.grid.hDiv);if(d.drag){DnRModal("#"+g.themodal,"#"+g.modalhead+" td.modaltext")}b("#dData","#"+i).click(function(r){var p=[true,""];var q=b("#DelData>td","#"+i).text();if(typeof d.onclickSubmit==="function"){d.delData=d.onclickSubmit(d)||{}}if(typeof d.beforeSubmit==="function"){p=d.beforeSubmit(q)}var o=d.url?d.url:j.p.editurl;if(!o){p[0]=false;p[1]+=" "+b.jgrid.errors.nourl}if(p[0]===false){b("#DelError>td","#"+i).html(p[1]);b("#DelError","#"+i).show()}else{if(!d.processing){d.processing=true;b("div.loading","#"+g.themodal).show();b(this).attr("disabled",true);var s=b.extend({oper:"del",id:q},d.delData);b.ajax({url:o,type:d.mtype,data:s,complete:function(w,u){if(u!="success"){p[0]=false;p[1]=u+" Status: "+w.statusText+" Error code: "+w.status}else{if(typeof d.afterSubmit==="function"){p=d.afterSubmit(w,q)}}if(p[0]===false){b("#DelError>td","#"+i).html(p[1]);b("#DelError","#"+i).show()}else{if(d.reloadAfterSubmit){if(j.p.treeGrid){b(j).setGridParam({treeANode:0,datatype:j.p.treedatatype})}b(j).trigger("reloadGrid")}else{var t=[];t=q.split(",");if(j.p.treeGrid===true){try{b(j).delTreeNode(t[0])}catch(x){}}else{for(var v=0;vtd","#"+i).html(t+" : "+u);b("#DelError","#"+i).show();d.processing=false;b("#dData","#"+i).attr("disabled",false);b("div.loading","#"+g.themodal).hide()}})}}return false});b("#eData","#"+i).click(function(o){hideModal("#"+g.themodal);return false});if(l){d.beforeShowForm(b("#"+i))}viewModal("#"+g.themodal,{modal:d.modal});if(f){d.afterShowForm(b("#"+i))}}})},navGrid:function(f,h,e,g,d,c,i){h=b.extend({edit:true,editicon:"row_edit.gif",add:true,addicon:"row_add.gif",del:true,delicon:"row_delete.gif",search:true,searchicon:"find.gif",refresh:true,refreshicon:"refresh.gif",refreshstate:"firstpage",position:"left",closeicon:"ico-close.gif",closeOnEscape:true,view:true,viewicon:"row_view.gif"},b.jgrid.nav,h||{});return this.each(function(){var l={themodal:"alertmod",modalhead:"alerthd",modalcontent:"alertcnt"};var o=this;if(!o.grid){return}if(b("#"+l.themodal).html()==null){var n;var q;if(typeof window.innerWidth!="undefined"){n=window.innerWidth,q=window.innerHeight}else{if(typeof document.documentElement!="undefined"&&typeof document.documentElement.clientWidth!="undefined"&&document.documentElement.clientWidth!=0){n=document.documentElement.clientWidth,q=document.documentElement.clientHeight}else{n=1024;q=768}}createModal(l,"
    "+h.alerttext+"
    ",{imgpath:o.p.imgpath,closeicon:h.closeicon,caption:h.alertcap,top:q/2-25,left:n/2-100,width:200,height:50,closeOnEscape:h.closeOnEscape},o.grid.hDiv,o.grid.hDiv,true);DnRModal("#"+l.themodal,"#"+l.modalhead)}var r=b("").height(20);var m=document.createElement("tr");b(m).addClass("nav-row");var j=o.p.imgpath;var p;if(h.add){p=document.createElement("td");b(p).append(" ").css({border:"none",padding:"0px"});m.appendChild(p);p=document.createElement("td");p.title=h.addtitle||"";b(p).append("
    "+h.addtext+" 
    ").css("cursor","pointer").addClass("nav-button").click(function(){if(typeof h.addfunc=="function"){h.addfunc()}else{b(o).editGridRow("new",g||{})}return false}).hover(function(){b(this).addClass("nav-hover")},function(){b(this).removeClass("nav-hover")});m.appendChild(p);p=null}if(h.edit){p=document.createElement("td");b(p).append(" ").css({border:"none",padding:"0px"});m.appendChild(p);p=document.createElement("td");p.title=h.edittitle||"";b(p).append("
    "+h.edittext+" 
    ").css("cursor","pointer").addClass("nav-button").click(function(){var s=b(o).getGridParam("selrow");if(s){if(typeof h.editfunc=="function"){h.editfunc(s)}else{b(o).editGridRow(s,e||{})}}else{viewModal("#"+l.themodal,{toTop:false});b("#jqg_alrt").focus()}return false}).hover(function(){b(this).addClass("nav-hover")},function(){b(this).removeClass("nav-hover")});m.appendChild(p);p=null}if(h.view){p=document.createElement("td");b(p).append(" ").css({border:"none",padding:"0px"});m.appendChild(p);p=document.createElement("td");p.title=h.viewtitle||"";b(p).append("
    "+h.viewtext+" 
    ").css("cursor","pointer").addClass("nav-button").click(function(){var s=b(o).getGridParam("selrow");if(s){b(o).viewGridRow(s,i||{})}else{viewModal("#"+l.themodal,{toTop:false});b("#jqg_alrt").focus()}return false}).hover(function(){b(this).addClass("nav-hover")},function(){b(this).removeClass("nav-hover")});m.appendChild(p);p=null}if(h.del){p=document.createElement("td");b(p).append(" ").css({border:"none",padding:"0px"});m.appendChild(p);p=document.createElement("td");p.title=h.deltitle||"";b(p).append("
    "+h.deltext+" 
    ").css("cursor","pointer").addClass("nav-button").click(function(){var s;if(o.p.multiselect){s=b(o).getGridParam("selarrrow");if(s.length==0){s=null}}else{s=b(o).getGridParam("selrow")}if(s){b(o).delGridRow(s,d||{})}else{viewModal("#"+l.themodal,{toTop:false});b("#jqg_alrt").focus()}return false}).hover(function(){b(this).addClass("nav-hover")},function(){b(this).removeClass("nav-hover")});m.appendChild(p);p=null}if(h.search){p=document.createElement("td");b(p).append(" ").css({border:"none",padding:"0px"});m.appendChild(p);p=document.createElement("td");if(b(f)[0]==o.p.pager[0]){c=b.extend(c,{dirty:true})}p.title=h.searchtitle||"";b(p).append("
    "+h.searchtext+" 
    ").css({cursor:"pointer"}).addClass("nav-button").click(function(){b(o).searchGrid(c||{});return false}).hover(function(){b(this).addClass("nav-hover")},function(){b(this).removeClass("nav-hover")});m.appendChild(p);p=null}if(h.refresh){p=document.createElement("td");b(p).append(" ").css({border:"none",padding:"0px"});m.appendChild(p);p=document.createElement("td");p.title=h.refreshtitle||"";var k=(b(f)[0]==o.p.pager[0])?true:false;b(p).append("
    "+h.refreshtext+" 
    ").css("cursor","pointer").addClass("nav-button").click(function(){o.p.search=false;switch(h.refreshstate){case"firstpage":o.p.page=1;b(o).trigger("reloadGrid");break;case"current":var s=o.p.multiselect===true?selarrrow:o.p.selrow;b(o).setGridParam({gridComplete:function(){if(o.p.multiselect===true){if(s.length>0){for(var u=0;u":" ";b(tbd).append("
    "+f+""+d.caption+" 
    ").css("cursor","pointer").addClass("nav-button").click(function(j){if(typeof d.onClickButton=="function"){d.onClickButton()}j.stopPropagation();return false}).hover(function(){b(this).addClass("nav-hover")},function(){b(this).removeClass("nav-hover")});if(d.position!="first"){g.appendChild(tbd)}else{b(g).prepend(tbd);b(g).prepend(h)}tbd=null;h=null}})},GridToForm:function(c,d){return this.each(function(){var g=this;if(!g.grid){return}var f=b(g).getRowData(c);if(f){for(var e in f){if(b("[name="+e+"]",d).is("input:radio")){b("[name="+e+"]",d).each(function(){if(b(this).val()==f[e]){b(this).attr("checked","checked")}else{b(this).attr("checked","")}})}else{b("[name="+e+"]",d).val(f[e])}}}})},FormToGrid:function(c,d){return this.each(function(){var g=this;if(!g.grid){return}var e=b(d).serializeArray();var f={};b.each(e,function(h,j){f[j.name]=j.value});b(g).setRowData(c,f)})}})})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.import-min.js b/site/vendors/js/jqGrid/js/min/grid.import-min.js new file mode 100644 index 0000000..ce5159f --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.import-min.js @@ -0,0 +1 @@ +(function(a){a.fn.extend({jqGridImport:function(b){b=a.extend({imptype:"xml",impstring:"",impurl:"",mtype:"GET",impData:{},xmlGrid:{config:"roots>grid",data:"roots>rows"},jsonGrid:{config:"grid",data:"data"}},b||{});return this.each(function(){var f=this;var d=function(h,m){var g=a(m.xmlGrid.config,h)[0];var l=a(m.xmlGrid.data,h)[0];if(xmlJsonClass.xml2json&&JSON.parse){var n=xmlJsonClass.xml2json(g," ");var n=JSON.parse(n);for(var i in n){var j=n[i]}if(l){var k=n.grid.datatype;n.grid.datatype="xmlstring";n.grid.datastr=h;a(f).jqGrid(j).setGridParam({datatype:k})}else{a(f).jqGrid(j)}n=null;j=null}else{alert("xml2json or json.parse are not present")}};var e=function(h,k){if(h&&typeof h=="string"&&JSON.parse){var g=JSON.parse(h);var l=g[k.jsonGrid.config];var i=g[k.jsonGrid.data];if(i){var j=l.datatype;l.datatype="jsonstring";l.datastr=i;a(f).jqGrid(l).setGridParam({datatype:j})}else{a(f).jqGrid(l)}}};switch(b.imptype){case"xml":a.ajax({url:b.impurl,type:b.mtype,data:b.impData,dataType:"xml",complete:function(g,h){if(h=="success"){d(g.responseXML,b);g=null}}});break;case"xmlstring":if(b.impstring&&typeof b.impstring=="string"){var c=xmlJsonClass.parseXml(b.impstring);if(c){d(c,b);c=null}}break;case"json":a.ajax({url:b.impurl,type:b.mtype,data:b.impData,dataType:"json",complete:function(g,h){if(h=="success"){e(g.responseText,b);g=null}}});break;case"jsonstring":if(b.impstring&&typeof b.impstring=="string"){e(b.impstring,b)}break}})},jqGridExport:function(c){c=a.extend({exptype:"xmlstring"},c||{});var b=null;this.each(function(){if(!this.grid){return}var d=a(this).getGridParam();switch(c.exptype){case"xmlstring":b=xmlJsonClass.json2xml(d," ");break;case"jsonstring":b=JSON.stringify(d);break}});return b}})})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.inlinedit-min.js b/site/vendors/js/jqGrid/js/min/grid.inlinedit-min.js new file mode 100644 index 0000000..d48ebf8 --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.inlinedit-min.js @@ -0,0 +1 @@ +(function(a){a.fn.extend({editRow:function(i,h,d,g,e,f,c,b){return this.each(function(){var n=this,t,o,k,l=0,s=null,r=[],j;if(!n.grid){return}var q,m,p;if(!n.p.multiselect){j=a(n).getInd(n.rows,i);if(j===false){return}k=a(n.rows[j]).attr("editable")||"0";if(k=="0"){a("td",n.rows[j]).each(function(w){t=n.p.colModel[w].name;p=n.p.colModel[w].hidden===true?true:false;try{o=a.unformat(this,{colModel:n.p.colModel[w]},w)}catch(u){o=a(this).html()}r[t]=o;if(t!=="cb"&&t!=="subgrid"&&n.p.colModel[w].editable===true&&!p){if(s===null){s=w}a(this).html("");var v=a.extend(n.p.colModel[w].editoptions||{},{id:i+"_"+t,name:t});if(!n.p.colModel[w].edittype){n.p.colModel[w].edittype="text"}var x=createEl(n.p.colModel[w].edittype,v,o,a(this));a(x).addClass("editable");a(this).append(x);if(n.p.colModel[w].edittype=="select"&&n.p.colModel[w].editoptions.multiple===true&&a.browser.msie){a(x).width(a(x).width())}l++}});if(l>0){r.id=i;n.p.savedRow.push(r);a(n.rows[j]).attr("editable","1");a("td:eq("+s+") input",n.rows[j]).focus();if(h===true){a(n.rows[j]).bind("keydown",function(u){if(u.keyCode===27){a(n).restoreRow(i)}if(u.keyCode===13){a(n).saveRow(i,g,e,f,c,b);return false}u.stopPropagation()})}if(a.isFunction(d)){d(i)}}}}})},saveRow:function(g,f,d,e,c,b){return this.each(function(){var n=this,s,o={},l={},j,q,p,h,i;if(!n.grid){return}i=a(n).getInd(n.rows,g);if(i===false){return}j=a(n.rows[i]).attr("editable");d=d?d:n.p.editurl;if(j==="1"&&d){a("td",n.rows[i]).each(function(t){s=n.p.colModel[t].name;if(s!=="cb"&&s!=="subgrid"&&n.p.colModel[t].editable===true){if(n.p.colModel[t].hidden===true){o[s]=a(this).html()}else{switch(n.p.colModel[t].edittype){case"checkbox":var k=["Yes","No"];if(n.p.colModel[t].editoptions){k=n.p.colModel[t].editoptions.value.split(":")}o[s]=a("input",this).attr("checked")?k[0]:k[1];break;case"text":case"password":case"textarea":o[s]=!n.p.autoencode?a("input, textarea",this).val():htmlEncode(a("input, textarea",this).val());break;case"select":if(!n.p.colModel[t].editoptions.multiple){o[s]=a("select>option:selected",this).val();l[s]=a("select>option:selected",this).text()}else{var u=a("select",this);o[s]=a(u).val();var v=[];a("select > option:selected",this).each(function(w,x){v[w]=a(x).text()});l[s]=v.join(",")}break}p=checkValues(o[s],t,n);if(p[0]===false){p[1]=o[s]+" "+p[1];return false}}}});if(p[0]===false){try{info_dialog(a.jgrid.errors.errcap,p[1],a.jgrid.edit.bClose,n.p.imgpath)}catch(r){alert(p[1])}return}if(o){o.id=g;if(e){o=a.extend({},o,e)}}if(!n.grid.hDiv.loading){n.grid.hDiv.loading=true;a("div.loading",n.grid.hDiv).fadeIn("fast");if(d=="clientArray"){o=a.extend({},o,l);a(n).setRowData(g,o);a(n.rows[i]).attr("editable","0");for(var m=0;m=0){n.p.savedRow.splice(q,1)}if(a.isFunction(c)){c(g,res.responseText)}}else{a.ajax({url:d,data:o,type:"POST",complete:function(v,w){if(w==="success"){var u;if(a.isFunction(f)){u=f(v)}else{u=true}if(u===true){o=a.extend({},o,l);a(n).setRowData(g,o);a(n.rows[i]).attr("editable","0");for(var t=0;t=0){n.p.savedRow.splice(q,1)}if(a.isFunction(c)){c(g,v.responseText)}}else{a(n).restoreRow(g)}}},error:function(k,t){if(a.isFunction(b)){b(k,t)}else{alert("Error Row: "+g+" Result: "+k.status+":"+k.statusText+" Status: "+t)}}})}n.grid.hDiv.loading=false;a("div.loading",n.grid.hDiv).fadeOut("fast");a(n.rows[i]).unbind("keydown")}}})},restoreRow:function(b){return this.each(function(){var g=this,c,d,f;if(!g.grid){return}f=a(g).getInd(g.rows,b);if(f===false){return}for(var e=0;e=0){a(g).setRowData(b,g.p.savedRow[d]);a(g.rows[f]).attr("editable","0");g.p.savedRow.splice(d,1)}})}})})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-bg-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-bg-min.js new file mode 100644 index 0000000..9cc393f --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-bg-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"запиÑ(а)",loadtext:"Зареждам...",pgtext:"от"};a.jgrid.search={caption:"ТърÑене...",Find:"Ðамери",Reset:"Ð?зчиÑти",odata:["равно","различно","по-малко","по-малко или=","по-голÑмо","по-голÑмо или =","започва Ñ","завършва Ñ","Ñъдържа"]};a.jgrid.edit={addCaption:"Ðов ЗапиÑ",editCaption:"Ð ÐµÐ´Ð°ÐºÑ†Ð¸Ñ Ð—Ð°Ð¿Ð¸Ñ",bSubmit:"Запиши",bCancel:"Ð?зход",bClose:"Затвори",processData:"Обработка...",msg:{required:"Полето е задължително",number:"Въведете валидно чиÑло!",minValue:"ÑтойноÑтта трÑбва да е по-голÑма или равна от",maxValue:"ÑтойноÑтта трÑбва да е по-малка или равна от",email:"не е валиден ел. адреÑ",integer:"Въведете валидно цÑло чиÑло",date:"Въведете валидна дата"}};a.jgrid.del={caption:"Ð?зтриване",msg:"Да Ð¸Ð·Ñ‚Ñ€Ð¸Ñ Ð»Ð¸ избраниÑÑ‚ запиÑ?",bSubmit:"Ð?зтрий",bCancel:"Отказ",processData:"Обработка..."};a.jgrid.nav={edittext:" ",edittitle:"Ð ÐµÐ´Ð°ÐºÑ†Ð¸Ñ Ð¸Ð·Ð±Ñ€Ð°Ð½ запиÑ",addtext:" ",addtitle:"ДобавÑне нов запиÑ",deltext:" ",deltitle:"Ð?зтриване избран запиÑ",searchtext:" ",searchtitle:"ТърÑене запиÑ(и)",refreshtext:"",refreshtitle:"Обнови таблица",alertcap:"Предупреждение",alerttext:"МолÑ, изберете запиÑ"};a.jgrid.col={caption:"Колони",bSubmit:"ЗапиÑ",bCancel:"Ð?зход"};a.jgrid.errors={errcap:"Грешка",nourl:"ÐÑма поÑочен url адреÑ",norecords:"ÐÑма Ð·Ð°Ð¿Ð¸Ñ Ð·Ð° обработка",model:"Модела не ÑъответÑтва на имената!"};a.jgrid.formatter={integer:{thousandsSeparator:" ",defaulValue:0},number:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,defaultValue:0},currency:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,prefix:"",suffix:" лв.",defaultValue:0},date:{dayNames:["Ðед","Пон","Ð’Ñ‚","Ср","Чет","Пет","Съб","ÐеделÑ","Понеделник","Вторник","СрÑда","Четвъртък","Петък","Събота"],monthNames:["Ян","Фев","Март","Ðпр","Май","Юни","Юли","Ðвг","Сеп","Окт","Ðоем","Дек","Януари","Февруари","Март","Ðприл","Май","Юни","Юли","ÐвгуÑÑ‚","Септември","Октомври","Ðоември","Декември"],AmPm:["","","",""],S:function(b){if(b==7||b==8||b==27||b==28){return"ми"}return["ви","ри","ти"][Math.min((b-1)%10,2)]},srcformat:"Y-m-d",newformat:"d/m/Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"n/j/Y",LongDate:"l, F d, Y",FullDateTime:"l, F d, Y g:i:s A",MonthDay:"F d",ShortTime:"g:i A",LongTime:"g:i:s A",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F, Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"show"}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-bg1251-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-bg1251-min.js new file mode 100644 index 0000000..ab5a384 --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-bg1251-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"çàïèñ(à)",loadtext:"Çàðåæäàì...",pgtext:"îò"};a.jgrid.search={caption:"Òúðñåíå...",Find:"Íàìåðè",Reset:"Èç÷èñòè",odata:["ðàâíî","ðàçëè÷íî","ïî-ìàëêî","ïî-ìàëêî èëè=","ïî-ãîëÿìî","ïî-ãîëÿìî èëè =","çàïî÷âà ñ","çàâúðøâà ñ","ñúäúðæà"]};a.jgrid.edit={addCaption:"Íîâ çàïèñ",editCaption:"Ðåäàêöèÿ Çàïèñ",bSubmit:"Çàïèøè",bCancel:"Èçõîä",bClose:"Çàòâîðè",processData:"Îáðàáîòêà...",msg:{required:"Ïîëåòî å çàäúëæèòåëíî",number:"Âúâåäåòå âàëèäíî ÷èñëî!",minValue:"ñòîéíîñòòà òðÿáâà äà å ïî-ãîëÿìà èëè ðàâíà íà",maxValue:"ñòîéíîñòòà òðÿáâà äà å ïî-ìàëêà èëè ðàâíà íà",email:"íå å âàëèäåí e-mail àäðåñ",integer:"Âúâåäåòå âàëèäíî öÿëî ÷èñëî",date:"Âúâåäåòå âàëèäíà äàòà"}};a.jgrid.del={caption:"Èçòðèâàíå",msg:"Äà èçòðèÿ ëè èçáðàíèÿ çàïèñ?",bSubmit:"Èçòðèé",bCancel:"Îòêàç",processData:"Îáðàáîòêà..."};a.jgrid.nav={edittext:" ",edittitle:"Ðåäàêöèÿ íà èçáðàí çàïèñ",addtext:" ",addtitle:"Äîáàâÿíå íà íîâ çàïèñ",deltext:" ",deltitle:"Èçòðèâíàå íà èçáðàí çàïèñ",searchtext:" ",searchtitle:"Òúðñåíå çàïèñ(è) ",refreshtext:"",refreshtitle:"Îáíîâè òàáëèöà",alertcap:"Ïðåäóïðåæäåíèå",alerttext:"Ìîëÿ, èçáåðåòå çàïèñ"};a.jgrid.col={caption:"Êîëîíè",bSubmit:"Çàïèñ",bCancel:"Èçõîä"};a.jgrid.errors={errcap:"Ãðåøêà",nourl:"Íÿìà ïîñî÷åí URL àäðåñ",norecords:"Íÿìà çàïèñ çà îáðàáîòêà",model:"Ìîäåëúò íå ñúîòâåòñòâà íà èìåíàòà!"};a.jgrid.formatter={integer:{thousandsSeparator:" ",defaulValue:0},number:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,defaultValue:0},currency:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,prefix:"",suffix:" ??.",defaultValue:0},date:{dayNames:["Íåä","Ïîí","Âò","Ñð","×åò","Ïåò","Ñúá","Íåäåëÿ","Ïîíåäåëíèê","Âòîðíèê","Ñðÿäà","×åòâúðòúê","Ïåòúê","Ñúáîòà"],monthNames:["ßí","Ôåâ","Ìàðò","Àïð","Ìàé","Þíè","Þëè","Àâã","Ñåï","Îêò","Íîåì","Äåê","ßíóàðè","Ôåâðóàðè","Ìàðò","Àïðèë","Ìàé","Þíè","Þëè","Àâãóñò","Ñåïòåìâðè","Îêòîìâðè","Íîåìâðè","Äåêåìâðè"],AmPm:["","","",""],S:function(b){if(b==7||b==8||b==27||b==28){return"ìè"}return["âè","ðè","òè"][Math.min((b-1)%10,2)]},srcformat:"Y-m-d",newformat:"d/m/Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"n/j/Y",LongDate:"l, F d, Y",FullDateTime:"l, F d, Y g:i:s A",MonthDay:"F d",ShortTime:"g:i A",LongTime:"g:i:s A",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F, Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"show"}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-cat-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-cat-min.js new file mode 100644 index 0000000..ee92e59 --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-cat-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"file(s)",loadtext:"Carregant...",pgtext:"/"};a.jgrid.search={caption:"Cerca...",Find:"Cercar",Reset:"Buidar",odata:["igual","no igual","menor","menor o igual","major","major o igual","comença amb","acaba amb","conté"]};a.jgrid.edit={addCaption:"Afegir registre",editCaption:"Modificar registre",bSubmit:"Enviar",bCancel:"Cancelar",bClose:"Tancar",processData:"Processant...",msg:{required:"Camp obligatori",number:"Introdueixi un nombre",minValue:"El valor ha de ser major o igual que ",maxValue:"El valor ha de ser menor o igual a ",email:"no és una direcció de correu vàlida",integer:"Introdueixi un valor enter",date:"Introdueixi una data correcta "}};a.jgrid.del={caption:"Eliminar",msg:"¿Desitja eliminar els registres seleccionats?",bSubmit:"Eliminar",bCancel:"Cancelar",processData:"Processant..."};a.jgrid.nav={edittext:" ",edittitle:"Modificar fila seleccionada",addtext:" ",addtitle:"Agregar nova fila",deltext:" ",deltitle:"Eliminar fila seleccionada",searchtext:" ",searchtitle:"Cercar informació",refreshtext:"",refreshtitle:"Refrescar taula",alertcap:"AvÃs",alerttext:"Seleccioni una fila"};a.jgrid.col={caption:"Mostrar/ocultar columnes",bSubmit:"Enviar",bCancel:"Cancelar"};a.jgrid.errors={errcap:"Error",nourl:"No s'ha especificat una URL",norecords:"No hi ha dades per processar",model:"Les columnes de noms són diferents de les columnes del model"};a.jgrid.formatter={integer:{thousandsSeparator:".",defaulValue:0},number:{decimalSeparator:",",thousandsSeparator:".",decimalPlaces:2,defaulValue:0},currency:{decimalSeparator:",",thousandsSeparator:".",decimalPlaces:2,prefix:"",suffix:"",defaulValue:0},date:{dayNames:["Dg","Dl","Dt","Dc","Dj","Dv","Ds","Diumenge","Dilluns","Dimarts","Dimecres","Dijous","Divendres","Dissabte"],monthNames:["Gen","Febr","Març","Abr","Maig","Juny","Jul","Ag","Set","Oct","Nov","Des","Gener","Febrer","Març","Abril","Maig","Juny","Juliol","Agost","Setembre","Octubre","Novembre","Desembre"],AmPm:["am","pm","AM","PM"],S:function(b){return b<11||b>13?["st","nd","rd","th"][Math.min((b-1)%10,3)]:"th"},srcformat:"Y-m-d",newformat:"d-m-Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"n/j/Y",LongDate:"l, F d, Y",FullDateTime:"l, F d, Y g:i:s A",MonthDay:"F d",ShortTime:"g:i A",LongTime:"g:i:s A",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F, Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"show"}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-cs-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-cs-min.js new file mode 100644 index 0000000..0865805 --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-cs-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"Å?ádek(ů)",loadtext:"NaÄÃtám...",pgtext:"/"};a.jgrid.search={caption:"Vyhledávám...",Find:"Hledat",Reset:"Reset",odata:["rovno","nenà rovno","menÅ¡Ã","menšà nebo rovno","vÄ›tÅ¡Ã","vÄ›tšà nebo rovno","zaÄÃná na","konÄà na","obsahuje"]};a.jgrid.edit={addCaption:"PÅ™idat záznam",editCaption:"Editace záznamu",bSubmit:"Uložit",bCancel:"Storno",bClose:"ZavÅ™Ãt",processData:"Zpracovávám...",msg:{required:"Pole je vyžadováno",number:"ProsÃm, vložte validnà ÄÃslo",minValue:"hodnota musà být vÄ›tšà než nebo rovná ",maxValue:"hodnota musà být menšà než nebo rovná ",email:"nenà validnà e-mail",integer:"ProsÃm, vložte celé ÄÃslo",date:"ProsÃm, vložte validnà datum"}};a.jgrid.del={caption:"Smazat",msg:"Smazat vybraný(é) záznam(y)?",bSubmit:"Smazat",bCancel:"Storno",processData:"Zpracovávám..."};a.jgrid.nav={edittext:" ",edittitle:"Editovat vybraný řádek",addtext:" ",addtitle:"PÅ™idat nový řádek",deltext:" ",deltitle:"Smazat vybraný záznam ",searchtext:" ",searchtitle:"NajÃt záznamy",refreshtext:"",refreshtitle:"Obnovit tabulku",alertcap:"VarovánÃ",alerttext:"ProsÃm, vyberte řádek"};a.jgrid.col={caption:"Zobrazit/Skrýt sloupce",bSubmit:"Uložit",bCancel:"Storno"};a.jgrid.errors={errcap:"Chyba",nourl:"Nenà nastavena url",norecords:"Žádné záznamy ke zpracovánÃ",model:"Length colNames <> colModel!"};a.jgrid.formatter={integer:{thousandsSeparator:" ",defaulValue:0},number:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,defaulValue:0},currency:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,prefix:"",suffix:"",defaulValue:0},date:{dayNames:["Ne","Po","Út","St","ÄŒt","Pá","So","NedÄ›le","PondÄ›lÃ","Úterý","StÅ™eda","ÄŒtvrtek","Pátek","Sobota"],monthNames:["Led","Úno","BÅ™e","Dub","KvÄ›","ÄŒer","ÄŒvc","Srp","Zář","Å?Ãj","Lis","Pro","Leden","Únor","BÅ™ezen","Duben","KvÄ›ten","ÄŒerven","ÄŒervenec","Srpen","ZářÃ","Å?Ãjen","Listopad","Prosinec"],AmPm:["do","od","DO","OD"],S:function(b){return b<11||b>13?["st","nd","rd","th"][Math.min((b-1)%10,3)]:"th"},srcformat:"Y-m-d",newformat:"d/m/Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"n/j/Y",LongDate:"l, F d, Y",FullDateTime:"l, F d, Y g:i:s A",MonthDay:"F d",ShortTime:"g:i A",LongTime:"g:i:s A",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F, Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"show",addParam:""}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-de-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-de-min.js new file mode 100644 index 0000000..2f1472a --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-de-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"Zeile(n)",loadtext:"Lädt...",pgtext:"/"};a.jgrid.search={caption:"Suche...",Find:"Finden",Reset:"Zurücksetzen",odata:["gleich","ungleich","kleiner","kleiner oder gleich","größer","größer oder gleich","beginnt mit","endet mit","beinhaltet"]};a.jgrid.edit={addCaption:"Datensatz hinzufügen",editCaption:"Datensatz bearbeiten",bSubmit:"Speichern",bCancel:"Abbrechen",bClose:"Schließen",processData:"Verarbeitung läuft...",msg:{required:"Feld ist erforderlich",number:"Bitte geben Sie eine Zahl ein",minValue:"Wert muss größer oder gleich sein, als ",maxValue:"Wert muss kleiner oder gleich sein, als ",email:"ist keine valide E-Mail Adresse",integer:"Bitte geben Sie eine Ganzzahl ein",date:"Please, enter valid date value"}};a.jgrid.del={caption:"Löschen",msg:"Ausgewählte Datensätze löschen?",bSubmit:"Löschen",bCancel:"Abbrechen",processData:"Verarbeitung läuft..."};a.jgrid.nav={edittext:" ",edittitle:"Ausgewählten Zeile editieren",addtext:" ",addtitle:"Neuen Zeile einfügen",deltext:" ",deltitle:"Ausgewählte Zeile löschen",searchtext:" ",searchtitle:"Datensatz finden",refreshtext:"",refreshtitle:"Tabelle neu laden",alertcap:"Warnung",alerttext:"Bitte Zeile auswählen"};a.jgrid.col={caption:"Spalten anzeigen/verbergen",bSubmit:"Speichern",bCancel:"Abbrechen"};a.jgrid.errors={errcap:"Fehler",nourl:"Keine URL angegeben",norecords:"Keine Datensätze zum verarbeiten",model:"Length of colNames <> colModel!"};a.jgrid.formatter={integer:{thousandsSeparator:" ",defaulValue:0},number:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,defaulValue:0},currency:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,prefix:"",suffix:"",defaulValue:0},date:{dayNames:["Sun","Mon","Tue","Wed","Thr","Fri","Sat","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],monthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","January","February","March","April","May","June","July","August","September","October","November","December"],AmPm:["am","pm","AM","PM"],S:function(b){return b<11||b>13?["st","nd","rd","th"][Math.min((b-1)%10,3)]:"th"},srcformat:"Y-m-d",newformat:"d/m/Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"n/j/Y",LongDate:"l, F d, Y",FullDateTime:"l, F d, Y g:i:s A",MonthDay:"F d",ShortTime:"g:i A",LongTime:"g:i:s A",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F, Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"show"}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-dk-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-dk-min.js new file mode 100644 index 0000000..4e593eb --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-dk-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"Række(r)",loadtext:"Indlæser...",pgtext:"/"};a.jgrid.search={caption:"Søg...",Find:"Find",Reset:"Nulstil",odata:["lig med","forskellig fra","mindre end","mindre end eller lig med","større end"," større end eller lig med","starter med","slutter med","indeholder"]};a.jgrid.edit={addCaption:"Tilføj",editCaption:"Ret",bSubmit:"Send",bCancel:"Annuller",bClose:"Luk",processData:"Behandler...",msg:{required:"Felt er nødvendigt",number:"Indtast venligst et validt tal",minValue:"værdi skal være større end eller lig med",maxValue:"værdi skal være mindre end eller lig med",email:"er ikke en valid email",integer:"Indtast venligst et validt heltalt",date:"Indtast venligst en valid datoværdi"}};a.jgrid.del={caption:"Slet",msg:"Slet valgte række(r)?",bSubmit:"Slet",bCancel:"Annuller",processData:"Behandler..."};a.jgrid.nav={edittext:" ",edittitle:"Rediger valgte række",addtext:" ",addtitle:"Tilføj ny række",deltext:" ",deltitle:"Slet valgte række",searchtext:" ",searchtitle:"Find poster",refreshtext:"",refreshtitle:"Indlæs igen",alertcap:"Advarsel",alerttext:"Vælg venligst række"};a.jgrid.col={caption:"Vis/skjul kolonner",bSubmit:"Send",bCancel:"Annuller"};a.jgrid.errors={errcap:"Fejl",nourl:"Ingel url valgt",norecords:"Ingen poster at behandle",model:"colNames og colModel har ikke samme længde!"};a.jgrid.formatter={integer:{thousandsSeparator:" ",defaulValue:0},number:{decimalSeparator:",",thousandsSeparator:" ",decimalPlaces:2,defaulValue:0},currency:{decimalSeparator:",",thousandsSeparator:" ",decimalPlaces:2,prefix:"",suffix:"",defaulValue:0},date:{dayNames:["Søn","Man","Tirs","Ons","Tors","Fre","Lør","Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],monthNames:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec","Januar","Februar","Marts","April","Maj","Juni","Juli","August","September","Oktober","November","December"],AmPm:["","","",""],S:function(b){return"."},srcformat:"Y-m-d",newformat:"d/m/Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"j/n/Y",LongDate:"l d. F Y",FullDateTime:"l d F Y G:i:s",MonthDay:"d. F",ShortTime:"G:i",LongTime:"G:i:s",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"show"}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-el-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-el-min.js new file mode 100644 index 0000000..777ee1a --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-el-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"ΕγγÏαφÎÏ‚",loadtext:"ΦόÏτωση...",pgtext:"/"};a.jgrid.search={caption:"Αναζήτηση...",Find:"ΕÏÏεση",Reset:"ΕπαναφοÏά",odata:["ίσο","άνισο","μικÏότεÏο από","μικÏότεÏο ή ίσο","μεγαλÏτεÏο από","μεγαλÏτεÏο ή ίσο","ξεκινά με","τελειώνει με","εμπεÏιÎχει"]};a.jgrid.edit={addCaption:"Εισαγωγή ΕγγÏαφής",editCaption:"ΕπεξεÏγασία ΕγγÏαφής",bSubmit:"ΚαταχώÏηση",bCancel:"ΆκυÏο",bClose:"Κλείσιμο",processData:"Υπό επεξεÏγασία...",msg:{required:"Το πεδίο είναι απαÏαίτητο",number:"Το πεδίο δÎχεται μόνο αÏιθμοÏÏ‚",minValue:"Η τιμή Ï€ÏÎπει να είναι μεγαλÏτεÏη ή ίση του ",maxValue:"Η τιμή Ï€ÏÎπει να είναι μικÏότεÏη ή ίση του ",email:"Η διεÏθυνση e-mail δεν είναι ÎγκυÏη",integer:"Το πεδίο δÎχεται μόνο ακÎÏαιους αÏιθμοÏÏ‚",date:"Ή ημεÏομηνία δεν είναι ÎγκυÏη"}};a.jgrid.del={caption:"ΔιαγÏαφή",msg:"ΔιαγÏαφή των επιλεγμÎνων εγγÏαφών;",bSubmit:"Îαι",bCancel:"ΆκυÏο",processData:"Υπό επεξεÏγασία..."};a.jgrid.nav={edittext:" ",edittitle:"ΕπεξεÏγασία επιλεγμÎνης εγγÏαφής",addtext:" ",addtitle:"Εισαγωγή νÎας εγγÏαφής",deltext:" ",deltitle:"ΔιαγÏαφή επιλεγμÎνης εγγÏαφής",searchtext:" ",searchtitle:"ΕÏÏεση ΕγγÏαφών",refreshtext:"",refreshtitle:"ΑνανÎωση Πίνακα",alertcap:"ΠÏοσοχή",alerttext:"Δεν Îχετε επιλÎξει εγγÏαφή"};a.jgrid.col={caption:"Εμφάνιση / ΑπόκÏυψη Στηλών",bSubmit:"ΟΚ",bCancel:"ΆκυÏο"};a.jgrid.errors={errcap:"Σφάλμα",nourl:"Δεν Îχει δοθεί διεÏθυνση χειÏÎ¹ÏƒÎ¼Î¿Ï Î³Î¹Î± τη συγκεκÏιμÎνη ενÎÏγεια",norecords:"Δεν υπάÏχουν εγγÏαφÎÏ‚ Ï€Ïος επεξεÏγασία",model:"Άνισος αÏιθμός πεδίων colNames/colModel!"};a.jgrid.formatter={integer:{thousandsSeparator:" ",defaulValue:0},number:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,defaulValue:0},currency:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,prefix:"",suffix:"",defaulValue:0},date:{dayNames:["ΚυÏ","Δευ","ΤÏι","Τετ","Πεμ","ΠαÏ","Σαβ","ΚυÏιακή","ΔευτÎÏα","ΤÏίτη","ΤετάÏτη","ΠÎμπτη","ΠαÏασκευή","Σάββατο"],monthNames:["Ιαν","Φεβ","ΜαÏ","ΑπÏ","Μαι","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Îοε","Δεκ","ΙανουάÏιος","ΦεβÏουάÏιος","ΜάÏτιος","ΑπÏίλιος","Μάιος","ΙοÏνιος","ΙοÏλιος","ΑÏγουστος","ΣεπτÎμβÏιος","ΟκτώβÏιος","ÎοÎμβÏιος","ΔεκÎμβÏιος"],AmPm:["πμ","μμ","ΠΜ","ΜΜ"],S:function(b){return b==1||b>1?["η"][Math.min((b-1)%10,3)]:""},srcformat:"Y-m-d",newformat:"d/m/Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"n/j/Y",LongDate:"l, F d, Y",FullDateTime:"l, F d, Y g:i:s A",MonthDay:"F d",ShortTime:"g:i A",LongTime:"g:i:s A",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F, Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"show"}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-en-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-en-min.js new file mode 100644 index 0000000..6688b99 --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-en-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"Row(s)",loadtext:"Loading...",pgtext:"/"};a.jgrid.search={caption:"Search...",Find:"Find",Reset:"Reset",odata:["equal","not equal","less","less or equal","greater","greater or equal","begins with","ends with","contains"]};a.jgrid.edit={addCaption:"Add Record",editCaption:"Edit Record",bSubmit:"Submit",bCancel:"Cancel",bClose:"Close",processData:"Processing...",msg:{required:"Field is required",number:"Please, enter valid number",minValue:"value must be greater than or equal to ",maxValue:"value must be less than or equal to",email:"is not a valid e-mail",integer:"Please, enter valid integer value",date:"Please, enter valid date value"}};a.jgrid.view={caption:"View Record",bClose:"Close"};a.jgrid.del={caption:"Delete",msg:"Delete selected record(s)?",bSubmit:"Delete",bCancel:"Cancel",processData:"Processing..."};a.jgrid.nav={edittext:" ",edittitle:"Edit selected row",addtext:" ",addtitle:"Add new row",deltext:" ",deltitle:"Delete selected row",searchtext:" ",searchtitle:"Find records",refreshtext:"",refreshtitle:"Reload Grid",alertcap:"Warning",alerttext:"Please, select row",viewtext:" ",viewtitle:"View selected row"};a.jgrid.col={caption:"Show/Hide Columns",bSubmit:"Submit",bCancel:"Cancel"};a.jgrid.errors={errcap:"Error",nourl:"No url is set",norecords:"No records to process",model:"Length of colNames <> colModel!"};a.jgrid.formatter={integer:{thousandsSeparator:" ",defaulValue:0},number:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,defaulValue:0},currency:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,prefix:"",suffix:"",defaulValue:0},date:{dayNames:["Sun","Mon","Tue","Wed","Thr","Fri","Sat","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],monthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","January","February","March","April","May","June","July","August","September","October","November","December"],AmPm:["am","pm","AM","PM"],S:function(b){return b<11||b>13?["st","nd","rd","th"][Math.min((b-1)%10,3)]:"th"},srcformat:"Y-m-d",newformat:"d/m/Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"n/j/Y",LongDate:"l, F d, Y",FullDateTime:"l, F d, Y g:i:s A",MonthDay:"F d",ShortTime:"g:i A",LongTime:"g:i:s A",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F, Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"show",addParam:"",checkbox:{disabled:true}}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-fi-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-fi-min.js new file mode 100644 index 0000000..af59783 --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-fi-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"Rivejä",loadtext:"Haetaan...",pgtext:"/"};a.jgrid.search={caption:"Etsi...",Find:"Etsi",Reset:"Tyhjää",odata:["=","<>","<","<=",">",">=","alkaa","loppuu","sisätää"]};a.jgrid.edit={addCaption:"Uusi rivi",editCaption:"Muokkaa rivi",bSubmit:"OK",bCancel:"Peru",bClose:"Sulje",processData:"Suoritetaan...",msg:{required:"pakollinen",number:"Anna kelvollinen nro",minValue:"arvo oltava >= ",maxValue:"arvo oltava <= ",email:"virheellinen sposti ",integer:"Anna kelvollinen kokonaisluku",date:"Anna kelvollinen pvm"}};a.jgrid.del={caption:"Poista",msg:"Poista valitut rivi(t)?",bSubmit:"Poista",bCancel:"Peru",processData:"Suoritetaan..."};a.jgrid.nav={edittext:" ",edittitle:"Muokkaa valittu rivi",addtext:" ",addtitle:"Uusi rivi",deltext:" ",deltitle:"Poista valittu rivi",searchtext:" ",searchtitle:"Etsi tietoja",refreshtext:"",refreshtitle:"Lataa uudelleen",alertcap:"Varoitus",alerttext:"Valitse rivi"};a.jgrid.col={caption:"Nayta/Piilota sarakkeet",bSubmit:"OK",bCancel:"Peru"};a.jgrid.errors={errcap:"Virhe",nourl:"url asettamatta",norecords:"Ei muokattavia tietoja",model:"Pituus colNames <> colModel!"};a.jgrid.formatter={integer:{thousandsSeparator:"",defaulValue:0},number:{decimalSeparator:",",thousandsSeparator:"",decimalPlaces:2,defaulValue:0},currency:{decimalSeparator:",",thousandsSeparator:"",decimalPlaces:2,prefix:"",suffix:"",defaulValue:0},date:{dayNames:["Su","Ma","Ti","Ke","To","Pe","La","Sunnuntai","Maanantai","Tiista","Keskiviikko","Torstai","Perjantai","Lauantai"],monthNames:["Tam","Hel","Maa","Huh","Tou","Kes","Hei","Elo","Syy","Lok","Mar","Jou","Tammikuu","Helmikuu","Maaliskuu","Huhtikuu","Toukokuu","Kesäkuu","Heinäkuu","Elokuu","Syyskuu","Lokakuu","Marraskuu","Joulukuu"],AmPm:["am","pm","AM","PM"],S:function(b){return b<11||b>13?["st","nd","rd","th"][Math.min((b-1)%10,3)]:"th"},srcformat:"Y-m-d",newformat:"d/m/Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"d.m.Y",LongDate:"l, F d, Y",FullDateTime:"l, F d, Y g:i:s A",MonthDay:"F d",ShortTime:"g:i A",LongTime:"g:i:s A",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F, Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"nayta"}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-fr-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-fr-min.js new file mode 100644 index 0000000..853d029 --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-fr-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"Ligne(s)",loadtext:"Chargement...",pgtext:"/"};a.jgrid.search={caption:"Recherche...",Find:"Chercher",Reset:"Annuler",odata:["égal","différent","inférieur","inférieur ou égal","supérieur","supérieur ou égal","débute par","termine par","contient"]};a.jgrid.edit={addCaption:"Ajouter",editCaption:"Editer",bSubmit:"Valider",bCancel:"Annuler",bClose:"Fermer",processData:"Traitement...",msg:{required:"Champ obligatoire",number:"Saisissez un nombre valide",minValue:"La valeur doit être supérieure ou égal à 0 ",maxValue:"La valeur doit être inférieure ou égal à 0",email:"n'est pas un email valide",integer:"Saisissez un entier valide",date:"Saisissez une date valide"}};a.jgrid.del={caption:"Supprimer",msg:"Supprimer les enregistrements sélectionnés ?",bSubmit:"Supprimer",bCancel:"Annuler",processData:"Traitement..."};a.jgrid.nav={edittext:" ",edittitle:"Editer la ligne sélectionnée",addtext:" ",addtitle:"Ajouter une ligne",deltext:" ",deltitle:"Supprimer la ligne sélectionnée",searchtext:" ",searchtitle:"Chercher un enregistrement",refreshtext:"",refreshtitle:"Recharger le tableau",alertcap:"Avertissement",alerttext:"Veuillez sélectionner une ligne"};a.jgrid.col={caption:"Afficher/Masquer les colonnes",bSubmit:"Valider",bCancel:"Annuler"};a.jgrid.errors={errcap:"Erreur",nourl:"Aucune url paramétrée",norecords:"Aucun enregistrement à traiter",model:"Nombre de titres (colNames) <> Nombre de données (colModel)!"};a.jgrid.formatter={integer:{thousandsSeparator:" ",defaulValue:0},number:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,defaulValue:0},currency:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,prefix:"",suffix:"",defaulValue:0},date:{dayNames:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam","Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],monthNames:["Jan","Fev","Mar","Avr","Mai","Jui","Jul","Aou","Sep","Oct","Nov","Dec","Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Saptembre","Octobre","Novembre","Décembre"],AmPm:["am","pm","AM","PM"],S:function(b){return b<11||b>13?["st","nd","rd","th"][Math.min((b-1)%10,3)]:"th"},srcformat:"Y-m-d",newformat:"d/m/Y",masks:{ISO8601Long:"d-m-Y H:i:s",ISO8601Short:"d-m-Y",ShortDate:"j/n/Y",LongDate:"l d F Y",FullDateTime:"l d F Y, G:i:s",MonthDay:"d F",ShortTime:"G:i",LongTime:"G:i:s",SortableDateTime:"d-m-Y\\TH:i:s",UniversalSortableDateTime:"d-m-Y H:i:sO",YearMonth:"F Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"show"}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-is-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-is-min.js new file mode 100644 index 0000000..4e0c57e --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-is-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"Raðir(s)",loadtext:"Hleður...",pgtext:"/"};a.jgrid.search={caption:"Leita...",Find:"Leita",Reset:"Endursetja",odata:["sama og","ekki sama og","minna en","minna en eða jafnt og","meira en","meira en eða jafnt og","byrjar á","endar á","inniheldur"]};a.jgrid.edit={addCaption:"Add Record",editCaption:"Edit Record",bSubmit:"Vista",bCancel:"Hætta við",bClose:"Loka",processData:"Vinnur...",msg:{required:"Reitur er nauðsynlegur",number:"Vinsamlega settu inn tölu",minValue:"gildi verður að vera meira en eða jafnt og ",maxValue:"gildi verður að vera minna en eða jafnt og ",email:"er ekki löglegt email",integer:"Vinsamlega settu inn tölu"}};a.jgrid.del={caption:"Eyða",msg:"Eyða völdum færslum ?",bSubmit:"Eyða",bCancel:"Hætta við",processData:"Vinnur..."};a.jgrid.nav={edittext:" ",edittitle:"Breyta færslu",addtext:" ",addtitle:"Ný færsla",deltext:" ",deltitle:"Eyða færslu",searchtext:" ",searchtitle:"Leita",refreshtext:"",refreshtitle:"Endurhlaða",alertcap:"Viðvörun",alerttext:"Vinsamlega veldu færslu"};a.jgrid.col={caption:"Sýna / fela dálka",bSubmit:"Vista",bCancel:"Hætta við"};a.jgrid.errors={errcap:"Villa",nourl:"Vantar slóð",norecords:"Engar færslur valdar",model:"Length of colNames <> colModel!"};a.jgrid.formatter={integer:{thousandsSeparator:" ",defaulValue:0},number:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,defaulValue:0},currency:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,prefix:"",suffix:"",defaulValue:0},date:{dayNames:["Sun","Mon","Tue","Wed","Thr","Fri","Sat","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],monthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","January","February","March","April","May","June","July","August","September","October","November","December"],AmPm:["am","pm","AM","PM"],S:function(b){return b<11||b>13?["st","nd","rd","th"][Math.min((b-1)%10,3)]:"th"},srcformat:"Y-m-d",newformat:"d/m/Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"n/j/Y",LongDate:"l, F d, Y",FullDateTime:"l, F d, Y g:i:s A",MonthDay:"F d",ShortTime:"g:i A",LongTime:"g:i:s A",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F, Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"show"}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-it-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-it-min.js new file mode 100644 index 0000000..027f1d3 --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-it-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"Record",loadtext:"Caricamento...",pgtext:"/"};a.jgrid.search={caption:"Ricerca...",Find:"Cerca",Reset:"Pulisci",odata:["uguale","diverso","minore","minore o uguale","maggiore","maggiore o uguale","inizia con","finisce con","contiene"]};a.jgrid.edit={addCaption:"Aggiungi Record",editCaption:"Modifica Record",bSubmit:"Invia",bCancel:"Annulla",bClose:"Chiudi",processData:"In elaborazione...",msg:{required:"Campo richiesto",number:"Per favore, inserisci un valore valido",minValue:"il valore deve essere maggiore o uguale a ",maxValue:"il valore deve essere minore o uguale a",email:"e-mail non corretta",integer:"Please, enter valid integer value",date:"Please, enter valid date value"}};a.jgrid.del={caption:"Cancella",msg:"Cancellare record selezionato/i?",bSubmit:"Cancella",bCancel:"Annulla",processData:"In elaborazione..."};a.jgrid.nav={edittext:" ",edittitle:"Modifica record selezionato",addtext:" ",addtitle:"Aggiungi nuovo record",deltext:" ",deltitle:"Cancella record selezionato",searchtext:" ",searchtitle:"Ricerca record",refreshtext:"",refreshtitle:"Aggiorna griglia",alertcap:"Attenzione",alerttext:"Per favore, seleziona un record"};a.jgrid.col={caption:"Mostra/Nascondi Colonne",bSubmit:"Invia",bCancel:"Annulla"};a.jgrid.errors={errcap:"Errore",nourl:"Url non settata",norecords:"Nessun record da elaborare",model:"Length of colNames <> colModel!"};a.jgrid.formatter={integer:{thousandsSeparator:" ",defaulValue:0},number:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,defaulValue:0},currency:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,prefix:"",suffix:"",defaulValue:0},date:{dayNames:["Sun","Mon","Tue","Wed","Thr","Fri","Sat","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],monthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","January","February","March","April","May","June","July","August","September","October","November","December"],AmPm:["am","pm","AM","PM"],S:function(b){return b<11||b>13?["st","nd","rd","th"][Math.min((b-1)%10,3)]:"th"},srcformat:"Y-m-d",newformat:"d/m/Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"n/j/Y",LongDate:"l, F d, Y",FullDateTime:"l, F d, Y g:i:s A",MonthDay:"F d",ShortTime:"g:i A",LongTime:"g:i:s A",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F, Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"show"}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-jp-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-jp-min.js new file mode 100644 index 0000000..bcfcad8 --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-jp-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"\u884c",loadtext:"\u8aad\u307f\u8fbc\u307f\u4e2d...",pgtext:"/"};a.jgrid.search={caption:"\u691c\u7d22...",Find:"\u691c\u7d22",Reset:"\u30ea\u30bb\u30c3\u30c8",odata:["=","!=","<","<=",">",">=","\u6b21\u306e\u8a00\u8449\u3067\u59cb\u307e\u308b","\u6b21\u306e\u8a00\u8449\u3067\u7d42\u308f\u308b","\u6b21\u306e\u8a00\u8449\u3092\u542b\u3080"]};a.jgrid.edit={addCaption:"\u30ec\u30b3\u30fc\u30c9\u8ffd\u52a0",editCaption:"\u30ec\u30b3\u30fc\u30c9\u7de8\u96c6",bSubmit:"\u9001\u4fe1",bCancel:"\u30ad\u30e3\u30f3\u30bb\u30eb",bClose:"\u9589\u3058\u308b",processData:"\u51e6\u7406\u4e2d...",msg:{required:"\u3053\u306e\u9805\u76ee\u306f\u5fc5\u9808\u3067\u3059\u3002",number:"\u6b63\u3057\u3044\u6570\u5024\u3092\u5165\u529b\u3057\u3066\u4e0b\u3055\u3044\u3002",minValue:"\u6b21\u306e\u5024\u4ee5\u4e0a\u3067\u5165\u529b\u3057\u3066\u4e0b\u3055\u3044\u3002",maxValue:"\u6b21\u306e\u5024\u4ee5\u4e0b\u3067\u5165\u529b\u3057\u3066\u4e0b\u3055\u3044\u3002",email:"e-mail\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002",integer:"\u6b63\u3057\u3044\u6574\u6570\u5024\u3092\u5165\u529b\u3057\u3066\u4e0b\u3055\u3044\u3002",date:"\u6b63\u3057\u3044\u5024\u3092\u5165\u529b\u3057\u3066\u4e0b\u3055\u3044\u3002"}};a.jgrid.del={caption:"\u524a\u9664",msg:"\u9078\u629e\u3057\u305f\u30ec\u30b3\u30fc\u30c9\u3092\u524a\u9664\u3057\u307e\u3059\u304b\uff1f",bSubmit:"\u524a\u9664",bCancel:"\u30ad\u30e3\u30f3\u30bb\u30eb",processData:"\u51e6\u7406\u4e2d..."};a.jgrid.nav={edittext:" ",edittitle:"\u9078\u629e\u3057\u305f\u884c\u3092\u7de8\u96c6",addtext:" ",addtitle:"\u884c\u3092\u65b0\u898f\u8ffd\u52a0",deltext:" ",deltitle:"\u9078\u629e\u3057\u305f\u884c\u3092\u524a\u9664",searchtext:" ",searchtitle:"\u30ec\u30b3\u30fc\u30c9\u691c\u7d22",refreshtext:"",refreshtitle:"\u30b0\u30ea\u30c3\u30c9\u3092\u30ea\u30ed\u30fc\u30c9",alertcap:"\u8b66\u544a",alerttext:"\u884c\u3092\u9078\u629e\u3057\u3066\u4e0b\u3055\u3044\u3002"};a.jgrid.col={caption:"\u5217\u3092\u8868\u793a\uff0f\u96a0\u3059",bSubmit:"\u9001\u4fe1",bCancel:"\u30ad\u30e3\u30f3\u30bb\u30eb"};a.jgrid.errors={errcap:"\u30a8\u30e9\u30fc",nourl:"URL\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002",norecords:"\u51e6\u7406\u5bfe\u8c61\u306e\u30ec\u30b3\u30fc\u30c9\u304c\u3042\u308a\u307e\u305b\u3093\u3002",model:"colNames\u306e\u9577\u3055\u304ccolModel\u3068\u4e00\u81f4\u3057\u307e\u305b\u3093\u3002"};a.jgrid.formatter={integer:{thousandsSeparator:" ",defaulValue:0},number:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,defaulValue:0},currency:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,prefix:"",suffix:"",defaulValue:0},date:{dayNames:["\u65e5","\u6708","\u706b","\u6c34","\u6728","\u91d1","\u571f","\u65e5","\u6708","\u706b","\u6c34","\u6728","\u91d1","\u571f"],monthNames:["1","2","3","4","5","6","7","8","9","10","11","12","1\u6708","2\u6708","3\u6708","4\u6708","5\u6708","6\u6708","7\u6708","8\u6708","9\u6708","10\u6708","11\u6708","12\u6708"],AmPm:["am","pm","AM","PM"],S:"\u756a\u76ee",srcformat:"Y-m-d",newformat:"d/m/Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"n/j/Y",LongDate:"l, F d, Y",FullDateTime:"l, F d, Y g:i:s A",MonthDay:"F d",ShortTime:"g:i A",LongTime:"g:i:s A",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F, Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"\u8868\u793a",addParam:""}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-pl-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-pl-min.js new file mode 100644 index 0000000..c4fea0d --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-pl-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"Wiersz(y)",loadtext:"Åadowanie...",pgtext:"/"};a.jgrid.search={caption:"Wyszukiwanie...",Find:"Szukaj",Reset:"Czyść",odata:["dokÅ‚adnie","różne od","mniejsze od","mniejsze lub różne","wiÄ™ksze od","wiÄ™ksze lub różne","zacznij od","zakoÅ„cz na","zawiera"]};a.jgrid.edit={addCaption:"Dodaj rekord",editCaption:"Edytuj rekord",bSubmit:"Zapisz",bCancel:"Anuluj",bClose:"Zamknij",processData:"Przetwarzanie...",msg:{required:"Pole jest wymagane",number:"ProszÄ™ wpisać poprawnÄ… liczbÄ™",minValue:"wartość musi być wiÄ™ksza lub równa",maxValue:"wartość musi być mniejsza od",email:"nie jest adresem e-mail",integer:"ProszÄ™ wpisać poprawnÄ… liczbÄ™",date:"Please, enter valid date value"}};a.jgrid.del={caption:"Usuwanie",msg:"UsuÅ„ wybrany rekord(y)?",bSubmit:"UsuÅ„",bCancel:"Anuluj",processData:"Przetwarzanie..."};a.jgrid.nav={edittext:" ",edittitle:"Edytuj wybrany wiersz",addtext:" ",addtitle:"Dodaj nowy wiersz",deltext:" ",deltitle:"UsuÅ„ wybrany wiersz",searchtext:" ",searchtitle:"Wyszukaj rekord",refreshtext:"",refreshtitle:"PrzeÅ‚aduj",alertcap:"Uwaga",alerttext:"ProszÄ™ wybrać wiersz"};a.jgrid.col={caption:"Pokaż/Ukryj kolumny",bSubmit:"Zatwierdź",bCancel:"Anuluj"};a.jgrid.errors={errcap:"Błąd",nourl:"Brak adresu url",norecords:"Brak danych",model:"Length of colNames <> colModel!"};a.jgrid.formatter={integer:{thousandsSeparator:" ",defaulValue:0},number:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,defaulValue:0},currency:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,prefix:"",suffix:"",defaulValue:0},date:{dayNames:["Sun","Mon","Tue","Wed","Thr","Fri","Sat","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],monthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","January","February","March","April","May","June","July","August","September","October","November","December"],AmPm:["am","pm","AM","PM"],S:function(b){return b<11||b>13?["st","nd","rd","th"][Math.min((b-1)%10,3)]:"th"},srcformat:"Y-m-d",newformat:"d/m/Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"n/j/Y",LongDate:"l, F d, Y",FullDateTime:"l, F d, Y g:i:s A",MonthDay:"F d",ShortTime:"g:i A",LongTime:"g:i:s A",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F, Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"show"}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-pt-br-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-pt-br-min.js new file mode 100644 index 0000000..326802b --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-pt-br-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"Registro(s)",loadtext:"Carregando...",pgtext:"/"};a.jgrid.search={caption:"Procurar...",Find:"Procurar",Reset:"Resetar",odata:["igual","diferente","menor","menor igual","maior","maior igual","começando com","terminando com","contém"]};a.jgrid.edit={addCaption:"Incluir",editCaption:"Alterar",bSubmit:"Enviar",bCancel:"Cancelar",bClose:"Fechar",processData:"Carregando...",msg:{required:"Campo é requerido",number:"Por favor, informe um número válido",minValue:"valor deve ser igual ou maior que ",maxValue:"valor deve ser menor ou igual a",email:"este e-mail não é válido",integer:"Por favor, informe um valor inteiro",date:"Please, enter valid date value"}};a.jgrid.del={caption:"Delete",msg:"Deletar registros selecionado(s)?",bSubmit:"Delete",bCancel:"Cancelar",processData:"Carregando..."};a.jgrid.nav={edittext:" ",edittitle:"Alterar registro selecionado",addtext:" ",addtitle:"Incluir novo registro",deltext:" ",deltitle:"Deletar registro selecionado",searchtext:" ",searchtitle:"Procurar registros",refreshtext:"",refreshtitle:"Recarrgando Tabela",alertcap:"Aviso",alerttext:"Por favor, selecione um registro"};a.jgrid.col={caption:"Mostrar/Esconder Colunas",bSubmit:"Enviar",bCancel:"Cancelar"};a.jgrid.errors={errcap:"Erro",nourl:"Nenhuma URL defenida",norecords:"Sem registros para exibir",model:"Length of colNames <> colModel!"};a.jgrid.formatter={integer:{thousandsSeparator:" ",defaulValue:0},number:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,defaulValue:0},currency:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,prefix:"",suffix:"",defaulValue:0},date:{dayNames:["Sun","Mon","Tue","Wed","Thr","Fri","Sat","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],monthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","January","February","March","April","May","June","July","August","September","October","November","December"],AmPm:["am","pm","AM","PM"],S:function(b){return b<11||b>13?["st","nd","rd","th"][Math.min((b-1)%10,3)]:"th"},srcformat:"Y-m-d",newformat:"d/m/Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"n/j/Y",LongDate:"l, F d, Y",FullDateTime:"l, F d, Y g:i:s A",MonthDay:"F d",ShortTime:"g:i A",LongTime:"g:i:s A",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F, Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"show"}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-pt-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-pt-min.js new file mode 100644 index 0000000..7617390 --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-pt-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"Registo(s)",loadtext:"A carregar...",pgtext:"/"};a.jgrid.search={caption:"Busca...",Find:"Procurar",Reset:"Limpar",odata:["igual","não igual","menor","menor ou igual","maior","maior ou igual","começa com","termina com","contém"]};a.jgrid.edit={addCaption:"Adicionar Registo",editCaption:"Modificar Registo",bSubmit:"Submeter",bCancel:"Cancelar",bClose:"Fechar",processData:"A processar...",msg:{required:"Campo obrigatório",number:"Por favor, introduza um numero",minValue:"O valor deve ser maior ou igual que",maxValue:"O valor deve ser menor ou igual a",email:"Não é um endereço de email válido",integer:"Por favor, introduza um numero inteiro",date:"Por favor, introduza uma data válida."}};a.jgrid.del={caption:"Eliminar",msg:"Deseja eliminar o(s) registo(s) seleccionado(s)?",bSubmit:"Eliminar",bCancel:"Cancelar",processData:"A processar..."};a.jgrid.nav={edittext:" ",edittitle:"Modificar registo seleccionado",addtext:" ",addtitle:"Adicionar novo registo",deltext:" ",deltitle:"Eliminar registo seleccionado",searchtext:" ",searchtitle:"Procurar",refreshtext:"",refreshtitle:"Actualizar",alertcap:"Aviso",alerttext:"Por favor, seleccione um registo"};a.jgrid.col={caption:"Mostrar/Ocultar Colunas",bSubmit:"Enviar",bCancel:"Cancelar"};a.jgrid.errors={errcap:"Erro",nourl:"Não especificou um url",norecords:"Não existem dados para processar",model:"Tamanho do colNames <> colModel!"};a.jgrid.formatter={integer:{thousandsSeparator:" ",defaulValue:0},number:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,defaulValue:0},currency:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,prefix:"",suffix:"",defaulValue:0},date:{dayNames:["Dom","Seg","Ter","Qua","Qui","Sex","Sab","Domingo","Segunda-Feira","Terça-Feira","Quarta-Feira","Quinta-Feira","Sexta-Feira","Sábado"],monthNames:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez","Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],AmPm:["am","pm","AM","PM"],S:function(b){return b<11||b>13?["º","º","º","º"][Math.min((b-1)%10,3)]:"º"},srcformat:"Y-m-d",newformat:"d/m/Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"n/j/Y",LongDate:"l, F d, Y",FullDateTime:"l, F d, Y g:i:s A",MonthDay:"F d",ShortTime:"g:i A",LongTime:"g:i:s A",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F, Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"show"}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-ru-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-ru-min.js new file mode 100644 index 0000000..4ca566e --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-ru-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"ЗапиÑей",loadtext:"Загрузка...",pgtext:"/"};a.jgrid.search={caption:"ПоиÑк...",Find:"Ðайти",Reset:"СброÑ",odata:["равно","не равно","меньше","меньше или равно","больше","больше или равно","начинаетÑÑ Ñ","заканчиваетÑÑ Ð½Ð°","Ñодержит"]};a.jgrid.edit={addCaption:"Добавить запиÑÑŒ",editCaption:"Редактировать запиÑÑŒ",bSubmit:"Сохранить",bCancel:"Отмена",bClose:"Закрыть",processData:"Обработка...",msg:{required:"Поле ÑвлÑетÑÑ Ð¾Ð±Ñзательным",number:"ПожалуйÑта, введите правильное чиÑло",minValue:"значение должно быть больше либо равно",maxValue:"значение должно быть больше либо равно",email:"некорректное значение e-mail",integer:"ПожалуйÑта введите целое чиÑло",date:"Please, enter valid date value"}};a.jgrid.del={caption:"Удалить",msg:"Удалить выделенную запиÑÑŒ(и)?",bSubmit:"Удвлить",bCancel:"Отмена",processData:"Обработка..."};a.jgrid.nav={edittext:" ",edittitle:"Редактировать выделенную запиÑÑŒ",addtext:" ",addtitle:"Добавить новую запиÑÑŒ",deltext:" ",deltitle:"Удалить выделенную запиÑÑŒ",searchtext:" ",searchtitle:"Ðайти запиÑи",refreshtext:"",refreshtitle:"Обновить таблицу",alertcap:"Внимание",alerttext:"ПожалуйÑта, выделите запиÑÑŒ"};a.jgrid.col={caption:"Показать/Ñкрыть Ñтолбцы",bSubmit:"Сохранить",bCancel:"Отмена"};a.jgrid.errors={errcap:"Ошибка",nourl:"URL не уÑтановлен",norecords:"Ðет запиÑей Ð´Ð»Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸",model:"ЧиÑло полей не ÑоответÑтвует чиÑлу Ñтолбцов таблицы!"};a.jgrid.formatter={integer:{thousandsSeparator:" ",defaulValue:0},number:{decimalSeparator:",",thousandsSeparator:" ",decimalPlaces:2,defaulValue:0},currency:{decimalSeparator:",",thousandsSeparator:" ",decimalPlaces:2,prefix:"",suffix:"",defaulValue:0},date:{dayNames:["Ð’Ñ","Пн","Ð’Ñ‚","Ср","Чт","Пт","Сб","ВоÑкреÑение","Понедельник","Вторник","Среда","Четверг","ПÑтница","Суббота"],monthNames:["Янв","Фев","Мар","Ðпр","Май","Ð?юн","Ð?юл","Ðвг","Сен","Окт","ÐоÑ","Дек","Январь","Февраль","Март","Ðпрель","Май","Ð?юнь","Ð?юль","ÐвгуÑÑ‚","СентÑбрь","ОктÑбрь","ÐоÑбрь","Декабрь"],AmPm:["am","pm","AM","PM"],S:function(b){return b<11||b>13?["st","nd","rd","th"][Math.min((b-1)%10,3)]:"th"},srcformat:"Y-m-d",newformat:"d.m.Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"n.j.Y",LongDate:"l, F d, Y",FullDateTime:"l, F d, Y G:i:s",MonthDay:"F d",ShortTime:"G:i",LongTime:"G:i:s",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F, Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"show"}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-sp-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-sp-min.js new file mode 100644 index 0000000..887cdf6 --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-sp-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"fila(s)",loadtext:"Cargando...",pgtext:"/"};a.jgrid.search={caption:"Búsqueda...",Find:"Buscar",Reset:"Limpiar",odata:["igual","no igual","menor","menor o igual","mayor","mayor o igual","comienza con","termina con","contiene"]};a.jgrid.edit={addCaption:"Agregar registro",editCaption:"Modificar registro",bSubmit:"Enviar",bCancel:"Cancelar",bClose:"Cerrar",processData:"Procesando...",msg:{required:"Campo obligatorio",number:"Introduzca un número",minValue:"El valor debe ser mayor o igual a ",maxValue:"El valor debe ser menor o igual a ",email:"no es una dirección de correo válida",integer:"Introduzca un valor entero",date:"Introduza una fecha correcta "}};a.jgrid.del={caption:"Eliminar",msg:"¿Desea eliminar los registros seleccionados?",bSubmit:"Eliminar",bCancel:"Cancelar",processData:"Procesando..."};a.jgrid.nav={edittext:" ",edittitle:"Modificar fila seleccionada",addtext:" ",addtitle:"Agregar nueva fila",deltext:" ",deltitle:"Eliminar fila seleccionada",searchtext:" ",searchtitle:"Buscar información",refreshtext:"",refreshtitle:"Recargar datos",alertcap:"Aviso",alerttext:"Seleccione una fila"};a.jgrid.col={caption:"Mostrar/ocultar columnas",bSubmit:"Enviar",bCancel:"Cancelar"};a.jgrid.errors={errcap:"Error",nourl:"No se ha especificado una URL",norecords:"No hay datos para procesar",model:"Las columnas de nombres son diferentes de las columnas de modelo"};a.jgrid.formatter={integer:{thousandsSeparator:".",defaulValue:0},number:{decimalSeparator:",",thousandsSeparator:".",decimalPlaces:2,defaulValue:0},currency:{decimalSeparator:",",thousandsSeparator:".",decimalPlaces:2,prefix:"",suffix:"",defaulValue:0},date:{dayNames:["Do","Lu","Ma","Mi","Ju","Vi","Sa","Domingo","Lunes","Martes","Miercoles","Jueves","Viernes","Sabado"],monthNames:["Ene","Feb","Mar","Abr","May","Jun","Jul","Ago","Sep","Oct","Nov","Dic","Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"],AmPm:["am","pm","AM","PM"],S:function(b){return b<11||b>13?["st","nd","rd","th"][Math.min((b-1)%10,3)]:"th"},srcformat:"Y-m-d",newformat:"d-m-Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"n/j/Y",LongDate:"l, F d, Y",FullDateTime:"l, F d, Y g:i:s A",MonthDay:"F d",ShortTime:"g:i A",LongTime:"g:i:s A",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F, Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"show"}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-tr-min.js b/site/vendors/js/jqGrid/js/min/grid.locale-tr-min.js new file mode 100644 index 0000000..1b32435 --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.locale-tr-min.js @@ -0,0 +1 @@ +(function(a){a.jgrid={};a.jgrid.defaults={recordtext:"Satır(lar)",loadtext:"Yükleniyor...",pgtext:"/"};a.jgrid.search={caption:"Arama...",Find:"Bul",Reset:"Temizle",odata:["eÅŸittir","eÅŸit deÄŸildir","küçük","küçük veya eÅŸit","büyük","büyük veya eÅŸit","ile baÅŸlayan","ile biten","içeren"]};a.jgrid.edit={addCaption:"Kayıt Ekle",editCaption:"Kayıt Düzenle",bSubmit:"Gönder",bCancel:"İptal",bClose:"Kapat",processData:"İşlem yapılıyor...",msg:{required:"Alan gerekli",number:"Lütfen bir numara giriniz",minValue:"girilen deÄŸer daha büyük ya da buna eÅŸit olmalıdır",maxValue:"girilen deÄŸer daha küçük ya da buna eÅŸit olmalıdır",email:"geçerli bir e-posta adresi deÄŸildir",integer:"Lütfen bir tamsayı giriniz",date:"Please, enter valid date value"}};a.jgrid.del={caption:"Sil",msg:"Seçilen kayıtlar silinsin mi?",bSubmit:"Sil",bCancel:"İptal",processData:"İşlem yapılıyor..."};a.jgrid.nav={edittext:" ",edittitle:"Seçili satırı düzenle",addtext:" ",addtitle:"Yeni satır ekle",deltext:" ",deltitle:"Seçili satırı sil",searchtext:" ",searchtitle:"Kayıtları bul",refreshtext:"",refreshtitle:"Tabloyu yenile",alertcap:"Uyarı",alerttext:"Lütfen bir satır seçiniz"};a.jgrid.col={caption:"Sütunları göster/gizle",bSubmit:"Gönder",bCancel:"İptal"};a.jgrid.errors={errcap:"Hata",nourl:"Bir url yapılandırılmamış",norecords:"İşlem yapılacak bir kayıt yok",model:"Length of colNames <> colModel!"};a.jgrid.formatter={integer:{thousandsSeparator:" ",defaulValue:0},number:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,defaulValue:0},currency:{decimalSeparator:".",thousandsSeparator:" ",decimalPlaces:2,prefix:"",suffix:"",defaulValue:0},date:{dayNames:["Sun","Mon","Tue","Wed","Thr","Fri","Sat","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],monthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","January","February","March","April","May","June","July","August","September","October","November","December"],AmPm:["am","pm","AM","PM"],S:function(b){return b<11||b>13?["st","nd","rd","th"][Math.min((b-1)%10,3)]:"th"},srcformat:"Y-m-d",newformat:"d/m/Y",masks:{ISO8601Long:"Y-m-d H:i:s",ISO8601Short:"Y-m-d",ShortDate:"n/j/Y",LongDate:"l, F d, Y",FullDateTime:"l, F d, Y g:i:s A",MonthDay:"F d",ShortTime:"g:i A",LongTime:"g:i:s A",SortableDateTime:"Y-m-d\\TH:i:s",UniversalSortableDateTime:"Y-m-d H:i:sO",YearMonth:"F, Y"},reformatAfterEdit:false},baseLinkUrl:"",showAction:"show"}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.postext-min.js b/site/vendors/js/jqGrid/js/min/grid.postext-min.js new file mode 100644 index 0000000..540eb9d --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.postext-min.js @@ -0,0 +1 @@ +(function(a){a.fn.extend({getPostData:function(){var b=this[0];if(!b.grid){return}return b.p.postData},setPostData:function(b){var c=this[0];if(!c.grid){return}if(typeof(b)==="object"){c.p.postData=b}else{alert("Error: cannot add a non-object postData value. postData unchanged.")}},appendPostData:function(b){var c=this[0];if(!c.grid){return}if(typeof(b)==="object"){a.extend(c.p.postData,b)}else{alert("Error: cannot append a non-object postData value. postData unchanged.")}},setPostDataItem:function(b,c){var d=this[0];if(!d.grid){return}d.p.postData[b]=c},getPostDataItem:function(b){var c=this[0];if(!c.grid){return}return c.p.postData[b]},removePostDataItem:function(b){var c=this[0];if(!c.grid){return}delete c.p.postData[b]},getUserData:function(){var b=this[0];if(!b.grid){return}return b.p.userData},getUserDataItem:function(b){var c=this[0];if(!c.grid){return}return c.p.userData[b]}})})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/grid.setcolumns-min.js b/site/vendors/js/jqGrid/js/min/grid.setcolumns-min.js new file mode 100644 index 0000000..0377af6 --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/grid.setcolumns-min.js @@ -0,0 +1 @@ +(function(a){a.fn.extend({setColumns:function(b){b=a.extend({top:0,left:0,width:200,height:195,modal:false,drag:true,closeicon:"ico-close.gif",beforeShowForm:null,afterShowForm:null,afterSubmitForm:null},a.jgrid.col,b||{});return this.each(function(){var j=this;if(!j.grid){return}var l=typeof b.beforeShowForm==="function"?true:false;var d=typeof b.afterShowForm==="function"?true:false;var e=typeof b.afterSubmitForm==="function"?true:false;if(!b.imgpath){b.imgpath=j.p.imgpath}var c=a("table:first",j.grid.bDiv).attr("id");var f={themodal:"colmod"+c,modalhead:"colhd"+c,modalcontent:"colcnt"+c};var h="ColTbl_"+c;if(a("#"+f.themodal).html()!=null){if(l){b.beforeShowForm(a("#"+h))}viewModal("#"+f.themodal,{modal:b.modal});if(d){b.afterShowForm(a("#"+h))}}else{var k=a("
    ");for(i=0;i")}}var g="";var m="";a(k).append(""+g+" "+m+"");createModal(f,k,b,j.grid.hDiv,j.grid.hDiv);if(b.drag){DnRModal("#"+f.themodal,"#"+f.modalhead+" td.modaltext")}a("#dData","#"+h).click(function(n){for(i=0;i").addClass("sgcollapsed").click(function(e){if($(this).hasClass("sgcollapsed")){pID=$("table:first",ts.grid.bDiv).attr("id");res=$(this).parent();var atd=pos==1?"":"";_id=$(res).attr("id");bfsc=true;if($.isFunction(ts.p.subGridBeforeExpand)){bfsc=ts.p.subGridBeforeExpand(pID+"_"+_id,_id)}if(bfsc===false){return false}nhc=0;$.each(ts.p.colModel,function(i,v){if(this.hidden===true){nhc++}});var subdata=""+atd+"
    ";$(this).parent().after(subdata+"
    ");$(".tablediv",ts).css("width",ts.grid.width-20+"px");if($.isFunction(ts.p.subGridRowExpanded)){ts.p.subGridRowExpanded(pID+"_"+_id,_id)}else{populatesubgrid(res)}$(this).html("").removeClass("sgcollapsed").addClass("sgexpanded")}else{if($(this).hasClass("sgexpanded")){bfsc=true;if($.isFunction(ts.p.subGridRowColapsed)){res=$(this).parent();_id=$(res).attr("id");bfsc=ts.p.subGridRowColapsed(pID+"_"+_id,_id)}if(bfsc===false){return false}$(this).parent().next().remove(".subgrid");$(this).html("").removeClass("sgexpanded").addClass("sgcollapsed")}}return false});row.appendChild(td);var populatesubgrid=function(rd){var res,sid,dp;sid=$(rd).attr("id");dp={id:sid,nd_:(new Date().getTime())};if(!ts.p.subGridModel[0]){return false}if(ts.p.subGridModel[0].params){for(var j=0;j"+sgmap.row,sjxml).each(function(){trdiv=document.createElement("div");trdiv.className="rowdiv";if(sgmap.repeatitems===true){$(sgmap.cell,this).each(function(i){subGridCell(trdiv,this.textContent||this.text||" ",i)})}else{var f=ts.p.subGridModel[0].mapping;if(f){for(i=0;i0;var f=!c&&g.length>0;var i=c||f;var h=o.attr("name")||g.attr("name");var k=[];var n=[];$("th",$(this)).each(function(){if(k.length==0&&i){k.push({name:"__selection__",index:"__selection__",width:0,hidden:true});n.push("__selection__")}else{k.push({name:$(this).html(),index:$(this).html(),width:$(this).width()||150});n.push($(this).html())}});var e=[];var d=[];var l=[];$("tbody > tr",$(this)).each(function(){var q={};var p=0;e.push(q);$("td",$(this)).each(function(){if(p==0&&i){var r=$("input",$(this));var s=r.attr("value");d.push(s||e.length);if(r.attr("checked")){l.push(s)}q[k[p].name]=r.attr("value")}else{q[k[p].name]=$(this).html()}p++})});$(this).empty();$(this).addClass("scroll");$(this).jqGrid({datatype:"local",width:m,colNames:n,colModel:k,multiselect:c});for(var j=0;j0){b=d[j];if(b&&b.replace){b=encodeURIComponent(b).replace(/[.\-%]/g,"_")}}if(b==null){b=j+1}$(this).addRowData(b,e[j])}for(var j=0;j"+e+"
    ").prepend(d);a(".treeclick",s).click(function(u){var t=u.target||u.srcElement;var i=a(t,k.rows).parents("tr:first")[0].rowIndex;if(!k.rows[i].isLeaf){if(k.rows[i].expanded){a(k).collapseRow(k.rows[i]);a(k).collapseNode(k.rows[i])}else{a(k).expandRow(k.rows[i]);a(k).expandNode(k.rows[i])}}return false});if(k.p.ExpandColClick===true){a("span",s).css("cursor","pointer").click(function(u){var t=u.target||u.srcElement;var i=a(t,k.rows).parents("tr:first")[0].rowIndex;if(!k.rows[i].isLeaf){if(k.rows[i].expanded){a(k).collapseRow(k.rows[i]);a(k).collapseNode(k.rows[i])}else{a(k).expandRow(k.rows[i]);a(k).expandNode(k.rows[i])}}a(k).setSelection(k.rows[i].id);return false})}})},setTreeGrid:function(){return this.each(function(){var b=this;if(!b.p.treeGrid){return}a.extend(b.p,{treedatatype:null});if(b.p.treeGridModel=="nested"){b.p.treeReader=a.extend({level_field:"level",left_field:"lft",right_field:"rgt",leaf_field:"isLeaf",expanded_field:"expanded"},b.p.treeReader)}else{if(b.p.treeGridModel=="adjacency"){b.p.treeReader=a.extend({level_field:"level",parent_id_field:"parent",leaf_field:"isLeaf",expanded_field:"expanded"},b.p.treeReader)}}})},expandRow:function(b){this.each(function(){var d=this;if(!d.grid||!d.p.treeGrid){return}var c=a(d).getNodeChildren(b);a(c).each(function(e){a(this).css("display","");if(this.expanded){a(d).expandRow(this)}})})},collapseRow:function(b){this.each(function(){var d=this;if(!d.grid||!d.p.treeGrid){return}var c=a(d).getNodeChildren(b);a(c).each(function(e){a(this).css("display","none");a(d).collapseRow(this)})})},getRootNodes:function(){var b=[];this.each(function(){var d=this;if(!d.grid||!d.p.treeGrid){return}switch(d.p.treeGridModel){case"nested":var c=d.p.treeReader.level_field;a(d.rows).each(function(e){if(parseInt(this[c],10)===parseInt(d.p.tree_root_level,10)){b.push(this)}});break;case"adjacency":a(d.rows).each(function(e){if(this.parent_id.toLowerCase()=="null"){b.push(this)}});break}});return b},getNodeDepth:function(c){var b=null;this.each(function(){var d=this;if(!this.grid||!this.p.treeGrid){return}switch(d.p.treeGridModel){case"nested":b=parseInt(c.level,10)-parseInt(this.p.tree_root_level,10);break;case"adjacency":b=a(d).getNodeAncestors(c).length;break}});return b},getNodeParent:function(c){var b=null;this.each(function(){var g=this;if(!g.grid||!g.p.treeGrid){return}switch(g.p.treeGridModel){case"nested":var e=parseInt(c.lft,10),d=parseInt(c.rgt,10),f=parseInt(c.level,10);a(this.rows).each(function(){if(parseInt(this.level,10)===f-1&&parseInt(this.lft)d){b=this;return false}});break;case"adjacency":a(this.rows).each(function(){if(this.id===c.parent_id){b=this;return false}});break}});return b},getNodeChildren:function(c){var b=[];this.each(function(){var h=this;if(!h.grid||!h.p.treeGrid){return}switch(h.p.treeGridModel){case"nested":var f=parseInt(c.lft,10),e=parseInt(c.rgt,10),g=parseInt(c.level,10);var d=c.rowIndex;a(this.rows).slice(1).each(function(j){if(parseInt(this.level,10)===g+1&&parseInt(this.lft,10)>f&&parseInt(this.rgt,10)=g&&parseInt(this.lft,10)>=f&&parseInt(this.lft,10)<=e){b.push(this)}});break;case"adjacency":break}});return b},getNodeAncestors:function(c){var b=[];this.each(function(){if(!this.grid||!this.p.treeGrid){return}var d=a(this).getNodeParent(c);while(d){b.push(d);d=a(this).getNodeParent(d)}});return b},isVisibleNode:function(c){var b=true;this.each(function(){var e=this;if(!e.grid||!e.p.treeGrid){return}var d=a(e).getNodeAncestors(c);a(d).each(function(){b=b&&this.expanded;if(!b){return false}})});return b},isNodeLoaded:function(c){var b;this.each(function(){var d=this;if(!d.grid||!d.p.treeGrid){return}if(c.loaded!==undefined){b=c.loaded}else{if(c.isLeaf||a(d).getNodeChildren(c).length>0){b=true}else{b=false}}});return b},expandNode:function(b){return this.each(function(){if(!this.grid||!this.p.treeGrid){return}if(!b.expanded){if(a(this).isNodeLoaded(b)){b.expanded=true;a("div.treeclick",b).removeClass("tree-plus").addClass("tree-minus")}else{b.expanded=true;a("div.treeclick",b).removeClass("tree-plus").addClass("tree-minus");this.p.treeANode=b.rowIndex;this.p.datatype=this.p.treedatatype;if(this.p.treeGridModel=="nested"){a(this).setGridParam({postData:{nodeid:b.id,n_left:b.lft,n_right:b.rgt,n_level:b.level}})}else{a(this).setGridParam({postData:{nodeid:b.id,parentid:b.parent_id,n_level:b.level}})}a(this).trigger("reloadGrid");if(this.p.treeGridModel=="nested"){a(this).setGridParam({postData:{nodeid:"",n_left:"",n_right:"",n_level:""}})}else{a(this).setGridParam({postData:{nodeid:"",parentid:"",n_level:""}})}}}})},collapseNode:function(b){return this.each(function(){if(!this.grid||!this.p.treeGrid){return}if(b.expanded){b.expanded=false;a("div.treeclick",b).removeClass("tree-minus").addClass("tree-plus")}})},SortTree:function(b){return this.each(function(){if(!this.grid||!this.p.treeGrid){return}var f,c,g,e=[],d=a(this).getRootNodes();d.sort(function(j,i){if(j.sortKeyi.sortKey){return b}return 0});for(f=0,c=d.length;fi.sortKey){return c}return 0});for(g=0,e=f.length;g0){for(var c=0;c0)?v:3000,f=d("
    ").css({height:"100%",width:"100%",position:"fixed",left:0,top:0,"z-index":v-1,opacity:q.overlay/100});if(m.a){return o}m.t=A;m.a=true;m.w.css("z-index",v);if(q.modal){if(!a[0]){k("bind")}a.push(B)}else{if(q.overlay>0){m.w.jqmAddClose(f)}else{f=o}}m.o=(f)?f.addClass(q.overlayClass).prependTo("body"):o;if(c){d("html,body").css({height:"100%",width:"100%"});if(f){f=f.css({position:"absolute"})[0];for(var w in {Top:1,Left:1}){f.style.setExpression(w.toLowerCase(),"(_=(document.documentElement.scroll"+w+" || document.body.scroll"+w+"))+'px'")}}}if(q.ajax){var e=q.target||m.w,x=q.ajax,e=(typeof e=="string")?d(e,m.w):d(e),x=(x.substr(0,1)=="@")?d(A).attr(x.substring(1)):x;e.html(q.ajaxText).load(x,function(){if(q.onLoad){q.onLoad.call(this,m)}if(i){m.w.jqmAddClose(d(i,m.w))}j(m)})}else{if(i){m.w.jqmAddClose(d(i,m.w))}}if(q.toTop&&m.o){m.w.before('').insertAfter(m.o)}(q.onShow)?q.onShow(m):m.w.show();j(m);return o},close:function(f){var e=n[f];if(!e.a){return o}e.a=o;if(a[0]){a.pop();if(!a[0]){k("unbind")}}if(e.c.toTop&&e.o){d("#jqmP"+e.w[0]._jqm).after(e.w).remove()}if(e.c.onHide){e.c.onHide(e)}else{e.w.hide();if(e.o){e.o.remove()}}return o},params:{}};var p=0,n=d.jqm.hash,a=[],c=d.browser.msie&&(d.browser.version=="6.0"),o=false,g=d('').css({opacity:0}),j=function(e){if(c){if(e.o){e.o.html('

    ').prepend(g)}else{if(!d("iframe.jqm",e.w)[0]){e.w.prepend(g)}}}h(e)},h=function(f){try{d(":input:visible",f.w)[0].focus()}catch(e){}},k=function(e){d()[e]("keypress",b)[e]("keydown",b)[e]("mousedown",b)},b=function(m){var f=n[a[a.length-1]],i=(!d(m.target).parents(".jqmID"+f.s)[0]);if(i){h(f)}return !i},l=function(e,f,i){return e.each(function(){var m=this._jqm;d(f).each(function(){if(!this[i]){this[i]=[];d(this).click(function(){for(var q in {jqmShow:1,jqmHide:1}){for(var r in this[q]){if(n[this[q][r]]){n[this[q][r]].w[q](this)}}}return o})}this[i].push(m)})})}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/jquery.fmatter-min.js b/site/vendors/js/jqGrid/js/min/jquery.fmatter-min.js new file mode 100644 index 0000000..318e1e1 --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/jquery.fmatter-min.js @@ -0,0 +1 @@ +(function($){$.fmatter={};$.fn.fmatter=function(formatType,cellval,opts,act){opts=$.extend({},$.jgrid.formatter,opts);return this.each(function(){$this=$(this);var o=$.meta?$.extend({},opts,$this.data()):opts;fireFormatter($this,formatType,cellval,opts,act)})};$.fmatter.util={NumberFormat:function(nData,opts){if(!isNumber(nData)){nData*=1}if(isNumber(nData)){var bNegative=(nData<0);var sOutput=nData+"";var sDecimalSeparator=(opts.decimalSeparator)?opts.decimalSeparator:".";var nDotIndex;if(isNumber(opts.decimalPlaces)){var nDecimalPlaces=opts.decimalPlaces;var nDecimal=Math.pow(10,nDecimalPlaces);sOutput=Math.round(nData*nDecimal)/nDecimal+"";nDotIndex=sOutput.lastIndexOf(".");if(nDecimalPlaces>0){if(nDotIndex<0){sOutput+=sDecimalSeparator;nDotIndex=sOutput.length-1}else{if(sDecimalSeparator!=="."){sOutput=sOutput.replace(".",sDecimalSeparator)}}while((sOutput.length-1-nDotIndex)-1)?nDotIndex:sOutput.length;var sNewOutput=sOutput.substring(nDotIndex);var nCount=-1;for(var i=nDotIndex;i>0;i--){nCount++;if((nCount%3===0)&&(i!==nDotIndex)&&(!bNegative||(i>1))){sNewOutput=sThousandsSeparator+sNewOutput}sNewOutput=sOutput.charAt(i-1)+sNewOutput}sOutput=sNewOutput}sOutput=(opts.prefix)?opts.prefix+sOutput:sOutput;sOutput=(opts.suffix)?sOutput+opts.suffix:sOutput;return sOutput}else{return nData}},DateFormat:function(format,date,newformat,opts){var token=/\\.|[dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU]/g,timezone=/\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,timezoneClip=timezoneClip=/[^-+\dA-Z]/g,pad=function(value,length){value=String(value);length=parseInt(length)||2;while(value.length=70&&ty<=99){ts.y=1900+ts.y}else{if(ty>=0&&ty<=69){ts.y=2000+ts.y}}timestamp=new Date(ts.y,ts.m,ts.d,ts.h,ts.i,ts.s,0);if(opts.masks.newformat){newformat=opts.masks.newformat}else{if(!newformat){newformat="Y-m-d"}}var G=timestamp.getHours(),i=timestamp.getMinutes(),j=timestamp.getDate(),n=timestamp.getMonth()+1,o=timestamp.getTimezoneOffset(),s=timestamp.getSeconds(),u=timestamp.getMilliseconds(),w=timestamp.getDay(),Y=timestamp.getFullYear(),N=(w+6)%7+1,z=(new Date(Y,n-1,j)-new Date(Y,0,1))/86400000,flags={d:pad(j),D:dateFormat.i18n.dayNames[w],j:j,l:dateFormat.i18n.dayNames[w+7],N:N,S:opts.S(j),w:w,z:z,W:N<5?Math.floor((z+N-1)/7)+1:Math.floor((z+N-1)/7)||((new Date(Y-1,0,1).getDay()+6)%7<4?53:52),F:dateFormat.i18n.monthNames[n-1+12],m:pad(n),M:dateFormat.i18n.monthNames[n-1],n:n,t:"?",L:"?",o:"?",Y:Y,y:String(Y).substring(2),a:G<12?opts.AmPm[0]:opts.AmPm[1],A:G<12?opts.AmPm[2]:opts.AmPm[3],B:"?",g:G%12||12,G:G,h:pad(G%12||12),H:pad(G),i:pad(i),s:pad(s),u:u,e:"?",I:"?",O:(o>0?"-":"+")+pad(Math.floor(Math.abs(o)/60)*100+Math.abs(o)%60,4),P:"?",T:(String(timestamp).match(timezone)||[""]).pop().replace(timezoneClip,""),Z:"?",c:"?",r:"?",U:Math.floor(timestamp/1000)};return newformat.replace(token,function($0){return $0 in flags?flags[$0]:$0.substring(1)})}};$.fn.fmatter.defaultFormat=function(el,cellval,opts){$(el).html((isValue(cellval)&&cellval!=="")?cellval:" ")};$.fn.fmatter.email=function(el,cellval,opts){if(!isEmpty(cellval)){$(el).html(''+cellval+"")}else{$.fn.fmatter.defaultFormat(el,cellval)}};$.fn.fmatter.checkbox=function(el,cval,opts){var op=$.extend({},opts.checkbox),ds;if(!isUndefined(opts.colModel.formatoptions)){op=$.extend({},op,opts.colModel.formatoptions)}if(op.disabled===true){ds="disabled"}else{ds=""}cval=cval+"";cval=cval.toLowerCase();var bchk=cval.search(/(false|0|no|off)/i)<0?' checked="checked"':"";$(el).html("")},$.fn.fmatter.link=function(el,cellval,opts){if(!isEmpty(cellval)){$(el).html(''+cellval+"")}else{$(el).html(isValue(cellval)?cellval:"")}};$.fn.fmatter.showlink=function(el,cellval,opts){var op={baseLinkUrl:opts.baseLinkUrl,showAction:opts.showAction,addParam:opts.addParam};if(!isUndefined(opts.colModel.formatoptions)){op=$.extend({},op,opts.colModel.formatoptions)}idUrl=op.baseLinkUrl+op.showAction+"?id="+opts.rowId+op.addParam;if(isString(cellval)){$(el).html(''+cellval+"")}else{$.fn.fmatter.defaultFormat(el,cellval)}};$.fn.fmatter.integer=function(el,cellval,opts){var op=$.extend({},opts.integer);if(!isUndefined(opts.colModel.formatoptions)){op=$.extend({},op,opts.colModel.formatoptions)}if(isEmpty(cellval)){cellval=op.defaultValue||0}$(el).html($.fmatter.util.NumberFormat(cellval,op))};$.fn.fmatter.number=function(el,cellval,opts){var op=$.extend({},opts.number);if(!isUndefined(opts.colModel.formatoptions)){op=$.extend({},op,opts.colModel.formatoptions)}if(isEmpty(cellval)){cellval=op.defaultValue||0}$(el).html($.fmatter.util.NumberFormat(cellval,op))};$.fn.fmatter.currency=function(el,cellval,opts){var op=$.extend({},opts.currency);if(!isUndefined(opts.colModel.formatoptions)){op=$.extend({},op,opts.colModel.formatoptions)}if(isEmpty(cellval)){cellval=op.defaultValue||0}$(el).html($.fmatter.util.NumberFormat(cellval,op))};$.fn.fmatter.date=function(el,cellval,opts,act){var op=$.extend({},opts.date);if(!isUndefined(opts.colModel.formatoptions)){op=$.extend({},op,opts.colModel.formatoptions)}if(!op.reformatAfterEdit&&act=="edit"){$.fn.fmatter.defaultFormat(el,cellval)}else{if(!isEmpty(cellval)){var ndf=$.fmatter.util.DateFormat(op.srcformat,cellval,op.newformat,op);$(el).html(ndf)}else{$.fn.fmatter.defaultFormat(el,cellval)}}};$.fn.fmatter.select=function(el,cellval,opts,act){if(act=="edit"){$.fn.fmatter.defaultFormat(el,cellval)}else{if(!isEmpty(cellval)){var oSelect=false;if(!isUndefined(opts.colModel.editoptions)){oSelect=opts.colModel.editoptions.value}if(oSelect){var ret=[];var msl=opts.colModel.editoptions.multiple===true?true:false;var scell=[];if(msl){scell=cellval.split(",");scell=$.map(scell,function(n){return $.trim(n)})}if(isString(oSelect)){var so=oSelect.split(";"),j=0;for(var i=0;i-1){ret[j]=sv[1];j++}}else{if($.trim(sv[0])==$.trim(cellval)){ret[0]=sv[1];break}}}}else{if(isObject(oSelect)){if(msl){ret=jQuery.map(scel,function(n,i){return oSelect[n]})}ret[0]=oSelect[cellval]||""}}$(el).html(ret.join(", "))}else{$.fn.fmatter.defaultFormat(el,cellval)}}}};$.unformat=function(cellval,options,pos,cnt){var ret,formatType=options.colModel.formatter,op=options.colModel.formatoptions||{};if(formatType!=="undefined"&&isString(formatType)){var opts=$.jgrid.formatter||{},stripTag;switch(formatType){case"link":case"showlink":case"email":ret=$(cellval).text();break;case"integer":op=$.extend({},opts.integer,op);stripTag=eval("/"+op.thousandsSeparator+"/g");ret=$(cellval).text().replace(stripTag,"");break;case"number":op=$.extend({},opts.number,op);stripTag=eval("/"+op.thousandsSeparator+"/g");ret=$(cellval).text().replace(op.decimalSeparator,".").replace(stripTag,"");break;case"currency":op=$.extend({},opts.currency,op);stripTag=eval("/"+op.thousandsSeparator+"/g");ret=$(cellval).text().replace(op.decimalSeparator,".").replace(op.prefix,"").replace(op.suffix,"").replace(stripTag,"");break;case"checkbox":var cbv=(options.colModel.editoptions)?options.colModel.editoptions.value.split(":"):["Yes","No"];ret=$("input",cellval).attr("checked")?cbv[0]:cbv[1];break}}return ret?ret:cnt===true?$(cellval).text():$.htmlDecode($(cellval).html())};function fireFormatter(el,formatType,cellval,opts,act){formatType=formatType.toLowerCase();switch(formatType){case"link":$.fn.fmatter.link(el,cellval,opts);break;case"showlink":$.fn.fmatter.showlink(el,cellval,opts);break;case"email":$.fn.fmatter.email(el,cellval,opts);break;case"currency":$.fn.fmatter.currency(el,cellval,opts);break;case"date":$.fn.fmatter.date(el,cellval,opts,act);break;case"number":$.fn.fmatter.number(el,cellval,opts);break;case"integer":$.fn.fmatter.integer(el,cellval,opts);break;case"checkbox":$.fn.fmatter.checkbox(el,cellval,opts);break;case"select":$.fn.fmatter.select(el,cellval,opts,act);break}}function debug($obj){if(window.console&&window.console.log){window.console.log($obj)}}isValue=function(o){return(isObject(o)||isString(o)||isNumber(o)||isBoolean(o))};isBoolean=function(o){return typeof o==="boolean"};isNull=function(o){return o===null};isNumber=function(o){return typeof o==="number"&&isFinite(o)};isString=function(o){return typeof o==="string"};isEmpty=function(o){if(!isString(o)&&isValue(o)){return false}else{if(!isValue(o)){return true}}o=$.trim(o).replace(/\ \;/ig,"").replace(/\ \;/ig,"");return o===""};isUndefined=function(o){return typeof o==="undefined"};isObject=function(o){return(o&&(typeof o==="object"||isFunction(o)))||false};isFunction=function(o){return typeof o==="function"}})(jQuery); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/jquery.tablednd-min.js b/site/vendors/js/jqGrid/js/min/jquery.tablednd-min.js new file mode 100644 index 0000000..355b9e8 --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/jquery.tablednd-min.js @@ -0,0 +1 @@ +jQuery.tableDnD={currentTable:null,dragObject:null,mouseOffset:null,oldY:0,build:function(a){this.each(function(){this.tableDnDConfig=jQuery.extend({onDragStyle:null,onDropStyle:null,onDragClass:"tDnD_whileDrag",onDrop:null,onDragStart:null,scrollAmount:5,serializeRegexp:/[^\-]*$/,serializeParamName:null,dragHandle:null},a||{});jQuery.tableDnD.makeDraggable(this)});jQuery(document).bind("mousemove",jQuery.tableDnD.mousemove).bind("mouseup",jQuery.tableDnD.mouseup);return this},makeDraggable:function(c){var b=c.tableDnDConfig;if(c.tableDnDConfig.dragHandle){var a=jQuery("td."+c.tableDnDConfig.dragHandle,c);a.each(function(){jQuery(this).mousedown(function(e){jQuery.tableDnD.dragObject=this.parentNode;jQuery.tableDnD.currentTable=c;jQuery.tableDnD.mouseOffset=jQuery.tableDnD.getMouseOffset(this,e);if(b.onDragStart){b.onDragStart(c,this)}return false})})}else{var d=jQuery("tr",c);d.each(function(){var e=jQuery(this);if(!e.hasClass("nodrag")){e.mousedown(function(f){if(f.target.tagName=="TD"){jQuery.tableDnD.dragObject=this;jQuery.tableDnD.currentTable=c;jQuery.tableDnD.mouseOffset=jQuery.tableDnD.getMouseOffset(this,f);if(b.onDragStart){b.onDragStart(c,this)}return false}}).css("cursor","move")}})}},updateTables:function(){this.each(function(){if(this.tableDnDConfig){jQuery.tableDnD.makeDraggable(this)}})},mouseCoords:function(a){if(a.pageX||a.pageY){return{x:a.pageX,y:a.pageY}}return{x:a.clientX+document.body.scrollLeft-document.body.clientLeft,y:a.clientY+document.body.scrollTop-document.body.clientTop}},getMouseOffset:function(d,c){c=c||window.event;var b=this.getPosition(d);var a=this.mouseCoords(c);return{x:a.x-b.x,y:a.y-b.y}},getPosition:function(c){var b=0;var a=0;if(c.offsetHeight==0){c=c.firstChild}if(c&&c.offsetParent){while(c.offsetParent){b+=c.offsetLeft;a+=c.offsetTop;c=c.offsetParent}b+=c.offsetLeft;a+=c.offsetTop}return{x:b,y:a}},mousemove:function(g){if(jQuery.tableDnD.dragObject==null){return}var d=jQuery(jQuery.tableDnD.dragObject);var b=jQuery.tableDnD.currentTable.tableDnDConfig;var i=jQuery.tableDnD.mouseCoords(g);var f=i.y-jQuery.tableDnD.mouseOffset.y;var c=window.pageYOffset;if(document.all){if(typeof document.compatMode!="undefined"&&document.compatMode!="BackCompat"){c=document.documentElement.scrollTop}else{if(typeof document.body!="undefined"){c=document.body.scrollTop}}}if(i.y-cjQuery.tableDnD.oldY;jQuery.tableDnD.oldY=f;if(b.onDragClass){d.addClass(b.onDragClass)}else{d.css(b.onDragStyle)}var h=jQuery.tableDnD.findDropTargetRow(d,f);if(h){if(e&&jQuery.tableDnD.dragObject!=h){jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject,h.nextSibling)}else{if(!e&&jQuery.tableDnD.dragObject!=h){jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject,h)}}}}return false},findDropTargetRow:function(f,g){var j=jQuery.tableDnD.currentTable.rows;for(var e=0;eb-a)&&(g<(b+a))){if(h==f){return null}var c=jQuery.tableDnD.currentTable.tableDnDConfig;if(c.onAllowDrop){if(c.onAllowDrop(f,h)){return h}else{return null}}else{var d=jQuery(h).hasClass("nodrop");if(!d){return h}else{return null}}return h}}return null},mouseup:function(c){if(jQuery.tableDnD.currentTable&&jQuery.tableDnD.dragObject){var b=jQuery.tableDnD.dragObject;var a=jQuery.tableDnD.currentTable.tableDnDConfig;if(a.onDragClass){jQuery(b).removeClass(a.onDragClass)}else{jQuery(b).css(a.onDropStyle)}jQuery.tableDnD.dragObject=null;if(a.onDrop){a.onDrop(jQuery.tableDnD.currentTable,b)}jQuery.tableDnD.currentTable=null}},serialize:function(){if(jQuery.tableDnD.currentTable){return jQuery.tableDnD.serializeTable(jQuery.tableDnD.currentTable)}else{return"Error: No Table id set, you need to set an id on your table and every row"}},serializeTable:function(d){var a="";var c=d.id;var e=d.rows;for(var b=0;b0){a+="&"}var f=e[b].id;if(f&&f&&d.tableDnDConfig&&d.tableDnDConfig.serializeRegexp){f=f.match(d.tableDnDConfig.serializeRegexp)[0]}a+=c+"[]="+f}return a},serializeTables:function(){var a="";this.each(function(){a+=jQuery.tableDnD.serializeTable(this)});return a}};jQuery.fn.extend({tableDnD:jQuery.tableDnD.build,tableDnDUpdate:jQuery.tableDnD.updateTables,tableDnDSerialize:jQuery.tableDnD.serializeTables}); \ No newline at end of file diff --git a/site/vendors/js/jqGrid/js/min/json2-min.js b/site/vendors/js/jqGrid/js/min/json2-min.js new file mode 100644 index 0000000..5514bd7 --- /dev/null +++ b/site/vendors/js/jqGrid/js/min/json2-min.js @@ -0,0 +1 @@ +var JSON={stringify:function stringify(a){var g,e,b,f="",d;switch(typeof a){case"object":if(a){if(a.constructor==Array){for(e=0;e=" "){if(g=="\\"||g=='"'){f+="\\"}f+=g}else{switch(g){case"\b":f+="\\b";break;case"\f":f+="\\f";break;case"\n":f+="\\n";break;case"\r":f+="\\r";break;case"\t":f+="\\t";break;default:g=g.charCodeAt();f+="\\u00"+Math.floor(g/16).toString(16)+(g%16).toString(16)}}}return f+'"';case"boolean":return String(a);case"function":return a.toString();default:return"null"}},parse:function(jsonString){var js=jsonString;if(js.substr(0,9)=="while(1);"){js=js.substr(9)}if(js.substr(0,2)=="/*"){js=js.substr(2,js.length-4)}return eval("("+js+")")}}; \ No newline at end of file diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index 74d0fbb..844f5e4 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -1,63 +1,175 @@ '.__('Customers',true).''; +//$imgpath = 'jqGrid/basic/images'; +$imgpath = '/pmgr/site/css/jqGrid/basic/images'; +$html->css('jqGrid/basic/grid', null, null, false); +$html->css('jqGrid/jqModal', null, null, false); +$javascript->link('jqGrid/jquery.jqGrid.js', false); +$javascript->link('jqGrid/js/jqModal', false); +$javascript->link('jqGrid/js/jqDnR', false); -$headers = array_merge(array('Name'), - isset($customers[0]['ContactsCustomer']) - ? array('Relationship') - : array(), - array('Comment')); -$column_class = array(); -foreach (array_intersect($headers, array('Comment')) AS $k => $v) { - $column_class[$k] = 'comment'; +/* //echo $html->css('jquery/start/ui.all') . "\n"; */ +/* echo $javascript->link('jquery/jquery') . "\n"; */ +/* //echo $javascript->link('jquery/jquery-ui') . "\n"; */ +/* //echo $javascript->link('jquery.form') . "\n"; */ +/* echo $javascript->link('pmgr') . "\n"; */ +/* echo $html->css('jqGrid/basic/grid') . "\n"; */ +/* //echo $html->css('jqGrid/jqModal') . "\n"; */ +/* echo $javascript->link('jqGrid/jquery.jqGrid.js') . "\n"; */ +/* //echo $javascript->link('jqGrid/js/jqModal') . "\n"; */ +/* //echo $javascript->link('jqGrid/js/jqDnR') . "\n"; */ + + +$cols = array(); +$cols['ID'] = array('index' => 'Customer.id', 'width' => '50', 'align' => 'center'); +/* $cols['Last Name'] = array('index' => 'Customer.last_name', 'width' => '200', 'align' => 'left'); */ +/* $cols['First Name'] = array('index' => 'Customer.first_name', 'width' => '200', 'align' => 'left'); */ +$cols['Name'] = array('index' => 'Customer.name', 'width' => '200', 'align' => 'left'); +$cols['Unit'] = array('index' => 'Customer.units', 'width' => '200', 'align' => 'left', 'sortable' => false); + +$colModels = array(); +foreach ($cols AS $col) { + $col['name'] = $col['index']; + $colModels[] = + '{ ' . implode(", ", + array_map(create_function + ('$k, $v', + 'return "$k:".($v===false?"false":"\'$v\'");'), + array_keys($col), + array_values($col))) . + '}'; } -if (isset($paginator)) { - echo $paginator->counter(array( - 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); +// URL to fetch data from. +// To prevent having to keep the controller and the view +// in sync on which fields need to be queried by the +// controller in order to be accessible to the view, +// we'll just pass the desired fields to the controller +// as part of the data fetch. +$url = $html->url(array('controller' => 'customers', + 'action' => 'data', + 'debug' => 0, + implode(";", + array_map(create_function + ('$col', + 'return $col["index"];'), + $cols)), + )); - $headers = array_merge(array($paginator->sort('name')), - isset($customers[0]['ContactsCustomer']) - ? array($paginator->sort('Relationship', 'type')) - : array(), - array($paginator->sort('comment'))); + +/* array_merge(array('Name'), */ +/* isset($customers[0]['ContactsCustomer']) */ +/* ? array('Relationship') */ +/* : array(), */ +/* array('Comment')); */ + +/* $rows[] = array_merge(array($html->link($customer['name'], */ +/* array('controller' => 'customers', */ +/* 'action' => 'view', */ +/* $customer['id']))), */ +/* isset($contacts_customer) */ +/* ? array($contacts_customer['type']) */ +/* : array(), */ +/* array($customer['comment'])); */ + +?> + + - if (isset($customer['Customer'])) - $customer = $customer['Customer']; +
    +

    + +
    - $rows[] = array_merge(array($html->link($customer['name'], - array('controller' => 'customers', - 'action' => 'view', - $customer['id']))), - isset($contacts_customer) - ? array($contacts_customer['type']) - : array(), - array($customer['comment'])); -} +element('table', - array('class' => 'item customer list', - 'caption' => isset($caption) ? $caption : null, - 'headers' => $headers, - 'rows' => $rows, - 'column_class' => $column_class)); +/* if (isset($heading)) */ +/* echo $heading; */ +/* elseif (!isset($caption)) */ +/* echo '

    '.__('Customers',true).'

    '; */ -if (isset($paginator)) { - echo('
    ' . "\n"); - echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); - echo(' | '); - echo $paginator->numbers(); - echo(' | '); - echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); - echo('
    ' . "\n"); -} +/* $headers = array_merge(array('Name'), */ +/* isset($customers[0]['ContactsCustomer']) */ +/* ? array('Relationship') */ +/* : array(), */ +/* array('Comment')); */ +/* $column_class = array(); */ +/* foreach (array_intersect($headers, array('Comment')) AS $k => $v) { */ +/* $column_class[$k] = 'comment'; */ +/* } */ + + +/* if (isset($paginator)) { */ +/* echo $paginator->counter(array( */ +/* 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); */ + +/* $headers = array_merge(array($paginator->sort('name')), */ +/* isset($customers[0]['ContactsCustomer']) */ +/* ? array($paginator->sort('Relationship', 'type')) */ +/* : array(), */ +/* array($paginator->sort('comment'))); */ +/* } */ + + + + +/* $rows = array(); */ +/* foreach ($customers as $customer) { */ +/* $contacts_customer = null; */ +/* if (isset($customer['ContactsCustomer'])) */ +/* $contacts_customer = $customer['ContactsCustomer']; */ + +/* if (isset($customer['Customer'])) */ +/* $customer = $customer['Customer']; */ + +/* $rows[] = array_merge(array($html->link($customer['name'], */ +/* array('controller' => 'customers', */ +/* 'action' => 'view', */ +/* $customer['id']))), */ +/* isset($contacts_customer) */ +/* ? array($contacts_customer['type']) */ +/* : array(), */ +/* array($customer['comment'])); */ +/* } */ + +/* echo $this->element('table', */ +/* array('class' => 'item customer list', */ +/* 'caption' => isset($caption) ? $caption : null, */ +/* 'headers' => $headers, */ +/* 'rows' => $rows, */ +/* 'column_class' => $column_class)); */ + +/* if (isset($paginator)) { */ +/* echo('
    ' . "\n"); */ +/* echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); */ +/* echo(' | '); */ +/* echo $paginator->numbers(); */ +/* echo(' | '); */ +/* echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); */ +/* echo('
    ' . "\n"); */ +/* } */ From 55dd94681a5da9f002a3ba8839d660c19569ce8c Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 13 Jun 2009 04:19:19 +0000 Subject: [PATCH 103/717] Added a primary contact for each customer, as there must be someone (or some entity) to contact for every customer. This simply makes it explicit, and has the added benefit of being easier to work with when querying. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@104 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 21 +++++++++++++++++++-- scripts/sitelink2pmgr.pl | 1 + site/models/customer.php | 3 +++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index e2b826b..b8b56bd 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -629,11 +629,28 @@ CREATE TABLE `pmgr_actions_late_schedules` ( DROP TABLE IF EXISTS `pmgr_customers`; CREATE TABLE `pmgr_customers` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `name` VARCHAR(80) NOT NULL, - `comment` VARCHAR(255) DEFAULT NULL, + -- If NULL, rely on the contact info exclusively + `name` VARCHAR(80) DEFAULT NULL, + + -- A customer gets their own account, although any + -- lease specific charge (rent, late fees, etc) will + -- be debited against the lease account. This one + -- will be used for non-lease related charges, as + -- well as charges that intentionally span more than + -- one lease (such as one security deposit to cover + -- two or more units). `account_id` INT(10) UNSIGNED NOT NULL, + -- Primary Contact... every customer must have one + -- (and presumably, most customers will _be_ one). + -- REVISIT 20090612: + -- Does this contact also get added to the + -- contacts_customers table? + `primary_contact_id` INT(10) UNSIGNED NOT NULL, + + `comment` VARCHAR(255) DEFAULT NULL, + PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 975c15e..c2309d8 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -678,6 +678,7 @@ foreach $row (@{query($sdbh, $query)}) { addRow('customers', { 'name' => "$row->{'LastName'}, $row->{'FirstName'}", + 'primary_contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'}, 'account_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account'} }); $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'} = diff --git a/site/models/customer.php b/site/models/customer.php index 452ebaf..827026d 100644 --- a/site/models/customer.php +++ b/site/models/customer.php @@ -9,6 +9,9 @@ class Customer extends AppModel { var $belongsTo = array( 'Account', + 'PrimaryContact' => array( + 'className' => 'Contact', + ), ); var $hasMany = array( From a49b86898ef8df655d37f2c7f8f5b05b28e6eaf4 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 13 Jun 2009 07:22:38 +0000 Subject: [PATCH 104/717] Check in aother snapshot, since I can now pass complex structures from the view back to the jqGrid data provider git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@105 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/customers_controller.php | 47 +++++-- site/views/elements/customers.ctp | 163 ++++++---------------- 2 files changed, 82 insertions(+), 128 deletions(-) diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 8c713b9..4c50e31 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -1,10 +1,6 @@ 100, - 'group' => 'Customer.id', - 'order' => array('Customer.name' => 'ASC')); - var $sidemenu_links = array(array('name' => 'Tenants', 'header' => true), array('name' => 'Current', 'url' => array('controller' => 'customers', 'action' => 'current')), @@ -12,7 +8,7 @@ class CustomersController extends AppController { array('name' => 'All', 'url' => array('controller' => 'customers', 'action' => 'all')), ); - var $components = array('RequestHandler'); + //var $components = array('RequestHandler'); /************************************************************************** @@ -102,6 +98,7 @@ class CustomersController extends AppController { function all() { $title = 'All Customers'; $this->set('title', $title); $this->set('heading', $title); + $this->set('params', $this->params); $this->render('index'); } @@ -113,11 +110,19 @@ class CustomersController extends AppController { * - */ - function data($fields_str) { + function jqGridData($debug = true) { /* pr(array('fields' => $fields, */ /* 'explode' => explode(";", $fields_str))); */ - $fields = explode(";", $fields_str); +/* $debug=true; */ + +/* $tf = unserialize($fields); */ +/* $tp = unserialize($params); */ + +/* $fields = array('Customer.id'); */ + + //$action_params = unserialize($action_params); + //$fields = explode(";", $fields_str); //$fields=array(); /* foreach (explode(";", $fields_str) AS $i => $field) { */ @@ -130,6 +135,7 @@ class CustomersController extends AppController { //pr(array('fields' => $fields)); + $debug = true; if (isset($this->passedArgs['debug'])) $debug = $this->passedArgs['debug']; @@ -146,9 +152,21 @@ class CustomersController extends AppController { $rows = 20; // rows in the grid - rowNum parameter $sidx = 'Customer.id'; // sort column - index from colModel $sord = 'ASC'; // sort order + + $fields = array('Customer.id'); if (isset($this->params['url']) && is_array($this->params['url'])) extract($this->params['url']); + + if (isset($fields)) + $fields = unserialize($fields); + else + $fields = array('Customer.id'); + + if (isset($params)) + $params = unserialize($params); + else + $params = array('action' => 'all'); // calculate the number of rows for the query. We need this for paging the result $row = $this->Customer->findCount(); @@ -172,12 +190,22 @@ class CustomersController extends AppController { // typical case is that the user type 0 for the requested page if($start <0) $start = 0; + $cond = array(); + if ($params['action'] == 'current') { + + } elseif ($params['action'] == 'past') { + + } else { + + } + + // the actual query for the grid data $customers = $this->Customer->find ('all', array('contain' => array (// Models -/* 'Contact' => */ + 'PrimaryContact', /* array(// Models */ /* 'ContactPhone', */ /* 'ContactEmail', */ @@ -221,6 +249,8 @@ class CustomersController extends AppController { /* echo " \n"; */ /* echo " params, true) . "]]>\n"; */ /* echo " passedArgs, true) . "]]>\n"; */ +/* echo " \n"; */ +/* echo " \n"; */ /* echo " \n"; */ echo " ".$page."\n"; echo " ".$total_pages."\n"; @@ -234,6 +264,7 @@ class CustomersController extends AppController { ('$lease', 'return $lease["Unit"]["name"];'), $customer['CurrentLease'])); + echo " \n"; foreach ($fields AS $field) { list($tbl, $col) = explode(".", $field); diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index 844f5e4..c526ef0 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -1,6 +1,16 @@ css('jqGrid/basic/grid', null, null, false); $html->css('jqGrid/jqModal', null, null, false); @@ -8,25 +18,22 @@ $javascript->link('jqGrid/jquery.jqGrid.js', false); $javascript->link('jqGrid/js/jqModal', false); $javascript->link('jqGrid/js/jqDnR', false); -/* //echo $html->css('jquery/start/ui.all') . "\n"; */ -/* echo $javascript->link('jquery/jquery') . "\n"; */ -/* //echo $javascript->link('jquery/jquery-ui') . "\n"; */ -/* //echo $javascript->link('jquery.form') . "\n"; */ -/* echo $javascript->link('pmgr') . "\n"; */ -/* echo $html->css('jqGrid/basic/grid') . "\n"; */ -/* //echo $html->css('jqGrid/jqModal') . "\n"; */ -/* echo $javascript->link('jqGrid/jquery.jqGrid.js') . "\n"; */ -/* //echo $javascript->link('jqGrid/js/jqModal') . "\n"; */ -/* //echo $javascript->link('jqGrid/js/jqDnR') . "\n"; */ - - +// Define the table columns $cols = array(); -$cols['ID'] = array('index' => 'Customer.id', 'width' => '50', 'align' => 'center'); -/* $cols['Last Name'] = array('index' => 'Customer.last_name', 'width' => '200', 'align' => 'left'); */ -/* $cols['First Name'] = array('index' => 'Customer.first_name', 'width' => '200', 'align' => 'left'); */ -$cols['Name'] = array('index' => 'Customer.name', 'width' => '200', 'align' => 'left'); -$cols['Unit'] = array('index' => 'Customer.units', 'width' => '200', 'align' => 'left', 'sortable' => false); +$cols['ID'] = array('index' => 'Customer.id', 'width' => '30', 'align' => 'center'); +if (isset($customers[0]['ContactsCustomer'])) + $cols['Relationship'] = array('index' => 'ContactsCustomer.type', 'width' => '75', 'align' => 'left'); +$cols['Name'] = array('index' => 'Customer.name', 'width' => '150', 'align' => 'left'); +$cols['Last Name'] = array('index' => 'PrimaryContact.last_name', 'width' => '100', 'align' => 'left'); +$cols['First Name'] = array('index' => 'PrimaryContact.first_name', 'width' => '100', 'align' => 'left'); +$cols['Unit(s)'] = array('index' => 'Customer.units', 'width' => '80', 'align' => 'center'); +$cols['Comment'] = array('index' => 'Customer.comment', 'width' => '300', 'align' => 'center'); +// Some of the columns should not be sortable +foreach (array('Unit(s)') AS $field) + $cols[$field]['sortable'] = false; + +// Create the javascript code for jqGrid to create each table column $colModels = array(); foreach ($cols AS $col) { $col['name'] = $col['index']; @@ -40,38 +47,24 @@ foreach ($cols AS $col) { '}'; } -// URL to fetch data from. +// Save just the column indices (fields) +$colFields= array_map(create_function('$col', 'return $col["index"];'), $cols); + +// Define the URL to fetch data from. // To prevent having to keep the controller and the view // in sync on which fields need to be queried by the // controller in order to be accessible to the view, // we'll just pass the desired fields to the controller // as part of the data fetch. + $url = $html->url(array('controller' => 'customers', - 'action' => 'data', + 'action' => 'jqGridData', 'debug' => 0, - implode(";", - array_map(create_function - ('$col', - 'return $col["index"];'), - $cols)), )); - -/* array_merge(array('Name'), */ -/* isset($customers[0]['ContactsCustomer']) */ -/* ? array('Relationship') */ -/* : array(), */ -/* array('Comment')); */ - -/* $rows[] = array_merge(array($html->link($customer['name'], */ -/* array('controller' => 'customers', */ -/* 'action' => 'view', */ -/* $customer['id']))), */ -/* isset($contacts_customer) */ -/* ? array($contacts_customer['type']) */ -/* : array(), */ -/* array($customer['comment'])); */ - +// OK, now that everything is in place, get out of PHP mode, +// and add the javascript code (along with a touch of HTML) +// to kick this thing off. ?>
    - -
    -'.__('Customers',true).''; */ - -/* $headers = array_merge(array('Name'), */ -/* isset($customers[0]['ContactsCustomer']) */ -/* ? array('Relationship') */ -/* : array(), */ -/* array('Comment')); */ -/* $column_class = array(); */ -/* foreach (array_intersect($headers, array('Comment')) AS $k => $v) { */ -/* $column_class[$k] = 'comment'; */ -/* } */ - - -/* if (isset($paginator)) { */ -/* echo $paginator->counter(array( */ -/* 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); */ - -/* $headers = array_merge(array($paginator->sort('name')), */ -/* isset($customers[0]['ContactsCustomer']) */ -/* ? array($paginator->sort('Relationship', 'type')) */ -/* : array(), */ -/* array($paginator->sort('comment'))); */ -/* } */ - - - - -/* $rows = array(); */ -/* foreach ($customers as $customer) { */ -/* $contacts_customer = null; */ -/* if (isset($customer['ContactsCustomer'])) */ -/* $contacts_customer = $customer['ContactsCustomer']; */ - -/* if (isset($customer['Customer'])) */ -/* $customer = $customer['Customer']; */ - -/* $rows[] = array_merge(array($html->link($customer['name'], */ -/* array('controller' => 'customers', */ -/* 'action' => 'view', */ -/* $customer['id']))), */ -/* isset($contacts_customer) */ -/* ? array($contacts_customer['type']) */ -/* : array(), */ -/* array($customer['comment'])); */ -/* } */ - -/* echo $this->element('table', */ -/* array('class' => 'item customer list', */ -/* 'caption' => isset($caption) ? $caption : null, */ -/* 'headers' => $headers, */ -/* 'rows' => $rows, */ -/* 'column_class' => $column_class)); */ - -/* if (isset($paginator)) { */ -/* echo('
    ' . "\n"); */ -/* echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); */ -/* echo(' | '); */ -/* echo $paginator->numbers(); */ -/* echo(' | '); */ -/* echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); */ -/* echo('
    ' . "\n"); */ -/* } */ From c5bd8b4b1601ab7cd5a9dc75f87f1abe62333655 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 13 Jun 2009 15:52:09 +0000 Subject: [PATCH 105/717] Another attempt to get the customer table working. Cake's query mechanism is really torquing me, it never seems to be able to do what I need (perhaps because they've generalized it to work with so many SQL engines. I'm just going to pull unit information out all together, and I can add it back in another day if needed. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@106 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/customers_controller.php | 242 ++++++++-------------- site/views/elements/customers.ctp | 2 +- 2 files changed, 82 insertions(+), 162 deletions(-) diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 4c50e31..eec095c 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -25,122 +25,39 @@ class CustomersController extends AppController { /************************************************************************** ************************************************************************** ************************************************************************** - * action: index - * - Lists all current tenants + * action: index / current / past / all + * - Creates a list of tenants */ - function index() { - $this->current(); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: current - * - Lists all current tenants - */ - - function current() { - $this->paginate = array_merge - ($this->paginate, - array('link' => - array(// Models - 'Lease' => - array('fields' => array(), - 'type' => 'INNER', - ), - ), - 'conditions' => array('Lease.close_date IS NULL') - )); - - $title = 'Current Tenants'; + function jqGridSetup($action, $title) { $this->set('title', $title); $this->set('heading', $title); - $this->set('customers', $this->paginate()); + // The resulting page will contain a jqGrid, which will + // use ajax to obtain the actual data for this action + $this->set('action', $action); $this->render('index'); } - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: past - * - Lists all past tenants - */ - - function past() { - $this->paginate = array_merge - ($this->paginate, - array('link' => - array(// Models - 'Lease' => - array('fields' => array(), - 'type' => 'INNER', - ), - ), - 'conditions' => array('Lease.close_date IS NOT NULL') - )); - - $title = 'Past Tenants'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('customers', $this->paginate()); - $this->render('index'); - } + function index() { $this->current(); } + function current() { $this->jqGridSetup('current', 'Current Tenants'); } + function past() { $this->jqGridSetup('past', 'Past Tenants'); } + function all() { $this->jqGridSetup('all', 'All Tenants'); } /************************************************************************** ************************************************************************** ************************************************************************** - * action: all - * - Lists all customers, including non-tenants + * action: jqGridData + * - Fetches the actual data requested by jqGrid as XML */ - function all() { - $title = 'All Customers'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('params', $this->params); - $this->render('index'); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: data - * - - */ - - function jqGridData($debug = true) { -/* pr(array('fields' => $fields, */ -/* 'explode' => explode(";", $fields_str))); */ - -/* $debug=true; */ - -/* $tf = unserialize($fields); */ -/* $tp = unserialize($params); */ - -/* $fields = array('Customer.id'); */ - - //$action_params = unserialize($action_params); - //$fields = explode(";", $fields_str); - - //$fields=array(); -/* foreach (explode(";", $fields_str) AS $i => $field) { */ -/* pr(array('field' => $field, */ -/* 'explode' => explode(".", $field))); */ -/* list($tbl, $col) = explode(".", $field); */ -/* unset($fields[$i]); */ -/* $fields[$tbl][] = $field; */ -/* } */ - - //pr(array('fields' => $fields)); - - + function jqGridData() { + // Assume we're debugging. + // The actual jqGrid request will set this to false $debug = true; + if (isset($this->passedArgs['debug'])) $debug = $this->passedArgs['debug']; - $this->autoRender = false; if (!$debug) { $this->layout = null; $this->autoLayout = false; @@ -148,88 +65,91 @@ class CustomersController extends AppController { Configure::write('debug', '0'); } - $page = 1; // page number - $rows = 20; // rows in the grid - rowNum parameter - $sidx = 'Customer.id'; // sort column - index from colModel - $sord = 'ASC'; // sort order + // Set up some defaults + $page = 1; // page number + $rows = 20; // rows in the grid - rowNum parameter + $sidx = 'Customer.id'; // sort column - index from colModel + $sord = 'ASC'; // sort order + $action = 'current'; // specific customer list - $fields = array('Customer.id'); - + // Extract the actual settings from the jqGrid request if (isset($this->params['url']) && is_array($this->params['url'])) extract($this->params['url']); + // Unserialize our complex structure if (isset($fields)) $fields = unserialize($fields); else - $fields = array('Customer.id'); + $fields = array('Customer.id', 'Customer.name'); - if (isset($params)) - $params = unserialize($params); - else - $params = array('action' => 'all'); - - // calculate the number of rows for the query. We need this for paging the result - $row = $this->Customer->findCount(); - $count = $row; - - // calculate the total pages for the query - if( $count > 0 ) { - $total_pages = ceil($count/$rows); - } else { - $total_pages = 0; - } - - // if for some reasons the requested page is greater than the total - // set the requested page to total page - if ($page > $total_pages) $page=$total_pages; - - // calculate the starting position of the rows - $start = $rows*$page - $rows; - - // if for some reasons start position is negative set it to 0 - // typical case is that the user type 0 for the requested page - if($start <0) $start = 0; - - $cond = array(); - if ($params['action'] == 'current') { - - } elseif ($params['action'] == 'past') { - - } else { - - } - - - // the actual query for the grid data - $customers = $this->Customer->find - ('all', - array('contain' => array - (// Models - 'PrimaryContact', + // Set up the basic 'contain' field to query the + // pertinent information. + $contain = + array(// Models + 'PrimaryContact', /* array(// Models */ /* 'ContactPhone', */ /* 'ContactEmail', */ /* 'ContactAddress', */ /* ), */ - 'Account' => - array('fields' => array('Account.id')), +/* 'Account' => */ +/* array('fields' => array('Account.id')), */ - 'CurrentLease' => - array('fields' => array(), - 'Unit' => - array('fields' => array('name')), - ), - ), - //'link' => array('fields' => $fields), - 'order' => "$sidx $sord", - 'limit' => "$start, $rows", + 'CurrentLease' => + array('fields' => array(), + 'Unit' => + array('fields' => array('name')), + ), + ); + + // Calculate the number of rows for the query, and figure out + // any special query conditions that will be necessary + $count = $this->Customer->find('count'); + if ($action != 'all') { + $count_past = $this->Customer->find('count', + array('link' => array('CurrentLease'), + 'conditions' => 'CurrentLease.id IS NULL')); + if ($action == 'current') { + $count = $count - $count_past; + $contain['CurrentLease']['conditions'] = 'CurrentLease.id IS NOT NULL'; + } + elseif ($action == 'past') { + $count = $count_past; + $contain['CurrentLease']['conditions'] = 'CurrentLease.id IS NULL'; + } + } + + // Verify a few parameters and determine our starting row + $total_pages = ($count < 0) ? 0 : ceil($count/$rows); + $page = ($page < 1) ? 1 : (($page > $total_pages) ? $total_pages : $page); + $start = $rows*$page - $rows; + + // the actual query for the grid data + $customers = $this->Customer->find + ('all', + array('contain' => $contain, + 'order' => "$sidx $sord", + 'limit' => "$start, $rows", )); - //pr($customers); +/* $query['order'] = "$sidx $sord"; */ +/* $query['limit'] = "$start, $rows"; */ +/* $query['group'] = 'Customer.id', */ +/* $query = array('link' => */ +/* array(// Models */ +/* 'PrimaryContact', */ +/* 'CurrentLease' => */ +/* array('fields' => array(), */ +/* 'Unit' => */ +/* array('fields' => array('name')), */ +/* ), */ +/* ), */ +/* ); */ if ($debug) { ob_start(); + print_r(compact('count', 'rows', 'total_pages', 'page', 'start', 'customers')); } else { if ( stristr($_SERVER["HTTP_ACCEPT"],"application/xhtml+xml") ) { diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index c526ef0..38b69bc 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -74,7 +74,7 @@ jQuery(document).ready(function(){ url: '', datatype: 'xml', mtype: 'GET', - postData: { params: '', + postData: { action: '', fields: '' }, colNames: [ '' ], colModel: [ ], From 508a8b08aa72ea79dcffd89f31ff42623f1ce49b Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 13 Jun 2009 20:44:36 +0000 Subject: [PATCH 106/717] Moved the position of the Loading... message on jqGrid. It probably doesn't matter, as we customize the grid, we'll likely add an icon instead of text to indicate loading. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@107 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/webroot/css/layout.css | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/site/webroot/css/layout.css b/site/webroot/css/layout.css index edf2314..7a43bf3 100644 --- a/site/webroot/css/layout.css +++ b/site/webroot/css/layout.css @@ -136,6 +136,21 @@ table.list.ledger td.date.receipt { padding-left: 1em; } table.list.ledger td.evnrow { background: #f4f4f4; } +/************************************************************ + ************************************************************ + * jqGrid + */ +table.Header th h2 { + color: #dd5; + font-family:'Gill Sans','lucida grande',helvetica, arial, sans-serif; + font-size: 190%; + margin-bottom: 0.0em; +} + +div.loading { + margin-top: 1.5em; + margin-left: 1.0em; +} /************************************************************ ************************************************************ From 0278c776108a4801c4fe4598df0c45f1aa9b1956 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 13 Jun 2009 20:46:17 +0000 Subject: [PATCH 107/717] Things are finally working fairly well for the customers grid (although I've not yet taken any speed issues into account). I removed the index.ctp file, since it was largely useless and I figured out how to render directly to the element. I also moved most of the jqGrid XML code into the application controller, since it will be reused by most of our controllers. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@108 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 103 ++++++++++++++ site/controllers/customers_controller.php | 163 +++------------------- site/views/customers/index.ctp | 3 - site/views/elements/customers.ctp | 31 ++-- 4 files changed, 147 insertions(+), 153 deletions(-) delete mode 100644 site/views/customers/index.ctp diff --git a/site/app_controller.php b/site/app_controller.php index 8bd1deb..a6478fe 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -55,5 +55,108 @@ class AppController extends Controller { $this->set('sidemenu', $this->sideMenuLinks()); } + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: jqGridData + * - Fetches the actual data requested by jqGrid as XML + */ + + function jqGridData($model, $records, $query) { + // Assume we're debugging. + // The actual jqGrid request will set this to false + $debug = true; + + $model_alias = $model->alias; + $model_id = $model_alias . '.id'; + + if (isset($this->passedArgs['debug'])) + $debug = $this->passedArgs['debug']; + + if (!$debug) { + $this->layout = null; + $this->autoLayout = false; + $this->autoRender = false; + Configure::write('debug', '0'); + } + + // Set up some defaults + $page = 1; // page number + $rows = 20; // rows in the grid - rowNum parameter + $sidx = $model_id; // sort column - index from colModel + $sord = 'ASC'; // sort order + + // Extract the actual settings from the jqGrid request + if (isset($this->params['url']) && is_array($this->params['url'])) + extract($this->params['url']); + + // Unserialize our complex structure of fields + // This SHOULD be always set, except when debugging + if (isset($fields)) + $fields = unserialize($fields); + else + $fields = array($model_id); + + // Verify a few parameters and determine our starting row + $total = ($records < 0) ? 0 : ceil($records/$rows); + $page = ($page < 1) ? 1 : (($page > $total) ? $total : $page); + $start = $rows*$page - $rows; + + // the actual query for the grid data + $query['group'] = $model_id; + $query['order'] = "$sidx $sord"; + $query['limit'] = "$start, $rows"; + $results = $model->find('all', $query); + + if ($debug) { + ob_start(); + print_r(compact('records', 'rows', 'total', 'page', 'start')); + } + else { + header("Content-type: text/xml;charset=utf-8"); + } + + echo "\n"; + echo "\n"; + echo " $page\n"; + echo " $total\n"; + echo " $records\n"; + + foreach ($results AS $result) { + // Add the calculated fields (if any), to the model fields + if (isset($result[0])) + $result[$model_alias] += $result[0]; + + echo " \n"; + foreach ($fields AS $field) { + list($tbl, $col) = explode(".", $field); + if (isset($col)) + $data = $result[$tbl][$col]; + else + $data = $result[$model_alias][$tbl]; + + // be sure to put text data in CDATA + if (preg_match("/^\d*$/", $data)) + echo " $data\n"; + else + echo " \n"; + } + echo " \n"; + } + echo "\n"; + + if ($debug) { + $xml = ob_get_contents(); + ob_end_clean(); + + $xml = preg_replace("/&/", "&", $xml); + $xml = preg_replace("//", ">", $xml); + + echo ("\n
    \n$xml\n
    \n"); + } + } + } ?> \ No newline at end of file diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index eec095c..1fb6d3f 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -34,7 +34,7 @@ class CustomersController extends AppController { // The resulting page will contain a jqGrid, which will // use ajax to obtain the actual data for this action $this->set('action', $action); - $this->render('index'); + $this->render('/elements/customers'); } function index() { $this->current(); } @@ -51,159 +51,40 @@ class CustomersController extends AppController { */ function jqGridData() { - // Assume we're debugging. - // The actual jqGrid request will set this to false - $debug = true; - if (isset($this->passedArgs['debug'])) - $debug = $this->passedArgs['debug']; + $action = 'all'; + if (isset($this->params['url']['action'])) + $action = $this->params['url']['action']; - if (!$debug) { - $this->layout = null; - $this->autoLayout = false; - $this->autoRender = false; - Configure::write('debug', '0'); - } - - // Set up some defaults - $page = 1; // page number - $rows = 20; // rows in the grid - rowNum parameter - $sidx = 'Customer.id'; // sort column - index from colModel - $sord = 'ASC'; // sort order - $action = 'current'; // specific customer list - - // Extract the actual settings from the jqGrid request - if (isset($this->params['url']) && is_array($this->params['url'])) - extract($this->params['url']); - - // Unserialize our complex structure - if (isset($fields)) - $fields = unserialize($fields); - else - $fields = array('Customer.id', 'Customer.name'); - - // Set up the basic 'contain' field to query the - // pertinent information. - $contain = - array(// Models + // Set up the basic query + $query = array + ('link' => + array(// Models 'PrimaryContact', -/* array(// Models */ -/* 'ContactPhone', */ -/* 'ContactEmail', */ -/* 'ContactAddress', */ -/* ), */ - -/* 'Account' => */ -/* array('fields' => array('Account.id')), */ - - 'CurrentLease' => - array('fields' => array(), - 'Unit' => - array('fields' => array('name')), - ), - ); + 'CurrentLease' => array('fields' => array()), + ), + 'fields' => 'Customer.*, COUNT(CurrentLease.id) AS lease_count', + ); // Calculate the number of rows for the query, and figure out // any special query conditions that will be necessary - $count = $this->Customer->find('count'); + $records = $this->Customer->find('count', array('contain'=>false)); if ($action != 'all') { - $count_past = $this->Customer->find('count', - array('link' => array('CurrentLease'), - 'conditions' => 'CurrentLease.id IS NULL')); + $records_past = $this->Customer->find('count', + array('link' => array('CurrentLease' => array('fields' => array())), + 'conditions' => 'CurrentLease.id IS NULL')); + if ($action == 'current') { - $count = $count - $count_past; - $contain['CurrentLease']['conditions'] = 'CurrentLease.id IS NOT NULL'; + $records = $records - $records_past; + $query['conditions'][] = 'CurrentLease.id IS NOT NULL'; } elseif ($action == 'past') { - $count = $count_past; - $contain['CurrentLease']['conditions'] = 'CurrentLease.id IS NULL'; + $records = $records_past; + $query['conditions'][] = 'CurrentLease.id IS NULL'; } } - // Verify a few parameters and determine our starting row - $total_pages = ($count < 0) ? 0 : ceil($count/$rows); - $page = ($page < 1) ? 1 : (($page > $total_pages) ? $total_pages : $page); - $start = $rows*$page - $rows; - - // the actual query for the grid data - $customers = $this->Customer->find - ('all', - array('contain' => $contain, - 'order' => "$sidx $sord", - 'limit' => "$start, $rows", - )); - -/* $query['order'] = "$sidx $sord"; */ -/* $query['limit'] = "$start, $rows"; */ -/* $query['group'] = 'Customer.id', */ -/* $query = array('link' => */ -/* array(// Models */ -/* 'PrimaryContact', */ -/* 'CurrentLease' => */ -/* array('fields' => array(), */ -/* 'Unit' => */ -/* array('fields' => array('name')), */ -/* ), */ -/* ), */ -/* ); */ - - if ($debug) { - ob_start(); - print_r(compact('count', 'rows', 'total_pages', 'page', 'start', 'customers')); - } - else { - if ( stristr($_SERVER["HTTP_ACCEPT"],"application/xhtml+xml") ) { - header("Content-type: application/xhtml+xml;charset=utf-8"); - } else { - header("Content-type: text/xml;charset=utf-8"); - } - - echo "\n"; - } - - echo "\n"; -/* echo " \n"; */ -/* echo " \n"; */ -/* echo " \n"; */ -/* echo " \n"; */ -/* echo " \n"; */ -/* echo " params, true) . "]]>\n"; */ -/* echo " passedArgs, true) . "]]>\n"; */ -/* echo " \n"; */ -/* echo " \n"; */ -/* echo " \n"; */ - echo " ".$page."\n"; - echo " ".$total_pages."\n"; - echo " ".$count."\n"; - - // be sure to put text data in CDATA - foreach ($customers AS $customer) { - $customer['Customer']['units'] = - implode("; ", - array_map(create_function - ('$lease', 'return $lease["Unit"]["name"];'), - $customer['CurrentLease'])); - - - echo " \n"; - foreach ($fields AS $field) { - list($tbl, $col) = explode(".", $field); - echo " \n"; - } - echo " \n"; - } - echo "\n"; - - if ($debug) { - $xml = ob_get_contents(); - ob_end_clean(); - - $xml = preg_replace("/&/", "&", $xml); - $xml = preg_replace("//", ">", $xml); - - echo ("\n
    \n$xml\n
    \n"); - } + parent::jqGridData($this->Customer, $records, $query); } diff --git a/site/views/customers/index.ctp b/site/views/customers/index.ctp deleted file mode 100644 index b67aad4..0000000 --- a/site/views/customers/index.ctp +++ /dev/null @@ -1,3 +0,0 @@ -
    -element('customers', array('heading' => '

    '.$heading.'

    ')) ?> -
    diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index 38b69bc..7c72e31 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -1,6 +1,8 @@ '.$this->pageTitle.''; + if (!isset($limit)) $limit = 20; @@ -8,7 +10,7 @@ if (!isset($limitOptions)) $limitOptions = array(10, 20, 50, 200); if (!isset($height)) - $height = '80%'; + $height = 'auto'; // Do some prework to bring in the appropriate libraries $imgpath = '/pmgr/site/css/jqGrid/basic/images'; @@ -26,12 +28,12 @@ if (isset($customers[0]['ContactsCustomer'])) $cols['Name'] = array('index' => 'Customer.name', 'width' => '150', 'align' => 'left'); $cols['Last Name'] = array('index' => 'PrimaryContact.last_name', 'width' => '100', 'align' => 'left'); $cols['First Name'] = array('index' => 'PrimaryContact.first_name', 'width' => '100', 'align' => 'left'); -$cols['Unit(s)'] = array('index' => 'Customer.units', 'width' => '80', 'align' => 'center'); -$cols['Comment'] = array('index' => 'Customer.comment', 'width' => '300', 'align' => 'center'); +$cols['Leases'] = array('index' => 'lease_count', 'width' => '60', 'align' => 'center'); +$cols['Comment'] = array('index' => 'Customer.comment', 'width' => '300', 'align' => 'left'); // Some of the columns should not be sortable -foreach (array('Unit(s)') AS $field) - $cols[$field]['sortable'] = false; +foreach (array_intersect_key($cols, array('Comment'=>1)) AS $k => $v) + $cols[$k]['sortable'] = false; // Create the javascript code for jqGrid to create each table column $colModels = array(); @@ -79,20 +81,31 @@ jQuery(document).ready(function(){ colNames: [ '' ], colModel: [ ], pager: jQuery('#customer-pager'), - height: '100%', - //height: 'auto', + height: '', rowNum: , rowList: [], sortname: 'Customer.id', sortorder: "ASC", viewrecords: true, imgpath: '', - caption: , + caption: , }); }); --> +
    +
    +Get Table Code
    */ +/*
    */ + +/*

    */ +/*
    */ +/* Show Loading
    */ +/* Set Top Margin
    */ +/* Set Left Margin
    */ +?> \ No newline at end of file From 3be775f9b2cdf4650684a1de559671ba4dc624c6 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 13 Jun 2009 21:20:11 +0000 Subject: [PATCH 108/717] Added query ability to the customer grid. There is a bug with the paging code, but it roughly works. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@109 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 20 ++++++++++++++++++++ site/views/elements/customers.ctp | 10 ++++++++++ 2 files changed, 30 insertions(+) diff --git a/site/app_controller.php b/site/app_controller.php index a6478fe..2e4c7af 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -98,6 +98,24 @@ class AppController extends Controller { else $fields = array($model_id); + if (isset($_search) && $_search === 'true') { + $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' => '%'), + ); + + $op = $ops[$searchOper]; + $field = $searchField . ($op['op'] ? ' '.$op['op'] : ''); + $val = $op['pre'] . $searchString . $op['post']; + $query['conditions'][] = array($field => $val); + } + // Verify a few parameters and determine our starting row $total = ($records < 0) ? 0 : ceil($records/$rows); $page = ($page < 1) ? 1 : (($page > $total) ? $total : $page); @@ -119,6 +137,8 @@ class AppController extends Controller { echo "\n"; echo "\n"; +/* echo " params['url'], true) . "\n]]>\n"; */ +/* echo " \n"; */ echo " $page\n"; echo " $total\n"; echo " $records\n"; diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index 7c72e31..46f9dc3 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -99,6 +99,16 @@ jQuery(document).ready(function(){

    + + + + Get Table Code
    */ /*
    */ From e7b4b2132842eaca0c02b3e61cf3bdd1817727d5 Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 14 Jun 2009 00:46:12 +0000 Subject: [PATCH 109/717] Moved all the vendor css & js code into webroot. Although it technically was working fine, cake apparently steps on the fact that the file doesn't change between requests, leading the browser to re-download the code with every hit. Under the webroot directory, cake returns code 304 if the browser already has a copy cached. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@110 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/{vendors => webroot}/css/jqGrid/basic/grid.css | 0 .../css/jqGrid/basic/images/cd_run.gif | Bin .../css/jqGrid/basic/images/dirty.gif | Bin .../css/jqGrid/basic/images/down.gif | Bin .../css/jqGrid/basic/images/find.gif | Bin .../css/jqGrid/basic/images/first.gif | Bin .../css/jqGrid/basic/images/folder.png | Bin .../css/jqGrid/basic/images/grid-blue-ft.gif | Bin .../css/jqGrid/basic/images/grid-blue-hd.gif | Bin .../css/jqGrid/basic/images/headerbg.gif | Bin .../css/jqGrid/basic/images/headerleft.gif | Bin .../css/jqGrid/basic/images/headerright.gif | Bin .../css/jqGrid/basic/images/ico-close.gif | Bin .../css/jqGrid/basic/images/last.gif | Bin .../css/jqGrid/basic/images/line3.gif | Bin .../css/jqGrid/basic/images/loading.gif | Bin .../css/jqGrid/basic/images/minus.gif | Bin .../css/jqGrid/basic/images/next.gif | Bin .../css/jqGrid/basic/images/nochild.gif | Bin .../css/jqGrid/basic/images/off-first.gif | Bin .../css/jqGrid/basic/images/off-last.gif | Bin .../css/jqGrid/basic/images/off-next.gif | Bin .../css/jqGrid/basic/images/off-prev.gif | Bin .../css/jqGrid/basic/images/plus.gif | Bin .../css/jqGrid/basic/images/prev.gif | Bin .../css/jqGrid/basic/images/refresh.gif | Bin .../css/jqGrid/basic/images/resize.gif | Bin .../css/jqGrid/basic/images/row_add.gif | Bin .../css/jqGrid/basic/images/row_delete.gif | Bin .../css/jqGrid/basic/images/row_edit.gif | Bin .../css/jqGrid/basic/images/sort_asc.gif | Bin .../css/jqGrid/basic/images/sort_desc.gif | Bin .../css/jqGrid/basic/images/spacer.gif | Bin .../css/jqGrid/basic/images/tab_close-on.gif | Bin .../css/jqGrid/basic/images/tree_leaf.gif | Bin .../css/jqGrid/basic/images/tree_minus.gif | Bin .../css/jqGrid/basic/images/tree_plus.gif | Bin .../css/jqGrid/basic/images/up.gif | Bin .../{vendors => webroot}/css/jqGrid/coffee/grid.css | 0 .../css/jqGrid/coffee/images/cd_run.gif | Bin .../css/jqGrid/coffee/images/dirty.gif | Bin .../css/jqGrid/coffee/images/down.gif | Bin .../css/jqGrid/coffee/images/find.gif | Bin .../css/jqGrid/coffee/images/first.gif | Bin .../css/jqGrid/coffee/images/folder.png | Bin .../css/jqGrid/coffee/images/grid-blue-ft.gif | Bin .../css/jqGrid/coffee/images/grid-blue-hd.gif | Bin .../css/jqGrid/coffee/images/headerbg.gif | Bin .../css/jqGrid/coffee/images/headerleft.gif | Bin .../css/jqGrid/coffee/images/headerright.gif | Bin .../css/jqGrid/coffee/images/ico-close.gif | Bin .../css/jqGrid/coffee/images/last.gif | Bin .../css/jqGrid/coffee/images/line3.gif | Bin .../css/jqGrid/coffee/images/loading.gif | Bin .../css/jqGrid/coffee/images/minus.gif | Bin .../css/jqGrid/coffee/images/next.gif | Bin .../css/jqGrid/coffee/images/nochild.gif | Bin .../css/jqGrid/coffee/images/off-first.gif | Bin .../css/jqGrid/coffee/images/off-last.gif | Bin .../css/jqGrid/coffee/images/off-next.gif | Bin .../css/jqGrid/coffee/images/off-prev.gif | Bin .../css/jqGrid/coffee/images/plus.gif | Bin .../css/jqGrid/coffee/images/prev.gif | Bin .../css/jqGrid/coffee/images/refresh.gif | Bin .../css/jqGrid/coffee/images/resize.gif | Bin .../css/jqGrid/coffee/images/row_add.gif | Bin .../css/jqGrid/coffee/images/row_delete.gif | Bin .../css/jqGrid/coffee/images/row_edit.gif | Bin .../css/jqGrid/coffee/images/sort_asc.gif | Bin .../css/jqGrid/coffee/images/sort_desc.gif | Bin .../css/jqGrid/coffee/images/spacer.gif | Bin .../css/jqGrid/coffee/images/tab_close-on.gif | Bin .../css/jqGrid/coffee/images/tree_leaf.gif | Bin .../css/jqGrid/coffee/images/tree_minus.gif | Bin .../css/jqGrid/coffee/images/tree_plus.gif | Bin .../css/jqGrid/coffee/images/up.gif | Bin site/{vendors => webroot}/css/jqGrid/green/grid.css | 0 .../css/jqGrid/green/images/cd_run.gif | Bin .../css/jqGrid/green/images/dirty.gif | Bin .../css/jqGrid/green/images/down.gif | Bin .../css/jqGrid/green/images/find.gif | Bin .../css/jqGrid/green/images/first.gif | Bin .../css/jqGrid/green/images/folder.png | Bin .../css/jqGrid/green/images/grid-blue-ft.gif | Bin .../css/jqGrid/green/images/grid-blue-hd.gif | Bin .../css/jqGrid/green/images/headerbg.gif | Bin .../css/jqGrid/green/images/headerleft.gif | Bin .../css/jqGrid/green/images/headerright.gif | Bin .../css/jqGrid/green/images/ico-close.gif | Bin .../css/jqGrid/green/images/last.gif | Bin .../css/jqGrid/green/images/leaf.gif | Bin .../css/jqGrid/green/images/line3.gif | Bin .../css/jqGrid/green/images/loading.gif | Bin .../css/jqGrid/green/images/minus.gif | Bin .../css/jqGrid/green/images/next.gif | Bin .../css/jqGrid/green/images/nochild.gif | Bin .../css/jqGrid/green/images/off-first.gif | Bin .../css/jqGrid/green/images/off-last.gif | Bin .../css/jqGrid/green/images/off-next.gif | Bin .../css/jqGrid/green/images/off-prev.gif | Bin .../css/jqGrid/green/images/plus.gif | Bin .../css/jqGrid/green/images/prev.gif | Bin .../css/jqGrid/green/images/refresh.gif | Bin .../css/jqGrid/green/images/resize.gif | Bin .../css/jqGrid/green/images/row_add.gif | Bin .../css/jqGrid/green/images/row_delete.gif | Bin .../css/jqGrid/green/images/row_edit.gif | Bin .../css/jqGrid/green/images/sort_asc.gif | Bin .../css/jqGrid/green/images/sort_desc.gif | Bin .../css/jqGrid/green/images/spacer.gif | Bin .../css/jqGrid/green/images/tab_close-on.gif | Bin .../css/jqGrid/green/images/tree_leaf.gif | Bin .../css/jqGrid/green/images/tree_minus.gif | Bin .../css/jqGrid/green/images/tree_plus.gif | Bin .../css/jqGrid/green/images/up.gif | Bin site/{vendors => webroot}/css/jqGrid/jqModal.css | 0 site/{vendors => webroot}/css/jqGrid/sand/grid.css | 0 .../css/jqGrid/sand/images/cd_run.gif | Bin .../css/jqGrid/sand/images/dirty.gif | Bin .../css/jqGrid/sand/images/down.gif | Bin .../css/jqGrid/sand/images/find.gif | Bin .../css/jqGrid/sand/images/first.gif | Bin .../css/jqGrid/sand/images/folder.png | Bin .../css/jqGrid/sand/images/grid-blue-ft.gif | Bin .../css/jqGrid/sand/images/grid-blue-hd.gif | Bin .../css/jqGrid/sand/images/headerbg.gif | Bin .../css/jqGrid/sand/images/headerleft.gif | Bin .../css/jqGrid/sand/images/headerright.gif | Bin .../css/jqGrid/sand/images/ico-close.gif | Bin .../css/jqGrid/sand/images/last.gif | Bin .../css/jqGrid/sand/images/line3.gif | Bin .../css/jqGrid/sand/images/loading.gif | Bin .../css/jqGrid/sand/images/minus.gif | Bin .../css/jqGrid/sand/images/next.gif | Bin .../css/jqGrid/sand/images/nochild.gif | Bin .../css/jqGrid/sand/images/off-first.gif | Bin .../css/jqGrid/sand/images/off-last.gif | Bin .../css/jqGrid/sand/images/off-next.gif | Bin .../css/jqGrid/sand/images/off-prev.gif | Bin .../css/jqGrid/sand/images/plus.gif | Bin .../css/jqGrid/sand/images/prev.gif | Bin .../css/jqGrid/sand/images/refresh.gif | Bin .../css/jqGrid/sand/images/resize.gif | Bin .../css/jqGrid/sand/images/row_add.gif | Bin .../css/jqGrid/sand/images/row_delete.gif | Bin .../css/jqGrid/sand/images/row_edit.gif | Bin .../css/jqGrid/sand/images/sort_asc.gif | Bin .../css/jqGrid/sand/images/sort_desc.gif | Bin .../css/jqGrid/sand/images/spacer.gif | Bin .../css/jqGrid/sand/images/tab_close-on.gif | Bin .../css/jqGrid/sand/images/tree_leaf.gif | Bin .../css/jqGrid/sand/images/tree_minus.gif | Bin .../css/jqGrid/sand/images/tree_plus.gif | Bin .../css/jqGrid/sand/images/up.gif | Bin site/{vendors => webroot}/css/jqGrid/steel/grid.css | 0 .../css/jqGrid/steel/images/._sprite5.png | Bin .../css/jqGrid/steel/images/._sprite5.psd | Bin .../css/jqGrid/steel/images/Arrow2 Down.png | Bin .../css/jqGrid/steel/images/Arrow2 Up.png | Bin .../css/jqGrid/steel/images/bg.gif | Bin .../css/jqGrid/steel/images/cd_run.gif | Bin .../css/jqGrid/steel/images/control_090.png | Bin .../css/jqGrid/steel/images/control_270.png | Bin .../css/jqGrid/steel/images/dirty.gif | Bin .../css/jqGrid/steel/images/down.gif | Bin .../css/jqGrid/steel/images/fhbg.gif | Bin .../css/jqGrid/steel/images/find.gif | Bin .../css/jqGrid/steel/images/find1.gif | Bin .../css/jqGrid/steel/images/first.gif | Bin .../css/jqGrid/steel/images/first.png | Bin .../css/jqGrid/steel/images/folder.png | Bin .../css/jqGrid/steel/images/headerleft1.gif | Bin .../css/jqGrid/steel/images/headerright1.gif | Bin .../css/jqGrid/steel/images/ico-close.gif | Bin .../css/jqGrid/steel/images/last.gif | Bin .../css/jqGrid/steel/images/last.png | Bin .../css/jqGrid/steel/images/line3.gif | Bin .../css/jqGrid/steel/images/loading.gif | Bin .../css/jqGrid/steel/images/minus.gif | Bin .../css/jqGrid/steel/images/next.gif | Bin .../css/jqGrid/steel/images/next.png | Bin .../css/jqGrid/steel/images/nochild.gif | Bin .../css/jqGrid/steel/images/odown.gif | Bin .../css/jqGrid/steel/images/off-first.gif | Bin .../css/jqGrid/steel/images/off-last.gif | Bin .../css/jqGrid/steel/images/off-next.gif | Bin .../css/jqGrid/steel/images/off-prev.gif | Bin .../css/jqGrid/steel/images/oup.gif | Bin .../css/jqGrid/steel/images/plus.gif | Bin .../css/jqGrid/steel/images/prev.gif | Bin .../css/jqGrid/steel/images/prev.png | Bin .../css/jqGrid/steel/images/refresh.gif | Bin .../css/jqGrid/steel/images/refresh1.gif | Bin .../css/jqGrid/steel/images/resize.gif | Bin .../css/jqGrid/steel/images/row_add.gif | Bin .../css/jqGrid/steel/images/row_add1.gif | Bin .../css/jqGrid/steel/images/row_delete.gif | Bin .../css/jqGrid/steel/images/row_delete1.gif | Bin .../css/jqGrid/steel/images/row_edit.gif | Bin .../css/jqGrid/steel/images/row_edit1.gif | Bin .../css/jqGrid/steel/images/sort_asc.gif | Bin .../css/jqGrid/steel/images/sort_desc.gif | Bin .../css/jqGrid/steel/images/spacer.gif | Bin .../css/jqGrid/steel/images/sprite.png | Bin .../css/jqGrid/steel/images/sprite5.png | Bin .../css/jqGrid/steel/images/sprite5.psd | Bin .../css/jqGrid/steel/images/tab_close-on.gif | Bin .../css/jqGrid/steel/images/tree_leaf.gif | Bin .../css/jqGrid/steel/images/tree_minus.gif | Bin .../css/jqGrid/steel/images/tree_plus.gif | Bin .../css/jqGrid/steel/images/up.gif | Bin .../css/jqGrid/steel/images/wbg.gif | Bin .../base/images/ui-bg_flat_0_aaaaaa_40x100.png | Bin .../base/images/ui-bg_flat_75_ffffff_40x100.png | Bin .../base/images/ui-bg_glass_55_fbf9ee_1x400.png | Bin .../base/images/ui-bg_glass_65_ffffff_1x400.png | Bin .../base/images/ui-bg_glass_75_dadada_1x400.png | Bin .../base/images/ui-bg_glass_75_e6e6e6_1x400.png | Bin .../base/images/ui-bg_glass_75_ffffff_1x400.png | Bin .../base/images/ui-bg_glass_95_fef1ec_1x400.png | Bin .../images/ui-bg_highlight-soft_75_cccccc_1x100.png | Bin .../images/ui-bg_inset-soft_95_fef1ec_1x100.png | Bin .../jquery/base/images/ui-icons_222222_256x240.png | Bin .../jquery/base/images/ui-icons_2e83ff_256x240.png | Bin .../jquery/base/images/ui-icons_454545_256x240.png | Bin .../jquery/base/images/ui-icons_888888_256x240.png | Bin .../jquery/base/images/ui-icons_cd0a0a_256x240.png | Bin .../css/jquery/base/ui.accordion.css | 0 .../{vendors => webroot}/css/jquery/base/ui.all.css | 0 .../css/jquery/base/ui.base.css | 0 .../css/jquery/base/ui.core.css | 0 .../css/jquery/base/ui.datepicker.css | 0 .../css/jquery/base/ui.dialog.css | 0 .../css/jquery/base/ui.progressbar.css | 0 .../css/jquery/base/ui.resizable.css | 0 .../css/jquery/base/ui.slider.css | 0 .../css/jquery/base/ui.tabs.css | 0 .../css/jquery/base/ui.theme.css | 0 .../ui-bg_diagonals-thick_15_0b3e6f_40x40.png | Bin .../images/ui-bg_dots-medium_30_0b58a2_4x4.png | Bin .../images/ui-bg_dots-small_20_333333_2x2.png | Bin .../images/ui-bg_dots-small_30_a32d00_2x2.png | Bin .../images/ui-bg_dots-small_40_00498f_2x2.png | Bin .../dotluv/images/ui-bg_flat_0_aaaaaa_40x100.png | Bin .../dotluv/images/ui-bg_flat_40_292929_40x100.png | Bin .../images/ui-bg_gloss-wave_20_111111_500x100.png | Bin .../dotluv/images/ui-icons_00498f_256x240.png | Bin .../dotluv/images/ui-icons_98d2fb_256x240.png | Bin .../dotluv/images/ui-icons_9ccdfc_256x240.png | Bin .../dotluv/images/ui-icons_ffffff_256x240.png | Bin .../css/jquery/dotluv/ui.all.css | 0 .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin .../images/ui-bg_flat_75_ffffff_40x100.png | Bin .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin .../images/ui-bg_glass_65_ffffff_1x400.png | Bin .../images/ui-bg_glass_75_dadada_1x400.png | Bin .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin .../images/ui-bg_highlight-soft_75_cccccc_1x100.png | Bin .../smoothness/images/ui-icons_222222_256x240.png | Bin .../smoothness/images/ui-icons_2e83ff_256x240.png | Bin .../smoothness/images/ui-icons_454545_256x240.png | Bin .../smoothness/images/ui-icons_888888_256x240.png | Bin .../smoothness/images/ui-icons_cd0a0a_256x240.png | Bin .../css/jquery/smoothness/ui.all.css | 0 .../start/images/ui-bg_flat_55_999999_40x100.png | Bin .../start/images/ui-bg_flat_75_aaaaaa_40x100.png | Bin .../start/images/ui-bg_glass_45_0078ae_1x400.png | Bin .../start/images/ui-bg_glass_55_f8da4e_1x400.png | Bin .../start/images/ui-bg_glass_75_79c9ec_1x400.png | Bin .../images/ui-bg_gloss-wave_45_e14f1c_500x100.png | Bin .../images/ui-bg_gloss-wave_50_6eac2c_500x100.png | Bin .../images/ui-bg_gloss-wave_75_2191c0_500x100.png | Bin .../images/ui-bg_inset-hard_100_fcfdfd_1x100.png | Bin .../jquery/start/images/ui-icons_0078ae_256x240.png | Bin .../jquery/start/images/ui-icons_056b93_256x240.png | Bin .../jquery/start/images/ui-icons_d8e7f3_256x240.png | Bin .../jquery/start/images/ui-icons_e0fdff_256x240.png | Bin .../jquery/start/images/ui-icons_f5e175_256x240.png | Bin .../jquery/start/images/ui-icons_f7a50d_256x240.png | Bin .../jquery/start/images/ui-icons_fcd113_256x240.png | Bin .../css/jquery/start/ui.all.css | 0 .../{vendors => webroot}/js/jqGrid/jquery.jqGrid.js | 0 site/{vendors => webroot}/js/jqGrid/js/JsonXml.js | 0 site/{vendors => webroot}/js/jqGrid/js/grid.base.js | 0 .../js/jqGrid/js/grid.celledit.js | 0 .../js/jqGrid/js/grid.common.js | 0 .../js/jqGrid/js/grid.custom.js | 0 .../js/jqGrid/js/grid.formedit.js | 0 .../js/jqGrid/js/grid.import.js | 0 .../js/jqGrid/js/grid.inlinedit.js | 0 .../js/jqGrid/js/grid.locale-bg.js | 0 .../js/jqGrid/js/grid.locale-bg1251.js | 0 .../js/jqGrid/js/grid.locale-cat.js | 0 .../js/jqGrid/js/grid.locale-cs.js | 0 .../js/jqGrid/js/grid.locale-de.js | 0 .../js/jqGrid/js/grid.locale-dk.js | 0 .../js/jqGrid/js/grid.locale-el.js | 0 .../js/jqGrid/js/grid.locale-en.js | 0 .../js/jqGrid/js/grid.locale-fa.js | 0 .../js/jqGrid/js/grid.locale-fi.js | 0 .../js/jqGrid/js/grid.locale-fr.js | 0 .../js/jqGrid/js/grid.locale-is.js | 0 .../js/jqGrid/js/grid.locale-it.js | 0 .../js/jqGrid/js/grid.locale-jp.js | 0 .../js/jqGrid/js/grid.locale-pl.js | 0 .../js/jqGrid/js/grid.locale-pt-br.js | 0 .../js/jqGrid/js/grid.locale-pt.js | 0 .../js/jqGrid/js/grid.locale-ru.js | 0 .../js/jqGrid/js/grid.locale-sp.js | 0 .../js/jqGrid/js/grid.locale-sv.js | 0 .../js/jqGrid/js/grid.locale-tr.js | 0 .../js/jqGrid/js/grid.postext.js | 0 .../js/jqGrid/js/grid.setcolumns.js | 0 .../js/jqGrid/js/grid.subgrid.js | 0 .../js/jqGrid/js/grid.tbltogrid.js | 0 .../js/jqGrid/js/grid.treegrid.js | 0 site/{vendors => webroot}/js/jqGrid/js/jqDnR.js | 0 site/{vendors => webroot}/js/jqGrid/js/jqModal.js | 0 .../js/jqGrid/js/jquery.fmatter.js | 0 .../js/jqGrid/js/jquery.tablednd.js | 0 site/{vendors => webroot}/js/jqGrid/js/json2.js | 0 .../js/jqGrid/js/min/JsonXml-min.js | 0 .../js/jqGrid/js/min/grid.base-min.js | 0 .../js/jqGrid/js/min/grid.celledit-min.js | 0 .../js/jqGrid/js/min/grid.common-min.js | 0 .../js/jqGrid/js/min/grid.custom-min.js | 0 .../js/jqGrid/js/min/grid.formedit-min.js | 0 .../js/jqGrid/js/min/grid.import-min.js | 0 .../js/jqGrid/js/min/grid.inlinedit-min.js | 0 .../js/jqGrid/js/min/grid.locale-bg-min.js | 0 .../js/jqGrid/js/min/grid.locale-bg1251-min.js | 0 .../js/jqGrid/js/min/grid.locale-cat-min.js | 0 .../js/jqGrid/js/min/grid.locale-cs-min.js | 0 .../js/jqGrid/js/min/grid.locale-de-min.js | 0 .../js/jqGrid/js/min/grid.locale-dk-min.js | 0 .../js/jqGrid/js/min/grid.locale-el-min.js | 0 .../js/jqGrid/js/min/grid.locale-en-min.js | 0 .../js/jqGrid/js/min/grid.locale-fi-min.js | 0 .../js/jqGrid/js/min/grid.locale-fr-min.js | 0 .../js/jqGrid/js/min/grid.locale-is-min.js | 0 .../js/jqGrid/js/min/grid.locale-it-min.js | 0 .../js/jqGrid/js/min/grid.locale-jp-min.js | 0 .../js/jqGrid/js/min/grid.locale-pl-min.js | 0 .../js/jqGrid/js/min/grid.locale-pt-br-min.js | 0 .../js/jqGrid/js/min/grid.locale-pt-min.js | 0 .../js/jqGrid/js/min/grid.locale-ru-min.js | 0 .../js/jqGrid/js/min/grid.locale-sp-min.js | 0 .../js/jqGrid/js/min/grid.locale-tr-min.js | 0 .../js/jqGrid/js/min/grid.postext-min.js | 0 .../js/jqGrid/js/min/grid.setcolumns-min.js | 0 .../js/jqGrid/js/min/grid.subgrid-min.js | 0 .../js/jqGrid/js/min/grid.tbltogrid-min.js | 0 .../js/jqGrid/js/min/grid.treegrid-min.js | 0 .../js/jqGrid/js/min/jqDnR-min.js | 0 .../js/jqGrid/js/min/jqModal-min.js | 0 .../js/jqGrid/js/min/jquery.fmatter-min.js | 0 .../js/jqGrid/js/min/jquery.tablednd-min.js | 0 .../js/jqGrid/js/min/json2-min.js | 0 site/{vendors => webroot}/js/jquery.form.js | 0 site/{vendors => webroot}/js/jquery/jquery-ui.js | 0 site/{vendors => webroot}/js/jquery/jquery.js | 0 362 files changed, 0 insertions(+), 0 deletions(-) rename site/{vendors => webroot}/css/jqGrid/basic/grid.css (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/cd_run.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/dirty.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/down.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/find.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/first.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/folder.png (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/grid-blue-ft.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/grid-blue-hd.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/headerbg.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/headerleft.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/headerright.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/ico-close.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/last.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/line3.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/loading.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/minus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/next.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/nochild.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/off-first.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/off-last.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/off-next.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/off-prev.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/plus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/prev.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/refresh.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/resize.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/row_add.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/row_delete.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/row_edit.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/sort_asc.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/sort_desc.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/spacer.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/tab_close-on.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/tree_leaf.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/tree_minus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/tree_plus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/basic/images/up.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/grid.css (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/cd_run.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/dirty.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/down.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/find.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/first.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/folder.png (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/grid-blue-ft.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/grid-blue-hd.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/headerbg.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/headerleft.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/headerright.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/ico-close.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/last.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/line3.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/loading.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/minus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/next.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/nochild.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/off-first.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/off-last.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/off-next.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/off-prev.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/plus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/prev.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/refresh.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/resize.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/row_add.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/row_delete.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/row_edit.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/sort_asc.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/sort_desc.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/spacer.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/tab_close-on.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/tree_leaf.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/tree_minus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/tree_plus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/coffee/images/up.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/grid.css (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/cd_run.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/dirty.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/down.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/find.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/first.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/folder.png (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/grid-blue-ft.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/grid-blue-hd.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/headerbg.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/headerleft.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/headerright.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/ico-close.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/last.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/leaf.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/line3.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/loading.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/minus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/next.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/nochild.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/off-first.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/off-last.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/off-next.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/off-prev.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/plus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/prev.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/refresh.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/resize.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/row_add.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/row_delete.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/row_edit.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/sort_asc.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/sort_desc.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/spacer.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/tab_close-on.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/tree_leaf.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/tree_minus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/tree_plus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/green/images/up.gif (100%) rename site/{vendors => webroot}/css/jqGrid/jqModal.css (100%) rename site/{vendors => webroot}/css/jqGrid/sand/grid.css (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/cd_run.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/dirty.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/down.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/find.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/first.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/folder.png (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/grid-blue-ft.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/grid-blue-hd.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/headerbg.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/headerleft.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/headerright.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/ico-close.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/last.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/line3.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/loading.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/minus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/next.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/nochild.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/off-first.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/off-last.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/off-next.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/off-prev.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/plus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/prev.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/refresh.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/resize.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/row_add.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/row_delete.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/row_edit.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/sort_asc.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/sort_desc.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/spacer.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/tab_close-on.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/tree_leaf.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/tree_minus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/tree_plus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/sand/images/up.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/grid.css (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/._sprite5.png (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/._sprite5.psd (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/Arrow2 Down.png (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/Arrow2 Up.png (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/bg.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/cd_run.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/control_090.png (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/control_270.png (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/dirty.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/down.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/fhbg.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/find.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/find1.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/first.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/first.png (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/folder.png (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/headerleft1.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/headerright1.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/ico-close.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/last.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/last.png (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/line3.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/loading.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/minus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/next.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/next.png (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/nochild.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/odown.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/off-first.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/off-last.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/off-next.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/off-prev.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/oup.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/plus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/prev.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/prev.png (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/refresh.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/refresh1.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/resize.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/row_add.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/row_add1.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/row_delete.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/row_delete1.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/row_edit.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/row_edit1.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/sort_asc.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/sort_desc.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/spacer.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/sprite.png (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/sprite5.png (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/sprite5.psd (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/tab_close-on.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/tree_leaf.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/tree_minus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/tree_plus.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/up.gif (100%) rename site/{vendors => webroot}/css/jqGrid/steel/images/wbg.gif (100%) rename site/{vendors => webroot}/css/jquery/base/images/ui-bg_flat_0_aaaaaa_40x100.png (100%) rename site/{vendors => webroot}/css/jquery/base/images/ui-bg_flat_75_ffffff_40x100.png (100%) rename site/{vendors => webroot}/css/jquery/base/images/ui-bg_glass_55_fbf9ee_1x400.png (100%) rename site/{vendors => webroot}/css/jquery/base/images/ui-bg_glass_65_ffffff_1x400.png (100%) rename site/{vendors => webroot}/css/jquery/base/images/ui-bg_glass_75_dadada_1x400.png (100%) rename site/{vendors => webroot}/css/jquery/base/images/ui-bg_glass_75_e6e6e6_1x400.png (100%) rename site/{vendors => webroot}/css/jquery/base/images/ui-bg_glass_75_ffffff_1x400.png (100%) rename site/{vendors => webroot}/css/jquery/base/images/ui-bg_glass_95_fef1ec_1x400.png (100%) rename site/{vendors => webroot}/css/jquery/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png (100%) rename site/{vendors => webroot}/css/jquery/base/images/ui-bg_inset-soft_95_fef1ec_1x100.png (100%) rename site/{vendors => webroot}/css/jquery/base/images/ui-icons_222222_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/base/images/ui-icons_2e83ff_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/base/images/ui-icons_454545_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/base/images/ui-icons_888888_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/base/images/ui-icons_cd0a0a_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/base/ui.accordion.css (100%) rename site/{vendors => webroot}/css/jquery/base/ui.all.css (100%) rename site/{vendors => webroot}/css/jquery/base/ui.base.css (100%) rename site/{vendors => webroot}/css/jquery/base/ui.core.css (100%) rename site/{vendors => webroot}/css/jquery/base/ui.datepicker.css (100%) rename site/{vendors => webroot}/css/jquery/base/ui.dialog.css (100%) rename site/{vendors => webroot}/css/jquery/base/ui.progressbar.css (100%) rename site/{vendors => webroot}/css/jquery/base/ui.resizable.css (100%) rename site/{vendors => webroot}/css/jquery/base/ui.slider.css (100%) rename site/{vendors => webroot}/css/jquery/base/ui.tabs.css (100%) rename site/{vendors => webroot}/css/jquery/base/ui.theme.css (100%) rename site/{vendors => webroot}/css/jquery/dotluv/images/ui-bg_diagonals-thick_15_0b3e6f_40x40.png (100%) rename site/{vendors => webroot}/css/jquery/dotluv/images/ui-bg_dots-medium_30_0b58a2_4x4.png (100%) rename site/{vendors => webroot}/css/jquery/dotluv/images/ui-bg_dots-small_20_333333_2x2.png (100%) rename site/{vendors => webroot}/css/jquery/dotluv/images/ui-bg_dots-small_30_a32d00_2x2.png (100%) rename site/{vendors => webroot}/css/jquery/dotluv/images/ui-bg_dots-small_40_00498f_2x2.png (100%) rename site/{vendors => webroot}/css/jquery/dotluv/images/ui-bg_flat_0_aaaaaa_40x100.png (100%) rename site/{vendors => webroot}/css/jquery/dotluv/images/ui-bg_flat_40_292929_40x100.png (100%) rename site/{vendors => webroot}/css/jquery/dotluv/images/ui-bg_gloss-wave_20_111111_500x100.png (100%) rename site/{vendors => webroot}/css/jquery/dotluv/images/ui-icons_00498f_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/dotluv/images/ui-icons_98d2fb_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/dotluv/images/ui-icons_9ccdfc_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/dotluv/images/ui-icons_ffffff_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/dotluv/ui.all.css (100%) rename site/{vendors => webroot}/css/jquery/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png (100%) rename site/{vendors => webroot}/css/jquery/smoothness/images/ui-bg_flat_75_ffffff_40x100.png (100%) rename site/{vendors => webroot}/css/jquery/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png (100%) rename site/{vendors => webroot}/css/jquery/smoothness/images/ui-bg_glass_65_ffffff_1x400.png (100%) rename site/{vendors => webroot}/css/jquery/smoothness/images/ui-bg_glass_75_dadada_1x400.png (100%) rename site/{vendors => webroot}/css/jquery/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png (100%) rename site/{vendors => webroot}/css/jquery/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png (100%) rename site/{vendors => webroot}/css/jquery/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png (100%) rename site/{vendors => webroot}/css/jquery/smoothness/images/ui-icons_222222_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/smoothness/images/ui-icons_2e83ff_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/smoothness/images/ui-icons_454545_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/smoothness/images/ui-icons_888888_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/smoothness/images/ui-icons_cd0a0a_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/smoothness/ui.all.css (100%) rename site/{vendors => webroot}/css/jquery/start/images/ui-bg_flat_55_999999_40x100.png (100%) rename site/{vendors => webroot}/css/jquery/start/images/ui-bg_flat_75_aaaaaa_40x100.png (100%) rename site/{vendors => webroot}/css/jquery/start/images/ui-bg_glass_45_0078ae_1x400.png (100%) rename site/{vendors => webroot}/css/jquery/start/images/ui-bg_glass_55_f8da4e_1x400.png (100%) rename site/{vendors => webroot}/css/jquery/start/images/ui-bg_glass_75_79c9ec_1x400.png (100%) rename site/{vendors => webroot}/css/jquery/start/images/ui-bg_gloss-wave_45_e14f1c_500x100.png (100%) rename site/{vendors => webroot}/css/jquery/start/images/ui-bg_gloss-wave_50_6eac2c_500x100.png (100%) rename site/{vendors => webroot}/css/jquery/start/images/ui-bg_gloss-wave_75_2191c0_500x100.png (100%) rename site/{vendors => webroot}/css/jquery/start/images/ui-bg_inset-hard_100_fcfdfd_1x100.png (100%) rename site/{vendors => webroot}/css/jquery/start/images/ui-icons_0078ae_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/start/images/ui-icons_056b93_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/start/images/ui-icons_d8e7f3_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/start/images/ui-icons_e0fdff_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/start/images/ui-icons_f5e175_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/start/images/ui-icons_f7a50d_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/start/images/ui-icons_fcd113_256x240.png (100%) rename site/{vendors => webroot}/css/jquery/start/ui.all.css (100%) rename site/{vendors => webroot}/js/jqGrid/jquery.jqGrid.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/JsonXml.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.base.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.celledit.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.common.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.custom.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.formedit.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.import.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.inlinedit.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-bg.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-bg1251.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-cat.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-cs.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-de.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-dk.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-el.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-en.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-fa.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-fi.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-fr.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-is.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-it.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-jp.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-pl.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-pt-br.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-pt.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-ru.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-sp.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-sv.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.locale-tr.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.postext.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.setcolumns.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.subgrid.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.tbltogrid.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/grid.treegrid.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/jqDnR.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/jqModal.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/jquery.fmatter.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/jquery.tablednd.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/json2.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/JsonXml-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.base-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.celledit-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.common-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.custom-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.formedit-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.import-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.inlinedit-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-bg-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-bg1251-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-cat-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-cs-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-de-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-dk-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-el-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-en-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-fi-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-fr-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-is-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-it-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-jp-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-pl-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-pt-br-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-pt-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-ru-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-sp-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.locale-tr-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.postext-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.setcolumns-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.subgrid-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.tbltogrid-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/grid.treegrid-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/jqDnR-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/jqModal-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/jquery.fmatter-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/jquery.tablednd-min.js (100%) rename site/{vendors => webroot}/js/jqGrid/js/min/json2-min.js (100%) rename site/{vendors => webroot}/js/jquery.form.js (100%) rename site/{vendors => webroot}/js/jquery/jquery-ui.js (100%) rename site/{vendors => webroot}/js/jquery/jquery.js (100%) diff --git a/site/vendors/css/jqGrid/basic/grid.css b/site/webroot/css/jqGrid/basic/grid.css similarity index 100% rename from site/vendors/css/jqGrid/basic/grid.css rename to site/webroot/css/jqGrid/basic/grid.css diff --git a/site/vendors/css/jqGrid/basic/images/cd_run.gif b/site/webroot/css/jqGrid/basic/images/cd_run.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/cd_run.gif rename to site/webroot/css/jqGrid/basic/images/cd_run.gif diff --git a/site/vendors/css/jqGrid/basic/images/dirty.gif b/site/webroot/css/jqGrid/basic/images/dirty.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/dirty.gif rename to site/webroot/css/jqGrid/basic/images/dirty.gif diff --git a/site/vendors/css/jqGrid/basic/images/down.gif b/site/webroot/css/jqGrid/basic/images/down.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/down.gif rename to site/webroot/css/jqGrid/basic/images/down.gif diff --git a/site/vendors/css/jqGrid/basic/images/find.gif b/site/webroot/css/jqGrid/basic/images/find.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/find.gif rename to site/webroot/css/jqGrid/basic/images/find.gif diff --git a/site/vendors/css/jqGrid/basic/images/first.gif b/site/webroot/css/jqGrid/basic/images/first.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/first.gif rename to site/webroot/css/jqGrid/basic/images/first.gif diff --git a/site/vendors/css/jqGrid/basic/images/folder.png b/site/webroot/css/jqGrid/basic/images/folder.png similarity index 100% rename from site/vendors/css/jqGrid/basic/images/folder.png rename to site/webroot/css/jqGrid/basic/images/folder.png diff --git a/site/vendors/css/jqGrid/basic/images/grid-blue-ft.gif b/site/webroot/css/jqGrid/basic/images/grid-blue-ft.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/grid-blue-ft.gif rename to site/webroot/css/jqGrid/basic/images/grid-blue-ft.gif diff --git a/site/vendors/css/jqGrid/basic/images/grid-blue-hd.gif b/site/webroot/css/jqGrid/basic/images/grid-blue-hd.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/grid-blue-hd.gif rename to site/webroot/css/jqGrid/basic/images/grid-blue-hd.gif diff --git a/site/vendors/css/jqGrid/basic/images/headerbg.gif b/site/webroot/css/jqGrid/basic/images/headerbg.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/headerbg.gif rename to site/webroot/css/jqGrid/basic/images/headerbg.gif diff --git a/site/vendors/css/jqGrid/basic/images/headerleft.gif b/site/webroot/css/jqGrid/basic/images/headerleft.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/headerleft.gif rename to site/webroot/css/jqGrid/basic/images/headerleft.gif diff --git a/site/vendors/css/jqGrid/basic/images/headerright.gif b/site/webroot/css/jqGrid/basic/images/headerright.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/headerright.gif rename to site/webroot/css/jqGrid/basic/images/headerright.gif diff --git a/site/vendors/css/jqGrid/basic/images/ico-close.gif b/site/webroot/css/jqGrid/basic/images/ico-close.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/ico-close.gif rename to site/webroot/css/jqGrid/basic/images/ico-close.gif diff --git a/site/vendors/css/jqGrid/basic/images/last.gif b/site/webroot/css/jqGrid/basic/images/last.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/last.gif rename to site/webroot/css/jqGrid/basic/images/last.gif diff --git a/site/vendors/css/jqGrid/basic/images/line3.gif b/site/webroot/css/jqGrid/basic/images/line3.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/line3.gif rename to site/webroot/css/jqGrid/basic/images/line3.gif diff --git a/site/vendors/css/jqGrid/basic/images/loading.gif b/site/webroot/css/jqGrid/basic/images/loading.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/loading.gif rename to site/webroot/css/jqGrid/basic/images/loading.gif diff --git a/site/vendors/css/jqGrid/basic/images/minus.gif b/site/webroot/css/jqGrid/basic/images/minus.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/minus.gif rename to site/webroot/css/jqGrid/basic/images/minus.gif diff --git a/site/vendors/css/jqGrid/basic/images/next.gif b/site/webroot/css/jqGrid/basic/images/next.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/next.gif rename to site/webroot/css/jqGrid/basic/images/next.gif diff --git a/site/vendors/css/jqGrid/basic/images/nochild.gif b/site/webroot/css/jqGrid/basic/images/nochild.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/nochild.gif rename to site/webroot/css/jqGrid/basic/images/nochild.gif diff --git a/site/vendors/css/jqGrid/basic/images/off-first.gif b/site/webroot/css/jqGrid/basic/images/off-first.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/off-first.gif rename to site/webroot/css/jqGrid/basic/images/off-first.gif diff --git a/site/vendors/css/jqGrid/basic/images/off-last.gif b/site/webroot/css/jqGrid/basic/images/off-last.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/off-last.gif rename to site/webroot/css/jqGrid/basic/images/off-last.gif diff --git a/site/vendors/css/jqGrid/basic/images/off-next.gif b/site/webroot/css/jqGrid/basic/images/off-next.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/off-next.gif rename to site/webroot/css/jqGrid/basic/images/off-next.gif diff --git a/site/vendors/css/jqGrid/basic/images/off-prev.gif b/site/webroot/css/jqGrid/basic/images/off-prev.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/off-prev.gif rename to site/webroot/css/jqGrid/basic/images/off-prev.gif diff --git a/site/vendors/css/jqGrid/basic/images/plus.gif b/site/webroot/css/jqGrid/basic/images/plus.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/plus.gif rename to site/webroot/css/jqGrid/basic/images/plus.gif diff --git a/site/vendors/css/jqGrid/basic/images/prev.gif b/site/webroot/css/jqGrid/basic/images/prev.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/prev.gif rename to site/webroot/css/jqGrid/basic/images/prev.gif diff --git a/site/vendors/css/jqGrid/basic/images/refresh.gif b/site/webroot/css/jqGrid/basic/images/refresh.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/refresh.gif rename to site/webroot/css/jqGrid/basic/images/refresh.gif diff --git a/site/vendors/css/jqGrid/basic/images/resize.gif b/site/webroot/css/jqGrid/basic/images/resize.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/resize.gif rename to site/webroot/css/jqGrid/basic/images/resize.gif diff --git a/site/vendors/css/jqGrid/basic/images/row_add.gif b/site/webroot/css/jqGrid/basic/images/row_add.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/row_add.gif rename to site/webroot/css/jqGrid/basic/images/row_add.gif diff --git a/site/vendors/css/jqGrid/basic/images/row_delete.gif b/site/webroot/css/jqGrid/basic/images/row_delete.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/row_delete.gif rename to site/webroot/css/jqGrid/basic/images/row_delete.gif diff --git a/site/vendors/css/jqGrid/basic/images/row_edit.gif b/site/webroot/css/jqGrid/basic/images/row_edit.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/row_edit.gif rename to site/webroot/css/jqGrid/basic/images/row_edit.gif diff --git a/site/vendors/css/jqGrid/basic/images/sort_asc.gif b/site/webroot/css/jqGrid/basic/images/sort_asc.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/sort_asc.gif rename to site/webroot/css/jqGrid/basic/images/sort_asc.gif diff --git a/site/vendors/css/jqGrid/basic/images/sort_desc.gif b/site/webroot/css/jqGrid/basic/images/sort_desc.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/sort_desc.gif rename to site/webroot/css/jqGrid/basic/images/sort_desc.gif diff --git a/site/vendors/css/jqGrid/basic/images/spacer.gif b/site/webroot/css/jqGrid/basic/images/spacer.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/spacer.gif rename to site/webroot/css/jqGrid/basic/images/spacer.gif diff --git a/site/vendors/css/jqGrid/basic/images/tab_close-on.gif b/site/webroot/css/jqGrid/basic/images/tab_close-on.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/tab_close-on.gif rename to site/webroot/css/jqGrid/basic/images/tab_close-on.gif diff --git a/site/vendors/css/jqGrid/basic/images/tree_leaf.gif b/site/webroot/css/jqGrid/basic/images/tree_leaf.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/tree_leaf.gif rename to site/webroot/css/jqGrid/basic/images/tree_leaf.gif diff --git a/site/vendors/css/jqGrid/basic/images/tree_minus.gif b/site/webroot/css/jqGrid/basic/images/tree_minus.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/tree_minus.gif rename to site/webroot/css/jqGrid/basic/images/tree_minus.gif diff --git a/site/vendors/css/jqGrid/basic/images/tree_plus.gif b/site/webroot/css/jqGrid/basic/images/tree_plus.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/tree_plus.gif rename to site/webroot/css/jqGrid/basic/images/tree_plus.gif diff --git a/site/vendors/css/jqGrid/basic/images/up.gif b/site/webroot/css/jqGrid/basic/images/up.gif similarity index 100% rename from site/vendors/css/jqGrid/basic/images/up.gif rename to site/webroot/css/jqGrid/basic/images/up.gif diff --git a/site/vendors/css/jqGrid/coffee/grid.css b/site/webroot/css/jqGrid/coffee/grid.css similarity index 100% rename from site/vendors/css/jqGrid/coffee/grid.css rename to site/webroot/css/jqGrid/coffee/grid.css diff --git a/site/vendors/css/jqGrid/coffee/images/cd_run.gif b/site/webroot/css/jqGrid/coffee/images/cd_run.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/cd_run.gif rename to site/webroot/css/jqGrid/coffee/images/cd_run.gif diff --git a/site/vendors/css/jqGrid/coffee/images/dirty.gif b/site/webroot/css/jqGrid/coffee/images/dirty.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/dirty.gif rename to site/webroot/css/jqGrid/coffee/images/dirty.gif diff --git a/site/vendors/css/jqGrid/coffee/images/down.gif b/site/webroot/css/jqGrid/coffee/images/down.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/down.gif rename to site/webroot/css/jqGrid/coffee/images/down.gif diff --git a/site/vendors/css/jqGrid/coffee/images/find.gif b/site/webroot/css/jqGrid/coffee/images/find.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/find.gif rename to site/webroot/css/jqGrid/coffee/images/find.gif diff --git a/site/vendors/css/jqGrid/coffee/images/first.gif b/site/webroot/css/jqGrid/coffee/images/first.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/first.gif rename to site/webroot/css/jqGrid/coffee/images/first.gif diff --git a/site/vendors/css/jqGrid/coffee/images/folder.png b/site/webroot/css/jqGrid/coffee/images/folder.png similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/folder.png rename to site/webroot/css/jqGrid/coffee/images/folder.png diff --git a/site/vendors/css/jqGrid/coffee/images/grid-blue-ft.gif b/site/webroot/css/jqGrid/coffee/images/grid-blue-ft.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/grid-blue-ft.gif rename to site/webroot/css/jqGrid/coffee/images/grid-blue-ft.gif diff --git a/site/vendors/css/jqGrid/coffee/images/grid-blue-hd.gif b/site/webroot/css/jqGrid/coffee/images/grid-blue-hd.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/grid-blue-hd.gif rename to site/webroot/css/jqGrid/coffee/images/grid-blue-hd.gif diff --git a/site/vendors/css/jqGrid/coffee/images/headerbg.gif b/site/webroot/css/jqGrid/coffee/images/headerbg.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/headerbg.gif rename to site/webroot/css/jqGrid/coffee/images/headerbg.gif diff --git a/site/vendors/css/jqGrid/coffee/images/headerleft.gif b/site/webroot/css/jqGrid/coffee/images/headerleft.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/headerleft.gif rename to site/webroot/css/jqGrid/coffee/images/headerleft.gif diff --git a/site/vendors/css/jqGrid/coffee/images/headerright.gif b/site/webroot/css/jqGrid/coffee/images/headerright.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/headerright.gif rename to site/webroot/css/jqGrid/coffee/images/headerright.gif diff --git a/site/vendors/css/jqGrid/coffee/images/ico-close.gif b/site/webroot/css/jqGrid/coffee/images/ico-close.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/ico-close.gif rename to site/webroot/css/jqGrid/coffee/images/ico-close.gif diff --git a/site/vendors/css/jqGrid/coffee/images/last.gif b/site/webroot/css/jqGrid/coffee/images/last.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/last.gif rename to site/webroot/css/jqGrid/coffee/images/last.gif diff --git a/site/vendors/css/jqGrid/coffee/images/line3.gif b/site/webroot/css/jqGrid/coffee/images/line3.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/line3.gif rename to site/webroot/css/jqGrid/coffee/images/line3.gif diff --git a/site/vendors/css/jqGrid/coffee/images/loading.gif b/site/webroot/css/jqGrid/coffee/images/loading.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/loading.gif rename to site/webroot/css/jqGrid/coffee/images/loading.gif diff --git a/site/vendors/css/jqGrid/coffee/images/minus.gif b/site/webroot/css/jqGrid/coffee/images/minus.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/minus.gif rename to site/webroot/css/jqGrid/coffee/images/minus.gif diff --git a/site/vendors/css/jqGrid/coffee/images/next.gif b/site/webroot/css/jqGrid/coffee/images/next.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/next.gif rename to site/webroot/css/jqGrid/coffee/images/next.gif diff --git a/site/vendors/css/jqGrid/coffee/images/nochild.gif b/site/webroot/css/jqGrid/coffee/images/nochild.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/nochild.gif rename to site/webroot/css/jqGrid/coffee/images/nochild.gif diff --git a/site/vendors/css/jqGrid/coffee/images/off-first.gif b/site/webroot/css/jqGrid/coffee/images/off-first.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/off-first.gif rename to site/webroot/css/jqGrid/coffee/images/off-first.gif diff --git a/site/vendors/css/jqGrid/coffee/images/off-last.gif b/site/webroot/css/jqGrid/coffee/images/off-last.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/off-last.gif rename to site/webroot/css/jqGrid/coffee/images/off-last.gif diff --git a/site/vendors/css/jqGrid/coffee/images/off-next.gif b/site/webroot/css/jqGrid/coffee/images/off-next.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/off-next.gif rename to site/webroot/css/jqGrid/coffee/images/off-next.gif diff --git a/site/vendors/css/jqGrid/coffee/images/off-prev.gif b/site/webroot/css/jqGrid/coffee/images/off-prev.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/off-prev.gif rename to site/webroot/css/jqGrid/coffee/images/off-prev.gif diff --git a/site/vendors/css/jqGrid/coffee/images/plus.gif b/site/webroot/css/jqGrid/coffee/images/plus.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/plus.gif rename to site/webroot/css/jqGrid/coffee/images/plus.gif diff --git a/site/vendors/css/jqGrid/coffee/images/prev.gif b/site/webroot/css/jqGrid/coffee/images/prev.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/prev.gif rename to site/webroot/css/jqGrid/coffee/images/prev.gif diff --git a/site/vendors/css/jqGrid/coffee/images/refresh.gif b/site/webroot/css/jqGrid/coffee/images/refresh.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/refresh.gif rename to site/webroot/css/jqGrid/coffee/images/refresh.gif diff --git a/site/vendors/css/jqGrid/coffee/images/resize.gif b/site/webroot/css/jqGrid/coffee/images/resize.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/resize.gif rename to site/webroot/css/jqGrid/coffee/images/resize.gif diff --git a/site/vendors/css/jqGrid/coffee/images/row_add.gif b/site/webroot/css/jqGrid/coffee/images/row_add.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/row_add.gif rename to site/webroot/css/jqGrid/coffee/images/row_add.gif diff --git a/site/vendors/css/jqGrid/coffee/images/row_delete.gif b/site/webroot/css/jqGrid/coffee/images/row_delete.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/row_delete.gif rename to site/webroot/css/jqGrid/coffee/images/row_delete.gif diff --git a/site/vendors/css/jqGrid/coffee/images/row_edit.gif b/site/webroot/css/jqGrid/coffee/images/row_edit.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/row_edit.gif rename to site/webroot/css/jqGrid/coffee/images/row_edit.gif diff --git a/site/vendors/css/jqGrid/coffee/images/sort_asc.gif b/site/webroot/css/jqGrid/coffee/images/sort_asc.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/sort_asc.gif rename to site/webroot/css/jqGrid/coffee/images/sort_asc.gif diff --git a/site/vendors/css/jqGrid/coffee/images/sort_desc.gif b/site/webroot/css/jqGrid/coffee/images/sort_desc.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/sort_desc.gif rename to site/webroot/css/jqGrid/coffee/images/sort_desc.gif diff --git a/site/vendors/css/jqGrid/coffee/images/spacer.gif b/site/webroot/css/jqGrid/coffee/images/spacer.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/spacer.gif rename to site/webroot/css/jqGrid/coffee/images/spacer.gif diff --git a/site/vendors/css/jqGrid/coffee/images/tab_close-on.gif b/site/webroot/css/jqGrid/coffee/images/tab_close-on.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/tab_close-on.gif rename to site/webroot/css/jqGrid/coffee/images/tab_close-on.gif diff --git a/site/vendors/css/jqGrid/coffee/images/tree_leaf.gif b/site/webroot/css/jqGrid/coffee/images/tree_leaf.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/tree_leaf.gif rename to site/webroot/css/jqGrid/coffee/images/tree_leaf.gif diff --git a/site/vendors/css/jqGrid/coffee/images/tree_minus.gif b/site/webroot/css/jqGrid/coffee/images/tree_minus.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/tree_minus.gif rename to site/webroot/css/jqGrid/coffee/images/tree_minus.gif diff --git a/site/vendors/css/jqGrid/coffee/images/tree_plus.gif b/site/webroot/css/jqGrid/coffee/images/tree_plus.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/tree_plus.gif rename to site/webroot/css/jqGrid/coffee/images/tree_plus.gif diff --git a/site/vendors/css/jqGrid/coffee/images/up.gif b/site/webroot/css/jqGrid/coffee/images/up.gif similarity index 100% rename from site/vendors/css/jqGrid/coffee/images/up.gif rename to site/webroot/css/jqGrid/coffee/images/up.gif diff --git a/site/vendors/css/jqGrid/green/grid.css b/site/webroot/css/jqGrid/green/grid.css similarity index 100% rename from site/vendors/css/jqGrid/green/grid.css rename to site/webroot/css/jqGrid/green/grid.css diff --git a/site/vendors/css/jqGrid/green/images/cd_run.gif b/site/webroot/css/jqGrid/green/images/cd_run.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/cd_run.gif rename to site/webroot/css/jqGrid/green/images/cd_run.gif diff --git a/site/vendors/css/jqGrid/green/images/dirty.gif b/site/webroot/css/jqGrid/green/images/dirty.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/dirty.gif rename to site/webroot/css/jqGrid/green/images/dirty.gif diff --git a/site/vendors/css/jqGrid/green/images/down.gif b/site/webroot/css/jqGrid/green/images/down.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/down.gif rename to site/webroot/css/jqGrid/green/images/down.gif diff --git a/site/vendors/css/jqGrid/green/images/find.gif b/site/webroot/css/jqGrid/green/images/find.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/find.gif rename to site/webroot/css/jqGrid/green/images/find.gif diff --git a/site/vendors/css/jqGrid/green/images/first.gif b/site/webroot/css/jqGrid/green/images/first.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/first.gif rename to site/webroot/css/jqGrid/green/images/first.gif diff --git a/site/vendors/css/jqGrid/green/images/folder.png b/site/webroot/css/jqGrid/green/images/folder.png similarity index 100% rename from site/vendors/css/jqGrid/green/images/folder.png rename to site/webroot/css/jqGrid/green/images/folder.png diff --git a/site/vendors/css/jqGrid/green/images/grid-blue-ft.gif b/site/webroot/css/jqGrid/green/images/grid-blue-ft.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/grid-blue-ft.gif rename to site/webroot/css/jqGrid/green/images/grid-blue-ft.gif diff --git a/site/vendors/css/jqGrid/green/images/grid-blue-hd.gif b/site/webroot/css/jqGrid/green/images/grid-blue-hd.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/grid-blue-hd.gif rename to site/webroot/css/jqGrid/green/images/grid-blue-hd.gif diff --git a/site/vendors/css/jqGrid/green/images/headerbg.gif b/site/webroot/css/jqGrid/green/images/headerbg.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/headerbg.gif rename to site/webroot/css/jqGrid/green/images/headerbg.gif diff --git a/site/vendors/css/jqGrid/green/images/headerleft.gif b/site/webroot/css/jqGrid/green/images/headerleft.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/headerleft.gif rename to site/webroot/css/jqGrid/green/images/headerleft.gif diff --git a/site/vendors/css/jqGrid/green/images/headerright.gif b/site/webroot/css/jqGrid/green/images/headerright.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/headerright.gif rename to site/webroot/css/jqGrid/green/images/headerright.gif diff --git a/site/vendors/css/jqGrid/green/images/ico-close.gif b/site/webroot/css/jqGrid/green/images/ico-close.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/ico-close.gif rename to site/webroot/css/jqGrid/green/images/ico-close.gif diff --git a/site/vendors/css/jqGrid/green/images/last.gif b/site/webroot/css/jqGrid/green/images/last.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/last.gif rename to site/webroot/css/jqGrid/green/images/last.gif diff --git a/site/vendors/css/jqGrid/green/images/leaf.gif b/site/webroot/css/jqGrid/green/images/leaf.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/leaf.gif rename to site/webroot/css/jqGrid/green/images/leaf.gif diff --git a/site/vendors/css/jqGrid/green/images/line3.gif b/site/webroot/css/jqGrid/green/images/line3.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/line3.gif rename to site/webroot/css/jqGrid/green/images/line3.gif diff --git a/site/vendors/css/jqGrid/green/images/loading.gif b/site/webroot/css/jqGrid/green/images/loading.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/loading.gif rename to site/webroot/css/jqGrid/green/images/loading.gif diff --git a/site/vendors/css/jqGrid/green/images/minus.gif b/site/webroot/css/jqGrid/green/images/minus.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/minus.gif rename to site/webroot/css/jqGrid/green/images/minus.gif diff --git a/site/vendors/css/jqGrid/green/images/next.gif b/site/webroot/css/jqGrid/green/images/next.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/next.gif rename to site/webroot/css/jqGrid/green/images/next.gif diff --git a/site/vendors/css/jqGrid/green/images/nochild.gif b/site/webroot/css/jqGrid/green/images/nochild.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/nochild.gif rename to site/webroot/css/jqGrid/green/images/nochild.gif diff --git a/site/vendors/css/jqGrid/green/images/off-first.gif b/site/webroot/css/jqGrid/green/images/off-first.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/off-first.gif rename to site/webroot/css/jqGrid/green/images/off-first.gif diff --git a/site/vendors/css/jqGrid/green/images/off-last.gif b/site/webroot/css/jqGrid/green/images/off-last.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/off-last.gif rename to site/webroot/css/jqGrid/green/images/off-last.gif diff --git a/site/vendors/css/jqGrid/green/images/off-next.gif b/site/webroot/css/jqGrid/green/images/off-next.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/off-next.gif rename to site/webroot/css/jqGrid/green/images/off-next.gif diff --git a/site/vendors/css/jqGrid/green/images/off-prev.gif b/site/webroot/css/jqGrid/green/images/off-prev.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/off-prev.gif rename to site/webroot/css/jqGrid/green/images/off-prev.gif diff --git a/site/vendors/css/jqGrid/green/images/plus.gif b/site/webroot/css/jqGrid/green/images/plus.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/plus.gif rename to site/webroot/css/jqGrid/green/images/plus.gif diff --git a/site/vendors/css/jqGrid/green/images/prev.gif b/site/webroot/css/jqGrid/green/images/prev.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/prev.gif rename to site/webroot/css/jqGrid/green/images/prev.gif diff --git a/site/vendors/css/jqGrid/green/images/refresh.gif b/site/webroot/css/jqGrid/green/images/refresh.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/refresh.gif rename to site/webroot/css/jqGrid/green/images/refresh.gif diff --git a/site/vendors/css/jqGrid/green/images/resize.gif b/site/webroot/css/jqGrid/green/images/resize.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/resize.gif rename to site/webroot/css/jqGrid/green/images/resize.gif diff --git a/site/vendors/css/jqGrid/green/images/row_add.gif b/site/webroot/css/jqGrid/green/images/row_add.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/row_add.gif rename to site/webroot/css/jqGrid/green/images/row_add.gif diff --git a/site/vendors/css/jqGrid/green/images/row_delete.gif b/site/webroot/css/jqGrid/green/images/row_delete.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/row_delete.gif rename to site/webroot/css/jqGrid/green/images/row_delete.gif diff --git a/site/vendors/css/jqGrid/green/images/row_edit.gif b/site/webroot/css/jqGrid/green/images/row_edit.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/row_edit.gif rename to site/webroot/css/jqGrid/green/images/row_edit.gif diff --git a/site/vendors/css/jqGrid/green/images/sort_asc.gif b/site/webroot/css/jqGrid/green/images/sort_asc.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/sort_asc.gif rename to site/webroot/css/jqGrid/green/images/sort_asc.gif diff --git a/site/vendors/css/jqGrid/green/images/sort_desc.gif b/site/webroot/css/jqGrid/green/images/sort_desc.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/sort_desc.gif rename to site/webroot/css/jqGrid/green/images/sort_desc.gif diff --git a/site/vendors/css/jqGrid/green/images/spacer.gif b/site/webroot/css/jqGrid/green/images/spacer.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/spacer.gif rename to site/webroot/css/jqGrid/green/images/spacer.gif diff --git a/site/vendors/css/jqGrid/green/images/tab_close-on.gif b/site/webroot/css/jqGrid/green/images/tab_close-on.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/tab_close-on.gif rename to site/webroot/css/jqGrid/green/images/tab_close-on.gif diff --git a/site/vendors/css/jqGrid/green/images/tree_leaf.gif b/site/webroot/css/jqGrid/green/images/tree_leaf.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/tree_leaf.gif rename to site/webroot/css/jqGrid/green/images/tree_leaf.gif diff --git a/site/vendors/css/jqGrid/green/images/tree_minus.gif b/site/webroot/css/jqGrid/green/images/tree_minus.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/tree_minus.gif rename to site/webroot/css/jqGrid/green/images/tree_minus.gif diff --git a/site/vendors/css/jqGrid/green/images/tree_plus.gif b/site/webroot/css/jqGrid/green/images/tree_plus.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/tree_plus.gif rename to site/webroot/css/jqGrid/green/images/tree_plus.gif diff --git a/site/vendors/css/jqGrid/green/images/up.gif b/site/webroot/css/jqGrid/green/images/up.gif similarity index 100% rename from site/vendors/css/jqGrid/green/images/up.gif rename to site/webroot/css/jqGrid/green/images/up.gif diff --git a/site/vendors/css/jqGrid/jqModal.css b/site/webroot/css/jqGrid/jqModal.css similarity index 100% rename from site/vendors/css/jqGrid/jqModal.css rename to site/webroot/css/jqGrid/jqModal.css diff --git a/site/vendors/css/jqGrid/sand/grid.css b/site/webroot/css/jqGrid/sand/grid.css similarity index 100% rename from site/vendors/css/jqGrid/sand/grid.css rename to site/webroot/css/jqGrid/sand/grid.css diff --git a/site/vendors/css/jqGrid/sand/images/cd_run.gif b/site/webroot/css/jqGrid/sand/images/cd_run.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/cd_run.gif rename to site/webroot/css/jqGrid/sand/images/cd_run.gif diff --git a/site/vendors/css/jqGrid/sand/images/dirty.gif b/site/webroot/css/jqGrid/sand/images/dirty.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/dirty.gif rename to site/webroot/css/jqGrid/sand/images/dirty.gif diff --git a/site/vendors/css/jqGrid/sand/images/down.gif b/site/webroot/css/jqGrid/sand/images/down.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/down.gif rename to site/webroot/css/jqGrid/sand/images/down.gif diff --git a/site/vendors/css/jqGrid/sand/images/find.gif b/site/webroot/css/jqGrid/sand/images/find.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/find.gif rename to site/webroot/css/jqGrid/sand/images/find.gif diff --git a/site/vendors/css/jqGrid/sand/images/first.gif b/site/webroot/css/jqGrid/sand/images/first.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/first.gif rename to site/webroot/css/jqGrid/sand/images/first.gif diff --git a/site/vendors/css/jqGrid/sand/images/folder.png b/site/webroot/css/jqGrid/sand/images/folder.png similarity index 100% rename from site/vendors/css/jqGrid/sand/images/folder.png rename to site/webroot/css/jqGrid/sand/images/folder.png diff --git a/site/vendors/css/jqGrid/sand/images/grid-blue-ft.gif b/site/webroot/css/jqGrid/sand/images/grid-blue-ft.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/grid-blue-ft.gif rename to site/webroot/css/jqGrid/sand/images/grid-blue-ft.gif diff --git a/site/vendors/css/jqGrid/sand/images/grid-blue-hd.gif b/site/webroot/css/jqGrid/sand/images/grid-blue-hd.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/grid-blue-hd.gif rename to site/webroot/css/jqGrid/sand/images/grid-blue-hd.gif diff --git a/site/vendors/css/jqGrid/sand/images/headerbg.gif b/site/webroot/css/jqGrid/sand/images/headerbg.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/headerbg.gif rename to site/webroot/css/jqGrid/sand/images/headerbg.gif diff --git a/site/vendors/css/jqGrid/sand/images/headerleft.gif b/site/webroot/css/jqGrid/sand/images/headerleft.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/headerleft.gif rename to site/webroot/css/jqGrid/sand/images/headerleft.gif diff --git a/site/vendors/css/jqGrid/sand/images/headerright.gif b/site/webroot/css/jqGrid/sand/images/headerright.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/headerright.gif rename to site/webroot/css/jqGrid/sand/images/headerright.gif diff --git a/site/vendors/css/jqGrid/sand/images/ico-close.gif b/site/webroot/css/jqGrid/sand/images/ico-close.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/ico-close.gif rename to site/webroot/css/jqGrid/sand/images/ico-close.gif diff --git a/site/vendors/css/jqGrid/sand/images/last.gif b/site/webroot/css/jqGrid/sand/images/last.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/last.gif rename to site/webroot/css/jqGrid/sand/images/last.gif diff --git a/site/vendors/css/jqGrid/sand/images/line3.gif b/site/webroot/css/jqGrid/sand/images/line3.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/line3.gif rename to site/webroot/css/jqGrid/sand/images/line3.gif diff --git a/site/vendors/css/jqGrid/sand/images/loading.gif b/site/webroot/css/jqGrid/sand/images/loading.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/loading.gif rename to site/webroot/css/jqGrid/sand/images/loading.gif diff --git a/site/vendors/css/jqGrid/sand/images/minus.gif b/site/webroot/css/jqGrid/sand/images/minus.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/minus.gif rename to site/webroot/css/jqGrid/sand/images/minus.gif diff --git a/site/vendors/css/jqGrid/sand/images/next.gif b/site/webroot/css/jqGrid/sand/images/next.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/next.gif rename to site/webroot/css/jqGrid/sand/images/next.gif diff --git a/site/vendors/css/jqGrid/sand/images/nochild.gif b/site/webroot/css/jqGrid/sand/images/nochild.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/nochild.gif rename to site/webroot/css/jqGrid/sand/images/nochild.gif diff --git a/site/vendors/css/jqGrid/sand/images/off-first.gif b/site/webroot/css/jqGrid/sand/images/off-first.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/off-first.gif rename to site/webroot/css/jqGrid/sand/images/off-first.gif diff --git a/site/vendors/css/jqGrid/sand/images/off-last.gif b/site/webroot/css/jqGrid/sand/images/off-last.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/off-last.gif rename to site/webroot/css/jqGrid/sand/images/off-last.gif diff --git a/site/vendors/css/jqGrid/sand/images/off-next.gif b/site/webroot/css/jqGrid/sand/images/off-next.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/off-next.gif rename to site/webroot/css/jqGrid/sand/images/off-next.gif diff --git a/site/vendors/css/jqGrid/sand/images/off-prev.gif b/site/webroot/css/jqGrid/sand/images/off-prev.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/off-prev.gif rename to site/webroot/css/jqGrid/sand/images/off-prev.gif diff --git a/site/vendors/css/jqGrid/sand/images/plus.gif b/site/webroot/css/jqGrid/sand/images/plus.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/plus.gif rename to site/webroot/css/jqGrid/sand/images/plus.gif diff --git a/site/vendors/css/jqGrid/sand/images/prev.gif b/site/webroot/css/jqGrid/sand/images/prev.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/prev.gif rename to site/webroot/css/jqGrid/sand/images/prev.gif diff --git a/site/vendors/css/jqGrid/sand/images/refresh.gif b/site/webroot/css/jqGrid/sand/images/refresh.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/refresh.gif rename to site/webroot/css/jqGrid/sand/images/refresh.gif diff --git a/site/vendors/css/jqGrid/sand/images/resize.gif b/site/webroot/css/jqGrid/sand/images/resize.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/resize.gif rename to site/webroot/css/jqGrid/sand/images/resize.gif diff --git a/site/vendors/css/jqGrid/sand/images/row_add.gif b/site/webroot/css/jqGrid/sand/images/row_add.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/row_add.gif rename to site/webroot/css/jqGrid/sand/images/row_add.gif diff --git a/site/vendors/css/jqGrid/sand/images/row_delete.gif b/site/webroot/css/jqGrid/sand/images/row_delete.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/row_delete.gif rename to site/webroot/css/jqGrid/sand/images/row_delete.gif diff --git a/site/vendors/css/jqGrid/sand/images/row_edit.gif b/site/webroot/css/jqGrid/sand/images/row_edit.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/row_edit.gif rename to site/webroot/css/jqGrid/sand/images/row_edit.gif diff --git a/site/vendors/css/jqGrid/sand/images/sort_asc.gif b/site/webroot/css/jqGrid/sand/images/sort_asc.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/sort_asc.gif rename to site/webroot/css/jqGrid/sand/images/sort_asc.gif diff --git a/site/vendors/css/jqGrid/sand/images/sort_desc.gif b/site/webroot/css/jqGrid/sand/images/sort_desc.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/sort_desc.gif rename to site/webroot/css/jqGrid/sand/images/sort_desc.gif diff --git a/site/vendors/css/jqGrid/sand/images/spacer.gif b/site/webroot/css/jqGrid/sand/images/spacer.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/spacer.gif rename to site/webroot/css/jqGrid/sand/images/spacer.gif diff --git a/site/vendors/css/jqGrid/sand/images/tab_close-on.gif b/site/webroot/css/jqGrid/sand/images/tab_close-on.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/tab_close-on.gif rename to site/webroot/css/jqGrid/sand/images/tab_close-on.gif diff --git a/site/vendors/css/jqGrid/sand/images/tree_leaf.gif b/site/webroot/css/jqGrid/sand/images/tree_leaf.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/tree_leaf.gif rename to site/webroot/css/jqGrid/sand/images/tree_leaf.gif diff --git a/site/vendors/css/jqGrid/sand/images/tree_minus.gif b/site/webroot/css/jqGrid/sand/images/tree_minus.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/tree_minus.gif rename to site/webroot/css/jqGrid/sand/images/tree_minus.gif diff --git a/site/vendors/css/jqGrid/sand/images/tree_plus.gif b/site/webroot/css/jqGrid/sand/images/tree_plus.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/tree_plus.gif rename to site/webroot/css/jqGrid/sand/images/tree_plus.gif diff --git a/site/vendors/css/jqGrid/sand/images/up.gif b/site/webroot/css/jqGrid/sand/images/up.gif similarity index 100% rename from site/vendors/css/jqGrid/sand/images/up.gif rename to site/webroot/css/jqGrid/sand/images/up.gif diff --git a/site/vendors/css/jqGrid/steel/grid.css b/site/webroot/css/jqGrid/steel/grid.css similarity index 100% rename from site/vendors/css/jqGrid/steel/grid.css rename to site/webroot/css/jqGrid/steel/grid.css diff --git a/site/vendors/css/jqGrid/steel/images/._sprite5.png b/site/webroot/css/jqGrid/steel/images/._sprite5.png similarity index 100% rename from site/vendors/css/jqGrid/steel/images/._sprite5.png rename to site/webroot/css/jqGrid/steel/images/._sprite5.png diff --git a/site/vendors/css/jqGrid/steel/images/._sprite5.psd b/site/webroot/css/jqGrid/steel/images/._sprite5.psd similarity index 100% rename from site/vendors/css/jqGrid/steel/images/._sprite5.psd rename to site/webroot/css/jqGrid/steel/images/._sprite5.psd diff --git a/site/vendors/css/jqGrid/steel/images/Arrow2 Down.png b/site/webroot/css/jqGrid/steel/images/Arrow2 Down.png similarity index 100% rename from site/vendors/css/jqGrid/steel/images/Arrow2 Down.png rename to site/webroot/css/jqGrid/steel/images/Arrow2 Down.png diff --git a/site/vendors/css/jqGrid/steel/images/Arrow2 Up.png b/site/webroot/css/jqGrid/steel/images/Arrow2 Up.png similarity index 100% rename from site/vendors/css/jqGrid/steel/images/Arrow2 Up.png rename to site/webroot/css/jqGrid/steel/images/Arrow2 Up.png diff --git a/site/vendors/css/jqGrid/steel/images/bg.gif b/site/webroot/css/jqGrid/steel/images/bg.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/bg.gif rename to site/webroot/css/jqGrid/steel/images/bg.gif diff --git a/site/vendors/css/jqGrid/steel/images/cd_run.gif b/site/webroot/css/jqGrid/steel/images/cd_run.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/cd_run.gif rename to site/webroot/css/jqGrid/steel/images/cd_run.gif diff --git a/site/vendors/css/jqGrid/steel/images/control_090.png b/site/webroot/css/jqGrid/steel/images/control_090.png similarity index 100% rename from site/vendors/css/jqGrid/steel/images/control_090.png rename to site/webroot/css/jqGrid/steel/images/control_090.png diff --git a/site/vendors/css/jqGrid/steel/images/control_270.png b/site/webroot/css/jqGrid/steel/images/control_270.png similarity index 100% rename from site/vendors/css/jqGrid/steel/images/control_270.png rename to site/webroot/css/jqGrid/steel/images/control_270.png diff --git a/site/vendors/css/jqGrid/steel/images/dirty.gif b/site/webroot/css/jqGrid/steel/images/dirty.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/dirty.gif rename to site/webroot/css/jqGrid/steel/images/dirty.gif diff --git a/site/vendors/css/jqGrid/steel/images/down.gif b/site/webroot/css/jqGrid/steel/images/down.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/down.gif rename to site/webroot/css/jqGrid/steel/images/down.gif diff --git a/site/vendors/css/jqGrid/steel/images/fhbg.gif b/site/webroot/css/jqGrid/steel/images/fhbg.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/fhbg.gif rename to site/webroot/css/jqGrid/steel/images/fhbg.gif diff --git a/site/vendors/css/jqGrid/steel/images/find.gif b/site/webroot/css/jqGrid/steel/images/find.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/find.gif rename to site/webroot/css/jqGrid/steel/images/find.gif diff --git a/site/vendors/css/jqGrid/steel/images/find1.gif b/site/webroot/css/jqGrid/steel/images/find1.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/find1.gif rename to site/webroot/css/jqGrid/steel/images/find1.gif diff --git a/site/vendors/css/jqGrid/steel/images/first.gif b/site/webroot/css/jqGrid/steel/images/first.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/first.gif rename to site/webroot/css/jqGrid/steel/images/first.gif diff --git a/site/vendors/css/jqGrid/steel/images/first.png b/site/webroot/css/jqGrid/steel/images/first.png similarity index 100% rename from site/vendors/css/jqGrid/steel/images/first.png rename to site/webroot/css/jqGrid/steel/images/first.png diff --git a/site/vendors/css/jqGrid/steel/images/folder.png b/site/webroot/css/jqGrid/steel/images/folder.png similarity index 100% rename from site/vendors/css/jqGrid/steel/images/folder.png rename to site/webroot/css/jqGrid/steel/images/folder.png diff --git a/site/vendors/css/jqGrid/steel/images/headerleft1.gif b/site/webroot/css/jqGrid/steel/images/headerleft1.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/headerleft1.gif rename to site/webroot/css/jqGrid/steel/images/headerleft1.gif diff --git a/site/vendors/css/jqGrid/steel/images/headerright1.gif b/site/webroot/css/jqGrid/steel/images/headerright1.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/headerright1.gif rename to site/webroot/css/jqGrid/steel/images/headerright1.gif diff --git a/site/vendors/css/jqGrid/steel/images/ico-close.gif b/site/webroot/css/jqGrid/steel/images/ico-close.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/ico-close.gif rename to site/webroot/css/jqGrid/steel/images/ico-close.gif diff --git a/site/vendors/css/jqGrid/steel/images/last.gif b/site/webroot/css/jqGrid/steel/images/last.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/last.gif rename to site/webroot/css/jqGrid/steel/images/last.gif diff --git a/site/vendors/css/jqGrid/steel/images/last.png b/site/webroot/css/jqGrid/steel/images/last.png similarity index 100% rename from site/vendors/css/jqGrid/steel/images/last.png rename to site/webroot/css/jqGrid/steel/images/last.png diff --git a/site/vendors/css/jqGrid/steel/images/line3.gif b/site/webroot/css/jqGrid/steel/images/line3.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/line3.gif rename to site/webroot/css/jqGrid/steel/images/line3.gif diff --git a/site/vendors/css/jqGrid/steel/images/loading.gif b/site/webroot/css/jqGrid/steel/images/loading.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/loading.gif rename to site/webroot/css/jqGrid/steel/images/loading.gif diff --git a/site/vendors/css/jqGrid/steel/images/minus.gif b/site/webroot/css/jqGrid/steel/images/minus.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/minus.gif rename to site/webroot/css/jqGrid/steel/images/minus.gif diff --git a/site/vendors/css/jqGrid/steel/images/next.gif b/site/webroot/css/jqGrid/steel/images/next.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/next.gif rename to site/webroot/css/jqGrid/steel/images/next.gif diff --git a/site/vendors/css/jqGrid/steel/images/next.png b/site/webroot/css/jqGrid/steel/images/next.png similarity index 100% rename from site/vendors/css/jqGrid/steel/images/next.png rename to site/webroot/css/jqGrid/steel/images/next.png diff --git a/site/vendors/css/jqGrid/steel/images/nochild.gif b/site/webroot/css/jqGrid/steel/images/nochild.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/nochild.gif rename to site/webroot/css/jqGrid/steel/images/nochild.gif diff --git a/site/vendors/css/jqGrid/steel/images/odown.gif b/site/webroot/css/jqGrid/steel/images/odown.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/odown.gif rename to site/webroot/css/jqGrid/steel/images/odown.gif diff --git a/site/vendors/css/jqGrid/steel/images/off-first.gif b/site/webroot/css/jqGrid/steel/images/off-first.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/off-first.gif rename to site/webroot/css/jqGrid/steel/images/off-first.gif diff --git a/site/vendors/css/jqGrid/steel/images/off-last.gif b/site/webroot/css/jqGrid/steel/images/off-last.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/off-last.gif rename to site/webroot/css/jqGrid/steel/images/off-last.gif diff --git a/site/vendors/css/jqGrid/steel/images/off-next.gif b/site/webroot/css/jqGrid/steel/images/off-next.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/off-next.gif rename to site/webroot/css/jqGrid/steel/images/off-next.gif diff --git a/site/vendors/css/jqGrid/steel/images/off-prev.gif b/site/webroot/css/jqGrid/steel/images/off-prev.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/off-prev.gif rename to site/webroot/css/jqGrid/steel/images/off-prev.gif diff --git a/site/vendors/css/jqGrid/steel/images/oup.gif b/site/webroot/css/jqGrid/steel/images/oup.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/oup.gif rename to site/webroot/css/jqGrid/steel/images/oup.gif diff --git a/site/vendors/css/jqGrid/steel/images/plus.gif b/site/webroot/css/jqGrid/steel/images/plus.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/plus.gif rename to site/webroot/css/jqGrid/steel/images/plus.gif diff --git a/site/vendors/css/jqGrid/steel/images/prev.gif b/site/webroot/css/jqGrid/steel/images/prev.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/prev.gif rename to site/webroot/css/jqGrid/steel/images/prev.gif diff --git a/site/vendors/css/jqGrid/steel/images/prev.png b/site/webroot/css/jqGrid/steel/images/prev.png similarity index 100% rename from site/vendors/css/jqGrid/steel/images/prev.png rename to site/webroot/css/jqGrid/steel/images/prev.png diff --git a/site/vendors/css/jqGrid/steel/images/refresh.gif b/site/webroot/css/jqGrid/steel/images/refresh.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/refresh.gif rename to site/webroot/css/jqGrid/steel/images/refresh.gif diff --git a/site/vendors/css/jqGrid/steel/images/refresh1.gif b/site/webroot/css/jqGrid/steel/images/refresh1.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/refresh1.gif rename to site/webroot/css/jqGrid/steel/images/refresh1.gif diff --git a/site/vendors/css/jqGrid/steel/images/resize.gif b/site/webroot/css/jqGrid/steel/images/resize.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/resize.gif rename to site/webroot/css/jqGrid/steel/images/resize.gif diff --git a/site/vendors/css/jqGrid/steel/images/row_add.gif b/site/webroot/css/jqGrid/steel/images/row_add.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/row_add.gif rename to site/webroot/css/jqGrid/steel/images/row_add.gif diff --git a/site/vendors/css/jqGrid/steel/images/row_add1.gif b/site/webroot/css/jqGrid/steel/images/row_add1.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/row_add1.gif rename to site/webroot/css/jqGrid/steel/images/row_add1.gif diff --git a/site/vendors/css/jqGrid/steel/images/row_delete.gif b/site/webroot/css/jqGrid/steel/images/row_delete.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/row_delete.gif rename to site/webroot/css/jqGrid/steel/images/row_delete.gif diff --git a/site/vendors/css/jqGrid/steel/images/row_delete1.gif b/site/webroot/css/jqGrid/steel/images/row_delete1.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/row_delete1.gif rename to site/webroot/css/jqGrid/steel/images/row_delete1.gif diff --git a/site/vendors/css/jqGrid/steel/images/row_edit.gif b/site/webroot/css/jqGrid/steel/images/row_edit.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/row_edit.gif rename to site/webroot/css/jqGrid/steel/images/row_edit.gif diff --git a/site/vendors/css/jqGrid/steel/images/row_edit1.gif b/site/webroot/css/jqGrid/steel/images/row_edit1.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/row_edit1.gif rename to site/webroot/css/jqGrid/steel/images/row_edit1.gif diff --git a/site/vendors/css/jqGrid/steel/images/sort_asc.gif b/site/webroot/css/jqGrid/steel/images/sort_asc.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/sort_asc.gif rename to site/webroot/css/jqGrid/steel/images/sort_asc.gif diff --git a/site/vendors/css/jqGrid/steel/images/sort_desc.gif b/site/webroot/css/jqGrid/steel/images/sort_desc.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/sort_desc.gif rename to site/webroot/css/jqGrid/steel/images/sort_desc.gif diff --git a/site/vendors/css/jqGrid/steel/images/spacer.gif b/site/webroot/css/jqGrid/steel/images/spacer.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/spacer.gif rename to site/webroot/css/jqGrid/steel/images/spacer.gif diff --git a/site/vendors/css/jqGrid/steel/images/sprite.png b/site/webroot/css/jqGrid/steel/images/sprite.png similarity index 100% rename from site/vendors/css/jqGrid/steel/images/sprite.png rename to site/webroot/css/jqGrid/steel/images/sprite.png diff --git a/site/vendors/css/jqGrid/steel/images/sprite5.png b/site/webroot/css/jqGrid/steel/images/sprite5.png similarity index 100% rename from site/vendors/css/jqGrid/steel/images/sprite5.png rename to site/webroot/css/jqGrid/steel/images/sprite5.png diff --git a/site/vendors/css/jqGrid/steel/images/sprite5.psd b/site/webroot/css/jqGrid/steel/images/sprite5.psd similarity index 100% rename from site/vendors/css/jqGrid/steel/images/sprite5.psd rename to site/webroot/css/jqGrid/steel/images/sprite5.psd diff --git a/site/vendors/css/jqGrid/steel/images/tab_close-on.gif b/site/webroot/css/jqGrid/steel/images/tab_close-on.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/tab_close-on.gif rename to site/webroot/css/jqGrid/steel/images/tab_close-on.gif diff --git a/site/vendors/css/jqGrid/steel/images/tree_leaf.gif b/site/webroot/css/jqGrid/steel/images/tree_leaf.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/tree_leaf.gif rename to site/webroot/css/jqGrid/steel/images/tree_leaf.gif diff --git a/site/vendors/css/jqGrid/steel/images/tree_minus.gif b/site/webroot/css/jqGrid/steel/images/tree_minus.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/tree_minus.gif rename to site/webroot/css/jqGrid/steel/images/tree_minus.gif diff --git a/site/vendors/css/jqGrid/steel/images/tree_plus.gif b/site/webroot/css/jqGrid/steel/images/tree_plus.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/tree_plus.gif rename to site/webroot/css/jqGrid/steel/images/tree_plus.gif diff --git a/site/vendors/css/jqGrid/steel/images/up.gif b/site/webroot/css/jqGrid/steel/images/up.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/up.gif rename to site/webroot/css/jqGrid/steel/images/up.gif diff --git a/site/vendors/css/jqGrid/steel/images/wbg.gif b/site/webroot/css/jqGrid/steel/images/wbg.gif similarity index 100% rename from site/vendors/css/jqGrid/steel/images/wbg.gif rename to site/webroot/css/jqGrid/steel/images/wbg.gif diff --git a/site/vendors/css/jquery/base/images/ui-bg_flat_0_aaaaaa_40x100.png b/site/webroot/css/jquery/base/images/ui-bg_flat_0_aaaaaa_40x100.png similarity index 100% rename from site/vendors/css/jquery/base/images/ui-bg_flat_0_aaaaaa_40x100.png rename to site/webroot/css/jquery/base/images/ui-bg_flat_0_aaaaaa_40x100.png diff --git a/site/vendors/css/jquery/base/images/ui-bg_flat_75_ffffff_40x100.png b/site/webroot/css/jquery/base/images/ui-bg_flat_75_ffffff_40x100.png similarity index 100% rename from site/vendors/css/jquery/base/images/ui-bg_flat_75_ffffff_40x100.png rename to site/webroot/css/jquery/base/images/ui-bg_flat_75_ffffff_40x100.png diff --git a/site/vendors/css/jquery/base/images/ui-bg_glass_55_fbf9ee_1x400.png b/site/webroot/css/jquery/base/images/ui-bg_glass_55_fbf9ee_1x400.png similarity index 100% rename from site/vendors/css/jquery/base/images/ui-bg_glass_55_fbf9ee_1x400.png rename to site/webroot/css/jquery/base/images/ui-bg_glass_55_fbf9ee_1x400.png diff --git a/site/vendors/css/jquery/base/images/ui-bg_glass_65_ffffff_1x400.png b/site/webroot/css/jquery/base/images/ui-bg_glass_65_ffffff_1x400.png similarity index 100% rename from site/vendors/css/jquery/base/images/ui-bg_glass_65_ffffff_1x400.png rename to site/webroot/css/jquery/base/images/ui-bg_glass_65_ffffff_1x400.png diff --git a/site/vendors/css/jquery/base/images/ui-bg_glass_75_dadada_1x400.png b/site/webroot/css/jquery/base/images/ui-bg_glass_75_dadada_1x400.png similarity index 100% rename from site/vendors/css/jquery/base/images/ui-bg_glass_75_dadada_1x400.png rename to site/webroot/css/jquery/base/images/ui-bg_glass_75_dadada_1x400.png diff --git a/site/vendors/css/jquery/base/images/ui-bg_glass_75_e6e6e6_1x400.png b/site/webroot/css/jquery/base/images/ui-bg_glass_75_e6e6e6_1x400.png similarity index 100% rename from site/vendors/css/jquery/base/images/ui-bg_glass_75_e6e6e6_1x400.png rename to site/webroot/css/jquery/base/images/ui-bg_glass_75_e6e6e6_1x400.png diff --git a/site/vendors/css/jquery/base/images/ui-bg_glass_75_ffffff_1x400.png b/site/webroot/css/jquery/base/images/ui-bg_glass_75_ffffff_1x400.png similarity index 100% rename from site/vendors/css/jquery/base/images/ui-bg_glass_75_ffffff_1x400.png rename to site/webroot/css/jquery/base/images/ui-bg_glass_75_ffffff_1x400.png diff --git a/site/vendors/css/jquery/base/images/ui-bg_glass_95_fef1ec_1x400.png b/site/webroot/css/jquery/base/images/ui-bg_glass_95_fef1ec_1x400.png similarity index 100% rename from site/vendors/css/jquery/base/images/ui-bg_glass_95_fef1ec_1x400.png rename to site/webroot/css/jquery/base/images/ui-bg_glass_95_fef1ec_1x400.png diff --git a/site/vendors/css/jquery/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/site/webroot/css/jquery/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png similarity index 100% rename from site/vendors/css/jquery/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png rename to site/webroot/css/jquery/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png diff --git a/site/vendors/css/jquery/base/images/ui-bg_inset-soft_95_fef1ec_1x100.png b/site/webroot/css/jquery/base/images/ui-bg_inset-soft_95_fef1ec_1x100.png similarity index 100% rename from site/vendors/css/jquery/base/images/ui-bg_inset-soft_95_fef1ec_1x100.png rename to site/webroot/css/jquery/base/images/ui-bg_inset-soft_95_fef1ec_1x100.png diff --git a/site/vendors/css/jquery/base/images/ui-icons_222222_256x240.png b/site/webroot/css/jquery/base/images/ui-icons_222222_256x240.png similarity index 100% rename from site/vendors/css/jquery/base/images/ui-icons_222222_256x240.png rename to site/webroot/css/jquery/base/images/ui-icons_222222_256x240.png diff --git a/site/vendors/css/jquery/base/images/ui-icons_2e83ff_256x240.png b/site/webroot/css/jquery/base/images/ui-icons_2e83ff_256x240.png similarity index 100% rename from site/vendors/css/jquery/base/images/ui-icons_2e83ff_256x240.png rename to site/webroot/css/jquery/base/images/ui-icons_2e83ff_256x240.png diff --git a/site/vendors/css/jquery/base/images/ui-icons_454545_256x240.png b/site/webroot/css/jquery/base/images/ui-icons_454545_256x240.png similarity index 100% rename from site/vendors/css/jquery/base/images/ui-icons_454545_256x240.png rename to site/webroot/css/jquery/base/images/ui-icons_454545_256x240.png diff --git a/site/vendors/css/jquery/base/images/ui-icons_888888_256x240.png b/site/webroot/css/jquery/base/images/ui-icons_888888_256x240.png similarity index 100% rename from site/vendors/css/jquery/base/images/ui-icons_888888_256x240.png rename to site/webroot/css/jquery/base/images/ui-icons_888888_256x240.png diff --git a/site/vendors/css/jquery/base/images/ui-icons_cd0a0a_256x240.png b/site/webroot/css/jquery/base/images/ui-icons_cd0a0a_256x240.png similarity index 100% rename from site/vendors/css/jquery/base/images/ui-icons_cd0a0a_256x240.png rename to site/webroot/css/jquery/base/images/ui-icons_cd0a0a_256x240.png diff --git a/site/vendors/css/jquery/base/ui.accordion.css b/site/webroot/css/jquery/base/ui.accordion.css similarity index 100% rename from site/vendors/css/jquery/base/ui.accordion.css rename to site/webroot/css/jquery/base/ui.accordion.css diff --git a/site/vendors/css/jquery/base/ui.all.css b/site/webroot/css/jquery/base/ui.all.css similarity index 100% rename from site/vendors/css/jquery/base/ui.all.css rename to site/webroot/css/jquery/base/ui.all.css diff --git a/site/vendors/css/jquery/base/ui.base.css b/site/webroot/css/jquery/base/ui.base.css similarity index 100% rename from site/vendors/css/jquery/base/ui.base.css rename to site/webroot/css/jquery/base/ui.base.css diff --git a/site/vendors/css/jquery/base/ui.core.css b/site/webroot/css/jquery/base/ui.core.css similarity index 100% rename from site/vendors/css/jquery/base/ui.core.css rename to site/webroot/css/jquery/base/ui.core.css diff --git a/site/vendors/css/jquery/base/ui.datepicker.css b/site/webroot/css/jquery/base/ui.datepicker.css similarity index 100% rename from site/vendors/css/jquery/base/ui.datepicker.css rename to site/webroot/css/jquery/base/ui.datepicker.css diff --git a/site/vendors/css/jquery/base/ui.dialog.css b/site/webroot/css/jquery/base/ui.dialog.css similarity index 100% rename from site/vendors/css/jquery/base/ui.dialog.css rename to site/webroot/css/jquery/base/ui.dialog.css diff --git a/site/vendors/css/jquery/base/ui.progressbar.css b/site/webroot/css/jquery/base/ui.progressbar.css similarity index 100% rename from site/vendors/css/jquery/base/ui.progressbar.css rename to site/webroot/css/jquery/base/ui.progressbar.css diff --git a/site/vendors/css/jquery/base/ui.resizable.css b/site/webroot/css/jquery/base/ui.resizable.css similarity index 100% rename from site/vendors/css/jquery/base/ui.resizable.css rename to site/webroot/css/jquery/base/ui.resizable.css diff --git a/site/vendors/css/jquery/base/ui.slider.css b/site/webroot/css/jquery/base/ui.slider.css similarity index 100% rename from site/vendors/css/jquery/base/ui.slider.css rename to site/webroot/css/jquery/base/ui.slider.css diff --git a/site/vendors/css/jquery/base/ui.tabs.css b/site/webroot/css/jquery/base/ui.tabs.css similarity index 100% rename from site/vendors/css/jquery/base/ui.tabs.css rename to site/webroot/css/jquery/base/ui.tabs.css diff --git a/site/vendors/css/jquery/base/ui.theme.css b/site/webroot/css/jquery/base/ui.theme.css similarity index 100% rename from site/vendors/css/jquery/base/ui.theme.css rename to site/webroot/css/jquery/base/ui.theme.css diff --git a/site/vendors/css/jquery/dotluv/images/ui-bg_diagonals-thick_15_0b3e6f_40x40.png b/site/webroot/css/jquery/dotluv/images/ui-bg_diagonals-thick_15_0b3e6f_40x40.png similarity index 100% rename from site/vendors/css/jquery/dotluv/images/ui-bg_diagonals-thick_15_0b3e6f_40x40.png rename to site/webroot/css/jquery/dotluv/images/ui-bg_diagonals-thick_15_0b3e6f_40x40.png diff --git a/site/vendors/css/jquery/dotluv/images/ui-bg_dots-medium_30_0b58a2_4x4.png b/site/webroot/css/jquery/dotluv/images/ui-bg_dots-medium_30_0b58a2_4x4.png similarity index 100% rename from site/vendors/css/jquery/dotluv/images/ui-bg_dots-medium_30_0b58a2_4x4.png rename to site/webroot/css/jquery/dotluv/images/ui-bg_dots-medium_30_0b58a2_4x4.png diff --git a/site/vendors/css/jquery/dotluv/images/ui-bg_dots-small_20_333333_2x2.png b/site/webroot/css/jquery/dotluv/images/ui-bg_dots-small_20_333333_2x2.png similarity index 100% rename from site/vendors/css/jquery/dotluv/images/ui-bg_dots-small_20_333333_2x2.png rename to site/webroot/css/jquery/dotluv/images/ui-bg_dots-small_20_333333_2x2.png diff --git a/site/vendors/css/jquery/dotluv/images/ui-bg_dots-small_30_a32d00_2x2.png b/site/webroot/css/jquery/dotluv/images/ui-bg_dots-small_30_a32d00_2x2.png similarity index 100% rename from site/vendors/css/jquery/dotluv/images/ui-bg_dots-small_30_a32d00_2x2.png rename to site/webroot/css/jquery/dotluv/images/ui-bg_dots-small_30_a32d00_2x2.png diff --git a/site/vendors/css/jquery/dotluv/images/ui-bg_dots-small_40_00498f_2x2.png b/site/webroot/css/jquery/dotluv/images/ui-bg_dots-small_40_00498f_2x2.png similarity index 100% rename from site/vendors/css/jquery/dotluv/images/ui-bg_dots-small_40_00498f_2x2.png rename to site/webroot/css/jquery/dotluv/images/ui-bg_dots-small_40_00498f_2x2.png diff --git a/site/vendors/css/jquery/dotluv/images/ui-bg_flat_0_aaaaaa_40x100.png b/site/webroot/css/jquery/dotluv/images/ui-bg_flat_0_aaaaaa_40x100.png similarity index 100% rename from site/vendors/css/jquery/dotluv/images/ui-bg_flat_0_aaaaaa_40x100.png rename to site/webroot/css/jquery/dotluv/images/ui-bg_flat_0_aaaaaa_40x100.png diff --git a/site/vendors/css/jquery/dotluv/images/ui-bg_flat_40_292929_40x100.png b/site/webroot/css/jquery/dotluv/images/ui-bg_flat_40_292929_40x100.png similarity index 100% rename from site/vendors/css/jquery/dotluv/images/ui-bg_flat_40_292929_40x100.png rename to site/webroot/css/jquery/dotluv/images/ui-bg_flat_40_292929_40x100.png diff --git a/site/vendors/css/jquery/dotluv/images/ui-bg_gloss-wave_20_111111_500x100.png b/site/webroot/css/jquery/dotluv/images/ui-bg_gloss-wave_20_111111_500x100.png similarity index 100% rename from site/vendors/css/jquery/dotluv/images/ui-bg_gloss-wave_20_111111_500x100.png rename to site/webroot/css/jquery/dotluv/images/ui-bg_gloss-wave_20_111111_500x100.png diff --git a/site/vendors/css/jquery/dotluv/images/ui-icons_00498f_256x240.png b/site/webroot/css/jquery/dotluv/images/ui-icons_00498f_256x240.png similarity index 100% rename from site/vendors/css/jquery/dotluv/images/ui-icons_00498f_256x240.png rename to site/webroot/css/jquery/dotluv/images/ui-icons_00498f_256x240.png diff --git a/site/vendors/css/jquery/dotluv/images/ui-icons_98d2fb_256x240.png b/site/webroot/css/jquery/dotluv/images/ui-icons_98d2fb_256x240.png similarity index 100% rename from site/vendors/css/jquery/dotluv/images/ui-icons_98d2fb_256x240.png rename to site/webroot/css/jquery/dotluv/images/ui-icons_98d2fb_256x240.png diff --git a/site/vendors/css/jquery/dotluv/images/ui-icons_9ccdfc_256x240.png b/site/webroot/css/jquery/dotluv/images/ui-icons_9ccdfc_256x240.png similarity index 100% rename from site/vendors/css/jquery/dotluv/images/ui-icons_9ccdfc_256x240.png rename to site/webroot/css/jquery/dotluv/images/ui-icons_9ccdfc_256x240.png diff --git a/site/vendors/css/jquery/dotluv/images/ui-icons_ffffff_256x240.png b/site/webroot/css/jquery/dotluv/images/ui-icons_ffffff_256x240.png similarity index 100% rename from site/vendors/css/jquery/dotluv/images/ui-icons_ffffff_256x240.png rename to site/webroot/css/jquery/dotluv/images/ui-icons_ffffff_256x240.png diff --git a/site/vendors/css/jquery/dotluv/ui.all.css b/site/webroot/css/jquery/dotluv/ui.all.css similarity index 100% rename from site/vendors/css/jquery/dotluv/ui.all.css rename to site/webroot/css/jquery/dotluv/ui.all.css diff --git a/site/vendors/css/jquery/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png b/site/webroot/css/jquery/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png similarity index 100% rename from site/vendors/css/jquery/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png rename to site/webroot/css/jquery/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png diff --git a/site/vendors/css/jquery/smoothness/images/ui-bg_flat_75_ffffff_40x100.png b/site/webroot/css/jquery/smoothness/images/ui-bg_flat_75_ffffff_40x100.png similarity index 100% rename from site/vendors/css/jquery/smoothness/images/ui-bg_flat_75_ffffff_40x100.png rename to site/webroot/css/jquery/smoothness/images/ui-bg_flat_75_ffffff_40x100.png diff --git a/site/vendors/css/jquery/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png b/site/webroot/css/jquery/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png similarity index 100% rename from site/vendors/css/jquery/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png rename to site/webroot/css/jquery/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png diff --git a/site/vendors/css/jquery/smoothness/images/ui-bg_glass_65_ffffff_1x400.png b/site/webroot/css/jquery/smoothness/images/ui-bg_glass_65_ffffff_1x400.png similarity index 100% rename from site/vendors/css/jquery/smoothness/images/ui-bg_glass_65_ffffff_1x400.png rename to site/webroot/css/jquery/smoothness/images/ui-bg_glass_65_ffffff_1x400.png diff --git a/site/vendors/css/jquery/smoothness/images/ui-bg_glass_75_dadada_1x400.png b/site/webroot/css/jquery/smoothness/images/ui-bg_glass_75_dadada_1x400.png similarity index 100% rename from site/vendors/css/jquery/smoothness/images/ui-bg_glass_75_dadada_1x400.png rename to site/webroot/css/jquery/smoothness/images/ui-bg_glass_75_dadada_1x400.png diff --git a/site/vendors/css/jquery/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png b/site/webroot/css/jquery/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png similarity index 100% rename from site/vendors/css/jquery/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png rename to site/webroot/css/jquery/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png diff --git a/site/vendors/css/jquery/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png b/site/webroot/css/jquery/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png similarity index 100% rename from site/vendors/css/jquery/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png rename to site/webroot/css/jquery/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png diff --git a/site/vendors/css/jquery/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/site/webroot/css/jquery/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png similarity index 100% rename from site/vendors/css/jquery/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png rename to site/webroot/css/jquery/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png diff --git a/site/vendors/css/jquery/smoothness/images/ui-icons_222222_256x240.png b/site/webroot/css/jquery/smoothness/images/ui-icons_222222_256x240.png similarity index 100% rename from site/vendors/css/jquery/smoothness/images/ui-icons_222222_256x240.png rename to site/webroot/css/jquery/smoothness/images/ui-icons_222222_256x240.png diff --git a/site/vendors/css/jquery/smoothness/images/ui-icons_2e83ff_256x240.png b/site/webroot/css/jquery/smoothness/images/ui-icons_2e83ff_256x240.png similarity index 100% rename from site/vendors/css/jquery/smoothness/images/ui-icons_2e83ff_256x240.png rename to site/webroot/css/jquery/smoothness/images/ui-icons_2e83ff_256x240.png diff --git a/site/vendors/css/jquery/smoothness/images/ui-icons_454545_256x240.png b/site/webroot/css/jquery/smoothness/images/ui-icons_454545_256x240.png similarity index 100% rename from site/vendors/css/jquery/smoothness/images/ui-icons_454545_256x240.png rename to site/webroot/css/jquery/smoothness/images/ui-icons_454545_256x240.png diff --git a/site/vendors/css/jquery/smoothness/images/ui-icons_888888_256x240.png b/site/webroot/css/jquery/smoothness/images/ui-icons_888888_256x240.png similarity index 100% rename from site/vendors/css/jquery/smoothness/images/ui-icons_888888_256x240.png rename to site/webroot/css/jquery/smoothness/images/ui-icons_888888_256x240.png diff --git a/site/vendors/css/jquery/smoothness/images/ui-icons_cd0a0a_256x240.png b/site/webroot/css/jquery/smoothness/images/ui-icons_cd0a0a_256x240.png similarity index 100% rename from site/vendors/css/jquery/smoothness/images/ui-icons_cd0a0a_256x240.png rename to site/webroot/css/jquery/smoothness/images/ui-icons_cd0a0a_256x240.png diff --git a/site/vendors/css/jquery/smoothness/ui.all.css b/site/webroot/css/jquery/smoothness/ui.all.css similarity index 100% rename from site/vendors/css/jquery/smoothness/ui.all.css rename to site/webroot/css/jquery/smoothness/ui.all.css diff --git a/site/vendors/css/jquery/start/images/ui-bg_flat_55_999999_40x100.png b/site/webroot/css/jquery/start/images/ui-bg_flat_55_999999_40x100.png similarity index 100% rename from site/vendors/css/jquery/start/images/ui-bg_flat_55_999999_40x100.png rename to site/webroot/css/jquery/start/images/ui-bg_flat_55_999999_40x100.png diff --git a/site/vendors/css/jquery/start/images/ui-bg_flat_75_aaaaaa_40x100.png b/site/webroot/css/jquery/start/images/ui-bg_flat_75_aaaaaa_40x100.png similarity index 100% rename from site/vendors/css/jquery/start/images/ui-bg_flat_75_aaaaaa_40x100.png rename to site/webroot/css/jquery/start/images/ui-bg_flat_75_aaaaaa_40x100.png diff --git a/site/vendors/css/jquery/start/images/ui-bg_glass_45_0078ae_1x400.png b/site/webroot/css/jquery/start/images/ui-bg_glass_45_0078ae_1x400.png similarity index 100% rename from site/vendors/css/jquery/start/images/ui-bg_glass_45_0078ae_1x400.png rename to site/webroot/css/jquery/start/images/ui-bg_glass_45_0078ae_1x400.png diff --git a/site/vendors/css/jquery/start/images/ui-bg_glass_55_f8da4e_1x400.png b/site/webroot/css/jquery/start/images/ui-bg_glass_55_f8da4e_1x400.png similarity index 100% rename from site/vendors/css/jquery/start/images/ui-bg_glass_55_f8da4e_1x400.png rename to site/webroot/css/jquery/start/images/ui-bg_glass_55_f8da4e_1x400.png diff --git a/site/vendors/css/jquery/start/images/ui-bg_glass_75_79c9ec_1x400.png b/site/webroot/css/jquery/start/images/ui-bg_glass_75_79c9ec_1x400.png similarity index 100% rename from site/vendors/css/jquery/start/images/ui-bg_glass_75_79c9ec_1x400.png rename to site/webroot/css/jquery/start/images/ui-bg_glass_75_79c9ec_1x400.png diff --git a/site/vendors/css/jquery/start/images/ui-bg_gloss-wave_45_e14f1c_500x100.png b/site/webroot/css/jquery/start/images/ui-bg_gloss-wave_45_e14f1c_500x100.png similarity index 100% rename from site/vendors/css/jquery/start/images/ui-bg_gloss-wave_45_e14f1c_500x100.png rename to site/webroot/css/jquery/start/images/ui-bg_gloss-wave_45_e14f1c_500x100.png diff --git a/site/vendors/css/jquery/start/images/ui-bg_gloss-wave_50_6eac2c_500x100.png b/site/webroot/css/jquery/start/images/ui-bg_gloss-wave_50_6eac2c_500x100.png similarity index 100% rename from site/vendors/css/jquery/start/images/ui-bg_gloss-wave_50_6eac2c_500x100.png rename to site/webroot/css/jquery/start/images/ui-bg_gloss-wave_50_6eac2c_500x100.png diff --git a/site/vendors/css/jquery/start/images/ui-bg_gloss-wave_75_2191c0_500x100.png b/site/webroot/css/jquery/start/images/ui-bg_gloss-wave_75_2191c0_500x100.png similarity index 100% rename from site/vendors/css/jquery/start/images/ui-bg_gloss-wave_75_2191c0_500x100.png rename to site/webroot/css/jquery/start/images/ui-bg_gloss-wave_75_2191c0_500x100.png diff --git a/site/vendors/css/jquery/start/images/ui-bg_inset-hard_100_fcfdfd_1x100.png b/site/webroot/css/jquery/start/images/ui-bg_inset-hard_100_fcfdfd_1x100.png similarity index 100% rename from site/vendors/css/jquery/start/images/ui-bg_inset-hard_100_fcfdfd_1x100.png rename to site/webroot/css/jquery/start/images/ui-bg_inset-hard_100_fcfdfd_1x100.png diff --git a/site/vendors/css/jquery/start/images/ui-icons_0078ae_256x240.png b/site/webroot/css/jquery/start/images/ui-icons_0078ae_256x240.png similarity index 100% rename from site/vendors/css/jquery/start/images/ui-icons_0078ae_256x240.png rename to site/webroot/css/jquery/start/images/ui-icons_0078ae_256x240.png diff --git a/site/vendors/css/jquery/start/images/ui-icons_056b93_256x240.png b/site/webroot/css/jquery/start/images/ui-icons_056b93_256x240.png similarity index 100% rename from site/vendors/css/jquery/start/images/ui-icons_056b93_256x240.png rename to site/webroot/css/jquery/start/images/ui-icons_056b93_256x240.png diff --git a/site/vendors/css/jquery/start/images/ui-icons_d8e7f3_256x240.png b/site/webroot/css/jquery/start/images/ui-icons_d8e7f3_256x240.png similarity index 100% rename from site/vendors/css/jquery/start/images/ui-icons_d8e7f3_256x240.png rename to site/webroot/css/jquery/start/images/ui-icons_d8e7f3_256x240.png diff --git a/site/vendors/css/jquery/start/images/ui-icons_e0fdff_256x240.png b/site/webroot/css/jquery/start/images/ui-icons_e0fdff_256x240.png similarity index 100% rename from site/vendors/css/jquery/start/images/ui-icons_e0fdff_256x240.png rename to site/webroot/css/jquery/start/images/ui-icons_e0fdff_256x240.png diff --git a/site/vendors/css/jquery/start/images/ui-icons_f5e175_256x240.png b/site/webroot/css/jquery/start/images/ui-icons_f5e175_256x240.png similarity index 100% rename from site/vendors/css/jquery/start/images/ui-icons_f5e175_256x240.png rename to site/webroot/css/jquery/start/images/ui-icons_f5e175_256x240.png diff --git a/site/vendors/css/jquery/start/images/ui-icons_f7a50d_256x240.png b/site/webroot/css/jquery/start/images/ui-icons_f7a50d_256x240.png similarity index 100% rename from site/vendors/css/jquery/start/images/ui-icons_f7a50d_256x240.png rename to site/webroot/css/jquery/start/images/ui-icons_f7a50d_256x240.png diff --git a/site/vendors/css/jquery/start/images/ui-icons_fcd113_256x240.png b/site/webroot/css/jquery/start/images/ui-icons_fcd113_256x240.png similarity index 100% rename from site/vendors/css/jquery/start/images/ui-icons_fcd113_256x240.png rename to site/webroot/css/jquery/start/images/ui-icons_fcd113_256x240.png diff --git a/site/vendors/css/jquery/start/ui.all.css b/site/webroot/css/jquery/start/ui.all.css similarity index 100% rename from site/vendors/css/jquery/start/ui.all.css rename to site/webroot/css/jquery/start/ui.all.css diff --git a/site/vendors/js/jqGrid/jquery.jqGrid.js b/site/webroot/js/jqGrid/jquery.jqGrid.js similarity index 100% rename from site/vendors/js/jqGrid/jquery.jqGrid.js rename to site/webroot/js/jqGrid/jquery.jqGrid.js diff --git a/site/vendors/js/jqGrid/js/JsonXml.js b/site/webroot/js/jqGrid/js/JsonXml.js similarity index 100% rename from site/vendors/js/jqGrid/js/JsonXml.js rename to site/webroot/js/jqGrid/js/JsonXml.js diff --git a/site/vendors/js/jqGrid/js/grid.base.js b/site/webroot/js/jqGrid/js/grid.base.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.base.js rename to site/webroot/js/jqGrid/js/grid.base.js diff --git a/site/vendors/js/jqGrid/js/grid.celledit.js b/site/webroot/js/jqGrid/js/grid.celledit.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.celledit.js rename to site/webroot/js/jqGrid/js/grid.celledit.js diff --git a/site/vendors/js/jqGrid/js/grid.common.js b/site/webroot/js/jqGrid/js/grid.common.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.common.js rename to site/webroot/js/jqGrid/js/grid.common.js diff --git a/site/vendors/js/jqGrid/js/grid.custom.js b/site/webroot/js/jqGrid/js/grid.custom.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.custom.js rename to site/webroot/js/jqGrid/js/grid.custom.js diff --git a/site/vendors/js/jqGrid/js/grid.formedit.js b/site/webroot/js/jqGrid/js/grid.formedit.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.formedit.js rename to site/webroot/js/jqGrid/js/grid.formedit.js diff --git a/site/vendors/js/jqGrid/js/grid.import.js b/site/webroot/js/jqGrid/js/grid.import.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.import.js rename to site/webroot/js/jqGrid/js/grid.import.js diff --git a/site/vendors/js/jqGrid/js/grid.inlinedit.js b/site/webroot/js/jqGrid/js/grid.inlinedit.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.inlinedit.js rename to site/webroot/js/jqGrid/js/grid.inlinedit.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-bg.js b/site/webroot/js/jqGrid/js/grid.locale-bg.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-bg.js rename to site/webroot/js/jqGrid/js/grid.locale-bg.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-bg1251.js b/site/webroot/js/jqGrid/js/grid.locale-bg1251.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-bg1251.js rename to site/webroot/js/jqGrid/js/grid.locale-bg1251.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-cat.js b/site/webroot/js/jqGrid/js/grid.locale-cat.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-cat.js rename to site/webroot/js/jqGrid/js/grid.locale-cat.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-cs.js b/site/webroot/js/jqGrid/js/grid.locale-cs.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-cs.js rename to site/webroot/js/jqGrid/js/grid.locale-cs.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-de.js b/site/webroot/js/jqGrid/js/grid.locale-de.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-de.js rename to site/webroot/js/jqGrid/js/grid.locale-de.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-dk.js b/site/webroot/js/jqGrid/js/grid.locale-dk.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-dk.js rename to site/webroot/js/jqGrid/js/grid.locale-dk.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-el.js b/site/webroot/js/jqGrid/js/grid.locale-el.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-el.js rename to site/webroot/js/jqGrid/js/grid.locale-el.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-en.js b/site/webroot/js/jqGrid/js/grid.locale-en.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-en.js rename to site/webroot/js/jqGrid/js/grid.locale-en.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-fa.js b/site/webroot/js/jqGrid/js/grid.locale-fa.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-fa.js rename to site/webroot/js/jqGrid/js/grid.locale-fa.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-fi.js b/site/webroot/js/jqGrid/js/grid.locale-fi.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-fi.js rename to site/webroot/js/jqGrid/js/grid.locale-fi.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-fr.js b/site/webroot/js/jqGrid/js/grid.locale-fr.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-fr.js rename to site/webroot/js/jqGrid/js/grid.locale-fr.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-is.js b/site/webroot/js/jqGrid/js/grid.locale-is.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-is.js rename to site/webroot/js/jqGrid/js/grid.locale-is.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-it.js b/site/webroot/js/jqGrid/js/grid.locale-it.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-it.js rename to site/webroot/js/jqGrid/js/grid.locale-it.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-jp.js b/site/webroot/js/jqGrid/js/grid.locale-jp.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-jp.js rename to site/webroot/js/jqGrid/js/grid.locale-jp.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-pl.js b/site/webroot/js/jqGrid/js/grid.locale-pl.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-pl.js rename to site/webroot/js/jqGrid/js/grid.locale-pl.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-pt-br.js b/site/webroot/js/jqGrid/js/grid.locale-pt-br.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-pt-br.js rename to site/webroot/js/jqGrid/js/grid.locale-pt-br.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-pt.js b/site/webroot/js/jqGrid/js/grid.locale-pt.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-pt.js rename to site/webroot/js/jqGrid/js/grid.locale-pt.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-ru.js b/site/webroot/js/jqGrid/js/grid.locale-ru.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-ru.js rename to site/webroot/js/jqGrid/js/grid.locale-ru.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-sp.js b/site/webroot/js/jqGrid/js/grid.locale-sp.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-sp.js rename to site/webroot/js/jqGrid/js/grid.locale-sp.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-sv.js b/site/webroot/js/jqGrid/js/grid.locale-sv.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-sv.js rename to site/webroot/js/jqGrid/js/grid.locale-sv.js diff --git a/site/vendors/js/jqGrid/js/grid.locale-tr.js b/site/webroot/js/jqGrid/js/grid.locale-tr.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.locale-tr.js rename to site/webroot/js/jqGrid/js/grid.locale-tr.js diff --git a/site/vendors/js/jqGrid/js/grid.postext.js b/site/webroot/js/jqGrid/js/grid.postext.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.postext.js rename to site/webroot/js/jqGrid/js/grid.postext.js diff --git a/site/vendors/js/jqGrid/js/grid.setcolumns.js b/site/webroot/js/jqGrid/js/grid.setcolumns.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.setcolumns.js rename to site/webroot/js/jqGrid/js/grid.setcolumns.js diff --git a/site/vendors/js/jqGrid/js/grid.subgrid.js b/site/webroot/js/jqGrid/js/grid.subgrid.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.subgrid.js rename to site/webroot/js/jqGrid/js/grid.subgrid.js diff --git a/site/vendors/js/jqGrid/js/grid.tbltogrid.js b/site/webroot/js/jqGrid/js/grid.tbltogrid.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.tbltogrid.js rename to site/webroot/js/jqGrid/js/grid.tbltogrid.js diff --git a/site/vendors/js/jqGrid/js/grid.treegrid.js b/site/webroot/js/jqGrid/js/grid.treegrid.js similarity index 100% rename from site/vendors/js/jqGrid/js/grid.treegrid.js rename to site/webroot/js/jqGrid/js/grid.treegrid.js diff --git a/site/vendors/js/jqGrid/js/jqDnR.js b/site/webroot/js/jqGrid/js/jqDnR.js similarity index 100% rename from site/vendors/js/jqGrid/js/jqDnR.js rename to site/webroot/js/jqGrid/js/jqDnR.js diff --git a/site/vendors/js/jqGrid/js/jqModal.js b/site/webroot/js/jqGrid/js/jqModal.js similarity index 100% rename from site/vendors/js/jqGrid/js/jqModal.js rename to site/webroot/js/jqGrid/js/jqModal.js diff --git a/site/vendors/js/jqGrid/js/jquery.fmatter.js b/site/webroot/js/jqGrid/js/jquery.fmatter.js similarity index 100% rename from site/vendors/js/jqGrid/js/jquery.fmatter.js rename to site/webroot/js/jqGrid/js/jquery.fmatter.js diff --git a/site/vendors/js/jqGrid/js/jquery.tablednd.js b/site/webroot/js/jqGrid/js/jquery.tablednd.js similarity index 100% rename from site/vendors/js/jqGrid/js/jquery.tablednd.js rename to site/webroot/js/jqGrid/js/jquery.tablednd.js diff --git a/site/vendors/js/jqGrid/js/json2.js b/site/webroot/js/jqGrid/js/json2.js similarity index 100% rename from site/vendors/js/jqGrid/js/json2.js rename to site/webroot/js/jqGrid/js/json2.js diff --git a/site/vendors/js/jqGrid/js/min/JsonXml-min.js b/site/webroot/js/jqGrid/js/min/JsonXml-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/JsonXml-min.js rename to site/webroot/js/jqGrid/js/min/JsonXml-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.base-min.js b/site/webroot/js/jqGrid/js/min/grid.base-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.base-min.js rename to site/webroot/js/jqGrid/js/min/grid.base-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.celledit-min.js b/site/webroot/js/jqGrid/js/min/grid.celledit-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.celledit-min.js rename to site/webroot/js/jqGrid/js/min/grid.celledit-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.common-min.js b/site/webroot/js/jqGrid/js/min/grid.common-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.common-min.js rename to site/webroot/js/jqGrid/js/min/grid.common-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.custom-min.js b/site/webroot/js/jqGrid/js/min/grid.custom-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.custom-min.js rename to site/webroot/js/jqGrid/js/min/grid.custom-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.formedit-min.js b/site/webroot/js/jqGrid/js/min/grid.formedit-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.formedit-min.js rename to site/webroot/js/jqGrid/js/min/grid.formedit-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.import-min.js b/site/webroot/js/jqGrid/js/min/grid.import-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.import-min.js rename to site/webroot/js/jqGrid/js/min/grid.import-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.inlinedit-min.js b/site/webroot/js/jqGrid/js/min/grid.inlinedit-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.inlinedit-min.js rename to site/webroot/js/jqGrid/js/min/grid.inlinedit-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-bg-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-bg-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-bg-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-bg-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-bg1251-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-bg1251-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-bg1251-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-bg1251-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-cat-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-cat-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-cat-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-cat-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-cs-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-cs-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-cs-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-cs-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-de-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-de-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-de-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-de-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-dk-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-dk-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-dk-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-dk-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-el-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-el-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-el-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-el-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-en-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-en-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-en-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-en-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-fi-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-fi-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-fi-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-fi-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-fr-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-fr-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-fr-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-fr-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-is-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-is-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-is-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-is-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-it-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-it-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-it-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-it-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-jp-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-jp-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-jp-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-jp-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-pl-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-pl-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-pl-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-pl-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-pt-br-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-pt-br-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-pt-br-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-pt-br-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-pt-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-pt-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-pt-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-pt-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-ru-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-ru-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-ru-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-ru-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-sp-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-sp-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-sp-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-sp-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.locale-tr-min.js b/site/webroot/js/jqGrid/js/min/grid.locale-tr-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.locale-tr-min.js rename to site/webroot/js/jqGrid/js/min/grid.locale-tr-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.postext-min.js b/site/webroot/js/jqGrid/js/min/grid.postext-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.postext-min.js rename to site/webroot/js/jqGrid/js/min/grid.postext-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.setcolumns-min.js b/site/webroot/js/jqGrid/js/min/grid.setcolumns-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.setcolumns-min.js rename to site/webroot/js/jqGrid/js/min/grid.setcolumns-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.subgrid-min.js b/site/webroot/js/jqGrid/js/min/grid.subgrid-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.subgrid-min.js rename to site/webroot/js/jqGrid/js/min/grid.subgrid-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.tbltogrid-min.js b/site/webroot/js/jqGrid/js/min/grid.tbltogrid-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.tbltogrid-min.js rename to site/webroot/js/jqGrid/js/min/grid.tbltogrid-min.js diff --git a/site/vendors/js/jqGrid/js/min/grid.treegrid-min.js b/site/webroot/js/jqGrid/js/min/grid.treegrid-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/grid.treegrid-min.js rename to site/webroot/js/jqGrid/js/min/grid.treegrid-min.js diff --git a/site/vendors/js/jqGrid/js/min/jqDnR-min.js b/site/webroot/js/jqGrid/js/min/jqDnR-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/jqDnR-min.js rename to site/webroot/js/jqGrid/js/min/jqDnR-min.js diff --git a/site/vendors/js/jqGrid/js/min/jqModal-min.js b/site/webroot/js/jqGrid/js/min/jqModal-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/jqModal-min.js rename to site/webroot/js/jqGrid/js/min/jqModal-min.js diff --git a/site/vendors/js/jqGrid/js/min/jquery.fmatter-min.js b/site/webroot/js/jqGrid/js/min/jquery.fmatter-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/jquery.fmatter-min.js rename to site/webroot/js/jqGrid/js/min/jquery.fmatter-min.js diff --git a/site/vendors/js/jqGrid/js/min/jquery.tablednd-min.js b/site/webroot/js/jqGrid/js/min/jquery.tablednd-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/jquery.tablednd-min.js rename to site/webroot/js/jqGrid/js/min/jquery.tablednd-min.js diff --git a/site/vendors/js/jqGrid/js/min/json2-min.js b/site/webroot/js/jqGrid/js/min/json2-min.js similarity index 100% rename from site/vendors/js/jqGrid/js/min/json2-min.js rename to site/webroot/js/jqGrid/js/min/json2-min.js diff --git a/site/vendors/js/jquery.form.js b/site/webroot/js/jquery.form.js similarity index 100% rename from site/vendors/js/jquery.form.js rename to site/webroot/js/jquery.form.js diff --git a/site/vendors/js/jquery/jquery-ui.js b/site/webroot/js/jquery/jquery-ui.js similarity index 100% rename from site/vendors/js/jquery/jquery-ui.js rename to site/webroot/js/jquery/jquery-ui.js diff --git a/site/vendors/js/jquery/jquery.js b/site/webroot/js/jquery/jquery.js similarity index 100% rename from site/vendors/js/jquery/jquery.js rename to site/webroot/js/jquery/jquery.js From 90a16c721eed06714d21eb5492734627426efc02 Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 14 Jun 2009 00:53:08 +0000 Subject: [PATCH 110/717] Split the jqGrid code out a bit further, giving the application controller full responsibility for handling the jqGrid requests. Virtual functions have been added to allow a derived controller to customize this action as needed. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@111 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 196 +++++++++++++++------- site/controllers/customers_controller.php | 84 +++++++--- 2 files changed, 193 insertions(+), 87 deletions(-) diff --git a/site/app_controller.php b/site/app_controller.php index 2e4c7af..2826944 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -63,17 +63,75 @@ class AppController extends Controller { * - Fetches the actual data requested by jqGrid as XML */ - function jqGridData($model, $records, $query) { + function jqGridData() { + // 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->jqGridDataSetup($params); + + // Get the top level model for this grid + $model = $this->jqGridDataModel($params); + + // Establish the basic query and conditions + $query = array_intersect_key($this->jqGridDataTables($params), + array('link'=>1, 'contain'=>1)); + $query['conditions'] = $this->jqGridDataConditions($params); + + // Get the number of records prior to pagination + $count = $this->jqGridDataRecordCount($params, $model, $query); + + // Verify a few parameters and determine our starting row + $limit = $params['rows']; + $total = ($count < 0) ? 0 : ceil($count/$limit); + $page = ($params['page'] <= 1) ? 1 : (($params['page'] > $total) ? $total : $params['page']); + $start = $limit*$page - $limit; + $sidx = isset($params['sidx']) ? $params['sidx'] : ''; + $sord = isset($params['sord']) ? ' ' . $params['sord'] : ''; + + // Grab the actual records taking pagination into account + $query['group'] = $model->alias . '.id'; + $query['order'] = $sidx ? $sidx . $sord : null; + $query['limit'] = $start . ', ' . $limit; + $query['fields'] = $this->jqGridDataFields($params); + $results = $this->jqGridDataRecords($params, $model, $query); + + // DEBUG PURPOSES ONLY + $params['query'] = $query; + + // Finally, dump out the data + $this->jqGridDataOutputHeader($params); + echo "\n"; + echo "\n"; + $this->jqGridDataOutputSummary($params, $page, $total, $count); + $this->jqGridDataOutputRecords($params, $model, $results); + echo "\n"; + + // Call out to finalize everything + $this->jqGridDataFinalize($params); + } + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * virtual: jqGridData* functions + * - These set up the context for the jqGrid data, and will + * need to be overridden in the derived class for anything + * other than the most basic of grids. + */ + + function jqGridDataSetup(&$params) { // Assume we're debugging. // The actual jqGrid request will set this to false $debug = true; - $model_alias = $model->alias; - $model_id = $model_alias . '.id'; - if (isset($this->passedArgs['debug'])) $debug = $this->passedArgs['debug']; + $params['debug'] = $debug; + if (!$debug) { $this->layout = null; $this->autoLayout = false; @@ -81,80 +139,96 @@ class AppController extends Controller { Configure::write('debug', '0'); } - // Set up some defaults - $page = 1; // page number - $rows = 20; // rows in the grid - rowNum parameter - $sidx = $model_id; // sort column - index from colModel - $sord = 'ASC'; // sort order - - // Extract the actual settings from the jqGrid request - if (isset($this->params['url']) && is_array($this->params['url'])) - extract($this->params['url']); - // Unserialize our complex structure of fields // This SHOULD be always set, except when debugging - if (isset($fields)) - $fields = unserialize($fields); + if (isset($params['fields'])) + $fields = unserialize($params['fields']); else - $fields = array($model_id); + $fields = array($this->modelClass . '.id'); - if (isset($_search) && $_search === 'true') { - $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' => '%'), - ); + $params['fields_str'] = $params['fields']; + $params['fields'] = $fields; - $op = $ops[$searchOper]; - $field = $searchField . ($op['op'] ? ' '.$op['op'] : ''); - $val = $op['pre'] . $searchString . $op['post']; - $query['conditions'][] = array($field => $val); - } + // Establish some defaults before extracting params + $params = array_merge(array('page' => 1, + 'rows' => 20), + $params); + } - // Verify a few parameters and determine our starting row - $total = ($records < 0) ? 0 : ceil($records/$rows); - $page = ($page < 1) ? 1 : (($page > $total) ? $total : $page); - $start = $rows*$page - $rows; + function jqGridDataModel(&$params) { + return $this->{$this->modelClass}; + } - // the actual query for the grid data - $query['group'] = $model_id; - $query['order'] = "$sidx $sord"; - $query['limit'] = "$start, $rows"; - $results = $model->find('all', $query); + function jqGridDataTables(&$params) { + return array('contain' => false); + } - if ($debug) { + function jqGridDataConditions(&$params) { + if (!isset($params['_search']) || $params['_search'] !== 'true') + return array(); + + $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' => '%'), + ); + + $op = $ops[$params['searchOper']]; + $field = $params['searchField'] . ($op['op'] ? ' '.$op['op'] : ''); + $val = $op['pre'] . $params['searchString'] . $op['post']; + return array($field => $val); + } + + function jqGridDataFields(&$params) { + return null; + } + + function jqGridDataRecordCount(&$params, $model, $query) { + return $model->find('count', $query); + } + + function jqGridDataRecords(&$params, $model, $query) { + return $model->find('all', $query); + } + + function jqGridDataOutputHeader(&$params) { + if ($params['debug']) { ob_start(); - print_r(compact('records', 'rows', 'total', 'page', 'start')); } else { header("Content-type: text/xml;charset=utf-8"); } + } - echo "\n"; - echo "\n"; -/* echo " params['url'], true) . "\n]]>\n"; */ -/* echo " \n"; */ + function jqGridDataOutputSummary(&$params, $page, $total, $records) { + echo " \n"; echo " $page\n"; echo " $total\n"; echo " $records\n"; + } - foreach ($results AS $result) { + function jqGridDataOutputRecords(&$params, $model, $records) { + $model_alias = $model->alias; + + foreach ($records AS $record) { // Add the calculated fields (if any), to the model fields - if (isset($result[0])) - $result[$model_alias] += $result[0]; + if (isset($record[0])) + $record[$model_alias] += $record[0]; - echo " \n"; - foreach ($fields AS $field) { - list($tbl, $col) = explode(".", $field); - if (isset($col)) - $data = $result[$tbl][$col]; - else - $data = $result[$model_alias][$tbl]; + echo " \n"; + foreach ($params['fields'] AS $field) { + if (preg_match("/\./", $field)) { + list($tbl, $col) = explode(".", $field); + $data = $record[$tbl][$col]; + } + else { + $data = $record[$model_alias][$field]; + } // be sure to put text data in CDATA if (preg_match("/^\d*$/", $data)) @@ -164,9 +238,10 @@ class AppController extends Controller { } echo " \n"; } - echo "\n"; + } - if ($debug) { + function jqGridDataFinalize(&$params) { + if ($params['debug']) { $xml = ob_get_contents(); ob_end_clean(); @@ -177,6 +252,5 @@ class AppController extends Controller { echo ("\n
    \n$xml\n
    \n"); } } - } ?> \ No newline at end of file diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 1fb6d3f..288018e 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -46,45 +46,77 @@ class CustomersController extends AppController { /************************************************************************** ************************************************************************** ************************************************************************** - * action: jqGridData - * - Fetches the actual data requested by jqGrid as XML + * virtuals: jqGridData + * - With the application controller handling the jqGridData action, + * these virutal functions ensure that the correct data is passed + * to jqGrid. */ - function jqGridData() { + function jqGridDataSetup(&$params) { + parent::jqGridDataSetup($params); + if (!isset($params['action'])) + $params['action'] = 'all'; + } - $action = 'all'; - if (isset($this->params['url']['action'])) - $action = $this->params['url']['action']; - - // Set up the basic query - $query = array + function jqGridDataTables(&$params) { + return array ('link' => array(// Models 'PrimaryContact', 'CurrentLease' => array('fields' => array()), ), - 'fields' => 'Customer.*, COUNT(CurrentLease.id) AS lease_count', ); + } - // Calculate the number of rows for the query, and figure out - // any special query conditions that will be necessary - $records = $this->Customer->find('count', array('contain'=>false)); - if ($action != 'all') { - $records_past = $this->Customer->find('count', - array('link' => array('CurrentLease' => array('fields' => array())), - 'conditions' => 'CurrentLease.id IS NULL')); + function jqGridDataFields(&$params) { + return array('Customer.*', + 'COUNT(CurrentLease.id) AS lease_count'); + } - if ($action == 'current') { - $records = $records - $records_past; - $query['conditions'][] = 'CurrentLease.id IS NOT NULL'; - } - elseif ($action == 'past') { - $records = $records_past; - $query['conditions'][] = 'CurrentLease.id IS NULL'; - } + function jqGridDataConditions(&$params) { + $conditions = parent::jqGridDataConditions($params); + + if ($params['action'] === 'current') { + $conditions[] = 'CurrentLease.id IS NOT NULL'; + } + elseif ($params['action'] === 'past') { + $conditions[] = 'CurrentLease.id IS NULL'; } - parent::jqGridData($this->Customer, $records, $query); + return $conditions; + } + + function jqGridDataRecordCount(&$params, $model, $query) { + + // We don't have a good way to use the query to obtain + // our count. The problem is that we're relying on the + // group by for the query, which will destroy the count, + // whether we omit the group by or leave it in. + // So, build a fresh query for counting. + + $query['conditions'] = parent::jqGridDataConditions($params); + + $count = $model->find('count', + array_merge(array('link' => array_diff_key($query['link'], + array('CurrentLease'=>1))), + array_diff_key($query, array('link'=>1)))); + + if ($params['action'] === 'all') + return $count; + + $query['conditions'][] = 'CurrentLease.id IS NULL'; + $count_past = $model->find('count', $query); + + // Since we can't easily count 'current' directly, we + // can quickly derive it since 'current' customers + // are mutually exclusive to 'past' customers. + if ($params['action'] == 'current') + $count = $count - $count_past; + elseif ($params['action'] == 'past') { + $count = $count_past; + } + + return $count; } From b4d640f7c244641ee34132d308fbb6434d984c07 Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 14 Jun 2009 01:27:58 +0000 Subject: [PATCH 111/717] Testing implementation of an autosearch functionality, which works. Probably wasted, as I suspect I can get this directly out of jqGrid git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@112 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 21 ++++++++++---- site/views/elements/customers.ctp | 46 +++++++++++++++++++++++++------ 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/site/app_controller.php b/site/app_controller.php index 2826944..72d6d8f 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -164,8 +164,19 @@ class AppController extends Controller { } function jqGridDataConditions(&$params) { - if (!isset($params['_search']) || $params['_search'] !== 'true') + if (isset($params['_search']) && $params['_search'] === 'true') { + $op = $params['searchOper']; + $field = $params['searchField']; + $string = $params['searchString']; + } + elseif (isset($params['filt']) && $params['filt']) { + $op = 'bw'; + $field = $params['filtField']; + $string = $params['filtString']; + } + else { return array(); + } $ops = array('eq' => array('op' => null, 'pre' => '', 'post' => ''), 'ne' => array('op' => '<>', 'pre' => '', 'post' => ''), @@ -178,10 +189,10 @@ class AppController extends Controller { 'cn' => array('op' => 'LIKE', 'pre' => '%', 'post' => '%'), ); - $op = $ops[$params['searchOper']]; - $field = $params['searchField'] . ($op['op'] ? ' '.$op['op'] : ''); - $val = $op['pre'] . $params['searchString'] . $op['post']; - return array($field => $val); + $op = $ops[$op]; + $field .= $op['op'] ? ' '.$op['op'] : ''; + $string = $op['pre'] . $string . $op['post']; + return array($field => $string); } function jqGridDataFields(&$params) { diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index 46f9dc3..341c4d7 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -99,15 +99,45 @@ jQuery(document).ready(function(){
    - - +
    Search By:
    +
    +Enable Autosearch +
    +
    Last Name
    + + +
    + Get Table Code
    */ From 336ec3b643dac36f4c30c778388ec00c618bbe42 Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 14 Jun 2009 03:22:53 +0000 Subject: [PATCH 112/717] Got the mulitcolumn search toolbar in place, but it's not working. First I haven't managed to get an autosearch working (searching as you type). Second, and much more critically, I don't have the controller correctly responding to search terms, as it was implemented rather poorly. I'm moving on for now. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@113 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 35 +++++++++++++------ site/views/elements/customers.ctp | 57 ++++++++++++++++++++----------- 2 files changed, 63 insertions(+), 29 deletions(-) diff --git a/site/app_controller.php b/site/app_controller.php index 72d6d8f..7f03fd3 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -164,15 +164,25 @@ class AppController extends Controller { } function jqGridDataConditions(&$params) { + $searches = array(); + if (isset($params['_search']) && $params['_search'] === 'true') { - $op = $params['searchOper']; - $field = $params['searchField']; - $string = $params['searchString']; + 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']) { - $op = 'bw'; - $field = $params['filtField']; - $string = $params['filtString']; + $searches[] = array('op' => 'bw', + 'field' => $params['filtField'], + 'value' => $params['filtString']); } else { return array(); @@ -189,10 +199,15 @@ class AppController extends Controller { 'cn' => array('op' => 'LIKE', 'pre' => '%', 'post' => '%'), ); - $op = $ops[$op]; - $field .= $op['op'] ? ' '.$op['op'] : ''; - $string = $op['pre'] . $string . $op['post']; - return array($field => $string); + $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); + } + + return $conditions; } function jqGridDataFields(&$params) { diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index 341c4d7..f71d590 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -35,6 +35,10 @@ $cols['Comment'] = array('index' => 'Customer.comment', 'width' => foreach (array_intersect_key($cols, array('Comment'=>1)) AS $k => $v) $cols[$k]['sortable'] = false; +// Some of the columns should be searchable +foreach (array_intersect_key($cols, array('Last Name'=>1, 'First Name'=>1)) AS $k => $v) + $cols[$k]['search'] = true; + // Create the javascript code for jqGrid to create each table column $colModels = array(); foreach ($cols AS $col) { @@ -43,7 +47,7 @@ foreach ($cols AS $col) { '{ ' . implode(", ", array_map(create_function ('$k, $v', - 'return "$k:".($v===false?"false":"\'$v\'");'), + 'return "$k:".($v===false?"false":($v===true?"true":"\'$v\'"));'), array_keys($col), array_values($col))) . '}'; @@ -70,8 +74,8 @@ $url = $html->url(array('controller' => 'customers', ?> -
    -
    -
    Search By:
    -
    -Enable Autosearch -
    -
    Last Name
    +
    Search By:
    +Enable Autosearch
    +Last Name
    @@ -139,13 +168,3 @@ function gridReload() { --> -Get Table Code
    */ -/*
    */ - -/*

    */ -/*
    */ -/* Show Loading
    */ -/* Set Top Margin
    */ -/* Set Left Margin
    */ -?> \ No newline at end of file From 6b8d05f2a01700dd35344fce94b427e31eb15cba Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 14 Jun 2009 04:40:47 +0000 Subject: [PATCH 113/717] Yanked the multicolumn toolbar, and returned to my simple text boxes. I will probably end up going with these search boxes, or the modal box (perhaps with autosearch) if I can't come up with a better idea. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@114 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 2 +- site/views/elements/customers.ctp | 143 ++++++++++++++++++++---------- 2 files changed, 97 insertions(+), 48 deletions(-) diff --git a/site/app_controller.php b/site/app_controller.php index 7f03fd3..7af38ef 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -182,7 +182,7 @@ class AppController extends Controller { elseif (isset($params['filt']) && $params['filt']) { $searches[] = array('op' => 'bw', 'field' => $params['filtField'], - 'value' => $params['filtString']); + 'value' => $params['filtValue']); } else { return array(); diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index f71d590..c3f501e 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -93,35 +93,35 @@ jQuery(document).ready(function(){ viewrecords: true, imgpath: '', caption: , - toolbar : [true,"bottom"], +/* toolbar : [true,"bottom"], */ }); - jQuery("#t_customer-list").height(25).hide() - .filterGrid("#customer-list", { - gridModel:true, - gridToolbar:true, - autosearch:true, - }); +/* jQuery("#t_customer-list").height(25).hide() */ +/* .filterGrid("#customer-list", { */ +/* gridModel:true, */ +/* gridToolbar:true, */ +/* autosearch:true, */ +/* }); */ - jQuery("#customer-list").navGrid('#customer-pager', - { view:false, - edit:false, - add:false, - del:false, - search:false, - refresh:false}) - .navButtonAdd("#customer-pager",{ - caption:"Search", - title:"Toggle Search", - buttonimg:'' + '/find.gif', - onClickButton:function(){ - if(jQuery("#t_customer-list").css("display")=="none") { - jQuery("#t_customer-list").css("display",""); - } else { - jQuery("#t_customer-list").css("display","none"); - } - } - }); +/* jQuery("#customer-list").navGrid('#customer-pager', */ +/* { view:false, */ +/* edit:false, */ +/* add:false, */ +/* del:false, */ +/* search:false, */ +/* refresh:false}) */ +/* .navButtonAdd("#customer-pager",{ */ +/* caption:"Search", */ +/* title:"Toggle Search", */ +/* buttonimg:'' + '/find.gif', */ +/* onClickButton:function(){ */ +/* if(jQuery("#t_customer-list").css("display")=="none") { */ +/* jQuery("#t_customer-list").css("display",""); */ +/* } else { */ +/* jQuery("#t_customer-list").css("display","none"); */ +/* } */ +/* } */ +/* }); */ }); @@ -132,39 +132,88 @@ jQuery(document).ready(function(){

    Search By:
    Enable Autosearch
    + Last Name
    - - + +
    + +First Name
    + +
    + +
    +
    +
    + +
    + From af2d5c38f37becfc2bef6c6139ab20de65840eeb Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 14 Jun 2009 05:04:41 +0000 Subject: [PATCH 114/717] Moved all the jqGrid logic into a separate element, in anticipation of moving all lists to jqGrid git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@115 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/customers.ctp | 182 +------------------------- site/views/elements/jqGrid.ctp | 210 ++++++++++++++++++++++++++++++ 2 files changed, 213 insertions(+), 179 deletions(-) create mode 100644 site/views/elements/jqGrid.ctp diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index c3f501e..faeb05a 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -1,25 +1,5 @@ '.$this->pageTitle.''; - -if (!isset($limit)) - $limit = 20; - -if (!isset($limitOptions)) - $limitOptions = array(10, 20, 50, 200); - -if (!isset($height)) - $height = 'auto'; - -// Do some prework to bring in the appropriate libraries -$imgpath = '/pmgr/site/css/jqGrid/basic/images'; -$html->css('jqGrid/basic/grid', null, null, false); -$html->css('jqGrid/jqModal', null, null, false); -$javascript->link('jqGrid/jquery.jqGrid.js', false); -$javascript->link('jqGrid/js/jqModal', false); -$javascript->link('jqGrid/js/jqDnR', false); - // Define the table columns $cols = array(); $cols['ID'] = array('index' => 'Customer.id', 'width' => '30', 'align' => 'center'); @@ -39,99 +19,13 @@ foreach (array_intersect_key($cols, array('Comment'=>1)) AS $k => $v) foreach (array_intersect_key($cols, array('Last Name'=>1, 'First Name'=>1)) AS $k => $v) $cols[$k]['search'] = true; -// Create the javascript code for jqGrid to create each table column -$colModels = array(); -foreach ($cols AS $col) { - $col['name'] = $col['index']; - $colModels[] = - '{ ' . implode(", ", - array_map(create_function - ('$k, $v', - 'return "$k:".($v===false?"false":($v===true?"true":"\'$v\'"));'), - array_keys($col), - array_values($col))) . - '}'; -} +echo $this->element('jqGrid', + array('jqGridColumns' => $cols)); -// Save just the column indices (fields) -$colFields= array_map(create_function('$col', 'return $col["index"];'), $cols); - -// Define the URL to fetch data from. -// To prevent having to keep the controller and the view -// in sync on which fields need to be queried by the -// controller in order to be accessible to the view, -// we'll just pass the desired fields to the controller -// as part of the data fetch. - -$url = $html->url(array('controller' => 'customers', - 'action' => 'jqGridData', - 'debug' => 0, - )); - -// OK, now that everything is in place, get out of PHP mode, -// and add the javascript code (along with a touch of HTML) -// to kick this thing off. ?> - - -
    -
    -
    Search By:
    -Enable Autosearch
    +Enable Autosearch
    Last Name
    @@ -147,73 +41,3 @@ First Name
    -
    - - - diff --git a/site/views/elements/jqGrid.ctp b/site/views/elements/jqGrid.ctp new file mode 100644 index 0000000..b12aae3 --- /dev/null +++ b/site/views/elements/jqGrid.ctp @@ -0,0 +1,210 @@ +'.$this->pageTitle.''; + +if (!isset($limit)) + $limit = 20; + +if (!isset($limitOptions)) + $limitOptions = array(10, 20, 50, 200); + +if (!isset($height)) + $height = 'auto'; + +if (!isset($gridId)) + $gridId = $this->params['controller'] . '-jqGrid'; + +// Do some prework to bring in the appropriate libraries +$imgpath = '/pmgr/site/css/jqGrid/basic/images'; +$html->css('jqGrid/basic/grid', null, null, false); +$html->css('jqGrid/jqModal', null, null, false); +$javascript->link('jqGrid/jquery.jqGrid.js', false); +$javascript->link('jqGrid/js/jqModal', false); +$javascript->link('jqGrid/js/jqDnR', false); + +// Create the javascript code for jqGrid to create each table column +$colModels = array(); +foreach ($jqGridColumns AS $col) { + $col['name'] = $col['index']; + $colModels[] = + '{ ' . implode(", ", + array_map(create_function + ('$k, $v', + 'return "$k:".($v===false?"false":($v===true?"true":"\'$v\'"));'), + array_keys($col), + array_values($col))) . + '}'; +} + +// Save just the column indices (fields) +$colFields= array_map(create_function('$col', 'return $col["index"];'), $jqGridColumns); + +// Define the URL to fetch data from. +// To prevent having to keep the controller and the view +// in sync on which fields need to be queried by the +// controller in order to be accessible to the view, +// we'll just pass the desired fields to the controller +// as part of the data fetch. + +$url = $html->url(array('action' => 'jqGridData', + 'debug' => 0, + )); + +// OK, now that everything is in place, get out of PHP mode, +// and add the javascript code (along with a touch of HTML) +// to kick this thing off. +?> + + + +
    +
    + + + From 5fab94011bf206a248b42a611d835d14e14a8e2c Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 14 Jun 2009 05:14:36 +0000 Subject: [PATCH 115/717] Fixed minor issue where an empty query could continue to persist. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@116 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/jqGrid.ctp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/site/views/elements/jqGrid.ctp b/site/views/elements/jqGrid.ctp index b12aae3..bc3e9a9 100644 --- a/site/views/elements/jqGrid.ctp +++ b/site/views/elements/jqGrid.ctp @@ -184,6 +184,16 @@ function gridRestore() { function gridFilter(id) { var field = jQuery("#"+id).attr('name'); var value = jQuery("#"+id).val(); + + // Make sure we're not issuing blank queries. + // It will work without observable effect, but + // it will result in slower queries. Just + // clear out all filter terms instead. + if (value == '') { + gridRestore(); + return; + } + /* $('#debug').append("RELOAD: field:"+field+"; value:"+value+"
    "); */ jQuery('#').setPostDataItem('filt', true); jQuery('#').setPostDataItem('filtField', field); From f6ca79d1a9e1933c8148abd8279215aac54cc0f3 Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 14 Jun 2009 05:33:30 +0000 Subject: [PATCH 116/717] Moved units onto jqGrid. Also generalized the jqGridSetup (now jqGridView) function and moved it into the app controller. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@117 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 15 +++ site/controllers/customers_controller.php | 14 +- site/controllers/units_controller.php | 156 ++++++++++------------ site/views/elements/units.ctp | 65 ++------- site/views/units/index.ctp | 3 - 5 files changed, 100 insertions(+), 153 deletions(-) delete mode 100644 site/views/units/index.ctp diff --git a/site/app_controller.php b/site/app_controller.php index 7af38ef..9ad388d 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -56,6 +56,21 @@ class AppController extends Controller { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * helper: jqGridView + * - called by function to create an index listing + */ + + function jqGridView($action, $title) { + $this->set('title', $title); + // The resulting page will contain a jqGrid, which will + // use ajax to obtain the actual data for this action + $this->set('action', $action); + $this->render('/elements/' . $this->params['controller']); + } + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 288018e..65b7fd5 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -29,18 +29,10 @@ class CustomersController extends AppController { * - Creates a list of tenants */ - function jqGridSetup($action, $title) { - $this->set('title', $title); $this->set('heading', $title); - // The resulting page will contain a jqGrid, which will - // use ajax to obtain the actual data for this action - $this->set('action', $action); - $this->render('/elements/customers'); - } - function index() { $this->current(); } - function current() { $this->jqGridSetup('current', 'Current Tenants'); } - function past() { $this->jqGridSetup('past', 'Past Tenants'); } - function all() { $this->jqGridSetup('all', 'All Tenants'); } + function current() { $this->jqGridView('current', 'Current Tenants'); } + function past() { $this->jqGridView('past', 'Past Tenants'); } + function all() { $this->jqGridView('all', 'All Tenants'); } /************************************************************************** diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index 6326447..86153fd 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -28,114 +28,98 @@ class UnitsController extends AppController { /************************************************************************** ************************************************************************** ************************************************************************** - * action: index - * - Lists all units + * action: index / current / past / all + * - Creates a list of tenants */ - function index() { - $this->all(); - } + function index() { $this->all(); } + function unavailable() { $this->jqGridView('unavailable', 'Unavailable Units'); } + function vacant() { $this->jqGridView('vacant', 'Vacant Units'); } + function occupied() { $this->jqGridView('occupied', 'Occupied Units'); } + function all() { $this->jqGridView('all', 'All Units'); } /************************************************************************** ************************************************************************** ************************************************************************** - * action: unavailable - * - Lists unavailable units + * virtuals: jqGridData + * - With the application controller handling the jqGridData action, + * these virutal functions ensure that the correct data is passed + * to jqGrid. */ - function unavailable() { - $this->paginate = array_merge - ($this->paginate, - array('link' => - array(// Models - 'UnitSize' => array('fields' => array('name')), - ), - 'conditions' => $this->Unit->conditionUnavailable() - )); - - $title = 'Unavailable Units'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('units', $this->paginate()); - $this->render('index'); + function jqGridDataSetup(&$params) { + parent::jqGridDataSetup($params); + if (!isset($params['action'])) + $params['action'] = 'all'; } + function jqGridDataTables(&$params) { + $link = array + ('link' => + array(// Models + 'UnitSize' => array('fields' => array('name')), + ), + ); - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: vacant - * - Lists vacant units - */ + if ($params['action'] === 'occupied') + $link['Lease'] = array('fields' => array(), + // Models + 'Contact' => array('fields' => array('display_name'), + //'type' => 'LEFT', + ), + ); - function vacant() { - $this->paginate = array_merge - ($this->paginate, - array('link' => - array(// Models - 'UnitSize' => array('fields' => array('name')), - ), - 'conditions' => $this->Unit->conditionVacant() - )); - - $title = 'Vacant Units'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('units', $this->paginate()); - $this->render('index'); + return $link; } + function jqGridDataConditions(&$params) { + $conditions = parent::jqGridDataConditions($params); - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: occupied - * - Lists occupied units - */ + if ($params['action'] === 'unavailable') { + $conditions[] = $this->Unit->conditionUnavailable(); + } + elseif ($params['action'] === 'vacant') { + $conditions[] = $this->Unit->conditionVacant(); + } + elseif ($params['action'] === 'occupied') { + $conditions[] = $this->Unit->conditionOccupied(); + } - function occupied() { - $this->paginate = array_merge - ($this->paginate, - array('link' => - array(// Models - 'UnitSize' => array('fields' => array('name')), - 'Lease' => array('fields' => array(), - - // Models - 'Contact' => array('fields' => array('display_name'), - //'type' => 'LEFT', - ), - ), - ), - 'conditions' => $this->Unit->conditionOccupied() - )); - - $title = 'Occupied Units'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('units', $this->paginate()); - $this->render('index'); + return $conditions; } + function zzjqGridDataRecordCount(&$params, $model, $query) { - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: all - * - Lists all units - */ + // We don't have a good way to use the query to obtain + // our count. The problem is that we're relying on the + // group by for the query, which will destroy the count, + // whether we omit the group by or leave it in. + // So, build a fresh query for counting. - function all() { - $this->paginate = array_merge - ($this->paginate, - array('link' => - array(// Models - 'UnitSize' => array('fields' => array('name')), - ), - )); + $query['conditions'] = parent::jqGridDataConditions($params); - $title = 'All Units'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('units', $this->paginate()); - $this->render('index'); + $count = $model->find('count', + array_merge(array('link' => array_diff_key($query['link'], + array('CurrentLease'=>1))), + array_diff_key($query, array('link'=>1)))); + + if ($params['action'] === 'all') + return $count; + + $query['conditions'][] = 'CurrentLease.id IS NULL'; + $count_past = $model->find('count', $query); + + // Since we can't easily count 'current' directly, we + // can quickly derive it since 'current' customers + // are mutually exclusive to 'past' customers. + if ($params['action'] == 'current') + $count = $count - $count_past; + elseif ($params['action'] == 'past') { + $count = $count_past; + } + + return $count; } diff --git a/site/views/elements/units.ctp b/site/views/elements/units.ctp index 6376a3c..e241c35 100644 --- a/site/views/elements/units.ctp +++ b/site/views/elements/units.ctp @@ -1,58 +1,17 @@ '.__('Units',true).''; +// Define the table columns +$cols = array(); +$cols['ID'] = array('index' => 'Unit.id', 'width' => '30', 'align' => 'center'); +$cols['Unit'] = array('index' => 'Unit.name', 'width' => '50', 'align' => 'left'); +$cols['Size'] = array('index' => 'UnitSize.name', 'width' => '75', 'align' => 'left'); +$cols['Status'] = array('index' => 'Unit.status', 'width' => '75', 'align' => 'left'); +$cols['Comment'] = array('index' => 'Unit.comment', 'width' => '400', 'align' => 'left'); -$headers = array('ID', 'Unit', 'Size', 'Status', 'Comment'); -$column_class = array(); -foreach (array_intersect($headers, array('ID')) AS $k => $v) { - $column_class[$k] = 'id'; -} -foreach (array_intersect($headers, array('Comment')) AS $k => $v) { - $column_class[$k] = 'slack'; -} +// Some of the columns should not be sortable +foreach (array_intersect_key($cols, array('Comment'=>1)) AS $k => $v) + $cols[$k]['sortable'] = false; -if (isset($paginator)) { - echo $paginator->counter(array( - 'format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true))); +echo $this->element('jqGrid', + array('jqGridColumns' => $cols)); - $headers = array($paginator->sort('id'), - $paginator->sort('Unit', 'name'), - $paginator->sort('unit_size_id'), - $paginator->sort('status'), - $paginator->sort('comment')); -} - -$rows = array(); -foreach ($units as $unit) { - $rows[] = array($html->link($unit['Unit']['id'], - array('controller' => 'units', - 'action' => 'view', - $unit['Unit']['id'])), - $html->link($unit['Unit']['name'], - array('controller' => 'units', - 'action' => 'view', - $unit['Unit']['id'])), - $unit['UnitSize']['name'], - $unit['Unit']['status'], - $unit['Unit']['comment']); -} - -echo $this->element('table', - array('class' => 'item unit list', - 'caption' => isset($caption) ? $caption : null, - 'headers' => $headers, - 'rows' => $rows, - 'column_class' => $column_class)); - -if (isset($paginator)) { - echo('
    ' . "\n"); - echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled')); - echo(' | '); - echo $paginator->numbers(); - echo(' | '); - echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled')); - echo('
    ' . "\n"); -} diff --git a/site/views/units/index.ctp b/site/views/units/index.ctp deleted file mode 100644 index d6ae893..0000000 --- a/site/views/units/index.ctp +++ /dev/null @@ -1,3 +0,0 @@ -
    -element('units', array('heading' => '

    '.$heading.'

    ')) ?> -
    From c90830d41a7ee1afdd3358a40c6e3312b8c0b118 Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 14 Jun 2009 19:50:09 +0000 Subject: [PATCH 117/717] Made the app controller include the action by default. Added virtual callouts for data order and limit. Changed fields to use formatting, including a custom format for currency and id. Added a function for auto conversion from PHP variables to javascript. Fixed some minor bugs in the controllers already converted to jqGrid. Moved leases onto jqGrid. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@118 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 23 ++- site/controllers/customers_controller.php | 6 +- site/controllers/leases_controller.php | 101 +++++------- site/controllers/units_controller.php | 50 ++---- site/views/elements/customers.ctp | 24 +-- site/views/elements/jqGrid.ctp | 180 ++++++++++++++++++---- site/views/elements/leases.ctp | 93 ++--------- site/views/elements/units.ctp | 14 +- site/views/leases/index.ctp | 3 - site/webroot/js/pmgr.js | 20 +++ 10 files changed, 260 insertions(+), 254 deletions(-) delete mode 100644 site/views/leases/index.ctp diff --git a/site/app_controller.php b/site/app_controller.php index 9ad388d..5da2ece 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -63,11 +63,11 @@ class AppController extends Controller { * - called by function to create an index listing */ - function jqGridView($action, $title) { + function jqGridView($title, $action = null) { $this->set('title', $title); // The resulting page will contain a jqGrid, which will // use ajax to obtain the actual data for this action - $this->set('action', $action); + $this->set('action', $action ? $action : $this->params['action']); $this->render('/elements/' . $this->params['controller']); } @@ -103,13 +103,13 @@ class AppController extends Controller { $total = ($count < 0) ? 0 : ceil($count/$limit); $page = ($params['page'] <= 1) ? 1 : (($params['page'] > $total) ? $total : $params['page']); $start = $limit*$page - $limit; - $sidx = isset($params['sidx']) ? $params['sidx'] : ''; - $sord = isset($params['sord']) ? ' ' . $params['sord'] : ''; // Grab the actual records taking pagination into account $query['group'] = $model->alias . '.id'; - $query['order'] = $sidx ? $sidx . $sord : null; - $query['limit'] = $start . ', ' . $limit; + $query['order'] = $this->jqGridDataOrder($params, + isset($params['sidx']) ? $params['sidx'] : null, + isset($params['sord']) ? $params['sord'] : null); + $query['limit'] = $this->jqGridDataLimit($params, $start, $limit); $query['fields'] = $this->jqGridDataFields($params); $results = $this->jqGridDataRecords($params, $model, $query); @@ -229,6 +229,17 @@ class AppController extends Controller { return null; } + function jqGridDataOrder(&$params, $index, $direction) { + if ($direction) + $direction = ' ' . $direction; + + return $index ? $index . $direction : null; + } + + function jqGridDataLimit(&$params, $start, $limit) { + return $start . ', ' . $limit; + } + function jqGridDataRecordCount(&$params, $model, $query) { return $model->find('count', $query); } diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 65b7fd5..e8d5af1 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -30,9 +30,9 @@ class CustomersController extends AppController { */ function index() { $this->current(); } - function current() { $this->jqGridView('current', 'Current Tenants'); } - function past() { $this->jqGridView('past', 'Past Tenants'); } - function all() { $this->jqGridView('all', 'All Tenants'); } + function current() { $this->jqGridView('Current Tenants'); } + function past() { $this->jqGridView('Past Tenants'); } + function all() { $this->jqGridView('All Tenants', 'all'); } /************************************************************************** diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index ecc593a..13ca357 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -1,10 +1,6 @@ 100, - 'group' => 'Lease.id', - 'order' => array('Lease.movein_date' => 'DESC')); var $sidemenu_links = array(array('name' => 'Leases', 'header' => true), @@ -28,24 +24,52 @@ class LeasesController extends AppController { /************************************************************************** ************************************************************************** ************************************************************************** - * action: index - * - Lists current leases + * action: index / active / closed / all + * - Generate a listing of leases */ - function index() { - $this->active(); - } + function index() { $this->all(); } + function active() { $this->jqGridView('Active Leases'); } + function closed() { $this->jqGridView('Closed Leases'); } + function all() { $this->jqGridView('All Leases'); } /************************************************************************** ************************************************************************** ************************************************************************** - * action: active - * - Lists all active leases + * virtuals: jqGridData + * - With the application controller handling the jqGridData action, + * these virutal functions ensure that the correct data is passed + * to jqGrid. */ - function active() { - $leases = $this->paginate(array('Lease.close_date IS NULL')); + function jqGridDataSetup(&$params) { + parent::jqGridDataSetup($params); + if (!isset($params['action'])) + $params['action'] = 'all'; + } + + function jqGridDataTables(&$params) { + return array + ('link' => array('Unit' => array('fields' => array('Unit.name')), + 'Customer' => array('fields' => array('Customer.name')))); + } + + function jqGridDataConditions(&$params) { + $conditions = parent::jqGridDataConditions($params); + + if ($params['action'] === 'active') { + $conditions[] = 'Lease.close_date IS NULL'; + } + elseif ($params['action'] === 'closed') { + $conditions[] = 'Lease.close_date IS NOT NULL'; + } + + return $conditions; + } + + function jqGridDataRecords(&$params, $model, $query) { + $leases = parent::jqGridDataRecords($params, $model, $query); // Get the balance on each lease. foreach ($leases AS &$lease) { @@ -53,56 +77,7 @@ class LeasesController extends AppController { $lease['Lease']['balance'] = $stats['Account']['Ledger']['balance']; } - $title = 'Active Leases'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('leases', $leases); - $this->render('index'); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: closed - * - Lists all closed (inactive) leases - */ - - function closed() { - $leases = $this->paginate(array('Lease.close_date IS NOT NULL')); - - // Get the balance on each lease. - foreach ($leases AS &$lease) { - $stats = $this->Lease->stats($lease['Lease']['id']); - $lease['Lease']['balance'] = $stats['Account']['Ledger']['balance']; - } - - $title = 'Past Leases'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('leases', $leases); - $this->render('index'); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: all - * - Lists all leases - */ - - function all() { - $leases = $this->paginate(); - - // Get the balance on each lease. - foreach ($leases AS &$lease) { - $stats = $this->Lease->stats($lease['Lease']['id']); - $lease['Lease']['balance'] = $stats['Account']['Ledger']['balance']; - } - - $title = 'All Leases'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('leases', $leases); - $this->render('index'); + return $leases; } diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index 86153fd..9fec73c 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -1,9 +1,6 @@ 100, - 'group' => 'Unit.id', - 'order' => array('Unit.sort_order' => 'ASC')); var $sidemenu_links = array(array('name' => 'Units', 'header' => true), @@ -28,15 +25,15 @@ class UnitsController extends AppController { /************************************************************************** ************************************************************************** ************************************************************************** - * action: index / current / past / all - * - Creates a list of tenants + * action: index / unavailable / vacant / occupied / all + * - Generate a listing of units */ function index() { $this->all(); } - function unavailable() { $this->jqGridView('unavailable', 'Unavailable Units'); } - function vacant() { $this->jqGridView('vacant', 'Vacant Units'); } - function occupied() { $this->jqGridView('occupied', 'Occupied Units'); } - function all() { $this->jqGridView('all', 'All Units'); } + function unavailable() { $this->jqGridView('Unavailable Units'); } + function vacant() { $this->jqGridView('Vacant Units'); } + function occupied() { $this->jqGridView('Occupied Units'); } + function all() { $this->jqGridView('All Units', 'all'); } /************************************************************************** @@ -89,40 +86,13 @@ class UnitsController extends AppController { return $conditions; } - function zzjqGridDataRecordCount(&$params, $model, $query) { - - // We don't have a good way to use the query to obtain - // our count. The problem is that we're relying on the - // group by for the query, which will destroy the count, - // whether we omit the group by or leave it in. - // So, build a fresh query for counting. - - $query['conditions'] = parent::jqGridDataConditions($params); - - $count = $model->find('count', - array_merge(array('link' => array_diff_key($query['link'], - array('CurrentLease'=>1))), - array_diff_key($query, array('link'=>1)))); - - if ($params['action'] === 'all') - return $count; - - $query['conditions'][] = 'CurrentLease.id IS NULL'; - $count_past = $model->find('count', $query); - - // Since we can't easily count 'current' directly, we - // can quickly derive it since 'current' customers - // are mutually exclusive to 'past' customers. - if ($params['action'] == 'current') - $count = $count - $count_past; - elseif ($params['action'] == 'past') { - $count = $count_past; + function jqGridDataOrder(&$params, $index, $direction) { + if ($index === 'Unit.name') { + $index = 'Unit.sort_order'; } - - return $count; + return parent::jqGridDataOrder($params, $index, $direction); } - /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index faeb05a..d779a70 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -2,22 +2,14 @@ // Define the table columns $cols = array(); -$cols['ID'] = array('index' => 'Customer.id', 'width' => '30', 'align' => 'center'); -if (isset($customers[0]['ContactsCustomer'])) - $cols['Relationship'] = array('index' => 'ContactsCustomer.type', 'width' => '75', 'align' => 'left'); -$cols['Name'] = array('index' => 'Customer.name', 'width' => '150', 'align' => 'left'); -$cols['Last Name'] = array('index' => 'PrimaryContact.last_name', 'width' => '100', 'align' => 'left'); -$cols['First Name'] = array('index' => 'PrimaryContact.first_name', 'width' => '100', 'align' => 'left'); -$cols['Leases'] = array('index' => 'lease_count', 'width' => '60', 'align' => 'center'); -$cols['Comment'] = array('index' => 'Customer.comment', 'width' => '300', 'align' => 'left'); - -// Some of the columns should not be sortable -foreach (array_intersect_key($cols, array('Comment'=>1)) AS $k => $v) - $cols[$k]['sortable'] = false; - -// Some of the columns should be searchable -foreach (array_intersect_key($cols, array('Last Name'=>1, 'First Name'=>1)) AS $k => $v) - $cols[$k]['search'] = true; +$cols['ID'] = array('index' => 'Customer.id', 'formatter' => 'id'); +if (0) // REVISIT: Need to figure out how to put this in play + $cols['Relationship'] = array('index' => 'ContactsCustomer.type', 'width' => '75'); +$cols['Name'] = array('index' => 'Customer.name', 'width' => '150'); +$cols['Last Name'] = array('index' => 'PrimaryContact.last_name', 'width' => '100'); +$cols['First Name'] = array('index' => 'PrimaryContact.first_name', 'width' => '100'); +$cols['Leases'] = array('index' => 'lease_count', 'width' => '60'); +$cols['Comment'] = array('index' => 'Customer.comment', 'formatter' => 'comment'); echo $this->element('jqGrid', array('jqGridColumns' => $cols)); diff --git a/site/views/elements/jqGrid.ctp b/site/views/elements/jqGrid.ctp index bc3e9a9..477970c 100644 --- a/site/views/elements/jqGrid.ctp +++ b/site/views/elements/jqGrid.ctp @@ -23,22 +23,75 @@ $javascript->link('jqGrid/jquery.jqGrid.js', false); $javascript->link('jqGrid/js/jqModal', false); $javascript->link('jqGrid/js/jqDnR', false); -// Create the javascript code for jqGrid to create each table column -$colModels = array(); -foreach ($jqGridColumns AS $col) { - $col['name'] = $col['index']; - $colModels[] = - '{ ' . implode(", ", - array_map(create_function - ('$k, $v', - 'return "$k:".($v===false?"false":($v===true?"true":"\'$v\'"));'), - array_keys($col), - array_values($col))) . - '}'; +// Helper function to convert PHP vars to javascript +function phpVarToJavascript($var, $name = '', $depth='', $special = false) { + + // Establish a prefix to use before printing $var + $prefix = $depth; + + // If given a name, set it up JS style + if ($name) + $prefix .= $name . ": "; + + if (!isset($var)) + return $prefix . 'null'; + + if (is_bool($var)) + return $prefix . ($var ? "true" : "false"); + + if (is_numeric($var)) + return $prefix . $var; + + if (is_string($var)) { + // Check to see if this is a special + if ($special) + return $prefix . $var; + + // OK, must just be a string after all + return $prefix . "'$var'"; + } + + // The only thing left that we know how to dump + // is an array. Die if we have anything else. + if (!is_array($var)) { + die; + return null; + } + + // Keep a lookout for special cases, flagged by '--special' + + // eg: array('name' => array('--special' => array('a' => 'one', 'b' => 'two'))) + // GIVES: name: [ 'one', 'two' ] + // NOT: name: { --special: { a: 'one', b: 'two' } } + + // eg: array('name' => array('--special' => 'varname')) + // GIVES: name: varname + // NOT: name: { --special: 'varname' } + + if (isset($var['--special']) && count($var) == 1) + return phpVarToJavascript($var['--special'], $name, $depth, true); + + // PHP array indices can be a mix of integer and string based. + // Just guess here, unless flagged as a special case. + if (isset($var[0]) || $special) + return ($prefix . "[\n" + . implode(",\n", + array_map('phpVarToJavascript', + array_values($var), + array(), + array_fill(0, count($var), $depth.' ') + )) + . "\n$depth]"); + + return ($prefix . "{\n" + . implode(",\n", + array_map('phpVarToJavascript', + array_values($var), array_keys($var), + array_fill(0, count($var), $depth.' ') + )) + . "\n$depth}"); } -// Save just the column indices (fields) -$colFields= array_map(create_function('$col', 'return $col["index"];'), $jqGridColumns); // Define the URL to fetch data from. // To prevent having to keep the controller and the view @@ -51,6 +104,57 @@ $url = $html->url(array('action' => 'jqGridData', 'debug' => 0, )); +// Create extra parameters that jqGrid will pass to our +// controller whenever data is requested. 'action' will +// ensure that the controller provides the correct subset +// of data, and 'fields' will allow it to return only the +// requested fields, and in the right order. Since fields +// is a complex structure (an array), we'll need to +// serialize it first for transport over HTTP. +$postData = array('action' => $action, + 'fields' => serialize(array_map(create_function('$col', + 'return $col["index"];'), + $jqGridColumns))); + + +// Perform column customizations. +// This will largely be based off of the 'formatter' parameter, +// but could be on any pertinent condition. +foreach ($jqGridColumns AS &$col) { + $default = array(); + + // Make sure every column has a name + $default['name'] = $col['index']; + + // Perform customization based on formatter + if (isset($col['formatter'])) { + if ($col['formatter'] === 'id') { + // Switch currency over to our own custom formatting + $col['formatter'] = array('--special' => 'idFormatter'); + $default['width'] = 50; + $default['align'] = 'center'; + } + elseif ($col['formatter'] === 'currency') { + // Switch currency over to our own custom formatting + $col['formatter'] = array('--special' => 'currencyFormatter'); + $default['width'] = 80; + $default['align'] = 'right'; + } + elseif ($col['formatter'] === 'date') { + $default['formatoptions'] = array('newformat' => 'm/d/Y'); + $default['width'] = 90; + $default['align'] = 'center'; + } + elseif ($col['formatter'] === 'comment') { + $default['width'] = 300; + $default['sortable'] = false; + } + } + + $col = array_merge($default, $col); +} + + // OK, now that everything is in place, get out of PHP mode, // and add the javascript code (along with a touch of HTML) // to kick this thing off. @@ -59,25 +163,34 @@ $url = $html->url(array('action' => 'jqGridData', -
    -
    -
    +
    +
    - - diff --git a/site/views/elements/leases.ctp b/site/views/elements/leases.ctp index 8dde048..0363083 100644 --- a/site/views/elements/leases.ctp +++ b/site/views/elements/leases.ctp @@ -11,6 +11,18 @@ $cols['Move-Out'] = array('index' => 'Lease.moveout_date', 'formatter' => 'dat $cols['Balance'] = array('index' => 'Lease.balance', 'formatter' => 'currency'); $cols['Comment'] = array('index' => 'Lease.comment', 'formatter' => 'comment'); -echo $this->element('jqGrid', - array('jqGridColumns' => $cols)); +$jqGrid_options = array('jqGridColumns' => $cols, + 'controller' => 'leases', + 'caption' => isset($caption) ? $caption : null); +if (isset($leases)) { + $jqGrid_options += array('custom_ids' => + array_map(create_function('$data', + 'return $data["id"];'), + $leases), + 'limit' => 5); +} + +$jqGrid_options += array('search_fields' => array('Customer', 'Unit')); + +echo $this->element('jqGrid', $jqGrid_options); diff --git a/site/views/layouts/default.ctp b/site/views/layouts/default.ctp index 0481e80..f394601 100644 --- a/site/views/layouts/default.ctp +++ b/site/views/layouts/default.ctp @@ -83,6 +83,8 @@ +
    + From 31c603c7572b21d26cedba1e0afe1d6bcb92f792 Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 14 Jun 2009 23:54:48 +0000 Subject: [PATCH 123/717] Minor tweak to the css to create a margin for each grid, and so added a div to wrap each item listing. Changed the search boxes to only be available for the overall item listing. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@124 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/contacts.ctp | 5 +++-- site/views/elements/customers.ctp | 5 +++-- site/views/elements/jqGrid.ctp | 29 +++++++++++++++++++++-------- site/views/elements/leases.ctp | 5 +++-- site/views/elements/units.ctp | 18 ++++++++++++++++-- site/webroot/css/layout.css | 5 +++-- 6 files changed, 49 insertions(+), 18 deletions(-) diff --git a/site/views/elements/contacts.ctp b/site/views/elements/contacts.ctp index 6952d76..51e05e2 100644 --- a/site/views/elements/contacts.ctp +++ b/site/views/elements/contacts.ctp @@ -23,7 +23,8 @@ if (isset($contacts)) { $contacts), 'limit' => 5); } - -$jqGrid_options += array('search_fields' => array('Last Name', 'First Name')); +else { + $jqGrid_options += array('search_fields' => array('Last Name', 'First Name')); +} echo $this->element('jqGrid', $jqGrid_options); diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index 53ba5e6..895f0eb 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -22,7 +22,8 @@ if (isset($customers)) { $customers), 'limit' => 5); } - -$jqGrid_options += array('search_fields' => array('Last Name', 'First Name')); +else { + $jqGrid_options += array('search_fields' => array('Last Name', 'First Name')); +} echo $this->element('jqGrid', $jqGrid_options); diff --git a/site/views/elements/jqGrid.ctp b/site/views/elements/jqGrid.ctp index de13101..a9f6358 100644 --- a/site/views/elements/jqGrid.ctp +++ b/site/views/elements/jqGrid.ctp @@ -9,13 +9,13 @@ if (!isset($limit)) if (!isset($limitOptions)) { $limitOptions = array(); if ($limit < 10) - $limitOptions += array(2, 5); + array_push($limitOptions, 2, 5); if ($limit < 30) - $limitOptions += array(10, 25); + array_push($limitOptions, 10, 25); if ($limit > 10) - $limitOptions += array(50, 200); + array_push($limitOptions, 50, 200); if ($limit > 20) - $limitOptions += array(500); + array_push($limitOptions, 500); } if (!isset($height)) @@ -24,8 +24,15 @@ if (!isset($height)) if (!isset($controller)) $controller = $this->params['controller']; +if (!isset($grid_div_class)) + $grid_div_class = ''; +$grid_div_class = 'item grid list' . ($grid_div_class ? ' '.$grid_div_class : ''); + +if (!isset($grid_div_id)) + $grid_div_id = $controller . '-list'; + if (!isset($grid_id)) - $grid_id = $controller . '-jqGrid'; + $grid_id = $grid_div_id . '-jqGrid'; if (!isset($search_fields)) $search_fields = array(); @@ -129,6 +136,9 @@ foreach ($jqGridColumns AS &$col) { // to kick this thing off. ?> +
    +
    +
    -
    -
    - 0) { echo('
    Search By:
    ' . "\n"); @@ -222,3 +231,7 @@ jQuery(document).ready(function(){ echo('
    ' . "\n"); echo('
    ' . "\n"); } + +// Finally, back to HTML mode, and end the grid DIV we created +?> +
    diff --git a/site/views/elements/leases.ctp b/site/views/elements/leases.ctp index 0363083..b26787a 100644 --- a/site/views/elements/leases.ctp +++ b/site/views/elements/leases.ctp @@ -22,7 +22,8 @@ if (isset($leases)) { $leases), 'limit' => 5); } - -$jqGrid_options += array('search_fields' => array('Customer', 'Unit')); +else { + $jqGrid_options += array('search_fields' => array('Customer', 'Unit')); +} echo $this->element('jqGrid', $jqGrid_options); diff --git a/site/views/elements/units.ctp b/site/views/elements/units.ctp index 6dde6f9..3ab81c8 100644 --- a/site/views/elements/units.ctp +++ b/site/views/elements/units.ctp @@ -8,6 +8,20 @@ $cols['Size'] = array('index' => 'UnitSize.name', 'width' => '75'); $cols['Status'] = array('index' => 'Unit.status', 'width' => '75'); $cols['Comment'] = array('index' => 'Unit.comment', 'formatter' => 'comment'); -echo $this->element('jqGrid', - array('jqGridColumns' => $cols)); +$jqGrid_options = array('jqGridColumns' => $cols, + 'controller' => 'units', + 'caption' => isset($caption) ? $caption : null); + +if (isset($units)) { + $jqGrid_options += array('custom_ids' => + array_map(create_function('$data', + 'return $data["id"];'), + $units), + 'limit' => 5); +} +else { + $jqGrid_options += array('search_fields' => array('Unit', 'Size', 'Status')); +} + +echo $this->element('jqGrid', $jqGrid_options); diff --git a/site/webroot/css/layout.css b/site/webroot/css/layout.css index 7a43bf3..8d32e34 100644 --- a/site/webroot/css/layout.css +++ b/site/webroot/css/layout.css @@ -27,7 +27,7 @@ table caption { text-align: left; padding-bottom: 0.5em; } -table.item { margin-bottom: 1.5em; } +div.item.list { margin-bottom: 1.5em; } /* table.item caption { margin-top: 1em; } */ /* table.detail caption { margin-top: 0; } */ @@ -68,7 +68,8 @@ table.detail { width : 60%; float: left; } table.detail td.field { width: 10em; } -div.detail.supporting { clear : both; } +div.detail.supporting { clear : both; + padding-top: 1.5em; } From 9f876b78de91694b4bfdf444da2fddad6ebe4c04 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 15 Jun 2009 00:13:57 +0000 Subject: [PATCH 124/717] I apparently forgot to check the pmgr_jqGrid.js file in a few checkins ago, meaning those revisions are all broken. This is finally the checkin to include it. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@125 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/webroot/js/pmgr_jqGrid.js | 91 ++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 site/webroot/js/pmgr_jqGrid.js diff --git a/site/webroot/js/pmgr_jqGrid.js b/site/webroot/js/pmgr_jqGrid.js new file mode 100644 index 0000000..e5021a2 --- /dev/null +++ b/site/webroot/js/pmgr_jqGrid.js @@ -0,0 +1,91 @@ +function gridRestore(grid_id) { +// $('#debug').append("RESTORE
    "); + $('.filt-text-'+grid_id).val(''); + jQuery('#'+grid_id).removePostDataItem('filt'); + jQuery('#'+grid_id).removePostDataItem('filtField'); + jQuery('#'+grid_id).removePostDataItem('filtValue'); + jQuery('#'+grid_id) + .setGridParam({ page: 1 }) + .trigger("reloadGrid"); +} + + +function gridFilter(field_id) { + var grid_id = $("#"+field_id).attr('filt-grid'); + var field = $("#"+field_id).attr('filt-index'); + var value = $("#"+field_id).val(); + + // Make sure we're not issuing blank queries. + // It will work without observable effect, but + // it will result in slower queries. Just + // clear out all filter terms instead. + if (value == '') { + gridRestore(grid_id); + return; + } + +// $('#debug').append("RELOAD: field_id:"+field_id+"; grid:"+grid_id+"; field:"+field+"; value:"+value+"
    "); + jQuery('#'+grid_id).setPostDataItem('filt', true); + jQuery('#'+grid_id).setPostDataItem('filtField', field); + jQuery('#'+grid_id).setPostDataItem('filtValue', value); + + $('.filt-text-'+grid_id).each(function(){ + if ($(this).attr('id') != field_id) + $(this).val(''); + }); + + jQuery('#'+grid_id) + .setGridParam({ page: 1 }) + .trigger("reloadGrid"); +} + + +var timeoutHnd; +function handleFiltKeydown(e){ + var field_id = $(this).attr('id'); + if (e.which == 8 || e.which >= 32) /* backspace OR printable */ + { +// $('#debug').append("KEYDOWN: id:"+field_id+"
    "); + if(timeoutHnd) + clearTimeout(timeoutHnd); + timeoutHnd = setTimeout(function() + {gridFilter(field_id)}, + 500); + } + else + handleFiltReturn(e); +} + +function handleFiltReturn(e) { + var field_id = $(this).attr('id'); + if (e.which == 10 || e.which == 13) { +// $('#debug').append("KEYDOWN: id:"+field_id+" CHAR 10/13
    "); + if(timeoutHnd) + clearTimeout(timeoutHnd); + gridFilter(field_id); + } +} + + +function enableAutosubmit(state) { + $(".filt-submit").attr("disabled",state); + $('.filt-autosearch').attr('checked', state); + if (state) { + $(".filt-text").unbind('keydown', handleFiltReturn); + $(".filt-text").keydown(handleFiltKeydown); +// $('#debug').append("BIND: id:"+id+"
    "); + } + else { + $(".filt-text").unbind('keydown', handleFiltKeydown); + $(".filt-text").keydown(handleFiltReturn); +// $('#debug').append("UNBIND: id:"+id+"
    "); + } +} + + +jQuery(document).ready(function(){ + $('.filt-submit').click(function(){ + gridFilter($(this).attr('id').replace(/^submit_/, 'filt_')); + }); + enableAutosubmit(true); + }); From 4ec3db7b586ee20c181443179acf6ca712e3c1ff Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 15 Jun 2009 00:44:40 +0000 Subject: [PATCH 125/717] Moved the pagination objects to the right side instead of centered. Also, replaced the jQuery function call for the pager parameter to just the id text. I found this in the manual, and it saves us from having to use the --special exception. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@126 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/jqGrid.ctp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/views/elements/jqGrid.ctp b/site/views/elements/jqGrid.ctp index a9f6358..c1ea577 100644 --- a/site/views/elements/jqGrid.ctp +++ b/site/views/elements/jqGrid.ctp @@ -138,7 +138,7 @@ foreach ($jqGridColumns AS &$col) {
    -
    +
    +' . "\n"; + +echo $this->element('customers', + array('caption' => 'Select Customer', + 'limit' => 7, + 'grid_setup' => $grid_setup, + )); + +echo ('

    ' . + (isset($customer['Customer']['id']) + ? 'Receipt for ' . $customer['Customer']['name'] + : 'Please select customer') . + '

    ' . "\n"); + + //echo $form->create(null, array('id' => 'payment-form', 'action' => 'other')); + echo $form->create(null, array('id' => 'payment-form', 'url' => 'http://localhost/vars.php')); +?> + +
    Payments @@ -264,13 +327,22 @@ function switchPaymentType(paymentid, type) { inputs(); -echo '
    ' . "\n"; -echo $form->end('Send'); +echo 'Date:
    ' . "\n"; +echo 'Comment:
    ' . "\n"; +echo $form->end('Post Payment'); +//echo '
    ' . "\n"; // End of the dialog DIV ?> + Clear Debug Output -
    +Create Payment */ +?> + + +

    Request

    +

    Response

    +

    Output

    @@ -278,7 +350,35 @@ echo $form->end('Send'); diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index 895f0eb..4cfa0e3 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -12,8 +12,10 @@ $cols['Leases'] = array('index' => 'lease_count', 'width' => $cols['Comment'] = array('index' => 'Customer.comment', 'formatter' => 'comment'); $jqGrid_options = array('jqGridColumns' => $cols, - 'controller' => 'customers', - 'caption' => isset($caption) ? $caption : null); + 'controller' => 'customers'); + +// User requested options have priority +$jqGrid_options += compact('caption', 'grid_setup', 'limit'); if (isset($customers)) { $jqGrid_options += array('custom_ids' => @@ -22,7 +24,9 @@ if (isset($customers)) { $customers), 'limit' => 5); } -else { + +// Not the long term solution here... just for testing +if (isset($searchfields)) { $jqGrid_options += array('search_fields' => array('Last Name', 'First Name')); } diff --git a/site/views/elements/jqGrid.ctp b/site/views/elements/jqGrid.ctp index fcc53d1..f41e985 100644 --- a/site/views/elements/jqGrid.ctp +++ b/site/views/elements/jqGrid.ctp @@ -39,6 +39,8 @@ if (!isset($grid_id)) if (!isset($search_fields)) $search_fields = array(); +if (!isset($grid_setup)) + $grid_setup = array(); // Do some prework to bring in the appropriate libraries $imgpath = '/pmgr/site/css/jqGrid/basic/images'; @@ -139,10 +141,35 @@ foreach ($jqGridColumns AS &$col) { $col = array_merge($default, $col); } +// Set the default sort column reset($jqGridColumns); $sortname = current($jqGridColumns); $sortname = $sortname['index']; +// Configure the grid setup, giving priority to user defined parameters +$jqGrid_setup = array_merge + (array('mtype' => 'GET', + 'datatype' => 'xml', + 'url' => $url, + 'postData' => $postData, + 'colNames' => array_keys($jqGridColumns), + 'colModel' => array('--special' => $jqGridColumns), + 'height' => $height, + 'rowNum' => $limit, + 'rowList' => $limitOptions, + 'sortname' => $sortname, + 'caption' => $caption, + 'imgpath' => $imgpath, + 'viewrecords' => true, + 'pager' => $grid_id.'-pager', + + 'loadComplete' => array('--special' => "function() {url=jQuery('#{$grid_id}').getGridParam('url');url=url.replace(/\/debug.*$/,'?'); pd=jQuery('#{$grid_id}').getPostData();$.each(pd,function(i){ url+=i+'='+escape(pd[i])+'&'; }); jQuery('#{$grid_id}-query').html('Grid Query
    ');}"), + 'loadError' => array('--special' => "function(xhr,st,err) {url=jQuery('#{$grid_id}').getGridParam('url');url=url.replace(/\/debug.*$/,'?'); pd=jQuery('#{$grid_id}').getPostData();$.each(pd,function(i){ url+=i+'='+escape(pd[i])+'&'; }); jQuery('#{$grid_id}-query').html('Grid Error Query
    ');}"), + + ), + $grid_setup + ); +//pr(compact('grid_setup', 'jqGrid_setup')); // OK, now that everything is in place, get out of PHP mode, // and add the javascript code (along with a touch of HTML) @@ -165,27 +192,7 @@ jQuery(document).ready(function(){ } jQuery('#').jqGrid( - 'GET', - 'datatype' => 'xml', - 'url' => $url, - 'postData' => $postData, - 'colNames' => array_keys($jqGridColumns), - 'colModel' => array('--special' => $jqGridColumns), - 'height' => $height, - 'rowNum' => $limit, - 'rowList' => $limitOptions, - 'sortname' => $sortname, - 'caption' => $caption, - 'imgpath' => $imgpath, - 'viewrecords' => true, - 'pager' => $grid_id.'-pager', - - 'loadComplete' => array('--special' => "function() {url=jQuery('#{$grid_id}').getGridParam('url');url=url.replace(/\/debug.*$/,'?'); pd=jQuery('#{$grid_id}').getPostData();$.each(pd,function(i){ url+=i+'='+escape(pd[i])+'&'; }); jQuery('#{$grid_id}-query').html('Grid Query
    ');}"), - 'loadError' => array('--special' => "function(xhr,st,err) {url=jQuery('#{$grid_id}').getGridParam('url');url=url.replace(/\/debug.*$/,'?'); pd=jQuery('#{$grid_id}').getPostData();$.each(pd,function(i){ url+=i+'='+escape(pd[i])+'&'; }); jQuery('#{$grid_id}-query').html('Grid Error Query
    ');}"), - //'toolbar' => array(true,"bottom"), - )); ?> + ).navGrid('#-pager', { view:false, edit:false, diff --git a/site/webroot/css/layout.css b/site/webroot/css/layout.css index 0b23087..74b1272 100644 --- a/site/webroot/css/layout.css +++ b/site/webroot/css/layout.css @@ -212,7 +212,7 @@ form div.submit { border: 0; clear: both; margin-top: 10px; - margin-left: 140px; +/* margin-left: 140px; */ } /************************************************************ From cd416ea5faf361b3f9d85a36f8e0547e9faa181b Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 17 Jun 2009 07:37:45 +0000 Subject: [PATCH 155/717] Fixed bug converting PHP strings to javascript when they contain the single quote (') character git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@156 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/helpers/format.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/views/helpers/format.php b/site/views/helpers/format.php index 005f71a..ffa6046 100644 --- a/site/views/helpers/format.php +++ b/site/views/helpers/format.php @@ -211,7 +211,7 @@ class FormatHelper extends AppHelper { return $prefix . $var; // OK, must just be a string after all - return $prefix . "'$var'"; + return $prefix . "'" . preg_replace("/'/", '\\\'', $var) . "'"; } // The only thing left that we know how to dump From 416e230da8600105603c5d7622c63549d216db9d Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 17 Jun 2009 07:38:39 +0000 Subject: [PATCH 156/717] Getting the receipt/payment data in order, getting ready to save (or at least experiment with save. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@157 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/transactions_controller.php | 18 ++++ site/views/customers/payment.ctp | 93 ++++++++++++++++---- 2 files changed, 94 insertions(+), 17 deletions(-) diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php index 70bb925..7bbc859 100644 --- a/site/controllers/transactions_controller.php +++ b/site/controllers/transactions_controller.php @@ -2,6 +2,8 @@ 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')), @@ -92,4 +94,20 @@ class TransactionsController extends AppController { $title = 'Transaction #' . $transaction['Transaction']['id']; $this->set(compact('transaction', 'title', 'total')); } + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: postReceipt + * - handles the creation of a payment receipt + */ + + function postReceipt() { + if ($this->RequestHandler->isPost()) { + pr($this->data); + //$this->redirect(array('action'=>'index')); + } + $this->autoRender = false; + } + } diff --git a/site/views/customers/payment.ctp b/site/views/customers/payment.ctp index 78151bb..9023240 100644 --- a/site/views/customers/payment.ctp +++ b/site/views/customers/payment.ctp @@ -164,7 +164,7 @@ $grid_setup['onSelectRow'] = array function resetPaymentForm() { // Get a clean slate for our payments $('#payments').html(''); - $('#payment-id').val(1); + $('#payment-id').val(0); addPaymentSource(false); } @@ -176,16 +176,27 @@ $grid_setup['onSelectRow'] = array '
    ' + 20090616: + * MUST GET THIS FROM THE DATABASE!! + * HARDCODED VALUES BAD... VERY BAD... + */ + $monetary_type_ids = array('Cash' => 2, + 'Check' => 3, + 'Money Order' => 4, + 'ACH' => 5, + 'Credit Card' => 7, + ); + $types = array(); foreach(array('Cash', 'Check', 'Money Order', /*'ACH', 'Credit Card'*/) AS $name) $types[preg_replace("/ /", "", strtolower($name))] = $name; foreach ($types AS $type => $name) { $div = '
    '; - $div .= ''; + $div .= ' VALUE="'.$monetary_type_ids[$name].'" ' . ($name == 'Cash' ? 'CHECKED ' : '') . '/>'; $div .= ' '; $div .= '
    '; echo "'$div' +\n"; @@ -196,7 +207,7 @@ $grid_setup['onSelectRow'] = array '
    ' + ' ' + ' ' + '
    ' + @@ -233,7 +244,8 @@ function switchPaymentType(paymentid, type) { html = '
    ' + ' ' + - ' : 20090617: Use comment field for now. + ' ' + '
    '; break; @@ -242,7 +254,8 @@ function switchPaymentType(paymentid, type) { html = '
    ' + ' ' + - ' : 20090617: Use comment field for now. + ' ' + '
    '; break; @@ -251,13 +264,15 @@ function switchPaymentType(paymentid, type) { html = '
    ' + ' ' + - ' : 20090617: Use comment field for now. + ' ' + '
    ' + '
    ' + ' ' + - ' : 20090617: Use comment field for now. + ' ' + '
    '; break; @@ -266,19 +281,22 @@ function switchPaymentType(paymentid, type) { html = '
    ' + ' ' + - ' : 20090617: Use comment field for now. + ' ' + '
    ' + '
    ' + ' ' + - ' : 20090617: Use comment field for now. + ' ' + '
    ' + '
    ' + ' ' + - ' : 20090617: Use comment field for now. + ' ' + '
    '; break; @@ -300,7 +318,7 @@ function switchPaymentType(paymentid, type) { //echo '
    ' . "\n"; echo $this->element('customers', - array('caption' => 'Select Customer', + array('caption' => 'Select Customer', 'limit' => 7, 'grid_setup' => $grid_setup, )); @@ -311,14 +329,55 @@ echo ('

    ' . : 'Please select customer') . '

    ' . "\n"); - //echo $form->create(null, array('id' => 'payment-form', 'action' => 'other')); - echo $form->create(null, array('id' => 'payment-form', 'url' => 'http://localhost/vars.php')); +echo $form->create(null, array('id' => 'payment-form', + 'url' => array('controller' => 'transactions', + 'action' => 'postReceipt'))); + +/*************************************************** + * Post data should look like this: + * + * data => Array + * ( + * [Transaction] => Array + * ( + * stamp => + * through_date => + * due_date => + * comment => + * ) + * + * [LedgerEntry] => Array + * ( + * [0] => Array + * ( + * name => + * amount => + * debit_ledger_id => + * credit_ledger_id => + * comment => + * + * [MonetarySource] => Array + * ( + * name => + * monetary_type_id => + * comment => + * ) + * + * REVISIT: Reconciliations will be tricker. + * ) + * + * ) + * + * ) + * + ***************************************************/ + ?>
    Payments - +
    Add Another Payment @@ -327,8 +386,8 @@ echo ('

    ' .
    ' . "\n"; -echo 'Comment:
    ' . "\n"; +echo 'Date:
    ' . "\n"; +echo 'Comment:
    ' . "\n"; echo $form->end('Post Payment'); //echo '

    ' . "\n"; // End of the dialog DIV From 518f7836ace3031f80428be36cbed90c86ab0c2c Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 17 Jun 2009 08:32:53 +0000 Subject: [PATCH 157/717] Fairly decent first pass at determining which ledger entries have not yet been reconciled for an account. I'm using the current ledger only, which I'm sure is not what we want. Since it works though, it's worth checking in. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@158 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/account.php | 57 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/site/models/account.php b/site/models/account.php index add07bf..9538803 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -195,6 +195,63 @@ class Account extends AppModel { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findUnreconciledLedgerEntries + * - Returns summary data from the requested account. + */ + + function findUnreconciledLedgerEntries($id = null) { + // Look in the Current Ledger only (for now) + $unreconciled['debits'] = $this->find + ('all', array + ('link' => array + ('CurrentLedger' => array + ('fields' => array(), + 'DebitLedgerEntry' => array + ('fields' => array('id', 'amount'), + 'DebitReconciliationLedgerEntry' => array + ('fields' => array('COALESCE(SUM(Reconciliation.amount),0) AS "reconciled"', + 'DebitLedgerEntry.amount - COALESCE(SUM(Reconciliation.amount),0) AS "balance"', + ), + ), + ), + ), + ), + 'group' => ('DebitLedgerEntry.id' . + ' HAVING DebitLedgerEntry.amount' . + ' <> COALESCE(SUM(Reconciliation.amount),0)'), + 'conditions' => array('Account.id' => $id), + 'fields' => array(), + )); + + $unreconciled['credits'] = $this->find + ('all', array + ('link' => array + ('CurrentLedger' => array + ('fields' => array(), + 'CreditLedgerEntry' => array + ('fields' => array('id', 'amount'), + 'CreditReconciliationLedgerEntry' => array + ('fields' => array('COALESCE(SUM(Reconciliation.amount),0) AS "reconciled"', + 'CreditLedgerEntry.amount - COALESCE(SUM(Reconciliation.amount),0) AS "balance"', + ), + ), + ), + ), + ), + 'group' => ('CreditLedgerEntry.id' . + ' HAVING CreditLedgerEntry.amount' . + ' <> COALESCE(SUM(Reconciliation.amount),0)'), + 'conditions' => array('Account.id' => $id), + 'fields' => array(), + )); + + return $unreconciled; + } + + /************************************************************************** ************************************************************************** ************************************************************************** From 1e3774cad6ca60140141b7e62e9aa4dd52b0b402 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 17 Jun 2009 09:00:38 +0000 Subject: [PATCH 158/717] Removed remnants of the Containable behavior (which we've already put into the application model. Modified the account model to look for all unreconciled transactions, not just those from the current ledger. Added a mechanism to find unreconciled transactions up the chain, including lease and customer. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@159 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/account.php | 11 ++++------- site/models/customer.php | 34 ++++++++++++++++++++++++++++++---- site/models/lease.php | 19 +++++++++++++++++++ site/models/ledger.php | 2 -- site/models/unit.php | 2 -- 5 files changed, 53 insertions(+), 15 deletions(-) diff --git a/site/models/account.php b/site/models/account.php index 9538803..b8b29fd 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -100,13 +100,11 @@ class Account extends AppModel { $contain = array('CurrentLedger' => array('fields' => array('CurrentLedger.id'))); } - $this->Behaviors->attach('Containable'); $account = $this->find('first', array ('contain' => $contain, 'fields' => array(), 'conditions' => array(array('Account.id' => $id)), )); - $this->Behaviors->detach('Containable'); if ($all) { $ledger_ids = array(); @@ -199,7 +197,8 @@ class Account extends AppModel { ************************************************************************** ************************************************************************** * function: findUnreconciledLedgerEntries - * - Returns summary data from the requested account. + * - Returns ledger entries that are not yet reconciled + * (such as charges not paid). */ function findUnreconciledLedgerEntries($id = null) { @@ -207,7 +206,7 @@ class Account extends AppModel { $unreconciled['debits'] = $this->find ('all', array ('link' => array - ('CurrentLedger' => array + ('Ledger' => array ('fields' => array(), 'DebitLedgerEntry' => array ('fields' => array('id', 'amount'), @@ -229,7 +228,7 @@ class Account extends AppModel { $unreconciled['credits'] = $this->find ('all', array ('link' => array - ('CurrentLedger' => array + ('Ledger' => array ('fields' => array(), 'CreditLedgerEntry' => array ('fields' => array('id', 'amount'), @@ -268,7 +267,6 @@ class Account extends AppModel { // (not just the balance), so we may have to query all // ledgers, as dictated by the $all parameter. - $this->Behaviors->attach('Containable'); $account = $this->find('first', array('contain' => ($all @@ -280,7 +278,6 @@ class Account extends AppModel { 'conditions' => array (array('Account.id' => $id)) )); - $this->Behaviors->detach('Containable'); $stats = array(); if ($all) { diff --git a/site/models/customer.php b/site/models/customer.php index 827026d..dc22db0 100644 --- a/site/models/customer.php +++ b/site/models/customer.php @@ -39,13 +39,11 @@ class Customer extends AppModel { /* 'args' => compact('id', 'link'), */ /* )); */ - $this->Behaviors->attach('Containable'); $customer = $this->find('first', array('contain' => array('Lease' => array('fields' => array('id'))), 'fields' => array('account_id'), 'conditions' => array(array('Customer.id' => $id)))); - $this->Behaviors->detach('Containable'); $entries = $this->Account->findLedgerEntriesRelatedToAccount ($customer['Customer']['account_id'], @@ -69,6 +67,36 @@ class Customer extends AppModel { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findUnreconciledLedgerEntries + * - Returns ledger entries that are not yet reconciled + * (such as charges not paid). + */ + + function findUnreconciledLedgerEntries($id = null) { + $customer = $this->find('first', + array('contain' => + array('Lease' => array('fields' => array('id'))), + 'fields' => array('account_id'), + 'conditions' => array(array('Customer.id' => $id)))); + + $unreconciled = $this->Account->findUnreconciledLedgerEntries + ($customer['Customer']['account_id']); + + foreach ($customer['Lease'] AS $lease) { + $lease_unrec = $this->Lease->findUnreconciledLedgerEntries($lease['id']); + $unreconciled['debits'] = array_merge($unreconciled['debits'], + $lease_unrec['debits']); + $unreconciled['credits'] = array_merge($unreconciled['credits'], + $lease_unrec['credits']); + } + + return $unreconciled; + } + + /************************************************************************** ************************************************************************** ************************************************************************** @@ -132,7 +160,6 @@ class Customer extends AppModel { return null; // Get the basic information necessary - $this->Behaviors->attach('Containable'); $customer = $this->find('first', array('contain' => array('Account' => array @@ -143,7 +170,6 @@ class Customer extends AppModel { ), 'conditions' => array (array('Customer.id' => $id)))); - $this->Behaviors->detach('Containable'); // Get stats from the customer account, and each lease $stats['Account'] = $this->Account->stats($customer['Account']['id']); diff --git a/site/models/lease.php b/site/models/lease.php index a7da73e..a611e85 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -91,6 +91,25 @@ class Lease extends AppModel { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findUnreconciledLedgerEntries + * - Returns ledger entries that are not yet reconciled + * (such as charges not paid). + */ + + function findUnreconciledLedgerEntries($id = null) { + $lease = $this->find('first', array + ('recursive' => -1, + 'fields' => array('account_id'), + 'conditions' => array(array('id' => $id)), + )); + + return $this->Account->findUnreconciledLedgerEntries($lease['Lease']['account_id']); + } + + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/models/ledger.php b/site/models/ledger.php index 56cbf7e..25f8f33 100644 --- a/site/models/ledger.php +++ b/site/models/ledger.php @@ -57,7 +57,6 @@ class Ledger extends AppModel { /* )); */ if (!isset($account_type)) { - $this->Behaviors->attach('Containable'); $ledger = $this->find('first', array ('contain' => array ('Account' => array @@ -67,7 +66,6 @@ class Ledger extends AppModel { 'fields' => array(), 'conditions' => array(array('Ledger.id' => $id)), )); - $this->Behaviors->detach('Containable'); $account_type = $ledger['Account']['type']; } diff --git a/site/models/unit.php b/site/models/unit.php index f7aa047..69b92e7 100644 --- a/site/models/unit.php +++ b/site/models/unit.php @@ -70,7 +70,6 @@ class Unit extends AppModel { return null; // Get the basic information necessary - $this->Behaviors->attach('Containable'); $unit = $this->find('first', array('contain' => array ('Lease' => array @@ -82,7 +81,6 @@ class Unit extends AppModel { 'conditions' => array (array('Unit.id' => $id)), )); - $this->Behaviors->detach('Containable'); // Get the stats for the current lease $stats['CurrentLease'] = $this->Lease->stats($unit['CurrentLease']['id']); From a136fd53135ebc8aee26468d1eb3becf7bd56346 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 17 Jun 2009 18:39:12 +0000 Subject: [PATCH 159/717] Stopped the debug output when dynamically adding a div git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@160 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/webroot/js/pmgr.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/webroot/js/pmgr.js b/site/webroot/js/pmgr.js index 3392cde..c264ac1 100644 --- a/site/webroot/js/pmgr.js +++ b/site/webroot/js/pmgr.js @@ -98,7 +98,7 @@ function addDiv(id_name, div_name, into_div_name, flash, html, script) { html += ''; } -$("#debug").append(htmlEncode(html)); + //$("#debug").append(htmlEncode(html)); $("#"+into_div_name).append(html); if (flash) { From 2e67695154dc9afe9d2e3d2e016854df360e166c Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 17 Jun 2009 18:40:39 +0000 Subject: [PATCH 160/717] Added routines to reconcile a new ledger entry against unreconciled entries. I haven't tested it robustly, but it seems to work on the surface at least. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@161 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/transactions_controller.php | 21 +- site/models/account.php | 219 +++++++++++++------ site/models/customer.php | 111 +++++++++- site/models/lease.php | 64 ++++-- 4 files changed, 312 insertions(+), 103 deletions(-) diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php index 7bbc859..a73ea42 100644 --- a/site/controllers/transactions_controller.php +++ b/site/controllers/transactions_controller.php @@ -103,11 +103,24 @@ class TransactionsController extends AppController { */ function postReceipt() { - if ($this->RequestHandler->isPost()) { - pr($this->data); - //$this->redirect(array('action'=>'index')); - } $this->autoRender = false; + + if (!$this->RequestHandler->isPost()) { + echo('

    THIS IS NOT A POST FOR SOME REASON

    '); + return; + } + //pr($this->data); + + $amount = 0; + foreach ($this->data['LedgerEntry'] AS $entry) { + $amount += isset($entry['amount']) ? $entry['amount'] : 0; + } + + $cust_id = $this->data['Customer']['id']; + $cust = new Customer(); + $unreconciled = $cust->findUnreconciledLedgerEntries($cust_id); + $reconciled = $cust->reconcileNewLedgerEntry($cust_id, 'credit', $amount); + pr(compact('amount', 'unreconciled', 'reconciled')); } } diff --git a/site/models/account.php b/site/models/account.php index b8b29fd..13333a6 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -19,7 +19,61 @@ class Account extends AppModel { 'Ledger', ); - var $cache; + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * 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($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) { + $fund = $this->fundamentalType($id_or_type); + + if ($fund == 'debit') + return 'credit'; + + return 'debit'; + } /************************************************************************** @@ -29,11 +83,13 @@ class Account extends AppModel { * - Returns the ID of the Security Deposit Account */ function securityDepositAccountID() { + $this->cacheQueries = true; $account = $this->find('first', array ('recursive' => -1, 'conditions' => array (array('name' => 'Security Deposit')), )); + $this->cacheQueries = false; return $account['Account']['id']; } @@ -45,43 +101,17 @@ class Account extends AppModel { * - Returns the ID of the Rent Account */ function rentAccountID() { + $this->cacheQueries = true; $account = $this->find('first', array ('recursive' => -1, 'conditions' => array (array('name' => 'Rent')), )); + $this->cacheQueries = false; return $account['Account']['id']; } - /************************************************************************** - ************************************************************************** - ************************************************************************** - * function: type - * - Returns the type of this array of ledger ids from the given account - */ - function type($id) { - if (isset($this->cache[$id]['type'])) { - return $this->cache[$id]['type']; - } - - $account = $this->find('first', array - ('recursive' => -1, - 'fields' => array('type'), - 'conditions' => array(array('Account.id' => $id)), - )); - - // Save the account type in our cache for future reference - $this->cache[$id]['type'] = $account['Account']['type']; - -/* pr(array('function' => 'Account::type', */ -/* 'args' => compact('id'), */ -/* 'return' => $this->cache[$id]['type'])); */ - - return $this->cache[$id]['type']; - } - - /************************************************************************** ************************************************************************** ************************************************************************** @@ -201,56 +231,103 @@ class Account extends AppModel { * (such as charges not paid). */ - function findUnreconciledLedgerEntries($id = null) { - // Look in the Current Ledger only (for now) - $unreconciled['debits'] = $this->find - ('all', array - ('link' => array - ('Ledger' => array - ('fields' => array(), - 'DebitLedgerEntry' => array - ('fields' => array('id', 'amount'), - 'DebitReconciliationLedgerEntry' => array - ('fields' => array('COALESCE(SUM(Reconciliation.amount),0) AS "reconciled"', - 'DebitLedgerEntry.amount - COALESCE(SUM(Reconciliation.amount),0) AS "balance"', - ), + function findUnreconciledLedgerEntries($id = null, $fundamental_type = null) { + foreach (($fundamental_type + ? array($fundamental_type) + : array('debit', 'credit')) AS $fund) { + $ucfund = ucfirst($fund); + $unreconciled[$fund]['entries'] = $this->find + ('all', array + ('link' => array + ('Ledger' => array + ('fields' => array(), + "LedgerEntry" => array + ('class' => "{$ucfund}LedgerEntry", + 'fields' => array('id', 'amount'), + "ReconciliationLedgerEntry" => array + ('class' => "{$ucfund}ReconciliationLedgerEntry", + 'fields' => array + ("COALESCE(SUM(Reconciliation.amount),0) AS 'reconciled'", + "LedgerEntry.amount - COALESCE(SUM(Reconciliation.amount),0) AS 'balance'", + ), + ), + ), ), ), - ), - ), - 'group' => ('DebitLedgerEntry.id' . - ' HAVING DebitLedgerEntry.amount' . - ' <> COALESCE(SUM(Reconciliation.amount),0)'), - 'conditions' => array('Account.id' => $id), - 'fields' => array(), - )); + 'group' => ("LedgerEntry.id" . + " HAVING LedgerEntry.amount" . + " <> COALESCE(SUM(Reconciliation.amount),0)"), + 'conditions' => array('Account.id' => $id), + 'fields' => array(), + )); + $balance = 0; + foreach ($unreconciled[$fund]['entries'] AS &$entry) { + //$balance += $entry[0]['balance']; +/* $entry["LedgerEntry"] += $entry[0]; */ +/* unset($entry[0]); */ + $entry = array_merge(array_diff_key($entry["LedgerEntry"], array(0=>true)), + $entry[0]); + $balance += $entry['balance']; + } + $unreconciled[$fund]['balance'] = $balance; + } - $unreconciled['credits'] = $this->find - ('all', array - ('link' => array - ('Ledger' => array - ('fields' => array(), - 'CreditLedgerEntry' => array - ('fields' => array('id', 'amount'), - 'CreditReconciliationLedgerEntry' => array - ('fields' => array('COALESCE(SUM(Reconciliation.amount),0) AS "reconciled"', - 'CreditLedgerEntry.amount - COALESCE(SUM(Reconciliation.amount),0) AS "balance"', - ), - ), - ), - ), - ), - 'group' => ('CreditLedgerEntry.id' . - ' HAVING CreditLedgerEntry.amount' . - ' <> COALESCE(SUM(Reconciliation.amount),0)'), - 'conditions' => array('Account.id' => $id), - 'fields' => array(), - )); + // pull up to the top level if only one fundamental type + if ($fundamental_type) + $unreconciled = $unreconciled[$fundamental_type]; return $unreconciled; } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: reconcileNewLedgerEntry + * - Returns which ledger entries a new credit/debit would + * reconcile, and how much. + * + * - REVISIT 20090617 + * This should be subject to different algorithms, such + * as apply to oldest charges first, newest first, to fees + * before rent, etc. Until we get there, I'll hardcode + * whatever algorithm is simplest. + */ + + function reconcileNewLedgerEntry($id, $fund, $amount) { + // if there is no money in the entry, it can reconcile nothing + // don't bother wasting time sifting ledger entries. + if ($amount <= 0) + return array('unapplied' => 0); + + $fund = $this->fundamentalOpposite($fund); + $unreconciled = $this->findUnreconciledLedgerEntries($id, $fund); + + $applied = 0; + foreach ($unreconciled['entries'] AS $i => &$entry) { + // Determine if amount is sufficient to cover the entry + if ($amount > $entry['balance']) + $apply = $entry['balance']; + elseif ($amount > 0) + $apply = $amount; + else { + unset($unreconciled[$i]); + continue; + } + + $entry['applied'] = $apply; + $entry['reconciled'] += $apply; + $entry['balance'] -= $apply; + $applied += $apply; + $amount -= $apply; + } + + $unreconciled['unapplied'] = $amount; + $unreconciled['applied'] = $applied; + $unreconciled['balance'] -= $applied; + return $unreconciled; + } + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/models/customer.php b/site/models/customer.php index dc22db0..2aa94e5 100644 --- a/site/models/customer.php +++ b/site/models/customer.php @@ -75,7 +75,7 @@ class Customer extends AppModel { * (such as charges not paid). */ - function findUnreconciledLedgerEntries($id = null) { + function findUnreconciledLedgerEntries($id = null, $fundamental_type = null) { $customer = $this->find('first', array('contain' => array('Lease' => array('fields' => array('id'))), @@ -83,20 +83,117 @@ class Customer extends AppModel { 'conditions' => array(array('Customer.id' => $id)))); $unreconciled = $this->Account->findUnreconciledLedgerEntries - ($customer['Customer']['account_id']); + ($customer['Customer']['account_id'], $fundamental_type); foreach ($customer['Lease'] AS $lease) { - $lease_unrec = $this->Lease->findUnreconciledLedgerEntries($lease['id']); - $unreconciled['debits'] = array_merge($unreconciled['debits'], - $lease_unrec['debits']); - $unreconciled['credits'] = array_merge($unreconciled['credits'], - $lease_unrec['credits']); + $unrec = $this->Lease->findUnreconciledLedgerEntries($lease['id'], + $fundamental_type); + + foreach (array('debit', 'credit', 'entries') AS $type) { + if (!isset($unreconciled[$type])) + continue; + + if ($type == 'entries') { + $left = &$unreconciled; + $right = &$unrec; + } else { + $left = &$unreconciled[$type]; + $right = &$unrec[$type]; + } + + $left['entries'] = array_merge($left['entries'], $right['entries']); + $left['balance'] += $right['balance']; + } + +/* if ($fundamental_type) { */ +/* $unreconciled['entries'] */ +/* = array_merge($unreconciled['entries'], $unrec['entries']); */ +/* } */ +/* else { */ +/* foreach (array_keys($unreconciled) AS $type) { */ +/* $unreconciled[$type]['entries'] */ +/* = array_merge($unreconciled[$type]['entries'], */ +/* $unrec[$type]['entries']); */ +/* $unreconciled['balance'] += $unrec['balance']; */ +/* } */ +/* } */ + +/* $balance = $unreconciled['balance']; */ +/* $unreconciled = array_merge_recursive */ +/* (array_diff_key($unreconciled, array('balance'=>1)), */ +/* $this->Lease->findUnreconciledLedgerEntries($lease['id'])); */ +/* $unreconciled['balance'] += $balance; */ } return $unreconciled; } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: reconcileNewLedgerEntry + * - Returns which ledger entries a new credit/debit would + * reconcile, and how much. + * + * - REVISIT 20090617 + * This should be subject to different algorithms, such + * as apply to oldest charges first, newest first, to fees + * before rent, etc. Until we get there, I'll hardcode + * whatever algorithm is simplest. + */ + + function reconcileNewLedgerEntry($id, $fund, $amount) { + $customer = $this->find('first', + array('contain' => + array('Lease' => array('fields' => array('id'))), + 'fields' => array('account_id'), + 'conditions' => array(array('Customer.id' => $id)))); + + $reconciled = $this->Account->reconcileNewLedgerEntry + ($customer['Customer']['account_id'], $fund, $amount); + + foreach ($customer['Lease'] AS $lease) { + $rec = $this->Lease->reconcileNewLedgerEntry($lease['id'], + $fund, + $reconciled['unapplied']); + + //pr(compact('reconciled', 'rec')); + foreach (array('debit', 'credit', 'entries') AS $type) { + if (!isset($reconciled[$type])) + continue; + + if ($type == 'entries') { + $left = &$reconciled; + $right = &$rec; + } else { + $left = &$reconciled[$type]; + $right = &$rec[$type]; + } + + //pr(compact('type', 'left', 'right')); + $left['entries'] = array_merge($left['entries'], $right['entries']); + $left['balance'] += $right['balance']; + $left['applied'] += $right['applied']; + $left['unapplied'] = $right['unapplied']; + } + } + +/* foreach ($customer['Lease'] AS $lease) { */ +/* $unapplied = $unreconciled['unapplied']; */ +/* $balance = $unreconciled['balance']; */ +/* $unreconciled = array_merge_recursive */ +/* (array_diff_key($unreconciled, array('unapplied'=>1, 'balance'=>1)), */ +/* $this->Lease->reconcileNewLedgerEntry($lease['id'], */ +/* $fund, */ +/* $unreconciled['unapplied'])); */ +/* $unreconciled['balance'] += $balance; */ +/* } */ + + return $reconciled; + } + + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/models/lease.php b/site/models/lease.php index a611e85..c6e8175 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -30,6 +30,24 @@ class Lease extends AppModel { 'LateSchedule', ); + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: accountId + * - Returns the accountId of the given lease + */ + function accountId($id) { + $this->cacheQueries = true; + $lease = $this->find('first', array + ('recursive' => -1, + 'fields' => array('account_id'), + 'conditions' => array(array('id' => $id)), + )); + $this->cacheQueries = false; + + return $lease['Lease']['account_id']; + } + /************************************************************************** ************************************************************************** @@ -43,14 +61,9 @@ class Lease extends AppModel { /* 'args' => compact('id', 'all', 'cond', 'link'), */ /* )); */ - $lease = $this->find('first', array - ('recursive' => -1, - 'fields' => array('account_id'), - 'conditions' => array(array('id' => $id)), - )); - - $entries = $this->Account->findLedgerEntries($lease['Lease']['account_id'], + $entries = $this->Account->findLedgerEntries($this->accountId($id), $all, $cond, $link); + /* pr(array('function' => 'Lease::findAccountEntries', */ /* 'args' => compact('id', 'all', 'cond', 'link'), */ /* 'vars' => compact('lease'), */ @@ -71,14 +84,8 @@ class Lease extends AppModel { /* 'args' => compact('id', 'link'), */ /* )); */ - $lease = $this->find('first', array - ('recursive' => -1, - 'fields' => array('account_id'), - 'conditions' => array(array('id' => $id)), - )); - $entries = $this->Account->findLedgerEntriesRelatedToAccount - ($lease['Lease']['account_id'], + ($this->accountId($id), $this->Account->securityDepositAccountID(), true, null, $link); @@ -99,14 +106,29 @@ class Lease extends AppModel { * (such as charges not paid). */ - function findUnreconciledLedgerEntries($id = null) { - $lease = $this->find('first', array - ('recursive' => -1, - 'fields' => array('account_id'), - 'conditions' => array(array('id' => $id)), - )); + function findUnreconciledLedgerEntries($id = null, $fundamental_type = null) { + return $this->Account->findUnreconciledLedgerEntries + ($this->accountId($id), $fundamental_type); + } - return $this->Account->findUnreconciledLedgerEntries($lease['Lease']['account_id']); + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: reconcileNewLedgerEntry + * - Returns which ledger entries a new credit/debit would + * reconcile, and how much. + * + * - REVISIT 20090617 + * This should be subject to different algorithms, such + * as apply to oldest charges first, newest first, to fees + * before rent, etc. Until we get there, I'll hardcode + * whatever algorithm is simplest. + */ + + function reconcileNewLedgerEntry($id, $fund, $amount) { + return $this->Account->reconcileNewLedgerEntry + ($this->accountId($id), $fund, $amount); } From ba218fbeebb9670b62fc08545eae2ec29fa2f40e Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 17 Jun 2009 19:12:22 +0000 Subject: [PATCH 161/717] Changed the unreconciled transaction list to always include 'debit' or 'credit', even if the user specifically requests one or the other. Handling it as a special case everywhere was bothering me. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@162 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/account.php | 56 +++++++--------- site/models/customer.php | 140 ++++++++++++++++----------------------- site/models/lease.php | 4 +- 3 files changed, 85 insertions(+), 115 deletions(-) diff --git a/site/models/account.php b/site/models/account.php index 13333a6..8945109 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -262,9 +262,6 @@ class Account extends AppModel { )); $balance = 0; foreach ($unreconciled[$fund]['entries'] AS &$entry) { - //$balance += $entry[0]['balance']; -/* $entry["LedgerEntry"] += $entry[0]; */ -/* unset($entry[0]); */ $entry = array_merge(array_diff_key($entry["LedgerEntry"], array(0=>true)), $entry[0]); $balance += $entry['balance']; @@ -272,10 +269,6 @@ class Account extends AppModel { $unreconciled[$fund]['balance'] = $balance; } - // pull up to the top level if only one fundamental type - if ($fundamental_type) - $unreconciled = $unreconciled[$fundamental_type]; - return $unreconciled; } @@ -294,37 +287,38 @@ class Account extends AppModel { * whatever algorithm is simplest. */ - function reconcileNewLedgerEntry($id, $fund, $amount) { + function reconcileNewLedgerEntry($id, $fundamental_type, $amount) { + $ofund = $this->fundamentalOpposite($fundamental_type); + $unreconciled = array($ofund => array('entries'=>array(), 'balance'=>0)); + $applied = 0; + // if there is no money in the entry, it can reconcile nothing // don't bother wasting time sifting ledger entries. - if ($amount <= 0) - return array('unapplied' => 0); + if ($amount > 0) { + $unreconciled = $this->findUnreconciledLedgerEntries($id, $ofund); - $fund = $this->fundamentalOpposite($fund); - $unreconciled = $this->findUnreconciledLedgerEntries($id, $fund); + foreach ($unreconciled[$ofund]['entries'] AS $i => &$entry) { + // Determine if amount is sufficient to cover the entry + if ($amount > $entry['balance']) + $apply = $entry['balance']; + elseif ($amount > 0) + $apply = $amount; + else { + unset($unreconciled[$i]); + continue; + } - $applied = 0; - foreach ($unreconciled['entries'] AS $i => &$entry) { - // Determine if amount is sufficient to cover the entry - if ($amount > $entry['balance']) - $apply = $entry['balance']; - elseif ($amount > 0) - $apply = $amount; - else { - unset($unreconciled[$i]); - continue; + $entry['applied'] = $apply; + $entry['reconciled'] += $apply; + $entry['balance'] -= $apply; + $applied += $apply; + $amount -= $apply; } - - $entry['applied'] = $apply; - $entry['reconciled'] += $apply; - $entry['balance'] -= $apply; - $applied += $apply; - $amount -= $apply; } - $unreconciled['unapplied'] = $amount; - $unreconciled['applied'] = $applied; - $unreconciled['balance'] -= $applied; + $unreconciled[$ofund]['unapplied'] = $amount; + $unreconciled[$ofund]['applied'] = $applied; + $unreconciled[$ofund]['balance'] -= $applied; return $unreconciled; } diff --git a/site/models/customer.php b/site/models/customer.php index 2aa94e5..e6475d5 100644 --- a/site/models/customer.php +++ b/site/models/customer.php @@ -28,6 +28,46 @@ class Customer extends AppModel { ); + /************************************************************************** + ************************************************************************** + ************************************************************************** + * 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; + } + /************************************************************************** ************************************************************************** ************************************************************************** @@ -39,19 +79,13 @@ class Customer extends AppModel { /* 'args' => compact('id', 'link'), */ /* )); */ - $customer = $this->find('first', - array('contain' => - array('Lease' => array('fields' => array('id'))), - 'fields' => array('account_id'), - 'conditions' => array(array('Customer.id' => $id)))); - $entries = $this->Account->findLedgerEntriesRelatedToAccount - ($customer['Customer']['account_id'], + ($this->accountId($id), $this->Account->securityDepositAccountID(), true, null, $link); - foreach ($customer['Lease'] AS $lease) { - $ledger_entries = $this->Lease->findSecurityDeposits($lease['id'], $link); + foreach ($this->leaseIds($id) AS $lease_id) { + $ledger_entries = $this->Lease->findSecurityDeposits($lease_id, $link); $this->statsMerge($entries['summary'], $ledger_entries['summary']); $entries['Entries'] = array_merge($entries['Entries'], $ledger_entries['Entries']); @@ -76,53 +110,21 @@ class Customer extends AppModel { */ function findUnreconciledLedgerEntries($id = null, $fundamental_type = null) { - $customer = $this->find('first', - array('contain' => - array('Lease' => array('fields' => array('id'))), - 'fields' => array('account_id'), - 'conditions' => array(array('Customer.id' => $id)))); $unreconciled = $this->Account->findUnreconciledLedgerEntries - ($customer['Customer']['account_id'], $fundamental_type); + ($this->accountId($id), $fundamental_type); - foreach ($customer['Lease'] AS $lease) { - $unrec = $this->Lease->findUnreconciledLedgerEntries($lease['id'], + foreach ($this->leaseIds($id) AS $lease_id) { + $unrec = $this->Lease->findUnreconciledLedgerEntries($lease_id, $fundamental_type); - foreach (array('debit', 'credit', 'entries') AS $type) { - if (!isset($unreconciled[$type])) - continue; - - if ($type == 'entries') { - $left = &$unreconciled; - $right = &$unrec; - } else { - $left = &$unreconciled[$type]; - $right = &$unrec[$type]; - } + foreach (array_keys($unreconciled) AS $type) { + $left = &$unreconciled[$type]; + $right = &$unrec[$type]; $left['entries'] = array_merge($left['entries'], $right['entries']); $left['balance'] += $right['balance']; } - -/* if ($fundamental_type) { */ -/* $unreconciled['entries'] */ -/* = array_merge($unreconciled['entries'], $unrec['entries']); */ -/* } */ -/* else { */ -/* foreach (array_keys($unreconciled) AS $type) { */ -/* $unreconciled[$type]['entries'] */ -/* = array_merge($unreconciled[$type]['entries'], */ -/* $unrec[$type]['entries']); */ -/* $unreconciled['balance'] += $unrec['balance']; */ -/* } */ -/* } */ - -/* $balance = $unreconciled['balance']; */ -/* $unreconciled = array_merge_recursive */ -/* (array_diff_key($unreconciled, array('balance'=>1)), */ -/* $this->Lease->findUnreconciledLedgerEntries($lease['id'])); */ -/* $unreconciled['balance'] += $balance; */ } return $unreconciled; @@ -143,35 +145,20 @@ class Customer extends AppModel { * whatever algorithm is simplest. */ - function reconcileNewLedgerEntry($id, $fund, $amount) { - $customer = $this->find('first', - array('contain' => - array('Lease' => array('fields' => array('id'))), - 'fields' => array('account_id'), - 'conditions' => array(array('Customer.id' => $id)))); + function reconcileNewLedgerEntry($id, $fundamental_type, $amount) { $reconciled = $this->Account->reconcileNewLedgerEntry - ($customer['Customer']['account_id'], $fund, $amount); + ($this->accountId($id), $fundamental_type, $amount); - foreach ($customer['Lease'] AS $lease) { - $rec = $this->Lease->reconcileNewLedgerEntry($lease['id'], - $fund, - $reconciled['unapplied']); + foreach ($this->leaseIds($id) AS $lease_id) { + foreach (array_keys($reconciled) AS $type) { + $rec = $this->Lease->reconcileNewLedgerEntry($lease_id, + $fundamental_type, + $reconciled[$type]['unapplied']); - //pr(compact('reconciled', 'rec')); - foreach (array('debit', 'credit', 'entries') AS $type) { - if (!isset($reconciled[$type])) - continue; + $left = &$reconciled[$type]; + $right = &$rec[$type]; - if ($type == 'entries') { - $left = &$reconciled; - $right = &$rec; - } else { - $left = &$reconciled[$type]; - $right = &$rec[$type]; - } - - //pr(compact('type', 'left', 'right')); $left['entries'] = array_merge($left['entries'], $right['entries']); $left['balance'] += $right['balance']; $left['applied'] += $right['applied']; @@ -179,17 +166,6 @@ class Customer extends AppModel { } } -/* foreach ($customer['Lease'] AS $lease) { */ -/* $unapplied = $unreconciled['unapplied']; */ -/* $balance = $unreconciled['balance']; */ -/* $unreconciled = array_merge_recursive */ -/* (array_diff_key($unreconciled, array('unapplied'=>1, 'balance'=>1)), */ -/* $this->Lease->reconcileNewLedgerEntry($lease['id'], */ -/* $fund, */ -/* $unreconciled['unapplied'])); */ -/* $unreconciled['balance'] += $balance; */ -/* } */ - return $reconciled; } diff --git a/site/models/lease.php b/site/models/lease.php index c6e8175..73b9950 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -126,9 +126,9 @@ class Lease extends AppModel { * whatever algorithm is simplest. */ - function reconcileNewLedgerEntry($id, $fund, $amount) { + function reconcileNewLedgerEntry($id, $fundamental_type, $amount) { return $this->Account->reconcileNewLedgerEntry - ($this->accountId($id), $fund, $amount); + ($this->accountId($id), $fundamental_type, $amount); } From a2ae522b2d684b940e677813affd0b725952abb2 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 18 Jun 2009 00:49:40 +0000 Subject: [PATCH 162/717] Further progress on payment entries. There is an outstanding charges grid, but it doesn't have amounts due to the way I designed the ledger_entries element. I'll do a bit of rework on that next. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@163 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/customers_controller.php | 50 +++++++- site/models/account.php | 8 +- site/models/customer.php | 4 +- site/views/customers/payment.ctp | 133 ++++++++++++++++------ site/views/elements/customers.ctp | 2 +- site/views/elements/ledger_entries.ctp | 4 +- site/webroot/js/pmgr.js | 102 +++++++++++++++++ 7 files changed, 255 insertions(+), 48 deletions(-) diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index d0a1238..d3e8ef7 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -180,15 +180,59 @@ class CustomersController extends AppController { /* $customer = $this->data; */ /* } */ if (isset($id)) { - $customer = $this->Customer->details($id); - unset($customer['deposits']['Entries']); + $this->Customer->recursive = -1; + $customer = $this->Customer->read(null, $id); + $customer = $customer['Customer']; + $unreconciled = $this->Customer->findUnreconciledLedgerEntries($id); + $charges = $unreconciled['debit']; } else { $customer = null; + $charges = array('balance' => 0, 'entry' => array()); } $title = 'Payment Entry'; - $this->set(compact('customer', 'title')); + $this->set(compact('customer', 'charges', 'title')); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: unreconciledEntries + * - returns the list of unreconciled entries + */ + + function unreconciled($id) { + + //$this->layout = 'ajax'; + $this->layout = null; + $this->autoLayout = false; + $this->autoRender = false; + Configure::write('debug', '0'); + header("Content-type: text/xml;charset=utf-8"); + + App::import('Helper', 'Xml'); + $xml = new XmlHelper(); + + // Find the unreconciled entries, then manipulate the structure + // slightly to accomodate the format necessary for XML Helper. + $unreconciled = $this->Customer->findUnreconciledLedgerEntries($id); + $unreconciled = array('entries' => + array_intersect_key($unreconciled['debit'], + array('entry'=>1, 'balance'=>1))); + + // XML Helper will dump an empty tag if the array is empty + if (!count($unreconciled['entries']['entry'])) + unset($unreconciled['entries']['entry']); + + pr($unreconciled); + //$reconciled = $cust->reconcileNewLedgerEntry($cust_id, 'credit', $amount); + + $opts = array(); + //$opts['format'] = 'tags'; + echo $xml->header(); + echo $xml->serialize($unreconciled, $opts); } } diff --git a/site/models/account.php b/site/models/account.php index 8945109..e007bc8 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -236,7 +236,7 @@ class Account extends AppModel { ? array($fundamental_type) : array('debit', 'credit')) AS $fund) { $ucfund = ucfirst($fund); - $unreconciled[$fund]['entries'] = $this->find + $unreconciled[$fund]['entry'] = $this->find ('all', array ('link' => array ('Ledger' => array @@ -261,7 +261,7 @@ class Account extends AppModel { 'fields' => array(), )); $balance = 0; - foreach ($unreconciled[$fund]['entries'] AS &$entry) { + foreach ($unreconciled[$fund]['entry'] AS &$entry) { $entry = array_merge(array_diff_key($entry["LedgerEntry"], array(0=>true)), $entry[0]); $balance += $entry['balance']; @@ -289,7 +289,7 @@ class Account extends AppModel { function reconcileNewLedgerEntry($id, $fundamental_type, $amount) { $ofund = $this->fundamentalOpposite($fundamental_type); - $unreconciled = array($ofund => array('entries'=>array(), 'balance'=>0)); + $unreconciled = array($ofund => array('entry'=>array(), 'balance'=>0)); $applied = 0; // if there is no money in the entry, it can reconcile nothing @@ -297,7 +297,7 @@ class Account extends AppModel { if ($amount > 0) { $unreconciled = $this->findUnreconciledLedgerEntries($id, $ofund); - foreach ($unreconciled[$ofund]['entries'] AS $i => &$entry) { + foreach ($unreconciled[$ofund]['entry'] AS $i => &$entry) { // Determine if amount is sufficient to cover the entry if ($amount > $entry['balance']) $apply = $entry['balance']; diff --git a/site/models/customer.php b/site/models/customer.php index e6475d5..4064fe0 100644 --- a/site/models/customer.php +++ b/site/models/customer.php @@ -122,7 +122,7 @@ class Customer extends AppModel { $left = &$unreconciled[$type]; $right = &$unrec[$type]; - $left['entries'] = array_merge($left['entries'], $right['entries']); + $left['entry'] = array_merge($left['entry'], $right['entry']); $left['balance'] += $right['balance']; } } @@ -159,7 +159,7 @@ class Customer extends AppModel { $left = &$reconciled[$type]; $right = &$rec[$type]; - $left['entries'] = array_merge($left['entries'], $right['entries']); + $left['entry'] = array_merge($left['entry'], $right['entry']); $left['balance'] += $right['balance']; $left['applied'] += $right['applied']; $left['unapplied'] = $right['unapplied']; diff --git a/site/views/customers/payment.ctp b/site/views/customers/payment.ctp index 9023240..2ec59e5 100644 --- a/site/views/customers/payment.ctp +++ b/site/views/customers/payment.ctp @@ -54,36 +54,14 @@ $grid_setup = array(); -if (isset($customer['Customer']['id'])) +if (isset($customer['id'])) $grid_setup['hiddengrid'] = true; $grid_setup['onSelectRow'] = array ('--special' => - 'function(ids) { if (ids != null)' . - ' {' . - // Set the customer id that will be returned with the form - ' $("#customer-id").val(ids);' . - // Get the customer name from the grid - ' $("#payment_customer").html($("#"+$(this).attr("id"))' . - ' .getCell(ids, "Customer-name"));' . - // Replace that with just the text portion of the hyperlink - ' $("#payment_customer").html("Receipt for "+ $("#payment_customer a").html());' . - ' } }' + 'function(ids) { if (ids != null) { onRowSelect("#"+$(this).attr("id"), ids); } }' ); -/* $grid_setup['loadComplete'] = array */ -/* ('--special' => */ -/* 'function() { ' . */ -/* //' $("#"+$(this).attr("id")).setSelection($("#customer-id").val());' . */ -/* ' $(\'#customers-list-jqGrid\').setSelection($(\'#customer-id\').val());' . */ -/* ' $("#"+$(this).attr("id")).setCaption("Hello");' . */ -/* ' alert("Loaded");' . */ -/* ' }' */ -/* ); */ - - -//pr($customer); -//echo ('Get grid code
    '); // Customer // Outstanding balance @@ -95,7 +73,7 @@ $grid_setup['onSelectRow'] = array ?> - ' . "\n"; echo $this->element('customers', - array('caption' => 'Select Customer', + array('grid_div_id' => 'customers-list', + 'caption' => ('Select Customer'), 'limit' => 7, 'grid_setup' => $grid_setup, )); -echo ('

    ' . - (isset($customer['Customer']['id']) - ? 'Receipt for ' . $customer['Customer']['name'] - : 'Please select customer') . - '

    ' . "\n"); +echo $this->element('ledger_entries', + array('grid_div_id' => 'charge-entries', + 'caption' => 'Outstanding Charges', +/* (isset($customer['name']) */ +/* ? " for {$customer['name']}: ".FormatHelper::currency($charges['balance']) */ +/* : '')), */ + 'limit' => 8, + 'ledger_id' => 6, + 'account_type' => 'credit', + 'ledger_entries' => $charges['entry'], + )); + +echo ('

    ' . + '' . + 'Enter new receipt for ' . + '' . (isset($customer['name']) ? $customer['name'] : "") . '' . + '' . + '' . + 'Please select customer' . + '' . + '

    ' . "\n"); echo $form->create(null, array('id' => 'payment-form', 'url' => array('controller' => 'transactions', @@ -373,7 +427,7 @@ echo $form->create(null, array('id' => 'payment-form', ***************************************************/ ?> - +
    Payments @@ -393,12 +447,10 @@ echo $form->end('Post Payment'); //echo '
    ' . "\n"; // End of the dialog DIV ?> -Clear Debug Output Create Payment */ ?> -

    Request

    Response

    Output

    @@ -412,6 +464,13 @@ echo $form->end('Post Payment'); $("#datepicker").datepicker() .datepicker('setDate', '+0'); + + $("#customer-id").val(); + updateChargesCaption("", + ); + + + /* $("#dialog").dialog({ */ /* bgiframe: true, */ /* autoOpen: false, */ @@ -439,8 +498,10 @@ echo $form->end('Post Payment'); /* }); */ }); + +
    - +Clear Debug Output diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index 4cfa0e3..f7a31fd 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -15,7 +15,7 @@ $jqGrid_options = array('jqGridColumns' => $cols, 'controller' => 'customers'); // User requested options have priority -$jqGrid_options += compact('caption', 'grid_setup', 'limit'); +$jqGrid_options += compact('grid_div_id', 'grid_id', 'caption', 'grid_setup', 'limit'); if (isset($customers)) { $jqGrid_options += array('custom_ids' => diff --git a/site/views/elements/ledger_entries.ctp b/site/views/elements/ledger_entries.ctp index 2a54d43..09cbbea 100644 --- a/site/views/elements/ledger_entries.ctp +++ b/site/views/elements/ledger_entries.ctp @@ -18,11 +18,11 @@ $custom_post_data = array('ledger_id' => $ledger_id, 'account_type' => $account_type); $jqGrid_options = array('jqGridColumns' => $cols, - 'grid_id' => isset($grid_id) ? $grid_id : null, - 'caption' => isset($caption) ? $caption : null, 'controller' => 'ledger_entries', ); +$jqGrid_options += compact('grid_div_id', 'grid_id', 'caption', 'grid_setup', 'limit'); + if (isset($ledger_entries)) { $jqGrid_options += array('custom_ids' => array_map(create_function('$data', diff --git a/site/webroot/js/pmgr.js b/site/webroot/js/pmgr.js index c264ac1..d7e931a 100644 --- a/site/webroot/js/pmgr.js +++ b/site/webroot/js/pmgr.js @@ -134,3 +134,105 @@ function fmtCurrency(amount) { } +// REVISIT : 20090617 +// I would rather use XML to pass from JS to PHP, but at the +// moment things were working just fine with serialize, and +// I'm not keen on redesigning it at the moment. So, here +// is a serialize implementation I found on the web. + +function serialize( mixed_value ) { + // http://kevin.vanzonneveld.net + // + original by: Arpad Ray (mailto:arpad@php.net) + // + improved by: Dino + // + bugfixed by: Andrej Pavlovic + // + bugfixed by: Garagoth + // + input by: DtTvB (http://dt.in.th/2008-09-16.string-length-in-bytes.html) + // + bugfixed by: Russell Walker + // % note: We feel the main purpose of this function should be to ease the transport of data between php & js + // % note: Aiming for PHP-compatibility, we have to translate objects to arrays + // * example 1: serialize(['Kevin', 'van', 'Zonneveld']); + // * returns 1: 'a:3:{i:0;s:5:"Kevin";i:1;s:3:"van";i:2;s:9:"Zonneveld";}' + // * example 2: serialize({firstName: 'Kevin', midName: 'van', surName: 'Zonneveld'}); + // * returns 2: 'a:3:{s:9:"firstName";s:5:"Kevin";s:7:"midName";s:3:"van";s:7:"surName";s:9:"Zonneveld";}' + + var _getType = function( inp ) { + var type = typeof inp, match; + var key; + if (type == 'object' && !inp) { + return 'null'; + } + if (type == "object") { + if (!inp.constructor) { + return 'object'; + } + var cons = inp.constructor.toString(); + match = cons.match(/(\w+)\(/); + if (match) { + cons = match[1].toLowerCase(); + } + var types = ["boolean", "number", "string", "array"]; + for (key in types) { + if (cons == types[key]) { + type = types[key]; + break; + } + } + } + return type; + }; + var type = _getType(mixed_value); + var val, ktype = ''; + + switch (type) { + case "function": + val = ""; + break; + case "undefined": + val = "N"; + break; + case "boolean": + val = "b:" + (mixed_value ? "1" : "0"); + break; + case "number": + val = (Math.round(mixed_value) == mixed_value ? "i" : "d") + ":" + mixed_value; + break; + case "string": + val = "s:" + encodeURIComponent(mixed_value).replace(/%../g, 'x').length + ":\"" + mixed_value + "\""; + break; + case "array": + case "object": + val = "a"; + /* + if (type == "object") { + var objname = mixed_value.constructor.toString().match(/(\w+)\(\)/); + if (objname == undefined) { + return; + } + objname[1] = serialize(objname[1]); + val = "O" + objname[1].substring(1, objname[1].length - 1); + } + */ + var count = 0; + var vals = ""; + var okey; + var key; + for (key in mixed_value) { + ktype = _getType(mixed_value[key]); + if (ktype == "function") { + continue; + } + + okey = (key.match(/^[0-9]+$/) ? parseInt(key, 10) : key); + vals += serialize(okey) + + serialize(mixed_value[key]); + count++; + } + val += ":" + count + ":{" + vals + "}"; + break; + } + if (type != "object" && type != "array") { + val += ";"; + } + return val; + +} From 063aec6c3cb4a12827374169c61e0c96d85d4bb8 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 18 Jun 2009 03:43:05 +0000 Subject: [PATCH 163/717] Fixed a confusion over the usage of the 'opposite' function, which was converting, for example, from 'ASSET' to 'credit'. However, it seemed like it could be used to convert from 'debit' to 'credit', but it didn't work that way. So, I modified it to do so, and made things a bit more robust by making the comparisons case insensitive. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@164 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/account.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/site/models/account.php b/site/models/account.php index e007bc8..af7fc34 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -52,7 +52,7 @@ class Account extends AppModel { $type = $id_or_type; // Asset and Expense accounts are debit accounts - if (in_array($type, array('ASSET', 'EXPENSE'))) + if (in_array(strtoupper($type), array('ASSET', 'EXPENSE'))) return 'debit'; // Otherwise, it's a credit account @@ -67,7 +67,10 @@ class Account extends AppModel { * - Returns the opposite fundmental type of the account, credit or debit */ function fundamentalOpposite($id_or_type) { - $fund = $this->fundamentalType($id_or_type); + if (in_array(strtolower($id_or_type), array('credit', 'debit'))) + $fund = $id_or_type; + else + $fund = $this->fundamentalType($id_or_type); if ($fund == 'debit') return 'credit'; From 9b6830468ebc921340ec608a8befd11685b4455f Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 18 Jun 2009 03:45:43 +0000 Subject: [PATCH 164/717] Modified to prevent stepping on the user's action if already set. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@165 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/jqGrid.ctp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/site/views/elements/jqGrid.ctp b/site/views/elements/jqGrid.ctp index f41e985..1b4ae4b 100644 --- a/site/views/elements/jqGrid.ctp +++ b/site/views/elements/jqGrid.ctp @@ -77,7 +77,8 @@ $postData['fields'] = serialize(array_map(create_function('$col', // Determine if we're to be using a custom list, or if // the data will simply be action based. if (isset($custom_ids)) { - $action = 'idlist'; + if (!isset($action)) + $action = 'idlist'; $postData['idlist'] = serialize($custom_ids); } elseif (!isset($action)) { From 3e5ac6410898225481a5c595f19e78980a9dfbf6 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 18 Jun 2009 03:57:43 +0000 Subject: [PATCH 165/717] Although I'm not too happy with the modifications, I do have a working version that minimizes the columns need to display ledger entries. The logic feels screwy to me, but I've beat my head on it long enough. I'll move on to something else and come back to it when my head clears. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@166 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 5 +- .../controllers/ledger_entries_controller.php | 105 +++++++++++++----- site/models/ledger_entry.php | 90 +++++++++++---- site/views/customers/payment.ctp | 9 +- site/views/elements/ledger_entries.ctp | 41 ++++--- site/views/ledger_entries/view.ctp | 19 ++-- 6 files changed, 189 insertions(+), 80 deletions(-) diff --git a/site/app_controller.php b/site/app_controller.php index 93e5135..f203193 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -248,7 +248,10 @@ class AppController extends Controller { } if (isset($params['action']) && $params['action'] === 'idlist') { - $conditions[] = array($model->alias.'.'.$model->primaryKey => $params['idlist']); + if (count($params['idlist'])) + $conditions[] = array($model->alias.'.'.$model->primaryKey => $params['idlist']); + else + $conditions[] = '0=1'; } return $conditions; diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index 3ca7f71..c4c9c59 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -32,31 +32,56 @@ class LedgerEntriesController extends AppController { array('fields' => array('id', 'stamp'), ), - 'DebitLedger' => - array('fields' => array('id', 'sequence'), - // Models - 'DebitAccount' => array('class' => 'Account', - 'fields' => array('id', 'name'), - ), - ), - - 'CreditLedger' => - array('fields' => array('id', 'sequence'), - // Models - 'CreditAccount' => array('class' => 'Account', - 'fields' => array('id', 'name'), - ), - ), - 'MonetarySource' => array('fields' => array('id', 'name'), ), ); - if ($params['action'] === 'reconcile') { - $type = $params['custom']['reconcile']; - $link[$type.'ReconciliationLedgerEntry'] = + if (isset($params['custom']['account_ftype'])) { + $ftype = $params['custom']['account_ftype']; + $ftype = ucfirst($ftype); + //$ftype = $this->LedgerEntry->DebitLedger->Account->fundamentalOpposite($ftype); + $link[$ftype . 'Ledger'] = + array('fields' => array('id', 'sequence'), + 'Account' => array('class' => 'Account', + 'fields' => array('id', 'name'), + ), + ); + } + elseif (isset($params['custom']['ledger_id'])) { + $ledger_id = $params['custom']['ledger_id']; + $link['Ledger'] = + array('fields' => array('id', 'sequence'), + 'conditions' => ("Ledger.id = IF(LedgerEntry.debit_ledger_id = $ledger_id," . + " LedgerEntry.credit_ledger_id," . + " LedgerEntry.debit_ledger_id)"), + 'Account' => array( + 'fields' => array('id', 'name'), + ), + ); + } + else { + $link['DebitLedger'] = + array('fields' => array('id', 'sequence'), + 'DebitAccount' => array('class' => 'Account', + 'fields' => array('id', 'name'), + ), + ); + + $link['CreditLedger'] = + array('fields' => array('id', 'sequence'), + 'CreditAccount' => array('class' => 'Account', + 'fields' => array('id', 'name'), + ), + ); + } + + if (isset($params['custom']['reconcile_id'])) { + $ftype = $params['custom']['account_ftype']; + $ftype = $this->LedgerEntry->DebitLedger->Account->fundamentalOpposite($ftype); + $ftype = ucfirst($ftype); + $link[$ftype.'ReconciliationLedgerEntry'] = array('fields' => array('Reconciliation.amount')); } @@ -64,21 +89,33 @@ class LedgerEntriesController extends AppController { } function jqGridDataFields(&$params, &$model) { - return $model->ledgerContextFields($params['custom']['ledger_id'], - $params['custom']['account_type']); + $ledger_id = (isset($params['custom']['ledger_id']) + ? $params['custom']['ledger_id'] + : null); + $account_type = (isset($params['custom']['account_type']) + ? $params['custom']['account_type'] + : null); + + return $model->ledgerContextFields($ledger_id, $account_type); } function jqGridDataConditions(&$params, &$model) { + $ledger_id = (isset($params['custom']['ledger_id']) + ? $params['custom']['ledger_id'] + : null); + $account_type = (isset($params['custom']['account_type']) + ? $params['custom']['account_type'] + : null); + $conditions = parent::jqGridDataConditions($params, $model); if ($params['action'] === 'ledger') { - $conditions[] = $model->ledgerContextConditions($params['custom']['ledger_id'], - $params['custom']['account_type']); + $conditions[] = $model->ledgerContextConditions($ledger_id, $account_type); } - if ($params['action'] === 'reconcile') { - $type = $params['custom']['reconcile']; - $other = ($type === 'Credit' ? 'debit' : 'credit'); - $conditions[] = array('Reconciliation.'.$other.'_ledger_entry_id' => $params['custom']['reconcile_id']); + if (isset($params['custom']['reconcile_id'])) { + $ftype = $params['custom']['account_ftype']; + //$ftype = $this->LedgerEntry->DebitLedger->Account->fundamentalOpposite($ftype); + $conditions[] = array('Reconciliation.'.$ftype.'_ledger_entry_id' => $params['custom']['reconcile_id']); } return $conditions; @@ -87,8 +124,13 @@ class LedgerEntriesController extends AppController { function jqGridRecordLinks(&$params, &$model, &$records, $links) { $links['Transaction'] = array('id'); $links['LedgerEntry'] = array('id'); - $links['DebitAccount'] = array('controller' => 'accounts', 'name'); - $links['CreditAccount'] = array('controller' => 'accounts', 'name'); + if (isset($params['custom']['account_ftype']) || isset($params['custom']['ledger_id'])) { + $links['Account'] = array('controller' => 'accounts', 'name'); + } + else { + $links['DebitAccount'] = array('controller' => 'accounts', 'name'); + $links['CreditAccount'] = array('controller' => 'accounts', 'name'); + } $links['MonetarySource'] = array('name'); return parent::jqGridRecordLinks($params, $model, $records, $links); } @@ -157,8 +199,11 @@ class LedgerEntriesController extends AppController { $stats['credit_amount_remaining'] = $entry['LedgerEntry']['amount'] - $stats['credit_amount_reconciled']; //pr($stats); + $reconciled = $this->LedgerEntry->findReconciledLedgerEntries($id); + //pr($reconciled); + // Prepare to render. $title = "Ledger Entry #{$entry['LedgerEntry']['id']}"; - $this->set(compact('entry', 'title', 'stats')); + $this->set(compact('entry', 'title', 'reconciled', 'stats')); } } diff --git a/site/models/ledger_entry.php b/site/models/ledger_entry.php index 9e16194..ad88596 100644 --- a/site/models/ledger_entry.php +++ b/site/models/ledger_entry.php @@ -61,29 +61,39 @@ class LedgerEntry extends AppModel { * as an argument for each function to avoid having to * query the ledger/account to find it out. */ - function ledgerContextFields($ledger_id, $account_type) { - if (in_array($account_type, array('ASSET', 'EXPENSE'))) - $ledger_type = 'debit'; - else - $ledger_type = 'credit'; + function ledgerContextFields($ledger_id = null, $account_type = null) { + $fields = array('id', 'name', 'comment', 'amount'); - return array - ('id', 'name', 'comment', - "IF(LedgerEntry.debit_ledger_id = $ledger_id," . - " LedgerEntry.amount, NULL) AS debit", - "IF(LedgerEntry.credit_ledger_id = $ledger_id," . - " LedgerEntry.amount, NULL) AS credit", - "(IF(LedgerEntry.{$ledger_type}_ledger_id = $ledger_id, 1, -1)" . - " * LedgerEntry.amount) AS balance", - ); + if (isset($ledger_id)) { + $fields[] = ("IF(LedgerEntry.debit_ledger_id = $ledger_id," . + " LedgerEntry.amount, NULL) AS debit"); + $fields[] = ("IF(LedgerEntry.credit_ledger_id = $ledger_id," . + " LedgerEntry.amount, NULL) AS credit"); + + if (isset($account_type)) { + if (in_array($account_type, array('ASSET', 'EXPENSE'))) + $ledger_type = 'debit'; + else + $ledger_type = 'credit'; + + $fields[] = ("(IF(LedgerEntry.{$ledger_type}_ledger_id = $ledger_id," . + " 1, -1) * LedgerEntry.amount) AS balance"); + } + } + + return $fields; } function ledgerContextConditions($ledger_id, $account_type) { - return array - ('OR' => - array(array('LedgerEntry.debit_ledger_id' => $ledger_id), - array('LedgerEntry.credit_ledger_id' => $ledger_id)), - ); + if (isset($ledger_id)) { + return array + ('OR' => + array(array('LedgerEntry.debit_ledger_id' => $ledger_id), + array('LedgerEntry.credit_ledger_id' => $ledger_id)), + ); + } + + return array(); } /************************************************************************** @@ -120,6 +130,48 @@ class LedgerEntry extends AppModel { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: findReconciledLedgerEntries + * - Returns ledger entries that are reconciled to the given entry. + * (such as payments towards a charge). + */ + + function findReconciledLedgerEntries($id = null, $fundamental_type = null) { + foreach (($fundamental_type + ? array($fundamental_type) + : array('debit', 'credit')) AS $fund) { + $ucfund = ucfirst($fund); + $reconciled[$fund]['entry'] = $this->find + ('all', array + ('link' => array + ("ReconciliationLedgerEntry" => array + ('class' => "{$ucfund}ReconciliationLedgerEntry", + 'fields' => array + ('id', + "COALESCE(SUM(Reconciliation.amount),0) AS 'reconciled'", + "LedgerEntry.amount - COALESCE(SUM(Reconciliation.amount),0) AS 'balance'", + ), + ), + ), + 'group' => ("ReconciliationLedgerEntry.id"), + 'conditions' => array('LedgerEntry.id' => $id), + 'fields' => array(), + )); + //pr($reconciled); + $balance = 0; + foreach ($reconciled[$fund]['entry'] AS &$entry) { + $entry = array_merge($entry["ReconciliationLedgerEntry"], $entry[0]); + $balance += $entry['balance']; + } + $reconciled[$fund]['balance'] = $balance; + } + + return $reconciled; + } + + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/views/customers/payment.ctp b/site/views/customers/payment.ctp index 2ec59e5..1c633e1 100644 --- a/site/views/customers/payment.ctp +++ b/site/views/customers/payment.ctp @@ -357,20 +357,15 @@ echo $this->element('customers', array('grid_div_id' => 'customers-list', 'caption' => ('Select Customer'), - 'limit' => 7, 'grid_setup' => $grid_setup, )); echo $this->element('ledger_entries', array('grid_div_id' => 'charge-entries', 'caption' => 'Outstanding Charges', -/* (isset($customer['name']) */ -/* ? " for {$customer['name']}: ".FormatHelper::currency($charges['balance']) */ -/* : '')), */ - 'limit' => 8, - 'ledger_id' => 6, - 'account_type' => 'credit', + 'account_ftype' => 'credit', 'ledger_entries' => $charges['entry'], + 'limit' => 8, )); echo ('

    ' . diff --git a/site/views/elements/ledger_entries.ctp b/site/views/elements/ledger_entries.ctp index 09cbbea..2fee5c3 100644 --- a/site/views/elements/ledger_entries.ctp +++ b/site/views/elements/ledger_entries.ctp @@ -5,17 +5,27 @@ $cols = array(); $cols['Transaction'] = array('index' => 'Transaction.id', 'formatter' => 'id'); $cols['Entry'] = array('index' => 'LedgerEntry.id', 'formatter' => 'id'); $cols['Date'] = array('index' => 'Transaction.stamp', 'formatter' => 'date'); -$cols['Debit Account'] = array('index' => 'DebitAccount.name', 'formatter' => 'longname'); -$cols['Credit Account'] = array('index' => 'CreditAccount.name', 'formatter' => 'longname'); +if (isset($account_ftype) || isset($ledger_id)) { + $cols['Account'] = array('index' => 'Account.name', 'formatter' => 'longname'); +} +else { + $cols['Debit Account'] = array('index' => 'DebitAccount.name', 'formatter' => 'longname'); + $cols['Credit Account'] = array('index' => 'CreditAccount.name', 'formatter' => 'longname'); +} $cols['Source'] = array('index' => 'MonetarySource.name', 'formatter' => 'name'); $cols['Comment'] = array('index' => 'LedgerEntry.comment', 'formatter' => 'comment', 'width'=>150); -$cols['Debit'] = array('index' => 'debit', 'formatter' => 'currency'); -$cols['Credit'] = array('index' => 'credit', 'formatter' => 'currency'); -if (isset($reconcile)) +if (isset($account_ftype)) { + $cols['Amount'] = array('index' => 'LedgerEntry.amount', 'formatter' => 'currency'); +} +else { + $cols['Debit'] = array('index' => 'debit', 'formatter' => 'currency'); + $cols['Credit'] = array('index' => 'credit', 'formatter' => 'currency'); +} +if (isset($reconcile_id)) { $cols['Applied'] = array('index' => "Reconciliation.amount", 'formatter' => 'currency'); +} -$custom_post_data = array('ledger_id' => $ledger_id, - 'account_type' => $account_type); +$custom_post_data = compact('ledger_id', 'account_type', 'account_ftype'); $jqGrid_options = array('jqGridColumns' => $cols, 'controller' => 'ledger_entries', @@ -23,6 +33,11 @@ $jqGrid_options = array('jqGridColumns' => $cols, $jqGrid_options += compact('grid_div_id', 'grid_id', 'caption', 'grid_setup', 'limit'); +if (isset($ledger_id)) { + $jqGrid_options += array('action' => 'ledger', + 'limit' => 50); +} + if (isset($ledger_entries)) { $jqGrid_options += array('custom_ids' => array_map(create_function('$data', @@ -30,14 +45,10 @@ if (isset($ledger_entries)) { $ledger_entries), 'limit' => 10); } -elseif (isset($reconcile)) { - $custom_post_data += compact('reconcile', 'reconcile_id'); - $jqGrid_options += array('action' => 'reconcile', - 'limit' => 5); -} -else { - $jqGrid_options += array('action' => 'ledger', - 'limit' => 50); + +if (isset($reconcile_id)) { + $custom_post_data += compact('reconcile_id'); + $jqGrid_options += array('limit' => 5); } $jqGrid_options += compact('custom_post_data'); diff --git a/site/views/ledger_entries/view.ctp b/site/views/ledger_entries/view.ctp index fc49c57..51a6cec 100644 --- a/site/views/ledger_entries/view.ctp +++ b/site/views/ledger_entries/view.ctp @@ -99,20 +99,23 @@ echo '
    ' . "\n"; echo $this->element('ledger_entries', array('caption' => "Debit Applications", - 'grid_id' => 'debit_reconciliation_ledger_entries', - 'ledger_id' => $debit_ledger['id'], - 'account_type' => $debit_ledger['Account']['type'], - 'reconcile' => 'Credit', // Looking for credits to match this debit + 'grid_div_id' => 'debit_reconciliation_ledger_entries', + //'ledger_id' => $debit_ledger['id'], + //'account_type' => $debit_ledger['Account']['type'], + 'account_ftype' => 'debit', 'reconcile_id' => $entry['id'], + 'ledger_entries' => $reconciled['debit']['entry'], )); echo $this->element('ledger_entries', array('caption' => "Credit Applications", - 'grid_id' => 'credit_reconciliation_ledger_entries', - 'ledger_id' => $credit_ledger['id'], - 'account_type' => $credit_ledger['Account']['type'], - 'reconcile' => 'Debit', // Looking for debits to match this credit + 'grid_div_id' => 'credit_reconciliation_ledger_entries', + //'ledger_id' => $credit_ledger['id'], + //'account_type' => $credit_ledger['Account']['type'], + //'account_ftype' => 'debit', // Looking for debits to match this credit + 'account_ftype' => 'credit', 'reconcile_id' => $entry['id'], + 'ledger_entries' => $reconciled['credit']['entry'], )); From c8b781804a482bbc78066d7caf97412dc8efb171 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 18 Jun 2009 04:07:52 +0000 Subject: [PATCH 166/717] Modified Transaction view to use jqGrid for entries. Also fixed a bug in the ledger entries element, since there is no way for credit/debit to be populated without a ledger_id, it makes sense to base the column displays on the presence of ledger_id. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@167 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/ledger_entries.ctp | 8 ++-- site/views/transactions/view.ctp | 59 ++------------------------ 2 files changed, 8 insertions(+), 59 deletions(-) diff --git a/site/views/elements/ledger_entries.ctp b/site/views/elements/ledger_entries.ctp index 2fee5c3..70e8c1f 100644 --- a/site/views/elements/ledger_entries.ctp +++ b/site/views/elements/ledger_entries.ctp @@ -14,13 +14,13 @@ else { } $cols['Source'] = array('index' => 'MonetarySource.name', 'formatter' => 'name'); $cols['Comment'] = array('index' => 'LedgerEntry.comment', 'formatter' => 'comment', 'width'=>150); -if (isset($account_ftype)) { - $cols['Amount'] = array('index' => 'LedgerEntry.amount', 'formatter' => 'currency'); -} -else { +if (isset($ledger_id)) { $cols['Debit'] = array('index' => 'debit', 'formatter' => 'currency'); $cols['Credit'] = array('index' => 'credit', 'formatter' => 'currency'); } +else { + $cols['Amount'] = array('index' => 'LedgerEntry.amount', 'formatter' => 'currency'); +} if (isset($reconcile_id)) { $cols['Applied'] = array('index' => "Reconciliation.amount", 'formatter' => 'currency'); } diff --git a/site/views/transactions/view.ctp b/site/views/transactions/view.ctp index 973edbf..67e77cd 100644 --- a/site/views/transactions/view.ctp +++ b/site/views/transactions/view.ctp @@ -52,61 +52,10 @@ echo '
    ' . "\n"; * Entries */ -$headers = array('Entry', 'Debit', 'Credit', 'Amount', 'Comment',/* 'Total'*/); -$column_class = array(); -foreach (array_intersect($headers, array('Entry')) AS $k => $v) { - $column_class[$k] = 'id'; -} -foreach (array_intersect($headers, array('Amount', 'Total')) AS $k => $v) { - $column_class[$k] = 'currency'; -} -foreach (array_intersect($headers, array('Comment')) AS $k => $v) { - $column_class[$k] = 'slack'; -} - -$rows = array(); -$running_total = 0; -foreach($transaction['LedgerEntry'] AS $entry) { - $amount = $entry['amount']; - $running_total += $amount; - $rows[] = array($html->link('#'.$entry['id'], - array('controller' => 'ledger_entries', - 'action' => 'view', - $entry['id'])), - ($html->link($entry['DebitLedger']['Account']['name'], - array('controller' => 'accounts', - 'action' => 'view', - $entry['DebitLedger']['Account']['id'])) - . ' (' - . $html->link('#' . $entry['DebitLedger']['Account']['id'] - . '-' . $entry['DebitLedger']['sequence'], - array('controller' => 'ledgers', - 'action' => 'view', - $entry['DebitLedger']['id'])) - . ')'), - ($html->link($entry['CreditLedger']['Account']['name'], - array('controller' => 'accounts', - 'action' => 'view', - $entry['CreditLedger']['Account']['id'])) - . ' (' - . $html->link('#' . $entry['CreditLedger']['Account']['id'] - . '-' . $entry['CreditLedger']['sequence'], - array('controller' => 'ledgers', - 'action' => 'view', - $entry['CreditLedger']['id'])) - . ')'), - FormatHelper::currency($entry['amount']), - $entry['comment'], - //FormatHelper::currency($running_total), - ); -} - -echo $this->element('table', - array('class' => 'item entry list', - 'caption' => 'Entries in Transaction', - 'headers' => $headers, - 'rows' => $rows, - 'column_class' => $column_class)); +echo $this->element('ledger_entries', + array('caption' => 'Entries in Transaction', + 'ledger_entries' => $transaction['LedgerEntry'], + )); /* End "detail supporting" div */ From febd216810d37d91db477bf35d3aa3443e9fd867 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 18 Jun 2009 04:19:17 +0000 Subject: [PATCH 167/717] Added a ledger listing to the Lease view page, which was otherwise quite empty. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@168 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/leases_controller.php | 6 +++++- site/views/leases/view.ctp | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index c98e28b..15c0feb 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -107,7 +107,7 @@ class LeasesController extends AppController { array(// Models 'LeaseType', 'Unit', - 'Account' => array('Ledger'), + 'Account' => array('CurrentLedger'), 'Customer', ), 'conditions' => array(array('Lease.id' => $id)), @@ -128,6 +128,10 @@ class LeasesController extends AppController { $deposits = $this->Lease->findSecurityDeposits($lease['Lease']['id']); $outstanding_deposit = $deposits['summary']['balance']; + // Move the Leder stats into our alias 'CurrentLedger' + $lease['Account']['CurrentLedger'] += $lease['Account']['Ledger']; + unset($lease['Account']['Ledger']); + // Prepare to render $title = 'Lease: #' . $lease['Lease']['id']; $this->set(compact('lease', 'title', diff --git a/site/views/leases/view.ctp b/site/views/leases/view.ctp index e195f43..8ee77e9 100644 --- a/site/views/leases/view.ctp +++ b/site/views/leases/view.ctp @@ -79,6 +79,16 @@ echo '
    ' . "\n"; echo '
    ' . "\n"; +/********************************************************************** + * Current Ledger + */ + +echo $this->element('ledger_entries', + array('caption' => "Current Ledger: (#{$account['id']}-{$account['CurrentLedger']['sequence']})", + 'ledger_id' => $account['CurrentLedger']['id'], + 'account_type' => $account['type'], + )); + /* End "detail supporting" div */ echo '
    ' . "\n"; From 3270ad9bf06723c10f95c095654c84fd2cc19a25 Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 19 Jun 2009 16:17:14 +0000 Subject: [PATCH 168/717] While working on payments, commented out the form reset stuff so I don't have to keep reentering the data with every post. Also, changed the customer ID to be passed outside of 'Customer', which appears to cake as a model that needs to be updated. Finally, added a bogus parameter, until I can figure out why the Model::set() function fails to recognize model fields if the first item in the model array is another Model. This bogus field just ensures Model::set uses all the fields, and bogus is ultimately ignored since it's not a member of LedgerEntry. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@169 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/customers/payment.ctp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/site/views/customers/payment.ctp b/site/views/customers/payment.ctp index 1c633e1..4c3dac4 100644 --- a/site/views/customers/payment.ctp +++ b/site/views/customers/payment.ctp @@ -84,10 +84,10 @@ $grid_setup['onSelectRow'] = array // other available options: //url: url, // override for form's 'action' attribute - //type: type, // 'get' or 'post', override for form's 'method' attribute + //type: 'get', // 'get' or 'post', override for form's 'method' attribute //dataType: null, // 'xml', 'script', or 'json' (expected server response type) //clearForm: true, // clear all form fields after successful submit - resetForm: true, // reset the form after successful submit + //resetForm: true, // reset the form after successful submit // $.ajax options can be used here too, for example: //timeout: 3000, @@ -132,7 +132,7 @@ $grid_setup['onSelectRow'] = array if (statusText == 'success') { // get a clean slate - resetPaymentForm(); + //resetPaymentForm(); } else { alert('not successful??'); @@ -175,6 +175,7 @@ $grid_setup['onSelectRow'] = array foreach ($types AS $type => $name) { $div = '
    '; + $div .= ''; $div .= 'create(null, array('id' => 'payment-form', ***************************************************/ ?> - +
    Payments From 1508f963d34eaa64032b3de269c71aedb6664b88 Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 19 Jun 2009 16:19:18 +0000 Subject: [PATCH 169/717] Fixed a bug that was leaving unreconciled entries in the list of reconciled entries. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@170 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/account.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/models/account.php b/site/models/account.php index af7fc34..71df3f2 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -307,7 +307,7 @@ class Account extends AppModel { elseif ($amount > 0) $apply = $amount; else { - unset($unreconciled[$i]); + unset($unreconciled[$ofund]['entry'][$i]); continue; } From dc6e399feab87f8983969e595d812ba2b65de59e Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 19 Jun 2009 16:21:16 +0000 Subject: [PATCH 170/717] Got rid of the custom paging functions, since it's no longer used, and added a function to convert dates into SQL format. Added a beforeSave callout to Transaction to convert the date before saving. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@171 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_model.php | 56 ++++++------------------------------- site/models/transaction.php | 17 ++++++++--- 2 files changed, 21 insertions(+), 52 deletions(-) diff --git a/site/app_model.php b/site/app_model.php index 424965c..9526295 100644 --- a/site/app_model.php +++ b/site/app_model.php @@ -110,56 +110,16 @@ class AppModel extends Model { } } - // Overriding pagination, since the stupid count mechanism blows. - // This is also a crappy solution, especially if the query returns - // a really large number of rows. However, trying to untagle this - // without changing a bunch of core code is near impossible. - //var $paginate_rows_save; - function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null, &$extra = null) { -/* pr("paginate"); */ -/* pr(array_merge(compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive', 'extra'))); */ - if ($page > 1 && isset($limit)) - $offset = ($page - 1) * $limit; - else - $offset = 0; + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: dateFormatBeforeSave + * - convert dates to database format + */ - if (!isset($extra['results'])) - die("Why isn't results set!?!"); - - $results = $extra['results']; - unset($extra['results']); - return array_slice($results, $offset, $limit); - } - function paginateCount($conditions = null, $recursive = null, &$extra = null) { -/* pr("paginateCount"); */ -/* pr(compact('conditions', 'recursive', 'extra')); */ - - if (isset($extra['results'])) { - // Beauty! The results are already in! - // This happens if the user sets up a complex query - // and passes us the result to paginate. - $results = $extra['results']; - } - elseif (isset($extra['query'])) { - // Perform the query directly... forget all the find B.S. - $results = $this->query($extra['query']); - } - else { - if (!isset($recursive)) - $recursive = $this->recursive; - - $parameters = array_merge(compact('conditions', 'recursive'), $extra); - $results = $this->find('all', $parameters); - } - - //$this->paginate_rows_save = $results; - //return count($this->paginate_rows_save); - - if (!isset($extra['results'])) - $extra['results'] = $results; - - return count($results); + function dateFormatBeforeSave($dateString) { + return date('Y-m-d', strtotime($dateString)); } } diff --git a/site/models/transaction.php b/site/models/transaction.php index 08ddf6d..2c22348 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -2,10 +2,9 @@ class Transaction extends AppModel { var $name = 'Transaction'; - var $validate = array( - 'id' => array('numeric'), - 'stamp' => array('time') - ); +/* var $validate = array( */ +/* 'stamp' => array('date') */ +/* ); */ var $belongsTo = array( 'Customer', @@ -15,5 +14,15 @@ class Transaction extends AppModel { 'LedgerEntry', ); + + function beforeSave() { + + if(!empty($this->data['Transaction']['stamp'])) { + $this->data['Transaction']['stamp'] = + $this->dateFormatBeforeSave($this->data['Transaction']['stamp']); + } + return true; + } + } ?> \ No newline at end of file From 2b8a5257186e3e374215582f4184d4ad4c677b48 Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 19 Jun 2009 16:22:28 +0000 Subject: [PATCH 171/717] Checking in completely non-working code, as I'm just trying to get a full checkin before the weekend. I cannot yet seem to get the Reconcilation entries to save. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@172 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/transactions_controller.php | 180 ++++++++++++++++++- 1 file changed, 171 insertions(+), 9 deletions(-) diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php index a73ea42..484a93f 100644 --- a/site/controllers/transactions_controller.php +++ b/site/controllers/transactions_controller.php @@ -109,18 +109,180 @@ class TransactionsController extends AppController { echo('

    THIS IS NOT A POST FOR SOME REASON

    '); return; } - //pr($this->data); + //pr(array('thisdata' => $this->data)); - $amount = 0; - foreach ($this->data['LedgerEntry'] AS $entry) { - $amount += isset($entry['amount']) ? $entry['amount'] : 0; + if (isset($this->data['customer_id'])) { + $C = new Customer(); + $C->recursive = -1; + $customer = $C->find + ('first', + array('contain' => array('Account.CurrentLedger.id'), + 'fields' => false, + 'conditions' => array('Customer.id', $this->data['customer_id']), + )); + $ledger_id = $customer['Account']['CurrentLedger']['id']; + } + else { + // Payment by Unit, Lease, etc + $ledger_id = 0; } - $cust_id = $this->data['Customer']['id']; - $cust = new Customer(); - $unreconciled = $cust->findUnreconciledLedgerEntries($cust_id); - $reconciled = $cust->reconcileNewLedgerEntry($cust_id, 'credit', $amount); - pr(compact('amount', 'unreconciled', 'reconciled')); + $amount = 0; + foreach ($this->data['LedgerEntry'] AS &$entry) { + $reconciled = $C->reconcileNewLedgerEntry($this->data['customer_id'], + 'credit', + $entry['amount']); + pr(compact('entry', 'reconciled')); + + foreach ($reconciled['debit']['entry'] AS $rec) { + $entry['DebitReconciliationLedgerEntry'] = + array('amount' => $rec['applied'], + //'debit_ledger_entry_id' + 'credit_ledger_entry_id' => $rec['id'] + ); + } + + $amount += isset($entry['amount']) ? $entry['amount'] : 0; + $entry['debit_ledger_id'] = 6; // Cash/Payments + $entry['credit_ledger_id'] = $ledger_id; + } + + + pr($this->data); + $T = new Transaction(); + $T->create(); + if ($T->saveAll($this->data, + array( + 'validate' => false, + //'fieldList' => array(), + //'callbacks' => true, + ))) { + $tid = $T->id; + $this->Session->setFlash(__("New Transaction Created ($tid)!", true)); + //$this->redirect(array('action'=>'view', $mid)); + } + else { + $this->autoRender = false; + pr(array('checkpoint' => "saveAll failed")); + } + pr($T->data); + + $C = new Customer(); + $LE = new LedgerEntry(); +/* $reconciled = $C->reconcileNewLedgerEntry($this->data['customer_id'], */ +/* 'credit', */ +/* $amount); */ +/* pr(compact('amount', 'unreconciled', 'reconciled')); */ +/* return; */ + + foreach ($this->data['LedgerEntry'] AS &$entry) { + $reconciled = $C->reconcileNewLedgerEntry($this->data['customer_id'], + 'credit', + $entry['amount']); + pr(compact('entry', 'reconciled')); + continue; + + foreach ($reconciled['debit']['entry'] AS $rec) { + $data = array('LedgerEntry' => + array('DebitReconciliationLedgerEntry' => + array('amount' => $rec['applied'], + //'debit_ledger_entry_id' + 'credit_ledger_entry_id' => $rec['id'] + ), + ), + ); + //'DebitReconciliationLedgerEntry' => array( + //pr(compact('amount', 'unreconciled', 'reconciled')); + } + } + + } + + function saveTest() { + $data = + array( +/* 'Customer' => array */ +/* ('id' => 7, */ +/* ), */ + + 'LedgerEntry' => array + ( + '0' => array( + 'amount' => 100, + 'debit_ledger_id' => 1, + 'credit_ledger_id' => 2, + 'MonetarySource' => array('name' => 'testmoney', 'monetary_type_id' => 2), + ), + '1' => array( + 'amount' => 101, + 'debit_ledger_id' => 1, + 'credit_ledger_id' => 2, + 'MonetarySource' => array('name' => 'testmoney2', 'monetary_type_id' => 2), + ), + ), + + 'Transaction' => array + ( + 'stamp' => '06/18/2009', + 'comment' => 'no comment', + ), + ); + + $data = +/* array( */ +/* 'LedgerEntry' => array */ +/* ( */ +/* '0' => */ + array( + 'amount' => 100, + 'debit_ledger_id' => 1, + 'credit_ledger_id' => 2, + 'transaction_id' => 1, + 'DebitReconciliationLedgerEntry' => + array('amount' => 44, + //'debit_ledger_entry_id' + 'credit_ledger_entry_id' => 17, + ), +/* ), */ +/* ), */ + + ); + + //$M = new Transaction(); + $M = new LedgerEntry(); + $M->create(); + $retval = $M->saveAll($data, + array( + 'validate' => false, + 'fieldList' => array(), + 'callbacks' => true, + )); + + $mid = $M->id; + pr(compact('retval', 'mid')); + if ($mid) { + $this->Session->setFlash(__("New Transaction Created ($mid)!", true)); + //$this->redirect(array('action'=>'view', $mid)); + } + else { + $this->autoRender = false; + pr(array('checkpoint' => "saveAll failed")); + } + + +/* $LE = new LedgerEntry(); */ +/* $LE->create(); */ +/* $ret = $LE->save($data, */ +/* array( */ +/* 'validate' => false, */ +/* 'fieldList' => array(), */ +/* 'callbacks' => true, */ +/* )); */ +/* $leid = $LE->id; */ +/* pr(array('checkpoint' => "New Ledger Entry", */ +/* compact('leid', 'ret'))); */ + //pr($LE); + } } From 28b3f35318ffb2528cd610f2c413a29aee6af57a Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 22 Jun 2009 17:43:24 +0000 Subject: [PATCH 172/717] Fixed problem with sorting by entries/debits/credits/balance git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@173 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/accounts.ctp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/site/views/elements/accounts.ctp b/site/views/elements/accounts.ctp index db454be..c3a7d84 100644 --- a/site/views/elements/accounts.ctp +++ b/site/views/elements/accounts.ctp @@ -5,10 +5,10 @@ $cols = array(); $cols['ID'] = array('index' => 'Account.id', 'formatter' => 'id'); $cols['Name'] = array('index' => 'Account.name', 'formatter' => 'name', 'width' => '250'); $cols['Type'] = array('index' => 'Account.type', 'width' => '60'); -$cols['Entries'] = array('index' => 'Account.entries', 'width' => '60', 'align' => 'right'); -$cols['Debits'] = array('index' => 'Account.debits', 'formatter' => 'currency'); -$cols['Credits'] = array('index' => 'Account.credits', 'formatter' => 'currency'); -$cols['Balance'] = array('index' => 'Account.balance', 'formatter' => 'currency'); +$cols['Entries'] = array('index' => 'entries', 'width' => '60', 'align' => 'right'); +$cols['Debits'] = array('index' => 'debits', 'formatter' => 'currency'); +$cols['Credits'] = array('index' => 'credits', 'formatter' => 'currency'); +$cols['Balance'] = array('index' => 'balance', 'formatter' => 'currency'); $cols['Comment'] = array('index' => 'Account.comment', 'formatter' => 'comment'); $jqGrid_options = array('jqGridColumns' => $cols, From 117e31af69ffab800b9b10e4826fa55ddbcaf676 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 22 Jun 2009 17:46:49 +0000 Subject: [PATCH 173/717] Due to the way we're adding in stats for each lease as a separate query, there isn't presently a way to sort by balance. Therefore I've disabled sorting on that column, which can be revisited if we reduce the grid down to a single SQL query. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@174 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/leases.ctp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/views/elements/leases.ctp b/site/views/elements/leases.ctp index b26787a..2315f99 100644 --- a/site/views/elements/leases.ctp +++ b/site/views/elements/leases.ctp @@ -8,7 +8,7 @@ $cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'lon $cols['Signed'] = array('index' => 'Lease.lease_date', 'formatter' => 'date'); $cols['Move-In'] = array('index' => 'Lease.movein_date', 'formatter' => 'date'); $cols['Move-Out'] = array('index' => 'Lease.moveout_date', 'formatter' => 'date'); -$cols['Balance'] = array('index' => 'Lease.balance', 'formatter' => 'currency'); +$cols['Balance'] = array('index' => 'Lease.balance', 'formatter' => 'currency', 'sortable'=>false); $cols['Comment'] = array('index' => 'Lease.comment', 'formatter' => 'comment'); $jqGrid_options = array('jqGridColumns' => $cols, From b780ebeb3e29fe08bbd26145d30f24bb5a9e4c93 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 22 Jun 2009 17:55:32 +0000 Subject: [PATCH 174/717] Added stats summary to the top level for lease. For consistency, I want all stats to be summarized at the top. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@175 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/leases_controller.php | 2 +- site/models/lease.php | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index 15c0feb..3957c69 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -80,7 +80,7 @@ class LeasesController extends AppController { // Get the balance on each lease. foreach ($leases AS &$lease) { $stats = $this->Lease->stats($lease['Lease']['id']); - $lease['Lease']['balance'] = $stats['Account']['Ledger']['balance']; + $lease['Lease']['balance'] = $stats['balance']; } return $leases; diff --git a/site/models/lease.php b/site/models/lease.php index 73b9950..13873e5 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -150,6 +150,11 @@ class Lease extends AppModel { // Pull the stats from the account. $stats['Account'] = $this->Account->stats($lease['Lease']['account_id']); + + // Place a summary of the stats (one lease account in this case) + // at the top level for easy summarized access. + $this->statsMerge($stats, $stats['Account']['Ledger']); + return $stats; } From ab51fd32d268648108e79dd67ea7aedd07d790b4 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 22 Jun 2009 17:58:13 +0000 Subject: [PATCH 175/717] Added a balance column to customer. Like lease, since it's based on additional queries for stats, it's not sortable. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@176 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/customers_controller.php | 12 ++++++++++++ site/views/elements/customers.ctp | 1 + 2 files changed, 13 insertions(+) diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index d3e8ef7..9d30858 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -122,6 +122,18 @@ class CustomersController extends AppController { return $count; } + function jqGridDataRecords(&$params, &$model, $query) { + $customers = parent::jqGridDataRecords($params, $model, $query); + + // Get the balance on each customer. + foreach ($customers AS &$customer) { + $stats = $this->Customer->stats($customer['Customer']['id']); + $customer['Customer']['balance'] = $stats['balance']; + } + + return $customers; + } + function jqGridRecordLinks(&$params, &$model, &$records, $links) { $links['Customer'] = array('name'); return parent::jqGridRecordLinks($params, $model, $records, $links); diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index f7a31fd..9b9b2e5 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -9,6 +9,7 @@ $cols['Name'] = array('index' => 'Customer.name', 'formatter $cols['Last Name'] = array('index' => 'PrimaryContact.last_name', 'formatter' => 'name'); $cols['First Name'] = array('index' => 'PrimaryContact.first_name', 'formatter' => 'name'); $cols['Leases'] = array('index' => 'lease_count', 'width' => '60'); +$cols['Balance'] = array('index' => 'balance', 'formatter' => 'currency', 'sortable' => false); $cols['Comment'] = array('index' => 'Customer.comment', 'formatter' => 'comment'); $jqGrid_options = array('jqGridColumns' => $cols, From 20b8908a000f962917dd117eed39a4a2fab02c14 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 22 Jun 2009 19:03:08 +0000 Subject: [PATCH 176/717] Experiment to group ledger entries by their transaction ID instead of their entry ID. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@177 97e9348a-65ac-dc4b-aefc-98561f571b83 --- .../controllers/ledger_entries_controller.php | 16 ++++++++++++- site/controllers/transactions_controller.php | 2 +- site/models/ledger_entry.php | 23 +++++++++++++++++++ site/views/elements/ledger_entries.ctp | 9 +++++--- site/views/transactions/view.ctp | 1 + 5 files changed, 46 insertions(+), 5 deletions(-) diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index c4c9c59..6b0100a 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -96,7 +96,7 @@ class LedgerEntriesController extends AppController { ? $params['custom']['account_type'] : null); - return $model->ledgerContextFields($ledger_id, $account_type); + return $model->ledgerContextFields2($ledger_id, $account_type); } function jqGridDataConditions(&$params, &$model) { @@ -135,6 +135,20 @@ class LedgerEntriesController extends AppController { return parent::jqGridRecordLinks($params, $model, $records, $links); } + function jqGridDataGroup(&$params, &$model) { + if (isset($params['custom']['notxgroup'])) + return parent::jqGridDataGroup($params, $model); + + return $model->alias.'.transaction_id'; + } + + function jqGridDataOrder(&$params, &$model, $index, $direction) { +/* if ($index === 'balance') */ +/* return ($index .' '. $direction); */ + + return parent::jqGridDataOrder($params, $model, $index, $direction); + } + /************************************************************************** ************************************************************************** diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php index 484a93f..e4a3f1f 100644 --- a/site/controllers/transactions_controller.php +++ b/site/controllers/transactions_controller.php @@ -237,7 +237,7 @@ class TransactionsController extends AppController { 'amount' => 100, 'debit_ledger_id' => 1, 'credit_ledger_id' => 2, - 'transaction_id' => 1, + 'transaction_id' => 66, 'DebitReconciliationLedgerEntry' => array('amount' => 44, //'debit_ledger_entry_id' diff --git a/site/models/ledger_entry.php b/site/models/ledger_entry.php index ad88596..e0ea6a9 100644 --- a/site/models/ledger_entry.php +++ b/site/models/ledger_entry.php @@ -84,6 +84,29 @@ class LedgerEntry extends AppModel { return $fields; } + function ledgerContextFields2($ledger_id = null, $account_type = null) { + $fields = array('id', 'name', 'comment', 'amount'); + + if (isset($ledger_id)) { + $fields[] = ("IF(LedgerEntry.debit_ledger_id = $ledger_id," . + " SUM(LedgerEntry.amount), NULL) AS debit"); + $fields[] = ("IF(LedgerEntry.credit_ledger_id = $ledger_id," . + " SUM(LedgerEntry.amount), NULL) AS credit"); + + if (isset($account_type)) { + if (in_array($account_type, array('ASSET', 'EXPENSE'))) + $ledger_type = 'debit'; + else + $ledger_type = 'credit'; + + $fields[] = ("(IF(LedgerEntry.{$ledger_type}_ledger_id = $ledger_id," . + " 1, -1) * SUM(LedgerEntry.amount)) AS balance"); + } + } + + return $fields; + } + function ledgerContextConditions($ledger_id, $account_type) { if (isset($ledger_id)) { return array diff --git a/site/views/elements/ledger_entries.ctp b/site/views/elements/ledger_entries.ctp index 70e8c1f..12fb532 100644 --- a/site/views/elements/ledger_entries.ctp +++ b/site/views/elements/ledger_entries.ctp @@ -2,8 +2,11 @@ // Define the table columns $cols = array(); -$cols['Transaction'] = array('index' => 'Transaction.id', 'formatter' => 'id'); -$cols['Entry'] = array('index' => 'LedgerEntry.id', 'formatter' => 'id'); +if (isset($notxgroup)) + $cols['Entry'] = array('index' => 'LedgerEntry.id', 'formatter' => 'id'); +else + $cols['Transaction'] = array('index' => 'Transaction.id', 'formatter' => 'id'); + $cols['Date'] = array('index' => 'Transaction.stamp', 'formatter' => 'date'); if (isset($account_ftype) || isset($ledger_id)) { $cols['Account'] = array('index' => 'Account.name', 'formatter' => 'longname'); @@ -25,7 +28,7 @@ if (isset($reconcile_id)) { $cols['Applied'] = array('index' => "Reconciliation.amount", 'formatter' => 'currency'); } -$custom_post_data = compact('ledger_id', 'account_type', 'account_ftype'); +$custom_post_data = compact('ledger_id', 'account_type', 'account_ftype', 'notxgroup'); $jqGrid_options = array('jqGridColumns' => $cols, 'controller' => 'ledger_entries', diff --git a/site/views/transactions/view.ctp b/site/views/transactions/view.ctp index 67e77cd..c51871e 100644 --- a/site/views/transactions/view.ctp +++ b/site/views/transactions/view.ctp @@ -55,6 +55,7 @@ echo '
    ' . "\n"; echo $this->element('ledger_entries', array('caption' => 'Entries in Transaction', 'ledger_entries' => $transaction['LedgerEntry'], + 'notxgroup' => true, )); From bd0bbd768dabed0008f571392b78e3e0c2b2cb93 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 22 Jun 2009 23:40:53 +0000 Subject: [PATCH 177/717] Prevent grouping of ledger entries by transaction, at least for now. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@178 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/ledger_entries.ctp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/site/views/elements/ledger_entries.ctp b/site/views/elements/ledger_entries.ctp index 12fb532..3755a78 100644 --- a/site/views/elements/ledger_entries.ctp +++ b/site/views/elements/ledger_entries.ctp @@ -2,10 +2,16 @@ // Define the table columns $cols = array(); +if (0) { if (isset($notxgroup)) $cols['Entry'] = array('index' => 'LedgerEntry.id', 'formatter' => 'id'); else $cols['Transaction'] = array('index' => 'Transaction.id', 'formatter' => 'id'); +} else { + $notxgroup = true; + $cols['Transaction'] = array('index' => 'Transaction.id', 'formatter' => 'id'); + $cols['Entry'] = array('index' => 'LedgerEntry.id', 'formatter' => 'id'); +} $cols['Date'] = array('index' => 'Transaction.stamp', 'formatter' => 'date'); if (isset($account_ftype) || isset($ledger_id)) { From b9c1a81c3b4a6a6fd2ff71e8e1a8c80abd7770ad Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 22 Jun 2009 23:42:13 +0000 Subject: [PATCH 178/717] Experiment to allow payments to trace back to the charge, even if the amount crosses several ledgers. I'd really like to go a different direction. git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605@179 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 10 +++--- scripts/sitelink2pmgr.pl | 69 +++++++++++++++++++++++++++++++++------- 2 files changed, 64 insertions(+), 15 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index be42f98..14dc12b 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -870,10 +870,11 @@ INSERT INTO `pmgr_accounts` (`type`, `name`, `trackable`) ('LIABILITY', 'Tax', 0), ('LIABILITY', 'Customer Credit', 1), ('ASSET', 'Bank', 0), - ('ASSET', 'Cash', 0), + ('ASSET', 'Payment', 0), ('LIABILITY', 'Security Deposit', 1), ('INCOME', 'Rent', 0), - ('INCOME', 'Late Charge', 0); + ('INCOME', 'Late Charge', 0), + ('EXPENSE', 'Concession', 0); UNLOCK TABLES; @@ -983,8 +984,9 @@ DROP TABLE IF EXISTS `pmgr_reconciliations`; CREATE TABLE `pmgr_reconciliations` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `debit_ledger_entry_id` INT(10) UNSIGNED NOT NULL, - `credit_ledger_entry_id` INT(10) UNSIGNED NOT NULL, + `debit_ledger_entry_id` INT(10) UNSIGNED NOT NULL, + `credit_ledger_entry_id` INT(10) UNSIGNED NOT NULL, + `terminal_ledger_entry_id` INT(10) UNSIGNED DEFAULT NULL, `amount` FLOAT(12,2) NOT NULL, PRIMARY KEY (`id`) diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 446aedc..8d12179 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -438,6 +438,7 @@ foreach $row (@$result) { $newdb{'lookup'}{'account'}{$row->{'name'}} = {'account' => $row->{'id'}, + 'tillable' => $row->{'tillable'}, 'ledger' => $newdb{'tables'}{'ledgers'}{'autoid'} }; if ((!defined $newdb{'tables'}{'accounts'}{'autoid'}) || @@ -446,6 +447,10 @@ foreach $row (@$result) { } } +# For compatibility, while deciding on account names +$newdb{'lookup'}{'account'}{'Cash'} += $newdb{'lookup'}{'account'}{'Payment'}; + $newdb{'lookup'}{'charge_type'} = {}; $newdb{'lookup'}{'charge_type'}{'Rent'} = $newdb{'lookup'}{'account'}{'Rent'}; @@ -469,15 +474,15 @@ foreach $row (@$result) { $newdb{'lookup'}{'payment_type'} = {}; $newdb{'lookup'}{'payment_type'}{1} -= { 'name' => 'Cash', 'id' => $newdb{'lookup'}{'monetary_type'}{'Cash'}{'id'} }; += { 'name' => 'Cash', 'account' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Cash'} }; $newdb{'lookup'}{'payment_type'}{2} -= { 'name' => 'Check', 'id' => $newdb{'lookup'}{'monetary_type'}{'Check'}{'id'} }; += { 'name' => 'Check', 'account' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Check'} }; $newdb{'lookup'}{'payment_type'}{3} -= { 'name' => 'Money Order', 'id' => $newdb{'lookup'}{'monetary_type'}{'Money Order'}{'id'} }; += { 'name' => 'Money Order', 'account' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Money Order'} }; $newdb{'lookup'}{'payment_type'}{4} -= { 'name' => 'ACH', 'id' => $newdb{'lookup'}{'monetary_type'}{'ACH'}{'id'} }; += { 'name' => 'ACH', 'account' => 'Bank', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'ACH'} }; $newdb{'lookup'}{'payment_type'}{12} -= { 'name' => 'Transfer', 'id' => $newdb{'lookup'}{'monetary_type'}{'Other Non-Tillable'}{'id'} }; += { 'name' => 'Concession', 'account' => 'Concession', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Other Non-Tillable'} }; $newdb{'ids'}{'monetary_source'} = {}; @@ -794,6 +799,10 @@ $newdb{'lookup'}{'ledger'} = {}; $query = "SELECT L.*, A.TenantID FROM TenantLedger L LEFT JOIN `Access` A ON A.LedgerID = L.LedgerID WHERE L.UnitID <> 'POS\$' ORDER BY L.LedgerID"; foreach $row (@{query($sdbh, $query)}) { + $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}} + = { 'cust' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'} }; + + if (1) { # Every lease gets its own account addRow('accounts', { 'type' => 'ASSET', @@ -807,10 +816,22 @@ foreach $row (@{query($sdbh, $query)}) { 'open_stamp' => datefmt($row->{'DateIn'}), 'comment' => undef }); - $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}} - = { 'cust' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'}, - 'account' => $newdb{'tables'}{'accounts'}{'autoid'}, - 'ledger' => $newdb{'tables'}{'ledgers'}{'autoid'} }; + $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'account'} + = $newdb{'tables'}{'accounts'}{'autoid'}; + $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'} + = $newdb{'tables'}{'ledgers'}{'autoid'}; + } + else { + $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'account'} + = $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account'}; + $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'} + = $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'ledger'}; + } + + $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust_account'} + = $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account'}; + $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust_ledger'} + = $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'ledger'}; addRow('leases', { 'number' => $row->{'LedgerID'}, @@ -867,8 +888,30 @@ foreach $row (@{query($sdbh, $query)}) { 'amount' => $row->{'ChargeAmount'}, 'comment' => "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}" }); + my $debit_entry_id = $newdb{'tables'}{'ledger_entries'}{'autoid'}, + + addRow('ledger_entries', + { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, + 'debit_ledger_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust_ledger'}, + 'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger'}, + 'amount' => $row->{'ChargeAmount'}, + 'comment' => "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}" }); + + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'terminal'} + = $debit_entry_id; $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'entry'} = $newdb{'tables'}{'ledger_entries'}{'autoid'}, + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger'} + = $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust_ledger'}; + + addRow('reconciliations', + { 'debit_ledger_entry_id' => $debit_entry_id, + 'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'entry'}, + 'terminal_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'terminal'}, + 'amount' => $row->{'ChargeAmount'}, + }); + next unless $row->{'TaxAmount'}; @@ -944,16 +987,18 @@ foreach $row (@{query($sdbh, $query)}) if (!defined $monetary_source_id) { addRow('monetary_sources', - { 'monetary_type_id' => $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'id'}, + { 'monetary_type_id' => $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'monetary_type'}{'id'}, 'name' => $row->{'RecdFrom'}, 'comment' => "Payment: $row->{'PaymentID'}; Type: $row->{'PaymentType'}; Check: $row->{'CheckNum'}; $row->{'Memo'}" }); $monetary_source_id = $newdb{'tables'}{'monetary_sources'}{'autoid'}; } + my $payment_acct = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'account'}; + addRow('ledger_entries', { 'monetary_source_id' => $monetary_source_id, 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Cash'}{'ledger'}, + 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$payment_acct}{'ledger'}, 'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger'}, 'amount' => $row->{'PaymentAmount'}, 'comment' => "Receipt: $row->{'ReceiptNum'}; Payment: $row->{'PaymentID'}; Charge: $row->{'ChargeID'}" }); @@ -971,6 +1016,7 @@ foreach $row (@{query($sdbh, $query)}) addRow('reconciliations', { 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'entry'}, 'credit_ledger_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'entry'}, + 'terminal_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'terminal'}, 'amount' => $reconcile_amount, }); @@ -1148,6 +1194,7 @@ foreach my $ir ('invoice', 'receipt') { addRow('reconciliations', { 'debit_ledger_entry_id' => $t->{'debit'}, 'credit_ledger_entry_id' => $e->{'id'}, + 'terminal_ledger_entry_id' => $t->{'debit'}, 'amount' => $t->{'amount'} }); } From 7aa1100cac2e0e119e4ddd56a32f38d001ee1c0b Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 22 Jun 2009 23:46:03 +0000 Subject: [PATCH 179/717] Moving to the standard accounting method of a single Account Receiveable. git-svn-id: file:///svn-source/pmgr/branches/single_AR_20090622@180 97e9348a-65ac-dc4b-aefc-98561f571b83 From 80f8bd36d542a33409881a0a0fdb9ee5c69dcecf Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 23 Jun 2009 19:04:41 +0000 Subject: [PATCH 180/717] Nowhere near done yet, but checking in a snapshot of semi-working code. There is some simultaneous support for both with and without use of the Invoice/Receipt account. I want to do away with them completely, but will need to change how sitelink payments are mapped (right now, they split a payment into multiple parts to match the charge). git-svn-id: file:///svn-source/pmgr/branches/single_AR_20090622@181 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 12 +- scripts/sitelink2pmgr.pl | 506 ++++++++++-------- site/app_controller.php | 6 + site/controllers/leases_controller.php | 12 +- .../controllers/ledger_entries_controller.php | 79 ++- site/controllers/units_controller.php | 4 +- site/models/account.php | 59 +- site/models/customer.php | 101 +--- site/models/lease.php | 44 +- site/models/ledger.php | 6 +- site/models/ledger_entry.php | 2 + site/views/customers/view.ctp | 7 +- site/views/elements/jqGrid.ctp | 8 +- site/views/elements/ledger_entries.ctp | 16 +- site/views/leases/view.ctp | 15 +- site/views/ledger_entries/view.ctp | 14 +- site/views/transactions/view.ctp | 3 +- site/views/units/view.ctp | 17 +- 18 files changed, 502 insertions(+), 409 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index 14dc12b..8d5a18f 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -866,15 +866,18 @@ LOCK TABLES `pmgr_accounts` WRITE; INSERT INTO `pmgr_accounts` (`type`, `name`, `trackable`) VALUES ('ASSET', 'A/R', 1), + ('ASSET', 'Invoice', 1), + ('ASSET', 'Receipt', 1), ('LIABILITY', 'A/P', 1), ('LIABILITY', 'Tax', 0), ('LIABILITY', 'Customer Credit', 1), ('ASSET', 'Bank', 0), - ('ASSET', 'Payment', 0), + ('ASSET', 'Till', 0), ('LIABILITY', 'Security Deposit', 1), ('INCOME', 'Rent', 0), ('INCOME', 'Late Charge', 0), - ('EXPENSE', 'Concession', 0); + ('EXPENSE', 'Concession', 0), + ('EXPENSE', 'Bad Debt', 0); UNLOCK TABLES; @@ -965,6 +968,8 @@ CREATE TABLE `pmgr_ledger_entries` ( `name` VARCHAR(80) DEFAULT NULL, `monetary_source_id` INT(10) UNSIGNED DEFAULT NULL, -- NULL if internal transfer `transaction_id` INT(10) UNSIGNED NOT NULL, + `customer_id` INT(10) UNSIGNED DEFAULT NULL, + `lease_id` INT(10) UNSIGNED DEFAULT NULL, `amount` FLOAT(12,2) NOT NULL, `debit_ledger_id` INT(10) UNSIGNED NOT NULL, @@ -986,8 +991,7 @@ CREATE TABLE `pmgr_reconciliations` ( `debit_ledger_entry_id` INT(10) UNSIGNED NOT NULL, `credit_ledger_entry_id` INT(10) UNSIGNED NOT NULL, - `terminal_ledger_entry_id` INT(10) UNSIGNED DEFAULT NULL, - `amount` FLOAT(12,2) NOT NULL, + `amount` FLOAT(12,2) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 8d12179..e7ad2d8 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -4,6 +4,8 @@ use DBI; use Data::Dumper; use File::Copy; +my $use_ir = 0; + # Internally adjust all numbers coming from the database to # be in inches. Not necessary to go to this detail, but the # actual units used is irrelevant, provided everything is to @@ -145,7 +147,13 @@ sub executeSchema { sub buildTables { foreach my $table (values %{$newdb{'tables'}}) { - printf(STDERR "%-30s : %d rows\n", $table->{'name'}, int(@{$table->{'rows'}})); + my $count = 0; + foreach (@{$table->{'rows'}}) { + next unless defined $_; + ++$count; + } + + printf(STDERR "%-30s : %d rows\n", $table->{'name'}, $count); foreach (@{$table->{'rows'}}) { next unless defined $_; @@ -437,9 +445,9 @@ foreach $row (@$result) { 'comment' => undef }); $newdb{'lookup'}{'account'}{$row->{'name'}} - = {'account' => $row->{'id'}, + = {'account_id' => $row->{'id'}, 'tillable' => $row->{'tillable'}, - 'ledger' => $newdb{'tables'}{'ledgers'}{'autoid'} }; + 'ledger_id' => $newdb{'tables'}{'ledgers'}{'autoid'} }; if ((!defined $newdb{'tables'}{'accounts'}{'autoid'}) || $row->{'id'} > $newdb{'tables'}{'accounts'}{'autoid'}) { @@ -449,7 +457,7 @@ foreach $row (@$result) { # For compatibility, while deciding on account names $newdb{'lookup'}{'account'}{'Cash'} -= $newdb{'lookup'}{'account'}{'Payment'}; += $newdb{'lookup'}{'account'}{'Till'}; $newdb{'lookup'}{'charge_type'} = {}; $newdb{'lookup'}{'charge_type'}{'Rent'} = @@ -474,15 +482,15 @@ foreach $row (@$result) { $newdb{'lookup'}{'payment_type'} = {}; $newdb{'lookup'}{'payment_type'}{1} -= { 'name' => 'Cash', 'account' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Cash'} }; += { 'name' => 'Cash', 'account_name' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Cash'} }; $newdb{'lookup'}{'payment_type'}{2} -= { 'name' => 'Check', 'account' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Check'} }; += { 'name' => 'Check', 'account_name' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Check'} }; $newdb{'lookup'}{'payment_type'}{3} -= { 'name' => 'Money Order', 'account' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Money Order'} }; += { 'name' => 'Money Order', 'account_name' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Money Order'} }; $newdb{'lookup'}{'payment_type'}{4} -= { 'name' => 'ACH', 'account' => 'Bank', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'ACH'} }; += { 'name' => 'ACH', 'account_name' => 'Bank', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'ACH'} }; $newdb{'lookup'}{'payment_type'}{12} -= { 'name' => 'Concession', 'account' => 'Concession', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Other Non-Tillable'} }; += { 'name' => 'Concession', 'account_name' => 'Concession', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Other Non-Tillable'} }; $newdb{'ids'}{'monetary_source'} = {}; @@ -490,14 +498,14 @@ $newdb{'ids'}{'monetary_source'}{'internal'} = undef; addRow('monetary_sources', { 'monetary_type_id' => $newdb{'lookup'}{'monetary_type'}{'Cash'}{'id'}, - 'name' => 'Cash Source', + 'name' => 'Cash', 'comment' => 'Monetary source used for any cash transaction' }); $newdb{'ids'}{'monetary_source'}{'Cash'} = $newdb{'tables'}{'monetary_sources'}{'autoid'}; addRow('monetary_sources', { 'monetary_type_id' => $newdb{'lookup'}{'monetary_type'}{'Other Non-Tillable'}{'id'}, - 'name' => 'Closing Monies Credited', + 'name' => 'Closing', 'comment' => 'Credited at the closing table' }); $newdb{'ids'}{'monetary_source'}{'Closing'} = $newdb{'tables'}{'monetary_sources'}{'autoid'}; @@ -660,35 +668,21 @@ foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'} = $newdb{'tables'}{'contacts'}{'autoid'}; - - # Every customer gets their own account - addRow('accounts', - { 'type' => 'ASSET', - 'trackable' => 1, - 'name' => ('Customer #' . ($newdb{'tables'}{'customers'}{'autoid'}+1) . - ' ('.$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'name'} . ')'), - 'comment' => undef }); - #'comment' => 'For direct customer transaction, NOT lease charges!' }); - addRow('ledgers', - { 'account_id' => $newdb{'tables'}{'accounts'}{'autoid'}, - 'open_stamp' => '2009-01-01', - 'comment' => undef }); - - $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account'} = - $newdb{'tables'}{'accounts'}{'autoid'}; - $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'ledger'} = - $newdb{'tables'}{'ledgers'}{'autoid'}; + $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account_id'} = + $newdb{'lookup'}{'account'}{'A/R'}{'account_id'}; + $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'ledger_id'} = + $newdb{'lookup'}{'account'}{'A/R'}{'ledger_id'}; addRow('customers', { 'name' => "$row->{'LastName'}, $row->{'FirstName'}", 'primary_contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'}, - 'account_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account'} }); + 'account_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account_id'} }); - $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'} = + $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'} = $newdb{'tables'}{'customers'}{'autoid'}; addRow('contacts_customers', - { 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'}, + { 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'}, 'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'}, 'type' => 'TENANT' }, 1); @@ -754,7 +748,7 @@ foreach $row (@{query($sdbh, $query)}) { $newdb{'tables'}{'contacts'}{'autoid'}; addRow('contacts_customers', - { 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'}, + { 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'}, 'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'alt'}, 'type' => 'ALTERNATE' }, 1); @@ -800,52 +794,26 @@ $query = "SELECT L.*, A.TenantID FROM TenantLedger L LEFT JOIN `Access` A ON A.L foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}} - = { 'cust' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'} }; + = { 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'} }; - if (1) { - # Every lease gets its own account - addRow('accounts', - { 'type' => 'ASSET', - 'trackable' => 1, - 'name' => ('Lease #' . $row->{'LedgerID'} - . ' ('.$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'name'} . ')'), - 'comment' => undef }); - #'comment' => 'For lease related transaction, NOT personal charges!' }); - addRow('ledgers', - { 'account_id' => $newdb{'tables'}{'accounts'}{'autoid'}, - 'open_stamp' => datefmt($row->{'DateIn'}), - 'comment' => undef }); - - $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'account'} - = $newdb{'tables'}{'accounts'}{'autoid'}; - $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'} - = $newdb{'tables'}{'ledgers'}{'autoid'}; - } - else { - $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'account'} - = $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account'}; - $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'} - = $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'ledger'}; - } - - $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust_account'} - = $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account'}; - $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust_ledger'} - = $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'ledger'}; + $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'account_id'} + = $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account_id'}; + $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger_id'} + = $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'ledger_id'}; addRow('leases', { 'number' => $row->{'LedgerID'}, 'lease_type_id' => $newdb{'tables'}{'lease_types'}{'autoid'}, 'unit_id' => $newdb{'lookup'}{'unit'}{$row->{'UnitID'}}{'id'}, - 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'}, - 'account_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'account'}, + 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'}, + 'account_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'account_id'}, 'lease_date' => datefmt($row->{'DateIn'}), 'movein_date' => datefmt($row->{'DateIn'}), 'moveout_date' => datefmt($row->{'DateOut'}), 'close_date' => datefmt($row->{'DateClosed'}), 'amount' => $row->{'Rent'} }); - $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease'} = + $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease_id'} = $newdb{'tables'}{'leases'}{'autoid'}; } @@ -868,6 +836,8 @@ $newdb{'lookup'}{'charge'} = {}; $query = "SELECT * FROM Charges ORDER BY ChargeID"; foreach $row (@{query($sdbh, $query)}) { + my $credit_ledger_id; + my $ledger_entry_id; addRow('transactions', { 'stamp' => datefmt($row->{'ChargeDate'}), @@ -875,57 +845,93 @@ foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}} = { 'tx' => $newdb{'tables'}{'transactions'}{'autoid'}, - 'ledger' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'}, + 'ledger_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger_id'}, + #'ledger_id' => $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}, 'amount' => $row->{'ChargeAmount'}, 'tax_amount' => $row->{'TaxAmount'}, + 'customer_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'customer_id'}, + 'lease_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease_id'}, }; - addRow('ledger_entries', - { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, - 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger'}, - 'credit_ledger_id' => $newdb{'lookup'}{'charge_type'}{$row->{'ChargeDescription'}}{'ledger'}, - 'amount' => $row->{'ChargeAmount'}, - 'comment' => "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}" }); - - my $debit_entry_id = $newdb{'tables'}{'ledger_entries'}{'autoid'}, + $credit_ledger_id = $newdb{'lookup'}{'charge_type'}{$row->{'ChargeDescription'}}{'ledger_id'}; + if ($use_ir) { + addRow('ledger_entries', + { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, + 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}, + 'credit_ledger_id' => $credit_ledger_id, + 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, + 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, + 'amount' => $row->{'ChargeAmount'}, + 'comment' => "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}" }); + $ledger_entry_id = $newdb{'tables'}{'ledger_entries'}{'autoid'}; + $credit_ledger_id = $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}; + } addRow('ledger_entries', { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust_ledger'}, - 'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger'}, + 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_id'}, + 'credit_ledger_id' => $credit_ledger_id, + 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, + 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, 'amount' => $row->{'ChargeAmount'}, 'comment' => "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}" }); - $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'terminal'} - = $debit_entry_id; - $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'entry'} - = $newdb{'tables'}{'ledger_entries'}{'autoid'}, - $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger'} - = $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust_ledger'}; - - addRow('reconciliations', - { 'debit_ledger_entry_id' => $debit_entry_id, - 'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'entry'}, - 'terminal_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'terminal'}, - 'amount' => $row->{'ChargeAmount'}, - }); + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'} + = $newdb{'tables'}{'ledger_entries'}{'autoid'}; + if ($use_ir) { + # Reconcile the invoice account. Since this is from the perspective + # of the invoice, the entry crediting the charge is the debit, and + # the entry debiting A/R is the credit. + addRow('reconciliations', + { 'debit_ledger_entry_id' => $ledger_entry_id, + 'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'}, + 'amount' => $row->{'ChargeAmount'}, + }); + } next unless $row->{'TaxAmount'}; + $credit_ledger_id = $newdb{'lookup'}{'charge_type'}{'Tax'}{'ledger_id'}; + if ($use_ir) { + addRow('ledger_entries', + { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, + 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}, + 'credit_ledger_id' => $credit_ledger_id, + 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, + 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, + 'amount' => $row->{'TaxAmount'}, + 'comment' => undef }); + $ledger_entry_id = $newdb{'tables'}{'ledger_entries'}{'autoid'}; + $credit_ledger_id = $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}; + } + addRow('ledger_entries', { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger'}, - 'credit_ledger_id' => $newdb{'lookup'}{'charge_type'}{'Tax'}{'ledger'}, + 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_id'}, + 'credit_ledger_id' => $credit_ledger_id, + 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, + 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, 'amount' => $row->{'TaxAmount'}, 'comment' => undef }); $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tax_entry'} - = $newdb{'tables'}{'ledger_entries'}{'autoid'}, + = $newdb{'tables'}{'ledger_entries'}{'autoid'}; + if ($use_ir) { + # Reconcile the invoice account. Since this is from the perspective + # of the invoice, the entry crediting the charge is the debit, and + # the entry debiting A/R is the credit. + addRow('reconciliations', + { 'debit_ledger_entry_id' => $ledger_entry_id, + 'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tax_entry'}, + 'amount' => $row->{'TaxAmount'}, + }); + } } @@ -944,10 +950,10 @@ $query = foreach $row (@{query($sdbh, $query)}) { if ($newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}) { - die unless ($newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'cust'} - == $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'cust'}); + die unless ($newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'customer_id'} + == $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'customer_id'}); push(@{$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'ledgers'}}, - $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'}); + $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger_id'}); #print Dumper $receipt_map{$row->{'ReceiptNum'}}; next; } @@ -958,8 +964,12 @@ foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}} = {'tx' => $newdb{'tables'}{'transactions'}{'autoid'}, - 'cust' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust'}, - 'ledgers' => [ $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'} ] }; + # NOTE: Use of 'lease_id' would be invalid, since the + # receipt could be for multiple leases. 'customer_id' + # could be OK, but better to avoid this issue all + # together by excluding them both from this lookup. + 'ledgers' => [ $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger_id'} ] }; + } @@ -976,47 +986,86 @@ $query = "SELECT * FROM Payments ORDER BY PaymentID"; foreach $row (@{query($sdbh, $query)}) { my $monetary_source_id; + my $payment_acct; + my $debit_ledger_id; + my $ledger_entry_id; + if ($row->{'PaymentDate'} =~ m%3/25/2009%) { - $monetary_source_id = $newdb{'ids'}{'monetary_source'}{'closing'}; + $monetary_source_id = $newdb{'ids'}{'monetary_source'}{'Closing'}; + $payment_acct = 'Bank'; } else { $monetary_source_id = $newdb{'ids'}{'monetary_source'}{ - $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'} + $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'} }; + $payment_acct = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'account_name'}; } - if (!defined $monetary_source_id) { - addRow('monetary_sources', - { 'monetary_type_id' => $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'monetary_type'}{'id'}, - 'name' => $row->{'RecdFrom'}, - 'comment' => "Payment: $row->{'PaymentID'}; Type: $row->{'PaymentType'}; Check: $row->{'CheckNum'}; $row->{'Memo'}" }); - $monetary_source_id = $newdb{'tables'}{'monetary_sources'}{'autoid'}; - } + if (!$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}) { + if (!defined $monetary_source_id) { + my $name; + $name = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'}; + if ($name eq 'Check') { + $name = 'Check #' . $row->{'CheckNum'}; + } + addRow('monetary_sources', + { 'monetary_type_id' => $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'monetary_type'}{'id'}, + 'name' => $name, + 'comment' => "Payment: $row->{'PaymentID'}; Type: $row->{'PaymentType'}; Check: $row->{'CheckNum'}; $row->{'Memo'}" }); + $monetary_source_id = $newdb{'tables'}{'monetary_sources'}{'autoid'}; + } - my $payment_acct = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'account'}; + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'} + = $monetary_source_id; + } - addRow('ledger_entries', - { 'monetary_source_id' => $monetary_source_id, - 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$payment_acct}{'ledger'}, - 'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger'}, - 'amount' => $row->{'PaymentAmount'}, - 'comment' => "Receipt: $row->{'ReceiptNum'}; Payment: $row->{'PaymentID'}; Charge: $row->{'ChargeID'}" }); + $debit_ledger_id = $newdb{'lookup'}{'account'}{$payment_acct}{'ledger_id'}; + if ($use_ir) { + addRow('ledger_entries', + { 'monetary_source_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}, + 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, + 'debit_ledger_id' => $debit_ledger_id, + 'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Receipt'}{'ledger_id'}, + 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, + 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, + 'amount' => $row->{'PaymentAmount'}, + 'comment' => "Receipt: $row->{'ReceiptNum'}; Payment: $row->{'PaymentID'}; Charge: $row->{'ChargeID'}" }); + $ledger_entry_id = $newdb{'tables'}{'ledger_entries'}{'autoid'}; + $debit_ledger_id = $newdb{'lookup'}{'account'}{'Receipt'}{'ledger_id'}; + } + + addRow('ledger_entries', + { 'monetary_source_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}, + 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, + 'debit_ledger_id' => $debit_ledger_id, + 'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_id'}, + 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, + 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, + 'amount' => $row->{'PaymentAmount'}, + 'comment' => "Receipt: $row->{'ReceiptNum'}; Payment: $row->{'PaymentID'}; Charge: $row->{'ChargeID'}" }); $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}} - = { 'entry' => $newdb{'tables'}{'ledger_entries'}{'autoid'} }; + = { 'ledger_entry_id' => $newdb{'tables'}{'ledger_entries'}{'autoid'} }; + + if ($use_ir) { + # Reconcile the receipt account. Since this is from the perspective + # of the receipt, the entry crediting the A/R is the debit, and + # the entry debiting Cash/Bank/etc is the credit. + addRow('reconciliations', + { 'debit_ledger_entry_id' => $ledger_entry_id, + 'credit_ledger_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'}, + 'amount' => $row->{'PaymentAmount'}, + }); + } - # Reconcile Payment to the Charge. Since tracking is due to - # the A/R account (Lease Account in this case), credit/debit - # is from the perspective of that account. Namely, the charge - # was the debit to the A/R, and the payment was the credit. my $reconcile_amount = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'amount'}; $reconcile_amount = $row->{'PaymentAmount'} if $row->{'PaymentAmount'} <= $reconcile_amount; + # Reconcile the A/R account. Since this is from the perspective + # of the A/R, charge is the debit, and payment is the credit addRow('reconciliations', - { 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'entry'}, - 'credit_ledger_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'entry'}, - 'terminal_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'terminal'}, + { 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'}, + 'credit_ledger_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'}, 'amount' => $reconcile_amount, }); @@ -1033,11 +1082,12 @@ foreach $row (@{query($sdbh, $query)}) ## Fake Data for Testing my %fake = - ('custid' => 2, + ('customer_id' => 4, + 'ledger_id' => 4, 'invoice' => [ { 'id' => 1000, 'date' => '2009-05-05', 'entry' => [ { 'id' => 2100, - 'account' => 'Security Deposit', + 'account_name' => 'Security Deposit', 'amount' => 10, 'tax' => 0 }, ], @@ -1046,7 +1096,7 @@ my %fake = 'date' => '2009-05-01', 'thru' => '2009-05-31', 'entry' => [ { 'id' => 2110, - 'account' => 'Rent', + 'account_name' => 'Rent', 'amount' => 100, 'tax' => 5 }, ], @@ -1054,7 +1104,7 @@ my %fake = { 'id' => 1002, 'date' => '2009-05-11', 'entry' => [ { 'id' => 2120, - 'account' => 'Late Charge', + 'account_name' => 'Late Charge', 'amount' => 25, 'tax' => 0 }, ], @@ -1115,105 +1165,137 @@ my %fake = ); +sub fakeTesting { + $newdb{'ids'}{'ledger'}{'Cash-Old'} = + $newdb{'lookup'}{'account'}{'Cash'}{'ledger_id'}; -$newdb{'ids'}{'ledger'}{'Cash-Old'} = - $newdb{'lookup'}{'account'}{'Cash'}{'ledger'}; + addRow('ledgers', + { 'account_id' => $newdb{'lookup'}{'account'}{'Cash'}{'account_id'}, + 'open_stamp' => 'NOW()', + 'sequence' => 2, + 'comment' => 'Opened new ledger for testing' }); -addRow('ledgers', - { 'account_id' => $newdb{'lookup'}{'account'}{'Cash'}{'account'}, - 'open_stamp' => 'NOW()', - 'sequence' => 2, - 'comment' => 'Opened new ledger for testing' }); + $newdb{'lookup'}{'account'}{'Cash'}{'ledger_id'} = + $newdb{'tables'}{'ledgers'}{'autoid'}; -$newdb{'lookup'}{'account'}{'Cash'}{'ledger'} = - $newdb{'tables'}{'ledgers'}{'autoid'}; + my $balance = 0; + foreach $row (@{$newdb{'tables'}{'ledger_entries'}{'rows'}}) { + next unless defined $row; + $balance += $row->{'amount'} + if $row->{'debit_ledger_id'} == $newdb{'ids'}{'ledger'}{'Cash-Old'}; + $balance -= $row->{'amount'} + if $row->{'credit_ledger_id'} == $newdb{'ids'}{'ledger'}{'Cash-Old'}; + } -my $balance = 0; -foreach $row (@{$newdb{'tables'}{'ledger_entries'}{'rows'}}) { - next unless defined $row; - $balance += $row->{'amount'} - if $row->{'debit_ledger_id'} == $newdb{'ids'}{'ledger'}{'Cash-Old'}; - $balance -= $row->{'amount'} - if $row->{'credit_ledger_id'} == $newdb{'ids'}{'ledger'}{'Cash-Old'}; -} + addRow('transactions', + { 'stamp' => '2009-05-10' }); -addRow('transactions', - { 'stamp' => '2009-05-10' }); - -addRow('ledger_entries', - { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, - 'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'}, - 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Cash'}{'ledger'}, - 'credit_ledger_id' => $newdb{'ids'}{'ledger'}{'Cash-Old'}, - 'amount' => $balance, - 'name' => "Close Out ($newdb{'ids'}{'ledger'}{'Cash-Old'} -> $newdb{'tables'}{'transactions'}{'autoid'})", - 'comment' => "Carrying forward old ledger balance onto new ledger" }); + addRow('ledger_entries', + { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + 'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'}, + 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Cash'}{'ledger_id'}, + 'credit_ledger_id' => $newdb{'ids'}{'ledger'}{'Cash-Old'}, + 'amount' => $balance, + 'name' => "Close Out ($newdb{'ids'}{'ledger'}{'Cash-Old'} -> $newdb{'tables'}{'transactions'}{'autoid'})", + 'comment' => "Carrying forward old ledger balance onto new ledger" }); # NOTE: no tracking for the Cash account -$newdb{'tables'}{'ledgers'}{'rows'}[$newdb{'ids'}{'ledger'}{'Cash-Old'}]{'closed'} = 1; -$newdb{'tables'}{'ledgers'}{'rows'}[$newdb{'ids'}{'ledger'}{'Cash-Old'}]{'close_stamp'} = 'NOW()'; + $newdb{'tables'}{'ledgers'}{'rows'}[$newdb{'ids'}{'ledger'}{'Cash-Old'}]{'closed'} = 1; + $newdb{'tables'}{'ledgers'}{'rows'}[$newdb{'ids'}{'ledger'}{'Cash-Old'}]{'close_stamp'} = 'NOW()'; -foreach my $ir ('invoice', 'receipt') { - foreach my $tx (@{$fake{$ir}}) { - #print Dumper ${%$tx{'date'}}; - #exit; - addRow('transactions', - { 'id' => $tx->{'id'}, - 'stamp' => $tx->{'date'}, - 'through_date' => $tx->{'thru'}, - 'comment' => "Fake $ir" }, - 1); + foreach my $ir ('invoice', 'receipt') { + foreach my $tx (@{$fake{$ir}}) { + #print Dumper ${%$tx{'date'}}; + #exit; + addRow('transactions', + { 'id' => $tx->{'id'}, + 'stamp' => $tx->{'date'}, + 'through_date' => $tx->{'thru'}, + 'comment' => "Fake $ir" }, + 1); - foreach my $e (@{$tx->{'entry'}}) { - my $dr = ($ir eq 'invoice') ? 'A/R' : 'Cash'; - my $cr = ($ir eq 'invoice') ? $e->{'account'} : 'A/R'; - my $monetary_source_id; + foreach my $e (@{$tx->{'entry'}}) { + my $crdr = ($ir eq 'invoice') ? 'Invoice' : 'Receipt'; + my $dr = ($ir eq 'invoice') ? 'A/R' : 'Cash'; + $crdr = $dr; + my $cr = ($ir eq 'invoice') ? $e->{'account_name'} : 'A/R'; + my $monetary_source_id; - if (defined $e->{'type'}) { - addRow('monetary_sources', - { 'monetary_type_id' => $e->{'type'}, - 'name' => "Money of type " . $e->{'type'}, - 'comment' => "Fake Money For " . $e->{'id'} }); - $monetary_source_id = $newdb{'tables'}{'monetary_sources'}{'autoid'}; - } - else { - $monetary_source_id = $newdb{'ids'}{'monetary_source'}{'internal'}; - } + if (defined $e->{'type'}) { + addRow('monetary_sources', + { 'monetary_type_id' => $e->{'type'}, + 'name' => "Money of type " . $e->{'type'}, + 'comment' => "Fake Money For " . $e->{'id'} }); + $monetary_source_id = $newdb{'tables'}{'monetary_sources'}{'autoid'}; + } + else { + $monetary_source_id = $newdb{'ids'}{'monetary_source'}{'internal'}; + } - addRow('ledger_entries', - { 'id' => $e->{'id'}, - 'monetary_source_id' => $monetary_source_id, - 'transaction_id' => $tx->{'id'}, - 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$dr}{'ledger'}, - 'credit_ledger_id' => $newdb{'lookup'}{'account'}{$cr}{'ledger'}, - 'amount' => $e->{'amount'}, - 'comment' => "Fake $ir entry" }, - 1); + addRow('ledger_entries', + { 'id' => $e->{'id'}, + 'monetary_source_id' => $monetary_source_id, + 'transaction_id' => $tx->{'id'}, + 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'account'}{$cr}{'ledger_id'}, + 'customer_id' => $fake{'customer_id'}, + 'lease_id' => $fake{'lease_id'}, + 'amount' => $e->{'amount'}, + 'comment' => "Fake $ir entry" }, + 1); - foreach my $t (@{$e->{'track'}}) { - addRow('reconciliations', - { 'debit_ledger_entry_id' => $t->{'debit'}, - 'credit_ledger_entry_id' => $e->{'id'}, - 'terminal_ledger_entry_id' => $t->{'debit'}, - 'amount' => $t->{'amount'} - }); - } +# addRow('ledger_entries', +# { 'id' => $e->{'id'}, +# 'monetary_source_id' => $monetary_source_id, +# 'transaction_id' => $tx->{'id'}, +# 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$dr}{'ledger_id'}, +# 'credit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'}, +# 'customer_id' => $fake{'customer_id'}, +# 'lease_id' => $fake{'lease_id'}, +# 'amount' => $e->{'amount'}, +# 'comment' => "Fake $ir entry" }, +# 1); - next unless $e->{'tax'}; + foreach my $t (@{$e->{'track'}}) { + addRow('reconciliations', + { 'debit_ledger_entry_id' => $t->{'debit'}, + 'credit_ledger_entry_id' => $e->{'id'}, + 'amount' => $t->{'amount'} + }); + } - addRow('ledger_entries', - { 'id' => $e->{'id'}+1, - 'monetary_source_id' => $monetary_source_id, - 'transaction_id' => $tx->{'id'}, - 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$dr}{'ledger'}, - 'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Tax'}{'ledger'}, - 'amount' => $e->{'tax'}, - 'comment' => "Fake Tax" }, - 1); - } - } + next unless $e->{'tax'}; + + addRow('ledger_entries', + { 'id' => $e->{'id'}+1, + 'monetary_source_id' => $monetary_source_id, + 'transaction_id' => $tx->{'id'}, + 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Tax'}{'ledger_id'}, + 'customer_id' => $fake{'customer_id'}, + 'lease_id' => $fake{'lease_id'}, + 'amount' => $e->{'amount'}, + 'comment' => "Fake Tax" }, + 1); + +# addRow('ledger_entries', +# { 'id' => $e->{'id'}+1, +# 'monetary_source_id' => $monetary_source_id, +# 'transaction_id' => $tx->{'id'}, +# 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$dr}{'ledger_id'}, +# 'credit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'}, +# 'customer_id' => $fake{'customer_id'}, +# 'lease_id' => $fake{'lease_id'}, +# 'amount' => $e->{'tax'}, +# 'comment' => "Fake Tax" }, +# 1); + } + } + } } +#fakeTesting(); + $Data::Dumper::Sortkeys = 1; print Dumper \%newdb; # exit; diff --git a/site/app_controller.php b/site/app_controller.php index f203193..b0b0bca 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -305,7 +305,13 @@ class AppController extends Controller { $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] = diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index 3957c69..b0942b3 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -71,6 +71,7 @@ class LeasesController extends AppController { function jqGridRecordLinks(&$params, &$model, &$records, $links) { $links['Lease'] = array('number'); $links['Unit'] = array('name'); + $links['Customer'] = array('name'); return parent::jqGridRecordLinks($params, $model, $records, $links); } @@ -107,7 +108,6 @@ class LeasesController extends AppController { array(// Models 'LeaseType', 'Unit', - 'Account' => array('CurrentLedger'), 'Customer', ), 'conditions' => array(array('Lease.id' => $id)), @@ -115,23 +115,15 @@ class LeasesController extends AppController { ) ); - // Summarize each ledger - $this->Lease->statsMerge($lease, - $this->Lease->stats($lease['Lease']['id'])); - // Obtain the overall lease balance $this->Lease->statsMerge($lease['Lease'], array('stats' => $this->Lease->stats($id))); - $outstanding_balance = $lease['Lease']['stats']['Account']['Ledger']['balance']; + $outstanding_balance = $lease['Lease']['stats']['balance']; // Determine the lease security deposit $deposits = $this->Lease->findSecurityDeposits($lease['Lease']['id']); $outstanding_deposit = $deposits['summary']['balance']; - // Move the Leder stats into our alias 'CurrentLedger' - $lease['Account']['CurrentLedger'] += $lease['Account']['Ledger']; - unset($lease['Account']['Ledger']); - // Prepare to render $title = 'Lease: #' . $lease['Lease']['id']; $this->set(compact('lease', 'title', diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index 6b0100a..5fbce32 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -36,6 +36,16 @@ class LedgerEntriesController extends AppController { array('fields' => array('id', 'name'), ), + 'Customer' => + array('fields' => array('id', 'name'), + ), + + 'Lease' => + array('fields' => array('id', 'number'), + 'Unit' => + array('fields' => array('id', 'name'), + ), + ), ); if (isset($params['custom']['account_ftype'])) { @@ -118,20 +128,64 @@ class LedgerEntriesController extends AppController { $conditions[] = array('Reconciliation.'.$ftype.'_ledger_entry_id' => $params['custom']['reconcile_id']); } + if (isset($params['custom']['customer_id'])) { + $conditions[] = + array('Customer.id' => $params['custom']['customer_id']); + +/* $Account = new Account(); */ +/* if (isset($params['custom']['account_ftype']) || */ +/* isset($params['custom']['ledger_id'])) { */ +/* $conditions[] = */ +/* array('OR' => array('Account.id' => $Account->invoiceAccountID(), */ +/* 'Account.id' => $Account->receiptAccountID())); */ +/* } else { */ +/* $conditions[] = */ +/* array('OR' => array('DebitAccount.id' => $Account->invoiceAccountID(), */ +/* //'CreditAccount.id' => $Account->invoiceAccountID(), */ +/* //'DebitAccount.id' => $Account->receiptAccountID(), */ +/* 'CreditAccount.id' => $Account->receiptAccountID(), */ +/* )); */ +/* } */ + } + + if (isset($params['custom']['lease_id'])) { + $conditions[] = + array('Lease.id' => $params['custom']['lease_id']); + +/* $Account = new Account(); */ +/* if (isset($params['custom']['account_ftype']) || */ +/* isset($params['custom']['ledger_id'])) { */ +/* $conditions[] = */ +/* array('OR' => array('Account.id' => $Account->invoiceAccountID(), */ +/* 'Account.id' => $Account->receiptAccountID())); */ +/* } else { */ +/* $conditions[] = */ +/* array('OR' => array('DebitAccount.id' => $Account->invoiceAccountID(), */ +/* //'CreditAccount.id' => $Account->invoiceAccountID(), */ +/* //'DebitAccount.id' => $Account->receiptAccountID(), */ +/* 'CreditAccount.id' => $Account->receiptAccountID(), */ +/* )); */ +/* } */ + } + + if (isset($params['custom']['transaction_id'])) { + $conditions[] = + array('Transaction.id' => $params['custom']['transaction_id']); + } + return $conditions; } function jqGridRecordLinks(&$params, &$model, &$records, $links) { $links['Transaction'] = array('id'); $links['LedgerEntry'] = array('id'); - if (isset($params['custom']['account_ftype']) || isset($params['custom']['ledger_id'])) { - $links['Account'] = array('controller' => 'accounts', 'name'); - } - else { - $links['DebitAccount'] = array('controller' => 'accounts', 'name'); - $links['CreditAccount'] = array('controller' => 'accounts', 'name'); - } + $links['Account'] = array('controller' => 'accounts', 'name'); + $links['DebitAccount'] = array('controller' => 'accounts', 'name'); + $links['CreditAccount'] = array('controller' => 'accounts', 'name'); $links['MonetarySource'] = array('name'); + $links['Customer'] = array('name'); + $links['Lease'] = array('number'); + $links['Unit'] = array('name'); return parent::jqGridRecordLinks($params, $model, $records, $links); } @@ -145,8 +199,13 @@ class LedgerEntriesController extends AppController { function jqGridDataOrder(&$params, &$model, $index, $direction) { /* if ($index === 'balance') */ /* return ($index .' '. $direction); */ + $order = parent::jqGridDataOrder($params, $model, $index, $direction); - return parent::jqGridDataOrder($params, $model, $index, $direction); + if ($index === 'Transaction.stamp') { + $order[] = 'LedgerEntry.id ' . $direction; + } + + return $order; } @@ -167,6 +226,7 @@ class LedgerEntriesController extends AppController { $entry = $this->LedgerEntry->find ('first', array('contain' => array('MonetarySource.id', + 'MonetarySource.name', 'MonetarySource.MonetaryType.id', 'Transaction.id', 'Transaction.stamp', @@ -176,6 +236,9 @@ class LedgerEntriesController extends AppController { 'CreditLedger.id', 'CreditLedger.sequence', 'CreditLedger.account_id', + 'Customer.id', + 'Customer.name', + 'Lease.id', ), 'fields' => array('LedgerEntry.id', diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index 5163f19..ee409bb 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -121,7 +121,7 @@ class UnitsController extends AppController { // Get the balance on each lease. foreach ($unit['Lease'] AS &$lease) { $stats = $this->Unit->Lease->stats($lease['id']); - $lease['balance'] = $stats['Account']['Ledger']['balance']; + $lease['balance'] = $stats['balance']; } $outstanding_balance = 0; @@ -130,7 +130,7 @@ class UnitsController extends AppController { // Figure out the outstanding balance of the current lease. $stats = $this->Unit->stats($id); $outstanding_balance = - $stats['CurrentLease']['Account']['Ledger']['balance']; + $stats['CurrentLease']['balance']; // Figure out the total security deposit for the current lease. $deposits = $this->Unit->Lease->findSecurityDeposits($unit['CurrentLease']['id']); diff --git a/site/models/account.php b/site/models/account.php index 71df3f2..bded9e5 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -82,37 +82,26 @@ class Account extends AppModel { /************************************************************************** ************************************************************************** ************************************************************************** - * function: securityDepositAccountID - * - Returns the ID of the Security Deposit Account + * function: accountNameToID + * - Returns the ID of the named account */ - function securityDepositAccountID() { + function accountNameToID($name) { $this->cacheQueries = true; $account = $this->find('first', array ('recursive' => -1, - 'conditions' => array - (array('name' => 'Security Deposit')), + 'conditions' => compact('name'), )); $this->cacheQueries = false; return $account['Account']['id']; } - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * function:rentAccountID - * - Returns the ID of the Rent Account - */ - function rentAccountID() { - $this->cacheQueries = true; - $account = $this->find('first', array - ('recursive' => -1, - 'conditions' => array - (array('name' => 'Rent')), - )); - $this->cacheQueries = false; - return $account['Account']['id']; - } + function securityDepositAccountID() { return $this->accountNameToID('Security Deposit'); } + function rentAccountID() { return $this->accountNameToID('Rent'); } + function accountReceivableAccountID() { return $this->accountNameToID('A/R'); } + function invoiceAccountID() { return $this->accountReceivableAccountID(); } + function receiptAccountID() { return $this->accountReceivableAccountID(); } + //function invoiceAccountID() { return $this->accountNameToID('Invoice'); } + //function receiptAccountID() { return $this->accountNameToID('Receipt'); } /************************************************************************** @@ -122,22 +111,19 @@ class Account extends AppModel { * - Returns an array of ledger ids from the given account */ function ledgers($id, $all = false) { - $cachekey = $all ? 'all' : 'current'; - if (isset($this->cache[$id]['ledgers'][$cachekey])) { - return $this->cache[$id]['ledgers'][$cachekey]; - } - 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(); @@ -148,14 +134,11 @@ class Account extends AppModel { $ledger_ids = array($account['CurrentLedger']['id']); } - // Save the ledgers in our cache for future reference - $this->cache[$id]['ledgers'][$cachekey] = $ledger_ids; - /* pr(array('function' => 'Account::ledgers', */ /* 'args' => compact('id', 'all'), */ -/* 'return' => $this->cache[$id]['ledgers'][$cachekey])); */ +/* 'return' => $ledger_ids)); */ - return $this->cache[$id]['ledgers'][$cachekey]; + return $ledger_ids; } @@ -234,7 +217,11 @@ class Account extends AppModel { * (such as charges not paid). */ - function findUnreconciledLedgerEntries($id = null, $fundamental_type = null) { + function findUnreconciledLedgerEntries($id = null, $fundamental_type = null, $cond = null) { + if (!isset($cond)) + $cond = array(); + $cond[] = array('Account.id' => $id); + foreach (($fundamental_type ? array($fundamental_type) : array('debit', 'credit')) AS $fund) { @@ -260,7 +247,7 @@ class Account extends AppModel { 'group' => ("LedgerEntry.id" . " HAVING LedgerEntry.amount" . " <> COALESCE(SUM(Reconciliation.amount),0)"), - 'conditions' => array('Account.id' => $id), + 'conditions' => $cond, 'fields' => array(), )); $balance = 0; @@ -290,7 +277,7 @@ class Account extends AppModel { * whatever algorithm is simplest. */ - function reconcileNewLedgerEntry($id, $fundamental_type, $amount) { + function reconcileNewLedgerEntry($id, $fundamental_type, $amount, $cond = null) { $ofund = $this->fundamentalOpposite($fundamental_type); $unreconciled = array($ofund => array('entry'=>array(), 'balance'=>0)); $applied = 0; @@ -298,7 +285,7 @@ class Account extends AppModel { // if there is no money in the entry, it can reconcile nothing // don't bother wasting time sifting ledger entries. if ($amount > 0) { - $unreconciled = $this->findUnreconciledLedgerEntries($id, $ofund); + $unreconciled = $this->findUnreconciledLedgerEntries($id, $ofund, $cond); foreach ($unreconciled[$ofund]['entry'] AS $i => &$entry) { // Determine if amount is sufficient to cover the entry diff --git a/site/models/customer.php b/site/models/customer.php index 4064fe0..b78deab 100644 --- a/site/models/customer.php +++ b/site/models/customer.php @@ -8,7 +8,6 @@ class Customer extends AppModel { ); var $belongsTo = array( - 'Account', 'PrimaryContact' => array( 'className' => 'Contact', ), @@ -20,11 +19,19 @@ class Customer extends AppModel { 'conditions' => 'CurrentLease.close_date IS NULL', ), 'Lease', - 'Transaction', + 'LedgerEntry', + + // Cheat to get Account set as part of this class + 'Account', ); var $hasAndBelongsToMany = array( 'Contact', + 'Transaction' => array( + 'joinTable' => 'ledger_entries', + 'foreignKey' => 'customer_id', + 'associationForeignKey' => 'transaction_id', + ), ); @@ -80,16 +87,9 @@ class Customer extends AppModel { /* )); */ $entries = $this->Account->findLedgerEntriesRelatedToAccount - ($this->accountId($id), + ($this->Account->invoiceAccountID(), $this->Account->securityDepositAccountID(), - true, null, $link); - - foreach ($this->leaseIds($id) AS $lease_id) { - $ledger_entries = $this->Lease->findSecurityDeposits($lease_id, $link); - $this->statsMerge($entries['summary'], $ledger_entries['summary']); - $entries['Entries'] = array_merge($entries['Entries'], - $ledger_entries['Entries']); - } + true, array('LedgerEntry.customer_id' => $id), $link); /* pr(array('function' => 'Customer::findSecurityDeposits', */ /* 'args' => compact('id', 'link'), */ @@ -110,22 +110,10 @@ class Customer extends AppModel { */ function findUnreconciledLedgerEntries($id = null, $fundamental_type = null) { - $unreconciled = $this->Account->findUnreconciledLedgerEntries - ($this->accountId($id), $fundamental_type); - - foreach ($this->leaseIds($id) AS $lease_id) { - $unrec = $this->Lease->findUnreconciledLedgerEntries($lease_id, - $fundamental_type); - - foreach (array_keys($unreconciled) AS $type) { - $left = &$unreconciled[$type]; - $right = &$unrec[$type]; - - $left['entry'] = array_merge($left['entry'], $right['entry']); - $left['balance'] += $right['balance']; - } - } + ($this->Account->accountReceivableAccountID(), + $fundamental_type, + array('LedgerEntry.customer_id' => $id)); return $unreconciled; } @@ -146,25 +134,11 @@ class Customer extends AppModel { */ function reconcileNewLedgerEntry($id, $fundamental_type, $amount) { - $reconciled = $this->Account->reconcileNewLedgerEntry - ($this->accountId($id), $fundamental_type, $amount); - - foreach ($this->leaseIds($id) AS $lease_id) { - foreach (array_keys($reconciled) AS $type) { - $rec = $this->Lease->reconcileNewLedgerEntry($lease_id, - $fundamental_type, - $reconciled[$type]['unapplied']); - - $left = &$reconciled[$type]; - $right = &$rec[$type]; - - $left['entry'] = array_merge($left['entry'], $right['entry']); - $left['balance'] += $right['balance']; - $left['applied'] += $right['applied']; - $left['unapplied'] = $right['unapplied']; - } - } + ($this->Account->accountReceivableAccountID(), + $fundamental_type, + $amount, + array('LedgerEntry.customer_id' => $id)); return $reconciled; } @@ -189,7 +163,6 @@ class Customer extends AppModel { 'ContactEmail', 'ContactAddress', ), - 'Account', 'Lease' => array('Unit' => array('order' => array('sort_order'), @@ -201,22 +174,12 @@ class Customer extends AppModel { 'conditions' => array('Customer.id' => $id), )); - // Add the lease balance to each lease. - foreach ($customer['Lease'] AS &$lease) { - $stats = $this->Lease->stats($lease['id']); - $lease['balance'] = $stats['Account']['Ledger']['balance']; - } - - // Figure out the outstanding balance of the current lease. + // Figure out the outstanding balance for this customer $customer['stats'] = $this->stats($id); // Figure out the total security deposit for the current lease. $customer['deposits'] = $this->findSecurityDeposits($id); - // Add statistics into the customer account. - $customer['Account'] = array_merge($customer['Account'], - $customer['stats']['Account']['Ledger']); - return $customer; } @@ -232,29 +195,11 @@ class Customer extends AppModel { if (!$id) return null; - // Get the basic information necessary - $customer = $this->find('first', - array('contain' => - array('Account' => array - ('fields' => array('Account.id')), - - 'Lease' => array - ('fields' => array('Lease.id')) - ), - 'conditions' => array - (array('Customer.id' => $id)))); - - // Get stats from the customer account, and each lease - $stats['Account'] = $this->Account->stats($customer['Account']['id']); - foreach ($customer['Lease'] AS $lease) { - $this->statsMerge($stats['Lease'], $this->Lease->stats($lease['id'])); - } - - // Merge the stats from both the customer specific account, as - // well as the leases. This will provide current customer standing. - $this->statsMerge($stats, $stats['Account']['Ledger']); - $this->statsMerge($stats, $stats['Lease']['Account']['Ledger']); + $stats = $this->Account->stats($this->Account->accountReceivableAccountID(), true, + array('LedgerEntry.customer_id' => $id)); + // Pull to the top level and return + $stats = $stats['Ledger']; return $stats; } diff --git a/site/models/lease.php b/site/models/lease.php index 13873e5..66d2a47 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -25,11 +25,18 @@ class Lease extends AppModel { var $belongsTo = array( 'LeaseType', 'Unit', - 'Account', 'Customer', 'LateSchedule', ); + var $hasMany = array( + 'LedgerEntry', + + // Cheat to get Account set as part of this class + 'Account', + ); + + /************************************************************************** ************************************************************************** ************************************************************************** @@ -37,15 +44,7 @@ class Lease extends AppModel { * - Returns the accountId of the given lease */ function accountId($id) { - $this->cacheQueries = true; - $lease = $this->find('first', array - ('recursive' => -1, - 'fields' => array('account_id'), - 'conditions' => array(array('id' => $id)), - )); - $this->cacheQueries = false; - - return $lease['Lease']['account_id']; + return $this->Account->invoiceAccountID(); } @@ -61,6 +60,10 @@ class Lease extends AppModel { /* 'args' => compact('id', 'all', 'cond', 'link'), */ /* )); */ + if (!isset($cond)) + $cond = array(); + $cond[] = array('LedgerEntry.lease_id' => $id); + $entries = $this->Account->findLedgerEntries($this->accountId($id), $all, $cond, $link); @@ -87,7 +90,7 @@ class Lease extends AppModel { $entries = $this->Account->findLedgerEntriesRelatedToAccount ($this->accountId($id), $this->Account->securityDepositAccountID(), - true, null, $link); + true, array('LedgerEntry.lease_id' => $id), $link); /* pr(array('function' => 'Lease::findSecurityDeposits', */ /* 'args' => compact('id', 'link'), */ @@ -108,7 +111,7 @@ class Lease extends AppModel { function findUnreconciledLedgerEntries($id = null, $fundamental_type = null) { return $this->Account->findUnreconciledLedgerEntries - ($this->accountId($id), $fundamental_type); + ($this->accountId($id), $fundamental_type, array('LedgerEntry.lease_id' => $id)); } @@ -128,7 +131,7 @@ class Lease extends AppModel { function reconcileNewLedgerEntry($id, $fundamental_type, $amount) { return $this->Account->reconcileNewLedgerEntry - ($this->accountId($id), $fundamental_type, $amount); + ($this->accountId($id), $fundamental_type, $amount, array('LedgerEntry.lease_id' => $id)); } @@ -143,18 +146,11 @@ class Lease extends AppModel { if (!$id) return null; - // Find the associated account. - $lease = $this->find('first', - array('recursive' => -1, - 'conditions' => array(array('Lease.id' => $id)))); - - // Pull the stats from the account. - $stats['Account'] = $this->Account->stats($lease['Lease']['account_id']); - - // Place a summary of the stats (one lease account in this case) - // at the top level for easy summarized access. - $this->statsMerge($stats, $stats['Account']['Ledger']); + $stats = $this->Account->stats($this->Account->accountReceivableAccountID(), true, + array('LedgerEntry.lease_id' => $id)); + // Pull to the top level and return + $stats = $stats['Ledger']; return $stats; } diff --git a/site/models/ledger.php b/site/models/ledger.php index 25f8f33..aa10e76 100644 --- a/site/models/ledger.php +++ b/site/models/ledger.php @@ -115,6 +115,9 @@ class Ledger extends AppModel { * - Returns summary data from the requested ledger. */ function stats($id, $cond = null) { + if (!isset($cond)) + $cond = array(); + $cond[] = array('Ledger.id' => $id); $stats = $this->find ('first', array @@ -138,8 +141,7 @@ class Ledger extends AppModel { ) * IF(LedgerEntry.amount, LedgerEntry.amount, 0) ) AS balance", "COUNT(LedgerEntry.id) AS entries"), - 'conditions' => array(isset($cond) ? $cond : array(), - array('Ledger.id' => $id)), + 'conditions' => $cond, 'group' => 'Ledger.id', )); diff --git a/site/models/ledger_entry.php b/site/models/ledger_entry.php index e0ea6a9..6831545 100644 --- a/site/models/ledger_entry.php +++ b/site/models/ledger_entry.php @@ -11,6 +11,8 @@ class LedgerEntry extends AppModel { var $belongsTo = array( 'MonetarySource', 'Transaction', + 'Customer', + 'Lease', 'DebitLedger' => array( 'className' => 'Ledger', diff --git a/site/views/customers/view.ctp b/site/views/customers/view.ctp index af239b2..fbf4b4a 100644 --- a/site/views/customers/view.ctp +++ b/site/views/customers/view.ctp @@ -63,12 +63,13 @@ echo $this->element('leases', /********************************************************************** - * Account + * Customer Account History */ -echo $this->element('accounts', +echo $this->element('ledger_entries', array('caption' => 'Account', - 'accounts' => array($customer['Account']))); + 'customer_id' => $customer['Customer']['id'], + )); /* End "detail supporting" div */ diff --git a/site/views/elements/jqGrid.ctp b/site/views/elements/jqGrid.ctp index 1b4ae4b..be6dbde 100644 --- a/site/views/elements/jqGrid.ctp +++ b/site/views/elements/jqGrid.ctp @@ -143,8 +143,12 @@ foreach ($jqGridColumns AS &$col) { } // Set the default sort column -reset($jqGridColumns); -$sortname = current($jqGridColumns); +if (isset($sort_column)) { + $sortname = $jqGridColumns[$sort_column]; +} else { + reset($jqGridColumns); + $sortname = current($jqGridColumns); +} $sortname = $sortname['index']; // Configure the grid setup, giving priority to user defined parameters diff --git a/site/views/elements/ledger_entries.ctp b/site/views/elements/ledger_entries.ctp index 3755a78..b4602c2 100644 --- a/site/views/elements/ledger_entries.ctp +++ b/site/views/elements/ledger_entries.ctp @@ -21,6 +21,9 @@ else { $cols['Debit Account'] = array('index' => 'DebitAccount.name', 'formatter' => 'longname'); $cols['Credit Account'] = array('index' => 'CreditAccount.name', 'formatter' => 'longname'); } +$cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'name'); +$cols['Lease'] = array('index' => 'Lease.number', 'formatter' => 'id'); +$cols['Unit'] = array('index' => 'Unit.name', 'formatter' => 'name'); $cols['Source'] = array('index' => 'MonetarySource.name', 'formatter' => 'name'); $cols['Comment'] = array('index' => 'LedgerEntry.comment', 'formatter' => 'comment', 'width'=>150); if (isset($ledger_id)) { @@ -34,7 +37,8 @@ if (isset($reconcile_id)) { $cols['Applied'] = array('index' => "Reconciliation.amount", 'formatter' => 'currency'); } -$custom_post_data = compact('ledger_id', 'account_type', 'account_ftype', 'notxgroup'); +$custom_post_data = compact('ledger_id', 'account_type', 'account_ftype', + 'customer_id', 'lease_id', 'transaction_id', 'notxgroup'); $jqGrid_options = array('jqGridColumns' => $cols, 'controller' => 'ledger_entries', @@ -42,11 +46,6 @@ $jqGrid_options = array('jqGridColumns' => $cols, $jqGrid_options += compact('grid_div_id', 'grid_id', 'caption', 'grid_setup', 'limit'); -if (isset($ledger_id)) { - $jqGrid_options += array('action' => 'ledger', - 'limit' => 50); -} - if (isset($ledger_entries)) { $jqGrid_options += array('custom_ids' => array_map(create_function('$data', @@ -54,6 +53,10 @@ if (isset($ledger_entries)) { $ledger_entries), 'limit' => 10); } +else { + $jqGrid_options += array('action' => 'ledger', + 'limit' => 50); +} if (isset($reconcile_id)) { $custom_post_data += compact('reconcile_id'); @@ -61,5 +64,6 @@ if (isset($reconcile_id)) { } $jqGrid_options += compact('custom_post_data'); +$jqGrid_options['sort_column'] = 'Date'; echo $this->element('jqGrid', $jqGrid_options); diff --git a/site/views/leases/view.ctp b/site/views/leases/view.ctp index 8ee77e9..f18e798 100644 --- a/site/views/leases/view.ctp +++ b/site/views/leases/view.ctp @@ -11,7 +11,6 @@ echo '
    ' . "\n"; $lease_type = $lease['LeaseType']; $customer = $lease['Customer']; -$account = $lease['Account']; $unit = $lease['Unit']; if (isset($lease['Lease'])) @@ -36,10 +35,6 @@ $rows = array(array('ID', $lease['id']), array('Notice Given', FormatHelper::date($lease['notice_given_date'], true)), array('Notice Received', FormatHelper::date($lease['notice_received_date'], true)), array('Closed', FormatHelper::date($lease['close_date'], true)), - array('Account', $html->link($account['name'], - array('controller' => 'accounts', - 'action' => 'view', - $account['id']))), array('Deposit', FormatHelper::currency($lease['deposit'])), array('Rent', FormatHelper::currency($lease['amount'])), array('Comment', $lease['comment'])); @@ -53,7 +48,7 @@ echo $this->element('table', /********************************************************************** - * Account Info Box + * Lease Info Box */ echo '
    ' . "\n"; @@ -80,15 +75,15 @@ echo '
    ' . "\n"; /********************************************************************** - * Current Ledger + * Lease Account History */ echo $this->element('ledger_entries', - array('caption' => "Current Ledger: (#{$account['id']}-{$account['CurrentLedger']['sequence']})", - 'ledger_id' => $account['CurrentLedger']['id'], - 'account_type' => $account['type'], + array('caption' => 'Account', + 'lease_id' => $lease['id'], )); + /* End "detail supporting" div */ echo '
    ' . "\n"; diff --git a/site/views/ledger_entries/view.ctp b/site/views/ledger_entries/view.ctp index 51a6cec..384d14e 100644 --- a/site/views/ledger_entries/view.ctp +++ b/site/views/ledger_entries/view.ctp @@ -13,6 +13,8 @@ $transaction = $entry['Transaction']; $debit_ledger = $entry['DebitLedger']; $credit_ledger = $entry['CreditLedger']; $source = $entry['MonetarySource']; +$customer = $entry['Customer']; +$lease = $entry['Lease']; $entry = $entry['LedgerEntry']; $rows = array(array('ID', $entry['id']), @@ -21,8 +23,16 @@ $rows = array(array('ID', $entry['id']), 'action' => 'view', $transaction['id']))), array('Timestamp', FormatHelper::datetime($transaction['stamp'])), - array('Monetary Source', (isset($source['id']) - ? $html->link('#'.$source['id'], + array('Customer', $html->link($customer['name'], + array('controller' => 'customers', + 'action' => 'view', + $customer['id']))), + array('Lease', $html->link('#'.$lease['id'], + array('controller' => 'leases', + 'action' => 'view', + $lease['id']))), + array('Monetary Source', (isset($source['name']) + ? $html->link($source['name'], array('controller' => 'monetary_sources', 'action' => 'view', $source['id'])) diff --git a/site/views/transactions/view.ctp b/site/views/transactions/view.ctp index c51871e..2e02e60 100644 --- a/site/views/transactions/view.ctp +++ b/site/views/transactions/view.ctp @@ -54,7 +54,8 @@ echo '
    ' . "\n"; echo $this->element('ledger_entries', array('caption' => 'Entries in Transaction', - 'ledger_entries' => $transaction['LedgerEntry'], + //'ledger_entries' => $transaction['LedgerEntry'], + 'transaction_id' => $transaction['Transaction']['id'], 'notxgroup' => true, )); diff --git a/site/views/units/view.ctp b/site/views/units/view.ctp index 9ea350f..a417554 100644 --- a/site/views/units/view.ctp +++ b/site/views/units/view.ctp @@ -57,16 +57,15 @@ echo $this->element('leases', /********************************************************************** - * Ledger History + * Current Tenant Lease Account History */ -/* foreach($unit['Lease'] AS $lease) { */ -/* pr($lease); */ -/* $caption = 'Lease #'.$lease['number'].' (Tenant: '.$lease['Customer']['name'].')'; */ -/* echo $this->element('lease', */ -/* array('caption' => $caption, */ -/* 'entries' => $lease['Customer']['Transaction'], */ -/* 'ledger' => array('mix'=>1))); */ -/* } */ + +echo $this->element('ledger_entries', + array('caption' => ('Current Lease Account (' . + $unit['CurrentLease']['Customer']['name'] + . ')'), + 'lease_id' => $unit['CurrentLease']['id'], + )); /* End "detail supporting" div */ From ce4fa4131a1c9387c9a7df4acf5f082749e86116 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 24 Jun 2009 00:33:39 +0000 Subject: [PATCH 181/717] More changes. I just can't seem to come up with a solution that works that I like. The problem now, without invoice/receipt, is that one check cannot cleanly pay for two units. git-svn-id: file:///svn-source/pmgr/branches/single_AR_20090622@182 97e9348a-65ac-dc4b-aefc-98561f571b83 --- scripts/sitelink2pmgr.pl | 116 ++++++++++++------ site/app_controller.php | 50 +++++--- .../controllers/ledger_entries_controller.php | 60 ++++++++- site/models/ledger_entry.php | 25 ++-- site/views/customers/view.ctp | 1 + site/views/elements/jqGrid.ctp | 4 + site/views/elements/ledger_entries.ctp | 57 +++++++-- site/views/leases/view.ctp | 3 +- site/views/ledger_entries/view.ctp | 57 +++++---- site/views/units/view.ctp | 1 + site/webroot/css/layout.css | 6 +- 11 files changed, 272 insertions(+), 108 deletions(-) diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index e7ad2d8..d50f0c9 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -94,6 +94,32 @@ sub addRow { } +###################################################################### +###################################################################### +## updateRow + +sub updateRow { + my ($table, $id, $cols) = @_; + die unless $table; + die unless $id; + die unless ref($cols) eq 'HASH'; + + die "Table `$table` is unknown!" + unless defined $newdb{'tables'}{$table}; + + die "Table `$table` : ID `$id` does not exist!" + unless $newdb{'tables'}{$table}{'rows'}[$id]; + + # For debug purposes + my $line = (caller())[2]; + $cols->{'--UPDATE-LINE--'} = [] unless $cols->{'--UPDATE-LINE--'}; + push(@{$cols->{'--UPDATE-LINE--'}}, "updateRow called from line: $line"); + + #$newdb{'tables'}{$table}{'rows'}[$id] = $cols; + return $id; +} + + ###################################################################### ###################################################################### ## query @@ -985,24 +1011,25 @@ $newdb{'lookup'}{'payment'} = {}; $query = "SELECT * FROM Payments ORDER BY PaymentID"; foreach $row (@{query($sdbh, $query)}) { - my $monetary_source_id; - my $payment_acct; - my $debit_ledger_id; - my $ledger_entry_id; + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}} = {}; if ($row->{'PaymentDate'} =~ m%3/25/2009%) { - $monetary_source_id = $newdb{'ids'}{'monetary_source'}{'Closing'}; - $payment_acct = 'Bank'; + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'} + = $newdb{'ids'}{'monetary_source'}{'Closing'}; + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'account_name'} + = 'Bank'; } else { - $monetary_source_id = $newdb{'ids'}{'monetary_source'}{ + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'} + = $newdb{'ids'}{'monetary_source'}{ $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'} }; - $payment_acct = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'account_name'}; + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'account_name'} + = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'account_name'}; } if (!$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}) { - if (!defined $monetary_source_id) { + if (!defined $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'}) { my $name; $name = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'}; if ($name eq 'Check') { @@ -1012,52 +1039,67 @@ foreach $row (@{query($sdbh, $query)}) { 'monetary_type_id' => $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'monetary_type'}{'id'}, 'name' => $name, 'comment' => "Payment: $row->{'PaymentID'}; Type: $row->{'PaymentType'}; Check: $row->{'CheckNum'}; $row->{'Memo'}" }); - $monetary_source_id = $newdb{'tables'}{'monetary_sources'}{'autoid'}; + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'} + = $newdb{'tables'}{'monetary_sources'}{'autoid'}; } $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'} - = $monetary_source_id; + = $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'}; } - $debit_ledger_id = $newdb{'lookup'}{'account'}{$payment_acct}{'ledger_id'}; + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'} + = $newdb{'lookup'}{'account'}{$newdb{'lookup'}{'payment'}{ + $row->{'PaymentID'}}{'account_name'} + }{'ledger_id'}; + if ($use_ir) { addRow('ledger_entries', { 'monetary_source_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}, 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, - 'debit_ledger_id' => $debit_ledger_id, + 'debit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'}, 'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Receipt'}{'ledger_id'}, 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, 'amount' => $row->{'PaymentAmount'}, - 'comment' => "Receipt: $row->{'ReceiptNum'}; Payment: $row->{'PaymentID'}; Charge: $row->{'ChargeID'}" }); - $ledger_entry_id = $newdb{'tables'}{'ledger_entries'}{'autoid'}; - $debit_ledger_id = $newdb{'lookup'}{'account'}{'Receipt'}{'ledger_id'}; + 'comment' => "Receipt: $row->{'ReceiptNum'}; Charge: $row->{'ChargeID'}; Payment: $row->{'PaymentID'}" }); + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} + = $newdb{'tables'}{'ledger_entries'}{'autoid'}; + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'} + = $newdb{'lookup'}{'account'}{'Receipt'}{'ledger_id'}; } - addRow('ledger_entries', - { 'monetary_source_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}, - 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, - 'debit_ledger_id' => $debit_ledger_id, - 'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_id'}, - 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, - 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, - 'amount' => $row->{'PaymentAmount'}, - 'comment' => "Receipt: $row->{'ReceiptNum'}; Payment: $row->{'PaymentID'}; Charge: $row->{'ChargeID'}" }); + # Sitelink splits one physical payment into multiple "payments" to match each charge + # This is kludgy, but for our cases at least, brings those pseudo-payments back into + # a single one. It presumes that there is only one PaymentType per receipt. + if (!$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}) { + addRow('ledger_entries', + { 'monetary_source_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}, + 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, + 'debit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_id'}, + 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, + #'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, + 'amount' => 0, + 'comment' => "Receipt: $row->{'ReceiptNum'}; " }); - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}} - = { 'ledger_entry_id' => $newdb{'tables'}{'ledger_entries'}{'autoid'} }; - - if ($use_ir) { - # Reconcile the receipt account. Since this is from the perspective - # of the receipt, the entry crediting the A/R is the debit, and - # the entry debiting Cash/Bank/etc is the credit. - addRow('reconciliations', - { 'debit_ledger_entry_id' => $ledger_entry_id, - 'credit_ledger_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'}, - 'amount' => $row->{'PaymentAmount'}, - }); + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'} + = $newdb{'tables'}{'ledger_entries'}{'autoid'}; } + $newdb{'tables'}{'ledger_entries'}{'rows'}[ + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'} + ]{'amount'} += $row->{'PaymentAmount'}; + + $newdb{'tables'}{'ledger_entries'}{'rows'}[ + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'} + ]{'comment'} .= 'P:'.$row->{'PaymentID'} . '->C:' . $row->{'ChargeID'} . '; '; + + # OK, now that the receipt is reconciled, update + # payment to reference the true ledger_entry_id + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} + = $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}; + + # Figure out how much of the charge can be reconciled my $reconcile_amount = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'amount'}; $reconcile_amount = $row->{'PaymentAmount'} if $row->{'PaymentAmount'} <= $reconcile_amount; diff --git a/site/app_controller.php b/site/app_controller.php index b0b0bca..d8de116 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -344,30 +344,40 @@ class AppController extends Controller { } function jqGridDataOutputRecords(&$params, &$model, &$records) { - $model_alias = $model->alias; - $id = 'jqGrid_id'; - + $id_field = 'jqGrid_id'; foreach ($records AS $record) { - echo " \n"; - foreach ($params['fields'] AS $field) { - if (preg_match("/\./", $field)) { - list($tbl, $col) = explode(".", $field); - $data = $record[$tbl][$col]; - } - else { - $data = $record[$model_alias][$field]; - } - - // be sure to put text data in CDATA - if (preg_match("/^\d*$/", $data)) - echo " $data\n"; - else - echo " \n"; - } - echo " \n"; + $this->jqGridDataOutputRecord($params, $model, $record, + $record[$id_field], $params['fields']); } } + function jqGridDataOutputRecord(&$params, &$model, &$record, $id, $fields) { + echo " \n"; + foreach ($fields AS $field) { + $this->jqGridDataOutputRecordField($params, $model, $record, $field); + } + echo " \n"; + } + + function jqGridDataOutputRecordField(&$params, &$model, &$record, $field) { + if (preg_match("/\./", $field)) { + list($tbl, $col) = explode(".", $field); + $data = $record[$tbl][$col]; + } + else { + $data = $record[$model->alias][$field]; + } + $this->jqGridDataOutputRecordCell($params, $model, $record, $field, $data); + } + + function jqGridDataOutputRecordCell(&$params, &$model, &$record, $field, $data) { + // be sure to put text data in CDATA + if (preg_match("/^\d*$/", $data)) + echo " $data\n"; + else + echo " \n"; + } + function jqGridDataFinalize(&$params) { if ($params['debug']) { $xml = ob_get_contents(); diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index 5fbce32..8206707 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -25,6 +25,14 @@ class LedgerEntriesController extends AppController { * to jqGrid. */ + function jqGridDataSetup(&$params) { + parent::jqGridDataSetup($params); + if (isset($params['custom']['ar_account'])) { + $params['custom']['account_id'] = + $this->LedgerEntry->DebitLedger->Account->accountReceivableAccountID(); + } + } + function jqGridDataTables(&$params, &$model) { $link = array(// Models @@ -87,6 +95,19 @@ class LedgerEntriesController extends AppController { ); } + if (isset($params['custom']['account_id'])) { + $account_id = $params['custom']['account_id']; + $link['Ledger'] = + array('fields' => array('id', 'sequence'), + 'conditions' => ("Ledger.id = IF(DebitLedger.account_id = $account_id," . + " LedgerEntry.credit_ledger_id," . + " LedgerEntry.debit_ledger_id)"), + 'Account' => array( + 'fields' => array('id', 'name'), + ), + ); + } + if (isset($params['custom']['reconcile_id'])) { $ftype = $params['custom']['account_ftype']; $ftype = $this->LedgerEntry->DebitLedger->Account->fundamentalOpposite($ftype); @@ -102,11 +123,14 @@ class LedgerEntriesController extends AppController { $ledger_id = (isset($params['custom']['ledger_id']) ? $params['custom']['ledger_id'] : null); + $account_id = (isset($params['custom']['account_id']) + ? $params['custom']['account_id'] + : null); $account_type = (isset($params['custom']['account_type']) ? $params['custom']['account_type'] : null); - return $model->ledgerContextFields2($ledger_id, $account_type); + return $model->ledgerContextFields2($ledger_id, $account_id, $account_type); } function jqGridDataConditions(&$params, &$model) { @@ -128,6 +152,13 @@ class LedgerEntriesController extends AppController { $conditions[] = array('Reconciliation.'.$ftype.'_ledger_entry_id' => $params['custom']['reconcile_id']); } + if (isset($params['custom']['account_id'])) { + $conditions[] = + array('OR' => + array(array('CreditAccount.id' => $params['custom']['account_id']), + array('DebitAccount.id' => $params['custom']['account_id']))); + } + if (isset($params['custom']['customer_id'])) { $conditions[] = array('Customer.id' => $params['custom']['customer_id']); @@ -208,6 +239,32 @@ class LedgerEntriesController extends AppController { return $order; } + function jqGridRecordsPostProcess(&$params, &$model, &$records) { + parent::jqGridRecordsPostProcess($params, $model, $records); + + $subtotal = 0; + foreach ($records AS &$record) { + $amount = (isset($record['LedgerEntry']['balance']) + ? $record['LedgerEntry']['balance'] + : $record['LedgerEntry']['amount']); + $record['LedgerEntry']['subtotal'] = ($subtotal += $amount); + + continue; + // Experiment to minimize columns by putting the monetary source + // as the Account, when available + if ($record['MonetarySource']['name']) + $record['Account']['name'] = $record['MonetarySource']['name']; + } + } + + function jqGridDataOutputRecordCell(&$params, &$model, &$record, $field, $data) { +/* if ($field === 'CreditAccount.name') { */ +/* $data .= '-OK'; */ +/* } */ + + parent::jqGridDataOutputRecordCell($params, $model, $record, $field, $data); + } + /************************************************************************** ************************************************************************** @@ -247,6 +304,7 @@ class LedgerEntriesController extends AppController { 'conditions' => array('LedgerEntry.id' => $id), )); + pr($entry); // Because 'DebitLedger' and 'CreditLedger' both relate to 'Account', // CakePHP will not include them in the LedgerEntry->find (or so it diff --git a/site/models/ledger_entry.php b/site/models/ledger_entry.php index 6831545..b528820 100644 --- a/site/models/ledger_entry.php +++ b/site/models/ledger_entry.php @@ -86,7 +86,7 @@ class LedgerEntry extends AppModel { return $fields; } - function ledgerContextFields2($ledger_id = null, $account_type = null) { + function ledgerContextFields2($ledger_id = null, $account_id = null, $account_type = null) { $fields = array('id', 'name', 'comment', 'amount'); if (isset($ledger_id)) { @@ -95,20 +95,29 @@ class LedgerEntry extends AppModel { $fields[] = ("IF(LedgerEntry.credit_ledger_id = $ledger_id," . " SUM(LedgerEntry.amount), NULL) AS credit"); - if (isset($account_type)) { - if (in_array($account_type, array('ASSET', 'EXPENSE'))) - $ledger_type = 'debit'; - else - $ledger_type = 'credit'; - - $fields[] = ("(IF(LedgerEntry.{$ledger_type}_ledger_id = $ledger_id," . + if (isset($account_id) || isset($account_type)) { + $Account = new Account(); + $account_ftype = $Account->fundamentalType($account_id ? $account_id : $account_type); + $fields[] = ("(IF(LedgerEntry.{$account_ftype}_ledger_id = $ledger_id," . " 1, -1) * SUM(LedgerEntry.amount)) AS balance"); } } + elseif (isset($account_id)) { + $fields[] = ("IF(DebitLedger.account_id = $account_id," . + " SUM(LedgerEntry.amount), NULL) AS debit"); + $fields[] = ("IF(CreditLedger.account_id = $account_id," . + " SUM(LedgerEntry.amount), NULL) AS credit"); + + $Account = new Account(); + $account_ftype = ucfirst($Account->fundamentalType($account_id)); + $fields[] = ("(IF({$account_ftype}Ledger.account_id = $account_id," . + " 1, -1) * SUM(LedgerEntry.amount)) AS balance"); + } return $fields; } + function ledgerContextConditions($ledger_id, $account_type) { if (isset($ledger_id)) { return array diff --git a/site/views/customers/view.ctp b/site/views/customers/view.ctp index fbf4b4a..b6d18de 100644 --- a/site/views/customers/view.ctp +++ b/site/views/customers/view.ctp @@ -69,6 +69,7 @@ echo $this->element('leases', echo $this->element('ledger_entries', array('caption' => 'Account', 'customer_id' => $customer['Customer']['id'], + 'ar_account' => true, )); diff --git a/site/views/elements/jqGrid.ctp b/site/views/elements/jqGrid.ctp index be6dbde..fdbfc35 100644 --- a/site/views/elements/jqGrid.ctp +++ b/site/views/elements/jqGrid.ctp @@ -189,10 +189,14 @@ $jqGrid_setup = array_merge jQuery(document).ready(function(){ currencyFormatter = function(el, cellval, opts) { + if (!cellval) + return; $(el).html(fmtCurrency(cellval)); } idFormatter = function(el, cellval, opts) { + if (!cellval) + return; $(el).html('#'+cellval); } diff --git a/site/views/elements/ledger_entries.ctp b/site/views/elements/ledger_entries.ctp index b4602c2..bf14b9c 100644 --- a/site/views/elements/ledger_entries.ctp +++ b/site/views/elements/ledger_entries.ctp @@ -1,5 +1,30 @@ 'Transaction.id', 'formatter' => 'id'); } else { - $notxgroup = true; + $notxgroup = false; $cols['Transaction'] = array('index' => 'Transaction.id', 'formatter' => 'id'); $cols['Entry'] = array('index' => 'LedgerEntry.id', 'formatter' => 'id'); } $cols['Date'] = array('index' => 'Transaction.stamp', 'formatter' => 'date'); -if (isset($account_ftype) || isset($ledger_id)) { - $cols['Account'] = array('index' => 'Account.name', 'formatter' => 'longname'); + +if ($single_account) { + $cols['Account'] = array('index' => 'Account.name', 'formatter' => 'name'); } else { - $cols['Debit Account'] = array('index' => 'DebitAccount.name', 'formatter' => 'longname'); - $cols['Credit Account'] = array('index' => 'CreditAccount.name', 'formatter' => 'longname'); + $cols['Debit Account'] = array('index' => 'DebitAccount.name', 'formatter' => 'name'); + $cols['Credit Account'] = array('index' => 'CreditAccount.name', 'formatter' => 'name'); } -$cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'name'); +$cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'longname'); $cols['Lease'] = array('index' => 'Lease.number', 'formatter' => 'id'); $cols['Unit'] = array('index' => 'Unit.name', 'formatter' => 'name'); $cols['Source'] = array('index' => 'MonetarySource.name', 'formatter' => 'name'); $cols['Comment'] = array('index' => 'LedgerEntry.comment', 'formatter' => 'comment', 'width'=>150); -if (isset($ledger_id)) { + +if ($single_amount) { + $cols['Amount'] = array('index' => 'LedgerEntry.amount', 'formatter' => 'currency'); +} +else { $cols['Debit'] = array('index' => 'debit', 'formatter' => 'currency'); $cols['Credit'] = array('index' => 'credit', 'formatter' => 'currency'); } -else { - $cols['Amount'] = array('index' => 'LedgerEntry.amount', 'formatter' => 'currency'); -} -if (isset($reconcile_id)) { + +if ($applied_amount) { $cols['Applied'] = array('index' => "Reconciliation.amount", 'formatter' => 'currency'); } -$custom_post_data = compact('ledger_id', 'account_type', 'account_ftype', +if ($subtotal_amount) { + $cols['Sub-Total'] = array('index' => 'subtotal', 'formatter' => 'currency', 'sortable' => false); +} + +$custom_post_data = compact('ledger_id', 'account_id', 'ar_account', + 'account_type', 'account_ftype', 'customer_id', 'lease_id', 'transaction_id', 'notxgroup'); $jqGrid_options = array('jqGridColumns' => $cols, diff --git a/site/views/leases/view.ctp b/site/views/leases/view.ctp index f18e798..fabee8f 100644 --- a/site/views/leases/view.ctp +++ b/site/views/leases/view.ctp @@ -19,7 +19,7 @@ if (isset($lease['Lease'])) $rows = array(array('ID', $lease['id']), array('Number', $lease['number']), array('Lease Type', $lease_type['name']), - array('Unit', $html->link($unit['id'], + array('Unit', $html->link($unit['name'], array('controller' => 'units', 'action' => 'view', $unit['id']))), @@ -81,6 +81,7 @@ echo '
    ' . "\n"; echo $this->element('ledger_entries', array('caption' => 'Account', 'lease_id' => $lease['id'], + 'ar_account' => true, )); diff --git a/site/views/ledger_entries/view.ctp b/site/views/ledger_entries/view.ctp index 384d14e..e92adba 100644 --- a/site/views/ledger_entries/view.ctp +++ b/site/views/ledger_entries/view.ctp @@ -23,14 +23,18 @@ $rows = array(array('ID', $entry['id']), 'action' => 'view', $transaction['id']))), array('Timestamp', FormatHelper::datetime($transaction['stamp'])), - array('Customer', $html->link($customer['name'], - array('controller' => 'customers', - 'action' => 'view', - $customer['id']))), - array('Lease', $html->link('#'.$lease['id'], - array('controller' => 'leases', - 'action' => 'view', - $lease['id']))), + array('Customer', (isset($customer['name']) + ? $html->link($customer['name'], + array('controller' => 'customers', + 'action' => 'view', + $customer['id'])) + : null)), + array('Lease', (isset($lease['id']) + ? $html->link('#'.$lease['id'], + array('controller' => 'leases', + 'action' => 'view', + $lease['id'])) + : null)), array('Monetary Source', (isset($source['name']) ? $html->link($source['name'], array('controller' => 'monetary_sources', @@ -107,26 +111,25 @@ echo '
    ' . "\n"; * Reconciliation Ledger Entries */ -echo $this->element('ledger_entries', - array('caption' => "Debit Applications", - 'grid_div_id' => 'debit_reconciliation_ledger_entries', - //'ledger_id' => $debit_ledger['id'], - //'account_type' => $debit_ledger['Account']['type'], - 'account_ftype' => 'debit', - 'reconcile_id' => $entry['id'], - 'ledger_entries' => $reconciled['debit']['entry'], - )); +if ($debit_ledger['Account']['trackable']) { + echo $this->element('ledger_entries', + array('caption' => "Payments Received", + 'grid_div_id' => 'debit_reconciliation_ledger_entries', + 'account_ftype' => 'debit', + 'reconcile_id' => $entry['id'], + //'ledger_entries' => $reconciled['debit']['entry'], + )); +} -echo $this->element('ledger_entries', - array('caption' => "Credit Applications", - 'grid_div_id' => 'credit_reconciliation_ledger_entries', - //'ledger_id' => $credit_ledger['id'], - //'account_type' => $credit_ledger['Account']['type'], - //'account_ftype' => 'debit', // Looking for debits to match this credit - 'account_ftype' => 'credit', - 'reconcile_id' => $entry['id'], - 'ledger_entries' => $reconciled['credit']['entry'], - )); +if ($credit_ledger['Account']['trackable']) { + echo $this->element('ledger_entries', + array('caption' => "Charges Paid", + 'grid_div_id' => 'credit_reconciliation_ledger_entries', + 'account_ftype' => 'credit', + 'reconcile_id' => $entry['id'], + //'ledger_entries' => $reconciled['credit']['entry'], + )); +} /* End "detail supporting" div */ diff --git a/site/views/units/view.ctp b/site/views/units/view.ctp index a417554..2ee8d08 100644 --- a/site/views/units/view.ctp +++ b/site/views/units/view.ctp @@ -64,6 +64,7 @@ echo $this->element('ledger_entries', array('caption' => ('Current Lease Account (' . $unit['CurrentLease']['Customer']['name'] . ')'), + 'ar_account' => true, 'lease_id' => $unit['CurrentLease']['id'], )); diff --git a/site/webroot/css/layout.css b/site/webroot/css/layout.css index 74b1272..9fb18b2 100644 --- a/site/webroot/css/layout.css +++ b/site/webroot/css/layout.css @@ -65,8 +65,10 @@ tr.evnrow { background: #f4f4f4; } */ table.detail { width : 60%; - float: left; } -table.detail td.field { width: 10em; } + float : left; } +table.detail td.field { width : 10em; } + +table.item.detail td.value { white-space : normal; } div.detail.supporting { clear : both; padding-top: 1.5em; } From c6f68861b35df467439d61cd838583ca78d55b4f Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 30 Jun 2009 01:06:33 +0000 Subject: [PATCH 182/717] Branch to revert way way back and get down to simple items, even if it's not extensible. git-svn-id: file:///svn-source/pmgr/branches/charge_credit_20090629@188 97e9348a-65ac-dc4b-aefc-98561f571b83 From 1c8cc70a284801acc662e1bf16b1740aa84f2f05 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 30 Jun 2009 04:47:18 +0000 Subject: [PATCH 183/717] Moving back to the Invoice/Receipt mechanism. Seems to work fairly well, even if it's non-standard. git-svn-id: file:///svn-source/pmgr/branches/charge_credit_20090629@189 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 32 +- scripts/sitelink2pmgr.pl | 293 ++++++++++-------- .../controllers/ledger_entries_controller.php | 2 +- site/views/ledger_entries/view.ctp | 16 +- 4 files changed, 191 insertions(+), 152 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index 8d5a18f..44c495c 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -633,15 +633,6 @@ CREATE TABLE `pmgr_customers` ( -- If NULL, rely on the contact info exclusively `name` VARCHAR(80) DEFAULT NULL, - -- A customer gets their own account, although any - -- lease specific charge (rent, late fees, etc) will - -- be debited against the lease account. This one - -- will be used for non-lease related charges, as - -- well as charges that intentionally span more than - -- one lease (such as one security deposit to cover - -- two or more units). - `account_id` INT(10) UNSIGNED NOT NULL, - -- Primary Contact... every customer must have one -- (and presumably, most customers will _be_ one). -- REVISIT 20090612: @@ -708,7 +699,6 @@ CREATE TABLE `pmgr_leases` ( `lease_type_id` INT(10) UNSIGNED NOT NULL, `unit_id` INT(10) UNSIGNED NOT NULL, `customer_id` INT(10) UNSIGNED NOT NULL, - `account_id` INT(10) UNSIGNED NOT NULL, `late_schedule_id` INT(10) UNSIGNED DEFAULT NULL, `lease_date` DATE NOT NULL, @@ -848,7 +838,7 @@ CREATE TABLE `pmgr_accounts` ( -- For LIABILITY, EQUITY, and INCOME, the opposite -- is true, with reconciliations posted, under -- normal circumstances, when a debit occurs. - `trackable` INT UNSIGNED DEFAULT 0, + `trackable` INT UNSIGNED DEFAULT 1, -- Security Level `level` INT UNSIGNED DEFAULT 1, @@ -869,15 +859,17 @@ INSERT INTO `pmgr_accounts` (`type`, `name`, `trackable`) ('ASSET', 'Invoice', 1), ('ASSET', 'Receipt', 1), ('LIABILITY', 'A/P', 1), - ('LIABILITY', 'Tax', 0), + ('LIABILITY', 'Tax', 1), ('LIABILITY', 'Customer Credit', 1), - ('ASSET', 'Bank', 0), - ('ASSET', 'Till', 0), + ('ASSET', 'Bank', 1), + ('ASSET', 'Cash', 1), + ('ASSET', 'Check', 1), + ('ASSET', 'Money Order', 1), ('LIABILITY', 'Security Deposit', 1), - ('INCOME', 'Rent', 0), - ('INCOME', 'Late Charge', 0), - ('EXPENSE', 'Concession', 0), - ('EXPENSE', 'Bad Debt', 0); + ('INCOME', 'Rent', 1), + ('INCOME', 'Late Charge', 1), + ('EXPENSE', 'Concession', 1), + ('EXPENSE', 'Bad Debt', 1); UNLOCK TABLES; @@ -942,6 +934,10 @@ DROP TABLE IF EXISTS `pmgr_transactions`; CREATE TABLE `pmgr_transactions` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, +-- `type` ENUM('INVOICE', +-- 'RECEIPT') +-- NOT NULL, + `stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `through_date` DATE DEFAULT NULL, `due_date` DATE DEFAULT NULL, diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index d50f0c9..427efbf 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -4,7 +4,7 @@ use DBI; use Data::Dumper; use File::Copy; -my $use_ir = 0; +my $use_ir = 1; # Internally adjust all numbers coming from the database to # be in inches. Not necessary to go to this detail, but the @@ -482,8 +482,10 @@ foreach $row (@$result) { } # For compatibility, while deciding on account names -$newdb{'lookup'}{'account'}{'Cash'} -= $newdb{'lookup'}{'account'}{'Till'}; +if (!defined $newdb{'lookup'}{'account'}{'Cash'}) { + $newdb{'lookup'}{'account'}{'Cash'} + = $newdb{'lookup'}{'account'}{'Till'}; +} $newdb{'lookup'}{'charge_type'} = {}; $newdb{'lookup'}{'charge_type'}{'Rent'} = @@ -510,9 +512,9 @@ $newdb{'lookup'}{'payment_type'} = {}; $newdb{'lookup'}{'payment_type'}{1} = { 'name' => 'Cash', 'account_name' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Cash'} }; $newdb{'lookup'}{'payment_type'}{2} -= { 'name' => 'Check', 'account_name' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Check'} }; += { 'name' => 'Check', 'account_name' => 'Check', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Check'} }; $newdb{'lookup'}{'payment_type'}{3} -= { 'name' => 'Money Order', 'account_name' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Money Order'} }; += { 'name' => 'Money Order', 'account_name' => 'Money Order', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Money Order'} }; $newdb{'lookup'}{'payment_type'}{4} = { 'name' => 'ACH', 'account_name' => 'Bank', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'ACH'} }; $newdb{'lookup'}{'payment_type'}{12} @@ -702,7 +704,7 @@ foreach $row (@{query($sdbh, $query)}) { addRow('customers', { 'name' => "$row->{'LastName'}, $row->{'FirstName'}", 'primary_contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'}, - 'account_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account_id'} }); + }); $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'} = $newdb{'tables'}{'customers'}{'autoid'}; @@ -832,7 +834,6 @@ foreach $row (@{query($sdbh, $query)}) { 'lease_type_id' => $newdb{'tables'}{'lease_types'}{'autoid'}, 'unit_id' => $newdb{'lookup'}{'unit'}{$row->{'UnitID'}}{'id'}, 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'}, - 'account_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'account_id'}, 'lease_date' => datefmt($row->{'DateIn'}), 'movein_date' => datefmt($row->{'DateIn'}), 'moveout_date' => datefmt($row->{'DateOut'}), @@ -1047,53 +1048,67 @@ foreach $row (@{query($sdbh, $query)}) = $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'}; } + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'} + = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_id'}; + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'} - = $newdb{'lookup'}{'account'}{$newdb{'lookup'}{'payment'}{ - $row->{'PaymentID'}}{'account_name'} + = $newdb{'lookup'}{'account'}{ + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'account_name'} }{'ledger_id'}; if ($use_ir) { addRow('ledger_entries', - { 'monetary_source_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}, + { #'monetary_source_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}, 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'}, - 'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Receipt'}{'ledger_id'}, + 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Receipt'}{'ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'}, 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, 'amount' => $row->{'PaymentAmount'}, - 'comment' => "Receipt: $row->{'ReceiptNum'}; Charge: $row->{'ChargeID'}; Payment: $row->{'PaymentID'}" }); - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} + 'comment' => "Receipt: $row->{'ReceiptNum'}; " }); + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'} = $newdb{'tables'}{'ledger_entries'}{'autoid'}; - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'} + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'} = $newdb{'lookup'}{'account'}{'Receipt'}{'ledger_id'}; } # Sitelink splits one physical payment into multiple "payments" to match each charge # This is kludgy, but for our cases at least, brings those pseudo-payments back into # a single one. It presumes that there is only one PaymentType per receipt. - if (!$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}) { + if (!$newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'}) { addRow('ledger_entries', { 'monetary_source_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}, 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, 'debit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'}, - 'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'}, 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, #'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, 'amount' => 0, - 'comment' => "Receipt: $row->{'ReceiptNum'}; " }); + 'comment' => "Receipt: $row->{'ReceiptNum'}; Charge: $row->{'ChargeID'}; Payment: $row->{'PaymentID'}" }); - $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'} + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} = $newdb{'tables'}{'ledger_entries'}{'autoid'}; } $newdb{'tables'}{'ledger_entries'}{'rows'}[ - $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'} + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} ]{'amount'} += $row->{'PaymentAmount'}; $newdb{'tables'}{'ledger_entries'}{'rows'}[ - $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'} + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} ]{'comment'} .= 'P:'.$row->{'PaymentID'} . '->C:' . $row->{'ChargeID'} . '; '; + if ($use_ir) { + # Reconcile the invoice account. Since this is from the perspective + # of the invoice, the entry crediting the charge is the debit, and + # the entry debiting A/R is the credit. + addRow('reconciliations', + { 'debit_ledger_entry_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}, + 'credit_ledger_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'}, + 'amount' => $row->{'PaymentAmount'}, + }); + } + # OK, now that the receipt is reconciled, update # payment to reference the true ledger_entry_id $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} @@ -1127,83 +1142,83 @@ my %fake = ('customer_id' => 4, 'ledger_id' => 4, 'invoice' => [ { 'id' => 1000, - 'date' => '2009-05-05', - 'entry' => [ { 'id' => 2100, - 'account_name' => 'Security Deposit', - 'amount' => 10, - 'tax' => 0 }, - ], - }, - { 'id' => 1001, - 'date' => '2009-05-01', - 'thru' => '2009-05-31', - 'entry' => [ { 'id' => 2110, - 'account_name' => 'Rent', - 'amount' => 100, - 'tax' => 5 }, - ], - }, - { 'id' => 1002, - 'date' => '2009-05-11', - 'entry' => [ { 'id' => 2120, - 'account_name' => 'Late Charge', - 'amount' => 25, - 'tax' => 0 }, - ], - }, - ], + 'date' => '2009-05-05', + 'entry' => [ { 'id' => 2100, + 'account_name' => 'Security Deposit', + 'amount' => 10, + 'tax' => 0 }, + ], + }, + { 'id' => 1001, + 'date' => '2009-05-01', + 'thru' => '2009-05-31', + 'entry' => [ { 'id' => 2110, + 'account_name' => 'Rent', + 'amount' => 100, + 'tax' => 5 }, + ], + }, + { 'id' => 1002, + 'date' => '2009-05-11', + 'entry' => [ { 'id' => 2120, + 'account_name' => 'Late Charge', + 'amount' => 25, + 'tax' => 0 }, + ], + }, + ], 'receipt' => [ { 'id' => 2000, - 'date' => '2009-05-15', - 'entry' => [ { 'id' => 2200, - 'track' => [ { 'debit'=>2100, 'amount'=>10 }, - { 'debit'=>2110, 'amount'=>5 } ], - 'type' => 1, - 'amount' => 15 }, - { 'id' => 2201, - 'track' => [ { 'debit'=>2110, 'amount'=>10 } ], - 'type' => 2, - 'amount' => 10 }, - { 'id' => 2202, - 'track' => [ { 'debit'=>2110, 'amount'=>5 } ], - 'type' => 3, - 'amount' => 5 }, - ], - }, - { 'id' => 2001, - 'date' => '2009-05-18', - 'entry' => [ { 'id' => 2210, - 'track' => [ { 'debit'=>2110, 'amount'=>30 } ], - 'type' => 5, - 'amount' => 30 }, - { 'id' => 2211, - 'track' => [ { 'debit'=>2110, 'amount'=>20 } ], - 'type' => 6, - 'amount' => 20 }, - ], - }, - { 'id' => 2002, - 'date' => '2009-05-22', - 'entry' => [ { 'id' => 2220, - 'track' => [ { 'debit'=>2110, 'amount'=>10 } ], - 'type' => 1, - 'amount' => 10 }, - { 'id' => 2221, - 'track' => [ { 'debit'=>2110, 'amount'=>5 } ], - 'type' => 2, - 'amount' => 5 }, - { 'id' => 2222, - 'track' => [ { 'debit'=>2110, 'amount'=>15 }, - { 'debit'=>2111, 'amount'=>5 }, - { 'debit'=>2120, 'amount'=>5 } ], - 'type' => 7, - 'amount' => 25 }, - { 'id' => 2223, - 'track' => [ { 'debit'=>2120, 'amount'=>20 } ], - 'type' => 8, - 'amount' => 30 }, - ], - }, - ], + 'date' => '2009-05-15', + 'entry' => [ { 'id' => 2200, + 'track' => [ { 'debit'=>2100, 'amount'=>10 }, + { 'debit'=>2110, 'amount'=>5 } ], + 'type' => 1, + 'amount' => 15 }, + { 'id' => 2201, + 'track' => [ { 'debit'=>2110, 'amount'=>10 } ], + 'type' => 2, + 'amount' => 10 }, + { 'id' => 2202, + 'track' => [ { 'debit'=>2110, 'amount'=>5 } ], + 'type' => 3, + 'amount' => 5 }, + ], + }, + { 'id' => 2001, + 'date' => '2009-05-18', + 'entry' => [ { 'id' => 2210, + 'track' => [ { 'debit'=>2110, 'amount'=>30 } ], + 'type' => 5, + 'amount' => 30 }, + { 'id' => 2211, + 'track' => [ { 'debit'=>2110, 'amount'=>20 } ], + 'type' => 6, + 'amount' => 20 }, + ], + }, + { 'id' => 2002, + 'date' => '2009-05-22', + 'entry' => [ { 'id' => 2220, + 'track' => [ { 'debit'=>2110, 'amount'=>10 } ], + 'type' => 1, + 'amount' => 10 }, + { 'id' => 2221, + 'track' => [ { 'debit'=>2110, 'amount'=>5 } ], + 'type' => 2, + 'amount' => 5 }, + { 'id' => 2222, + 'track' => [ { 'debit'=>2110, 'amount'=>15 }, + { 'debit'=>2111, 'amount'=>5 }, + { 'debit'=>2120, 'amount'=>5 } ], + 'type' => 7, + 'amount' => 25 }, + { 'id' => 2223, + 'track' => [ { 'debit'=>2120, 'amount'=>20 } ], + 'type' => 8, + 'amount' => 30 }, + ], + }, + ], ); @@ -1230,7 +1245,7 @@ sub fakeTesting { } addRow('transactions', - { 'stamp' => '2009-05-10' }); + { 'stamp' => '2009-04-30' }); addRow('ledger_entries', { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, @@ -1257,10 +1272,10 @@ sub fakeTesting { 1); foreach my $e (@{$tx->{'entry'}}) { - my $crdr = ($ir eq 'invoice') ? 'Invoice' : 'Receipt'; + my $ircrdr = ($ir eq 'invoice') ? 'Invoice' : 'Receipt'; my $dr = ($ir eq 'invoice') ? 'A/R' : 'Cash'; - $crdr = $dr; my $cr = ($ir eq 'invoice') ? $e->{'account_name'} : 'A/R'; + my $crdr; my $monetary_source_id; if (defined $e->{'type'}) { @@ -1274,29 +1289,41 @@ sub fakeTesting { $monetary_source_id = $newdb{'ids'}{'monetary_source'}{'internal'}; } + $crdr = $dr; + if ($use_ir) { + $crdr = $ircrdr; + addRow('ledger_entries', + { 'id' => $e->{'id'}+10000, + 'monetary_source_id' => ($ir eq 'invoice' ? undef : $monetary_source_id), + 'transaction_id' => $tx->{'id'}, + 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$dr}{'ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'}, + 'customer_id' => $fake{'customer_id'}, + #'lease_id' => $fake{'lease_id'}, + 'amount' => $e->{'amount'}, + 'comment' => "Fake $ir entry" }, + 1); + } + addRow('ledger_entries', { 'id' => $e->{'id'}, - 'monetary_source_id' => $monetary_source_id, + 'monetary_source_id' => ($ir eq 'invoice' ? $monetary_source_id : undef), 'transaction_id' => $tx->{'id'}, 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'}, 'credit_ledger_id' => $newdb{'lookup'}{'account'}{$cr}{'ledger_id'}, 'customer_id' => $fake{'customer_id'}, 'lease_id' => $fake{'lease_id'}, 'amount' => $e->{'amount'}, - 'comment' => "Fake $ir entry" }, + 'comment' => "Fake Entry" }, 1); -# addRow('ledger_entries', -# { 'id' => $e->{'id'}, -# 'monetary_source_id' => $monetary_source_id, -# 'transaction_id' => $tx->{'id'}, -# 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$dr}{'ledger_id'}, -# 'credit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'}, -# 'customer_id' => $fake{'customer_id'}, -# 'lease_id' => $fake{'lease_id'}, -# 'amount' => $e->{'amount'}, -# 'comment' => "Fake $ir entry" }, -# 1); + if ($use_ir) { + addRow('reconciliations', + { 'debit_ledger_entry_id' => $e->{'id'} + ($ir eq 'invoice' ? 10000 : 0), + 'credit_ledger_entry_id' => $e->{'id'} + ($ir eq 'invoice' ? 0 : 10000), + 'amount' => $e->{'amount'}, + }); + } foreach my $t (@{$e->{'track'}}) { addRow('reconciliations', @@ -1308,29 +1335,41 @@ sub fakeTesting { next unless $e->{'tax'}; + $crdr = $dr; + if ($use_ir) { + $crdr = $ircrdr; + addRow('ledger_entries', + { 'id' => $e->{'id'}+10001, + 'monetary_source_id' => ($ir eq 'invoice' ? undef : $monetary_source_id), + 'transaction_id' => $tx->{'id'}, + 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$dr}{'ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'}, + 'customer_id' => $fake{'customer_id'}, + #'lease_id' => $fake{'lease_id'}, + 'amount' => $e->{'tax'}, + 'comment' => "Fake Tax Invoice Entry" }, + 1); + } + addRow('ledger_entries', { 'id' => $e->{'id'}+1, - 'monetary_source_id' => $monetary_source_id, + 'monetary_source_id' => ($ir eq 'invoice' ? $monetary_source_id : undef), 'transaction_id' => $tx->{'id'}, 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'}, 'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Tax'}{'ledger_id'}, 'customer_id' => $fake{'customer_id'}, 'lease_id' => $fake{'lease_id'}, - 'amount' => $e->{'amount'}, - 'comment' => "Fake Tax" }, + 'amount' => $e->{'tax'}, + 'comment' => "Fake Tax Entry" }, 1); -# addRow('ledger_entries', -# { 'id' => $e->{'id'}+1, -# 'monetary_source_id' => $monetary_source_id, -# 'transaction_id' => $tx->{'id'}, -# 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$dr}{'ledger_id'}, -# 'credit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'}, -# 'customer_id' => $fake{'customer_id'}, -# 'lease_id' => $fake{'lease_id'}, -# 'amount' => $e->{'tax'}, -# 'comment' => "Fake Tax" }, -# 1); + if ($use_ir) { + addRow('reconciliations', + { 'debit_ledger_entry_id' => $e->{'id'} + ($ir eq 'invoice' ? 10001 : 1), + 'credit_ledger_entry_id' => $e->{'id'} + ($ir eq 'invoice' ? 1 : 10001), + 'amount' => $e->{'tax'}, + }); + } } } } diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index 8206707..07a4b1d 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -304,7 +304,7 @@ class LedgerEntriesController extends AppController { 'conditions' => array('LedgerEntry.id' => $id), )); - pr($entry); + //pr($entry); // Because 'DebitLedger' and 'CreditLedger' both relate to 'Account', // CakePHP will not include them in the LedgerEntry->find (or so it diff --git a/site/views/ledger_entries/view.ctp b/site/views/ledger_entries/view.ctp index e92adba..0851f25 100644 --- a/site/views/ledger_entries/view.ctp +++ b/site/views/ledger_entries/view.ctp @@ -81,12 +81,16 @@ echo $this->element('table', echo '
    ' . "\n"; $rows = array(); if ($debit_ledger['Account']['trackable']) { - $rows[] = array('Debit Amount Reconciled:', FormatHelper::currency($stats['debit_amount_reconciled'])); - $rows[] = array('Debit Amount Remaining:', FormatHelper::currency($stats['debit_amount_remaining'])); + $rows[] = array("Applied from {$debit_ledger['Account']['name']}:", + FormatHelper::currency($stats['debit_amount_reconciled'])); + $rows[] = array("{$debit_ledger['Account']['name']} Amount Remaining:", + FormatHelper::currency($stats['debit_amount_remaining'])); } if ($credit_ledger['Account']['trackable']) { - $rows[] = array('Credit Amount Reconciled:', FormatHelper::currency($stats['credit_amount_reconciled'])); - $rows[] = array('Credit Amount Remaining:', FormatHelper::currency($stats['credit_amount_remaining'])); + $rows[] = array("Applied to {$credit_ledger['Account']['name']}:", + FormatHelper::currency($stats['credit_amount_reconciled'])); + $rows[] = array("{$credit_ledger['Account']['name']} Amount Remaining:", + FormatHelper::currency($stats['credit_amount_remaining'])); } echo $this->element('table', array('class' => 'summary', @@ -113,7 +117,7 @@ echo '
    ' . "\n"; if ($debit_ledger['Account']['trackable']) { echo $this->element('ledger_entries', - array('caption' => "Payments Received", + array('caption' => "Applied to " . $debit_ledger['Account']['name'], 'grid_div_id' => 'debit_reconciliation_ledger_entries', 'account_ftype' => 'debit', 'reconcile_id' => $entry['id'], @@ -123,7 +127,7 @@ if ($debit_ledger['Account']['trackable']) { if ($credit_ledger['Account']['trackable']) { echo $this->element('ledger_entries', - array('caption' => "Charges Paid", + array('caption' => "Applied to " . $credit_ledger['Account']['name'], 'grid_div_id' => 'credit_reconciliation_ledger_entries', 'account_ftype' => 'credit', 'reconcile_id' => $entry['id'], From 0b69e065aedcba5b6d4c2c2fb3bf5efe41829032 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 30 Jun 2009 17:52:43 +0000 Subject: [PATCH 184/717] Major change to invoice/receipt algorithms. The end result shouldn't be visible, but there were significant problems understanding how to reconcile entries and this cleaned things up significantly. There may be some bugs left, but quick tests show it to be working git-svn-id: file:///svn-source/pmgr/branches/charge_credit_20090629@190 97e9348a-65ac-dc4b-aefc-98561f571b83 --- scripts/sitelink2pmgr.pl | 495 +++++++++++++++++++++++---------------- 1 file changed, 291 insertions(+), 204 deletions(-) diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 427efbf..a37d282 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -696,10 +696,6 @@ foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'} = $newdb{'tables'}{'contacts'}{'autoid'}; - $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account_id'} = - $newdb{'lookup'}{'account'}{'A/R'}{'account_id'}; - $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'ledger_id'} = - $newdb{'lookup'}{'account'}{'A/R'}{'ledger_id'}; addRow('customers', { 'name' => "$row->{'LastName'}, $row->{'FirstName'}", @@ -818,19 +814,15 @@ foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'ledger'} = {}; -$query = "SELECT L.*, A.TenantID FROM TenantLedger L LEFT JOIN `Access` A ON A.LedgerID = L.LedgerID WHERE L.UnitID <> 'POS\$' ORDER BY L.LedgerID"; +$query = "SELECT L.*, A.TenantID FROM TenantLedger L LEFT JOIN `Access` A ON A.LedgerID = L.LedgerID WHERE L.UnitID <> 'POS\$' ORDER BY L.DateIn"; foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}} = { 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'} }; - $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'account_id'} - = $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account_id'}; - $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger_id'} - = $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'ledger_id'}; - addRow('leases', - { 'number' => $row->{'LedgerID'}, + { #'number' => $newdb{'tables'}{'leases'}{'autoid'}+1, + 'number' => $row->{'LedgerID'}, 'lease_type_id' => $newdb{'tables'}{'lease_types'}{'autoid'}, 'unit_id' => $newdb{'lookup'}{'unit'}{$row->{'UnitID'}}{'id'}, 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'}, @@ -857,49 +849,78 @@ foreach $row (@{query($sdbh, $query)}) { ## ###################################################################### -## Charges +## Invoices $newdb{'lookup'}{'charge'} = {}; -$query = "SELECT * FROM Charges ORDER BY ChargeID"; +$query = "SELECT *, ChargeAmount+TaxAmount AS InvoiceAmount FROM Charges ORDER BY ChargeID"; foreach $row (@{query($sdbh, $query)}) { - my $credit_ledger_id; - my $ledger_entry_id; addRow('transactions', { 'stamp' => datefmt($row->{'ChargeDate'}), 'through_date' => datefmt($row->{'EndDate'}) }); $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}} - = { 'tx' => $newdb{'tables'}{'transactions'}{'autoid'}, - 'ledger_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger_id'}, - #'ledger_id' => $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}, - 'amount' => $row->{'ChargeAmount'}, - 'tax_amount' => $row->{'TaxAmount'}, - 'customer_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'customer_id'}, - 'lease_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease_id'}, - }; + = { 'invoice' => + { 'tx' => $newdb{'tables'}{'transactions'}{'autoid'}, + 'lease_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease_id'}, + 'customer_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'customer_id'}, + 'amount' => $row->{'InvoiceAmount'}, + } }; - $credit_ledger_id = $newdb{'lookup'}{'charge_type'}{$row->{'ChargeDescription'}}{'ledger_id'}; - if ($use_ir) { - addRow('ledger_entries', - { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, - 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}, - 'credit_ledger_id' => $credit_ledger_id, - 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, - 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, - 'amount' => $row->{'ChargeAmount'}, - 'comment' => "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}" }); - $ledger_entry_id = $newdb{'tables'}{'ledger_entries'}{'autoid'}; - $credit_ledger_id = $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}; - } + # Invoice must debit the A/R ledger... + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'debit_ledger_id'} + = $newdb{'lookup'}{'account'}{'A/R'}{'ledger_id'}; + # ...and credit the Invoice ledger. + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'credit_ledger_id'} + = $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}; + + # Create the invoice entry + # debit: A/R credit: Invoice + addRow('ledger_entries', + { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'tx'}, + 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'debit_ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'credit_ledger_id'}, + 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'customer_id'}, + 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'lease_id'}, + 'amount' => $row->{'InvoiceAmount'}, + 'comment' => "Invoice: Charge: $row->{'ChargeID'}" }); + + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'} + = $newdb{'tables'}{'ledger_entries'}{'autoid'}; +} + + +###################################################################### +## Charges + +$query = "SELECT * FROM Charges ORDER BY ChargeID"; +foreach $row (@{query($sdbh, $query)}) { + + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'} + = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'tx'}; + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'} + = $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'customer_id'}; + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'} + = $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease_id'}; + + # Charge must credit the invoice ledger... + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'credit_ledger_id'} + = $newdb{'lookup'}{'charge_type'}{$row->{'ChargeDescription'}}{'ledger_id'}; + + # ...and debit the A/R ledger. + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'debit_ledger_id'} + = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'credit_ledger_id'}; + + # Add the charge entry + # debit: Invoice credit: Rent/LateCharge/Etc addRow('ledger_entries', { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_id'}, - 'credit_ledger_id' => $credit_ledger_id, + 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'debit_ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'credit_ledger_id'}, 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, 'amount' => $row->{'ChargeAmount'}, @@ -908,57 +929,46 @@ foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'} = $newdb{'tables'}{'ledger_entries'}{'autoid'}; - if ($use_ir) { - # Reconcile the invoice account. Since this is from the perspective - # of the invoice, the entry crediting the charge is the debit, and - # the entry debiting A/R is the credit. - addRow('reconciliations', - { 'debit_ledger_entry_id' => $ledger_entry_id, - 'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'}, - 'amount' => $row->{'ChargeAmount'}, - }); - } + # Reconcile the Invoice account. Our two entries look like: + # debit: Invoice credit: Rent/LateCharge/Etc + # debit: A/R credit: Invoice + # Since this is from the perspective of the Invoice account, + # the credit entry is the Invoice<->A/R, and the debit + # entry is the actual charge ledger entry. + addRow('reconciliations', + { 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'}, + 'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'}, + 'amount' => $row->{'ChargeAmount'}, + }); next unless $row->{'TaxAmount'}; - $credit_ledger_id = $newdb{'lookup'}{'charge_type'}{'Tax'}{'ledger_id'}; - if ($use_ir) { - addRow('ledger_entries', - { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, - 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}, - 'credit_ledger_id' => $credit_ledger_id, - 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, - 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, - 'amount' => $row->{'TaxAmount'}, - 'comment' => undef }); - $ledger_entry_id = $newdb{'tables'}{'ledger_entries'}{'autoid'}; - $credit_ledger_id = $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}; - } - + # Add the tax charge entry + # debit: Invoice credit: Tax addRow('ledger_entries', { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_id'}, - 'credit_ledger_id' => $credit_ledger_id, + 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'debit_ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Tax'}{'ledger_id'}, 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, 'amount' => $row->{'TaxAmount'}, - 'comment' => undef }); + 'comment' => "Tax for ChargeID:$row->{'ChargeID'}" }); - $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tax_entry'} + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tax_ledger_entry_id'} = $newdb{'tables'}{'ledger_entries'}{'autoid'}; - if ($use_ir) { - # Reconcile the invoice account. Since this is from the perspective - # of the invoice, the entry crediting the charge is the debit, and - # the entry debiting A/R is the credit. - addRow('reconciliations', - { 'debit_ledger_entry_id' => $ledger_entry_id, - 'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tax_entry'}, - 'amount' => $row->{'TaxAmount'}, - }); - } + # Reconcile the Invoice account. Our two entries look like: + # debit: Invoice credit: Tax + # debit: A/R credit: Invoice + # Since this is from the perspective of the Invoice account, + # the credit entry is the Invoice<->A/R, and the debit + # entry is the actual tax ledger entry. + addRow('reconciliations', + { 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tax_ledger_entry_id'}, + 'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'}, + 'amount' => $row->{'TaxAmount'}, + }); } @@ -967,42 +977,168 @@ foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'receipt'} = {}; -$query = - "SELECT R.ReceiptNum, C.LedgerID, R.ReceiptDate" . - " FROM Receipts R, Payments P, Charges C" . - " WHERE P.ReceiptNum = R.ReceiptNum" . - " AND C.ChargeID = P.ChargeID" . - " GROUP BY R.ReceiptNum, C.LedgerID, R.ReceiptDate" . - " ORDER BY R.ReceiptNum"; -foreach $row (@{query($sdbh, $query)}) { +############################################################ +############################################################ +############################################################ +# REVISIT 20090630 +# Handling of receipts is all backwards. The way things +# _should_ look if someone provides Cash and Check to pay +# rent & tax for two units (50 on UnitA and 40 UnitB): +# +# RENT TAX INVOICE A/R RECEIPT CASH CHECK +# ------- ------- ------- ------- ------- ------- ------- +# |50 | 50| | | | | +# | | 5 5| | | | | +# | | |55 55| | | | +# |40 | 40| | | | | +# | | 4 4| | | | | +# | | |44 44| | | | +# | | | | |79 | 79| +# | | | | |20 20| | +# | | | |99 99| | | +# | | | | | | | +# +# HOWEVER, +# Our current implementation MUST match LedgerEntry to +# LedgerEntry for reconcile purposes. Thus, although there +# is a way to reconcile that $50 was received, there is no +# way to flag the payment as being for UnitA, unless we +# either rely on the charge to determine the fact (a +# solution that has proven very messy), or we add it to +# the reconciliations table. The hope, for simplicity's +# sake, was to ensure there was a single ledger entry in +# A/R for each payment that could correspond to a lease/unit, +# so that no A/R ledger entry ever represented payment for +# more than one lease. However, to do so, our ledgers +# appear like this instead: +# +# RENT TAX INVOICE A/R RECEIPT CASH CHECK +# ------- ------- ------- ------- ------- ------- ------- +# |50 | 50| | | | | +# | | 5 5| | | | | +# | | |55 55| | | | +# |40 | 40| | | | | +# | | 4 4| | | | | +# | | |44 44| | | | +# | | | | |79 | 79| +# | | | | |20 20| | +# | | | |50 50| | | +# | | | | 5 5| | | +# | | | |40 40| | | +# | | | | 4 4| | | +# | | | | | | | +# +# There is another possible solution, although it is +# very probably ledger overkill (even invoice/receipt +# already fall into the overkill category). +# +# RENT TAX INVOICE A/R MERGE RECEIPT CASH CHECK +# ------- ------- ------- ------- ------- ------- ------- ------- +# |50 | 50| | | | | | +# | | 5 5| | | | | | +# | | |55 55| | | | | +# |40 | 40| | | | | | +# | | 4 4| | | | | | +# | | |44 44| | | | | +# | | | | | |79 | 79| +# | | | | | |20 20| | +# | | | | |50 50| | | +# | | | | | 5 5| | | +# | | | | |40 40| | | +# | | | | | 4 4| | | +# | | | |99 99| | | | +# | | | | | | | | +# +# I might opt for this last option, but ultimately, none +# of these are really correct. We need a better solution. +# Until then, I'll go with the easiest. - if ($newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}) { - die unless ($newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'customer_id'} - == $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'customer_id'}); - push(@{$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'ledgers'}}, - $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger_id'}); - #print Dumper $receipt_map{$row->{'ReceiptNum'}}; - next; +############################################################ +############################################################ +############################################################ + +# Sitelink splits one physical payment into multiple "payments" to match each charge. +# The solution here is kludgy, but for our cases at least, it brings those pseudo-payments +# back into a single one. This presumes there is only one PaymentType per receipt. +$query = + "SELECT R.ReceiptNum, R.ReceiptDate, P.PaymentType, P.CheckNum, SUM(P.PaymentAmount) AS ReceiptAmount" . + " FROM Receipts R, Payments P" . + " WHERE P.ReceiptNum = R.ReceiptNum" . + " GROUP BY R.ReceiptNum, R.ReceiptDate, P.PaymentType, P.CheckNum" . + " ORDER BY R.ReceiptNum, P.PaymentType"; +foreach $row (@{query($sdbh, $query)}) { + +# if ($newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}) { +# next; +# } + + if (!$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}) { + addRow('transactions', + { 'stamp' => datefmt($row->{'ReceiptDate'}), + 'through_date' => undef }); + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}} + = {'tx' => $newdb{'tables'}{'transactions'}{'autoid'} }; + } + + if ($row->{'ReceiptDate'} =~ m%3/25/2009%) { + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'} + = $newdb{'ids'}{'monetary_source'}{'Closing'}; + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'account_name'} + = 'Bank'; + } + else { + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'} + = $newdb{'ids'}{'monetary_source'}{ + $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'} + }; + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'account_name'} + = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'account_name'}; } - addRow('transactions', - { 'stamp' => datefmt($row->{'ReceiptDate'}), - 'through_date' => undef }); + # Set up a monetary source for the receipt, + if (!$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}) { + my $name = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'}; + if ($name eq 'Check') { + $name = 'Check #' . $row->{'CheckNum'}; + } + addRow('monetary_sources', + { 'monetary_type_id' => $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'monetary_type'}{'id'}, + 'name' => $name, + 'comment' => "Receipt:$row->{'ReceiptNum'}; Payment:$row->{'PaymentType'}; Check:$row->{'CheckNum'}" }); - $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}} - = {'tx' => $newdb{'tables'}{'transactions'}{'autoid'}, - # NOTE: Use of 'lease_id' would be invalid, since the - # receipt could be for multiple leases. 'customer_id' - # could be OK, but better to avoid this issue all - # together by excluding them both from this lookup. - 'ledgers' => [ $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger_id'} ] }; + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'} + = $newdb{'tables'}{'monetary_sources'}{'autoid'}; + } + + # Receipt must debit the "money" asset (bank, cash, check, etc)... + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'debit_ledger_id'} + = $newdb{'lookup'}{'account'}{ + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'account_name'} + }{'ledger_id'}; + + # ...and credit the Receipt ledger + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'credit_ledger_id'} + = $newdb{'lookup'}{'account'}{'Receipt'}{'ledger_id'}; + + # NOTE THE ABOVE LARGE COMMENT BLOCK + # The choice of credit/debit ledgers does not mirror the + # choices for invoice. This _should_ be A/R to Receipt, + # but it is Money to Receipt instead. + # debit: Cash/Check/Etc credit: Receipt + addRow('ledger_entries', + { 'monetary_source_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}, + 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, + 'debit_ledger_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'debit_ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'credit_ledger_id'}, + 'amount' => $row->{'ReceiptAmount'}, + 'comment' => "Receipt: $row->{'ReceiptNum'}; " }); + + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'} + = $newdb{'tables'}{'ledger_entries'}{'autoid'}; } -# sub idkeys { [ sort( {$a <=> $b} keys(%{$_[0]})) ] } -# $Data::Dumper::Sortkeys = \&idkeys; - ###################################################################### ## Payments @@ -1014,117 +1150,68 @@ foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}} = {}; - if ($row->{'PaymentDate'} =~ m%3/25/2009%) { - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'} - = $newdb{'ids'}{'monetary_source'}{'Closing'}; - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'account_name'} - = 'Bank'; - } - else { - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'} - = $newdb{'ids'}{'monetary_source'}{ - $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'} - }; - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'account_name'} - = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'account_name'}; - } + # NOTE THE ABOVE LARGE COMMENT BLOCK + # The choice of credit/debit ledgers does not mirror the + # choices for charges. This _should_ be Money to Receipt, + # but it is A/R to Receipt instead. - if (!$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}) { - if (!defined $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'}) { - my $name; - $name = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'}; - if ($name eq 'Check') { - $name = 'Check #' . $row->{'CheckNum'}; - } - addRow('monetary_sources', - { 'monetary_type_id' => $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'monetary_type'}{'id'}, - 'name' => $name, - 'comment' => "Payment: $row->{'PaymentID'}; Type: $row->{'PaymentType'}; Check: $row->{'CheckNum'}; $row->{'Memo'}" }); - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'} - = $newdb{'tables'}{'monetary_sources'}{'autoid'}; - } - - $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'} - = $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'}; - } - - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'} - = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_id'}; - - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'} - = $newdb{'lookup'}{'account'}{ - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'account_name'} - }{'ledger_id'}; - - if ($use_ir) { - addRow('ledger_entries', - { #'monetary_source_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}, - 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Receipt'}{'ledger_id'}, - 'credit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'}, - 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, - 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, - 'amount' => $row->{'PaymentAmount'}, - 'comment' => "Receipt: $row->{'ReceiptNum'}; " }); + # Ensure Receipt has the right customer + $newdb{'tables'}{'ledger_entries'}{'rows'}[ $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'} - = $newdb{'tables'}{'ledger_entries'}{'autoid'}; - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'} - = $newdb{'lookup'}{'account'}{'Receipt'}{'ledger_id'}; - } + ]{'customer_id'} = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}; - # Sitelink splits one physical payment into multiple "payments" to match each charge - # This is kludgy, but for our cases at least, brings those pseudo-payments back into - # a single one. It presumes that there is only one PaymentType per receipt. - if (!$newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'}) { - addRow('ledger_entries', - { 'monetary_source_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}, - 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'}, - 'credit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'}, - 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, - #'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, - 'amount' => 0, - 'comment' => "Receipt: $row->{'ReceiptNum'}; Charge: $row->{'ChargeID'}; Payment: $row->{'PaymentID'}" }); + # Payment must debit the associated receipt ledger (which should be Receipt)... + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'} + = $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'credit_ledger_id'}; - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} - = $newdb{'tables'}{'ledger_entries'}{'autoid'}; - } + # ...and credit the A/R ledger. + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'} + = $newdb{'lookup'}{'account'}{'A/R'}{'ledger_id'}; - $newdb{'tables'}{'ledger_entries'}{'rows'}[ - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} - ]{'amount'} += $row->{'PaymentAmount'}; + # Add the payment entry + # debit: Receipt credit: A/R + addRow('ledger_entries', + { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, + 'debit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'}, + 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, + 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, + 'amount' => $row->{'PaymentAmount'}, + 'comment' => "Receipt: $row->{'ReceiptNum'}; Charge: $row->{'ChargeID'}; Payment: $row->{'PaymentID'}" }); - $newdb{'tables'}{'ledger_entries'}{'rows'}[ - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} - ]{'comment'} .= 'P:'.$row->{'PaymentID'} . '->C:' . $row->{'ChargeID'} . '; '; + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} + = $newdb{'tables'}{'ledger_entries'}{'autoid'}; - if ($use_ir) { - # Reconcile the invoice account. Since this is from the perspective - # of the invoice, the entry crediting the charge is the debit, and - # the entry debiting A/R is the credit. - addRow('reconciliations', - { 'debit_ledger_entry_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}, - 'credit_ledger_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'}, - 'amount' => $row->{'PaymentAmount'}, - }); - } + # Reconcile the Receipt account. Our two entries look like: + # debit: Cash/Check/Etc credit: Receipt + # debit: Receipt credit: A/R + # Since this is from the perspective of the Receipt account, + # the debit entry is the Receipt<->A/R, and the credit + # entry is the actual receipt ledger entry. + addRow('reconciliations', + { 'debit_ledger_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'}, + 'credit_ledger_entry_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}, + 'amount' => $row->{'PaymentAmount'}, + }); - # OK, now that the receipt is reconciled, update - # payment to reference the true ledger_entry_id - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} - = $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}; # Figure out how much of the charge can be reconciled - my $reconcile_amount = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'amount'}; + my $reconcile_amount = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'amount'}; + #print STDERR Dumper($newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}); exit; $reconcile_amount = $row->{'PaymentAmount'} if $row->{'PaymentAmount'} <= $reconcile_amount; - # Reconcile the A/R account. Since this is from the perspective - # of the A/R, charge is the debit, and payment is the credit + # Reconcile the A/R account. Our two entries look like: + # debit: Receipt credit: A/R + # debit: A/R credit: Invoice + # Since this is from the perspective of the A/R account, + # the debit entry is the Invoice<->A/R, and the credit + # entry is the Receipt<->A/R. addRow('reconciliations', - { 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'}, - 'credit_ledger_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'}, - 'amount' => $reconcile_amount, - }); + { 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'}, + 'credit_ledger_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'}, + 'amount' => $reconcile_amount, + }); # Update the transaction to use the memo from this payment if ($row->{'Memo'}) { From c1aedde374a29652ea2567abcd5e488a7aa7fcf9 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 30 Jun 2009 17:54:54 +0000 Subject: [PATCH 185/717] I quickly bailed on regressing back to charge/payment, as I don't see it solving the fundamental issues I'm having. In fact, I've decided to push forward with Invoice/Credit accounts, something I'm not fond of, but that at least was working. This checking is just a branch rename to reflect that fact. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@191 97e9348a-65ac-dc4b-aefc-98561f571b83 From 2b2991a13a133fbf15a0da29524e53fe0d262342 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 30 Jun 2009 17:56:32 +0000 Subject: [PATCH 186/717] Since Lease.number is a VARCHAR, it doesn't sort well. So I added a hidden column for Lease.id, which sorts better. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@192 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/leases.ctp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/site/views/elements/leases.ctp b/site/views/elements/leases.ctp index 2315f99..d5a9b34 100644 --- a/site/views/elements/leases.ctp +++ b/site/views/elements/leases.ctp @@ -2,6 +2,7 @@ // Define the table columns $cols = array(); +$cols['LeaseID'] = array('index' => 'Lease.id', 'hidden' => true); $cols['Lease'] = array('index' => 'Lease.number', 'formatter' => 'id'); $cols['Unit'] = array('index' => 'Unit.name', 'width' => '50', 'align' => 'center'); $cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'longname'); @@ -26,4 +27,5 @@ else { $jqGrid_options += array('search_fields' => array('Customer', 'Unit')); } +$jqGrid_options['sort_column'] = 'LeaseID'; echo $this->element('jqGrid', $jqGrid_options); From 0558c35ebcb2675b49898d082eccc8e5794dcbbb Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 30 Jun 2009 18:09:17 +0000 Subject: [PATCH 187/717] Merge in some desired changes from the statements_20090623 branch git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@193 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_model.php | 18 ++++++++++++++++++ site/models/account.php | 25 +++++++------------------ 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/site/app_model.php b/site/app_model.php index 9526295..14fff2d 100644 --- a/site/app_model.php +++ b/site/app_model.php @@ -78,6 +78,24 @@ class AppModel extends Model { + /************************************************************************** + ************************************************************************** + ************************************************************************** + * 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; + $item = current($item); + return $item['id']; + } + + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/models/account.php b/site/models/account.php index bded9e5..05c5a39 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -82,26 +82,15 @@ class Account extends AppModel { /************************************************************************** ************************************************************************** ************************************************************************** - * function: accountNameToID - * - Returns the ID of the named account + * function: Account IDs + * - Returns the ID of the desired account */ - function accountNameToID($name) { - $this->cacheQueries = true; - $account = $this->find('first', array - ('recursive' => -1, - 'conditions' => compact('name'), - )); - $this->cacheQueries = false; - return $account['Account']['id']; - } - function securityDepositAccountID() { return $this->accountNameToID('Security Deposit'); } - function rentAccountID() { return $this->accountNameToID('Rent'); } - function accountReceivableAccountID() { return $this->accountNameToID('A/R'); } - function invoiceAccountID() { return $this->accountReceivableAccountID(); } - function receiptAccountID() { return $this->accountReceivableAccountID(); } - //function invoiceAccountID() { return $this->accountNameToID('Invoice'); } - //function receiptAccountID() { return $this->accountNameToID('Receipt'); } + function securityDepositAccountID() { return $this->nameToID('Security Deposit'); } + function rentAccountID() { return $this->nameToID('Rent'); } + function accountReceivableAccountID() { return $this->nameToID('A/R'); } + function invoiceAccountID() { return $this->nameToID('Invoice'); } + function receiptAccountID() { return $this->nameToID('Receipt'); } /************************************************************************** From 707c9a87effbbb92441e1248c32c9d99a5b441e3 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 30 Jun 2009 18:11:40 +0000 Subject: [PATCH 188/717] Merge in the bug fixes made to Linkable, as well as the better logging mechanism. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@194 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/behaviors/linkable.php | 255 ++++++++++++++++++----------- 1 file changed, 162 insertions(+), 93 deletions(-) diff --git a/site/models/behaviors/linkable.php b/site/models/behaviors/linkable.php index 73f3f19..529b407 100644 --- a/site/models/behaviors/linkable.php +++ b/site/models/behaviors/linkable.php @@ -85,6 +85,28 @@ class LinkableBehavior extends ModelBehavior { protected $_defaults = array('type' => 'LEFT'); + function pr($lev, $mixed) { + if ($lev >= 5) + return; + + pr($mixed); + return; + + $trace = debug_backtrace(false); + //array_shift($trace); + $calls = array(); + foreach ($trace AS $call) { + $call = array_intersect_key($call, + array('file'=>1, + 'line'=>1, + //'class'=>1, + 'function'=>1, + )); + $calls[] = implode("; ", $call); + } + pr(array('debug' => $mixed, 'stack' => $calls)); + } + /* * This is a function for made recursive str_replaces in an array * NOTE: The palacement of this function is terrible, but I don't @@ -108,7 +130,10 @@ class LinkableBehavior extends ModelBehavior { } public function beforeFind(&$Model, $query) { -/* pr("Linkable::beforeFind() begin"); pr($query); */ + $this->pr(10, + array('function' => 'Linkable::beforeFind', + 'args' => array('Model->alias' => '$Model->alias') + compact('query'), + )); if (isset($query[$this->_key])) { $optionsDefaults = $this->_defaults + array('reference' => array('class' => $Model->alias, @@ -132,7 +157,10 @@ class LinkableBehavior extends ModelBehavior { unset($iterator['defaults']); } $iterations = Set::normalize($iterator); -/* pr(array('checkpoint' => 'Iterations', compact('iterations'))); */ + $this->pr(25, + array('checkpoint' => 'Iterations', + compact('iterations'), + )); foreach ($iterations as $alias => $options) { if (is_null($options)) { $options = array(); @@ -145,7 +173,15 @@ class LinkableBehavior extends ModelBehavior { if (empty($options['class'])) $options['class'] = $alias; -/* pr(array('checkpoint' => 'Begin Model Work', compact('alias', 'options'))); */ + if (!isset($options['conditions'])) + $options['conditions'] = array(); + elseif (!is_array($options['conditions'])) + $options['conditions'] = array($options['conditions']); + + $this->pr(20, + array('checkpoint' => 'Begin Model Work', + compact('alias', 'options'), + )); $modelClass = $options['class']; $modelAlias = $options['alias']; @@ -154,11 +190,13 @@ class LinkableBehavior extends ModelBehavior { $_Model =& ClassRegistry::init($modelClass); // the incoming model to be linked in query $Reference =& ClassRegistry::init($referenceClass); // the already in query model that links to $_Model -/* pr(array('checkpoint' => 'Aliases Established', */ -/* 'Model' => ($modelAlias .' : '. $modelClass . */ -/* ' ('. $_Model->alias .' : '. $_Model->name .')'), */ -/* 'Reference' => ($referenceAlias .' : '. $referenceClass . */ -/* ' ('. $Reference->alias .' : '. $Reference->name .')'))); */ + $this->pr(12, + array('checkpoint' => 'Aliases Established', + 'Model' => ($modelAlias .' : '. $modelClass . + ' ('. $_Model->alias .' : '. $_Model->name .')'), + 'Reference' => ($referenceAlias .' : '. $referenceClass . + ' ('. $Reference->alias .' : '. $Reference->name .')'), + )); $db =& $_Model->getDataSource(); @@ -169,20 +207,20 @@ class LinkableBehavior extends ModelBehavior { // a relationship if one doesn't otherwise already exists. if (($associations = $Reference->getAssociated()) && isset($associations[$_Model->alias])) { -/* pr("Reference defines association to _Model"); */ + $this->pr(12, array('checkpoint' => "Reference defines association to _Model")); $associatedThroughReference = 1; $type = $associations[$_Model->alias]; $association = $Reference->{$type}[$_Model->alias]; } elseif (($associations = $_Model->getAssociated()) && isset($associations[$Reference->alias])) { -/* pr("_Model defines association to Reference"); */ + $this->pr(12, array('checkpoint' => "_Model defines association to Reference")); $type = $associations[$Reference->alias]; $association = $_Model->{$type}[$Reference->alias]; } else { // No relationship... make our best effort to create one. -/* pr("No assocation between _Model and Reference"); */ + $this->pr(12, array('checkpoint' => "No assocation between _Model and Reference")); $type = 'belongsTo'; $_Model->bind($Reference->alias); // Grab the association now, since we'll unbind in a moment. @@ -212,93 +250,119 @@ class LinkableBehavior extends ModelBehavior { $associationAlias, $association['conditions']); -/* pr(array('checkpoint' => 'Models Established - Check Associations', */ -/* 'primaryModel' => $primaryAlias .' : '. $primaryModel->name, */ -/* 'foreignModel' => $foreignAlias .' : '. $foreignModel->name, */ -/* compact('type', 'association'))); */ + $this->pr(15, + array('checkpoint' => 'Models Established - Check Associations', + 'primaryModel' => $primaryAlias .' : '. $primaryModel->name, + 'foreignModel' => $foreignAlias .' : '. $foreignModel->name, + compact('type', 'association'), + )); - if (empty($options['conditions'])) { - if ($type === 'hasAndBelongsToMany') { - if (isset($association['with'])) - $linkClass = $association['with']; - else - $linkClass = Inflector::classify($association['joinTable']); + if ($type === 'hasAndBelongsToMany') { + if (isset($association['with'])) + $linkClass = $association['with']; + else + $linkClass = Inflector::classify($association['joinTable']); - $Link =& $_Model->{$linkClass}; + $Link =& $_Model->{$linkClass}; - if (isset($options['linkalias'])) - $linkAlias = $options['linkalias']; - else - $linkAlias = $Link->alias; + if (isset($options['linkalias'])) + $linkAlias = $options['linkalias']; + else + $linkAlias = $Link->alias; - // 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['foreignKey'], $linkAlias); - $referenceLink = $Link->escapeField($association['associationForeignKey'], $linkAlias); + $this->pr(17, + array('checkpoint' => 'Linking HABTM', + compact('linkClass', '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); + // 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['foreignKey'], $linkAlias); + $referenceLink = $Link->escapeField($association['associationForeignKey'], $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); + // 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); - // Get the primary key from the tables we're joining. - $referenceKey = $Reference->escapeField(null, $referenceAlias); - $modelKey = $_Model->escapeField(null, $modelAlias); + // 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); - // 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); - - // 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 { - // No Foreign Key... nothing we can do. - $options['conditions'] = array(); - } - - // The user may have specified conditions directly in the model - // for this join. Make sure to adhere to those conditions. - if (isset($association['conditions']) && is_array($association['conditions'])) - $options['conditions'] = array_merge($options['conditions'], $association['conditions']); - elseif (!empty($association['conditions'])) - $options['conditions'][] = $association['conditions']; + // 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'], + 'association[conditions]' => $association['conditions'], + ), + )); + + // The user may have specified conditions directly in the model + // for this join. Make sure to adhere to those conditions. + if (isset($association['conditions']) && is_array($association['conditions'])) + $options['conditions'] = array_merge($options['conditions'], $association['conditions']); + elseif (!empty($association['conditions'])) + $options['conditions'][] = $association['conditions']; + + $this->pr(19, + array('checkpoint' => 'Conditions2', + array('options[conditions]' => $options['conditions'], + ), + )); + if (empty($options['table'])) { $options['table'] = $db->fullTableName($_Model, true); } @@ -312,26 +376,31 @@ class LinkableBehavior extends ModelBehavior { (empty($association['fields']) ? array() : $db->fields($_Model, $modelAlias, $association['fields']))); -/* pr(array('checkpoint' => 'Model Work Complete', compact('options', 'modelClass', 'modelAlias'))); */ - $options[$this->_key] = am($options[$this->_key], array_diff_key($options, $optionsKeys)); $options = array_intersect_key($options, $optionsKeys); if (!empty($options[$this->_key])) { $iterators[] = $options[$this->_key] + array('defaults' => - array_merge($defaults, + array_merge($defaults, array('reference' => array('class' => $modelClass, 'alias' => $modelAlias)))); } $query['joins'][] = array_intersect_key($options, array('type' => true, 'alias' => true, 'table' => true, 'joins' => true, 'conditions' => true)); + + $this->pr(19, + array('checkpoint' => 'Model Join Complete', + compact('options', 'modelClass', 'modelAlias', 'query'), + )); } ++$cont; $notDone = isset($iterators[$cont]); } while ($notDone); } -/* pr(array('checkpoint' => 'Linkable::beforeFind() end', */ -/* compact('query'))); */ + $this->pr(20, + array('function' => 'Linkable::beforeFind', + 'return' => compact('query'), + )); return $query; } } \ No newline at end of file From 44df78e69f53a376e9614c74cfc1d7acd8c9cf80 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 1 Jul 2009 08:17:31 +0000 Subject: [PATCH 189/717] Finally, finally... a working version for payment entry. The current schema is working well, and seems to handle our technical needs. However, it does seem to be very confusing with the extra accounts. Nonetheless, it does work and so I'll keep going down this path. This checkin also includes a mechanism to close the books on an account (by closing the underlying ledger) and start a new ledger. One of the decisions worth revisiting is separating out ledger entries that are really part of the same transaction. Without this change, inspecting a transaction results in the transaction total being off by a factor of two, since all money movement is in their twice (once for the expected reason, and again to hit the invoice/receipt ledger). git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@195 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 14 +- scripts/sitelink2pmgr.pl | 34 +- site/app_model.php | 11 +- site/controllers/accounts_controller.php | 25 ++ site/controllers/transactions_controller.php | 342 ++++++++++--------- site/models/account.php | 47 ++- site/models/ledger.php | 66 ++++ site/models/ledger_entry.php | 10 + site/models/reconciliation.php | 15 + site/models/transaction.php | 8 +- site/views/accounts/view.ctp | 2 +- site/views/customers/payment.ctp | 51 +-- site/views/elements/accounts.ctp | 4 +- site/views/elements/jqGrid.ctp | 4 +- site/views/elements/ledger_entries.ctp | 16 +- site/views/elements/ledgers.ctp | 7 +- site/views/ledger_entries/view.ctp | 2 - site/views/monetary_sources/view.ctp | 4 + 18 files changed, 455 insertions(+), 207 deletions(-) create mode 100644 site/models/reconciliation.php diff --git a/db/schema.sql b/db/schema.sql index 44c495c..ad6daa4 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -1007,8 +1007,20 @@ CREATE TABLE `pmgr_monetary_sources` ( -- REVISIT : 20090605 -- Check Number; -- Routing Number, Account Number; - -- Card Number, Expiration Date; CCV2 Code + -- Card Number, Expiration Date; CVV2 Code -- etc. + -- REVISIT 20090630 + -- I _think_ that CVV2 is NEVER supposed to + -- be stored ANYWHERE. Merchants agree to + -- use it only to verify the transaction and + -- then leave no record of it, so that even + -- if their security is compromised, no one + -- will know the CVV2 code unless they are + -- in physical possession of the card. + `data1` VARCHAR(80) DEFAULT NULL, + `data2` VARCHAR(80) DEFAULT NULL, + `data3` VARCHAR(80) DEFAULT NULL, + `data4` VARCHAR(80) DEFAULT NULL, `comment` VARCHAR(255) DEFAULT NULL, diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index a37d282..d91667c 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -868,6 +868,13 @@ foreach $row (@{query($sdbh, $query)}) { 'amount' => $row->{'InvoiceAmount'}, } }; + addRow('transactions', + { 'stamp' => datefmt($row->{'ChargeDate'}), + 'through_date' => datefmt($row->{'EndDate'}) }); + + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'charge_tx'} + = $newdb{'tables'}{'transactions'}{'autoid'}; + # Invoice must debit the A/R ledger... $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'debit_ledger_id'} = $newdb{'lookup'}{'account'}{'A/R'}{'ledger_id'}; @@ -900,7 +907,7 @@ $query = "SELECT * FROM Charges ORDER BY ChargeID"; foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'} - = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'tx'}; + = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'charge_tx'}; $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'} = $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'customer_id'}; $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'} @@ -1077,7 +1084,15 @@ foreach $row (@{query($sdbh, $query)}) { { 'stamp' => datefmt($row->{'ReceiptDate'}), 'through_date' => undef }); $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}} - = {'tx' => $newdb{'tables'}{'transactions'}{'autoid'} }; + = {'tx' => $newdb{'tables'}{'transactions'}{'autoid'}, + 'date' => datefmt($row->{'ReceiptDate'}), + }; + + addRow('transactions', + { 'stamp' => datefmt($row->{'ReceiptDate'}), + 'through_date' => undef }); + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'payment_tx'} + = $newdb{'tables'}{'transactions'}{'autoid'}; } if ($row->{'ReceiptDate'} =~ m%3/25/2009%) { @@ -1098,12 +1113,15 @@ foreach $row (@{query($sdbh, $query)}) { # Set up a monetary source for the receipt, if (!$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}) { my $name = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'}; + my $data1; if ($name eq 'Check') { $name = 'Check #' . $row->{'CheckNum'}; + $data1 = $row->{'CheckNum'}; } addRow('monetary_sources', { 'monetary_type_id' => $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'monetary_type'}{'id'}, 'name' => $name, + 'data1' => $data1, 'comment' => "Receipt:$row->{'ReceiptNum'}; Payment:$row->{'PaymentType'}; Check:$row->{'CheckNum'}" }); $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'} @@ -1148,7 +1166,15 @@ $newdb{'lookup'}{'payment'} = {}; $query = "SELECT * FROM Payments ORDER BY PaymentID"; foreach $row (@{query($sdbh, $query)}) { - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}} = {}; +# addRow('transactions', +# { 'stamp' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'date'}, +# 'through_date' => undef }); +# $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}} +# = {'tx' => $newdb{'tables'}{'transactions'}{'autoid'} }; + + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}} + = { 'tx' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'payment_tx'} }; + # NOTE THE ABOVE LARGE COMMENT BLOCK # The choice of credit/debit ledgers does not mirror the @@ -1172,7 +1198,7 @@ foreach $row (@{query($sdbh, $query)}) # debit: Receipt credit: A/R addRow('ledger_entries', { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, - 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, + 'transaction_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'tx'}, 'debit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'}, 'credit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'}, 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, diff --git a/site/app_model.php b/site/app_model.php index 14fff2d..f2f0197 100644 --- a/site/app_model.php +++ b/site/app_model.php @@ -137,7 +137,16 @@ class AppModel extends Model { */ function dateFormatBeforeSave($dateString) { - return date('Y-m-d', strtotime($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)); } } diff --git a/site/controllers/accounts_controller.php b/site/controllers/accounts_controller.php index c35989a..d957f10 100644 --- a/site/controllers/accounts_controller.php +++ b/site/controllers/accounts_controller.php @@ -119,6 +119,25 @@ class AccountsController extends AppController { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: newledger + * - Close the current account ledger and create a new one, + * carrying forward any balance if necessary. + */ + + function newledger($id = null) { + if (!$this->Account->closeCurrentLedger($id)) { + $this->Session->setFlash(__('Unable to create new Ledger.', true)); + } + if ($id) + $this->redirect(array('action'=>'view', $id)); + else + $this->redirect(array('action'=>'index')); + } + + /************************************************************************** ************************************************************************** ************************************************************************** @@ -160,8 +179,14 @@ class AccountsController extends AppController { $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)); + // Prepare to render $title = 'Account: ' . $account['Account']['name']; $this->set(compact('account', 'title', 'stats')); } + } diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php index e4a3f1f..8f182cf 100644 --- a/site/controllers/transactions_controller.php +++ b/site/controllers/transactions_controller.php @@ -103,186 +103,204 @@ class TransactionsController extends AppController { */ function postReceipt() { - $this->autoRender = false; - if (!$this->RequestHandler->isPost()) { echo('

    THIS IS NOT A POST FOR SOME REASON

    '); return; } - //pr(array('thisdata' => $this->data)); - if (isset($this->data['customer_id'])) { - $C = new Customer(); - $C->recursive = -1; - $customer = $C->find - ('first', - array('contain' => array('Account.CurrentLedger.id'), - 'fields' => false, - 'conditions' => array('Customer.id', $this->data['customer_id']), - )); - $ledger_id = $customer['Account']['CurrentLedger']['id']; - } - else { - // Payment by Unit, Lease, etc - $ledger_id = 0; + $this->layout = null; + $this->autoLayout = false; + $this->autoRender = false; + Configure::write('debug', '0'); + + // Sanitize the transaction data + if (!$this->data['Transaction']['comment']) + $this->data['Transaction']['comment'] = null; + + if(empty($this->data['Transaction']['stamp'])) { + die("Time/Date not valid"); } + pr($this->data['Transaction']); - $amount = 0; - foreach ($this->data['LedgerEntry'] AS &$entry) { - $reconciled = $C->reconcileNewLedgerEntry($this->data['customer_id'], - 'credit', - $entry['amount']); - pr(compact('entry', 'reconciled')); - - foreach ($reconciled['debit']['entry'] AS $rec) { - $entry['DebitReconciliationLedgerEntry'] = - array('amount' => $rec['applied'], - //'debit_ledger_entry_id' - 'credit_ledger_entry_id' => $rec['id'] - ); - } - - $amount += isset($entry['amount']) ? $entry['amount'] : 0; - $entry['debit_ledger_id'] = 6; // Cash/Payments - $entry['credit_ledger_id'] = $ledger_id; - } - - - pr($this->data); - $T = new Transaction(); - $T->create(); - if ($T->saveAll($this->data, - array( - 'validate' => false, - //'fieldList' => array(), - //'callbacks' => true, - ))) { - $tid = $T->id; - $this->Session->setFlash(__("New Transaction Created ($tid)!", true)); - //$this->redirect(array('action'=>'view', $mid)); - } - else { - $this->autoRender = false; - pr(array('checkpoint' => "saveAll failed")); - } - pr($T->data); - + // Create some models for convenience + $A = new Account(); $C = new Customer(); - $LE = new LedgerEntry(); -/* $reconciled = $C->reconcileNewLedgerEntry($this->data['customer_id'], */ -/* 'credit', */ -/* $amount); */ -/* pr(compact('amount', 'unreconciled', 'reconciled')); */ -/* return; */ + // Create a transaction for the receipt + $receipt_transaction = new Transaction(); + $receipt_transaction->create(); + if (!$receipt_transaction->save($this->data['Transaction'], + array('validate' => false, + ))) { + pr(array('checkpoint' => "receipt transaction save failed")); + die("Unknown Database Failure"); + } + pr("New Transaction Created ({$receipt_transaction->id})!"); + $receipt_transaction->read(); + pr($receipt_transaction->data); + + // Create a transaction for the splits + $split_transaction = new Transaction(); + $split_transaction->create(); + if (!$split_transaction->save($this->data['Transaction'], + array('validate' => false, + ))) { + pr(array('checkpoint' => "split transaction save failed")); + die("Unknown Database Failure"); + } + pr("New Transaction Created ({$split_transaction->id})!"); + $split_transaction->read(); + pr($split_transaction->data); + + // Go through the entered payments foreach ($this->data['LedgerEntry'] AS &$entry) { + + // Get the Monetary Source squared away + if ($entry['monetary_type_name'] === 'Cash') { + // No distinguishing features of Cash, just + // use the shared monetary source + $entry['monetary_source_id'] = + $this->Transaction->LedgerEntry->MonetarySource->nameToID('Cash'); + unset($entry['MonetarySource']); + } + else { + // The monetary source needs to be unique + // Create a new one dedicated to this entry + $entry['MonetarySource']['monetary_type_id'] = + $this->Transaction->LedgerEntry->MonetarySource->MonetaryType + ->nameToID($entry['monetary_type_name']); + + $entry['MonetarySource']['name'] = + $this->Transaction->LedgerEntry->MonetarySource->MonetaryType + ->nameToID($entry['monetary_type_name']); + + // Give it a fancy name based on the check number + $entry['MonetarySource']['name'] = $entry['monetary_type_name']; + if ($entry['monetary_type_name'] === 'Check' || + $entry['monetary_type_name'] === 'Money Order') { + $entry['MonetarySource']['name'] .= + ' #' . $entry['MonetarySource']['data1']; + } + } + + + // This entry of physical money is part of the receipt transaction + // debit: Cash/Check/Etc credit: Receipt + $entry['transaction_id'] = $receipt_transaction->id; + + // Receipt must debit the "money" asset (bank, cash, check, etc)... + $entry['debit_ledger_id'] + = $A->currentLedgerID($A->nameToID($entry['monetary_type_name'])); + + // ...and credit the Receipt ledger + $entry['credit_ledger_id'] + = $A->currentLedgerID($A->receiptAccountID()); + + $entry['customer_id'] + = $this->data['customer_id']; + + // Create it + $receipt_entry = new LedgerEntry(); + $receipt_entry->create(); + if (!$receipt_entry->saveAll($entry, + array('validate' => false, + ))) { + pr(array('checkpoint' => "receipt entry saveAll failed")); + die("Unknown Database Failure"); + } + pr("New Receipt LedgerEntry Created ({$receipt_entry->id})!"); + $receipt_entry->read(); + pr($receipt_entry->data); + $reconciled = $C->reconcileNewLedgerEntry($this->data['customer_id'], 'credit', $entry['amount']); pr(compact('entry', 'reconciled')); - continue; - foreach ($reconciled['debit']['entry'] AS $rec) { - $data = array('LedgerEntry' => - array('DebitReconciliationLedgerEntry' => - array('amount' => $rec['applied'], - //'debit_ledger_entry_id' - 'credit_ledger_entry_id' => $rec['id'] - ), - ), - ); - //'DebitReconciliationLedgerEntry' => array( - //pr(compact('amount', 'unreconciled', 'reconciled')); + foreach (array_merge($reconciled['debit']['entry'], array + (array('id' => null, + 'applied' => $reconciled['debit']['unapplied'], + 'customer_id' => $this->data['customer_id'], + 'lease_id' => null))) AS $rec) { + + pr(array('checkpoint' => "Handle Reconciled Entry", + compact('rec'), + )); + if (!$rec['applied']) + continue; + + // Create an entry to handle the splitting of the funds ("Payment") + // Payment must debit the Receipt ledger, and credit the A/R ledger + // debit: Receipt credit: A/R + $split_entry_data = array + ('debit_ledger_id' => $A->currentLedgerID($A->receiptAccountID()), + 'credit_ledger_id' => $A->currentLedgerID($A->accountReceivableAccountID()), + 'transaction_id' => $split_transaction->id, + 'amount' => $rec['applied'], + 'lease_id' => $rec['lease_id'], + 'customer_id' => $rec['customer_id'], + ); + + // Create a new split entry from the data + $split_entry = new LedgerEntry(); + $split_entry->create(); + if (!$split_entry->save($split_entry_data, + array('validate' => false, + ))) { + pr(array('checkpoint' => "split entry save failed")); + die("Unknown Database Failure"); + } + pr("New Split LedgerEntry Created ({$split_entry->id})!"); + $split_entry->read(); + pr($split_entry->data); + + // Reconcile the Receipt account. Our two entries look like: + // debit: Cash/Check/Etc credit: Receipt + // debit: Receipt credit: A/R + // Since this is from the perspective of the Receipt account, + // the debit entry is the Receipt<->A/R, and the credit + // entry is the actual receipt ledger entry. + $R = new Reconciliation(); + $R->create(); + if (!$R->save(array('debit_ledger_entry_id' => $split_entry->id, + 'credit_ledger_entry_id' => $receipt_entry->id, + 'amount' => $rec['applied']), + array('validate' => false, + ))) { + pr(array('checkpoint' => "receipt reconcile save failed")); + die("Unknown Database Failure"); + } + pr("New Receipt Reconciliation Created ({$R->id})!"); + $R->read(); + pr($R->data); + + // Only reconcile the A/R account if we have an entry + // to reconcile with, otherwise, just go on. + if (!$rec['id']) + continue; + + // Reconcile the A/R account. Our two entries look like: + // debit: Receipt credit: A/R + // debit: A/R credit: Invoice + // Since this is from the perspective of the A/R account, + // the debit entry is the Invoice<->A/R, and the credit + // entry is the Receipt<->A/R. + $R = new Reconciliation(); + $R->create(); + if (!$R->save(array('debit_ledger_entry_id' => $rec['id'], + 'credit_ledger_entry_id' => $split_entry->id, + 'amount' => $rec['applied']), + array('validate' => false, + ))) { + pr(array('checkpoint' => "split reconcile save failed")); + die("Unknown Database Failure"); + } + pr("New Split Reconciliation Created ({$R->id})!"); + $R->read(); + pr($R->data); } } - } - function saveTest() { - $data = - array( -/* 'Customer' => array */ -/* ('id' => 7, */ -/* ), */ - - 'LedgerEntry' => array - ( - '0' => array( - 'amount' => 100, - 'debit_ledger_id' => 1, - 'credit_ledger_id' => 2, - 'MonetarySource' => array('name' => 'testmoney', 'monetary_type_id' => 2), - ), - '1' => array( - 'amount' => 101, - 'debit_ledger_id' => 1, - 'credit_ledger_id' => 2, - 'MonetarySource' => array('name' => 'testmoney2', 'monetary_type_id' => 2), - ), - ), - - 'Transaction' => array - ( - 'stamp' => '06/18/2009', - 'comment' => 'no comment', - ), - ); - - $data = -/* array( */ -/* 'LedgerEntry' => array */ -/* ( */ -/* '0' => */ - array( - 'amount' => 100, - 'debit_ledger_id' => 1, - 'credit_ledger_id' => 2, - 'transaction_id' => 66, - 'DebitReconciliationLedgerEntry' => - array('amount' => 44, - //'debit_ledger_entry_id' - 'credit_ledger_entry_id' => 17, - ), -/* ), */ -/* ), */ - - ); - - //$M = new Transaction(); - $M = new LedgerEntry(); - $M->create(); - $retval = $M->saveAll($data, - array( - 'validate' => false, - 'fieldList' => array(), - 'callbacks' => true, - )); - - $mid = $M->id; - pr(compact('retval', 'mid')); - if ($mid) { - $this->Session->setFlash(__("New Transaction Created ($mid)!", true)); - //$this->redirect(array('action'=>'view', $mid)); - } - else { - $this->autoRender = false; - pr(array('checkpoint' => "saveAll failed")); - } - - -/* $LE = new LedgerEntry(); */ -/* $LE->create(); */ -/* $ret = $LE->save($data, */ -/* array( */ -/* 'validate' => false, */ -/* 'fieldList' => array(), */ -/* 'callbacks' => true, */ -/* )); */ -/* $leid = $LE->id; */ -/* pr(array('checkpoint' => "New Ledger Entry", */ -/* compact('leid', 'ret'))); */ - //pr($LE); - - } } diff --git a/site/models/account.php b/site/models/account.php index 05c5a39..792eda7 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -92,6 +92,23 @@ class Account extends AppModel { function invoiceAccountID() { return $this->nameToID('Invoice'); } function receiptAccountID() { return $this->nameToID('Receipt'); } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * 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']; + } + + /************************************************************************** ************************************************************************** @@ -131,6 +148,34 @@ class Account extends AppModel { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: closeCurrentLedger + * - Closes the current account ledger, and opens a new one + * with the old balance carried forward. + */ + function closeCurrentLedger($id = null) { + $contain = array('CurrentLedger' => array('fields' => array('CurrentLedger.id'))); + + $this->cacheQueries = true; + $account = $this->find('all', array + ('contain' => $contain, + 'fields' => array(), + 'conditions' => + $id ? array(array('Account.id' => $id)) : array() + )); + $this->cacheQueries = false; + //pr(compact('id', 'account')); + + foreach ($account AS $acct) { + if (!$this->Ledger->closeLedger($acct['CurrentLedger']['id'])) + return false; + } + return true; + } + + /************************************************************************** ************************************************************************** ************************************************************************** @@ -222,7 +267,7 @@ class Account extends AppModel { ('fields' => array(), "LedgerEntry" => array ('class' => "{$ucfund}LedgerEntry", - 'fields' => array('id', 'amount'), + 'fields' => array('id', 'customer_id', 'lease_id', 'amount'), "ReconciliationLedgerEntry" => array ('class' => "{$ucfund}ReconciliationLedgerEntry", 'fields' => array diff --git a/site/models/ledger.php b/site/models/ledger.php index aa10e76..7e159aa 100644 --- a/site/models/ledger.php +++ b/site/models/ledger.php @@ -44,6 +44,72 @@ class Ledger extends AppModel { ); + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: closeLedger + * - Closes the current ledger, and returns a fresh one + */ + function closeLedger($id) { + $this->recursive = -1; + + $stamp = date('Y-m-d G:i:s'); + $this->id = $id; + $this->read(); + $this->data['Ledger']['close_stamp'] = $stamp; + $this->data['Ledger']['closed'] = 1; + $this->save($this->data, false); + + $stats = $this->stats($id); + + $this->read(); + $this->data['Ledger']['id'] = null; + $this->data['Ledger']['closed'] = 0; + $this->data['Ledger']['open_stamp'] = $stamp; + $this->data['Ledger']['close_stamp'] = null; + $this->data['Ledger']['comment'] = null; + ++$this->data['Ledger']['sequence']; + $this->id = null; + $this->save($this->data, false); + //pr($this->data); + + if ($stats['balance'] == 0) + return $this->id; + + $this->read(); + $ftype = $this->Account->fundamentalType($this->data['Ledger']['account_id']); + $otype = $this->Account->fundamentalOpposite($ftype); + + // Create a transaction for balance transfer + $transaction = new Transaction(); + $transaction->create(); + if (!$transaction->save(array(), + array('validate' => false, + ))) { + return null; + } + + // Create an entry to carry the balance forward + $carry_entry_data = array + ($ftype.'_ledger_id' => $this->id, + $otype.'_ledger_id' => $id, + 'transaction_id' => $transaction->id, + 'amount' => $stats['balance'], + 'comment' => "Ledger Balance Forward", + ); + + $carry_entry = new LedgerEntry(); + $carry_entry->create(); + if (!$carry_entry->save($carry_entry_data, + array('validate' => false, + ))) { + return null; + } + + return $this->id; + } + + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/models/ledger_entry.php b/site/models/ledger_entry.php index b528820..b51b203 100644 --- a/site/models/ledger_entry.php +++ b/site/models/ledger_entry.php @@ -8,6 +8,16 @@ class LedgerEntry extends AppModel { 'amount' => array('money') ); + var $hasMany = array( + 'DebitReconciliation' => array( + 'className' => 'Reconciliation', + 'foreignKey' => 'debit_ledger_entry_id', + ), + 'CreditReconciliation' => array( + 'className' => 'Reconciliation', + 'foreignKey' => 'credit_ledger_entry_id', + ), + ); var $belongsTo = array( 'MonetarySource', 'Transaction', diff --git a/site/models/reconciliation.php b/site/models/reconciliation.php new file mode 100644 index 0000000..214b3d0 --- /dev/null +++ b/site/models/reconciliation.php @@ -0,0 +1,15 @@ + array( + 'className' => 'LedgerEntry', + //'foreignKey' => 'credit_ledger_entry_id', + ), + 'CreditLedgerEntry' => array( + 'className' => 'LedgerEntry', + //'foreignKey' => 'credit_ledger_entry_id', + ), + ); + +} diff --git a/site/models/transaction.php b/site/models/transaction.php index 2c22348..e7ccb03 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -7,7 +7,6 @@ class Transaction extends AppModel { /* ); */ var $belongsTo = array( - 'Customer', ); var $hasMany = array( @@ -17,10 +16,15 @@ class Transaction extends AppModel { function beforeSave() { - if(!empty($this->data['Transaction']['stamp'])) { + if(isset($this->data['Transaction']['stamp']) && + $this->data['Transaction']['stamp'] !== 'CURRENT_TIMESTAMP') { $this->data['Transaction']['stamp'] = $this->dateFormatBeforeSave($this->data['Transaction']['stamp']); } + else { + $this->data['Transaction']['stamp'] = null; + } + return true; } diff --git a/site/views/accounts/view.ctp b/site/views/accounts/view.ctp index d31b926..cf21063 100644 --- a/site/views/accounts/view.ctp +++ b/site/views/accounts/view.ctp @@ -65,7 +65,7 @@ echo $this->element('ledgers', */ echo $this->element('ledger_entries', - array('caption' => "Current Ledger: (#{$account['CurrentLedger']['sequence']})", + array('caption' => "Current Ledger: (#{$account['Account']['id']}-{$account['CurrentLedger']['sequence']})", 'ledger_id' => $account['CurrentLedger']['id'], 'account_type' => $account['Account']['type'], )); diff --git a/site/views/customers/payment.ctp b/site/views/customers/payment.ctp index 4c3dac4..1ac95c0 100644 --- a/site/views/customers/payment.ctp +++ b/site/views/customers/payment.ctp @@ -148,6 +148,17 @@ $grid_setup['onSelectRow'] = array $('#payments').html(''); $('#payment-id').val(0); addPaymentSource(false); + datepickerNow(); + } + + function datepickerNow() { + now = new Date(); + $("#datepicker").val($.datepicker.formatDate('mm/dd/yy', now) + + ' ' + + (now.getHours() < 10 ? '0' : '') + + now.getHours() + ':' + + (now.getMinutes() < 10 ? '0' : '') + + now.getMinutes()); } function addPaymentSource(flash) { @@ -158,16 +169,6 @@ $grid_setup['onSelectRow'] = array '
    ' + 20090616: - * MUST GET THIS FROM THE DATABASE!! - * HARDCODED VALUES BAD... VERY BAD... - */ - $monetary_type_ids = array('Cash' => 2, - 'Check' => 3, - 'Money Order' => 4, - 'ACH' => 5, - 'Credit Card' => 7, - ); $types = array(); foreach(array('Cash', 'Check', 'Money Order', /*'ACH', 'Credit Card'*/) AS $name) @@ -175,11 +176,10 @@ $grid_setup['onSelectRow'] = array foreach ($types AS $type => $name) { $div = '
    '; - $div .= ''; - $div .= ''; + $div .= ' VALUE="'.$name.'" ' . ($name == 'Cash' ? 'CHECKED ' : '') . '/>'; $div .= ' '; $div .= '
    '; echo "'$div' +\n"; @@ -228,7 +228,7 @@ function switchPaymentType(paymentid, type) { '
    ' + ' ' + // REVISIT : 20090617: Use comment field for now. - ' ' + '
    '; break; @@ -238,7 +238,7 @@ function switchPaymentType(paymentid, type) { '
    ' + ' ' + // REVISIT : 20090617: Use comment field for now. - ' ' + '
    '; break; @@ -248,14 +248,14 @@ function switchPaymentType(paymentid, type) { '
    ' + ' ' + // REVISIT : 20090617: Use comment field for now. - ' ' + '
    ' + '
    ' + ' ' + // REVISIT : 20090617: Use comment field for now. - ' ' + '
    '; break; @@ -265,21 +265,21 @@ function switchPaymentType(paymentid, type) { '
    ' + ' ' + // REVISIT : 20090617: Use comment field for now. - ' ' + '
    ' + '
    ' + ' ' + // REVISIT : 20090617: Use comment field for now. - ' ' + '
    ' + '
    ' + ' ' + // REVISIT : 20090617: Use comment field for now. - ' ' + '
    '; break; @@ -436,7 +436,8 @@ echo $form->create(null, array('id' => 'payment-form',
    ' . "\n"; +echo 'Date: '; +echo ' Now
    ' . "\n"; echo 'Comment:
    ' . "\n"; echo $form->end('Post Payment'); @@ -457,8 +458,12 @@ echo $form->end('Post Payment'); + +element('customers', + array('grid_div_id' => 'customers-list', + 'caption' => ('Select Customer'), + 'grid_setup' => $customer_grid_setup, + 'nolinks' => true, + 'limit' => 10, + )); + +echo $this->element('units', + array('grid_div_id' => 'units-list', + 'caption' => ('Select Unit'), + 'grid_setup' => $unit_grid_setup, + 'action' => 'unoccupied', + 'nolinks' => true, + 'limit' => 10, + )); + +echo ('

    ' . + '' . + 'Customer: ' . + '' . (isset($customer['name']) ? $customer['name'] : "") . '' . + '' . + '' . + 'Please select customer' . + '' . + '

    ' . "\n"); + +echo ('

    ' . + '' . + 'Unit: ' . + '' . (isset($unit['name']) ? $unit['name'] : "") . '' . + '' . + '' . + 'Please select unit' . + '' . + '

    ' . "\n"); + +echo $form->create(null, array('id' => 'move-in-form', + 'url' => array('controller' => 'leases', + 'action' => 'move_in'))); + +echo $form->input("Lease.customer_id", + array('id' => 'customer-id', + 'type' => 'hidden', + 'value' => isset($customer['id']) ? $customer['id'] : 0)); + +echo $form->input("Lease.unit_id", + array('id' => 'unit-id', + 'type' => 'hidden', + 'value' => isset($unit['id']) ? $unit['id'] : 0)); + +echo 'Date:
    ' . "\n"; +echo 'Comment:
    ' . "\n"; +echo $form->end('Move In Customer'); + +?> + + + +
    diff --git a/site/views/leases/view.ctp b/site/views/leases/view.ctp index fabee8f..16d2f85 100644 --- a/site/views/leases/view.ctp +++ b/site/views/leases/view.ctp @@ -36,7 +36,7 @@ $rows = array(array('ID', $lease['id']), array('Notice Received', FormatHelper::date($lease['notice_received_date'], true)), array('Closed', FormatHelper::date($lease['close_date'], true)), array('Deposit', FormatHelper::currency($lease['deposit'])), - array('Rent', FormatHelper::currency($lease['amount'])), + array('Rent', FormatHelper::currency($lease['rent'])), array('Comment', $lease['comment'])); diff --git a/site/views/units/view.ctp b/site/views/units/view.ctp index 4fed8be..83e3426 100644 --- a/site/views/units/view.ctp +++ b/site/views/units/view.ctp @@ -9,15 +9,25 @@ echo '
    ' . "\n"; * Unit Detail Main Section */ -$rows = array(array('Name', $unit['Unit']['name']), - array('Status', $unit['Unit']['status']), - array('Comment', $unit['Unit']['comment'])); +$leases = $unit['Lease']; +$current_lease = $unit['CurrentLease']; +$unit_size = $unit['UnitSize']; + +if (isset($unit['Unit'])) + $unit = $unit['Unit']; + +$rows = array(array('Name', $unit['name']), + array('Status', $unit['status']), + array('Size', $unit_size['name']), + array('Deposit', FormatHelper::currency($unit['deposit'])), + array('Rent', FormatHelper::currency($unit['rent'])), + array('Comment', $unit['comment'])); echo $this->element('table', array('class' => 'item unit detail', - 'caption' => 'Unit Info', - 'rows' => $rows, - 'column_class' => array('field', 'value'))); + 'caption' => 'Unit Info', + 'rows' => $rows, + 'column_class' => array('field', 'value'))); /********************************************************************** @@ -52,22 +62,22 @@ echo '
    ' . "\n"; */ echo $this->element('leases', - array('caption' => 'Lease History', - 'leases' => $unit['Lease'])); + array('caption' => 'Lease History', + 'leases' => $leases)); /********************************************************************** * Current Tenant Lease Account History */ -if (isset($unit['CurrentLease']['id'])) { +if (isset($current_lease['id'])) { echo $this->element('ledger_entries', - array('caption' => - ('Current Lease Account (' - . $unit['CurrentLease']['Customer']['name'] - . ')'), - 'ar_account' => true, - 'lease_id' => $unit['CurrentLease']['id'], - )); + array('caption' => + ('Current Lease Account (' + . $current_lease['Customer']['name'] + . ')'), + 'ar_account' => true, + 'lease_id' => $current_lease['id'], + )); } From f6401c92be627c9277582c4271e5a9d98f4ad76a Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 4 Jul 2009 04:13:09 +0000 Subject: [PATCH 199/717] Moved menu items unintended for long term into a 'Debug' section of the sidemenu bar git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@205 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/site/app_controller.php b/site/app_controller.php index 28a151e..ab0dc81 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -45,8 +45,9 @@ class AppController extends Controller { array('name' => 'Units', 'url' => array('controller' => 'units', 'action' => 'index')), array('name' => 'Leases', 'url' => array('controller' => 'leases', 'action' => 'index')), array('name' => 'Customers', 'url' => array('controller' => 'customers', 'action' => 'index')), - array('name' => 'Contacts', 'url' => array('controller' => 'contacts', 'action' => 'index')), array('name' => 'Accounts', 'url' => array('controller' => 'accounts', 'action' => 'index')), + array('name' => 'Debug', 'header' => true), + array('name' => 'Contacts', 'url' => array('controller' => 'contacts', 'action' => 'index')), array('name' => 'Ledgers', 'url' => array('controller' => 'ledgers', 'action' => 'index')), array('name' => 'RESET DATA', 'url' => array('controller' => 'accounts', 'action' => 'reset_data')), ); From 27503ac4f90b245dd1c9ce69466c30b956698652 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 4 Jul 2009 04:42:11 +0000 Subject: [PATCH 200/717] Got rid of the temporary function to determine unit status enums, and switched over to actually querying the database. Eliminated a legend entry for DELETED since no one should ever see a unit like that given that it should be, well, deleted. Modified the legend algorithm slightly to fix the number of rows instead of columns, since the placement algorithm works through the rows before moving to the next column. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@206 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_model.php | 2 +- site/controllers/maps_controller.php | 25 +++++-------------------- site/models/unit.php | 4 ++++ 3 files changed, 10 insertions(+), 21 deletions(-) diff --git a/site/app_model.php b/site/app_model.php index f2f0197..0f8aa86 100644 --- a/site/app_model.php +++ b/site/app_model.php @@ -72,7 +72,7 @@ class AppModel extends Model { //Get the values return array_flip(array_merge(array(''), // MySQL sets 0 to be the empty string - explode("','", preg_replace("/(enum)\('(.+?)'\)/","\\2", $types)) + explode("','", strtoupper(preg_replace("/(enum)\('(.+?)'\)/","\\2", $types))) )); } //end getEnumValues diff --git a/site/controllers/maps_controller.php b/site/controllers/maps_controller.php index 1684ce8..ebeb991 100644 --- a/site/controllers/maps_controller.php +++ b/site/controllers/maps_controller.php @@ -151,22 +151,6 @@ class MapsController extends AppController { return $info; } - // Temporary function - function unitStatusList() { - return - array('DELETED' => array(), - 'DAMAGED' => array(), - 'COMPANY' => array(), - 'UNAVAILABLE' => array(), - 'RESERVED' => array(), - 'DIRTY' => array(), - 'VACANT' => array(), - 'OCCUPIED' => array(), - 'LATE' => array(), - 'LOCKED' => array(), - 'LIENED' => array(), - ); - } /************************************************************************** ************************************************************************** @@ -176,9 +160,10 @@ class MapsController extends AppController { */ function legend($id = null, $requested_width = 400) { - $status = $this->unitStatusList(); - $cols = 6; - $rows = (int)((count($status) + $cols - 1) / $cols); + $status = $this->Map->Unit->activeStatusEnums(); + //pr($status); + $rows = 2; + $cols = (int)((count($status) + $rows - 1) / $rows); $info = array('units' => array()); @@ -206,7 +191,7 @@ class MapsController extends AppController { $item_width *= $screen_adjustment_factor; $item_depth *= $screen_adjustment_factor; - foreach ($status AS $code => $color) { + foreach ($status AS $code => $value) { $info['units'][] = array('name' => $code, 'status' => $code, 'width' => $item_width, diff --git a/site/models/unit.php b/site/models/unit.php index 2d1d519..a5abd89 100644 --- a/site/models/unit.php +++ b/site/models/unit.php @@ -40,6 +40,10 @@ class Unit extends AppModel { return $status_enums; } + function activeStatusEnums() { + return array_diff_key($this->statusEnums(), array(''=>1, 'DELETED'=>1)); + } + function statusValue($enum) { $enums = $this->statusEnums(); return $enums[$enum]; From 6a8d21dad7702b3de1860d009eee7650f6de92bd Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 4 Jul 2009 17:38:22 +0000 Subject: [PATCH 201/717] Changed the relationship between grid visibility and text of the selected item. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@207 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/customers.ctp | 2 +- site/views/elements/units.ctp | 2 +- site/views/leases/move_in.ctp | 121 ++++++++++++++++++------------ site/webroot/css/layout.css | 4 + 4 files changed, 77 insertions(+), 52 deletions(-) diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index 6f7203e..46cd28f 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -16,7 +16,7 @@ $custom_post_data = compact('nothing'); $jqGrid_options = array('jqGridColumns' => $cols, 'controller' => 'customers'); $jqGrid_options += compact('action', 'caption', - 'grid_div_id', 'grid_id', 'grid_setup', + 'grid_div_id', 'grid_div_class', 'grid_id', 'grid_setup', 'nolinks', 'limit'); if (isset($customers)) { diff --git a/site/views/elements/units.ctp b/site/views/elements/units.ctp index 6b9a6fa..6f2eed7 100644 --- a/site/views/elements/units.ctp +++ b/site/views/elements/units.ctp @@ -16,7 +16,7 @@ $custom_post_data = compact('nothing'); $jqGrid_options = array('jqGridColumns' => $cols, 'controller' => 'units'); $jqGrid_options += compact('action', 'caption', - 'grid_div_id', 'grid_id', 'grid_setup', + 'grid_div_id', 'grid_div_class', 'grid_id', 'grid_setup', 'nolinks', 'limit'); if (isset($units)) { diff --git a/site/views/leases/move_in.ctp b/site/views/leases/move_in.ctp index c107366..e8dcd2b 100644 --- a/site/views/leases/move_in.ctp +++ b/site/views/leases/move_in.ctp @@ -19,7 +19,12 @@ if (isset($customer['id'])) $customer_grid_setup['onSelectRow'] = array ('--special' => - 'function(ids) { if (ids != null) { onCustomerRowSelect("#"+$(this).attr("id"), ids); } }' + 'function(ids) { if (ids != null) { onRowSelect("#"+$(this).attr("id"), "customer", ids); } }' + ); + +$customer_grid_setup['onHeaderClick'] = array + ('--special' => + 'function(gridstate) { onGridState("#"+$(this).attr("id"), "customer", gridstate); }' ); $unit_grid_setup = array(); @@ -29,49 +34,58 @@ if (isset($unit['id'])) $unit_grid_setup['onSelectRow'] = array ('--special' => - 'function(ids) { if (ids != null) { onUnitRowSelect("#"+$(this).attr("id"), ids); } }' + 'function(ids) { if (ids != null) { onRowSelect("#"+$(this).attr("id"), "unit", ids); } }' + ); + +$unit_grid_setup['onHeaderClick'] = array + ('--special' => + 'function(gridstate) { onGridState("#"+$(this).attr("id"), "unit", gridstate); }' ); ?> diff --git a/site/webroot/css/layout.css b/site/webroot/css/layout.css index a7bd608..17a3161 100644 --- a/site/webroot/css/layout.css +++ b/site/webroot/css/layout.css @@ -4,6 +4,7 @@ */ /* table th, td { border: dashed 1px; } */ +/* .debug-border { border: dashed 1px; } */ /************************************************************ ************************************************************ @@ -178,6 +179,9 @@ table.deposit-summary td.quantity { padding-right: 0.8em; } ************************************************************ * jqGrid */ + +div.grid.text-below { margin-bottom: 0; } + table.Header th h2 { color: #dd5; font-family:'Gill Sans','lucida grande',helvetica, arial, sans-serif; From dea1454dcd0eb309435b76e81fbe9808daecf710 Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 5 Jul 2009 02:48:23 +0000 Subject: [PATCH 202/717] Nowhere near complete, but a quick checkin to the contacts edit view so I can clean up some of the commented code that's getting intrusive. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@208 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/contacts/edit.ctp | 212 +++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 site/views/contacts/edit.ctp diff --git a/site/views/contacts/edit.ctp b/site/views/contacts/edit.ctp new file mode 100644 index 0000000..cee1f04 --- /dev/null +++ b/site/views/contacts/edit.ctp @@ -0,0 +1,212 @@ + + + + +' . "\n"; + +/********************************************************************** + ********************************************************************** + ********************************************************************** + ********************************************************************** + * Contact Detail Main Section + */ + +echo $form->create('Contact'); +echo $form->input('id'); + +$rows = array(); +foreach (array('first_name' => null, + 'last_name' => null, + 'middle_name' => null, + 'display_name' => null, + 'company_name' => 'Company', + 'id_federal' => 'SSN', + 'id_local' => 'ID #', + 'id_local_state' => 'ID State', + //'id_local_exp' => 'ID Expires', + 'comment' => null, + + //'' => null, + //'' => '', + + ) AS $field => $label) { + if (!isset($label)) + $label = implode(' ', array_map('ucfirst', explode('_', $field))); + + $opts = array('label' => false); + if ($field === 'id_local_exp') + $opts['empty'] = true; + + $rows[] = array($label, $form->input($field, $opts)); +} + +echo $this->element('table', + array('class' => 'item contact detail', + 'caption' => 'Edit Contact', + 'rows' => $rows, + 'column_class' => array('field', 'value'))); + + + + +/* echo $form->input('ContactAddress'); */ +/* echo $form->input('ContactPhone'); */ +/* echo $form->input('ContactEmail'); */ +/* echo $form->input('Customer'); */ + +echo $form->submit('Update') . $form->submit('Cancel'); +echo $form->end(); + +?> + +
    + Phones + +
    +
    + Add Another Phone +
    +
    + +' . "\n"; From dc850f4e8e9452f30326356429a39ee599083c19 Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 5 Jul 2009 15:01:18 +0000 Subject: [PATCH 203/717] First shot at an actual working form to enter contact information. It only handles phone numbers at the moment, and it does NOT handle existing ones. It's a decent start though, and worth checking in. Next I'll have to handle existing phone numbers, and then addresses and emails. Of course, after that, I'll have to actually save everything to the database. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@209 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_model.php | 10 +- site/controllers/contacts_controller.php | 66 ++++++ site/models/contact_phone.php | 17 +- site/views/contacts/edit.ctp | 255 +++++++++++------------ site/views/elements/form_table.ctp | 31 +++ site/views/helpers/format.php | 13 +- 6 files changed, 245 insertions(+), 147 deletions(-) create mode 100644 site/views/elements/form_table.ctp diff --git a/site/app_model.php b/site/app_model.php index 0f8aa86..64c398b 100644 --- a/site/app_model.php +++ b/site/app_model.php @@ -47,13 +47,15 @@ class AppModel extends Model { * * Gets the enum values for MySQL 4 and 5 to use in selectTag() */ - function getEnumValues($columnName=null, $respectDefault=false) + function getEnumValues($columnName=null, $tableName=null) { if ($columnName==null) { return array(); } //no field specified - //Get the name of the table - $db =& ConnectionManager::getDataSource($this->useDbConfig); - $tableName = $db->fullTableName($this, false); + 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}'"); diff --git a/site/controllers/contacts_controller.php b/site/controllers/contacts_controller.php index d61d64d..7baa3ae 100644 --- a/site/controllers/contacts_controller.php +++ b/site/controllers/contacts_controller.php @@ -46,6 +46,11 @@ class ContactsController extends AppController { return $order; } + function jqGridRecordLinks(&$params, &$model, &$records, $links) { + $links['Contact'] = array('id'); + return parent::jqGridRecordLinks($params, $model, $records, $links); + } + /************************************************************************** ************************************************************************** @@ -72,8 +77,69 @@ class ContactsController extends AppController { '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']['display_name']; $this->set(compact('contact', 'title')); } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: edit + */ + + function edit($id = null) { + if (isset($this->data)) { + pr($this->data); + $this->autoRender = false; + return; + } + + if (!$id) { + $this->Session->setFlash(__('Invalid Item.', true)); + $this->redirect(array('action'=>'index')); + } + + $this->data = $this->Contact->find + ('first', array + ('contain' => array + (// Models + 'ContactPhone', + 'ContactEmail', + 'ContactAddress', + 'Customer'), + + 'conditions' => array('Contact.id' => $id), + )); + + $phone_types = array_flip($this->Contact->ContactPhone->getEnumValues('type')); + unset($phone_types[0]); + $this->set(compact('phone_types')); + + $method_types = array_flip($this->Contact->getEnumValues('type', 'pmgr_contacts_methods')); + unset($method_types[0]); + $this->set(compact('method_types')); + + $method_preferences = array_flip($this->Contact->getEnumValues('preference', 'pmgr_contacts_methods')); + unset($method_preferences[0]); + $this->set(compact('method_preferences')); + + $contact_phones = $this->Contact->ContactPhone->phoneList(); + $this->set(compact('contact_phones')); + + // Prepare to render. + //pr($this->data); + $title = $this->data['Contact']['display_name'] . " : Edit"; + $this->set(compact('title')); + } } diff --git a/site/models/contact_phone.php b/site/models/contact_phone.php index f53b61d..012afcf 100644 --- a/site/models/contact_phone.php +++ b/site/models/contact_phone.php @@ -1,7 +1,6 @@ array('numeric'), //'type' => array('inlist'), @@ -20,5 +19,21 @@ class ContactPhone extends AppModel { ) ); + 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; + } + } ?> \ No newline at end of file diff --git a/site/views/contacts/edit.ctp b/site/views/contacts/edit.ctp index cee1f04..07ba1e1 100644 --- a/site/views/contacts/edit.ctp +++ b/site/views/contacts/edit.ctp @@ -1,21 +1,30 @@ +/********************************************************************** + ********************************************************************** + ********************************************************************** + ********************************************************************** + * Javascript + */ + + +' . "\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' => $this->data ? 'Edit Customer' : 'New Customer', + 'fields' => array + ('name' => null, + 'comment' => null, + ))) . "\n"); + +echo $form->submit('Update') . "\n"; +?> + +
    +
    + Contacts + +
    +
    + Add a Contact +
    +
    +
    + +submit('Update') . "\n"; +echo $form->submit('Cancel', array('name' => 'cancel')) . "\n"; +echo $form->end() . "\n"; +echo '
    ' . "\n"; From 3e60f8d45e02a8e8929df62b19fab461e1ac247a Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 6 Jul 2009 03:01:28 +0000 Subject: [PATCH 214/717] Implemented ability to add a customer, and fixed the problem with flagging of the primary contact. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@220 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/customers_controller.php | 5 +++ site/models/customer.php | 3 +- site/views/customers/edit.ctp | 50 +++++++++++++++++++---- site/views/elements/form_table.ctp | 2 +- 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 2f2e58d..e266817 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -6,6 +6,7 @@ class CustomersController extends AppController { 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 Tenant', 'url' => array('controller' => 'customers', 'action' => 'add')), ); //var $components = array('RequestHandler'); @@ -286,6 +287,9 @@ class CustomersController extends AppController { return; } + $this->data['Customer']['primary_contact_id'] + = $this->data['Contact'][$this->data['Customer']['primary_contact_entry']]['id']; + $this->Customer->create(); if (!$this->Customer->save($this->data, false)) { pr("CUSTOMER SAVE FAILED"); @@ -367,6 +371,7 @@ class CustomersController extends AppController { */ function add() { + $this->edit(); } /************************************************************************** diff --git a/site/models/customer.php b/site/models/customer.php index 6de7d3c..de625c3 100644 --- a/site/models/customer.php +++ b/site/models/customer.php @@ -159,7 +159,8 @@ class Customer extends AppModel { ('contain' => array (// Models 'Contact' => - array(// Models + array('order' => array('Contact.display_name'), + // Models 'ContactPhone', 'ContactEmail', 'ContactAddress', diff --git a/site/views/customers/edit.ctp b/site/views/customers/edit.ctp index 58275ce..a68f595 100644 --- a/site/views/customers/edit.ctp +++ b/site/views/customers/edit.ctp @@ -15,7 +15,7 @@ $this->varstore = compact('contactTypes', 'contacts'); * Javascript */ -function customerContactDiv($obj, $values = null) { +function customerContactDiv($obj, $values = null, $primary = false) { $div = // BEGIN type-div @@ -67,12 +67,31 @@ function customerContactDiv($obj, $values = null) { // BEGIN contact-div '
    ' . "\n" . */ +/* ' ' . "\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'], @@ -171,9 +190,10 @@ function customerContactTypeDiv($obj, $stype, $values = null) { function addContact(flash) { addDiv('contact-entry-id', 'contact', 'contacts', flash, ); } @@ -185,14 +205,26 @@ function customerContactTypeDiv($obj, $stype, $values = null) { data['Contact'] AS $contact): ?> addDiv('contact-entry-id', 'contact', 'contacts', false, data['Customer']['primary_contact_id'] + ), + null, + ' '); ?> ); + + if ($("#contact-entry-id").val() == 1) { + addDiv('contact-entry-id', 'contact', 'contacts', false, + ); + } } function switchContactSource(id, source) { diff --git a/site/views/elements/form_table.ctp b/site/views/elements/form_table.ctp index a7bd801..c3c15bc 100644 --- a/site/views/elements/form_table.ctp +++ b/site/views/elements/form_table.ctp @@ -16,7 +16,7 @@ foreach ($fields AS $field => $config) { if (!isset($config['opts'])) $config['opts'] = null; - if (isset($field_prefix)) + if (isset($field_prefix) && !isset($config['no_prefix'])) $field = $field_prefix . '.' . $field; $config['opts']['label'] = false; From 689a6dc7aa4d3af9b012890a16190b0a53e91236 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 6 Jul 2009 03:09:54 +0000 Subject: [PATCH 215/717] Changed layout to enlarge the detail table on the edit page. Changed edit action to redirect to the view page. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@221 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/customers_controller.php | 4 ++-- site/views/customers/edit.ctp | 4 +++- site/webroot/css/layout.css | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index e266817..13f3f4e 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -335,8 +335,8 @@ class CustomersController extends AppController { } // Now that the work is done, let the user view the updated customer - //$this->redirect(array('action'=>'view', $this->data['Customer']['id'])); - $this->autoRender = false; + $this->redirect(array('action'=>'view', $this->data['Customer']['id'])); + //$this->autoRender = false; return; } diff --git a/site/views/customers/edit.ctp b/site/views/customers/edit.ctp index a68f595..970b0f5 100644 --- a/site/views/customers/edit.ctp +++ b/site/views/customers/edit.ctp @@ -120,6 +120,7 @@ function customerContactDiv($obj, $values = null, $primary = false) { function customerContactTypeDiv($obj, $stype, $values = null) { $element = 'form_table'; + $class = $stype; if ($stype === 'existing') { $fields = array @@ -144,6 +145,7 @@ function customerContactTypeDiv($obj, $stype, $values = null) { } elseif ($stype === 'show') { $element = 'table'; + $class = 'detail'; $column_class = array('field', 'value'); $rows = array(array('First Name', $values['first_name']), //array('Middle Name', $values['middle_name']), @@ -170,7 +172,7 @@ function customerContactTypeDiv($obj, $stype, $values = null) { $obj->element ($element, - array('class' => "item contact {$stype}", + array('class' => "item contact {$class}", 'field_prefix' => 'Contact.%{id}') + compact('rows', 'fields', 'column_class')) . diff --git a/site/webroot/css/layout.css b/site/webroot/css/layout.css index a7b789d..3709b11 100644 --- a/site/webroot/css/layout.css +++ b/site/webroot/css/layout.css @@ -84,7 +84,7 @@ div.detail.supporting { clear : both; * Item edit formats */ -.edit table.detail { width : auto; +.edit table.detail { width : 80%; float : none; } From 5fd783dc50e784c87dc01a0c481818f70dba40c4 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 6 Jul 2009 03:34:33 +0000 Subject: [PATCH 216/717] Cleaned up and got rid of the word Tenant in most places. The original thought was to minimize confusion in our specific case (since we don't sell POS items) by simply refering to customers as tenants. However, I don't think customers is a very confusing term and so I decided to clear up the inconsistency. I did leave it in a couple places, where the customers in questions are clearly tenants git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@222 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/customers_controller.php | 14 ++++---------- site/views/contacts/edit.ctp | 9 +-------- site/views/customers/edit.ctp | 18 +----------------- site/views/customers/view.ctp | 2 +- site/views/units/view.ctp | 2 +- site/webroot/css/layout.css | 2 +- 6 files changed, 9 insertions(+), 38 deletions(-) diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 13f3f4e..4a0bf71 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -2,11 +2,11 @@ class CustomersController extends AppController { var $sidemenu_links = - array(array('name' => 'Tenants', 'header' => true), + 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 Tenant', 'url' => array('controller' => 'customers', 'action' => 'add')), + array('name' => 'Add Customer', 'url' => array('controller' => 'customers', 'action' => 'add')), ); //var $components = array('RequestHandler'); @@ -27,13 +27,13 @@ class CustomersController extends AppController { ************************************************************************** ************************************************************************** * action: index / current / past / all - * - Creates a list of tenants + * - Creates a list of customers */ function index() { $this->current(); } function current() { $this->jqGridView('Current Tenants'); } function past() { $this->jqGridView('Past Tenants'); } - function all() { $this->jqGridView('All Tenants', 'all'); } + function all() { $this->jqGridView('All Customers', 'all'); } /************************************************************************** @@ -236,12 +236,6 @@ class CustomersController extends AppController { 'url' => array('action' => 'edit', $id)); - $this->sidemenu_links[] = - array('name' => 'Add Contact', - 'url' => array('controller' => 'contacts', - 'action' => 'add', - $id)); - $this->sidemenu_links[] = array('name' => 'Move-In', 'url' => array('action' => 'move_in', diff --git a/site/views/contacts/edit.ctp b/site/views/contacts/edit.ctp index 86e0592..5574fd9 100644 --- a/site/views/contacts/edit.ctp +++ b/site/views/contacts/edit.ctp @@ -45,7 +45,6 @@ function contactMethodDiv($obj, $type, $legend, $values = null) { ' CLASS="'.$type.'-method-%{id}-source" ' . "\n" . ' ID="'.$type.'-method-%{id}-source-'.$stype.'"' . "\n" . ' VALUE="'.$stype.'"' . "\n" . - //' CHECKED' . "\n" . ' />' . "\n" . ' ' . "\n" . ' '; @@ -70,10 +69,6 @@ function contactMethodDiv($obj, $type, $legend, $values = null) { // BEGIN method-div '
    ' . "\n" */ -/* : '') . */ - $obj->element ('form_table', array('class' => "item contact-{$type} entry", @@ -348,7 +343,7 @@ echo $form->input('id') . "\n"; echo($this->element ('form_table', array('class' => 'item contact detail', - 'caption' => $this->data ? 'Edit Contact' : 'New Contact', + 'caption' => isset($this->data['Contact']) ? 'Edit Contact' : 'New Contact', 'fields' => array ('first_name' => null, 'last_name' => null, @@ -361,8 +356,6 @@ echo($this->element /* 'id_local_exp' => array('name' => 'ID Expiration', */ /* 'opts' => array('empty' => true)), */ 'comment' => null, - //'' => null, - //'' => '', ))) . "\n"); echo $form->submit('Update') . "\n"; diff --git a/site/views/customers/edit.ctp b/site/views/customers/edit.ctp index 970b0f5..b9c4ec9 100644 --- a/site/views/customers/edit.ctp +++ b/site/views/customers/edit.ctp @@ -67,16 +67,6 @@ function customerContactDiv($obj, $values = null, $primary = false) { // BEGIN contact-div '
    ' . "\n" . */ -/* ' ' . "\n" . */ - $obj->element ('form_table', array('class' => "item contact entry", @@ -148,14 +138,8 @@ function customerContactTypeDiv($obj, $stype, $values = null) { $class = 'detail'; $column_class = array('field', 'value'); $rows = array(array('First Name', $values['first_name']), - //array('Middle Name', $values['middle_name']), array('Last Name', $values['last_name']), array('Company', $values['company_name']), - //array('SSN', $values['id_federal']), -/* array('ID', ($values['id_local'] */ -/* . ($values['id_local'] */ -/* ? " - ".$values['id_local_state'] */ -/* : ""))), */ array('Comment', $values['comment'])); } else { @@ -261,7 +245,7 @@ echo $form->input('id') . "\n"; echo($this->element ('form_table', array('class' => 'item customer detail', - 'caption' => $this->data ? 'Edit Customer' : 'New Customer', + 'caption' => isset($this->data['Customer']) ? 'Edit Customer' : 'New Customer', 'fields' => array ('name' => null, 'comment' => null, diff --git a/site/views/customers/view.ctp b/site/views/customers/view.ctp index b6d18de..28e57e5 100644 --- a/site/views/customers/view.ctp +++ b/site/views/customers/view.ctp @@ -14,7 +14,7 @@ $rows = array(array('Name', $customer['Customer']['name']), echo $this->element('table', array('class' => 'item customer detail', - 'caption' => 'Tenant Info', + 'caption' => 'Customer Info', 'rows' => $rows, 'column_class' => array('field', 'value'))); diff --git a/site/views/units/view.ctp b/site/views/units/view.ctp index 83e3426..79e5f01 100644 --- a/site/views/units/view.ctp +++ b/site/views/units/view.ctp @@ -67,7 +67,7 @@ echo $this->element('leases', /********************************************************************** - * Current Tenant Lease Account History + * Current Customer Lease Account History */ if (isset($current_lease['id'])) { echo $this->element('ledger_entries', diff --git a/site/webroot/css/layout.css b/site/webroot/css/layout.css index 3709b11..23f5fa2 100644 --- a/site/webroot/css/layout.css +++ b/site/webroot/css/layout.css @@ -66,7 +66,7 @@ td.center { text-align: center; } /************************************************************ ************************************************************ * Item detail formats - * (such as Tenant Info, Unit Info, etc) + * (such as Customer Info, Unit Info, etc) */ table.detail { width : 60%; From 96dd06b58ad701ec19fb288be534836b7f5fa5f3 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 6 Jul 2009 03:35:09 +0000 Subject: [PATCH 217/717] Changed the lease 'payment' action to just point to the customer payment instead. Makes my life easier at the moment... git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@223 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/leases_controller.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index 8a799a9..08293ec 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -213,8 +213,9 @@ class LeasesController extends AppController { } $this->sidemenu_links[] = - array('name' => 'Payment', 'url' => array('action' => 'payment', - $id)); + array('name' => 'Payment', 'url' => array('controller' => 'customers', + 'action' => 'payment', + $lease['Customer']['id'])); } // Prepare to render From e953f2709dac81e82d83b1bc581a21e086463d0c Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 6 Jul 2009 04:30:03 +0000 Subject: [PATCH 218/717] Changed leases element to understand some common fields git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@224 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/leases.ctp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/site/views/elements/leases.ctp b/site/views/elements/leases.ctp index d5a9b34..119146a 100644 --- a/site/views/elements/leases.ctp +++ b/site/views/elements/leases.ctp @@ -12,9 +12,12 @@ $cols['Move-Out'] = array('index' => 'Lease.moveout_date', 'formatter' => 'dat $cols['Balance'] = array('index' => 'Lease.balance', 'formatter' => 'currency', 'sortable'=>false); $cols['Comment'] = array('index' => 'Lease.comment', 'formatter' => 'comment'); -$jqGrid_options = array('jqGridColumns' => $cols, - 'controller' => 'leases', - 'caption' => isset($caption) ? $caption : null); +$custom_post_data = compact('nothing'); +$jqGrid_options = array('jqGridColumns' => $cols, + 'controller' => 'leases'); +$jqGrid_options += compact('action', 'caption', + 'grid_div_id', 'grid_div_class', 'grid_id', 'grid_setup', + 'nolinks', 'limit'); if (isset($leases)) { $jqGrid_options += array('custom_ids' => @@ -23,9 +26,11 @@ if (isset($leases)) { $leases), 'limit' => 5); } -else { + +if (isset($searchfields)) { $jqGrid_options += array('search_fields' => array('Customer', 'Unit')); } +$jqGrid_options += compact('custom_post_data'); $jqGrid_options['sort_column'] = 'LeaseID'; echo $this->element('jqGrid', $jqGrid_options); From 9aa598f81fa9e16ec509a0a5306b7c3d9b485de5 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 6 Jul 2009 04:32:14 +0000 Subject: [PATCH 219/717] Added a datepicker to the move-out view and put the input fields of both move-in and move-out into a table to tidy things up a bit. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@225 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/leases/move_in.ctp | 11 +++++++++-- site/views/leases/move_out.ctp | 36 +++++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/site/views/leases/move_in.ctp b/site/views/leases/move_in.ctp index e8dcd2b..76be016 100644 --- a/site/views/leases/move_in.ctp +++ b/site/views/leases/move_in.ctp @@ -139,8 +139,15 @@ echo $form->input("Lease.unit_id", 'type' => 'hidden', 'value' => 0)); -echo 'Date:
    ' . "\n"; -echo 'Comment:
    ' . "\n"; +echo $this->element('form_table', + array('class' => "item move-in entry", + 'field_prefix' => 'Lease', + 'fields' => array + ("movein_date" => array('opts' => array('type' => 'text', + 'id' => 'datepicker')), + "comment" => array('opts' => array('size' => 50)), + ))); + echo $form->end('Move In Customer'); ?> diff --git a/site/views/leases/move_out.ctp b/site/views/leases/move_out.ctp index db4a657..bf976ac 100644 --- a/site/views/leases/move_out.ctp +++ b/site/views/leases/move_out.ctp @@ -39,6 +39,17 @@ echo('

    Be sure that you really want to move this customer out, ' . 'and press the "Perform Move Out" button.' . "\n"); echo '


    ' . "\n"; +?> + + + +create(null, array('id' => 'move-out-form', 'url' => array('controller' => 'leases', 'action' => 'move_out'))); @@ -46,7 +57,6 @@ echo $form->create(null, array('id' => 'move-out-form', // REVISIT : 20090702 // Ask how to handle the security deposit // (apply to rent, damages, cleaning, etc). -// Possibly provide a move-out date. // Let user select the next unit status // (DAMAGED, COMPANY, UNAVAILABLE, RESERVED, DIRTY, VACANT) @@ -65,6 +75,14 @@ else { )); } +echo $this->element('form_table', + array('class' => "item move-out entry", + 'field_prefix' => 'Lease', + 'fields' => array + ("moveout_date" => array('opts' => array('type' => 'text', + 'id' => 'datepicker')), + ))); + // Set up a redirect page. I use lower case 'redirect' here // to avoid the model convention, which starts with upper-case. foreach ($redirect AS $name => $value) { @@ -75,6 +93,18 @@ foreach ($redirect AS $name => $value) { } echo $form->end('Perform Move Out'); +?> -// End page div -echo '

    ' . "\n"; + + +
    From 758a5f700c958531f91245b61aaf667f911b35dc Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 6 Jul 2009 15:40:32 +0000 Subject: [PATCH 220/717] Added empty view for debugging. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@226 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/empty.ctp | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 site/views/empty.ctp diff --git a/site/views/empty.ctp b/site/views/empty.ctp new file mode 100644 index 0000000..e69de29 From aa12a1efa440beeeed6d36dd2b9a4798f536c38b Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 6 Jul 2009 15:45:49 +0000 Subject: [PATCH 221/717] Moved the customer save logic into the model git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@227 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/customers_controller.php | 57 ++++--------------- site/models/customer.php | 69 +++++++++++++++++++++++ 2 files changed, 81 insertions(+), 45 deletions(-) diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 4a0bf71..2512555 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -272,7 +272,7 @@ class CustomersController extends AppController { 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'])); @@ -281,56 +281,23 @@ class CustomersController extends AppController { return; } - $this->data['Customer']['primary_contact_id'] - = $this->data['Contact'][$this->data['Customer']['primary_contact_entry']]['id']; - - $this->Customer->create(); - if (!$this->Customer->save($this->data, false)) { - pr("CUSTOMER SAVE FAILED"); - $this->Session->setFlash("CUSTOMER SAVE FAILED", true); - return; - } - $this->data['Customer']['id'] = $this->Customer->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. - $this->Customer->ContactsCustomer->deleteAll - (array('customer_id' => $this->data['Customer']['id']), false); - - if (!isset($this->data['Contact'])) - $this->data['Contact'] = array(); - - // Go through each entry of this customer method + // Go through each customer and strip the bogus ID if new foreach ($this->data['Contact'] AS &$contact) { - - // Check if the user has entered a brand new contact - if (isset($contact['source']) && $contact['source'] === 'new') { + if (isset($contact['source']) && $contact['source'] === 'new') unset($contact['id']); - $I = new Contact(); - $I->create(); - if (!$I->save($contact, false)) { - pr("CONTACT SAVE FAILED"); - $this->Session->setFlash("CONTACT SAVE FAILED", true); - continue; - } - $contact['id'] = $I->id; - } + } - // Update the ContactsCustomer to reflect the appropriate IDs - $contact['ContactsCustomer']['customer_id'] = $this->data['Customer']['id']; - $contact['ContactsCustomer']['contact_id'] = $contact['id']; - - // Save the relationship between customer and contact - $CM = new ContactsCustomer(); - if (!$CM->save($contact['ContactsCustomer'], false)) { - die("ContactsCustomer Save FAILED!"); - } + // 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"); } // Now that the work is done, let the user view the updated customer - $this->redirect(array('action'=>'view', $this->data['Customer']['id'])); - //$this->autoRender = false; + $this->redirect(array('action'=>'view', $this->Customer->id)); + //$this->render('/empty'); return; } diff --git a/site/models/customer.php b/site/models/customer.php index de625c3..2e23a59 100644 --- a/site/models/customer.php +++ b/site/models/customer.php @@ -186,6 +186,75 @@ class Customer extends AppModel { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: stats + * - Returns summary data from the requested customer. + */ + + function saveCustomer($id, $data, $primary_contact_entry) { + $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 : 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); */ + + // Avoid PHP notifications by making sure we have an array + if (!isset($data['Contact'])) + $data['Contact'] = array(); + + // Assume this operation will succeed + $ret = true; + + // Go through each entry of this customer method + foreach ($data['Contact'] AS &$contact) { + + // Check if the user has entered a brand new contact + if (!isset($contact['id'])) { + $I = new Contact(); + $I->create(); + if (!$I->save($contact, false)) { + $ret = false; + continue; + } + $contact['id'] = $I->id; + } + + // 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; + continue; + } + } + + // Set the primary contact ID based on caller selection + if (!$this->saveField('primary_contact_id', + $data['Contact'][$primary_contact_entry]['id'])) + $ret = false; + + // Return the result + return $ret; + } + + /************************************************************************** ************************************************************************** ************************************************************************** From 1d82e263addde0ddd02c473fbd3a2173458ee0a5 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 6 Jul 2009 16:57:23 +0000 Subject: [PATCH 222/717] Changed the logic a little bit in the customer model saveCustomer function, such that we can provide a default customer name if otherwise unspecified. Changed the page titles to reflect Customer vs Contact, since they can easily have the same names. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@228 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/contacts_controller.php | 4 +- site/controllers/customers_controller.php | 18 +++++++- site/models/customer.php | 54 ++++++++++++++--------- 3 files changed, 50 insertions(+), 26 deletions(-) diff --git a/site/controllers/contacts_controller.php b/site/controllers/contacts_controller.php index 845ac5c..08cd291 100644 --- a/site/controllers/contacts_controller.php +++ b/site/controllers/contacts_controller.php @@ -87,7 +87,7 @@ class ContactsController extends AppController { $id)); // Prepare to render. - $title = $contact['Contact']['display_name']; + $title = 'Contact: ' . $contact['Contact']['display_name']; $this->set(compact('contact', 'title')); } @@ -192,7 +192,7 @@ class ContactsController extends AppController { 'conditions' => array('Contact.id' => $id), )); - $title = $this->data['Contact']['display_name'] . " : Edit"; + $title = 'Contact: ' . $this->data['Contact']['display_name'] . " : Edit"; } else { $title = "Enter New Contact"; diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 2512555..d233067 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -256,7 +256,7 @@ class CustomersController extends AppController { } // Prepare to render. - $title = $customer['Customer']['name']; + $title = 'Customer: ' . $customer['Customer']['name']; $this->set(compact('customer', 'title', 'outstanding_balance', 'outstanding_deposit')); @@ -281,6 +281,20 @@ class CustomersController extends AppController { return; } + // Make sure we have at least one contact + if (!isset($this->data['Contact']) || count($this->data['Contact']) == 0) { + $this->Session->setFlash("MUST SPECIFY AT LEAST ONE CONTACT", true); + $this->redirect(array('action'=>'view', $this->data['Customer']['id'])); + return; + } + + // Make sure there is a primary contact + if (!isset($this->data['Customer']['primary_contact_entry'])) { + $this->Session->setFlash("MUST SPECIFY A PRIMARY CONTACT", true); + $this->redirect(array('action'=>'view', $this->data['Customer']['id'])); + return; + } + // Go through each customer and strip the bogus ID if new foreach ($this->data['Contact'] AS &$contact) { if (isset($contact['source']) && $contact['source'] === 'new') @@ -303,7 +317,7 @@ class CustomersController extends AppController { if ($id) { $this->data = $this->Customer->details($id); - $title = $this->data['Customer']['name'] . " : Edit"; + $title = 'Customer: ' . $this->data['Customer']['name'] . " : Edit"; } else { $title = "Enter New Customer"; diff --git a/site/models/customer.php b/site/models/customer.php index 2e23a59..02c0ac7 100644 --- a/site/models/customer.php +++ b/site/models/customer.php @@ -194,6 +194,33 @@ class Customer extends AppModel { */ function saveCustomer($id, $data, $primary_contact_entry) { + + // Go through each contact, and create new ones as needed + foreach ($data['Contact'] AS &$contact) { + if (isset($contact['id'])) + continue; + + $I = new Contact(); + $I->create(); + if (!$I->save($contact, false)) { + return false; + } + $contact['id'] = $I->id; + } + + // Set the primary contact ID based on caller selection + $data['Customer']['primary_contact_id'] + = $data['Contact'][$primary_contact_entry]['id']; + + // Provide a default customer name if not specified + if (!$data['Customer']['name']) { + $this->Contact->recursive = -1; + $pcontact = $this->Contact->read(null, $data['Customer']['primary_contact_id']); + pr($pcontact); + $data['Customer']['name'] = $pcontact['Contact']['display_name']; + } + + // Save the customer data $this->create(); if ($id) $this->id = $id; @@ -212,26 +239,15 @@ class Customer extends AppModel { /* $this->ContactsCustomer->deleteAll */ /* (array('customer_id' => $id), false); */ - // Avoid PHP notifications by making sure we have an array - if (!isset($data['Contact'])) - $data['Contact'] = array(); - - // Assume this operation will succeed + // 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; // Go through each entry of this customer method foreach ($data['Contact'] AS &$contact) { - - // Check if the user has entered a brand new contact - if (!isset($contact['id'])) { - $I = new Contact(); - $I->create(); - if (!$I->save($contact, false)) { - $ret = false; - continue; - } - $contact['id'] = $I->id; - } + pr(compact('contact')); // Update the ContactsCustomer to reflect the appropriate IDs $contact['ContactsCustomer']['customer_id'] = $id; @@ -241,15 +257,9 @@ class Customer extends AppModel { $CM = new ContactsCustomer(); if (!$CM->save($contact['ContactsCustomer'], false)) { $ret = false; - continue; } } - // Set the primary contact ID based on caller selection - if (!$this->saveField('primary_contact_id', - $data['Contact'][$primary_contact_entry]['id'])) - $ret = false; - // Return the result return $ret; } From fbeed43e61f441ab4c4dcda87997fd144092ae65 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 6 Jul 2009 16:59:13 +0000 Subject: [PATCH 223/717] Fixed comment block git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@229 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/customer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/models/customer.php b/site/models/customer.php index 02c0ac7..3761c49 100644 --- a/site/models/customer.php +++ b/site/models/customer.php @@ -189,8 +189,8 @@ class Customer extends AppModel { /************************************************************************** ************************************************************************** ************************************************************************** - * function: stats - * - Returns summary data from the requested customer. + * function: saveCustomer + * - Saves the customer and related data */ function saveCustomer($id, $data, $primary_contact_entry) { From cba8e16be766e8b372f56accca44f5b5af41ffd8 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 6 Jul 2009 17:25:05 +0000 Subject: [PATCH 224/717] Moved the contact save logic into the model and out of the controller. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@230 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/contacts_controller.php | 73 +++-------------- site/models/contact.php | 100 +++++++++++++++++++++-- site/models/customer.php | 2 +- 3 files changed, 107 insertions(+), 68 deletions(-) diff --git a/site/controllers/contacts_controller.php b/site/controllers/contacts_controller.php index 08cd291..19be865 100644 --- a/site/controllers/contacts_controller.php +++ b/site/controllers/contacts_controller.php @@ -110,72 +110,23 @@ class ContactsController extends AppController { return; } - if (!$this->data['Contact']['display_name']) - $this->data['Contact']['display_name'] = - (($this->data['Contact']['first_name'] && - $this->data['Contact']['last_name']) - ? $this->data['Contact']['last_name'] . ', ' . $this->data['Contact']['first_name'] - : ($this->data['Contact']['first_name'] - ? $this->data['Contact']['first_name'] - : $this->data['Contact']['last_name'])); - - $this->Contact->create(); - if (!$this->Contact->save($this->data, false)) { - pr("CONTACT SAVE FAILED"); - $this->Session->setFlash("CONTACT SAVE FAILED", true); - return; - } - $this->data['Contact']['id'] = $this->Contact->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. - $this->Contact->ContactsMethod->deleteAll - (array('contact_id' => $this->data['Contact']['id']), false); - - // 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($this->data[$class])) - continue; - - // Go through each entry of this contact method - foreach ($this->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['source']) && $item['source'] === 'new') { - unset($item['id']); - $I = new $class(); - $I->create(); - if (!$I->save($item, false)) { - pr("$enum SAVE FAILED"); - $this->Session->setFlash("$enum SAVE FAILED", true); - continue; - } - $item['id'] = $I->id; - } - - // Update the ContactsMethod to reflect the appropriate IDs - $item['ContactsMethod']['contact_id'] = $this->data['Contact']['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)) { - die("ContactsMethod Save FAILED!"); - } + // Go through each contact method and strip the bogus ID if new + foreach (array_intersect_key($this->data, + array('ContactPhone'=>1, + 'ContactAddress'=>1, + 'ContactEmail'=>1)) AS $type => $arr) { + foreach ($arr AS $idx => $item) { + if (isset($item['source']) && $item['source'] === 'new') + unset($this->data[$type][$idx]['id']); } } + // Save the contact and all associated data + $this->Contact->saveContact($this->data['Contact']['id'], $this->data); + // Now that the work is done, let the user view the updated contact $this->redirect(array('action'=>'view', $this->data['Contact']['id'])); - //$this->autoRender = false; + //$this->render('/empty'); return; } diff --git a/site/models/contact.php b/site/models/contact.php index 6e7c69e..f611803 100644 --- a/site/models/contact.php +++ b/site/models/contact.php @@ -37,12 +37,100 @@ class Contact extends AppModel { ), ); - function contactList() { - return $this->find('list', - array('order' => - //array('last_name', 'first_name', 'middle_name'), - array('display_name'), - )); + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * 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 : 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'), + )); + } + } ?> \ No newline at end of file diff --git a/site/models/customer.php b/site/models/customer.php index 3761c49..9ef4ea8 100644 --- a/site/models/customer.php +++ b/site/models/customer.php @@ -239,7 +239,7 @@ class Customer extends AppModel { /* $this->ContactsCustomer->deleteAll */ /* (array('customer_id' => $id), false); */ - // At this point, since we've saved data to contact, + // 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. From cd07f51ff9e8c4c697ed8468c23cf76c3572077b Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 6 Jul 2009 18:34:44 +0000 Subject: [PATCH 225/717] First pass at entering charges for a lease. This works, but does not have the ability to add multiple charges, and does not mirror the payment method, which is ajax based. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@231 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_model.php | 12 ++ site/controllers/leases_controller.php | 62 +++++++- site/controllers/transactions_controller.php | 159 +++++++++++++++++++ site/models/account.php | 1 + site/models/lease.php | 13 ++ site/models/transaction.php | 2 +- site/views/elements/form_table.ctp | 4 +- site/views/leases/assess.ctp | 155 ++++++++++++++++++ 8 files changed, 405 insertions(+), 3 deletions(-) create mode 100644 site/views/leases/assess.ctp diff --git a/site/app_model.php b/site/app_model.php index 12d1f58..c06ec08 100644 --- a/site/app_model.php +++ b/site/app_model.php @@ -40,6 +40,7 @@ class AppModel extends Model { var $actsAs = array('Containable', 'Linkable'); var $useNullForEmpty = true; + var $dateFields = array(); /** * Get Enum Values @@ -155,6 +156,17 @@ class AppModel extends Model { // override the behavior, or set useNullForEmpty to false. if ($this->useNullForEmpty) $this->recursive_array_replace("/^\s*$/", null, $this->data); + + foreach ($this->dateFields AS $field) { +/* if(isset($this->data['Transaction']['stamp']) && */ +/* $this->data['Transaction']['stamp'] !== 'CURRENT_TIMESTAMP') { */ +/* $this->data['Transaction']['stamp'] = */ +/* $this->dateFormatBeforeSave($this->data['Transaction']['stamp']); */ +/* } */ +/* else { */ +/* $this->data['Transaction']['stamp'] = null; */ + } + return true; } diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index 08293ec..d930fd9 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -125,7 +125,7 @@ class LeasesController extends AppController { function move_out($id = null) { if ($this->data) { // Handle the move out based on the data given - pr($this->data); + //pr($this->data); $this->Lease->moveOut($this->data['Lease']['id']); $this->redirect($this->data['redirect']); @@ -166,6 +166,58 @@ class LeasesController extends AppController { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: assess + * - Assesses charges to the lease + */ + + function assess($id = null, $type = null) { + if ($this->data) { + // Assess the charges based on the given data + pr($this->data); + + $this->Lease->addCharge($this->data['Lease']['id'], $this->data['Charge']); + //$this->redirect($this->data['redirect']); + $this->render('/empty'); + return; + } + + $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), + ), + )); + + $charge['type'] = $type; + if ($type == 'rent') + $charge['amount'] = $lease['Lease']['rent']; + else + // REVISIT 20090705: + // Of course, the late charge should come from the late_schedule + $charge['amount'] = 10.00; + + $title = ('Lease #' . $lease['Lease']['number'] . ': ' . + $lease['Unit']['name'] . ': ' . + $lease['Customer']['name'] . ': Assess Charges'); + $this->set(compact('title', 'lease', 'charge')); + } + + /************************************************************************** ************************************************************************** ************************************************************************** @@ -206,6 +258,14 @@ class LeasesController extends AppController { $this->sidemenu_links[] = array('name' => 'Operations', 'header' => true); + $this->sidemenu_links[] = + array('name' => 'Assess Rent', 'url' => array('action' => 'assess', + $id, 'rent')); + + $this->sidemenu_links[] = + array('name' => 'Assess Late Charge', 'url' => array('action' => 'assess', + $id, 'late')); + if (!isset($lease['Lease']['moveout_date'])) { $this->sidemenu_links[] = array('name' => 'Move-Out', 'url' => array('action' => 'move_out', diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php index 8f182cf..5c031bc 100644 --- a/site/controllers/transactions_controller.php +++ b/site/controllers/transactions_controller.php @@ -95,6 +95,165 @@ class TransactionsController extends AppController { $this->set(compact('transaction', 'title', 'total')); } + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: postInvoice + * - handles the creation of a charge invoice + */ + + function postInvoice() { + if (!$this->RequestHandler->isPost()) { + echo('

    THIS IS NOT A POST FOR SOME REASON

    '); + return; + } + + pr($this->data); + +/* $this->layout = null; */ +/* $this->autoLayout = false; */ +/* $this->autoRender = false; */ +/* Configure::write('debug', '0'); */ + + // Sanitize the transaction data + if (!$this->data['Transaction']['comment']) + $this->data['Transaction']['comment'] = null; + + if(empty($this->data['Transaction']['stamp'])) { + die("Time/Date not valid"); + } + pr($this->data['Transaction']); + + // Create some models for convenience + $A = new Account(); + $C = new Customer(); + $L = new Lease(); + + $L->recursive = -1; + $lease = $L->read(null, $this->data['Lease']['id']); + + // Create a transaction for the invoice + $invoice_transaction = new Transaction(); + $invoice_transaction->create(); + if (!$invoice_transaction->save($this->data['Transaction'], + array('validate' => false, + ))) { + pr(array('checkpoint' => "invoice transaction save failed")); + return; + die("Unknown Database Failure"); + } + pr("New Transaction Created ({$invoice_transaction->id})!"); + $invoice_transaction->read(); + pr($invoice_transaction->data); + + // Create a transaction for the A/R + $ar_transaction = new Transaction(); + $ar_transaction->create(); + if (!$ar_transaction->save($this->data['Transaction'], + array('validate' => false, + ))) { + pr(array('checkpoint' => "A/R transaction save failed")); + die("Unknown Database Failure"); + } + pr("New Transaction Created ({$ar_transaction->id})!"); + $ar_transaction->read(); + pr($ar_transaction->data); + + // Go through the entered charges + $grand_total = 0; + foreach ($this->data['LedgerEntry'] AS &$entry) { + pr(compact('entry')); + + // Invoice Transaction + // debit: Invoice credit: Charge + $entry['transaction_id'] = $invoice_transaction->id; + + // Invoice must debit the "invoice" asset... + $entry['debit_ledger_id'] + = $A->currentLedgerID($A->invoiceAccountID()); + + // ...and credit the charge ledger + // REVISIT 20090706 + // The charge page should have a list of all income types + // and thus the field _should_ contain a valid account + // name. At the moment, however, I'm still cobbling things + // together, and only have two types. +/* $entry['credit_ledger_id'] */ +/* = $A->currentLedgerID($A->nameToID($entry['charge_account'])); */ + if ($entry['charge_type'] === 'rent') { + $entry['credit_ledger_id'] + = $A->currentLedgerID($A->rentAccountID()); + } elseif ($entry['charge_type'] === 'late') { + $entry['credit_ledger_id'] + = $A->currentLedgerID($A->lateChargeAccountID()); + } else { + die("Invalid charge account"); + } + + $entry['customer_id'] + = $lease['Lease']['customer_id']; + $entry['lease_id'] + = $lease['Lease']['id']; + + // Create it + $invoice_entry = new LedgerEntry(); + $invoice_entry->create(); + if (!$invoice_entry->save($entry, false)) { + pr(array('checkpoint' => "invoice entry saveAll failed")); + die("Unknown Database Failure"); + } + pr("New Invoice LedgerEntry Created ({$invoice_entry->id})!"); + $invoice_entry->read(); + pr($invoice_entry->data); + + $grand_total += $entry['amount']; + } + + // Create an account receivable entry + // debit: A/R credit: Invoice + $ar_entry_data = array + ('debit_ledger_id' => $A->currentLedgerID($A->accountReceivableAccountID()), + 'credit_ledger_id' => $A->currentLedgerID($A->invoiceAccountID()), + 'transaction_id' => $ar_transaction->id, + 'amount' => $grand_total, + 'lease_id' => $lease['Lease']['id'], + 'customer_id' => $lease['Lease']['customer_id'], + ); + + // Create a new A/R entry from the data + $ar_entry = new LedgerEntry(); + $ar_entry->create(); + if (!$ar_entry->save($ar_entry_data, false)) { + pr(array('checkpoint' => "ar entry save failed")); + die("Unknown Database Failure"); + } + pr("New A/R LedgerEntry Created ({$ar_entry->id})!"); + $ar_entry->read(); + pr($ar_entry->data); + + // Reconcile the Invoice account. Our two entries look like: + // debit: Invoice credit: Charge + // debit: A/R credit: Invoice + // Since this is from the perspective of the Invoice account, + // the credit entry is the Invoice<->A/R, and the debit + // entry is the actual invoice ledger entry. + $R = new Reconciliation(); + $R->create(); + if (!$R->save(array('debit_ledger_entry_id' => $invoice_entry->id, + 'credit_ledger_entry_id' => $ar_entry->id, + 'amount' => $grand_total), false)) { + pr(array('checkpoint' => "invoice reconcile save failed")); + die("Unknown Database Failure"); + } + pr("New Invoice Reconciliation Created ({$R->id})!"); + $R->read(); + pr($R->data); + + $this->render('/empty'); + } + + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/models/account.php b/site/models/account.php index f3541f5..da02936 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -94,6 +94,7 @@ class Account extends AppModel { function securityDepositAccountID() { return $this->nameToID('Security Deposit'); } function rentAccountID() { return $this->nameToID('Rent'); } + function lateChargeAccountID() { return $this->nameToID('Late Charge'); } function accountReceivableAccountID() { return $this->nameToID('A/R'); } function invoiceAccountID() { return $this->nameToID('Invoice'); } function receiptAccountID() { return $this->nameToID('Receipt'); } diff --git a/site/models/lease.php b/site/models/lease.php index 631e14f..c3628a6 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -266,6 +266,19 @@ class Lease extends AppModel { $this->Unit->updateStatus($this->data['Lease']['unit_id'], $status); } + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: addCharge + * - Adds an additional charge to the lease + */ + + function addCharge($id, $charge) { + + } + + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/models/transaction.php b/site/models/transaction.php index e7ccb03..e2af783 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -25,7 +25,7 @@ class Transaction extends AppModel { $this->data['Transaction']['stamp'] = null; } - return true; + return parent::beforeSave(); } } diff --git a/site/views/elements/form_table.ctp b/site/views/elements/form_table.ctp index c3c15bc..7085238 100644 --- a/site/views/elements/form_table.ctp +++ b/site/views/elements/form_table.ctp @@ -16,7 +16,9 @@ foreach ($fields AS $field => $config) { if (!isset($config['opts'])) $config['opts'] = null; - if (isset($field_prefix) && !isset($config['no_prefix'])) + if (isset($config['prefix']) && !isset($config['no_prefix'])) + $field = $config['prefix'] . '.' . $field; + elseif (isset($field_prefix) && !isset($config['no_prefix'])) $field = $field_prefix . '.' . $field; $config['opts']['label'] = false; diff --git a/site/views/leases/assess.ctp b/site/views/leases/assess.ctp new file mode 100644 index 0000000..655b59e --- /dev/null +++ b/site/views/leases/assess.ctp @@ -0,0 +1,155 @@ + + +
    + + 'function(ids) { if (ids != null) { onRowSelect("#"+$(this).attr("id"), ids); } }' + ); + +$lease_grid_setup['onHeaderClick'] = array + ('--special' => + 'function(gridstate) { onGridState("#"+$(this).attr("id"), gridstate); }' + ); + +?> + + + +element('leases', + array('grid_div_id' => 'leases-list', + 'grid_div_class' => 'text-below', + 'caption' => ('Select Lease'), + 'grid_setup' => $lease_grid_setup, + 'nolinks' => true, + 'limit' => 10, + )); + +echo ('

    ' . + 'Lease: ' . + 'Please select lease' . + '

    ' . "\n"); + + +echo $form->create(null, array('id' => 'assess-form', + 'url' => array('controller' => 'transactions', + 'action' => 'postInvoice'))); + +echo $form->input("Lease.id", + array('id' => 'lease-id', + 'type' => 'hidden', + 'value' => 0)); + +echo $this->element('form_table', + array('class' => "item assess entry", + 'field_prefix' => 'Transaction', + 'fields' => array + ("stamp" => array('opts' => array('id' => 'charge_date', + 'type' => 'text')), + "through_date" => array('opts' => array('id' => 'through_date', + 'type' => 'text')), + "charge_type" => array('prefix' => 'LedgerEntry.0', + 'opts' => + array('options' => + array('rent' => 'Rent', + 'late' => 'Late Charge'), + 'value' => $charge['type'])), + "amount" => array('prefix' => 'LedgerEntry.0', + 'opts' => + array('value' => $charge['amount'])), + "comment" => array('opts' => array('size' => 50)), + ))); + +echo $form->end('Assess Charge'); + +?> + + + +
    From cb39f6f0eb975c45f5d281da7feae391026b2502 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 6 Jul 2009 19:22:27 +0000 Subject: [PATCH 226/717] Modified the form table to support a variety of extra texts and/or columns git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@232 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/form_table.ctp | 95 ++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 5 deletions(-) diff --git a/site/views/elements/form_table.ctp b/site/views/elements/form_table.ctp index 7085238..e51a80e 100644 --- a/site/views/elements/form_table.ctp +++ b/site/views/elements/form_table.ctp @@ -8,6 +8,40 @@ * @package pmgr */ +$include_before = false; +if (isset($before) && $before) + $include_before = true; +foreach ($fields AS $field => $config) { + if (isset($config['before'])) + $include_before = true; +} + +$include_between = false; +if (isset($between) && $between) + $include_between = true; +foreach ($fields AS $field => $config) { + if (isset($config['between'])) + $include_between = true; +} + +$include_after = false; +if (isset($after) && $after) + $include_after = true; +foreach ($fields AS $field => $config) { + if (isset($config['after'])) + $include_after = true; +} + + +$column_class = array(); +if ($include_before) + $column_class[] = 'before'; +$column_class[] = 'field'; +if ($include_between) + $column_class[] = 'between'; +$column_class[] = 'value'; +if ($include_after) + $column_class[] = 'after'; $rows = array(); foreach ($fields AS $field => $config) { @@ -22,12 +56,63 @@ foreach ($fields AS $field => $config) { $field = $field_prefix . '.' . $field; $config['opts']['label'] = false; - $rows[] = array($config['name'], - $form->input($field, $config['opts'])); + $config['opts']['div'] = false; + + $cells = array(); + if ($include_before) { + if (isset($config['before'])) + $cells[] = $config['before']; + elseif (isset($before) && $before) + $cells[] = $before; + else + $cells[] = null; + } + + $name = $config['name']; + if (isset($config['with_name_before'])) + $name = $config['with_name_before'] . $name; + elseif (isset($with_name_before)) + $name = $with_name_before . $name; + if (isset($config['with_name_after'])) + $name = $name . $config['with_name_after']; + elseif (isset($with_name_after)) + $name = $name . $with_name_after; + $cells[] = $name; + + if ($include_between) { + if (isset($config['between'])) + $cells[] = $config['between']; + elseif (isset($between) && $between) + $cells[] = $between; + else + $cells[] = null; + } + + $value = $form->input($field, $config['opts']); + if (isset($config['with_value_before'])) + $value = $config['with_value_before'] . $value; + elseif (isset($with_value_before)) + $value = $with_value_before . $value; + if (isset($config['with_value_after'])) + $value = $value . $config['with_value_after']; + elseif (isset($with_value_after)) + $value = $valeu . $with_value_after; + $cells[] = $value; + + if ($include_after) { + if (isset($config['after'])) + $cells[] = $config['after']; + elseif (isset($after) && $after) + $cells[] = $after; + else + $cells[] = null; + } + + $rows[] = $cells; } echo $this->element('table', compact('class', 'caption', 'headers', - 'rows', 'row_class', 'suppress_alternate_rows') + - array('column_class' => array('field', 'value'), - )); + 'rows', 'row_class', 'suppress_alternate_rows', + 'column_class') + ); From 240a16367bf1eb6df4b590030e06ab391bbaf7aa Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 6 Jul 2009 22:23:40 +0000 Subject: [PATCH 227/717] Moved date formatting fully into the AppModel, automatically determining the necessary fields from the schema. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@233 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_model.php | 35 ++++++++++++++++++++++++++--------- site/models/lease.php | 15 --------------- site/models/transaction.php | 22 ++++------------------ 3 files changed, 30 insertions(+), 42 deletions(-) diff --git a/site/app_model.php b/site/app_model.php index c06ec08..f246e69 100644 --- a/site/app_model.php +++ b/site/app_model.php @@ -40,7 +40,7 @@ class AppModel extends Model { var $actsAs = array('Containable', 'Linkable'); var $useNullForEmpty = true; - var $dateFields = array(); + var $formatDateFields = true; /** * Get Enum Values @@ -151,21 +151,38 @@ class AppModel extends Model { } 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); - foreach ($this->dateFields AS $field) { -/* if(isset($this->data['Transaction']['stamp']) && */ -/* $this->data['Transaction']['stamp'] !== 'CURRENT_TIMESTAMP') { */ -/* $this->data['Transaction']['stamp'] = */ -/* $this->dateFormatBeforeSave($this->data['Transaction']['stamp']); */ -/* } */ -/* else { */ -/* $this->data['Transaction']['stamp'] = null; */ + 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]['stamp'] === '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; } diff --git a/site/models/lease.php b/site/models/lease.php index c3628a6..8bf7acd 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -34,21 +34,6 @@ class Lease extends AppModel { ); - function beforeSave() { - foreach (array('lease', - 'movein', 'movein_planned', - 'moveout', 'moveout_planned', - 'notice_givein', 'notice_received', - 'close', 'next_rent') AS $dtfield) { - $dtfield .= '_date'; - if(isset($this->data['Lease'][$dtfield])) - $this->data['Lease'][$dtfield] = - $this->dateFormatBeforeSave($this->data['Lease'][$dtfield]); - } - - return true; - } - /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/models/transaction.php b/site/models/transaction.php index e2af783..e471b62 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -2,9 +2,10 @@ class Transaction extends AppModel { var $name = 'Transaction'; -/* var $validate = array( */ -/* 'stamp' => array('date') */ -/* ); */ + + var $validate = array( + 'stamp' => array('date') + ); var $belongsTo = array( ); @@ -13,20 +14,5 @@ class Transaction extends AppModel { 'LedgerEntry', ); - - function beforeSave() { - - if(isset($this->data['Transaction']['stamp']) && - $this->data['Transaction']['stamp'] !== 'CURRENT_TIMESTAMP') { - $this->data['Transaction']['stamp'] = - $this->dateFormatBeforeSave($this->data['Transaction']['stamp']); - } - else { - $this->data['Transaction']['stamp'] = null; - } - - return parent::beforeSave(); - } - } ?> \ No newline at end of file From eba1267f00cbcd353fa1c79266be0a6b68a5d787 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 6 Jul 2009 23:17:53 +0000 Subject: [PATCH 228/717] Moved the debug grid query link into the caption bar to minimize layout distractions. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@234 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/jqGrid.ctp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/site/views/elements/jqGrid.ctp b/site/views/elements/jqGrid.ctp index 6ed8e8c..c4bb5d9 100644 --- a/site/views/elements/jqGrid.ctp +++ b/site/views/elements/jqGrid.ctp @@ -161,6 +161,9 @@ if (isset($sort_order)) { $sortorder = 'ASC'; } +if (1) { // debug + $caption .= ' :: '; +} // Configure the grid setup, giving priority to user defined parameters $jqGrid_setup = array_merge @@ -196,7 +199,6 @@ $jqGrid_setup = array_merge
    -
    @@ -356,11 +330,24 @@ function onRowSelect(grid_id, cust_id) { echo $this->element('customers', array('grid_div_id' => 'customers-list', + 'grid_div_class' => 'text-below', 'caption' => ('Select Customer'), 'grid_setup' => $grid_setup, + 'nolinks' => true, + 'limit' => 10, )); +echo ('

    ' . + '' . + '' . + '

    ' . "\n"); + echo $this->element('ledger_entries', array('grid_div_id' => 'charge-entries', 'caption' => 'Outstanding Charges', @@ -369,107 +356,72 @@ echo $this->element('ledger_entries', 'limit' => 8, )); -echo ('

    ' . - '' . - 'Enter new receipt for ' . - '' . (isset($customer['name']) ? $customer['name'] : "") . '' . - '' . - '' . - 'Please select customer' . - '' . - '

    ' . "\n"); - -echo $form->create(null, array('id' => 'payment-form', +echo $form->create(null, array('id' => 'receipt-form', 'url' => array('controller' => 'transactions', 'action' => 'postReceipt'))); -/*************************************************** - * Post data should look like this: - * - * data => Array - * ( - * [Transaction] => Array - * ( - * stamp => - * through_date => - * due_date => - * comment => - * ) - * - * [LedgerEntry] => Array - * ( - * [0] => Array - * ( - * name => - * amount => - * debit_ledger_id => - * credit_ledger_id => - * comment => - * - * [MonetarySource] => Array - * ( - * name => - * monetary_type_id => - * comment => - * ) - * - * REVISIT: Reconciliations will be tricker. - * ) - * - * ) - * - * ) - * - ***************************************************/ +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' => 'Now', + ), + "comment" => array('opts' => array('size' => 50), + ), + ))); + +echo $form->submit('Generate Receipt') . "\n"; ?> -
    Payments - +
    Add Another Payment
    -end('Generate Receipt'); ?> -echo 'Date: '; -echo ' Now
    ' . "\n"; -echo 'Comment:
    ' . "\n"; -echo $form->end('Post Payment'); - -//echo '
    ' . "\n"; // End of the dialog DIV -?> - -Create Payment */ -?> +' . "\n"; // End of the dialog DIV */ ?>

    Request

    Response

    Output

    - diff --git a/site/webroot/js/pmgr.js b/site/webroot/js/pmgr.js index 5b4bde7..0ead35a 100644 --- a/site/webroot/js/pmgr.js +++ b/site/webroot/js/pmgr.js @@ -139,6 +139,48 @@ function fmtCurrency(amount) { } +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// +// +// Datepicker helpers + +function datepickerNow(id) { + now = new Date(); + // datepicker seems to squash the time portion, + // so we have to pass in a copy of now instead. + $("#"+id).datepicker('setDate', new Date(now)); + $("#"+id).val($("#"+id).val() + + ' ' + + (now.getHours() < 10 ? '0' : '') + + now.getHours() + ':' + + (now.getMinutes() < 10 ? '0' : '') + + now.getMinutes()); +} + +function datepickerSet(fromid, id, a, b) { + if (fromid == null) + dt = new Date(); + else + dt = new Date($("#"+fromid).datepicker('getDate')); + + if (a != null) + dt.setDate(a); + if (b != null) + dt.setDate(b); + + $("#"+id).datepicker('setDate', dt); +} + +function datepickerBOM(fromid, id) { + datepickerSet(fromid, id, 1); +} + +function datepickerEOM(fromid, id) { + datepickerSet(fromid, id, 32, 0); +} + + // REVISIT : 20090617 // I would rather use XML to pass from JS to PHP, but at the // moment things were working just fine with serialize, and From e17cf213519f25d8b4e5ff0f1a4845eb07d1a48e Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 7 Jul 2009 04:29:34 +0000 Subject: [PATCH 234/717] Removed the debug comments for each invoice/receipt/payment/charge/etc git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@240 97e9348a-65ac-dc4b-aefc-98561f571b83 --- scripts/sitelink2pmgr.pl | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 2beb5df..99682e1 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -929,7 +929,8 @@ foreach $row (@{query($sdbh, $query)}) { 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'customer_id'}, 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'lease_id'}, 'amount' => $row->{'InvoiceAmount'}, - 'comment' => "Invoice: Charge: $row->{'ChargeID'}" }); + #'comment' => "Invoice: Charge: $row->{'ChargeID'}", + }); $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'} = $newdb{'tables'}{'ledger_entries'}{'autoid'}; @@ -967,7 +968,8 @@ foreach $row (@{query($sdbh, $query)}) { 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, 'amount' => $row->{'ChargeAmount'}, - 'comment' => "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}" }); + #'comment' => "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}", + }); $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'} = $newdb{'tables'}{'ledger_entries'}{'autoid'}; @@ -996,7 +998,8 @@ foreach $row (@{query($sdbh, $query)}) { 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, 'amount' => $row->{'TaxAmount'}, - 'comment' => "Tax for ChargeID:$row->{'ChargeID'}" }); + #'comment' => "Tax for ChargeID:$row->{'ChargeID'}", + }); $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tax_ledger_entry_id'} = $newdb{'tables'}{'ledger_entries'}{'autoid'}; @@ -1158,7 +1161,8 @@ foreach $row (@{query($sdbh, $query)}) { { 'monetary_type_id' => $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'monetary_type'}{'id'}, 'name' => $name, 'data1' => $data1, - 'comment' => "Receipt:$row->{'ReceiptNum'}; Payment:$row->{'PaymentType'}; Check:$row->{'CheckNum'}" }); + #'comment' => "Receipt:$row->{'ReceiptNum'}; Payment:$row->{'PaymentType'}; Check:$row->{'CheckNum'}", + }); $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'} = $newdb{'tables'}{'monetary_sources'}{'autoid'}; @@ -1185,7 +1189,8 @@ foreach $row (@{query($sdbh, $query)}) { 'debit_ledger_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'debit_ledger_id'}, 'credit_ledger_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'credit_ledger_id'}, 'amount' => $row->{'ReceiptAmount'}, - 'comment' => "Receipt: $row->{'ReceiptNum'}; " }); + #'comment' => "Receipt: $row->{'ReceiptNum'}; ", + }); $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'} = $newdb{'tables'}{'ledger_entries'}{'autoid'}; @@ -1240,7 +1245,8 @@ foreach $row (@{query($sdbh, $query)}) 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, 'amount' => $row->{'PaymentAmount'}, - 'comment' => "Receipt: $row->{'ReceiptNum'}; Charge: $row->{'ChargeID'}; Payment: $row->{'PaymentID'}" }); + #'comment' => "Receipt: $row->{'ReceiptNum'}; Charge: $row->{'ChargeID'}; Payment: $row->{'PaymentID'}", + }); $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} = $newdb{'tables'}{'ledger_entries'}{'autoid'}; From 7b3f77430407e0cdc252868c00241578c6bdc162 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 7 Jul 2009 04:33:06 +0000 Subject: [PATCH 235/717] The only functional change was to start payment numbers at 1 instead of zero. All other changes are just white space and code movement. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@241 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/customers/receipt.ctp | 254 +++++++++++++++---------------- 1 file changed, 125 insertions(+), 129 deletions(-) diff --git a/site/views/customers/receipt.ctp b/site/views/customers/receipt.ctp index 33e96a9..541de02 100644 --- a/site/views/customers/receipt.ctp +++ b/site/views/customers/receipt.ctp @@ -60,111 +60,148 @@ $grid_setup['onHeaderClick'] = array $('#receipt-form').ajaxForm(options); }); - // pre-submit callback - function verifyRequest(formData, jqForm, options) { - // formData is an array; here we use $.param to convert it to a string to display it - // but the form plugin does this for you automatically when it submits the data - //var_dump(formData); - //$('#request-debug').html('
    '+dump(formData)+'
    '); - $('#request-debug').html('Ommitted'); - //return false; +// pre-submit callback +function verifyRequest(formData, jqForm, options) { + // formData is an array; here we use $.param to convert it to a string to display it + // but the form plugin does this for you automatically when it submits the data + //var_dump(formData); + //$('#request-debug').html('
    '+dump(formData)+'
    '); + $('#request-debug').html('Ommitted'); + //return false; - $('#response-debug').html('Loading ...'); - $('#output-debug').html('Loading ...'); + $('#response-debug').html('Loading ...'); + $('#output-debug').html('Loading ...'); - // 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; - } + // 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) { - // for normal html responses, the first argument to the success callback - // is the XMLHttpRequest object's responseText property +// post-submit callback +function showResponse(responseText, statusText) { + // for normal html responses, the first argument to the success callback + // is the XMLHttpRequest object's responseText property - // if the ajaxForm method was passed an Options Object with the dataType - // property set to 'xml' then the first argument to the success callback - // is the XMLHttpRequest object's responseXML property + // if the ajaxForm method was passed an Options Object with the dataType + // property set to 'xml' then the first argument to the success callback + // is the XMLHttpRequest object's responseXML property - // if the ajaxForm method was passed an Options Object with the dataType - // property set to 'json' then the first argument to the success callback - // is the json data object returned by the server + // if the ajaxForm method was passed an Options Object with the dataType + // property set to 'json' then the first argument to the success callback + // is the json data object returned by the server - if (statusText == 'success') { - // get a clean slate - //resetForm(); - } - else { - alert('not successful??'); - } - - - $('#response-debug').html('
    '+dump(statusText)+'
    '); + if (statusText == 'success') { + // get a clean slate + //resetForm(); + } + else { + alert('not successful??'); } - // Reset the form - function resetForm() { - $('#payment-entry-id').val(0); - $('#payments').html(''); - $("#receipt-customer-id").html("INTERNAL ERROR"); - $("#receipt-customer-name").html("INTERNAL ERROR"); + $('#response-debug').html('
    '+dump(statusText)+'
    '); +} - addPaymentSource(false); - datepickerNow('TransactionStamp'); +// Reset the form +function resetForm() { + $('#payment-entry-id').val(1); + $('#payments').html(''); + + $("#receipt-customer-id").html("INTERNAL ERROR"); + $("#receipt-customer-name").html("INTERNAL ERROR"); + + addPaymentSource(false); + datepickerNow('TransactionStamp'); +} + +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')); + $("#receipt-customer-name").html($(grid_id).getCell(customer_id, 'Customer-name')); + + // Make sure the redirect is up to date, if necessary + if ($("#redirectController").val() == 'customers') + $("#redirect0").val(customer_id); + + // Hide the "no customer" message and show the current customer + $("#no-customer").hide(); + $("#current-customer").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') { + $("#no-customer").hide(); + $("#current-customer").hide(); } + else { + if ($("#customer-id").val() > 0) { + $("#current-customer").show(); + $("#no-customer").hide(); + } else { + $("#current-customer").hide(); + $("#no-customer").show(); + } + } +} - function addPaymentSource(flash) { - addDiv('payment-entry-id', 'payment', 'payments', flash, - // HTML section - '
    ' + - 'Payment #%{id} (%{remove})' + +function addPaymentSource(flash) { + addDiv('payment-entry-id', 'payment', 'payments', flash, + // HTML section + '
    ' + + 'Payment #%{id} (%{remove})' + - '
    ' + - ' + + $name) { - $div = '
    '; - $div .= ''; - $div .= ' '; - $div .= '
    '; - echo "'$div' +\n"; - } - ?> - '
    ' + + foreach ($types AS $type => $name) { + $div = '
    '; + $div .= ''; + $div .= ' '; + $div .= '
    '; + echo "'$div' +\n"; + } + ?> + '
    ' + - '
    ' + - ' ' + - ' ' + - '
    ' + + '
    ' + + ' ' + + ' ' + + '
    ' + - $name) { - if ($type == 'cash') - continue; + $name) { + if ($type == 'cash') + continue; - $div = ' + $div = ' - '
    ' - ); - - + '' + ); } function switchPaymentType(paymentid, type) { @@ -283,44 +320,6 @@ function updateCharges(id) { }); } -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')); - $("#receipt-customer-name").html($(grid_id).getCell(customer_id, 'Customer-name')); - - // Make sure the redirect is up to date, if necessary - if ($("#redirectController").val() == 'customers') - $("#redirect0").val(customer_id); - - // Hide the "no customer" message and show the current customer - $("#no-customer").hide(); - $("#current-customer").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') { - $("#no-customer").hide(); - $("#current-customer").hide(); - } - else { - if ($("#customer-id").val() > 0) { - $("#current-customer").show(); - $("#no-customer").hide(); - } else { - $("#current-customer").hide(); - $("#no-customer").show(); - } - } -} --> @@ -398,8 +397,7 @@ echo $form->submit('Generate Receipt') . "\n";

    Response

    Output

    - +-->
    From d5d2d07894f68f016f7fc75a5ed430827ef6c0d8 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 7 Jul 2009 04:34:18 +0000 Subject: [PATCH 236/717] Fixed invoice reconciliation. This was original modified from the receipt code, but we know that receipts and invoices are not mirror images in our current implementation. So, no surprise then that this was broken. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@242 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/transaction.php | 76 +++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/site/models/transaction.php b/site/models/transaction.php index 7960cf8..d23ae0a 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -42,7 +42,11 @@ class Transaction extends AppModel { // Create some models for convenience $A = new Account(); - $C = new Customer(); + + // Determine the total charges on the invoice + $grand_total = 0; + foreach ($data['LedgerEntry'] AS $entry) + $grand_total += $entry['amount']; // Create a transaction for the invoice $invoice_transaction = new Transaction(); @@ -56,8 +60,33 @@ class Transaction extends AppModel { if (!$ar_transaction->save($data['Transaction'], false)) return false; + // Create an account receivable entry + // I would prefer to do this last, as it feels more + // logical to me that the entries would flow from the + // charge to the A/R, but in reality it makes no + // difference to the end result. Entering the A/R + // first allows us to reconcile each charge on the + // invoice as we enter them. Otherwise, we would + // need to loop again at the end to reconcile, and + // would need to save each charge entry id in the + // interim. This keeps the logic simple. + // debit: A/R credit: Invoice + $ar_entry_data = array + ('debit_ledger_id' => $A->currentLedgerID($A->accountReceivableAccountID()), + 'credit_ledger_id' => $A->currentLedgerID($A->invoiceAccountID()), + 'transaction_id' => $ar_transaction->id, + 'amount' => $grand_total, + 'lease_id' => $lease_id, + 'customer_id' => $customer_id, + ); + + // Create a new A/R entry from the data + $ar_entry = new LedgerEntry(); + $ar_entry->create(); + if (!$ar_entry->save($ar_entry_data, false)) + return false; + // Go through the entered charges - $grand_total = 0; foreach ($data['LedgerEntry'] AS $entry) { // Invoice Transaction // debit: Invoice credit: Charge @@ -94,39 +123,20 @@ class Transaction extends AppModel { if (!$invoice_entry->save($entry, false)) return false; - $grand_total += $entry['amount']; + // Reconcile the Invoice account. Our two entries are: + // debit: Invoice credit: Charge + // debit: A/R credit: Invoice + // Since this is from the perspective of the Invoice account, + // the credit entry is the Invoice<->A/R, and the debit + // entry is the actual invoice ledger entry. + $R = new Reconciliation(); + $R->create(); + if (!$R->save(array('debit_ledger_entry_id' => $invoice_entry->id, + 'credit_ledger_entry_id' => $ar_entry->id, + 'amount' => $entry['amount']), false)) + return false; } - // Create an account receivable entry - // debit: A/R credit: Invoice - $ar_entry_data = array - ('debit_ledger_id' => $A->currentLedgerID($A->accountReceivableAccountID()), - 'credit_ledger_id' => $A->currentLedgerID($A->invoiceAccountID()), - 'transaction_id' => $ar_transaction->id, - 'amount' => $grand_total, - 'lease_id' => $lease_id, - 'customer_id' => $customer_id, - ); - - // Create a new A/R entry from the data - $ar_entry = new LedgerEntry(); - $ar_entry->create(); - if (!$ar_entry->save($ar_entry_data, false)) - return false; - - // Reconcile the Invoice account. Our two entries are: - // debit: Invoice credit: Charge - // debit: A/R credit: Invoice - // Since this is from the perspective of the Invoice account, - // the credit entry is the Invoice<->A/R, and the debit - // entry is the actual invoice ledger entry. - $R = new Reconciliation(); - $R->create(); - if (!$R->save(array('debit_ledger_entry_id' => $invoice_entry->id, - 'credit_ledger_entry_id' => $ar_entry->id, - 'amount' => $grand_total), false)) - return false; - // Return indication of success return true; } From a8c91d8b22c3a97e7380a30cf04a3bb986dac19f Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 7 Jul 2009 04:37:04 +0000 Subject: [PATCH 237/717] First pass at having invoice support multiple charges, just like receipt/payment. It works well, but I know we still need a better solution for income accounts, and it hasn't been robustly tested yet. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@243 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/leases_controller.php | 5 - site/controllers/transactions_controller.php | 8 +- site/views/leases/invoice.ctp | 171 ++++++++++++++----- 3 files changed, 132 insertions(+), 52 deletions(-) diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index 3efe50e..7513f7c 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -202,11 +202,6 @@ class LeasesController extends AppController { // Of course, the late charge should come from the late_schedule $charge['amount'] = 10.00; - $redirect = array('controller' => 'leases', - 'action' => 'view', - $id); - $this->set(compact('redirect')); - $title = ('Lease #' . $lease['Lease']['number'] . ': ' . $lease['Unit']['name'] . ': ' . $lease['Customer']['name'] . ': Charge Entry'); diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php index bcc80f8..c73ddd5 100644 --- a/site/controllers/transactions_controller.php +++ b/site/controllers/transactions_controller.php @@ -118,11 +118,9 @@ class TransactionsController extends AppController { die("

    INVOICE FAILED

    "); } - // Comment this out to debug - $this->redirect($this->data['redirect']); - - pr($this->data['redirect']); - $this->render('/empty'); + $this->layout = null; + $this->autoLayout = false; + $this->autoRender = false; } diff --git a/site/views/leases/invoice.ctp b/site/views/leases/invoice.ctp index d829bfd..5e44970 100644 --- a/site/views/leases/invoice.ctp +++ b/site/views/leases/invoice.ctp @@ -30,14 +30,79 @@ $lease_grid_setup['onHeaderClick'] = array element('form_table', ), ))); -echo ('
    ' . "\n"); -echo $this->element('form_table', - array('class' => "item invoice ledger-entry entry", - //'with_name_after' => ':', - 'field_prefix' => 'LedgerEntry.0', - 'fields' => array - ("charge_type" => array('opts' => - array('options' => - array('rent' => 'Rent', - 'late' => 'Late Charge'), - 'value' => - (isset($charge['type']) - ? $charge['type'] - : null) - ), - ), - "amount" => array('opts' => - array('value' => - (isset($charge['amount']) - ? $charge['amount'] - : null) - ), - ), - "comment" => array('opts' => array('size' => 50)), - ))); - - -// Set up a redirect page. I use lower case 'redirect' here -// to avoid the model convention, which starts with upper-case. -foreach ($redirect AS $name => $value) { - echo $form->input("redirect.$name", - array('type' => 'hidden', - 'value' => $value, - )); -} -echo $form->end('Generate Invoice'); - +echo $form->submit('Generate Invoice') . "\n"; ?> +
    + Charges + +
    +
    + Add Another Charge +
    +
    + +end('Generate Invoice'); ?> + +

    Request

    +

    Response

    +

    Output

    +
    + +Clear Debug Output From aab8a994c82df96c68c341e58582c50f17ef80f1 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 7 Jul 2009 07:14:18 +0000 Subject: [PATCH 238/717] Modified to dynamically determine eligible charge accounts, instead of the two that were hardcoded. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@244 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/leases_controller.php | 17 ++++--- site/models/account.php | 70 ++++++++++++++++++++++++++ site/models/transaction.php | 18 +------ site/views/leases/invoice.ctp | 30 +++-------- 4 files changed, 89 insertions(+), 46 deletions(-) diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index 7513f7c..8e80d97 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -194,13 +194,16 @@ class LeasesController extends AppController { ), )); - $charge['type'] = $type; - if ($type == 'rent') - $charge['amount'] = $lease['Lease']['rent']; - elseif ($type == 'late') - // REVISIT 20090705: - // Of course, the late charge should come from the late_schedule - $charge['amount'] = 10.00; + $A = new Account(); + $charge_accounts = $A->chargeAccounts(); + $default_account = $A->rentAccountID(); + $this->set(compact('charge_accounts', 'default_account')); + + // REVISIT 20090705: + // Of course, the late charge should come from the late_schedule + $default_rent = $lease['Lease']['rent']; + $default_late = 10; + $this->set(compact('default_rent', 'default_late')); $title = ('Lease #' . $lease['Lease']['number'] . ': ' . $lease['Unit']['name'] . ': ' . diff --git a/site/models/account.php b/site/models/account.php index da02936..48cd586 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -95,10 +95,32 @@ class Account extends AppModel { function securityDepositAccountID() { return $this->nameToID('Security Deposit'); } function rentAccountID() { return $this->nameToID('Rent'); } function lateChargeAccountID() { return $this->nameToID('Late Charge'); } + function taxAccountID() { return $this->nameToID('Tax'); } function accountReceivableAccountID() { return $this->nameToID('A/R'); } function invoiceAccountID() { return $this->nameToID('Invoice'); } function receiptAccountID() { return $this->nameToID('Receipt'); } + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * 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; + } + + /************************************************************************** ************************************************************************** ************************************************************************** @@ -119,6 +141,54 @@ class Account extends AppModel { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: chargeAccounts + * - Returns an array of accounts suitable for charges + */ + + function chargeAccounts() { + // REVISIT : 20090706 + // It's not clear how to authoritatively return accounts + // that are suitable for entering charges. Clearly, INCOME + // accounts are part of the list, but there must be others + // as well. Security Deposit, for example, is clearly not + // an INCOME account. In fact, it is a LIABILITY, yet not + // all liability accounts should be part of this list + // (consider a mortgage account, for example). At the + // moment, I'll just specify the exceptions individually, + // and we'll update the algorithm when we figure out how to + // bettter genericize it. +/* $accounts = array_merge($A->fundamentalAccounts('INCOME'), */ +/* $A->fundamentalAccounts('LIABILITY')); */ +/* usort($accounts, */ +/* create_function('$a, $b', */ +/* 'return strcasecmp($a["Account"]["name"], $b["Account"]["name"]);') */ +/* ); */ + + // Find the accounts suitable for invoicing + $accounts = $this->find + ('all', array + ('contain' => false, + 'conditions' => array + ('OR' => array + (array('type' => 'INCOME'), + array('id' => $this->securityDepositAccountID()), + array('id' => $this->taxAccountID()), + ), + ), + 'order' => array('name'), + )); + + // Rearrange to be of the form (id => name) + $charge_accounts = array(); + foreach ($accounts AS $acct) { + $charge_accounts[$acct['Account']['id']] = $acct['Account']['name']; + } + + return $charge_accounts; + } /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/models/transaction.php b/site/models/transaction.php index d23ae0a..5b4543d 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -97,22 +97,8 @@ class Transaction extends AppModel { = $A->currentLedgerID($A->invoiceAccountID()); // ...and credit the charge ledger - // REVISIT 20090706 - // The charge page should have a list of all income types - // and thus the field _should_ contain a valid account - // name. At the moment, however, I'm still cobbling things - // together, and only have two types. -/* $entry['credit_ledger_id'] */ -/* = $A->currentLedgerID($A->nameToID($entry['charge_account'])); */ - if ($entry['charge_type'] === 'rent') { - $entry['credit_ledger_id'] - = $A->currentLedgerID($A->rentAccountID()); - } elseif ($entry['charge_type'] === 'late') { - $entry['credit_ledger_id'] - = $A->currentLedgerID($A->lateChargeAccountID()); - } else { - die("Invalid charge account"); - } + $entry['credit_ledger_id'] + = $A->currentLedgerID($entry['account_id']); $entry['customer_id'] = $customer_id; $entry['lease_id'] = $lease_id; diff --git a/site/views/leases/invoice.ctp b/site/views/leases/invoice.ctp index 5e44970..6f50f2c 100644 --- a/site/views/leases/invoice.ctp +++ b/site/views/leases/invoice.ctp @@ -154,29 +154,13 @@ function addChargeSource(flash) { //'with_name_after' => ':', 'field_prefix' => 'LedgerEntry.%{id}', 'fields' => array - ("charge_type" => array('opts' => - array('options' => - array('rent' => 'Rent', - 'late' => 'Late Charge', - 'secd' => 'Security Deposit'), - 'separator' => ' ', - 'type' => 'radio', - 'label' => false, - 'div' => false, - 'legend' => false, - 'value' => - (isset($charge['type']) - ? $charge['type'] - : null) - ), - ), - "amount" => array('opts' => - array('value' => - (isset($charge['amount']) - ? $charge['amount'] - : null) - ), - ), + ("account_id" => array('name' => 'Account', + 'opts' => + array('options' => $chargeAccounts, + 'value' => $defaultAccount, + ), + ), + "amount" => null, "comment" => array('opts' => array('size' => 50)), ), ))) . "+\n"; From 5007890d09185b1d5c4a20079c00c72e5c9679b9 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 7 Jul 2009 07:14:28 +0000 Subject: [PATCH 239/717] Added a petty cash account git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@245 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/schema.sql b/db/schema.sql index 451453b..7f02150 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -864,6 +864,7 @@ INSERT INTO `pmgr_accounts` (`type`, `name`, `tillable`, `depositable`) ('LIABILITY', 'A/P', 0, 0), ('LIABILITY', 'Tax', 0, 0), ('LIABILITY', 'Customer Credit', 0, 0), + ('ASSET', 'Petty Cash', 0, 0), ('ASSET', 'Bank', 0, 1), ('ASSET', 'Cash', 1, 0), ('ASSET', 'Check', 1, 0), From 40264d3c39baa18ffb73dd6fb2e64a683ccb022f Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 7 Jul 2009 07:21:22 +0000 Subject: [PATCH 240/717] Experiment to provide a fieldset around the transaction details. I didn't care too much for the looks of it, so I commented it out for the moment. Ultimately though, there is going to be confusion over having two comment fields, so if we intend to keep them both, we'll need to clearly distinguish the purpose of each. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@246 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/leases/invoice.ctp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/site/views/leases/invoice.ctp b/site/views/leases/invoice.ctp index 6f50f2c..8e68232 100644 --- a/site/views/leases/invoice.ctp +++ b/site/views/leases/invoice.ctp @@ -205,6 +205,9 @@ echo $form->input("Lease.id", 'type' => 'hidden', 'value' => 0)); +/* echo '
    ' . "\n"; */ +/* echo ' Invoice' . "\n"; */ + echo $this->element('form_table', array('class' => "item invoice transaction entry", //'with_name_after' => ':', @@ -224,6 +227,8 @@ echo $this->element('form_table', ), ))); +/* echo '
    ' . "\n"; */ + echo $form->submit('Generate Invoice') . "\n"; ?> From 06b8ff2ae9cd74b2569e203fb1d2ee9cb23bb358 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 7 Jul 2009 07:52:41 +0000 Subject: [PATCH 241/717] Added a flag to accounts, indicating whether they can be used for charges and/or payments. Invoice has already switch to this mechanism, but we're keeping receipt the same for now since I have bigger fish to fry. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@247 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 36 +++++++------ site/controllers/customers_controller.php | 15 ++---- site/models/account.php | 63 +++++++++++------------ site/views/customers/receipt.ctp | 4 -- 4 files changed, 54 insertions(+), 64 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index 7f02150..0c9ddcd 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -842,6 +842,8 @@ CREATE TABLE `pmgr_accounts` ( `trackable` TINYINT(1) UNSIGNED NOT NULL DEFAULT 1, `tillable` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Does manager collect by hand? `depositable` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Does this account receive deposits? + `chargeable` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Can be used for charges? + `payable` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Can be used for payments? -- Security Level `level` INT UNSIGNED DEFAULT 1, @@ -856,24 +858,24 @@ CREATE TABLE `pmgr_accounts` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8; LOCK TABLES `pmgr_accounts` WRITE; -INSERT INTO `pmgr_accounts` (`type`, `name`, `tillable`, `depositable`) +INSERT INTO `pmgr_accounts` (`type`, `name`, `tillable`, `depositable`, `chargeable`, `payable`) VALUES - ('ASSET', 'A/R', 0, 0), - ('ASSET', 'Invoice', 0, 0), - ('ASSET', 'Receipt', 0, 0), - ('LIABILITY', 'A/P', 0, 0), - ('LIABILITY', 'Tax', 0, 0), - ('LIABILITY', 'Customer Credit', 0, 0), - ('ASSET', 'Petty Cash', 0, 0), - ('ASSET', 'Bank', 0, 1), - ('ASSET', 'Cash', 1, 0), - ('ASSET', 'Check', 1, 0), - ('ASSET', 'Money Order', 1, 0), - ('LIABILITY', 'Security Deposit', 0, 0), - ('INCOME', 'Rent', 0, 0), - ('INCOME', 'Late Charge', 0, 0), - ('EXPENSE', 'Concession', 0, 0), - ('EXPENSE', 'Bad Debt', 0, 0); + ('ASSET', 'A/R', 0, 0, 0, 0), + ('ASSET', 'Invoice', 0, 0, 0, 0), + ('ASSET', 'Receipt', 0, 0, 0, 0), + ('LIABILITY', 'A/P', 0, 0, 0, 0), + ('LIABILITY', 'Tax', 0, 0, 1, 0), + ('LIABILITY', 'Customer Credit', 0, 0, 1, 1), + ('ASSET', 'Petty Cash', 0, 0, 0, 0), + ('ASSET', 'Bank', 0, 1, 0, 0), + ('ASSET', 'Cash', 1, 0, 0, 0), + ('ASSET', 'Check', 1, 0, 0, 0), + ('ASSET', 'Money Order', 1, 0, 0, 0), + ('LIABILITY', 'Security Deposit', 0, 0, 1, 1), + ('INCOME', 'Rent', 0, 0, 1, 0), + ('INCOME', 'Late Charge', 0, 0, 1, 0), + ('EXPENSE', 'Concession', 0, 0, 0, 1), + ('EXPENSE', 'Bad Debt', 0, 0, 0, 1); UNLOCK TABLES; diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 87d5b42..8aa6563 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -357,16 +357,6 @@ class CustomersController extends AppController { */ function receipt($id = null) { -/* if (!$id) { */ -/* $this->Session->setFlash(__('Invalid Item.', true)); */ -/* $this->redirect(array('action'=>'index')); */ -/* } */ - -/* if ($this->RequestHandler->isPost()) { */ -/* pr($this->data); */ -/* //$this->redirect(array('action'=>'index')); */ -/* $customer = $this->data; */ -/* } */ if (isset($id)) { $this->Customer->recursive = -1; $customer = $this->Customer->read(null, $id); @@ -379,6 +369,11 @@ class CustomersController extends AppController { $charges = array('balance' => 0, 'entry' => array()); } + $A = new Account(); + $payment_accounts = $A->paymentAccounts(); + $default_account = $A->cashAccountID(); + $this->set(compact('payment_accounts', 'default_account')); + $title = ($customer['name'] . ': Payment Entry'); $this->set(compact('customer', 'charges', 'title')); } diff --git a/site/models/account.php b/site/models/account.php index 48cd586..267fdbc 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -97,6 +97,8 @@ class Account extends AppModel { function lateChargeAccountID() { return $this->nameToID('Late Charge'); } function taxAccountID() { return $this->nameToID('Tax'); } function accountReceivableAccountID() { return $this->nameToID('A/R'); } + function cashAccountID() { return $this->nameToID('Cash'); } + function pettyCashAccountID() { return $this->nameToID('Petty Cash'); } function invoiceAccountID() { return $this->nameToID('Invoice'); } function receiptAccountID() { return $this->nameToID('Receipt'); } @@ -128,13 +130,14 @@ class Account extends AppModel { * - Returns an array of accounts related by similar attributes */ - function relatedAccounts($attribute) { + function relatedAccounts($attribute, $extra = null) { $this->cacheQueries = true; $account = $this->find('all', array ('contain' => array('CurrentLedger'), 'fields' => array('Account.id', 'Account.type', 'Account.name', 'CurrentLedger.id'), 'conditions' => array('Account.'.$attribute => true) - )); + ) + (isset($extra) ? $extra : array()) + ); $this->cacheQueries = false; return $account; @@ -149,37 +152,8 @@ class Account extends AppModel { */ function chargeAccounts() { - // REVISIT : 20090706 - // It's not clear how to authoritatively return accounts - // that are suitable for entering charges. Clearly, INCOME - // accounts are part of the list, but there must be others - // as well. Security Deposit, for example, is clearly not - // an INCOME account. In fact, it is a LIABILITY, yet not - // all liability accounts should be part of this list - // (consider a mortgage account, for example). At the - // moment, I'll just specify the exceptions individually, - // and we'll update the algorithm when we figure out how to - // bettter genericize it. -/* $accounts = array_merge($A->fundamentalAccounts('INCOME'), */ -/* $A->fundamentalAccounts('LIABILITY')); */ -/* usort($accounts, */ -/* create_function('$a, $b', */ -/* 'return strcasecmp($a["Account"]["name"], $b["Account"]["name"]);') */ -/* ); */ - - // Find the accounts suitable for invoicing - $accounts = $this->find - ('all', array - ('contain' => false, - 'conditions' => array - ('OR' => array - (array('type' => 'INCOME'), - array('id' => $this->securityDepositAccountID()), - array('id' => $this->taxAccountID()), - ), - ), - 'order' => array('name'), - )); + // Get all accounts that support charges + $accounts = $this->relatedAccounts('chargeable', array('order' => 'name')); // Rearrange to be of the form (id => name) $charge_accounts = array(); @@ -189,6 +163,29 @@ class Account extends AppModel { return $charge_accounts; } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: paymentAccounts + * - Returns an array of accounts suitable for payments + */ + + function paymentAccounts() { + // Get all accounts that support payments + $accounts = $this->relatedAccounts('payable', array('order' => 'name')); + + // Rearrange to be of the form (id => name) + $payment_accounts = array(); + foreach ($accounts AS $acct) { + $payment_accounts[$acct['Account']['id']] = $acct['Account']['name']; + } + + return $payment_accounts; + } + + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/views/customers/receipt.ctp b/site/views/customers/receipt.ctp index 541de02..a22f50a 100644 --- a/site/views/customers/receipt.ctp +++ b/site/views/customers/receipt.ctp @@ -122,10 +122,6 @@ function onRowSelect(grid_id, customer_id) { $("#receipt-customer-id").html($(grid_id).getCell(customer_id, 'Customer-id')); $("#receipt-customer-name").html($(grid_id).getCell(customer_id, 'Customer-name')); - // Make sure the redirect is up to date, if necessary - if ($("#redirectController").val() == 'customers') - $("#redirect0").val(customer_id); - // Hide the "no customer" message and show the current customer $("#no-customer").hide(); $("#current-customer").show(); From b36d3117a37444b4604f816c6586399774315882 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 7 Jul 2009 08:08:36 +0000 Subject: [PATCH 242/717] Removed lingering debug prints git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@248 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/customer.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/site/models/customer.php b/site/models/customer.php index 9ef4ea8..4da68dc 100644 --- a/site/models/customer.php +++ b/site/models/customer.php @@ -216,7 +216,6 @@ class Customer extends AppModel { if (!$data['Customer']['name']) { $this->Contact->recursive = -1; $pcontact = $this->Contact->read(null, $data['Customer']['primary_contact_id']); - pr($pcontact); $data['Customer']['name'] = $pcontact['Contact']['display_name']; } @@ -247,8 +246,6 @@ class Customer extends AppModel { // Go through each entry of this customer method foreach ($data['Contact'] AS &$contact) { - pr(compact('contact')); - // Update the ContactsCustomer to reflect the appropriate IDs $contact['ContactsCustomer']['customer_id'] = $id; $contact['ContactsCustomer']['contact_id'] = $contact['id']; From 54ded6173ae4b88b5ede63d739a885e8e6e566c5 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 7 Jul 2009 08:09:51 +0000 Subject: [PATCH 243/717] Modified the page redirects to flow 'new customer' => 'move-in' => 'invoice'. What's missing here is the addition of contacts, but I'll ignore for now. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@249 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/customers_controller.php | 13 ++++++++++--- site/controllers/leases_controller.php | 12 ++++++++---- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 8aa6563..0b7e45a 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -309,9 +309,16 @@ class CustomersController extends AppController { pr("CUSTOMER SAVE FAILED"); } - // Now that the work is done, let the user view the updated customer - $this->redirect(array('action'=>'view', $this->Customer->id)); - //$this->render('/empty'); + // Exisisting Customer, then view it, else if this + // is a new customer, go to the move in screen. + if ($this->data['Customer']['id']) + $this->redirect(array('action'=>'view', $this->Customer->id)); + else + $this->redirect(array('action'=>'move_in', $this->Customer->id)); + + // For debugging, only if the redirects above have been + // commented out, otherwise this section isn't reached. + $this->render('/empty'); return; } diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index 8e80d97..c1a6386 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -109,10 +109,14 @@ class LeasesController extends AppController { $this->data['Lease']['comment'] ); - if (isset($this->data['redirect'])) - $this->redirect($this->data['redirect']); - else - $this->redirect(array('action' => 'view', $lid)); + // Since this is a new lease, go to the invoice + // screen so we can start assessing charges. + $this->redirect(array('action'=>'invoice', $lid)); + + // For debugging, only if the redirect above have been + // commented out, otherwise this section isn't reached. + $this->render('/empty'); + return; } /************************************************************************** From f4319364f2dec9d8b0aeeb4d90617771ef9cb570 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 7 Jul 2009 09:00:54 +0000 Subject: [PATCH 244/717] Added mechanism for user to know the rent amount on the invoice screen. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@250 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/leases_controller.php | 18 ++++------ site/views/elements/leases.ctp | 2 ++ site/views/leases/invoice.ctp | 48 ++++++++++++++++++++++++-- 3 files changed, 54 insertions(+), 14 deletions(-) diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index c1a6386..e877c66 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -256,14 +256,6 @@ class LeasesController extends AppController { $this->sidemenu_links[] = array('name' => 'Operations', 'header' => true); - $this->sidemenu_links[] = - array('name' => 'Assess Rent', 'url' => array('action' => 'invoice', - $id, 'rent')); - - $this->sidemenu_links[] = - array('name' => 'Assess Late Charge', 'url' => array('action' => 'invoice', - $id, 'late')); - if (!isset($lease['Lease']['moveout_date'])) { $this->sidemenu_links[] = array('name' => 'Move-Out', 'url' => array('action' => 'move_out', @@ -271,9 +263,13 @@ class LeasesController extends AppController { } $this->sidemenu_links[] = - array('name' => 'Payment', 'url' => array('controller' => 'customers', - 'action' => 'receipt', - $lease['Customer']['id'])); + array('name' => 'Charges', 'url' => array('action' => 'invoice', + $id)); + + $this->sidemenu_links[] = + array('name' => 'Payments', 'url' => array('controller' => 'customers', + 'action' => 'receipt', + $id)); } // Prepare to render diff --git a/site/views/elements/leases.ctp b/site/views/elements/leases.ctp index 119146a..9171cca 100644 --- a/site/views/elements/leases.ctp +++ b/site/views/elements/leases.ctp @@ -6,6 +6,8 @@ $cols['LeaseID'] = array('index' => 'Lease.id', 'hidden' => true); $cols['Lease'] = array('index' => 'Lease.number', 'formatter' => 'id'); $cols['Unit'] = array('index' => 'Unit.name', 'width' => '50', 'align' => 'center'); $cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'longname'); +$cols['Rent'] = array('index' => 'Lease.rent', 'formatter' => 'currency', 'hidden' => true); +$cols['Deposit'] = array('index' => 'Lease.deposit', 'formatter' => 'currency', 'hiddenz' => true); $cols['Signed'] = array('index' => 'Lease.lease_date', 'formatter' => 'date'); $cols['Move-In'] = array('index' => 'Lease.movein_date', 'formatter' => 'date'); $cols['Move-Out'] = array('index' => 'Lease.moveout_date', 'formatter' => 'date'); diff --git a/site/views/leases/invoice.ctp b/site/views/leases/invoice.ctp index 8e68232..b39d785 100644 --- a/site/views/leases/invoice.ctp +++ b/site/views/leases/invoice.ctp @@ -101,6 +101,9 @@ function resetForm() { $("#invoice-lease").html("INTERNAL ERROR"); $("#invoice-unit").html("INTERNAL ERROR"); $("#invoice-customer").html("INTERNAL ERROR"); + $("#invoice-rent").html("INTERNAL ERROR"); + $("#invoice-late").html("INTERNAL ERROR"); + $("#invoice-deposit").html("INTERNAL ERROR"); addChargeSource(false); datepickerNow('charge_date'); @@ -116,6 +119,11 @@ function onRowSelect(grid_id, lease_id) { $("#invoice-lease").html($(grid_id).getCell(lease_id, 'Lease-number')); $("#invoice-unit").html($(grid_id).getCell(lease_id, 'Unit-name')); $("#invoice-customer").html($(grid_id).getCell(lease_id, 'Customer-name')); + $("#invoice-rent").html($(grid_id).getCell(lease_id, 'Lease-rent')); + $("#invoice-late").html('$10.00'); + $("#invoice-deposit").html($(grid_id).getCell(lease_id, 'Lease-deposit') + ? $(grid_id).getCell(lease_id, 'Lease-deposit') + : '-'); // Hide the "no lease" message and show the current lease $("#no-lease").hide(); @@ -185,16 +193,47 @@ echo $this->element('leases', 'limit' => 10, )); -echo ('

    ' . - '

    ' . "\n"); + "\n"); echo $form->create(null, array('id' => 'invoice-form', 'url' => array('controller' => 'transactions', @@ -270,6 +309,9 @@ echo $form->submit('Generate Invoice') . "\n"; $("#invoice-lease").html(""); $("#invoice-unit").html(""); $("#invoice-customer").html(""); + $("#invoice-rent").html(""); + $("#invoice-late").html('$10.00'); + $("#invoice-deposit").html(""); onGridState(null, 'hidden'); onGridState(null, 'visible'); From 3f275b127b5bb3e01d73f825dc2b020e93d3936c Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 7 Jul 2009 16:08:56 +0000 Subject: [PATCH 245/717] Implemented the balance field of Leases as part of a single query. This not only reduces the number of queries required, it also allows balance to be a sortable column, so that we can determine which customers are overdue. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@251 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 9 ++++-- site/controllers/leases_controller.php | 41 ++++++++++++++++++-------- site/models/ledger_entry.php | 17 +++++++++++ site/views/elements/leases.ctp | 4 +-- 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/site/app_controller.php b/site/app_controller.php index ab0dc81..86da138 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -112,6 +112,9 @@ class AppController extends Controller { array('link'=>1, 'contain'=>1)); $query['conditions'] = $this->jqGridDataConditions($params, $model); + // DEBUG PURPOSES ONLY! + $params['count_query'] = $query; + // Get the number of records prior to pagination $count = $this->jqGridDataRecordCount($params, $model, $query); @@ -136,15 +139,15 @@ class AppController extends Controller { $query['fields'] = $this->jqGridDataFields($params, $model); $results = $this->jqGridDataRecords($params, $model, $query); + // DEBUG PURPOSES ONLY! + $params['query'] = $query; + // Post process the records $this->jqGridRecordsPostProcess($params, $model, $results); // Add in any needed hyperlinks $this->jqGridRecordLinks($params, $model, $results, array()); - // DEBUG PURPOSES ONLY! - $params['query'] = $query; - // Finally, dump out the data $this->jqGridDataOutputHeader($params, $model); echo "\n"; diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index e877c66..a6b46fd 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -49,12 +49,39 @@ class LeasesController extends AppController { $params['action'] = 'all'; } - function jqGridDataTables(&$params, &$model) { + function jqGridDataCountTables(&$params, &$model) { return array ('link' => array('Unit' => array('fields' => array('Unit.id', 'Unit.name')), 'Customer' => array('fields' => array('Customer.id', 'Customer.name')))); } + function jqGridDataTables(&$params, &$model) { + $link = $this->jqGridDataCountTables($params, $model); + $link['link']['LedgerEntry'] = array('fields' => array()); + $link['link']['LedgerEntry']['Ledger'] = array('fields' => array()); + $link['link']['LedgerEntry']['Ledger']['Account'] = array('fields' => array()); + // INNER JOIN would be great, as it would ensure we're only looking + // at the ledger entries that we truly want. However, this also + // removes from the query any leases that do not yet have a ledger + // entry in A/R. A solution would be to INNER JOIN these tables, + // and LEFT JOIN it to the rest. Grouping of JOINs, however, is + // implemented with the 'joins' tag, and is not available through + // the Linkable behavior interface. + //$link['link']['LedgerEntry']['Ledger']['Account']['type'] = 'INNER'; + $link['link']['LedgerEntry']['Ledger']['Account']['conditions'] + = array('Account.id' => + $this->Lease->LedgerEntry->Ledger->Account->accountReceivableAccountID()); + return $link; + } + + function jqGridDataFields(&$params, &$model) { + return array("Lease.*", + "SUM(IF(Account.id IS NULL, 0," . + " IF(LedgerEntry.debit_ledger_id = Account.id," . + " 1, -1))" . + " * LedgerEntry.amount) AS 'balance'"); + } + function jqGridDataConditions(&$params, &$model) { $conditions = parent::jqGridDataConditions($params, $model); @@ -75,18 +102,6 @@ class LeasesController extends AppController { return parent::jqGridRecordLinks($params, $model, $records, $links); } - function jqGridDataRecords(&$params, &$model, $query) { - $leases = parent::jqGridDataRecords($params, $model, $query); - - // Get the balance on each lease. - foreach ($leases AS &$lease) { - $stats = $this->Lease->stats($lease['Lease']['id']); - $lease['Lease']['balance'] = $stats['balance']; - } - - return $leases; - } - /************************************************************************** ************************************************************************** diff --git a/site/models/ledger_entry.php b/site/models/ledger_entry.php index b51b203..8578197 100644 --- a/site/models/ledger_entry.php +++ b/site/models/ledger_entry.php @@ -32,6 +32,23 @@ class LedgerEntry extends AppModel { 'className' => 'Ledger', 'foreignKey' => 'credit_ledger_id', ), + + 'Ledger' => array( + 'foreignKey' => false, + // conditions will be used when JOINing tables + // (such as find with LinkableBehavior) + 'conditions' => array('OR' => + array('%{MODEL_ALIAS}.debit_ledger_id = Ledger.id', + '%{MODEL_ALIAS}.credit_ledger_id = Ledger.id')), + + // finderQuery will be used when tables are put + // together across several querys, not with JOIN. + // (such as find with ContainableBehavior) + 'finderQuery' => 'NOT-IMPLEMENTED', + + 'counterQuery' => '' + ), + ); var $hasAndBelongsToMany = array( diff --git a/site/views/elements/leases.ctp b/site/views/elements/leases.ctp index 9171cca..26c095e 100644 --- a/site/views/elements/leases.ctp +++ b/site/views/elements/leases.ctp @@ -6,12 +6,12 @@ $cols['LeaseID'] = array('index' => 'Lease.id', 'hidden' => true); $cols['Lease'] = array('index' => 'Lease.number', 'formatter' => 'id'); $cols['Unit'] = array('index' => 'Unit.name', 'width' => '50', 'align' => 'center'); $cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'longname'); -$cols['Rent'] = array('index' => 'Lease.rent', 'formatter' => 'currency', 'hidden' => true); +$cols['Rent'] = array('index' => 'Lease.rent', 'formatter' => 'currency', 'hiddenz' => true); $cols['Deposit'] = array('index' => 'Lease.deposit', 'formatter' => 'currency', 'hiddenz' => true); $cols['Signed'] = array('index' => 'Lease.lease_date', 'formatter' => 'date'); $cols['Move-In'] = array('index' => 'Lease.movein_date', 'formatter' => 'date'); $cols['Move-Out'] = array('index' => 'Lease.moveout_date', 'formatter' => 'date'); -$cols['Balance'] = array('index' => 'Lease.balance', 'formatter' => 'currency', 'sortable'=>false); +$cols['Balance'] = array('index' => 'balance', 'formatter' => 'currency'); $cols['Comment'] = array('index' => 'Lease.comment', 'formatter' => 'comment'); $custom_post_data = compact('nothing'); From f7f9da92f3a6af994abf94b1286ef7c8eedd25d1 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 8 Jul 2009 00:32:22 +0000 Subject: [PATCH 246/717] Fixed a couple sort order issues, and modified the balance results to always return a number (zero) instead of null. A Lease should always have a balance, unlike Units where it's appropriate to have an null balance on a vacant unit. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@252 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/leases_controller.php | 31 +++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index a6b46fd..e590b05 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -75,11 +75,14 @@ class LeasesController extends AppController { } function jqGridDataFields(&$params, &$model) { - return array("Lease.*", - "SUM(IF(Account.id IS NULL, 0," . + $db = &$model->getDataSource(); + $fields = $db->fields($model, $model->alias); + $fields[] = ("SUM(IF(Account.id IS NULL, 0," . " IF(LedgerEntry.debit_ledger_id = Account.id," . " 1, -1))" . - " * LedgerEntry.amount) AS 'balance'"); + " * IF(LedgerEntry.amount IS NULL, 0, LedgerEntry.amount))" . + " AS 'balance'"); + return $fields; } function jqGridDataConditions(&$params, &$model) { @@ -95,6 +98,28 @@ class LeasesController extends AppController { return $conditions; } + function jqGridDataOrder(&$params, &$model, $index, $direction) { + // Do not sort by number, which is type varchar and + // sorts on an ascii basis. Sort by ID instead. + if ($index === 'Lease.number') + $index = 'Lease.id'; + + // Instead of sorting by name, sort by defined order + if ($index === 'Unit.name') + $index = 'Unit.sort_order'; + + $order = array(); + $order[] = parent::jqGridDataOrder($params, $model, $index, $direction); + + // If sorting by anything other than id/number + // add sorting by id as a secondary condition. + if ($index !== 'Lease.id' && $index !== 'Lease.number') + $order[] = parent::jqGridDataOrder($params, $model, + 'Lease.id', $direction); + + return $order; + } + function jqGridRecordLinks(&$params, &$model, &$records, $links) { $links['Lease'] = array('number'); $links['Unit'] = array('name'); From 1f95e835f8a480222a403fa11cce6004b3d974af Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 8 Jul 2009 00:34:03 +0000 Subject: [PATCH 247/717] Updated the balance algorithm for units and customers as was done for leases. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@253 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/customers_controller.php | 56 ++++++++++++++++++----- site/controllers/units_controller.php | 47 +++++++++++++++++-- site/views/elements/customers.ctp | 2 +- site/views/elements/units.ctp | 1 + 4 files changed, 89 insertions(+), 17 deletions(-) diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 0b7e45a..2e48793 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -51,7 +51,7 @@ class CustomersController extends AppController { $params['action'] = 'all'; } - function jqGridDataTables(&$params, &$model) { + function jqGridDataCountTables(&$params, &$model) { return array ('link' => array(// Models @@ -61,9 +61,35 @@ class CustomersController extends AppController { ); } + function jqGridDataTables(&$params, &$model) { + $link = $this->jqGridDataCountTables($params, $model); + $link['link']['LedgerEntry'] = array('fields' => array()); + $link['link']['LedgerEntry']['Ledger'] = array('fields' => array()); + $link['link']['LedgerEntry']['Ledger']['Account'] = array('fields' => array()); + // INNER JOIN would be great, as it would ensure we're only looking + // at the ledger entries that we truly want. However, this also + // removes from the query any units that do not yet have a ledger + // entry in A/R. A solution would be to INNER JOIN these tables, + // and LEFT JOIN it to the rest. Grouping of JOINs, however, is + // implemented with the 'joins' tag, and is not available through + // the Linkable behavior interface. + //$link['link']['LedgerEntry']['Ledger']['Account']['type'] = 'INNER'; + $link['link']['LedgerEntry']['Ledger']['Account']['conditions'] + = array('Account.id' => + $this->Customer->LedgerEntry->Ledger->Account->accountReceivableAccountID()); + return $link; + } + function jqGridDataFields(&$params, &$model) { - return array('Customer.*', - 'COUNT(CurrentLease.id) AS lease_count'); + $db = &$model->getDataSource(); + $fields = $db->fields($model, $model->alias); + $fields[] = ('COUNT(DISTINCT CurrentLease.id) AS lease_count'); + $fields[] = ("SUM(IF(Account.id IS NULL, 0," . + " IF(LedgerEntry.debit_ledger_id = Account.id," . + " 1, -1))" . + " * IF(LedgerEntry.amount IS NULL, 0, LedgerEntry.amount))" . + " AS 'balance'"); + return $fields; } function jqGridDataConditions(&$params, &$model) { @@ -80,13 +106,19 @@ class CustomersController extends AppController { } function jqGridDataOrder(&$params, &$model, $index, $direction) { - $order = parent::jqGridDataOrder($params, $model, $index, $direction); - if ($index === 'PrimaryContact.last_name') { - $order[] = 'PrimaryContact.first_name ' . $direction; - } - if ($index === 'PrimaryContact.first_name') { - $order[] = 'PrimaryContact.last_name ' . $direction; - } + $order = array(); + $order[] = parent::jqGridDataOrder($params, $model, $index, $direction); + + if ($index !== 'PrimaryContact.last_name') + $order[] = parent::jqGridDataOrder($params, $model, + 'PrimaryContact.last_name', $direction); + if ($index !== 'PrimaryContact.first_name') + $order[] = parent::jqGridDataOrder($params, $model, + 'PrimaryContact.first_name', $direction); + if ($index !== 'Customer.id') + $order[] = parent::jqGridDataOrder($params, $model, + 'Customer.id', $direction); + return $order; } @@ -309,8 +341,8 @@ class CustomersController extends AppController { pr("CUSTOMER SAVE FAILED"); } - // Exisisting Customer, then view it, else if this - // is a new customer, go to the move in screen. + // If existing customer, then view it. Otherwise, since + // this is a new customer, go to the move in screen. if ($this->data['Customer']['id']) $this->redirect(array('action'=>'view', $this->Customer->id)); else diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index 0d570b7..aaaad60 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -51,7 +51,7 @@ class UnitsController extends AppController { $params['action'] = 'all'; } - function jqGridDataTables(&$params, &$model) { + function jqGridDataCountTables(&$params, &$model) { $link = array ('link' => array(// Models @@ -70,6 +70,35 @@ class UnitsController extends AppController { return $link; } + function jqGridDataTables(&$params, &$model) { + $link = $this->jqGridDataCountTables($params, $model); + $link['link']['CurrentLease']['LedgerEntry'] = array('fields' => array()); + $link['link']['CurrentLease']['LedgerEntry']['Ledger'] = array('fields' => array()); + $link['link']['CurrentLease']['LedgerEntry']['Ledger']['Account'] = array('fields' => array()); + // INNER JOIN would be great, as it would ensure we're only looking + // at the ledger entries that we truly want. However, this also + // removes from the query any leases that do not yet have a ledger + // entry in A/R. A solution would be to INNER JOIN these tables, + // and LEFT JOIN it to the rest. Grouping of JOINs, however, is + // implemented with the 'joins' tag, and is not available through + // the Linkable behavior interface. + //$link['link']['CurrentLease']['LedgerEntry']['Ledger']['Account']['type'] = 'INNER'; + $link['link']['CurrentLease']['LedgerEntry']['Ledger']['Account']['conditions'] + = array('Account.id' => + $this->Unit->CurrentLease->LedgerEntry->Ledger->Account->accountReceivableAccountID()); + return $link; + } + + function jqGridDataFields(&$params, &$model) { + $db = &$model->getDataSource(); + $fields = $db->fields($model, $model->alias); + $fields[] = ("SUM(IF(Account.id IS NULL, 0," . + " IF(LedgerEntry.debit_ledger_id = Account.id," . + " 1, -1))" . + " * LedgerEntry.amount) AS 'balance'"); + return $fields; + } + function jqGridDataConditions(&$params, &$model) { $conditions = parent::jqGridDataConditions($params, $model); @@ -90,10 +119,20 @@ class UnitsController extends AppController { } function jqGridDataOrder(&$params, &$model, $index, $direction) { - if ($index === 'Unit.name') { + // Instead of sorting by name, sort by defined order + if ($index === 'Unit.name') $index = 'Unit.sort_order'; - } - return parent::jqGridDataOrder($params, $model, $index, $direction); + + $order = array(); + $order[] = parent::jqGridDataOrder($params, $model, $index, $direction); + + // If sorting by anything other than name (defined order) + // add the sort-order as a secondary condition + if ($index !== 'Unit.name') + $order[] = parent::jqGridDataOrder($params, $model, + 'Unit.sort_order', $direction); + + return $order; } function jqGridRecordLinks(&$params, &$model, &$records, $links) { diff --git a/site/views/elements/customers.ctp b/site/views/elements/customers.ctp index 46cd28f..0dab029 100644 --- a/site/views/elements/customers.ctp +++ b/site/views/elements/customers.ctp @@ -9,7 +9,7 @@ $cols['Name'] = array('index' => 'Customer.name', 'formatter $cols['Last Name'] = array('index' => 'PrimaryContact.last_name', 'formatter' => 'name'); $cols['First Name'] = array('index' => 'PrimaryContact.first_name', 'formatter' => 'name'); $cols['Leases'] = array('index' => 'lease_count', 'width' => '60'); -$cols['Balance'] = array('index' => 'balance', 'formatter' => 'currency', 'sortable' => false); +$cols['Balance'] = array('index' => 'balance', 'formatter' => 'currency'); $cols['Comment'] = array('index' => 'Customer.comment', 'formatter' => 'comment'); $custom_post_data = compact('nothing'); diff --git a/site/views/elements/units.ctp b/site/views/elements/units.ctp index 6f2eed7..95c17e6 100644 --- a/site/views/elements/units.ctp +++ b/site/views/elements/units.ctp @@ -9,6 +9,7 @@ $cols['ID'] = array('index' => 'Unit.id', 'formatter' => 'id'); $cols['Unit'] = array('index' => 'Unit.name', 'width' => '50'); $cols['Size'] = array('index' => 'UnitSize.name', 'width' => '75'); $cols['Status'] = array('index' => 'Unit.status', 'width' => '75'); +$cols['Balance'] = array('index' => 'balance', 'formatter' => 'currency'); $cols['Comment'] = array('index' => 'Unit.comment', 'formatter' => 'comment'); From 5f9b9e15cbf02dfc0f786ca35d962ae82d64560a Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 8 Jul 2009 00:52:33 +0000 Subject: [PATCH 248/717] Fixed bug with security deposits after I did away with sitelinks use of ledger number some time back git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@254 97e9348a-65ac-dc4b-aefc-98561f571b83 --- scripts/sitelink2pmgr.pl | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 99682e1..b19c120 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -904,6 +904,15 @@ foreach $row (@{query($sdbh, $query)}) { 'amount' => $row->{'InvoiceAmount'}, } }; + # Charges are the only way we have to figure out security + # deposit requirements for a lease. So, if we encounter + # a security deposit charge, update the lease to reflect. + if ($row->{'ChargeDescription'} eq 'Security Deposit') { + $newdb{'tables'}{'leases'}{'rows'}[ + $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease_id'} + ]{'deposit'} = $row->{'ChargeAmount'}; + } + addRow('transactions', { 'stamp' => datefmt($row->{'ChargeDate'}), 'through_date' => datefmt($row->{'EndDate'}) }); @@ -1539,21 +1548,6 @@ print Dumper \%newdb; buildTables(); -###################################################################### -## Security Deposits - -print(STDERR "Set Lease Security Deposits...\n"); - -$query = "SELECT L.LedgerID, L.UnitID, C.ChargeAmount FROM TenantLedger L INNER JOIN Charges C ON C.LedgerID = L.LedgerID WHERE L.UnitID <> 'POS\$' AND C.ChargeDescription = 'Security Deposit' ORDER BY UnitID"; - -foreach $row (@{query($sdbh, $query)}) { - #my $uid = $newdb{'lookup'}{'unit'}{$row->{'UnitID'}}; - $query = "UPDATE pmgr_leases - SET deposit = $row->{'ChargeAmount'} - WHERE `number` = '$row->{'LedgerID'}'"; - query($db_handle, $query, $row); -} - ###################################################################### ## Contact Display Names @@ -1567,6 +1561,7 @@ $query = " IF(first_name IS NOT NULL, first_name, last_name))"; query($db_handle, $query); + ###################################################################### ## Unit Lease Assignments From 3aacbb94aa9e43b66d83e71d4b21b590083cc8e5 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 8 Jul 2009 14:48:34 +0000 Subject: [PATCH 249/717] Fixed a cut/paste error when moving code from the Transaction model into the App model. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@255 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/app_model.php b/site/app_model.php index f246e69..3838982 100644 --- a/site/app_model.php +++ b/site/app_model.php @@ -169,7 +169,7 @@ class AppModel extends Model { if (isset($this->data[$alias][$field])) { /* pr("Fix Date for '$alias'.'$field'; current value = " . */ /* "'{$this->data[$alias][$field]}'"); */ - if ($this->data[$alias]['stamp'] === 'CURRENT_TIMESTAMP') + 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 From 014fa0feb925d973ffc0f2b8ce7536aad9cb028d Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 8 Jul 2009 16:04:53 +0000 Subject: [PATCH 250/717] Modified effective dates to be part of the ledger entry, not the transaction. This is the logically correct way, as a transaction is simply a collection of entries which might be anywhere from completely aligned to totally disjoint from one another (more likely the former). As a practical example, consider a move-in invoice, with security deposit (effective immediately with no end date), a prorated rent (effective move-in day through the end of the first month), and first full months rent (effective beginning of next month through the end of next month). There is certainly more work to be done on this, and testing was minimal. It does seem to be functioning though, so I'm checking in. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@256 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 18 ++- scripts/sitelink2pmgr.pl | 115 +++++++++++++----- .../controllers/ledger_entries_controller.php | 4 +- site/models/ledger_entry.php | 4 +- site/views/elements/ledger_entries.ctp | 2 + site/views/elements/transactions.ctp | 3 +- site/views/leases/invoice.ctp | 45 ++++--- site/views/ledger_entries/view.ctp | 2 + site/views/transactions/view.ctp | 1 - 9 files changed, 134 insertions(+), 60 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index 0c9ddcd..4c354a1 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -948,7 +948,6 @@ CREATE TABLE `pmgr_transactions` ( -- NOT NULL, `stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - `through_date` DATE DEFAULT NULL, `due_date` DATE DEFAULT NULL, -- REVISIT : 20090604 @@ -970,13 +969,28 @@ DROP TABLE IF EXISTS `pmgr_ledger_entries`; CREATE TABLE `pmgr_ledger_entries` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `name` VARCHAR(80) DEFAULT NULL, + -- Effective date may be used for a variety of entries + -- charges & payments are not always effective at the + -- time of transaction. Through date, on the other hand, + -- will probably only be relevant for charges, such as + -- rent, which is effective for a range of dates. + `effective_date` DATE DEFAULT NULL, -- first day + `through_date` DATE DEFAULT NULL, -- last day + `monetary_source_id` INT(10) UNSIGNED DEFAULT NULL, -- NULL if internal transfer `transaction_id` INT(10) UNSIGNED NOT NULL, `customer_id` INT(10) UNSIGNED DEFAULT NULL, `lease_id` INT(10) UNSIGNED DEFAULT NULL, `amount` FLOAT(12,2) NOT NULL, + -- REVISIT : 20090707 + -- Experimental. Considering automatically hooking + -- charges to their invoice. This may help ease the + -- ongoing accounting dilema that we've been having. + -- It might allow us to keep the underlying invoice + -- ledgers without having to expose the user to them. + `root_transaction_id` INT(10) UNSIGNED DEFAULT NULL, + `debit_ledger_id` INT(10) UNSIGNED NOT NULL, `credit_ledger_id` INT(10) UNSIGNED NOT NULL, diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index b19c120..fd1288f 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -224,6 +224,36 @@ sub datefmt { return sprintf("%04d-%02d-%02d%s", $dt[2], $dt[0], $dt[1], $dt[3] ? ' '.$dt[3] : ""); } +sub dates { + my ($type, $dt, $dt_end, $comment, $ledger_id) = @_; + + # Nothing should be stamped before possession + my $stamp = $dt; + if ($stamp =~ m%^0?[12]/% || ($stamp =~ m%^0?3/(\d+)/% && $1 <= 25)) { + $stamp = "3/25/2009 16:00"; + } + + my $effective_dt = $dt; + my $through_dt = $dt_end; + + # Use different dates for security deposits + if ($type eq 'charge' && $comment eq 'Security Deposit') { + $effective_dt = $newdb{'lookup'}{'ledger'}{$ledger_id}{'lease_date'}; + $through_dt = undef; + } + + # REVISIT : 20090708 + # Do we want to have effective dates on invoices? + # Do we want to have effective dates for payments? + # The Receipt already has an effective date. + if ($type eq 'invoice' || $type eq 'payment') { + $effective_dt = undef; + $through_dt = undef; + } + + return (datefmt($stamp), datefmt($effective_dt), datefmt($through_dt)); +} + ###################################################################### ###################################################################### @@ -854,7 +884,9 @@ $query = "SELECT L.*, A.TenantID FROM TenantLedger L LEFT JOIN `Access` A ON A.L foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}} - = { 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'} }; + = { 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'}, + 'lease_date' => $row->{'DateIn'}, + }; addRow('leases', { 'number' => $newdb{'tables'}{'leases'}{'autoid'}+1, @@ -892,9 +924,13 @@ $newdb{'lookup'}{'charge'} = {}; $query = "SELECT *, ChargeAmount+TaxAmount AS InvoiceAmount FROM Charges ORDER BY ChargeID"; foreach $row (@{query($sdbh, $query)}) { + my ($stamp, $effective_date, $through_date) = + dates('invoice', $row->{'ChargeDate'}, $row->{'EndDate'}, + $row->{'ChargeDescription'}, $row->{'LedgerID'}); + addRow('transactions', - { 'stamp' => datefmt($row->{'ChargeDate'}), - 'through_date' => datefmt($row->{'EndDate'}) }); + { 'stamp' => $stamp, + }); $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}} = { 'invoice' => @@ -914,8 +950,8 @@ foreach $row (@{query($sdbh, $query)}) { } addRow('transactions', - { 'stamp' => datefmt($row->{'ChargeDate'}), - 'through_date' => datefmt($row->{'EndDate'}) }); + { 'stamp' => $stamp, + }); $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'charge_tx'} = $newdb{'tables'}{'transactions'}{'autoid'}; @@ -931,7 +967,9 @@ foreach $row (@{query($sdbh, $query)}) { # Create the invoice entry # debit: A/R credit: Invoice addRow('ledger_entries', - { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + { 'effective_date' => $effective_date, + 'through_date' => $through_date, + 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'tx'}, 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'debit_ledger_id'}, 'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'credit_ledger_id'}, @@ -952,6 +990,10 @@ foreach $row (@{query($sdbh, $query)}) { $query = "SELECT * FROM Charges ORDER BY ChargeID"; foreach $row (@{query($sdbh, $query)}) { + my (undef, $effective_date, $through_date) = + dates('charge', $row->{'ChargeDate'}, $row->{'EndDate'}, + $row->{'ChargeDescription'}, $row->{'LedgerID'}); + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'} = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'charge_tx'}; $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'} @@ -970,7 +1012,9 @@ foreach $row (@{query($sdbh, $query)}) { # Add the charge entry # debit: Invoice credit: Rent/LateCharge/Etc addRow('ledger_entries', - { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + { 'effective_date' => $effective_date, + 'through_date' => $through_date, + 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'debit_ledger_id'}, 'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'credit_ledger_id'}, @@ -1000,7 +1044,9 @@ foreach $row (@{query($sdbh, $query)}) { # Add the tax charge entry # debit: Invoice credit: Tax addRow('ledger_entries', - { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + { 'effective_date' => $effective_date, + 'through_date' => $through_date, + 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'debit_ledger_id'}, 'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Tax'}{'ledger_id'}, @@ -1069,18 +1115,18 @@ $newdb{'lookup'}{'receipt'} = {}; # # RENT TAX INVOICE A/R RECEIPT CASH CHECK # ------- ------- ------- ------- ------- ------- ------- -# |50 | 50| | | | | -# | | 5 5| | | | | -# | | |55 55| | | | -# |40 | 40| | | | | -# | | 4 4| | | | | -# | | |44 44| | | | -# | | | | |79 | 79| -# | | | | |20 20| | -# | | | |50 50| | | -# | | | | 5 5| | | -# | | | |40 40| | | -# | | | | 4 4| | | +# |50 | 50| | | | | t1a +# | | 5 5| | | | | t1a +# | | |55 55| | | | t1b +# |40 | 40| | | | | t2a +# | | 4 4| | | | | t2a +# | | |44 44| | | | t2b +# | | | | |79 | 79| t3a +# | | | | |20 20| | t3a +# | | | |50 50| | | t3b +# | | | | 5 5| | | t3b +# | | | |40 40| | | t3b +# | | | | 4 4| | | t3b # | | | | | | | # # There is another possible solution, although it is @@ -1127,18 +1173,21 @@ foreach $row (@{query($sdbh, $query)}) { # next; # } + my ($stamp, $effective_date, $through_date) = + dates('receipt', $row->{'ReceiptDate'}, undef); + if (!$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}) { addRow('transactions', - { 'stamp' => datefmt($row->{'ReceiptDate'}), - 'through_date' => undef }); + { 'stamp' => $stamp, + }); $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}} = {'tx' => $newdb{'tables'}{'transactions'}{'autoid'}, - 'date' => datefmt($row->{'ReceiptDate'}), + 'date' => $stamp, }; addRow('transactions', - { 'stamp' => datefmt($row->{'ReceiptDate'}), - 'through_date' => undef }); + { 'stamp' => $stamp, + }); $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'payment_tx'} = $newdb{'tables'}{'transactions'}{'autoid'}; } @@ -1193,7 +1242,9 @@ foreach $row (@{query($sdbh, $query)}) { # but it is Money to Receipt instead. # debit: Cash/Check/Etc credit: Receipt addRow('ledger_entries', - { 'monetary_source_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}, + { 'effective_date' => $effective_date, + 'through_date' => $through_date, + 'monetary_source_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}, 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, 'debit_ledger_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'debit_ledger_id'}, 'credit_ledger_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'credit_ledger_id'}, @@ -1216,11 +1267,9 @@ $newdb{'lookup'}{'payment'} = {}; $query = "SELECT * FROM Payments ORDER BY PaymentID"; foreach $row (@{query($sdbh, $query)}) { -# addRow('transactions', -# { 'stamp' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'date'}, -# 'through_date' => undef }); -# $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}} -# = {'tx' => $newdb{'tables'}{'transactions'}{'autoid'} }; + + my (undef, $effective_date, $through_date) = + dates('payment', $row->{'PaymentDate'}, undef); $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}} = { 'tx' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'payment_tx'} }; @@ -1247,7 +1296,9 @@ foreach $row (@{query($sdbh, $query)}) # Add the payment entry # debit: Receipt credit: A/R addRow('ledger_entries', - { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + { 'effective_date' => $effective_date, + 'through_date' => $through_date, + 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, 'transaction_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'tx'}, 'debit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'}, 'credit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'}, diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index 07a4b1d..aad81e4 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -298,9 +298,7 @@ class LedgerEntriesController extends AppController { 'Lease.id', ), - 'fields' => array('LedgerEntry.id', - 'LedgerEntry.amount', - 'LedgerEntry.comment'), + 'fields' => array('LedgerEntry.*'), 'conditions' => array('LedgerEntry.id' => $id), )); diff --git a/site/models/ledger_entry.php b/site/models/ledger_entry.php index 8578197..bfce372 100644 --- a/site/models/ledger_entry.php +++ b/site/models/ledger_entry.php @@ -91,7 +91,7 @@ class LedgerEntry extends AppModel { * query the ledger/account to find it out. */ function ledgerContextFields($ledger_id = null, $account_type = null) { - $fields = array('id', 'name', 'comment', 'amount'); + $fields = array('id', 'effective_date', 'through_date', 'comment', 'amount'); if (isset($ledger_id)) { $fields[] = ("IF(LedgerEntry.debit_ledger_id = $ledger_id," . @@ -114,7 +114,7 @@ class LedgerEntry extends AppModel { } function ledgerContextFields2($ledger_id = null, $account_id = null, $account_type = null) { - $fields = array('id', 'name', 'comment', 'amount'); + $fields = array('id', 'effective_date', 'through_date', 'comment', 'amount'); if (isset($ledger_id)) { $fields[] = ("IF(LedgerEntry.debit_ledger_id = $ledger_id," . diff --git a/site/views/elements/ledger_entries.ctp b/site/views/elements/ledger_entries.ctp index 8ca5e3d..b409395 100644 --- a/site/views/elements/ledger_entries.ctp +++ b/site/views/elements/ledger_entries.ctp @@ -50,6 +50,8 @@ else } $cols['Date'] = array('index' => 'Transaction.stamp', 'formatter' => 'date'); +$cols['Effective'] = array('index' => 'LedgerEntry.effective_date', 'formatter' => 'date'); +$cols['Through'] = array('index' => 'LedgerEntry.through_date', 'formatter' => 'date'); if ($single_account) { $cols['Account'] = array('index' => 'Account.name', 'formatter' => 'name'); diff --git a/site/views/elements/transactions.ctp b/site/views/elements/transactions.ctp index cfcd6c3..d0692cb 100644 --- a/site/views/elements/transactions.ctp +++ b/site/views/elements/transactions.ctp @@ -4,8 +4,7 @@ $cols = array(); $cols['ID'] = array('index' => 'Transaction.id', 'formatter' => 'id'); //$cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'longname'); -$cols['Timesamp'] = array('index' => 'Transaction.stamp', 'formatter' => 'date'); -$cols['Through'] = array('index' => 'Transaction.through_date', 'formatter' => 'date'); +$cols['Timestamp'] = array('index' => 'Transaction.stamp', 'formatter' => 'date'); $cols['Due'] = array('index' => 'Transaction.due_date', 'formatter' => 'date'); $cols['Comment'] = array('index' => 'Transaction.comment', 'formatter' => 'comment'); diff --git a/site/views/leases/invoice.ctp b/site/views/leases/invoice.ctp index b39d785..270bcb4 100644 --- a/site/views/leases/invoice.ctp +++ b/site/views/leases/invoice.ctp @@ -106,8 +106,7 @@ function resetForm() { $("#invoice-deposit").html("INTERNAL ERROR"); addChargeSource(false); - datepickerNow('charge_date'); - $("#through_date").val(''); + datepickerNow('TransactionStamp'); } @@ -150,6 +149,7 @@ function onGridState(grid_id, state) { } function addChargeSource(flash) { + var id = $("#charge-entry-id").val(); addDiv('charge-entry-id', 'charge', 'charges', flash, // HTML section '
    ' + @@ -168,6 +168,14 @@ function addChargeSource(flash) { 'value' => $defaultAccount, ), ), + "effective_date" => array('opts' => + array('type' => 'text'), + 'between' => 'BOM', + ), + "through_date" => array('opts' => + array('type' => 'text'), + 'between' => 'EOM', + ), "amount" => null, "comment" => array('opts' => array('size' => 50)), ), @@ -176,6 +184,20 @@ function addChargeSource(flash) { '
    ' ); + + $("#LedgerEntry"+id+"EffectiveDate") + .attr('autocomplete', 'off') + .datepicker({ constrainInput: true, + numberOfMonths: [1, 1], + showCurrentAtPos: 0, + dateFormat: 'mm/dd/yy' }); + + $("#LedgerEntry"+id+"ThroughDate") + .attr('autocomplete', 'off') + .datepicker({ constrainInput: true, + numberOfMonths: [1, 1], + showCurrentAtPos: 0, + dateFormat: 'mm/dd/yy' }); } --> @@ -253,14 +275,8 @@ echo $this->element('form_table', 'field_prefix' => 'Transaction', 'fields' => array ("stamp" => array('opts' => - array('id' => 'charge_date', - 'type' => 'text'), - 'between' => 'Now', - ), - "through_date" => array('opts' => - array('id' => 'through_date', - 'type' => 'text'), - 'between' => 'EOM', + array('type' => 'text'), + 'between' => 'Now', ), "comment" => array('opts' => array('size' => 50), ), @@ -288,14 +304,7 @@ echo $form->submit('Generate Invoice') . "\n"; From 208aaaa5048ae45d86ed1c5ae804d27b8b2417ea Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 9 Jul 2009 00:31:56 +0000 Subject: [PATCH 266/717] Modified the datepickerNow() function to return results without the time (just date). Updated the move_in datepicker to use it and added a link for the user. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@272 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/leases/move_in.ctp | 17 ++++++++++------- site/webroot/js/pmgr.js | 18 +++++++++++------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/site/views/leases/move_in.ctp b/site/views/leases/move_in.ctp index 8aa4f93..5e1a317 100644 --- a/site/views/leases/move_in.ctp +++ b/site/views/leases/move_in.ctp @@ -52,6 +52,7 @@ function resetForm() { $("#movein-customer").html("INTERNAL ERROR"); $("#unit-id").val(0); $("#movein-unit").html("INTERNAL ERROR"); + datepickerNow('LeaseMoveinDate', false); } function onRowSelect(grid_id, item_type, item_id) { @@ -159,8 +160,9 @@ echo $this->element('form_table', array('class' => "item move-in entry", 'field_prefix' => 'Lease', 'fields' => array - ("movein_date" => array('opts' => array('type' => 'text', - 'id' => 'datepicker')), + ("movein_date" => array('opts' => array('type' => 'text'), + 'between' => 'Now', + ), "comment" => array('opts' => array('size' => 50)), ))); @@ -170,11 +172,12 @@ echo $form->end('Move In Customer'); @@ -79,8 +80,9 @@ echo $this->element('form_table', array('class' => "item move-out entry", 'field_prefix' => 'Lease', 'fields' => array - ("moveout_date" => array('opts' => array('type' => 'text', - 'id' => 'datepicker')), + ("moveout_date" => array('opts' => array('type' => 'text'), + 'between' => 'Now', + ), ))); // Set up a redirect page. I use lower case 'redirect' here @@ -97,11 +99,12 @@ echo $form->end('Perform Move Out'); - -create(null, array('id' => 'move-out-form', - 'url' => array('controller' => 'leases', - 'action' => 'move_out'))); - -// REVISIT : 20090702 -// Ask how to handle the security deposit -// (apply to rent, damages, cleaning, etc). -// Let user select the next unit status -// (DAMAGED, COMPANY, UNAVAILABLE, RESERVED, DIRTY, VACANT) - - -if ($multiple) { - $options = array(); - foreach ($data['Lease'] AS $lease) - $options[$lease['id']] = $lease['Unit']['name']; - echo $form->input('Lease.id', array('label' => 'Move Out of Unit: ', - 'options' => $options)); -} -else { - echo $form->input('Lease.id', - array('type' => 'hidden', - 'value' => $data['Lease']['id'], - )); -} - -echo $this->element('form_table', - array('class' => "item move-out entry", - 'field_prefix' => 'Lease', - 'fields' => array - ("moveout_date" => array('opts' => array('type' => 'text'), - 'between' => 'Now', - ), - ))); - -// Set up a redirect page. I use lower case 'redirect' here -// to avoid the model convention, which starts with upper-case. -foreach ($redirect AS $name => $value) { - echo $form->input("redirect.$name", - array('type' => 'hidden', - 'value' => $value, - )); -} - -echo $form->end('Perform Move Out'); -?> - - - -

    From 43787d643432e5776762c96ba31939cba0d0c2ee Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 9 Jul 2009 02:57:29 +0000 Subject: [PATCH 271/717] Removed the comment from lease move-out, and tweaked the form_table to support it git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@277 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/form_table.ctp | 3 +++ site/views/leases/move.ctp | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/site/views/elements/form_table.ctp b/site/views/elements/form_table.ctp index e51a80e..6fc374e 100644 --- a/site/views/elements/form_table.ctp +++ b/site/views/elements/form_table.ctp @@ -45,6 +45,9 @@ if ($include_after) $rows = array(); foreach ($fields AS $field => $config) { + if (!isset($config)) + continue; + if (!isset($config['name'])) $config['name'] = implode(' ', array_map('ucfirst', explode('_', $field))); if (!isset($config['opts'])) diff --git a/site/views/leases/move.ctp b/site/views/leases/move.ctp index 0f0bd4d..f580fe3 100644 --- a/site/views/leases/move.ctp +++ b/site/views/leases/move.ctp @@ -185,7 +185,10 @@ echo $this->element('form_table', 'id' => "LeaseMoveDate"), 'between' => 'Now', ), - "comment" => array('opts' => array('size' => 50)), + "comment" => + ($move_type !== 'out' + ? array('opts' => array('size' => 50)) + : null), ))); if ($move_type === 'out') { From 80ddeeed6f94094ad9bfa202de35be7e3474fde1 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 9 Jul 2009 02:57:43 +0000 Subject: [PATCH 272/717] Implemented more around lease closings. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@278 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/leases_controller.php | 33 +++++++++-- site/models/lease.php | 81 +++++++++++++++++++++++--- 2 files changed, 101 insertions(+), 13 deletions(-) diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index 6ac7295..25917bf 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -170,9 +170,15 @@ class LeasesController extends AppController { // Handle the move out based on the data given //pr($this->data); - $this->Lease->moveOut($this->data['Lease']['id']); + $this->Lease->moveOut($this->data['Lease']['id'], + 'VACANT', + $this->data['Lease']['moveout_date'], + //true // Close this lease, if able + false + ); + $this->redirect($this->data['redirect']); - //$this->autoRender = false; + $this->autoRender = false; return; } @@ -213,6 +219,21 @@ class LeasesController extends AppController { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: close + * - Closes a lease to any further action + */ + + function close($id) { + // REVISIT : 20090708 + // We should probably seek confirmation first... + $this->Lease->close($id); + $this->redirect(array('action'=>'view', $id)); + } + + /************************************************************************** ************************************************************************** ************************************************************************** @@ -299,11 +320,10 @@ class LeasesController extends AppController { $this->sidemenu_links[] = array('name' => 'Operations', 'header' => true); - if (!isset($lease['Lease']['moveout_date'])) { + if (!isset($lease['Lease']['moveout_date'])) $this->sidemenu_links[] = array('name' => 'Move-Out', 'url' => array('action' => 'move_out', $id)); - } $this->sidemenu_links[] = array('name' => 'Charges', 'url' => array('action' => 'invoice', @@ -313,6 +333,11 @@ class LeasesController extends AppController { array('name' => 'Payments', 'url' => array('controller' => 'customers', 'action' => 'receipt', $lease['Customer']['id'])); + + if ($this->Lease->closeable($id)) + $this->sidemenu_links[] = + array('name' => 'Close', 'url' => array('action' => 'close', + $id)); } // Prepare to render diff --git a/site/models/lease.php b/site/models/lease.php index 8bf7acd..5ff8230 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -228,27 +228,90 @@ class Lease extends AppModel { * - Moves the customer out of the specified lease */ - function moveOut($id = null, $status = 'VACANT', + function moveOut($id, $status = 'VACANT', $stamp = null, $close = false) { - $this->create(false); + // 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); + + // Close the lease, if so requested + if ($close) + $this->close($id, $stamp); + + // 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) { + if (!$this->closeable($id)) + return 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'); - // Move customer out of the lease, and possibly close it - $this->data['Lease']['moveout_date'] = $stamp; - if ($close) - $this->data['Lease']['close_date'] = $stamp; + // Set the close date + $this->data['Lease']['close_date'] = $stamp; // Save it! $this->save($this->data, false); + return true; + } - // Finally, update the unit status + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: closeable + * - Indicates whether or not the lease can be closed + */ + + function closeable($id) { $this->recursive = -1; - $this->read(); - $this->Unit->updateStatus($this->data['Lease']['unit_id'], $status); + $this->read(null, $id); + + // We can't close a lease that's still in use + if (!isset($this->data['Lease']['moveout_date'])) + return false; + + // We can't close a lease that's already closed + if (isset($this->data['Lease']['close_date'])) + return false; + + $deposits = $this->findSecurityDeposits($id); + $stats = $this->stats($id); + + // A lease can only be closed if there are no outstanding + // security deposits, and if the account balance is zero. + if ($deposits['summary']['balance'] != 0 || $stats['balance'] != 0) + return false; + + // Apparently this lease meets all the criteria! + return true; } From b3bceef570219b274f503ec5f1584f38e9ddecde Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 9 Jul 2009 03:29:24 +0000 Subject: [PATCH 273/717] Copied this requirements file from a different repository. For history, see http://localhost/svn/domain/branches/rent_manager_20090510/requirements.txt. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@279 97e9348a-65ac-dc4b-aefc-98561f571b83 --- requirements.txt | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..210a37c --- /dev/null +++ b/requirements.txt @@ -0,0 +1,29 @@ +N - GATE +N - ACH / CREDIT CARD PROCESSING +Y - CREDIT CARD ENTRY +Y - ACH ENTRY +P - INVENTORY TRACKING / POS +Y - UNIT TYPES +Y - UNIT SIZES +Y - UNITS +Y - MOVE IN / OUT +Y - UNIT TRANSFERS +Y - LEASE TRACKING (PDF Generation) +Y - LETTERS (PDF Generation) +Y - REMINDERS +Y - MULTIPLE LATE RENT SCHEDULES (Tenant A vs Tenant B) +Y - ACCOUNTING (assign charges to accounts) +Y - DETAILED REPORTING (HTML & PDF) +Y - SITE MAP; HOT CLICKABLE +P - PROSPECTIVE TENANTS +Y - MARKETING +P - RESERVATIONS +P - MOVE OUT NOTICES +P - MULTI-SITE (One database, multiple sites) +Y - GENERATE GEOGRAPHIC MAP OF CUSTOMERS USING GOOGLE! + - Major advantage here... MapPoint only choice with competitors +Y - WEB BASED +Y - CUSTOMER VIEW / MANAGER VIEW +Y - CUSTOMERS CAN CREATE ACCOUNTS, VIEW HISTORY +Y - CUSTOMERS CAN SIGN UP FOR AUTO PAY + From 3463ae329b253d95a9aa61ecaed479cdea5959ef Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 9 Jul 2009 03:41:21 +0000 Subject: [PATCH 274/717] Captured notes on functional requirements to just get this thing out the door. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@280 97e9348a-65ac-dc4b-aefc-98561f571b83 --- requirements.txt | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/requirements.txt b/requirements.txt index 210a37c..dedd0fe 100644 --- a/requirements.txt +++ b/requirements.txt @@ -27,3 +27,40 @@ Y - CUSTOMER VIEW / MANAGER VIEW Y - CUSTOMERS CAN CREATE ACCOUNTS, VIEW HISTORY Y - CUSTOMERS CAN SIGN UP FOR AUTO PAY + + +---------------------------------------------------------------------- +---------------------------------------------------------------------- +Operations to be functional +'X' marks functionality sufficiently completed + + X - Create Customer ID/Account + X - Add Contact information to Customer + X - Move Customer into Unit + - Enter Rent Concessions given + X - Asses Rent Charges + X - Asses Late Charges + X - Asses Security Deposits + X - Receive and record Checks + X - Receive and record Money Orders + X - Receive and record Cash + - Receive and record ACH Deposits + - Handle NSF checks + - Assess NSF Fees + - Determine Lease Paid-Through status + - Report: List of customers overdue + - Flag unit as overlocked + - Flag unit as evicting + - Flag unit as normal status + - Flag unit as dirty + - Enter notes when communicating with Customer + - Accept pre-payments + - NOTE: As a temporary solution, disallow customer to run + a credit. Require charges be entered first. + X - Record Customer Move-Out from Unit + - Record utilization of Security Deposit + - Record issuing of a refund + - Record Deposit into Petty Cash + - Record Payment from Petty Cash to expenses + - Record Petty Cash to refund. + - Write Off Bad Debt From 00b473ee4f8b075f46bba36dba0b495af5fca0c5 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 9 Jul 2009 05:07:33 +0000 Subject: [PATCH 275/717] Noted the need to perform bank deposits git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@281 97e9348a-65ac-dc4b-aefc-98561f571b83 --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index dedd0fe..21fb902 100644 --- a/requirements.txt +++ b/requirements.txt @@ -64,3 +64,4 @@ Operations to be functional - Record Payment from Petty Cash to expenses - Record Petty Cash to refund. - Write Off Bad Debt + X - Perform a Deposit and Close the Books From 17b6986758d7b6ed98f60252070a783e22982e63 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 9 Jul 2009 05:27:13 +0000 Subject: [PATCH 276/717] Fixed problem when nameToID returns no results. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@282 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_model.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/site/app_model.php b/site/app_model.php index 3838982..e7e1372 100644 --- a/site/app_model.php +++ b/site/app_model.php @@ -95,8 +95,11 @@ class AppModel extends Model { 'conditions' => compact('name'), )); $this->cacheQueries = false; - $item = current($item); - return $item['id']; + if ($item) { + $item = current($item); + return $item['id']; + } + return null; } From 5a4cfb0581c5dabd673161f36c9d77e7f7f3313a Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 9 Jul 2009 06:08:31 +0000 Subject: [PATCH 277/717] Since adding the MODEL_ALIAS condition to LedgerEntry (which only works for the Linkable Behavior), the read() ails when it tries to link models together. Setting recursive to -1 solves the problem (or at least, the symptom). git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@283 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/account.php | 1 + 1 file changed, 1 insertion(+) diff --git a/site/models/account.php b/site/models/account.php index 267fdbc..c0c02bb 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -599,6 +599,7 @@ class Account extends AppModel { if (!$entry->saveAll($entry_data, array('validate'=>false))) { return false; } + $entry->recursive = -1; $entry->read(); //pr(array('post-save', $entry->data)); From 1afaede12aae1dda9984eff4caf377d9e2044f28 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 9 Jul 2009 06:10:00 +0000 Subject: [PATCH 278/717] Added ACH and Concession entry. Like everything else, I haven't tested too robustly, but it does seem to work. I might want to change the monetary source id for Concession. Right now each concession gets its own monetary source, but we could probably use a common one without issue. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@284 97e9348a-65ac-dc4b-aefc-98561f571b83 --- requirements.txt | 4 +-- site/models/transaction.php | 28 +++++++++++++++---- site/views/customers/receipt.ctp | 47 ++++++++++++++++++-------------- 3 files changed, 51 insertions(+), 28 deletions(-) diff --git a/requirements.txt b/requirements.txt index 21fb902..2335469 100644 --- a/requirements.txt +++ b/requirements.txt @@ -37,14 +37,14 @@ Operations to be functional X - Create Customer ID/Account X - Add Contact information to Customer X - Move Customer into Unit - - Enter Rent Concessions given + X - Enter Rent Concessions given X - Asses Rent Charges X - Asses Late Charges X - Asses Security Deposits X - Receive and record Checks X - Receive and record Money Orders X - Receive and record Cash - - Receive and record ACH Deposits + X - Receive and record ACH Deposits - Handle NSF checks - Assess NSF Fees - Determine Lease Paid-Through status diff --git a/site/models/transaction.php b/site/models/transaction.php index 5b4543d..8e055e3 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -180,12 +180,16 @@ class Transaction extends AppModel { $this->LedgerEntry->MonetarySource->MonetaryType ->nameToID($entry['monetary_type_name']); - $entry['MonetarySource']['name'] = - $this->LedgerEntry->MonetarySource->MonetaryType - ->nameToID($entry['monetary_type_name']); - + if (!isset($entry['MonetarySource']['monetary_type_id'])) { + $entry['MonetarySource']['name'] = 'Other'; + $entry['MonetarySource']['monetary_type_id'] = + $this->LedgerEntry->MonetarySource->MonetaryType + ->nameToID('Other Non-Tillable'); + } else { + $entry['MonetarySource']['name'] = $entry['monetary_type_name']; + } + // Give it a fancy name based on the check number - $entry['MonetarySource']['name'] = $entry['monetary_type_name']; if ($entry['monetary_type_name'] === 'Check' || $entry['monetary_type_name'] === 'Money Order') { $entry['MonetarySource']['name'] .= @@ -193,6 +197,18 @@ class Transaction extends AppModel { } } + // Determine which account we'll use for the ledger entry + $account_name = $entry['monetary_type_name']; + + // REVISIT : 20090708 + // I _hate_ hardcoding values, but I'm not sure how + // else to handle this at the moment. I'm pretty sure + // what needs to happen is for the account information + // to be figured out programatically on the receipt + // presentation page, and then those values would flow + // back after entry to here. + if ($account_name === 'ACH') + $account_name = 'Bank'; // This entry of physical money is part of the receipt transaction // debit: Cash/Check/Etc credit: Receipt @@ -200,7 +216,7 @@ class Transaction extends AppModel { // Receipt must debit the "money" asset (bank, cash, check, etc)... $entry['debit_ledger_id'] - = $A->currentLedgerID($A->nameToID($entry['monetary_type_name'])); + = $A->currentLedgerID($A->nameToID($account_name)); // ...and credit the Receipt ledger $entry['credit_ledger_id'] diff --git a/site/views/customers/receipt.ctp b/site/views/customers/receipt.ctp index 52e8619..9a23de9 100644 --- a/site/views/customers/receipt.ctp +++ b/site/views/customers/receipt.ctp @@ -168,20 +168,25 @@ function addPaymentSource(flash) { '
    ' + 'Payment #%{id} (%{remove})' + - '
    ' + + '
    ' + $type, 'name' => $name, 'acct' => $acct); + } - foreach ($types AS $type => $name) { + foreach ($types AS $type) { $div = '
    '; $div .= ''; - $div .= ' '; + $div .= ' ONCLICK="switchPaymentType(\\\'payment-type-div\\\', %{id}, \\\''.$type['key'].'\\\')"'; + $div .= ' CLASS="payment-radio-%{id}" ID="payment-radio-%{id}-'.$type['key'].'"'; + $div .= ' VALUE="'.$type['acct'].'" ' . ($type['name'] == 'Cash' ? 'CHECKED ' : '') . '/>'; + $div .= ' '; $div .= '
    '; echo "'$div' +\n"; } @@ -196,12 +201,9 @@ function addPaymentSource(flash) { '
    ' + $name) { - if ($type == 'cash') - continue; - + foreach ($types AS $type) { $div = ''; break; + case 'concession': + return; + default: - html = '

    INVALID TYPE ('+type+')

    '; + html = '

    INVALID TYPE ('+type+')

    '; break; } - $("#payment-"+type+"-div-"+paymentid).html(html); - $("#payment-"+type+"-div-"+paymentid).slideDown(); + $("#"+paymentid_base+"-"+paymentid+"-"+type).html(html); + $("#"+paymentid_base+"-"+paymentid+"-"+type).slideDown(); } From 645458c081ab4b53566f60b5b6c6f89e841d6bbe Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 9 Jul 2009 06:20:59 +0000 Subject: [PATCH 279/717] Added some special cases git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@285 97e9348a-65ac-dc4b-aefc-98561f571b83 --- scripts/sitelink2pmgr.pl | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 909984a..7cbfbcb 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -1607,6 +1607,31 @@ $Data::Dumper::Sortkeys = 1; buildTables(); +###################################################################### +## Special cases - Name corrections +print("Special Cases...\n"); +$query = + "UPDATE pmgr_contacts" . + " SET first_name = 'Krystan'" . + " WHERE first_name = 'Kristan' AND last_name = 'Mancini'"; +query($db_handle, $query); +$query = + "UPDATE pmgr_customers" . + " SET name = 'Mancini, Krystan'" . + " WHERE name = 'Mancini, Kristan'"; +query($db_handle, $query); +$query = + "UPDATE pmgr_contacts" . + " SET first_name = NULL, last_name = NULL, company_name = 'Valley Bible Church'" . + " WHERE first_name = 'VBC' AND last_name = 'Tenant'"; +query($db_handle, $query); +$query = + "UPDATE pmgr_customers" . + " SET name = 'Valley Bible Church'" . + " WHERE name = 'Tenant, VBC'"; +query($db_handle, $query); + + ###################################################################### ## Contact Display Names From 372578f171228439dd41b438d770a371e199080b Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 9 Jul 2009 07:22:38 +0000 Subject: [PATCH 280/717] Initial work to determine whether or not a lease has charge gaps, and when the lease has been charged through. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@286 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/leases_controller.php | 3 + site/models/lease.php | 87 ++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index 25917bf..3e0f7e9 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -306,6 +306,9 @@ class LeasesController extends AppController { ) ); + $this->set('charge_gaps', $this->Lease->rentChargeGaps($id)); + $this->set('charge_through', $this->Lease->rentChargeThrough($id)); + // Obtain the overall lease balance $this->Lease->statsMerge($lease['Lease'], array('stats' => $this->Lease->stats($id))); diff --git a/site/models/lease.php b/site/models/lease.php index 5ff8230..699bbe7 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -137,6 +137,93 @@ class Lease extends AppModel { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * 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) { + $A = new Account(); + $entries = $this->find + ('all', + array('link' => + array(// Models + 'LedgerEntry' => array + ('Ledger' => array + ('fields' => array(), + 'Account' => array + ('fields' => array(), + 'Ledger' => array + ('alias' => 'Lx', + 'fields' => array(), + 'LedgerEntry' => array + ('alias' => 'LEx', + 'fields' => array(), + 'conditions' => array + ('LEx.effective_date = DATE_ADD(LedgerEntry.through_date, INTERVAL 1 day)', + 'LEx.lease_id = LedgerEntry.lease_id', + ) + ), + ), + ), + ), + ), + + ), + //'fields' => array('id', 'amount', 'effective_date', 'through_date'), + 'fields' => array(), + 'conditions' => array(array('Lease.id' => $id), + array('Account.id' => $A->rentAccountID()), + array('LEx.id' => null), + ), + ) + ); + return $entries; + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: rentChargeGaps + * - Checks for gaps in rent charges + */ + + function rentChargeGaps($id) { + $entries = $this->rentLastCharges($id); + if ($entries && count($entries) > 1) + return true; + return 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) { + $entries = $this->rentLastCharges($id); + if (!$entries) + return false; + if (count($entries) != 1) + return null; + return $entries[0]['LedgerEntry']['through_date']; + } + + /************************************************************************** ************************************************************************** ************************************************************************** From 112aa7cf5985ce5766e8047082986bd86a358640 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 9 Jul 2009 07:50:44 +0000 Subject: [PATCH 281/717] Shouldn't check this garbage in, but I can't bring my self to revert it git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@287 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/leases_controller.php | 9 +++++++++ site/models/lease.php | 26 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index 3e0f7e9..d121a89 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -120,6 +120,15 @@ class LeasesController extends AppController { return $order; } +/* function jqGridRecordsPostProcess(&$params, &$model, &$records) { */ +/* foreach ($records AS &$record) { */ +/* $record['Lease']['through_date'] */ +/* = $this->Lease->rentChargeThrough($record['Lease']['id']); */ +/* } */ + +/* parent::jqGridRecordsPostProcess($params, $model, $records); */ +/* } */ + function jqGridRecordLinks(&$params, &$model, &$records, $links) { $links['Lease'] = array('number'); $links['Unit'] = array('name'); diff --git a/site/models/lease.php b/site/models/lease.php index 699bbe7..c64422b 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -224,6 +224,32 @@ class Lease extends AppModel { } +/* /\************************************************************************** */ +/* ************************************************************************** */ +/* ************************************************************************** */ +/* * function: rentPaidThrough */ +/* * - Determines the date that rent has been paid through */ +/* * Returns one of: */ +/* * null: There are gaps in the charges */ +/* * false: There are not yet any charges */ +/* * date: The date rent has been paid through */ +/* *\/ */ + +/* function rentPaidThrough($id) { */ +/* if ($this->rentChargeGaps($id)) */ +/* return null; */ + +/* $A = new Account(); */ +/* $unrec_entries = $A->findUnreconciledLedgerEntries */ +/* ($A->rentAccountID(), 'INCOME', array('LedgerEntry.lease_id' => $id)); */ + +/* $unrec_ids */ +/* = array_map(create_function('$data', */ +/* 'return $data["id"];'), */ +/* $unrec_entries); */ +/* } */ + + /************************************************************************** ************************************************************************** ************************************************************************** From 7a31f5cbd27a7c514e3409ff0895cb10e45cbc94 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 9 Jul 2009 08:28:34 +0000 Subject: [PATCH 282/717] Removed monetary_source_type. It was redundant, and it's entirely unclear what purpose it ultimately would or could serve. Our use of different accounts for Check, Cash, etc likely obsoleted any intention we might have had for monetary_source_type git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@288 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 44 ++++--------------- scripts/sitelink2pmgr.pl | 31 ++++--------- .../controllers/ledger_entries_controller.php | 1 - .../monetary_sources_controller.php | 7 +-- site/models/account.php | 24 ++++------ site/models/monetary_source.php | 1 - site/models/monetary_type.php | 16 ------- site/models/transaction.php | 37 +++------------- site/views/customers/receipt.ctp | 4 +- site/views/elements/monetary_sources.ctp | 1 - site/views/monetary_sources/view.ctp | 3 -- 11 files changed, 36 insertions(+), 133 deletions(-) delete mode 100644 site/models/monetary_type.php diff --git a/db/schema.sql b/db/schema.sql index 596a1ba..f7ffa70 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -871,14 +871,18 @@ INSERT INTO `pmgr_accounts` (`type`, `name`, `tillable`, `depositable`, `chargea ('LIABILITY', 'Customer Credit', 0, 0, 1, 1), ('ASSET', 'Petty Cash', 0, 0, 0, 0), ('ASSET', 'Bank', 0, 1, 0, 0), - ('ASSET', 'Cash', 1, 0, 0, 0), - ('ASSET', 'Check', 1, 0, 0, 0), - ('ASSET', 'Money Order', 1, 0, 0, 0), + ('ASSET', 'ACH', 0, 0, 0, 1), + ('ASSET', 'Cash', 1, 0, 0, 1), + ('ASSET', 'Check', 1, 0, 0, 1), + ('ASSET', 'Money Order', 1, 0, 0, 1), ('LIABILITY', 'Security Deposit', 0, 0, 1, 1), ('INCOME', 'Rent', 0, 0, 1, 0), ('INCOME', 'Late Charge', 0, 0, 1, 0), ('EXPENSE', 'Concession', 0, 0, 0, 1), - ('EXPENSE', 'Bad Debt', 0, 0, 0, 1); + ('EXPENSE', 'Bad Debt', 0, 0, 0, 1), + ('EXPENSE', 'Cleaning', 0, 0, 0, 0), + ('EXPENSE', 'Maintenance', 0, 0, 0, 0); + UNLOCK TABLES; @@ -1028,7 +1032,6 @@ CREATE TABLE `pmgr_monetary_sources` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `name` VARCHAR(80) DEFAULT NULL, - monetary_type_id INT(10) UNSIGNED NOT NULL, -- REVISIT : 20090605 -- Check Number; @@ -1054,37 +1057,6 @@ CREATE TABLE `pmgr_monetary_sources` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8; --- ---------------------------------------------------------------------- --- ---------------------------------------------------------------------- --- TABLE pmgr_monetary_types - -DROP TABLE IF EXISTS `pmgr_monetary_types`; -CREATE TABLE `pmgr_monetary_types` ( - `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - - `name` VARCHAR(80) NOT NULL, - `comment` VARCHAR(255) DEFAULT NULL, - `tillable` TINYINT(1) NOT NULL DEFAULT 1, -- Does manager collect by hand? - - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -LOCK TABLES `pmgr_monetary_types` WRITE; -INSERT INTO `pmgr_monetary_types` (`id`, `name`, `tillable`) - VALUES - -- (1, 'Transfer', 0), - (2, 'Cash', 1), - (3, 'Check', 1), - (4, 'Money Order', 1), - (5, 'ACH', 0), - (6, 'Debit Card', 0), - (7, 'Credit Card', 0), - (8, 'Other Tillable', 1), - (9, 'Other Non-Tillable', 0); -UNLOCK TABLES; - - - -- ###################################################################### -- ###################################################################### diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 7cbfbcb..98b7908 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -535,41 +535,30 @@ $newdb{'lookup'}{'charge_type'}{'Security Deposit'} = ################################################################# ## MONETARY -$newdb{'lookup'}{'monetary_type'} = {}; - -$query = "SELECT * FROM pmgr_monetary_types"; -$result = query($db_handle, $query); -foreach $row (@$result) { - $newdb{'lookup'}{'monetary_type'}{$row->{'name'}} - = {'id' => $row->{'id'} }; -} - $newdb{'lookup'}{'payment_type'} = {}; $newdb{'lookup'}{'payment_type'}{1} -= { 'name' => 'Cash', 'account_name' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Cash'} }; += { 'name' => 'Cash', 'account_name' => 'Cash' }; $newdb{'lookup'}{'payment_type'}{2} -= { 'name' => 'Check', 'account_name' => 'Check', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Check'} }; += { 'name' => 'Check', 'account_name' => 'Check' }; $newdb{'lookup'}{'payment_type'}{3} -= { 'name' => 'Money Order', 'account_name' => 'Money Order', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Money Order'} }; += { 'name' => 'Money Order', 'account_name' => 'Money Order' }; $newdb{'lookup'}{'payment_type'}{4} -= { 'name' => 'ACH', 'account_name' => 'Bank', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'ACH'} }; += { 'name' => 'ACH', 'account_name' => 'Bank' }; $newdb{'lookup'}{'payment_type'}{12} -= { 'name' => 'Concession', 'account_name' => 'Concession', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Other Non-Tillable'} }; += { 'name' => 'Concession', 'account_name' => 'Concession' }; $newdb{'ids'}{'monetary_source'} = {}; $newdb{'ids'}{'monetary_source'}{'internal'} = undef; addRow('monetary_sources', - { 'monetary_type_id' => $newdb{'lookup'}{'monetary_type'}{'Cash'}{'id'}, - 'name' => 'Cash', + { 'name' => 'Cash', 'comment' => 'Monetary source used for any cash transaction' }); $newdb{'ids'}{'monetary_source'}{'Cash'} = $newdb{'tables'}{'monetary_sources'}{'autoid'}; addRow('monetary_sources', - { 'monetary_type_id' => $newdb{'lookup'}{'monetary_type'}{'Other Non-Tillable'}{'id'}, - 'name' => 'Closing', + { 'name' => 'Closing', 'comment' => 'Credited at the closing table' }); $newdb{'ids'}{'monetary_source'}{'Closing'} = $newdb{'tables'}{'monetary_sources'}{'autoid'}; @@ -1224,8 +1213,7 @@ foreach $row (@{query($sdbh, $query)}) { $data1 = $row->{'CheckNum'}; } addRow('monetary_sources', - { 'monetary_type_id' => $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'monetary_type'}{'id'}, - 'name' => $name, + { 'name' => $name, 'data1' => $data1, #'comment' => "Receipt:$row->{'ReceiptNum'}; Payment:$row->{'PaymentType'}; Check:$row->{'CheckNum'}", }); @@ -1503,8 +1491,7 @@ sub fakeTesting { if (defined $e->{'type'}) { addRow('monetary_sources', - { 'monetary_type_id' => $e->{'type'}, - 'name' => "Money of type " . $e->{'type'}, + { 'name' => "Money of type " . $e->{'type'}, 'comment' => "Fake Money For " . $e->{'id'} }); $monetary_source_id = $newdb{'tables'}{'monetary_sources'}{'autoid'}; } diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index aad81e4..4a21335 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -284,7 +284,6 @@ class LedgerEntriesController extends AppController { ('first', array('contain' => array('MonetarySource.id', 'MonetarySource.name', - 'MonetarySource.MonetaryType.id', 'Transaction.id', 'Transaction.stamp', 'DebitLedger.id', diff --git a/site/controllers/monetary_sources_controller.php b/site/controllers/monetary_sources_controller.php index ffe5ab3..cef0f05 100644 --- a/site/controllers/monetary_sources_controller.php +++ b/site/controllers/monetary_sources_controller.php @@ -38,8 +38,7 @@ class MonetarySourcesController extends AppController { function jqGridDataTables(&$params, &$model) { return array - ('link' => array('MonetaryType' => array('fields' => array('MonetaryType.id', 'MonetaryType.name')), - ), + ('contain' => false, ); } @@ -65,9 +64,7 @@ class MonetarySourcesController extends AppController { // Get the MonetarySource and related fields $monetary_source = $this->MonetarySource->find ('first', array - ('contain' => array - ('MonetaryType', - ), + ('contain' => false, )); // Prepare to render. diff --git a/site/models/account.php b/site/models/account.php index c0c02bb..a6ce986 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -463,10 +463,9 @@ class Account extends AppModel { * * monetary_source_data * - monetary_source_id (optional... if set all else is ignored) - * - monetary_type_name + * - account_name * - MonetarySource * - name - * - monetary_type_id */ function postLedgerEntry($transaction_data, @@ -512,8 +511,8 @@ class Account extends AppModel { = array_intersect_key($monetary_data, array('monetary_source_id'=>1)); } - elseif (isset($monetary_data['monetary_type_name'])) { - if ($monetary_data['monetary_type_name'] === 'Cash') { + elseif (isset($monetary_data['account_name'])) { + if ($monetary_data['account_name'] === 'Cash') { // No distinguishing features of Cash, just // use the shared monetary source $monetary_data['monetary_source_id'] = @@ -525,21 +524,16 @@ class Account extends AppModel { else { // The monetary source needs to be unique // Create a new one dedicated to this entry - $monetary_data['MonetarySource']['monetary_type_id'] = - $this->Ledger->LedgerEntry->MonetarySource->MonetaryType - ->nameToID($monetary_data['monetary_type_name']); - - $monetary_data['MonetarySource']['name'] = - $this->Ledger->LedgerEntry->MonetarySource->MonetaryType - ->nameToID($monetary_data['monetary_type_name']); - // Give it a fancy name based on the check number - $monetary_data['MonetarySource']['name'] = $monetary_data['monetary_type_name']; - if ($monetary_data['monetary_type_name'] === 'Check' || - $monetary_data['monetary_type_name'] === 'Money Order') { + $monetary_data['MonetarySource']['name'] = $monetary_data['account_name']; + if ($monetary_data['account_name'] === 'Check' || + $monetary_data['account_name'] === 'Money Order') { $monetary_data['MonetarySource']['name'] .= ' #' . $monetary_data['MonetarySource']['data1']; } + else { + $monetary_data['MonetarySource']['name'] = $monetary_data['account_name']; + } $monetary_data = array_intersect_key($monetary_data, diff --git a/site/models/monetary_source.php b/site/models/monetary_source.php index 230e3b9..32b99fb 100644 --- a/site/models/monetary_source.php +++ b/site/models/monetary_source.php @@ -9,7 +9,6 @@ class MonetarySource extends AppModel { ); var $belongsTo = array( - 'MonetaryType', ); var $hasMany = array( diff --git a/site/models/monetary_type.php b/site/models/monetary_type.php deleted file mode 100644 index 22241a4..0000000 --- a/site/models/monetary_type.php +++ /dev/null @@ -1,16 +0,0 @@ - array('numeric'), - 'name' => array('notempty'), - 'tillable' => array('boolean') - ); - - var $hasMany = array( - 'MonetarySource', - ); - -} -?> \ No newline at end of file diff --git a/site/models/transaction.php b/site/models/transaction.php index 8e055e3..7c323c8 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -166,7 +166,7 @@ class Transaction extends AppModel { foreach ($data['LedgerEntry'] AS $entry) { // Get the Monetary Source squared away - if ($entry['monetary_type_name'] === 'Cash') { + if ($entry['account_name'] === 'Cash') { // No distinguishing features of Cash, just // use the shared monetary source $entry['monetary_source_id'] = @@ -176,47 +176,24 @@ class Transaction extends AppModel { else { // The monetary source needs to be unique // Create a new one dedicated to this entry - $entry['MonetarySource']['monetary_type_id'] = - $this->LedgerEntry->MonetarySource->MonetaryType - ->nameToID($entry['monetary_type_name']); - - if (!isset($entry['MonetarySource']['monetary_type_id'])) { - $entry['MonetarySource']['name'] = 'Other'; - $entry['MonetarySource']['monetary_type_id'] = - $this->LedgerEntry->MonetarySource->MonetaryType - ->nameToID('Other Non-Tillable'); - } else { - $entry['MonetarySource']['name'] = $entry['monetary_type_name']; - } - // Give it a fancy name based on the check number - if ($entry['monetary_type_name'] === 'Check' || - $entry['monetary_type_name'] === 'Money Order') { + if ($entry['account_name'] === 'Check' || + $entry['account_name'] === 'Money Order') { $entry['MonetarySource']['name'] .= ' #' . $entry['MonetarySource']['data1']; } + else { + $entry['MonetarySource']['name'] = $entry['account_name']; + } } - // Determine which account we'll use for the ledger entry - $account_name = $entry['monetary_type_name']; - - // REVISIT : 20090708 - // I _hate_ hardcoding values, but I'm not sure how - // else to handle this at the moment. I'm pretty sure - // what needs to happen is for the account information - // to be figured out programatically on the receipt - // presentation page, and then those values would flow - // back after entry to here. - if ($account_name === 'ACH') - $account_name = 'Bank'; - // This entry of physical money is part of the receipt transaction // debit: Cash/Check/Etc credit: Receipt $entry['transaction_id'] = $receipt_transaction->id; // Receipt must debit the "money" asset (bank, cash, check, etc)... $entry['debit_ledger_id'] - = $A->currentLedgerID($A->nameToID($account_name)); + = $A->currentLedgerID($A->nameToID($entry['account_name'])); // ...and credit the Receipt ledger $entry['credit_ledger_id'] diff --git a/site/views/customers/receipt.ctp b/site/views/customers/receipt.ctp index 9a23de9..0fc710d 100644 --- a/site/views/customers/receipt.ctp +++ b/site/views/customers/receipt.ctp @@ -175,14 +175,12 @@ function addPaymentSource(flash) { foreach(array('Cash', 'Check', 'Money Order', 'ACH', /*'Credit Card'*/ 'Concession') AS $name) { $type = preg_replace("/ /", "", strtolower($name)); $acct = $name; -/* if ($acct === 'ACH') */ -/* $acct = 'Bank'; */ $types[] = array('key' => $type, 'name' => $name, 'acct' => $acct); } foreach ($types AS $type) { $div = '
    '; - $div .= ''; diff --git a/site/views/elements/monetary_sources.ctp b/site/views/elements/monetary_sources.ctp index 133ec23..ae75f0d 100644 --- a/site/views/elements/monetary_sources.ctp +++ b/site/views/elements/monetary_sources.ctp @@ -4,7 +4,6 @@ $cols = array(); $cols['ID'] = array('index' => 'MonetarySource.id', 'formatter' => 'id'); $cols['Name'] = array('index' => 'MonetarySource.name', 'formatter' => 'longname'); -$cols['Type'] = array('index' => 'MonetaryType.name', 'formatter' => 'name'); $cols['Comment'] = array('index' => 'MonetarySource.comment', 'formatter' => 'comment'); // Set up search fields if requested by caller diff --git a/site/views/monetary_sources/view.ctp b/site/views/monetary_sources/view.ctp index bfb18fe..371cf1b 100644 --- a/site/views/monetary_sources/view.ctp +++ b/site/views/monetary_sources/view.ctp @@ -9,17 +9,14 @@ echo '
    ' . "\n"; * MonetarySource Detail Main Section */ -$type = $monetarySource['MonetaryType']; $source = $monetarySource['MonetarySource']; $rows = array(array('ID', $source['id']), array('Name', $source['name']), - array('Type', $type['name']), array('Data 1', $source['data1']), array('Data 2', $source['data2']), array('Data 3', $source['data3']), array('Data 4', $source['data4']), - array('Tillable', $type['tillable'] ? 'Yes' : 'No'), array('Comment', $source['comment'])); echo $this->element('table', From 6e1eba03a02c921e26f4ffd31a545b5becb735a8 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 9 Jul 2009 09:20:04 +0000 Subject: [PATCH 283/717] Changed the list of payment types to be dynamically generated. This works OK, but the list is longer than is probably useful, and more importantly, some of these types need to be associated with a lease, such as a security deposit. Not sure how I'll handle that. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@289 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/account.php | 19 ++++++++++ site/models/transaction.php | 15 +++----- site/views/customers/receipt.ctp | 63 ++++++++++++++------------------ 3 files changed, 53 insertions(+), 44 deletions(-) diff --git a/site/models/account.php b/site/models/account.php index a6ce986..c0a2558 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -85,6 +85,25 @@ class Account extends AppModel { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * 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']; + } + + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/models/transaction.php b/site/models/transaction.php index 7c323c8..7dfb7a8 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -166,7 +166,7 @@ class Transaction extends AppModel { foreach ($data['LedgerEntry'] AS $entry) { // Get the Monetary Source squared away - if ($entry['account_name'] === 'Cash') { + if ($entry['account_id'] == $A->cashAccountID()) { // No distinguishing features of Cash, just // use the shared monetary source $entry['monetary_source_id'] = @@ -174,17 +174,14 @@ class Transaction extends AppModel { unset($entry['MonetarySource']); } else { - // The monetary source needs to be unique - // Create a new one dedicated to this entry + $entry['MonetarySource']['name'] = $A->name($entry['account_id']); + // Give it a fancy name based on the check number - if ($entry['account_name'] === 'Check' || - $entry['account_name'] === 'Money Order') { + if ($A->name($entry['account_id']) === 'Check' || + $A->name($entry['account_id']) === 'Money Order') { $entry['MonetarySource']['name'] .= ' #' . $entry['MonetarySource']['data1']; } - else { - $entry['MonetarySource']['name'] = $entry['account_name']; - } } // This entry of physical money is part of the receipt transaction @@ -193,7 +190,7 @@ class Transaction extends AppModel { // Receipt must debit the "money" asset (bank, cash, check, etc)... $entry['debit_ledger_id'] - = $A->currentLedgerID($A->nameToID($entry['account_name'])); + = $A->currentLedgerID($entry['account_id']); // ...and credit the Receipt ledger $entry['credit_ledger_id'] diff --git a/site/views/customers/receipt.ctp b/site/views/customers/receipt.ctp index 0fc710d..c36f2f3 100644 --- a/site/views/customers/receipt.ctp +++ b/site/views/customers/receipt.ctp @@ -170,24 +170,21 @@ function addPaymentSource(flash) { '
    ' + $type, 'name' => $name, 'acct' => $acct); - } - - foreach ($types AS $type) { - $div = '
    '; - $div .= ''; - $div .= ' '; - $div .= '
    '; - echo "'$div' +\n"; - } + echo FormatHelper::phpVarToJavascript + ($form->input('LedgerEntry.%{id}.account_id', + array('type' => 'radio', + 'separator' => '
    ', + 'onclick' => ('switchPaymentType(' . + '\\\'payment-type-div\\\', ' . + '%{id}, ' . + '$(this).attr("id")' . + ')' . + //' return false;' + '' + ), + 'legend' => false, + 'value' => $defaultAccount, + 'options' => $paymentAccounts))) . "+\n"; ?> '
    ' + @@ -199,9 +196,9 @@ function addPaymentSource(flash) { '
    ' + $name) { $div = 'Check Number' + @@ -234,7 +231,7 @@ function switchPaymentType(paymentid_base, paymentid, type) { '
    '; break; - case 'moneyorder': + case 'Money Order': html = '
    ' + ' ' + @@ -244,7 +241,7 @@ function switchPaymentType(paymentid_base, paymentid, type) { '
    '; break; - case 'ach': + case 'ACH': html = '
    ' + ' ' + @@ -261,7 +258,7 @@ function switchPaymentType(paymentid_base, paymentid, type) { '
    '; break; - case 'creditcard': + case 'Credit Card': html = '
    ' + ' ' + @@ -285,16 +282,12 @@ function switchPaymentType(paymentid_base, paymentid, type) { '
    '; break; - case 'concession': - return; - default: - html = '

    INVALID TYPE ('+type+')

    '; - break; + return; } - $("#"+paymentid_base+"-"+paymentid+"-"+type).html(html); - $("#"+paymentid_base+"-"+paymentid+"-"+type).slideDown(); + $("#"+paymentid_base+"-"+paymentid+"-"+account_id).html(html); + $("#"+paymentid_base+"-"+paymentid+"-"+account_id).slideDown(); } From 6507009acc957bfcb47c52e02cbcb48d7d3b13c1 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 9 Jul 2009 16:07:19 +0000 Subject: [PATCH 284/717] Fixed a bug created with each form table when that element was modified to ignore fields set to null. The original intention was that null simply meant 'no special configuration'. However, we needed a way to programatically enable/disable fields, so null was an obvious choice to use. Now that I'm about to check in, I think I should have just made a minor change to use false to skip a field, which would have been backwards compatible (except for the one place using null to exclude the field). However, it's done now, so what the heck. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@290 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/contacts/edit.ctp | 28 ++++++++++++++-------------- site/views/customers/edit.ctp | 14 +++++++------- site/views/elements/form_table.ctp | 6 ++++++ site/views/leases/invoice.ctp | 2 +- 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/site/views/contacts/edit.ctp b/site/views/contacts/edit.ctp index 5574fd9..163af2f 100644 --- a/site/views/contacts/edit.ctp +++ b/site/views/contacts/edit.ctp @@ -120,9 +120,9 @@ function contactMethodTypeDiv($obj, $type, $stype, $values = null) { elseif ($stype === 'new') { $fields = array ('type' => array('opts' => array('options' => $obj->varstore['phoneTypes'])), - 'phone' => null, + 'phone' => true, 'ext' => array('name' => "Extension"), - 'comment' => null, + 'comment' => true, ); } elseif ($stype === 'show') { @@ -149,12 +149,12 @@ function contactMethodTypeDiv($obj, $type, $stype, $values = null) { } elseif ($stype === 'new') { $fields = array - ('address' => null, - 'city' => null, - 'state' => null, + ('address' => true, + 'city' => true, + 'state' => true, 'postcode' => array('name' => 'Zip Code'), - 'country' => null, - 'comment' => null, + 'country' => true, + 'comment' => true, ); } elseif ($stype === 'show') { @@ -182,8 +182,8 @@ function contactMethodTypeDiv($obj, $type, $stype, $values = null) { } elseif ($stype === 'new') { $fields = array - ('email' => null, - 'comment' => null, + ('email' => true, + 'comment' => true, ); } elseif ($stype === 'show') { @@ -345,17 +345,17 @@ echo($this->element array('class' => 'item contact detail', 'caption' => isset($this->data['Contact']) ? 'Edit Contact' : 'New Contact', 'fields' => array - ('first_name' => null, - 'last_name' => null, - 'middle_name' => null, - 'display_name' => null, + ('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' => null, + 'comment' => true, ))) . "\n"); echo $form->submit('Update') . "\n"; diff --git a/site/views/customers/edit.ctp b/site/views/customers/edit.ctp index b9c4ec9..9b66f61 100644 --- a/site/views/customers/edit.ctp +++ b/site/views/customers/edit.ctp @@ -120,17 +120,17 @@ function customerContactTypeDiv($obj, $stype, $values = null) { } elseif ($stype === 'new') { $fields = array - ('first_name' => null, - 'last_name' => null, - 'middle_name' => null, - 'display_name' => null, + ('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' => null, + 'comment' => true, ); } elseif ($stype === 'show') { @@ -247,8 +247,8 @@ echo($this->element array('class' => 'item customer detail', 'caption' => isset($this->data['Customer']) ? 'Edit Customer' : 'New Customer', 'fields' => array - ('name' => null, - 'comment' => null, + ('name' => true, + 'comment' => true, ))) . "\n"); echo $form->submit('Update') . "\n"; diff --git a/site/views/elements/form_table.ctp b/site/views/elements/form_table.ctp index 6fc374e..cecc4ad 100644 --- a/site/views/elements/form_table.ctp +++ b/site/views/elements/form_table.ctp @@ -48,6 +48,12 @@ foreach ($fields AS $field => $config) { if (!isset($config)) continue; + if (is_bool($config) && !$config) + continue; + + if (is_bool($config) && $config) + $config = array(); + if (!isset($config['name'])) $config['name'] = implode(' ', array_map('ucfirst', explode('_', $field))); if (!isset($config['opts'])) diff --git a/site/views/leases/invoice.ctp b/site/views/leases/invoice.ctp index 76359f4..802db38 100644 --- a/site/views/leases/invoice.ctp +++ b/site/views/leases/invoice.ctp @@ -185,7 +185,7 @@ function addChargeSource(flash) { array('type' => 'text'), 'between' => 'EOM', ), - "amount" => null, + "amount" => true, "comment" => array('opts' => array('size' => 50)), ), ))) . "+\n"; From de5f4208eb6fac7fe563ad92922b50102fd3bee6 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 9 Jul 2009 16:37:16 +0000 Subject: [PATCH 285/717] Added petty cash and a couple higher security accounts, Equity and Loan git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@291 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 10 +++++-- scripts/sitelink2pmgr.pl | 64 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index f7ffa70..9d40241 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -849,7 +849,7 @@ CREATE TABLE `pmgr_accounts` ( `payable` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Can be used for payments? -- Security Level - `level` INT UNSIGNED DEFAULT 1, + `level` INT UNSIGNED DEFAULT 10, `name` VARCHAR(80) NOT NULL, `external_account` INT(10) UNSIGNED DEFAULT NULL, @@ -861,6 +861,10 @@ CREATE TABLE `pmgr_accounts` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8; LOCK TABLES `pmgr_accounts` WRITE; +INSERT INTO `pmgr_accounts` (`type`, `name`, `level`) + VALUES + ('EQUITY', 'Equity', 1), + ('LIABILITY', 'Loan', 1); INSERT INTO `pmgr_accounts` (`type`, `name`, `tillable`, `depositable`, `chargeable`, `payable`) VALUES ('ASSET', 'A/R', 0, 0, 0, 0), @@ -868,7 +872,7 @@ INSERT INTO `pmgr_accounts` (`type`, `name`, `tillable`, `depositable`, `chargea ('ASSET', 'Receipt', 0, 0, 0, 0), ('LIABILITY', 'A/P', 0, 0, 0, 0), ('LIABILITY', 'Tax', 0, 0, 1, 0), - ('LIABILITY', 'Customer Credit', 0, 0, 1, 1), +-- ('LIABILITY', 'Customer Credit', 0, 0, 1, 1), ('ASSET', 'Petty Cash', 0, 0, 0, 0), ('ASSET', 'Bank', 0, 1, 0, 0), ('ASSET', 'ACH', 0, 0, 0, 1), @@ -878,9 +882,9 @@ INSERT INTO `pmgr_accounts` (`type`, `name`, `tillable`, `depositable`, `chargea ('LIABILITY', 'Security Deposit', 0, 0, 1, 1), ('INCOME', 'Rent', 0, 0, 1, 0), ('INCOME', 'Late Charge', 0, 0, 1, 0), + ('INCOME', 'Damage', 0, 0, 1, 0), ('EXPENSE', 'Concession', 0, 0, 0, 1), ('EXPENSE', 'Bad Debt', 0, 0, 0, 1), - ('EXPENSE', 'Cleaning', 0, 0, 0, 0), ('EXPENSE', 'Maintenance', 0, 0, 0, 0); UNLOCK TABLES; diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 98b7908..54bd007 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -1346,6 +1346,70 @@ foreach $row (@{query($sdbh, $query)}) } +###################################################################### +## Special case - Equities / Loans / Petty Cash + +my ($stamp, $effective_date, $through_date); + +print("Set up Petty Cash...\n"); + +# Add the first loan +# debit: Equity credit: Loan +addRow('transactions', + { 'stamp' => datefmt('03/25/2009 16:00'), + }); +addRow('ledger_entries', + { 'effective_date' => $effective_date, + 'through_date' => $through_date, + 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + 'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'}, + 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Equity'}{'ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Loan'}{'ledger_id'}, + 'customer_id' => undef, + 'lease_id' => undef, + 'amount' => 5000, + 'comment' => "HTP Loan #1", + }); + +# Add the second loan +# debit: Equity credit: Loan +addRow('transactions', + { 'stamp' => datefmt('04/01/2009 16:00'), + }); +addRow('ledger_entries', + { 'effective_date' => $effective_date, + 'through_date' => $through_date, + 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + 'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'}, + 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Equity'}{'ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Loan'}{'ledger_id'}, + 'customer_id' => undef, + 'lease_id' => undef, + 'amount' => 1000, + 'comment' => "HTP Loan #2", + }); + +# Cheat for now, using equity for Petty Cash +# debit: Petty Cash credit: Equity +addRow('transactions', + { 'stamp' => datefmt('03/25/2009 16:00'), + }); +addRow('ledger_entries', + { 'effective_date' => $effective_date, + 'through_date' => $through_date, + 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + 'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'}, + 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Petty Cash'}{'ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Equity'}{'ledger_id'}, + 'customer_id' => undef, + 'lease_id' => undef, + 'amount' => 750, + 'comment' => "Petty Cash Funding", + }); + + + + ###################################################################### ## Fake Data for Testing From 5877874e8286b794cc9b1273e118e77b419f3161 Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 10 Jul 2009 07:25:55 +0000 Subject: [PATCH 286/717] Check in the near completed implementation of security deposit utilization. It was on it's way to working well (although it only works for existing payment divs and there is not an obviously easy way for new payment divs to have the security deposit info as well). It feels like we've really gone overboard on the payment screen, pushing too much together. I'm going to strip some of this out on the next checkin, and create a dedicated security deposit utilization screen, perhaps just as part of move-out, or perhaps part of move-out and as an independent operation as well. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@292 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/customers_controller.php | 28 +++- site/controllers/transactions_controller.php | 8 ++ site/models/customer.php | 4 +- site/models/lease.php | 4 +- site/models/ledger_entry.php | 3 +- site/views/customers/receipt.ctp | 142 +++++++++---------- 6 files changed, 106 insertions(+), 83 deletions(-) diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 4994824..59ceb4d 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -399,12 +399,27 @@ class CustomersController extends AppController { */ function receipt($id = null) { +/* $deposits = $this->Customer->findSecurityDeposits($id); */ +/* pr($deposits); */ +/* $this->autoRender = false; */ +/* return; */ + if (isset($id)) { $this->Customer->recursive = -1; $customer = $this->Customer->read(null, $id); $customer = $customer['Customer']; $unreconciled = $this->Customer->findUnreconciledLedgerEntries($id); $charges = $unreconciled['debit']; + $leases = $this->Customer->find('first', array('contain' => array('CurrentLease'), + 'conditions' => array('Customer.id' => $id))); + $deposits = array(); + foreach ($leases['CurrentLease'] AS $lease) { + $lease_deposits = $this->Customer->Lease->findSecurityDeposits($lease['id']); + $deposits[] = array('lease_id' => $lease['id'], + 'balance' => $lease_deposits['summary']['balance']); + } + pr($deposits); + $this->set(compact('deposits')); } else { $customer = null; @@ -445,12 +460,23 @@ class CustomersController extends AppController { $unreconciled = $this->Customer->findUnreconciledLedgerEntries($id); $unreconciled = array('entries' => array_intersect_key($unreconciled['debit'], - array('entry'=>1, 'balance'=>1))); + array('entry'=>1, 'balance'=>1)), + 'deposit' => array(), + ); // XML Helper will dump an empty tag if the array is empty if (!count($unreconciled['entries']['entry'])) unset($unreconciled['entries']['entry']); + $leases = $this->Customer->find('first', array('contain' => array('CurrentLease'), + 'conditions' => array('Customer.id' => $id))); + foreach ($leases['CurrentLease'] AS $lease) { + $lease_deposits = $this->Customer->Lease->findSecurityDeposits($lease['id']); + $unreconciled['deposit'][] + = array('lease_id' => $lease['id'], + 'balance' => $lease_deposits['summary']['balance']); + } + pr($unreconciled); //$reconciled = $cust->reconcileNewLedgerEntry($cust_id, 'credit', $amount); diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php index c73ddd5..5d1a68b 100644 --- a/site/controllers/transactions_controller.php +++ b/site/controllers/transactions_controller.php @@ -137,6 +137,14 @@ class TransactionsController extends AppController { return; } + foreach($this->data['LedgerEntry'] AS &$entry) { + if (!isset($entry['acct'][$entry['account_id']])) + continue; + + $entry['MonetarySource'] = $entry['acct'][$entry['account_id']]; + } + + pr($this->data); if (!$this->Transaction->addReceipt($this->data, $this->data['Customer']['id'])) { $this->Session->setFlash("RECEIPT FAILED", true); diff --git a/site/models/customer.php b/site/models/customer.php index 4da68dc..e399b0d 100644 --- a/site/models/customer.php +++ b/site/models/customer.php @@ -86,8 +86,8 @@ class Customer extends AppModel { $A = new Account(); $entries = $A->findLedgerEntriesRelatedToAccount - ($A->invoiceAccountID(), - $A->securityDepositAccountID(), + ($A->securityDepositAccountID(), + array($A->invoiceAccountID(), $A->receiptAccountID()), true, array('LedgerEntry.customer_id' => $id), $link); /* pr(array('function' => 'Customer::findSecurityDeposits', */ diff --git a/site/models/lease.php b/site/models/lease.php index c64422b..f1fc24a 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -88,8 +88,8 @@ class Lease extends AppModel { $A = new Account(); $entries = $A->findLedgerEntriesRelatedToAccount - ($this->accountId($id), - $A->securityDepositAccountID(), + ($A->securityDepositAccountID(), + array($A->invoiceAccountID(), $A->receiptAccountID()), true, array('LedgerEntry.lease_id' => $id), $link); /* pr(array('function' => 'Lease::findSecurityDeposits', */ diff --git a/site/models/ledger_entry.php b/site/models/ledger_entry.php index bfce372..8fc8bad 100644 --- a/site/models/ledger_entry.php +++ b/site/models/ledger_entry.php @@ -91,7 +91,8 @@ class LedgerEntry extends AppModel { * query the ledger/account to find it out. */ function ledgerContextFields($ledger_id = null, $account_type = null) { - $fields = array('id', 'effective_date', 'through_date', 'comment', 'amount'); + $fields = array('id', 'effective_date', 'through_date', + 'lease_id', 'customer_id', 'comment', 'amount'); if (isset($ledger_id)) { $fields[] = ("IF(LedgerEntry.debit_ledger_id = $ledger_id," . diff --git a/site/views/customers/receipt.ctp b/site/views/customers/receipt.ctp index c36f2f3..65dba59 100644 --- a/site/views/customers/receipt.ctp +++ b/site/views/customers/receipt.ctp @@ -201,6 +201,57 @@ function addPaymentSource(flash) { $div .= ' ID="payment-type-div-%{id}-'.$account_id.'"'; $div .= ' CLASS="payment-type-div-%{id}"'; $div .= ' STYLE="display:none;">'; + + if ($name == 'Check') { + $div .= '
    '; + $div .= ' '; + $div .= ' ' + - ' ' + - // REVISIT : 20090617: Use comment field for now. - ' ' + - '
    '; - break; - - case 'Money Order': - html = - '
    ' + - ' ' + - // REVISIT : 20090617: Use comment field for now. - ' ' + - '
    '; - break; - - case 'ACH': - html = - '
    ' + - ' ' + - // REVISIT : 20090617: Use comment field for now. - ' ' + - '
    ' + - - '
    ' + - ' ' + - // REVISIT : 20090617: Use comment field for now. - ' ' + - '
    '; - break; - - case 'Credit Card': - html = - '
    ' + - ' ' + - // REVISIT : 20090617: Use comment field for now. - ' ' + - '
    ' + - - '
    ' + - ' ' + - // REVISIT : 20090617: Use comment field for now. - ' ' + - '
    ' + - - '
    ' + - ' ' + - // REVISIT : 20090617: Use comment field for now. - ' ' + - '
    '; - break; - - default: - return; - } - - $("#"+paymentid_base+"-"+paymentid+"-"+account_id).html(html); $("#"+paymentid_base+"-"+paymentid+"-"+account_id).slideDown(); } @@ -311,11 +288,22 @@ function updateCharges(id) { dataType: "xml", success: function(xml) { var ids = new Array(); - //$('#update-target ol').html('Data URL'); $('entry',xml).each(function(i){ ids.push($(this).attr('id')); - //$('#update-target').append("Push: len=" + ids.length + '
    '); }); + var html = ''; + $('deposit',xml).each(function(i){ + html += 'Lease #' + $(this).attr('lease_id') + ' Deposit:' + + fmtCurrency($(this).attr('balance')) + ''; + }); + + var html = '
      '; + $('deposit',xml).each(function(i){ + html += '
    • Lease #' + $(this).attr('lease_id') + ': ' + + fmtCurrency($(this).attr('balance')) + '
    • '; + }); + html += '
    '; + $('.security-deposit-info').html(html); $('#receipt-balance').html(fmtCurrency($('entries',xml).attr('balance'))); $("#receipt-charges-caption").html("Outstanding Charges"); updateChargesGrid(ids); @@ -381,7 +369,7 @@ echo('
    ' . ''; } - elseif ($name == 'Security Deposit') { - $div .= '
    '; + else { + continue; } $div .= '
    '; @@ -291,19 +291,6 @@ function updateCharges(id) { $('entry',xml).each(function(i){ ids.push($(this).attr('id')); }); - var html = ''; - $('deposit',xml).each(function(i){ - html += 'Lease #' + $(this).attr('lease_id') + ' Deposit:' + - fmtCurrency($(this).attr('balance')) + ''; - }); - - var html = '
      '; - $('deposit',xml).each(function(i){ - html += '
    • Lease #' + $(this).attr('lease_id') + ': ' + - fmtCurrency($(this).attr('balance')) + '
    • '; - }); - html += '
    '; - $('.security-deposit-info').html(html); $('#receipt-balance').html(fmtCurrency($('entries',xml).attr('balance'))); $("#receipt-charges-caption").html("Outstanding Charges"); updateChargesGrid(ids); From 1cb56894ce52b04b2d5d649bcb1738026512821d Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 10 Jul 2009 09:35:50 +0000 Subject: [PATCH 288/717] Forgot to add apply_deposit.ctp to the last checkin. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@294 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/leases/apply_deposit.ctp | 77 +++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 site/views/leases/apply_deposit.ctp diff --git a/site/views/leases/apply_deposit.ctp b/site/views/leases/apply_deposit.ctp new file mode 100644 index 0000000..cde254a --- /dev/null +++ b/site/views/leases/apply_deposit.ctp @@ -0,0 +1,77 @@ +' . "\n"; + +echo ('
    ' . + + 'Lease #' . $lease['number'] . + ' / Customer #' . $customer['id'] . + ': ' . $customer['name'] . + ' / Unit ' . $unit['name'] . + + '
    ' . + '' . + '' . + '' . + '
    Balance:'.$lease['stats']['balance'].'
    Deposit:'.$deposit['summary']['balance'].'
    ' . + '
    ' . + + '
    ' . "\n"); + + +echo $form->create(null, array('id' => 'receipt-form', + 'url' => array('controller' => 'transactions', + 'action' => 'postReceipt'))); + +echo $form->input("Customer.id", + array('id' => 'customer-id', + 'type' => 'hidden', + 'value' => $customer['id'])); + +echo $form->input("Lease.id", + array('id' => 'lease-id', + 'type' => 'hidden', + 'value' => $lease['id'])); + +echo $form->input("LedgerEntry.0.account_id", + array('id' => 'account-id', + 'type' => 'hidden', + 'value' => $account['id'])); + + +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' => 'Now', + ), + "amount" => array('prefix' => 'LedgerEntry.0'), + "comment" => array('opts' => array('size' => 50), + ), + ))); + +echo $form->end('Utilize Deposit'); +?> + + + +
    From 90d990e0a54a3cf86a3f2435187d5f73ee45fa68 Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 10 Jul 2009 10:06:56 +0000 Subject: [PATCH 289/717] Implemented bad debt write-off. This was tested about as well as the last checkin for security deposit utilization. Also, both of these need a redirect. I'm thinking redirect will have to be controlled dynamically, since we probably want to have them in a sequence of pages daisy changed at move out. Of course, we also will allow them each to be run on their own individually. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@295 97e9348a-65ac-dc4b-aefc-98561f571b83 --- requirements.txt | 2 +- site/controllers/leases_controller.php | 63 ++++++++++++++++++++ site/models/account.php | 1 + site/views/leases/bad_debt.ctp | 80 ++++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 site/views/leases/bad_debt.ctp diff --git a/requirements.txt b/requirements.txt index 7041774..eae70ac 100644 --- a/requirements.txt +++ b/requirements.txt @@ -63,5 +63,5 @@ Operations to be functional - Record Deposit into Petty Cash - Record Payment from Petty Cash to expenses - Record Petty Cash to refund. - - Write Off Bad Debt + X - Write Off Bad Debt X - Perform a Deposit and Close the Books diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index ae19402..d58bf8a 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -283,6 +283,64 @@ class LeasesController extends AppController { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: bad_debt + * - Writes off remaining charges on a lease. + * REVISIT : 20090710 + * Should this be a customer function? What customer + * would have only one lease that results in bad debt. + */ + + function bad_debt($id) { + $A = new Account(); + + $lease = $this->Lease->find + ('first', array + ('contain' => array + (// Models + 'Unit' => + array('order' => array('sort_order'), + 'fields' => array('id', 'name'), + ), + + 'Customer' => + array('fields' => array('id', 'name'), + ), + ), + + 'conditions' => array(array('Lease.id' => $id), + array('Lease.close_date' => null), + ), + )); + + + // Get the lease balance, part of lease stats + $this->Lease->statsMerge($lease['Lease'], + array('stats' => $this->Lease->stats($id))); + + // Determine the lease security deposit + $deposit = $this->Lease->findSecurityDeposits($lease['Lease']['id']); + if ($deposit['summary']['balance'] > 0) + die("Still have un-utilized security deposit"); + + $this->set('customer', $lease['Customer']); + $this->set('unit', $lease['Unit']); + $this->set('lease', $lease['Lease']); + $this->set('account', array('id' => $A->badDebtAccountID())); + +/* $redirect = array('controller' => 'leases', */ +/* 'action' => 'view', */ +/* $id); */ + + $title = ('Lease #' . $lease['Lease']['number'] . ': ' . + $lease['Unit']['name'] . ': ' . + $lease['Customer']['name'] . ': Write Off Bad Debt'); + $this->set(compact('title', 'redirect')); + } + + /************************************************************************** ************************************************************************** ************************************************************************** @@ -406,6 +464,11 @@ class LeasesController extends AppController { array('name' => 'Apply Deposit', 'url' => array('action' => 'apply_deposit', $id)); + if (isset($lease['Lease']['moveout_date']) && $outstanding_deposit == 0 && $outstanding_balance > 0) + $this->sidemenu_links[] = + array('name' => 'Write-Off', 'url' => array('action' => 'bad_debt', + $id)); + if ($this->Lease->closeable($id)) $this->sidemenu_links[] = array('name' => 'Close', 'url' => array('action' => 'close', diff --git a/site/models/account.php b/site/models/account.php index c0a2558..0c0968c 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -120,6 +120,7 @@ class Account extends AppModel { function pettyCashAccountID() { return $this->nameToID('Petty Cash'); } function invoiceAccountID() { return $this->nameToID('Invoice'); } function receiptAccountID() { return $this->nameToID('Receipt'); } + function badDebtAccountID() { return $this->nameToID('Bad Debt'); } /************************************************************************** diff --git a/site/views/leases/bad_debt.ctp b/site/views/leases/bad_debt.ctp new file mode 100644 index 0000000..fec8b58 --- /dev/null +++ b/site/views/leases/bad_debt.ctp @@ -0,0 +1,80 @@ +' . "\n"; + +echo ('
    ' . + + 'Lease #' . $lease['number'] . + ' / Customer #' . $customer['id'] . + ': ' . $customer['name'] . + ' / Unit ' . $unit['name'] . + + '
    ' . + '' . + '' . + '
    Balance:'.$lease['stats']['balance'].'
    ' . + '
    ' . + + '
    ' . "\n"); + + +echo $form->create(null, array('id' => 'receipt-form', + 'url' => array('controller' => 'transactions', + 'action' => 'postReceipt'))); + +echo $form->input("Customer.id", + array('id' => 'customer-id', + 'type' => 'hidden', + 'value' => $customer['id'])); + +echo $form->input("Lease.id", + array('id' => 'lease-id', + 'type' => 'hidden', + 'value' => $lease['id'])); + +echo $form->input("LedgerEntry.0.account_id", + array('id' => 'account-id', + 'type' => 'hidden', + 'value' => $account['id'])); + +echo $form->input("LedgerEntry.0.amount", + array('id' => 'amount', + 'type' => 'hidden', + 'value' => $lease['stats']['balance'])); + + +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' => 'Now', + ), + "comment" => array('opts' => array('size' => 50), + ), + ))); + +echo $form->end('Write Off Remaining Balance'); +?> + + + +
    From 9cac8c26a93bcc80a1fb47d2a8999147cdb6c970 Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 10 Jul 2009 10:09:34 +0000 Subject: [PATCH 290/717] Added another requirement git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@296 97e9348a-65ac-dc4b-aefc-98561f571b83 --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index eae70ac..5d2d5f5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -45,6 +45,7 @@ Operations to be functional X - Receive and record Money Orders X - Receive and record Cash X - Receive and record ACH Deposits + - Reverse rent charges (early moveout on prepaid occupancy) - Handle NSF checks - Assess NSF Fees - Determine Lease Paid-Through status From ad1702357041717b72ee1c5cd96c918aa1085583 Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 10 Jul 2009 10:49:19 +0000 Subject: [PATCH 291/717] Changed security deposits to be returned regardless of where second half of the ledger entry is git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@297 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/customer.php | 3 +-- site/models/lease.php | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/site/models/customer.php b/site/models/customer.php index e399b0d..a4f7786 100644 --- a/site/models/customer.php +++ b/site/models/customer.php @@ -85,9 +85,8 @@ class Customer extends AppModel { /* )); */ $A = new Account(); - $entries = $A->findLedgerEntriesRelatedToAccount + $entries = $A->findLedgerEntries ($A->securityDepositAccountID(), - array($A->invoiceAccountID(), $A->receiptAccountID()), true, array('LedgerEntry.customer_id' => $id), $link); /* pr(array('function' => 'Customer::findSecurityDeposits', */ diff --git a/site/models/lease.php b/site/models/lease.php index f1fc24a..7fd9750 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -87,9 +87,8 @@ class Lease extends AppModel { /* )); */ $A = new Account(); - $entries = $A->findLedgerEntriesRelatedToAccount + $entries = $A->findLedgerEntries ($A->securityDepositAccountID(), - array($A->invoiceAccountID(), $A->receiptAccountID()), true, array('LedgerEntry.lease_id' => $id), $link); /* pr(array('function' => 'Lease::findSecurityDeposits', */ From 46db9c83417b84d3697b61559fb31faa991085a3 Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 10 Jul 2009 10:51:57 +0000 Subject: [PATCH 292/717] Fixed bug with undefined Lease. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@298 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/transactions_controller.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php index 9e1fd0e..f5d2053 100644 --- a/site/controllers/transactions_controller.php +++ b/site/controllers/transactions_controller.php @@ -147,7 +147,9 @@ class TransactionsController extends AppController { pr($this->data); if (!$this->Transaction->addReceipt($this->data, $this->data['Customer']['id'], - $this->data['Lease']['id'])) { + (isset($this->data['Lease']['id']) + ? $this->data['Lease']['id'] + : null ))) { $this->Session->setFlash("RECEIPT FAILED", true); // REVISIT 20090706: // Until we can work out the session problems, From d9297d89ab6298d60213d60db347f262dfaaedf9 Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 10 Jul 2009 21:21:49 +0000 Subject: [PATCH 293/717] No real visible changes, but started work on making ledger entries more clear. I'll do more in a moment, just capturing a snapshot. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@299 97e9348a-65ac-dc4b-aefc-98561f571b83 --- .../controllers/ledger_entries_controller.php | 12 +- site/views/ledger_entries/view.ctp | 188 ++++++++++-------- 2 files changed, 120 insertions(+), 80 deletions(-) diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index 4a21335..05a6fd4 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -314,6 +314,9 @@ class LedgerEntriesController extends AppController { 'fields' => array('Account.id', 'Account.name', 'Account.type', 'Account.trackable'), 'conditions' => array('Account.id' => $entry['DebitLedger']['account_id']), )); + $entry['DebitLedger']['Account']['ftype'] = + $this->LedgerEntry->DebitLedger->Account + ->fundamentalType($entry['DebitLedger']['Account']['type']); // Get the Account from CreditLedger $entry['CreditLedger'] += $this->LedgerEntry->CreditLedger->Account->find @@ -322,13 +325,18 @@ class LedgerEntriesController extends AppController { 'fields' => array('Account.id', 'Account.name', 'Account.type', 'Account.trackable'), 'conditions' => array('Account.id' => $entry['CreditLedger']['account_id']), )); + $entry['CreditLedger']['Account']['ftype'] = + $this->LedgerEntry->CreditLedger->Account + ->fundamentalType($entry['CreditLedger']['Account']['type']); // Get the reconciliation balances for this ledger entry $stats = $this->LedgerEntry->stats($id); + $stats['debit']['amount_reconciled'] = $stats['debit_amount_reconciled']; + $stats['credit']['amount_reconciled'] = $stats['credit_amount_reconciled']; if ($entry['DebitLedger']['Account']['trackable']) - $stats['debit_amount_remaining'] = $entry['LedgerEntry']['amount'] - $stats['debit_amount_reconciled']; + $stats['debit']['amount_remaining'] = $entry['LedgerEntry']['amount'] - $stats['debit']['amount_reconciled']; if ($entry['CreditLedger']['Account']['trackable']) - $stats['credit_amount_remaining'] = $entry['LedgerEntry']['amount'] - $stats['credit_amount_reconciled']; + $stats['credit']['amount_remaining'] = $entry['LedgerEntry']['amount'] - $stats['credit']['amount_reconciled']; //pr($stats); $reconciled = $this->LedgerEntry->findReconciledLedgerEntries($id); diff --git a/site/views/ledger_entries/view.ctp b/site/views/ledger_entries/view.ctp index 5e437b6..efc8926 100644 --- a/site/views/ledger_entries/view.ctp +++ b/site/views/ledger_entries/view.ctp @@ -12,61 +12,56 @@ echo '
    ' . "\n"; $transaction = $entry['Transaction']; $debit_ledger = $entry['DebitLedger']; $credit_ledger = $entry['CreditLedger']; +$ledgers['debit'] = $entry['DebitLedger']; +$ledgers['credit'] = $entry['CreditLedger']; $source = $entry['MonetarySource']; $customer = $entry['Customer']; $lease = $entry['Lease']; $entry = $entry['LedgerEntry']; -$rows = array(array('ID', $entry['id']), - array('Transaction', $html->link('#'.$transaction['id'], - array('controller' => 'transactions', - 'action' => 'view', - $transaction['id']))), - array('Timestamp', FormatHelper::datetime($transaction['stamp'])), - array('Effective', FormatHelper::date($entry['effective_date'])), - array('Through', FormatHelper::date($entry['through_date'])), - array('Customer', (isset($customer['name']) - ? $html->link($customer['name'], - array('controller' => 'customers', - 'action' => 'view', - $customer['id'])) - : null)), - array('Lease', (isset($lease['id']) - ? $html->link('#'.$lease['id'], - array('controller' => 'leases', - 'action' => 'view', - $lease['id'])) - : null)), - array('Monetary Source', (isset($source['name']) - ? $html->link($source['name'], - array('controller' => 'monetary_sources', - 'action' => 'view', - $source['id'])) - : null)), - array('Amount', FormatHelper::currency($entry['amount'])), - array('Debit', ($html->link($debit_ledger['Account']['name'], - array('controller' => 'accounts', - 'action' => 'view', - $debit_ledger['Account']['id'])) - . ' (' - . $html->link('#' . $debit_ledger['Account']['id'] - . '-' . $debit_ledger['sequence'], - array('controller' => 'ledgers', - 'action' => 'view', - $debit_ledger['id'])) - . ')')), - array('Credit', ($html->link($credit_ledger['Account']['name'], - array('controller' => 'accounts', - 'action' => 'view', - $credit_ledger['Account']['id'])) - . ' (' - . $html->link('#' . $credit_ledger['Account']['id'] - . '-' . $credit_ledger['sequence'], - array('controller' => 'ledgers', - 'action' => 'view', - $credit_ledger['id'])) - . ')')), - array('Comment', $entry['comment'])); +$rows = array(); +$rows[] = array('ID', $entry['id']); +$rows[] = array('Transaction', $html->link('#'.$transaction['id'], + array('controller' => 'transactions', + 'action' => 'view', + $transaction['id']))); +$rows[] = array('Timestamp', FormatHelper::datetime($transaction['stamp'])); +$rows[] = array('Effective', FormatHelper::date($entry['effective_date'])); +$rows[] = array('Through', FormatHelper::date($entry['through_date'])); +$rows[] = array('Customer', (isset($customer['name']) + ? $html->link($customer['name'], + array('controller' => 'customers', + 'action' => 'view', + $customer['id'])) + : null)); +$rows[] = array('Lease', (isset($lease['id']) + ? $html->link('#'.$lease['id'], + array('controller' => 'leases', + 'action' => 'view', + $lease['id'])) + : null)); +$rows[] = array('Monetary Source', (isset($source['name']) + ? $html->link($source['name'], + array('controller' => 'monetary_sources', + 'action' => 'view', + $source['id'])) + : null)); +$rows[] = array('Amount', FormatHelper::currency($entry['amount'])); + +foreach ($ledgers AS $type => $ledger) + $rows[] = array(ucfirst($type), ($html->link($ledger['Account']['name'], + array('controller' => 'accounts', + 'action' => 'view', + $ledger['Account']['id'])) + . ' (' + . $html->link('#' . $ledger['Account']['id'] + . '-' . $ledger['sequence'], + array('controller' => 'ledgers', + 'action' => 'view', + $ledger['id'])) + . ')')); + +$rows[] = array('Comment', $entry['comment']); echo $this->element('table', @@ -82,18 +77,60 @@ echo $this->element('table', echo '
    ' . "\n"; $rows = array(); -if ($debit_ledger['Account']['trackable']) { - $rows[] = array("Applied from {$debit_ledger['Account']['name']}:", - FormatHelper::currency($stats['debit_amount_reconciled'])); +foreach ($ledgers AS $type => $ledger) { + pr($ledger); + if (!$ledger['Account']['trackable']) + continue; + + // The two accounts, debit and credit, are actually individual + // entries in each of those account (each make up one of the two + // entries required for "double entry"). This, when we provide + // reconcile information, we're really providing reconcile info + // for two independent accounts. The reconciling entries, + // therefore, are those on the opposite side of the ledger in + // each account. For example, assume this "double" entry is + // + // debit: A/R credit: Cash amount: 55 + // + // Then, our accounts might look like: + // + // RENT TAX A/R CASH BANK + // ------- ------- ------- ------- ------- + // |20 | 20| | | <-- Unrelated + // | | |20 20| | <-- Unrelated + // | | | | | + // |50 | 50| | | <-- Rent paid by this entry + // | |5 5| | | <-- Tax paid by this entry + // | | |55 55| | <-- THIS ENTRY + // | | | | | + // | | | |75 75| <-- Deposit includes this entry + // | | | | | + // + // In this case, we're looking to provide reconcile information + // of A/R for (the credit side of) this entry, and also of Cash + // (for the debit side). Taking the accounts as individual + // entries, instead of the "double entry" representation in the + // database, we're actually providing information on the two + // A/R entries, 50 & 5, which are both debits, i.e. opposite + // entries to the credit of A/R. The cash account entry + // reconciles against the credit of 75. Again, this is the + // opposite entry to the debit of Cash. + // + // Thus, for our debit_ledger_id, we're reconciling against + // credits, and for our credit_ledger_id, against debits. + + // Since we're looking at items opposite to $type (see above), + // our verbage needs to reflect those entry types. + + $verb = ($ledger['Account']['ftype'] == $type) ? 'REDUCTION' : 'INCREASE'; + + $rows[] = array("Applied $verb {$ledger['Account']['name']}:", + FormatHelper::currency($stats[$type]['amount_reconciled'])); $rows[] = array("{$debit_ledger['Account']['name']} Amount Remaining:", - FormatHelper::currency($stats['debit_amount_remaining'])); -} -if ($credit_ledger['Account']['trackable']) { - $rows[] = array("Applied to {$credit_ledger['Account']['name']}:", - FormatHelper::currency($stats['credit_amount_reconciled'])); - $rows[] = array("{$credit_ledger['Account']['name']} Amount Remaining:", - FormatHelper::currency($stats['credit_amount_remaining'])); + FormatHelper::currency($stats[$type]['amount_remaining'])); + } + echo $this->element('table', array('class' => 'summary', 'rows' => $rows, @@ -117,30 +154,25 @@ echo '
    ' . "\n"; * Reconciliation Ledger Entries */ -if ($debit_ledger['Account']['trackable']) { +foreach ($ledgers AS $type => $ledger) { + if (!$ledger['Account']['trackable']) + continue; + + //$verb = ($ledger['Account']['ftype'] == $type) ? 'REDUCTION' : 'INCREASE'; + $caption = ('Matching ' . (($type == 'credit') ? 'DEBITS' : 'CREDITS') . + ' from Account ' . $ledger['Account']['name']); + //$caption = ('Reconciled Entries ' . ($ledger['Account']['ftype'] == $type ? 'OUT OF' : 'INTO') . + $caption = ('Contribution to entries ' . ($ledger['Account']['ftype'] == $type ? 'OUT OF' : 'INTO') . + ' Account ' . $ledger['Account']['name']); echo $this->element('ledger_entries', array (// Element configuration - 'account_ftype' => 'debit', + 'account_ftype' => $type, 'reconcile_id' => $entry['id'], // Grid configuration 'config' => array - ('caption' => "Applied to " . $debit_ledger['Account']['name'], - 'grid_div_id' => 'debit_reconciliation_ledger_entries', - ), - )); -} - -if ($credit_ledger['Account']['trackable']) { - echo $this->element('ledger_entries', array - (// Element configuration - 'account_ftype' => 'credit', - 'reconcile_id' => $entry['id'], - - // Grid configuration - 'config' => array - ('caption' => "Applied to " . $credit_ledger['Account']['name'], - 'grid_div_id' => 'credit_reconciliation_ledger_entries', + ('caption' => $caption, + 'grid_div_id' => $type.'_reconciliation_ledger_entries', ), )); } From 8d2a544042b3881b6d111a48c70c4c1001543fcf Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 11 Jul 2009 00:34:43 +0000 Subject: [PATCH 294/717] More changes to the ledger_entry view git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@300 97e9348a-65ac-dc4b-aefc-98561f571b83 --- .../controllers/ledger_entries_controller.php | 2 +- site/views/elements/table.ctp | 13 +- site/views/ledger_entries/view.ctp | 144 +++++++++--------- site/webroot/css/layout.css | 28 ++++ 4 files changed, 116 insertions(+), 71 deletions(-) diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index 05a6fd4..cb370ad 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -343,7 +343,7 @@ class LedgerEntriesController extends AppController { //pr($reconciled); // Prepare to render. - $title = "Ledger Entry #{$entry['LedgerEntry']['id']}"; + $title = "Double Ledger Entry #{$entry['LedgerEntry']['id']}"; $this->set(compact('entry', 'title', 'reconciled', 'stats')); } } diff --git a/site/views/elements/table.ctp b/site/views/elements/table.ctp index 32bc8d5..7f2433f 100644 --- a/site/views/elements/table.ctp +++ b/site/views/elements/table.ctp @@ -58,18 +58,29 @@ if (isset($rows) && is_array($rows) && count($rows)) { $row[$c] = array($col, array('class' => $cell_class)); } } + + // Allow user to specify a list of classes + if (isset($class) && is_array($class)) + $class = implode(' ', $class); + // OK, output the table HTML echo('' . "\n"); + if (isset($caption)) echo(' ' . $caption . '' . "\n"); - if (isset($headers) && is_array($headers)) + if (isset($headers) && is_array($headers)) { + echo(' ' . "\n"); echo $html->tableHeaders($headers) . "\n"; + echo(' ' . "\n"); + } + echo(' ' . "\n"); echo $html->tableCells($rows, $suppress_alternate_rows ? null : array('class' => "oddrow"), $suppress_alternate_rows ? null : array('class' => "evnrow"), false, false) . "\n"; + echo(' ' . "\n"); echo('' . "\n"); } diff --git a/site/views/ledger_entries/view.ctp b/site/views/ledger_entries/view.ctp index efc8926..f516848 100644 --- a/site/views/ledger_entries/view.ctp +++ b/site/views/ledger_entries/view.ctp @@ -2,6 +2,44 @@ echo '
    ' . "\n"; +// The two entry ids, debit and credit, are actually individual +// entries in separate accounts (each make up one of the two +// entries required for "double entry"). This, when we provide +// reconcile information, we're really providing reconcile info +// for two independent accounts. The reconciling entries, +// therefore, are those on the opposite side of the ledger in +// each account. For example, assume this "double" entry is +// +// debit: A/R credit: Cash amount: 55 +// +// Then, our accounts might look like: +// +// RENT TAX A/R CASH BANK +// ------- ------- ------- ------- ------- +// |20 | 20| | | <-- Unrelated +// | | |20 20| | <-- Unrelated +// | | | | | +// |50 | 50| | | <-- Rent paid by this entry +// | |5 5| | | <-- Tax paid by this entry +// | | |55 55| | <-- THIS ENTRY +// | | | | | +// | | | |75 75| <-- Deposit includes this entry +// | | | | | +// +// In this case, we're looking to provide reconcile information +// of A/R for (the credit side of) this entry, and also of Cash +// (for the debit side). Taking the accounts as individual +// entries, instead of the "double entry" representation in the +// database, we're actually providing information on the two +// A/R entries, 50 & 5, which are both debits, i.e. opposite +// entries to the credit of A/R. The cash account entry +// reconciles against the credit of 75. Again, this is the +// opposite entry to the debit of Cash. +// +// Thus, for our debit_ledger_id, we're reconciling against +// credits, and for our credit_ledger_id, against debits. + + /********************************************************************** ********************************************************************** ********************************************************************** @@ -10,10 +48,8 @@ echo '
    ' . "\n"; */ $transaction = $entry['Transaction']; -$debit_ledger = $entry['DebitLedger']; -$credit_ledger = $entry['CreditLedger']; -$ledgers['debit'] = $entry['DebitLedger']; -$ledgers['credit'] = $entry['CreditLedger']; +$ledgers = array('debit' => $entry['DebitLedger'], + 'credit' => $entry['CreditLedger']); $source = $entry['MonetarySource']; $customer = $entry['Customer']; $lease = $entry['Lease']; @@ -46,27 +82,12 @@ $rows[] = array('Monetary Source', (isset($source['name']) 'action' => 'view', $source['id'])) : null)); -$rows[] = array('Amount', FormatHelper::currency($entry['amount'])); - -foreach ($ledgers AS $type => $ledger) - $rows[] = array(ucfirst($type), ($html->link($ledger['Account']['name'], - array('controller' => 'accounts', - 'action' => 'view', - $ledger['Account']['id'])) - . ' (' - . $html->link('#' . $ledger['Account']['id'] - . '-' . $ledger['sequence'], - array('controller' => 'ledgers', - 'action' => 'view', - $ledger['id'])) - . ')')); - +//$rows[] = array('Amount', FormatHelper::currency($entry['amount'])); $rows[] = array('Comment', $entry['comment']); - echo $this->element('table', array('class' => 'item ledger-entry detail', - 'caption' => 'Ledger Entry Detail', + 'caption' => 'Double Ledger Entry Detail', 'rows' => $rows, 'column_class' => array('field', 'value'))); @@ -78,57 +99,17 @@ echo $this->element('table', echo '
    ' . "\n"; $rows = array(); foreach ($ledgers AS $type => $ledger) { - pr($ledger); + //pr($ledger); if (!$ledger['Account']['trackable']) continue; - // The two accounts, debit and credit, are actually individual - // entries in each of those account (each make up one of the two - // entries required for "double entry"). This, when we provide - // reconcile information, we're really providing reconcile info - // for two independent accounts. The reconciling entries, - // therefore, are those on the opposite side of the ledger in - // each account. For example, assume this "double" entry is - // - // debit: A/R credit: Cash amount: 55 - // - // Then, our accounts might look like: - // - // RENT TAX A/R CASH BANK - // ------- ------- ------- ------- ------- - // |20 | 20| | | <-- Unrelated - // | | |20 20| | <-- Unrelated - // | | | | | - // |50 | 50| | | <-- Rent paid by this entry - // | |5 5| | | <-- Tax paid by this entry - // | | |55 55| | <-- THIS ENTRY - // | | | | | - // | | | |75 75| <-- Deposit includes this entry - // | | | | | - // - // In this case, we're looking to provide reconcile information - // of A/R for (the credit side of) this entry, and also of Cash - // (for the debit side). Taking the accounts as individual - // entries, instead of the "double entry" representation in the - // database, we're actually providing information on the two - // A/R entries, 50 & 5, which are both debits, i.e. opposite - // entries to the credit of A/R. The cash account entry - // reconciles against the credit of 75. Again, this is the - // opposite entry to the debit of Cash. - // - // Thus, for our debit_ledger_id, we're reconciling against - // credits, and for our credit_ledger_id, against debits. - - // Since we're looking at items opposite to $type (see above), - // our verbage needs to reflect those entry types. - - $verb = ($ledger['Account']['ftype'] == $type) ? 'REDUCTION' : 'INCREASE'; - - $rows[] = array("Applied $verb {$ledger['Account']['name']}:", + $applied_caption = "Transfers applied to {$ledger['Account']['name']} entry"; + $remaining_caption = "{$ledger['Account']['name']} entry unapplied amount"; + + $rows[] = array($applied_caption, FormatHelper::currency($stats[$type]['amount_reconciled'])); - $rows[] = array("{$debit_ledger['Account']['name']} Amount Remaining:", + $rows[] = array($remaining_caption, FormatHelper::currency($stats[$type]['amount_remaining'])); - } echo $this->element('table', @@ -139,6 +120,31 @@ echo $this->element('table', )); echo '
    ' . "\n"; +echo ('
    ' . "\n"); +foreach ($ledgers AS $type => $ledger) { + $rows = array(); + + $rows[] = array('Account', $html->link($ledger['Account']['name'], + array('controller' => 'accounts', + 'action' => 'view', + $ledger['Account']['id']))); + $rows[] = array('Ledger', $html->link('#' . $ledger['Account']['id'] + . '-' . $ledger['sequence'], + array('controller' => 'ledgers', + 'action' => 'view', + $ledger['id']))); + $rows[] = array('Amount', FormatHelper::currency($entry['amount'])); + $rows[] = array('Effect', $ledger['Account']['ftype'] == $type ? 'INCREASE' : 'DECREASE'); + + echo $this->element('table', + array('class' => array('item', $type, 'detail'), + 'caption' => ucfirst($type) . ' Ledger Entry', + 'rows' => $rows, + 'column_class' => array('field', 'value'))); +} +echo ('
    ' . "\n"); + + /********************************************************************** ********************************************************************** @@ -162,8 +168,8 @@ foreach ($ledgers AS $type => $ledger) { $caption = ('Matching ' . (($type == 'credit') ? 'DEBITS' : 'CREDITS') . ' from Account ' . $ledger['Account']['name']); //$caption = ('Reconciled Entries ' . ($ledger['Account']['ftype'] == $type ? 'OUT OF' : 'INTO') . - $caption = ('Contribution to entries ' . ($ledger['Account']['ftype'] == $type ? 'OUT OF' : 'INTO') . - ' Account ' . $ledger['Account']['name']); + $caption = ('Applied transfers ' . ($ledger['Account']['ftype'] == $type ? 'out of' : 'into') . + ' Account: ' . $ledger['Account']['name']); echo $this->element('ledger_entries', array (// Element configuration 'account_ftype' => $type, diff --git a/site/webroot/css/layout.css b/site/webroot/css/layout.css index 66d861a..41de1e0 100644 --- a/site/webroot/css/layout.css +++ b/site/webroot/css/layout.css @@ -78,6 +78,34 @@ table.item.detail td.value { white-space : normal; } div.detail.supporting { clear : both; padding-top: 1.5em; } +/* Exception for Ledger Entry, which is split over 3 tables */ +.ledger-double-entry { padding-top: 1.0em; + float: left; + clear : left; + width : 60%; +} + +.ledger-double-entry table.item.detail { + width : 45%; +/* border: 2px dashed #0f0; */ +/* margin-left : 5%; */ +/* margin-right : 5%; */ +} + +.ledger-double-entry table.item.detail.debit { +/* margin-left : 2%; */ + float: left; +} + +.ledger-double-entry table.item.detail.credit { +/* margin-right : 2%; */ + float: right; + +} + +/* .ledger-double-entry table.debit { clear: */ + + /************************************************************ ************************************************************ From d44007a358b90ada8b793ece2fc791c533aaea1a Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 11 Jul 2009 00:45:17 +0000 Subject: [PATCH 295/717] Final tweaks (for now) to ledger entry view. Hopefully didn't break other summary boxes. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@301 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/ledger_entries/view.ctp | 19 ++++++++++--------- site/webroot/css/layout.css | 13 +++++++++---- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/site/views/ledger_entries/view.ctp b/site/views/ledger_entries/view.ctp index f516848..ceddf47 100644 --- a/site/views/ledger_entries/view.ctp +++ b/site/views/ledger_entries/view.ctp @@ -97,27 +97,28 @@ echo $this->element('table', */ echo '
    ' . "\n"; -$rows = array(); foreach ($ledgers AS $type => $ledger) { //pr($ledger); if (!$ledger['Account']['trackable']) continue; - $applied_caption = "Transfers applied to {$ledger['Account']['name']} entry"; - $remaining_caption = "{$ledger['Account']['name']} entry unapplied amount"; + $applied_caption = "Transfers applied"; + $remaining_caption = "Unapplied amount"; + $rows = array(); $rows[] = array($applied_caption, FormatHelper::currency($stats[$type]['amount_reconciled'])); $rows[] = array($remaining_caption, FormatHelper::currency($stats[$type]['amount_remaining'])); + echo $this->element('table', + array('class' => 'item summary', + 'caption' => "{$ledger['Account']['name']} Ledger Entry", + 'rows' => $rows, + 'column_class' => array('field', 'value'), + //'suppress_alternate_rows' => true, + )); } -echo $this->element('table', - array('class' => 'summary', - 'rows' => $rows, - 'column_class' => array('field', 'value'), - 'suppress_alternate_rows' => true, - )); echo '
    ' . "\n"; echo ('
    ' . "\n"); diff --git a/site/webroot/css/layout.css b/site/webroot/css/layout.css index 41de1e0..ba93892 100644 --- a/site/webroot/css/layout.css +++ b/site/webroot/css/layout.css @@ -127,21 +127,26 @@ div.detail.supporting { clear : both; div.infobox { float: right; width: 39%; - margin-top: 1.5em; + margin-top: 2.0em; margin-right: 0.5em; } table.summary { margin-left:auto; margin-right:0.5em; - color: #993; + color: #339; font-family:'Gill Sans','lucida grande',helvetica, arial, sans-serif; font-size: 125%; text-align: right; - margin-top: 0.5em; - margin-bottom: 0.2em; + margin-bottom: 1.5em; } +table.summary caption { + font-size: 100%; + text-align: right; + margin-right: 0.6em; + } + table.summary td { padding-left:0.5em; } From 6ce9eec1a42dbe18d0a8f8402ced0418964277e8 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 11 Jul 2009 00:46:31 +0000 Subject: [PATCH 296/717] clean up lingering comments. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@302 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/ledger_entries/view.ctp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/site/views/ledger_entries/view.ctp b/site/views/ledger_entries/view.ctp index ceddf47..8302350 100644 --- a/site/views/ledger_entries/view.ctp +++ b/site/views/ledger_entries/view.ctp @@ -82,7 +82,6 @@ $rows[] = array('Monetary Source', (isset($source['name']) 'action' => 'view', $source['id'])) : null)); -//$rows[] = array('Amount', FormatHelper::currency($entry['amount'])); $rows[] = array('Comment', $entry['comment']); echo $this->element('table', @@ -165,10 +164,6 @@ foreach ($ledgers AS $type => $ledger) { if (!$ledger['Account']['trackable']) continue; - //$verb = ($ledger['Account']['ftype'] == $type) ? 'REDUCTION' : 'INCREASE'; - $caption = ('Matching ' . (($type == 'credit') ? 'DEBITS' : 'CREDITS') . - ' from Account ' . $ledger['Account']['name']); - //$caption = ('Reconciled Entries ' . ($ledger['Account']['ftype'] == $type ? 'OUT OF' : 'INTO') . $caption = ('Applied transfers ' . ($ledger['Account']['ftype'] == $type ? 'out of' : 'into') . ' Account: ' . $ledger['Account']['name']); echo $this->element('ledger_entries', array From 5a1fdedad0d1feead73fbe8b0d6e15ec404539f6 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 11 Jul 2009 01:44:46 +0000 Subject: [PATCH 297/717] Fixed the bank deposit, which was not reconciling the income received with the actual deposit. Thus, there was no way to determine when a particular check, for example, was actually deposited in the bank... the trail was broken. This seems to work. I would like to move some of the logic in Transaction to simply use the Account::postLedgerEntry function, but I'll not do it just yet... other fish and all. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@303 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/accounts_controller.php | 16 +--- site/models/account.php | 95 ++++++++++++++++++++---- 2 files changed, 85 insertions(+), 26 deletions(-) diff --git a/site/controllers/accounts_controller.php b/site/controllers/accounts_controller.php index ed044af..49a4c44 100644 --- a/site/controllers/accounts_controller.php +++ b/site/controllers/accounts_controller.php @@ -164,7 +164,7 @@ class AccountsController extends AppController { array('fields' => array('name')), 'LedgerEntry' => - array('fields' => array('amount'), + array('fields' => array('id', 'amount'), 'MonetarySource' => array('fields' => array('name')), @@ -183,23 +183,15 @@ class AccountsController extends AppController { )); $deposit['total'] += $ledger['amount']; - $deposit['ledgers'][] = array('name' => $ledger['account_name'], + $deposit['ledgers'][] = array('id' => $ledger_id, + 'name' => $ledger['account_name'], 'total' => $ledger['amount'], 'entries' => $ledger_entries); } - // Estabish a set of ledgers to close - $set = array(); - foreach ($this->data['Tillable']['Ledger'] AS $ledger_id => $ledger) { - if (!$ledger['checked'] || $ledger['amount'] == 0) - continue; - $set[] = array('ledger_id' => $ledger_id, 'amount' => $ledger['amount']); - } - // Perform the accounting work necessary to close the // monetary ledgers and deposit into the bank account. - if (count($set) > 0) - $this->Account->closeAndDeposit($set, $this->data['Deposit']['Account']['id']); + $this->Account->closeAndDeposit($deposit['ledgers'], $this->data['Deposit']['Account']['id']); $title = 'Account: Deposit Slip'; $this->set(compact('title', 'deposit')); diff --git a/site/models/account.php b/site/models/account.php index 0c0968c..bd61252 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -155,7 +155,8 @@ class Account extends AppModel { $account = $this->find('all', array ('contain' => array('CurrentLedger'), 'fields' => array('Account.id', 'Account.type', 'Account.name', 'CurrentLedger.id'), - 'conditions' => array('Account.'.$attribute => true) + 'conditions' => array('Account.'.$attribute => true), + 'order' => array('Account.name'), ) + (isset($extra) ? $extra : array()) ); $this->cacheQueries = false; @@ -490,7 +491,8 @@ class Account extends AppModel { function postLedgerEntry($transaction_data, $monetary_data, - $entry_data) { + $entry_data, + $reconcile = null) { /* if (!isset($entry_data) || */ /* !isset($entry_data['amount']) || */ @@ -608,18 +610,69 @@ class Account extends AppModel { //pr(array('pre-save', compact('entry_data'))); // Create it! - $entry = new LedgerEntry(); - $entry->create(); - if (!$entry->saveAll($entry_data, array('validate'=>false))) { - return false; + $new_entry = new LedgerEntry(); + $new_entry->create(); + if (!$new_entry->saveAll($entry_data, array('validate'=>false))) { + return array('error' => true); } - $entry->recursive = -1; - $entry->read(); + + // See if the user has entered some sort of non-array + // for the reconcile parameter. + if (isset($reconcile) && is_bool($reconcile) && $reconcile) { + $reconcile = array('debit' => true, 'credit' => true); + } + elseif (!isset($reconcile) || !is_array($reconcile)) { + $reconcile = array(); + } + + // Reconcile the new entry... assume we'll have success + $err = false; + foreach (array_intersect_key($reconcile, array('credit'=>1,'debit'=>1)) + AS $dr => $reconcile_set) { + if (!isset($reconcile_set) || (is_bool($reconcile_set) && !$reconcile_set)) + continue; + + if (is_bool($reconcile_set) && $reconcile_set) { + // REVISIT : 20090710 + // Take the reconcile code from the Transaction model, + // which utilizes reconcileNewLedgerEntry, and insert + // it here so that we can migrate the bulk of the + // functions addReceipt and addInvoice + } + + if (is_array($reconcile_set)) { + foreach ($reconcile_set AS $reconcile_entry) { + $amount = $reconcile_entry['LedgerEntry']['amount']; + if (!$amount) + continue; + + if ($dr == 'debit') { + $debit_ledger_entry_id = $new_entry->id; + $credit_ledger_entry_id = $reconcile_entry['LedgerEntry']['id']; + } + else { + $debit_ledger_entry_id = $reconcile_entry['LedgerEntry']['id']; + $credit_ledger_entry_id = $new_entry->id; + } + + $R = new Reconciliation(); + $R->create(); + if (!$R->save(compact('amount', + 'debit_ledger_entry_id', + 'credit_ledger_entry_id'), false)) + $err = true; + } + } + } + + $new_entry->recursive = -1; + $new_entry->read(); //pr(array('post-save', $entry->data)); - return array('transaction_id' => $entry->data['LedgerEntry']['transaction_id'], - 'monetary_source_id' => $entry->data['LedgerEntry']['monetary_source_id'], - 'id' => $entry->data['LedgerEntry']['id']); + return array('error' => $err, + 'id' => $new_entry->data['LedgerEntry']['id'], + 'transaction_id' => $new_entry->data['LedgerEntry']['transaction_id'], + 'monetary_source_id' => $new_entry->data['LedgerEntry']['monetary_source_id']); } @@ -640,14 +693,28 @@ class Account extends AppModel { $transaction = array(); foreach ($set AS $ledger) { + // REVISIT : 20090710 + // If the user said to include a ledger in the + // set, should we really be excluding it? + if ($ledger['total'] == 0) + continue; + $ids = $this->postLedgerEntry ($transaction, null, array('debit_account_id' => $deposit_account_id, - 'credit_ledger_id' => $ledger['ledger_id'], - 'amount' => $ledger['amount'])); + 'credit_ledger_id' => $ledger['id'], + 'amount' => $ledger['total']), + // Reconcile the account for cash/check/etc, + // which is the credit side of this entry. + array('credit' => $ledger['entries'])); + + if ($ids['error']) + die("closeAndDeposit : postLedgerEntry returned error!"); + $transaction = array_intersect_key($ids, array('transaction_id'=>1)); - $this->Ledger->closeLedger($ledger['ledger_id'], $close->id); + + $this->Ledger->closeLedger($ledger['id'], $close->id); } } From 4b43433d2d08525b3d3325e6a55b709780902bcd Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 11 Jul 2009 01:52:32 +0000 Subject: [PATCH 298/717] Fixed a bug causing leder_entry lists to only list one item from each transaction (although the numbers were right, the other ledger_entry fields were not). This was due to the changes I made to ledger_entries.ctp when moving everything to the Grid Helper. Prior to that, the default was to group by transactions, unless notxgroup was defined. Since it was experimental, it was hardcoded to false in the ledger_entries element, so there was no problem. After Grid Helper, it was inadvertantly deleted, hence the bug. I changed the default to be NOT to group by transaction, and also invalidate the ledger_entry fields when we do group that way. So, this bug should be put mostly to rest, although I don't like converting the ledger_entry list into a simple transaction list (we do have another element for that after all). Oh well, works for now. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@304 97e9348a-65ac-dc4b-aefc-98561f571b83 --- .../controllers/ledger_entries_controller.php | 6 +-- site/views/accounts/view.ctp | 1 + site/views/elements/ledger_entries.ctp | 40 ++++++++++++++++--- site/views/ledgers/view.ctp | 1 + site/views/transactions/view.ctp | 6 ++- 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index cb370ad..25cd6f6 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -221,10 +221,10 @@ class LedgerEntriesController extends AppController { } function jqGridDataGroup(&$params, &$model) { - if (isset($params['custom']['notxgroup'])) - return parent::jqGridDataGroup($params, $model); + if (isset($params['custom']['group_by_tx']) && $params['custom']['group_by_tx']) + return $model->alias.'.transaction_id'; - return $model->alias.'.transaction_id'; + return parent::jqGridDataGroup($params, $model); } function jqGridDataOrder(&$params, &$model, $index, $direction) { diff --git a/site/views/accounts/view.ctp b/site/views/accounts/view.ctp index a041e52..fd17d41 100644 --- a/site/views/accounts/view.ctp +++ b/site/views/accounts/view.ctp @@ -70,6 +70,7 @@ echo $this->element('ledger_entries', array (// Element configuration 'ledger_id' => $account['CurrentLedger']['id'], 'account_type' => $account['Account']['type'], + 'group_by_tx' => true, // Grid configuration 'config' => array diff --git a/site/views/elements/ledger_entries.ctp b/site/views/elements/ledger_entries.ctp index a0a2bba..5770a1a 100644 --- a/site/views/elements/ledger_entries.ctp +++ b/site/views/elements/ledger_entries.ctp @@ -28,12 +28,37 @@ $cols['Applied'] = array('index' => "Reconciliation.amount", 'formatter' $cols['Sub-Total'] = array('index' => 'subtotal', 'formatter' => 'currency', 'sortable' => false); +// Since group_by_tx is a boolean, let's just get it +// defined, regardless of whether the caller did so. +// group_by_tx will cause all entry fields to be +// invalidated, and will leave only the transaction +// fields. Yes... the caller should just use the +// transactions element instead, in theory. However, +// it hasn't yet been implemented to the level of +// this element, and additionally, the transactions +// element will not allow for customer information +// (rightly so, since it's a ledger_entry field). +// However, at the current implementation, all ledger +// entries of a transaction are for the same customer. +// So... we allow it for now. +if (!isset($group_by_tx)) + $group_by_tx = false; + +if (isset($transaction_id) || isset($reconcile_id)) + $grid->invalidFields('Transaction'); + +if ($group_by_tx) + $grid->invalidFields('Entry'); + +if ($group_by_tx) + $grid->invalidFields(array('Effective', 'Through')); + if (isset($account_ftype) || isset($ledger_id) || isset($account_id) || isset($ar_account)) $grid->invalidFields(array('Debit Account', 'Credit Account')); else $grid->invalidFields('Account'); -if (isset($no_account)) +if (isset($no_account) || $group_by_tx) $grid->invalidFields(array('Account', 'Debit Account', 'Credit Account')); if (isset($ledger_id) || isset($account_id) || isset($ar_account)) @@ -41,10 +66,13 @@ if (isset($ledger_id) || isset($account_id) || isset($ar_account)) else $grid->invalidFields(array('Debit', 'Credit')); +// group_by_tx SHOULD wipe out Customer, but the reality +// is that it works good at the present, so we'll leave it. if (isset($lease_id) || isset($customer_id)) - $grid->invalidFields(array('Customer', 'Lease', 'Unit')) - // Invoice/Receipt accounts don't use effective/through - ->invalidFields(array('Effective', 'Through')); + $grid->invalidFields(array('Customer')) + +if (isset($lease_id) || $group_by_tx) + $grid->invalidFields(array('Lease', 'Unit')) if (!isset($reconcile_id)) $grid->invalidFields('Applied'); @@ -59,7 +87,7 @@ if (!isset($config['rows'])) { } if (isset($reconcile_id)) { - $grid->customData(compact('reconcile_id'))->limit(5); + $grid->customData(compact('reconcile_id'))->limit(20); } // Set up search fields if requested by caller @@ -69,7 +97,7 @@ if (isset($searchfields)) // Include custom data $grid->customData(compact('ledger_id', 'account_id', 'ar_account', 'account_type', 'account_ftype', - 'customer_id', 'lease_id', 'transaction_id', 'notxgroup')); + 'customer_id', 'lease_id', 'transaction_id', 'group_by_tx')); // Render the grid $grid diff --git a/site/views/ledgers/view.ctp b/site/views/ledgers/view.ctp index de10d73..aa3c27f 100644 --- a/site/views/ledgers/view.ctp +++ b/site/views/ledgers/view.ctp @@ -67,6 +67,7 @@ echo $this->element('ledger_entries', array (// Element configuration 'ledger_id' => $ledger['id'], 'account_type' => $account['type'], + 'group_by_tx' => true, // Grid configuration 'config' => array diff --git a/site/views/transactions/view.ctp b/site/views/transactions/view.ctp index 081138d..5c6f02a 100644 --- a/site/views/transactions/view.ctp +++ b/site/views/transactions/view.ctp @@ -54,7 +54,11 @@ echo '
    ' . "\n"; echo $this->element('ledger_entries', array (// Element configuration 'transaction_id' => $transaction['Transaction']['id'], - 'notxgroup' => true, + + // Default for grouping by transaction is already false, + // but we'll get explicit here, since we clearly want to + // see all of the ledger entries not grouped by tx. + 'group_by_tx' => false, // Grid configuration 'config' => array From 546766d9be6f74c18b481e67bc23a89c65b08152 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 11 Jul 2009 07:24:14 +0000 Subject: [PATCH 299/717] Fixed stupid syntax error git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@305 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/ledger_entries.ctp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/views/elements/ledger_entries.ctp b/site/views/elements/ledger_entries.ctp index 5770a1a..2dca8c6 100644 --- a/site/views/elements/ledger_entries.ctp +++ b/site/views/elements/ledger_entries.ctp @@ -69,10 +69,10 @@ else // group_by_tx SHOULD wipe out Customer, but the reality // is that it works good at the present, so we'll leave it. if (isset($lease_id) || isset($customer_id)) - $grid->invalidFields(array('Customer')) + $grid->invalidFields(array('Customer')); if (isset($lease_id) || $group_by_tx) - $grid->invalidFields(array('Lease', 'Unit')) + $grid->invalidFields(array('Lease', 'Unit')); if (!isset($reconcile_id)) $grid->invalidFields('Applied'); From e067af589cdb2ce2e1b56509cb9b7169745987b4 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 11 Jul 2009 07:26:17 +0000 Subject: [PATCH 300/717] Moved invoice/receipt code into Account. It appears to be broken in that the receipt ledger_entries are all getting a uniqe transaction. I'll have to look at this tomorrow. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@306 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/account.php | 136 ++++++++++++------ site/models/transaction.php | 265 ++++++++---------------------------- 2 files changed, 145 insertions(+), 256 deletions(-) diff --git a/site/models/account.php b/site/models/account.php index bd61252..24494cb 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -117,6 +117,8 @@ class Account extends AppModel { function taxAccountID() { return $this->nameToID('Tax'); } function accountReceivableAccountID() { return $this->nameToID('A/R'); } function cashAccountID() { return $this->nameToID('Cash'); } + function checkAccountID() { return $this->nameToID('Check'); } + function moneyOrderAccountID() { return $this->nameToID('Money Order'); } function pettyCashAccountID() { return $this->nameToID('Petty Cash'); } function invoiceAccountID() { return $this->nameToID('Invoice'); } function receiptAccountID() { return $this->nameToID('Receipt'); } @@ -493,23 +495,24 @@ class Account extends AppModel { $monetary_data, $entry_data, $reconcile = null) { - -/* if (!isset($entry_data) || */ -/* !isset($entry_data['amount']) || */ -/* !$entry_data['amount']) */ -/* return false; */ - + // Create some models for convenience $A = new Account(); -/* // Create a transaction if necessary */ -/* if (!isset($transaction_data['id'])) { */ -/* $transaction = new Transaction(); */ -/* $transaction->create(); */ -/* if (!$transaction->save($transaction_data, false)) { */ -/* return false; */ -/* } */ -/* $transaction_data['id'] = $transaction->id; */ -/* } */ + pr(compact('transaction_data', 'monetary_data', 'entry_data', 'reconcile')); + + // Automatically figure out the customer if we have the lease + if (isset($entry_data['lease_id']) && !isset($entry_data['customer_id'])) { + $L = new Lease(); + $L->recursive = -1; + $lease = $L->read(null, $entry_data['lease_id']); + $entry_data['customer_id'] = $lease['Lease']['customer_id']; + } + + if (!isset($entry_data['lease_id'])) + $entry_data['lease_id'] = null; + + if (!isset($entry_data['customer_id'])) + $entry_data['customer_id'] = null; // Get the Transaction squared away if (isset($transaction_data['transaction_id'])) { @@ -528,17 +531,25 @@ class Account extends AppModel { // Get the Monetary Source squared away - if (isset($monetary_data['monetary_source_id'])) { - $monetary_data - = array_intersect_key($monetary_data, - array('monetary_source_id'=>1)); - } - elseif (isset($monetary_data['account_name'])) { - if ($monetary_data['account_name'] === 'Cash') { - // No distinguishing features of Cash, just - // use the shared monetary source - $monetary_data['monetary_source_id'] = - $this->Ledger->LedgerEntry->MonetarySource->nameToID('Cash'); + if (isset($monetary_data)) { + if (!isset($monetary_data['monetary_source_id'])) { + + // Convert Account ID to name or vice versa + if (isset($monetary_data['account_id'])) { + $monetary_data['account_name'] = $A->name($monetary_data['account_id']); + } elseif (isset($monetary_data['account_name'])) { + $monetary_data['account_id'] = $A->nameToID($monetary_data['account_name']); + } + + if ($monetary_data['account_id'] == $A->cashAccountID()) { + // No distinguishing features of Cash, just + // use the shared monetary source + $monetary_data['monetary_source_id'] = + $this->Ledger->LedgerEntry->MonetarySource->nameToID('Cash'); + } + } + + if (isset($monetary_data['monetary_source_id'])) { $monetary_data = array_intersect_key($monetary_data, array('monetary_source_id'=>1)); @@ -548,25 +559,17 @@ class Account extends AppModel { // Create a new one dedicated to this entry // Give it a fancy name based on the check number $monetary_data['MonetarySource']['name'] = $monetary_data['account_name']; - if ($monetary_data['account_name'] === 'Check' || - $monetary_data['account_name'] === 'Money Order') { + if ($monetary_data['account_name'] === $A->name($A->checkAccountID()) || + $monetary_data['account_name'] === $A->name($A->moneyOrderAccountID())) { $monetary_data['MonetarySource']['name'] .= ' #' . $monetary_data['MonetarySource']['data1']; } - else { - $monetary_data['MonetarySource']['name'] = $monetary_data['account_name']; - } $monetary_data = array_intersect_key($monetary_data, array('MonetarySource'=>1)); } } - elseif (isset($monetary_data)) { - $monetary_data - = array_intersect_key($monetary_data, - array('MonetarySource'=>1)); - } else { $monetary_data = array(); } @@ -621,6 +624,12 @@ class Account extends AppModel { if (isset($reconcile) && is_bool($reconcile) && $reconcile) { $reconcile = array('debit' => true, 'credit' => true); } + elseif (isset($reconcile) && $reconcile == 'invoice') { + $reconcile = array('credit' => 'invoice'); + } + elseif (isset($reconcile) && $reconcile == 'receipt') { + $reconcile = array('debit' => 'receipt'); + } elseif (!isset($reconcile) || !is_array($reconcile)) { $reconcile = array(); } @@ -628,25 +637,63 @@ class Account extends AppModel { // Reconcile the new entry... assume we'll have success $err = false; foreach (array_intersect_key($reconcile, array('credit'=>1,'debit'=>1)) - AS $dr => $reconcile_set) { + AS $dc_type => $reconcile_set) { if (!isset($reconcile_set) || (is_bool($reconcile_set) && !$reconcile_set)) continue; - if (is_bool($reconcile_set) && $reconcile_set) { - // REVISIT : 20090710 - // Take the reconcile code from the Transaction model, - // which utilizes reconcileNewLedgerEntry, and insert - // it here so that we can migrate the bulk of the - // functions addReceipt and addInvoice + if ($reconcile_set === 'receipt') { + $C = new Customer(); + $reconciled = $C->reconcileNewLedgerEntry($entry_data['customer_id'], + $this->fundamentalOpposite($dc_type), + $entry_data['amount']); + + pr(array("reconcile receipt", + compact('reconciled', 'split_transaction', 'transaction_data'))); + $split_transaction = array_intersect_key($transaction_data, + array('Transaction'=>1)); + if (is_array($reconciled) && count($reconciled[$dc_type]['entry'])) { + foreach ($reconciled[$dc_type]['entry'] AS $rec) { + //.pr(compact('rec')); + if (!$rec['applied']) + continue; + + // Create an entry to handle the splitting of the funds ("Payment") + // and reconcile against the new cash/check/etc entry created above, + // as well as the A/R account. + + // Payment must debit the Receipt ledger, and credit the A/R ledger + // debit: Receipt credit: A/R + $ids = $this->postLedgerEntry + ($split_transaction, + null, + array('debit_ledger_id' => $A->currentLedgerID($A->receiptAccountID()), + 'credit_ledger_id' => $A->currentLedgerID($A->accountReceivableAccountID()), + 'amount' => $rec['applied'], + 'lease_id' => $rec['lease_id'], + 'customer_id' => $rec['customer_id'], + ), + array('debit' => array(array('LedgerEntry' => array('id' => $new_entry->id, + 'amount' => $rec['applied']))), + 'credit' => array(array('LedgerEntry' => array('id' => $rec['id'], + 'amount' => $rec['applied'])))) + ); + // Keep using the same split transaction for all reconciled entries + $split_transaction = array_intersect_key($ids, array('transaction_id'=>1)); + pr(compact('ids', 'split_transaction')); + } + } } if (is_array($reconcile_set)) { foreach ($reconcile_set AS $reconcile_entry) { + if (!isset($reconcile_entry['LedgerEntry']['id'])) + continue; + $amount = $reconcile_entry['LedgerEntry']['amount']; if (!$amount) continue; - if ($dr == 'debit') { + if ($dc_type == 'debit') { $debit_ledger_entry_id = $new_entry->id; $credit_ledger_entry_id = $reconcile_entry['LedgerEntry']['id']; } @@ -708,6 +755,7 @@ class Account extends AppModel { // Reconcile the account for cash/check/etc, // which is the credit side of this entry. array('credit' => $ledger['entries'])); + //pr(compact('ids')); if ($ids['error']) die("closeAndDeposit : postLedgerEntry returned error!"); diff --git a/site/models/transaction.php b/site/models/transaction.php index 52699a6..baa645c 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -23,108 +23,55 @@ class Transaction extends AppModel { */ function addInvoice($data, $customer_id, $lease_id = null) { - - // Sanitize the data - if (!$data['Transaction']['comment']) - $data['Transaction']['comment'] = null; - - // Automatically figure out the customer if we have the lease - if ($lease_id && !$customer_id) { - $L = new Lease(); - $L->recursive = -1; - $lease = $L->read(null, $lease_id); - $customer_id = $lease['Lease']['customer_id']; - } - - // Invoice must be attributed to _someone_ - if (!$customer_id) - return false; - // Create some models for convenience $A = new Account(); + //pr(compact('data', 'customer_id', 'lease_id')); + + // Assume this will succeed + $ret = true; + // Determine the total charges on the invoice $grand_total = 0; foreach ($data['LedgerEntry'] AS $entry) $grand_total += $entry['amount']; - // Create a transaction for the invoice - $invoice_transaction = new Transaction(); - $invoice_transaction->create(); - if (!$invoice_transaction->save($data['Transaction'], false)) - return false; - - // Create a transaction for the A/R - $ar_transaction = new Transaction(); - $ar_transaction->create(); - if (!$ar_transaction->save($data['Transaction'], false)) - return false; - - // Create an account receivable entry - // I would prefer to do this last, as it feels more - // logical to me that the entries would flow from the - // charge to the A/R, but in reality it makes no - // difference to the end result. Entering the A/R - // first allows us to reconcile each charge on the - // invoice as we enter them. Otherwise, we would - // need to loop again at the end to reconcile, and - // would need to save each charge entry id in the - // interim. This keeps the logic simple. - // debit: A/R credit: Invoice - $ar_entry_data = array - ('debit_ledger_id' => $A->currentLedgerID($A->accountReceivableAccountID()), - 'credit_ledger_id' => $A->currentLedgerID($A->invoiceAccountID()), - 'transaction_id' => $ar_transaction->id, - 'amount' => $grand_total, - 'lease_id' => $lease_id, - 'customer_id' => $customer_id, - ); - - // Create a new A/R entry from the data - $ar_entry = new LedgerEntry(); - $ar_entry->create(); - if (!$ar_entry->save($ar_entry_data, false)) - return false; + $ids = $this->LedgerEntry->Ledger->Account->postLedgerEntry + (array_intersect_key($data, array('Transaction'=>1, 'transaction_id'=>1)), + null, + array('debit_ledger_id' => $A->currentLedgerID($A->accountReceivableAccountID()), + 'credit_ledger_id' => $A->currentLedgerID($A->invoiceAccountID()), + 'customer_id' => $customer_id, + 'lease_id' => $lease_id, + 'amount' => $grand_total)); + $ar_entry_id = $ids['id']; // Go through the entered charges + $invoice_transaction = array_intersect_key($data, array('Transaction'=>1, 'transaction_id'=>1)); foreach ($data['LedgerEntry'] AS $entry) { - // Invoice Transaction - // debit: Invoice credit: Charge - $entry['transaction_id'] = $invoice_transaction->id; + //pr(compact('entry')); + // Create the receipt entry, and reconcile the credit side + // of the double-entry (which should be A/R) as a payment. + $ids = $this->LedgerEntry->Ledger->Account->postLedgerEntry + ($invoice_transaction, + array_intersect_key($entry, array('MonetarySource'=>1)) + + array_intersect_key($entry, array('account_id'=>1)), + array('debit_ledger_id' => $A->currentLedgerID($A->invoiceAccountID()), + 'credit_ledger_id' => $A->currentLedgerID($entry['account_id']), + 'customer_id' => $customer_id, + 'lease_id' => $lease_id) + + $entry, + array('debit' => array(array('LedgerEntry' => array('id' => $ar_entry_id, + 'amount' => $entry['amount'])))) + ); - // Debit the "invoice" asset... - $entry['debit_ledger_id'] - = $A->currentLedgerID($A->invoiceAccountID()); + if ($ids['error']) + $ret = false; - // ...and credit the charge ledger - $entry['credit_ledger_id'] - = $A->currentLedgerID($entry['account_id']); - - $entry['customer_id'] = $customer_id; - $entry['lease_id'] = $lease_id; - - // Create it - $invoice_entry = new LedgerEntry(); - $invoice_entry->create(); - if (!$invoice_entry->save($entry, false)) - return false; - - // Reconcile the Invoice account. Our two entries are: - // debit: Invoice credit: Charge - // debit: A/R credit: Invoice - // Since this is from the perspective of the Invoice account, - // the credit entry is the Invoice<->A/R, and the debit - // entry is the actual invoice ledger entry. - $R = new Reconciliation(); - $R->create(); - if (!$R->save(array('debit_ledger_entry_id' => $invoice_entry->id, - 'credit_ledger_entry_id' => $ar_entry->id, - 'amount' => $entry['amount']), false)) - return false; + $invoice_transaction = array_intersect_key($ids, array('transaction_id'=>1)); } - // Return indication of success - return true; + return $ret; } @@ -136,141 +83,35 @@ class Transaction extends AppModel { */ function addReceipt($data, $customer_id, $lease_id = null) { - // Sanitize the data - if (!$data['Transaction']['comment']) - $data['Transaction']['comment'] = null; - // Create some models for convenience $A = new Account(); - $C = new Customer(); - // Receipt must be paid by _someone_ - // REVISIT 20090706: - // Will we really disallow anonymous payments? - if (!$customer_id) - return false; - - // Create a transaction for the receipt - $receipt_transaction = new Transaction(); - $receipt_transaction->create(); - if (!$receipt_transaction->save($data['Transaction'], false)) - return false; - - // Create a transaction for the splits - $split_transaction = new Transaction(); - $split_transaction->create(); - if (!$split_transaction->save($data['Transaction'], false)) - return false; + // Assume this will succeed + $ret = true; // Go through the entered payments + $receipt_transaction = array_intersect_key($data, array('Transaction'=>1, 'transaction_id'=>1)); foreach ($data['LedgerEntry'] AS $entry) { + // Create the receipt entry, and reconcile the credit side + // of the double-entry (which should be A/R) as a payment. + $ids = $this->LedgerEntry->Ledger->Account->postLedgerEntry + ($receipt_transaction, + array_intersect_key($entry, array('MonetarySource'=>1)) + + array_intersect_key($entry, array('account_id'=>1)), + array('debit_ledger_id' => $A->currentLedgerID($entry['account_id']), + 'credit_ledger_id' => $A->currentLedgerID($A->receiptAccountID()), + 'customer_id' => $customer_id, + 'lease_id' => $lease_id) + + $entry, + 'receipt'); - // Get the Monetary Source squared away - if ($entry['account_id'] == $A->cashAccountID()) { - // No distinguishing features of Cash, just - // use the shared monetary source - $entry['monetary_source_id'] = - $this->LedgerEntry->MonetarySource->nameToID('Cash'); - unset($entry['MonetarySource']); - } - elseif (isset($entry['MonetarySource'])) { - $entry['MonetarySource']['name'] = $A->name($entry['account_id']); + if ($ids['error']) + $ret = false; - // Give it a fancy name based on the check number - if ($A->name($entry['account_id']) === 'Check' || - $A->name($entry['account_id']) === 'Money Order') { - $entry['MonetarySource']['name'] .= - ' #' . $entry['MonetarySource']['data1']; - } - } - - // This entry of physical money is part of the receipt transaction - // debit: Cash/Check/Etc credit: Receipt - $entry['transaction_id'] = $receipt_transaction->id; - - // Receipt must debit the "money" asset (bank, cash, check, etc)... - $entry['debit_ledger_id'] - = $A->currentLedgerID($entry['account_id']); - - // ...and credit the Receipt ledger - $entry['credit_ledger_id'] - = $A->currentLedgerID($A->receiptAccountID()); - - $entry['customer_id'] = $customer_id; - $entry['lease_id'] = $lease_id; - - // Create it - $receipt_entry = new LedgerEntry(); - $receipt_entry->create(); - if (!$receipt_entry->saveAll($entry, - array('validate' => false, - ))) - return false; - - $reconciled = $C->reconcileNewLedgerEntry($customer_id, - 'credit', - $entry['amount']); - - foreach (array_merge($reconciled['debit']['entry'], array - (array('id' => null, - 'applied' => $reconciled['debit']['unapplied'], - 'customer_id' => $customer_id, - 'lease_id' => null))) AS $rec) { - if (!$rec['applied']) - continue; - - // Create an entry to handle the splitting of the funds ("Payment") - // Payment must debit the Receipt ledger, and credit the A/R ledger - // debit: Receipt credit: A/R - $split_entry_data = array - ('debit_ledger_id' => $A->currentLedgerID($A->receiptAccountID()), - 'credit_ledger_id' => $A->currentLedgerID($A->accountReceivableAccountID()), - 'transaction_id' => $split_transaction->id, - 'amount' => $rec['applied'], - 'lease_id' => $rec['lease_id'], - 'customer_id' => $rec['customer_id'], - ); - - // Create a new split entry from the data - $split_entry = new LedgerEntry(); - $split_entry->create(); - if (!$split_entry->save($split_entry_data, false)) - return false; - - // Reconcile the Receipt account. Our two entries are: - // debit: Cash/Check/Etc credit: Receipt - // debit: Receipt credit: A/R - // Since this is from the perspective of the Receipt account, - // the debit entry is the Receipt<->A/R, and the credit - // entry is the actual receipt ledger entry. - $R = new Reconciliation(); - $R->create(); - if (!$R->save(array('debit_ledger_entry_id' => $split_entry->id, - 'credit_ledger_entry_id' => $receipt_entry->id, - 'amount' => $rec['applied']), false)) - return false; - - // Only reconcile the A/R account if we have an entry - // to reconcile with, otherwise, just go on. - if (!$rec['id']) - continue; - - // Reconcile the A/R account. Our two entries look like: - // debit: Receipt credit: A/R - // debit: A/R credit: Invoice - // Since this is from the perspective of the A/R account, - // the debit entry is the Invoice<->A/R, and the credit - // entry is the Receipt<->A/R. - $R = new Reconciliation(); - $R->create(); - if (!$R->save(array('debit_ledger_entry_id' => $rec['id'], - 'credit_ledger_entry_id' => $split_entry->id, - 'amount' => $rec['applied']), false)) - return false; - } + $receipt_transaction = array_intersect_key($ids, array('transaction_id'=>1)); } - return true; + return $ret; } } From 860006ed389eef8bf07c8cb7d7679f68a5792a8b Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 11 Jul 2009 08:10:23 +0000 Subject: [PATCH 301/717] Not terribly happy with the solution to the extra transactions problem noted on the last checkin (however, it does seem to be working). I simply keep a record of the split transaction id, pass it back to the caller, and expect it to be passed back in. Works for now, even if it isn't terribly elegant. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@307 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/account.php | 42 ++++++++++++++++++++++++++----------- site/models/transaction.php | 4 +++- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/site/models/account.php b/site/models/account.php index 24494cb..ab6fa13 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -498,7 +498,7 @@ class Account extends AppModel { // Create some models for convenience $A = new Account(); - pr(compact('transaction_data', 'monetary_data', 'entry_data', 'reconcile')); + //pr(compact('transaction_data', 'monetary_data', 'entry_data', 'reconcile')); // Automatically figure out the customer if we have the lease if (isset($entry_data['lease_id']) && !isset($entry_data['customer_id'])) { @@ -518,12 +518,14 @@ class Account extends AppModel { if (isset($transaction_data['transaction_id'])) { $transaction_data = array_intersect_key($transaction_data, - array('transaction_id'=>1)); + array('transaction_id'=>1, + 'split_transaction_id'=>1)); } elseif (isset($transaction_data['Transaction'])) { $transaction_data = array_intersect_key($transaction_data, - array('Transaction'=>1)); + array('Transaction'=>1, + 'split_transaction_id'=>1)); } else { $transaction_data = array('Transaction'=>array('stamp' => null)); @@ -647,13 +649,18 @@ class Account extends AppModel { $this->fundamentalOpposite($dc_type), $entry_data['amount']); - pr(array("reconcile receipt", - compact('reconciled', 'split_transaction', 'transaction_data'))); +/* pr(array("reconcile receipt", */ +/* compact('reconciled', 'split_transaction', 'transaction_data'))); */ $split_transaction = array_intersect_key($transaction_data, - array('Transaction'=>1)); + array('Transaction'=>1, + 'split_transaction_id'=>1)); + + if (isset($split_transaction['split_transaction_id'])) + $split_transaction['transaction_id'] = $split_transaction['split_transaction_id']; + if (is_array($reconciled) && count($reconciled[$dc_type]['entry'])) { foreach ($reconciled[$dc_type]['entry'] AS $rec) { - //.pr(compact('rec')); + //pr(compact('rec', 'split_transaction')); if (!$rec['applied']) continue; @@ -679,12 +686,17 @@ class Account extends AppModel { ); // Keep using the same split transaction for all reconciled entries $split_transaction = array_intersect_key($ids, array('transaction_id'=>1)); - pr(compact('ids', 'split_transaction')); + //pr(compact('ids', 'split_transaction')); } + + //pr("end reconciled is array"); } + + //pr("end reconcile receipt"); } if (is_array($reconcile_set)) { + //pr("reconcile_set is array"); foreach ($reconcile_set AS $reconcile_entry) { if (!isset($reconcile_entry['LedgerEntry']['id'])) continue; @@ -716,10 +728,16 @@ class Account extends AppModel { $new_entry->read(); //pr(array('post-save', $entry->data)); - return array('error' => $err, - 'id' => $new_entry->data['LedgerEntry']['id'], - 'transaction_id' => $new_entry->data['LedgerEntry']['transaction_id'], - 'monetary_source_id' => $new_entry->data['LedgerEntry']['monetary_source_id']); + $ret = array + ('error' => $err, + 'id' => $new_entry->data['LedgerEntry']['id'], + 'transaction_id' => $new_entry->data['LedgerEntry']['transaction_id'], + 'monetary_source_id' => $new_entry->data['LedgerEntry']['monetary_source_id']); + + if (isset($split_transaction['transaction_id'])) + $ret['split_transaction_id'] = $split_transaction['transaction_id']; + + return $ret; } diff --git a/site/models/transaction.php b/site/models/transaction.php index baa645c..27f739a 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -108,7 +108,9 @@ class Transaction extends AppModel { if ($ids['error']) $ret = false; - $receipt_transaction = array_intersect_key($ids, array('transaction_id'=>1)); + $receipt_transaction = array_intersect_key($ids, + array('transaction_id'=>1, + 'split_transaction_id'=>1)); } return $ret; From ece7ab25ae659c071deafea1d755f3022450c037 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 11 Jul 2009 08:23:55 +0000 Subject: [PATCH 302/717] Eliminated the need for the Invoice Account. I'm having a bit of a hard time believing that it works, since it sure seems like we needed the Invoice account for some reason. However, it's entirely possible that we really just had it for symmetry with Receipt (another account which we'd love to delete). It needs more testing, but it works good enough to check in. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@308 97e9348a-65ac-dc4b-aefc-98561f571b83 --- scripts/sitelink2pmgr.pl | 380 ++++++++---------------------------- site/models/transaction.php | 16 +- 2 files changed, 84 insertions(+), 312 deletions(-) diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 54bd007..5fd40ff 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -4,7 +4,8 @@ use DBI; use Data::Dumper; use File::Copy; -my $use_ir = 1; +my $use_invoice = 0; +my $use_receipt = 1; # Internally adjust all numbers coming from the database to # be in inches. Not necessary to go to this detail, but the @@ -926,6 +927,7 @@ foreach $row (@{query($sdbh, $query)}) { addRow('transactions', { 'stamp' => $stamp, + #'comment' => "Invoice Transaction", }); $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}} @@ -945,39 +947,51 @@ foreach $row (@{query($sdbh, $query)}) { ]{'deposit'} = $row->{'ChargeAmount'}; } - addRow('transactions', - { 'stamp' => $stamp, - }); - - $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'charge_tx'} - = $newdb{'tables'}{'transactions'}{'autoid'}; - # Invoice must debit the A/R ledger... $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'debit_ledger_id'} = $newdb{'lookup'}{'account'}{'A/R'}{'ledger_id'}; - # ...and credit the Invoice ledger. - $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'credit_ledger_id'} - = $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}; + if ($use_invoice) { + addRow('transactions', + { 'stamp' => $stamp, + #'comment' => "Charges Transaction", + }); - # Create the invoice entry - # debit: A/R credit: Invoice - addRow('ledger_entries', - { 'effective_date' => $effective_date, - 'through_date' => $through_date, - 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, - 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'tx'}, - 'root_transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'charge_tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'debit_ledger_id'}, - 'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'credit_ledger_id'}, - 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'customer_id'}, - 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'lease_id'}, - 'amount' => $row->{'InvoiceAmount'}, - #'comment' => "Invoice: Charge: $row->{'ChargeID'}", - }); + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'charge_tx'} + = $newdb{'tables'}{'transactions'}{'autoid'}; + + # ...and credit the Invoice ledger. + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'credit_ledger_id'} + = $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}; + + # Create the invoice entry + # debit: A/R credit: Invoice + addRow('ledger_entries', + { 'effective_date' => $effective_date, + 'through_date' => $through_date, + 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'tx'}, + 'root_transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'charge_tx'}, + 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'debit_ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'credit_ledger_id'}, + 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'customer_id'}, + 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'lease_id'}, + 'amount' => $row->{'InvoiceAmount'}, + #'comment' => "Invoice: Charge: $row->{'ChargeID'}", + }); + + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'} + = $newdb{'tables'}{'ledger_entries'}{'autoid'}; + } + else { + # OK, no invoice ledger + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'charge_tx'} + = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'tx'}; + + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'credit_ledger_id'} + = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'debit_ledger_id'}; + } - $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'} - = $newdb{'tables'}{'ledger_entries'}{'autoid'}; } @@ -998,11 +1012,11 @@ foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'} = $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease_id'}; - # Charge must credit the invoice ledger... + # Charge must credit the Charge ledger... $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'credit_ledger_id'} = $newdb{'lookup'}{'charge_type'}{$row->{'ChargeDescription'}}{'ledger_id'}; - # ...and debit the A/R ledger. + # ...and debit the Invoice ledger. $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'debit_ledger_id'} = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'credit_ledger_id'}; @@ -1018,23 +1032,29 @@ foreach $row (@{query($sdbh, $query)}) { 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, 'amount' => $row->{'ChargeAmount'}, - #'comment' => "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}", + #'comment' => "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}", }); $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'} = $newdb{'tables'}{'ledger_entries'}{'autoid'}; - # Reconcile the Invoice account. Our two entries look like: - # debit: Invoice credit: Rent/LateCharge/Etc - # debit: A/R credit: Invoice - # Since this is from the perspective of the Invoice account, - # the credit entry is the Invoice<->A/R, and the debit - # entry is the actual charge ledger entry. - addRow('reconciliations', - { 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'}, - 'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'}, - 'amount' => $row->{'ChargeAmount'}, - }); + if ($use_invoice) { + # Reconcile the Invoice account. Our two entries look like: + # debit: Invoice credit: Rent/LateCharge/Etc + # debit: A/R credit: Invoice + # Since this is from the perspective of the Invoice account, + # the credit entry is the Invoice<->A/R, and the debit + # entry is the actual charge ledger entry. + addRow('reconciliations', + { 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'}, + 'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'}, + 'amount' => $row->{'ChargeAmount'}, + }); + } + else { + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'} + = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'}; + } next unless $row->{'TaxAmount'}; @@ -1050,23 +1070,25 @@ foreach $row (@{query($sdbh, $query)}) { 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, 'amount' => $row->{'TaxAmount'}, - #'comment' => "Tax for ChargeID:$row->{'ChargeID'}", + #'comment' => "Tax for ChargeID:$row->{'ChargeID'}", }); $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tax_ledger_entry_id'} = $newdb{'tables'}{'ledger_entries'}{'autoid'}; - # Reconcile the Invoice account. Our two entries look like: - # debit: Invoice credit: Tax - # debit: A/R credit: Invoice - # Since this is from the perspective of the Invoice account, - # the credit entry is the Invoice<->A/R, and the debit - # entry is the actual tax ledger entry. - addRow('reconciliations', - { 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tax_ledger_entry_id'}, - 'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'}, - 'amount' => $row->{'TaxAmount'}, - }); + if ($use_invoice) { + # Reconcile the Invoice account. Our two entries look like: + # debit: Invoice credit: Tax + # debit: A/R credit: Invoice + # Since this is from the perspective of the Invoice account, + # the credit entry is the Invoice<->A/R, and the debit + # entry is the actual tax ledger entry. + addRow('reconciliations', + { 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tax_ledger_entry_id'}, + 'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'}, + 'amount' => $row->{'TaxAmount'}, + }); + } } @@ -1176,7 +1198,8 @@ foreach $row (@{query($sdbh, $query)}) { if (!$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}) { addRow('transactions', { 'stamp' => $stamp, - }); + #'comment' => "Receipt Transaction", + }); $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}} = {'tx' => $newdb{'tables'}{'transactions'}{'autoid'}, 'date' => $stamp, @@ -1184,6 +1207,7 @@ foreach $row (@{query($sdbh, $query)}) { addRow('transactions', { 'stamp' => $stamp, + #'comment' => "Payment Split Transaction", }); $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'payment_tx'} = $newdb{'tables'}{'transactions'}{'autoid'}; @@ -1245,7 +1269,7 @@ foreach $row (@{query($sdbh, $query)}) { 'debit_ledger_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'debit_ledger_id'}, 'credit_ledger_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'credit_ledger_id'}, 'amount' => $row->{'ReceiptAmount'}, - #'comment' => "Receipt: $row->{'ReceiptNum'}; ", + #'comment' => "Receipt: $row->{'ReceiptNum'}; ", }); $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'} @@ -1301,7 +1325,7 @@ foreach $row (@{query($sdbh, $query)}) 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, 'amount' => $row->{'PaymentAmount'}, - #'comment' => "Receipt: $row->{'ReceiptNum'}; Charge: $row->{'ChargeID'}; Payment: $row->{'PaymentID'}", + #'comment' => "Split; Receipt: $row->{'ReceiptNum'}; Charge: $row->{'ChargeID'}; Payment: $row->{'PaymentID'}", }); $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} @@ -1408,248 +1432,8 @@ addRow('ledger_entries', }); - - ###################################################################### -## Fake Data for Testing - -my %fake = - ('customer_id' => 4, - 'ledger_id' => 4, - 'invoice' => [ { 'id' => 1000, - 'date' => '2009-05-05', - 'entry' => [ { 'id' => 2100, - 'account_name' => 'Security Deposit', - 'amount' => 10, - 'tax' => 0 }, - ], - }, - { 'id' => 1001, - 'date' => '2009-05-01', - 'thru' => '2009-05-31', - 'entry' => [ { 'id' => 2110, - 'account_name' => 'Rent', - 'amount' => 100, - 'tax' => 5 }, - ], - }, - { 'id' => 1002, - 'date' => '2009-05-11', - 'entry' => [ { 'id' => 2120, - 'account_name' => 'Late Charge', - 'amount' => 25, - 'tax' => 0 }, - ], - }, - ], - 'receipt' => [ { 'id' => 2000, - 'date' => '2009-05-15', - 'entry' => [ { 'id' => 2200, - 'track' => [ { 'debit'=>2100, 'amount'=>10 }, - { 'debit'=>2110, 'amount'=>5 } ], - 'type' => 1, - 'amount' => 15 }, - { 'id' => 2201, - 'track' => [ { 'debit'=>2110, 'amount'=>10 } ], - 'type' => 2, - 'amount' => 10 }, - { 'id' => 2202, - 'track' => [ { 'debit'=>2110, 'amount'=>5 } ], - 'type' => 3, - 'amount' => 5 }, - ], - }, - { 'id' => 2001, - 'date' => '2009-05-18', - 'entry' => [ { 'id' => 2210, - 'track' => [ { 'debit'=>2110, 'amount'=>30 } ], - 'type' => 5, - 'amount' => 30 }, - { 'id' => 2211, - 'track' => [ { 'debit'=>2110, 'amount'=>20 } ], - 'type' => 6, - 'amount' => 20 }, - ], - }, - { 'id' => 2002, - 'date' => '2009-05-22', - 'entry' => [ { 'id' => 2220, - 'track' => [ { 'debit'=>2110, 'amount'=>10 } ], - 'type' => 1, - 'amount' => 10 }, - { 'id' => 2221, - 'track' => [ { 'debit'=>2110, 'amount'=>5 } ], - 'type' => 2, - 'amount' => 5 }, - { 'id' => 2222, - 'track' => [ { 'debit'=>2110, 'amount'=>15 }, - { 'debit'=>2111, 'amount'=>5 }, - { 'debit'=>2120, 'amount'=>5 } ], - 'type' => 7, - 'amount' => 25 }, - { 'id' => 2223, - 'track' => [ { 'debit'=>2120, 'amount'=>20 } ], - 'type' => 8, - 'amount' => 30 }, - ], - }, - ], - - ); - -sub fakeTesting { - $newdb{'ids'}{'ledger'}{'Cash-Old'} = - $newdb{'lookup'}{'account'}{'Cash'}{'ledger_id'}; - - addRow('ledgers', - { 'account_id' => $newdb{'lookup'}{'account'}{'Cash'}{'account_id'}, - 'open_stamp' => 'NOW()', - 'sequence' => 2, - 'comment' => 'Opened new ledger for testing' }); - - $newdb{'lookup'}{'account'}{'Cash'}{'ledger_id'} = - $newdb{'tables'}{'ledgers'}{'autoid'}; - - my $balance = 0; - foreach $row (@{$newdb{'tables'}{'ledger_entries'}{'rows'}}) { - next unless defined $row; - $balance += $row->{'amount'} - if $row->{'debit_ledger_id'} == $newdb{'ids'}{'ledger'}{'Cash-Old'}; - $balance -= $row->{'amount'} - if $row->{'credit_ledger_id'} == $newdb{'ids'}{'ledger'}{'Cash-Old'}; - } - - addRow('transactions', - { 'stamp' => '2009-04-30' }); - - addRow('ledger_entries', - { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, - 'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'}, - 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Cash'}{'ledger_id'}, - 'credit_ledger_id' => $newdb{'ids'}{'ledger'}{'Cash-Old'}, - 'amount' => $balance, - 'name' => "Close Out ($newdb{'ids'}{'ledger'}{'Cash-Old'} -> $newdb{'tables'}{'transactions'}{'autoid'})", - 'comment' => "Carrying forward old ledger balance onto new ledger" }); -# NOTE: no tracking for the Cash account - - $newdb{'tables'}{'ledgers'}{'rows'}[$newdb{'ids'}{'ledger'}{'Cash-Old'}]{'closed'} = 1; - $newdb{'tables'}{'ledgers'}{'rows'}[$newdb{'ids'}{'ledger'}{'Cash-Old'}]{'close_stamp'} = 'NOW()'; - - foreach my $ir ('invoice', 'receipt') { - foreach my $tx (@{$fake{$ir}}) { - #print Dumper ${%$tx{'date'}}; - #exit; - addRow('transactions', - { 'id' => $tx->{'id'}, - 'stamp' => $tx->{'date'}, - 'through_date' => $tx->{'thru'}, - 'comment' => "Fake $ir" }, - 1); - - foreach my $e (@{$tx->{'entry'}}) { - my $ircrdr = ($ir eq 'invoice') ? 'Invoice' : 'Receipt'; - my $dr = ($ir eq 'invoice') ? 'A/R' : 'Cash'; - my $cr = ($ir eq 'invoice') ? $e->{'account_name'} : 'A/R'; - my $crdr; - my $monetary_source_id; - - if (defined $e->{'type'}) { - addRow('monetary_sources', - { 'name' => "Money of type " . $e->{'type'}, - 'comment' => "Fake Money For " . $e->{'id'} }); - $monetary_source_id = $newdb{'tables'}{'monetary_sources'}{'autoid'}; - } - else { - $monetary_source_id = $newdb{'ids'}{'monetary_source'}{'internal'}; - } - - $crdr = $dr; - if ($use_ir) { - $crdr = $ircrdr; - addRow('ledger_entries', - { 'id' => $e->{'id'}+10000, - 'monetary_source_id' => ($ir eq 'invoice' ? undef : $monetary_source_id), - 'transaction_id' => $tx->{'id'}, - 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$dr}{'ledger_id'}, - 'credit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'}, - 'customer_id' => $fake{'customer_id'}, - #'lease_id' => $fake{'lease_id'}, - 'amount' => $e->{'amount'}, - 'comment' => "Fake $ir entry" }, - 1); - } - - addRow('ledger_entries', - { 'id' => $e->{'id'}, - 'monetary_source_id' => ($ir eq 'invoice' ? $monetary_source_id : undef), - 'transaction_id' => $tx->{'id'}, - 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'}, - 'credit_ledger_id' => $newdb{'lookup'}{'account'}{$cr}{'ledger_id'}, - 'customer_id' => $fake{'customer_id'}, - 'lease_id' => $fake{'lease_id'}, - 'amount' => $e->{'amount'}, - 'comment' => "Fake Entry" }, - 1); - - if ($use_ir) { - addRow('reconciliations', - { 'debit_ledger_entry_id' => $e->{'id'} + ($ir eq 'invoice' ? 10000 : 0), - 'credit_ledger_entry_id' => $e->{'id'} + ($ir eq 'invoice' ? 0 : 10000), - 'amount' => $e->{'amount'}, - }); - } - - foreach my $t (@{$e->{'track'}}) { - addRow('reconciliations', - { 'debit_ledger_entry_id' => $t->{'debit'}, - 'credit_ledger_entry_id' => $e->{'id'}, - 'amount' => $t->{'amount'} - }); - } - - next unless $e->{'tax'}; - - $crdr = $dr; - if ($use_ir) { - $crdr = $ircrdr; - addRow('ledger_entries', - { 'id' => $e->{'id'}+10001, - 'monetary_source_id' => ($ir eq 'invoice' ? undef : $monetary_source_id), - 'transaction_id' => $tx->{'id'}, - 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$dr}{'ledger_id'}, - 'credit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'}, - 'customer_id' => $fake{'customer_id'}, - #'lease_id' => $fake{'lease_id'}, - 'amount' => $e->{'tax'}, - 'comment' => "Fake Tax Invoice Entry" }, - 1); - } - - addRow('ledger_entries', - { 'id' => $e->{'id'}+1, - 'monetary_source_id' => ($ir eq 'invoice' ? $monetary_source_id : undef), - 'transaction_id' => $tx->{'id'}, - 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'}, - 'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Tax'}{'ledger_id'}, - 'customer_id' => $fake{'customer_id'}, - 'lease_id' => $fake{'lease_id'}, - 'amount' => $e->{'tax'}, - 'comment' => "Fake Tax Entry" }, - 1); - - if ($use_ir) { - addRow('reconciliations', - { 'debit_ledger_entry_id' => $e->{'id'} + ($ir eq 'invoice' ? 10001 : 1), - 'credit_ledger_entry_id' => $e->{'id'} + ($ir eq 'invoice' ? 1 : 10001), - 'amount' => $e->{'tax'}, - }); - } - } - } - } -} - -#fakeTesting(); +## Build the Database $Data::Dumper::Sortkeys = 1; # print Dumper \%newdb; diff --git a/site/models/transaction.php b/site/models/transaction.php index 27f739a..6870b11 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -36,16 +36,6 @@ class Transaction extends AppModel { foreach ($data['LedgerEntry'] AS $entry) $grand_total += $entry['amount']; - $ids = $this->LedgerEntry->Ledger->Account->postLedgerEntry - (array_intersect_key($data, array('Transaction'=>1, 'transaction_id'=>1)), - null, - array('debit_ledger_id' => $A->currentLedgerID($A->accountReceivableAccountID()), - 'credit_ledger_id' => $A->currentLedgerID($A->invoiceAccountID()), - 'customer_id' => $customer_id, - 'lease_id' => $lease_id, - 'amount' => $grand_total)); - $ar_entry_id = $ids['id']; - // Go through the entered charges $invoice_transaction = array_intersect_key($data, array('Transaction'=>1, 'transaction_id'=>1)); foreach ($data['LedgerEntry'] AS $entry) { @@ -56,13 +46,11 @@ class Transaction extends AppModel { ($invoice_transaction, array_intersect_key($entry, array('MonetarySource'=>1)) + array_intersect_key($entry, array('account_id'=>1)), - array('debit_ledger_id' => $A->currentLedgerID($A->invoiceAccountID()), + array('debit_ledger_id' => $A->currentLedgerID($A->accountReceivableAccountID()), 'credit_ledger_id' => $A->currentLedgerID($entry['account_id']), 'customer_id' => $customer_id, 'lease_id' => $lease_id) - + $entry, - array('debit' => array(array('LedgerEntry' => array('id' => $ar_entry_id, - 'amount' => $entry['amount'])))) + + $entry ); if ($ids['error']) From b8fd17efcf5b16f5438e4aae8a71e8b457bcd6bb Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 11 Jul 2009 09:06:36 +0000 Subject: [PATCH 303/717] Added mechanism to reverse a ledger entry. For now I've restricted it to those ledger entries that have not already been reconciled in some way. More thought will have to go into this, especially with respect to tenants who have pre-paid and then move out early. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@309 97e9348a-65ac-dc4b-aefc-98561f571b83 --- requirements.txt | 2 +- .../controllers/ledger_entries_controller.php | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 5d2d5f5..99615f2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -45,7 +45,7 @@ Operations to be functional X - Receive and record Money Orders X - Receive and record Cash X - Receive and record ACH Deposits - - Reverse rent charges (early moveout on prepaid occupancy) + x - Reverse rent charges (early moveout on prepaid occupancy) - Handle NSF checks - Assess NSF Fees - Determine Lease Paid-Through status diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index 25cd6f6..6675547 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -266,6 +266,18 @@ class LedgerEntriesController extends AppController { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: reverse the ledger entry + */ + + function reverse($id) { + $id = $this->LedgerEntry->reverse($id); + $this->redirect(array('action'=>'view', $id)); + } + + /************************************************************************** ************************************************************************** ************************************************************************** @@ -342,6 +354,27 @@ class LedgerEntriesController extends AppController { $reconciled = $this->LedgerEntry->findReconciledLedgerEntries($id); //pr($reconciled); + + // REVISIT : 20090711 + // It's not clear whether we should be able to reverse charges that have + // already been paid/cleared/reconciled. Certainly, that will be the + // case when someone has pre-paid and then moves out early. However, this + // will work well for items accidentally charged but not yet paid for. + if ((!$entry['DebitLedger']['Account']['trackable'] || + $stats['debit']['amount_reconciled'] == 0) && + (!$entry['CreditLedger']['Account']['trackable'] || + $stats['credit']['amount_reconciled'] == 0)) + { + // Set up dynamic menu items + $this->sidemenu_links[] = + array('name' => 'Operations', 'header' => true); + + $this->sidemenu_links[] = + array('name' => 'Reverse', + 'url' => array('action' => 'reverse', + $id)); + } + // Prepare to render. $title = "Double Ledger Entry #{$entry['LedgerEntry']['id']}"; $this->set(compact('entry', 'title', 'reconciled', 'stats')); From b3ca71951782007350603b35726d92e2677536dc Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 11 Jul 2009 15:37:17 +0000 Subject: [PATCH 304/717] Forgot to check in the model as part of the last change set. Guess that's what happens when you're tired. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@310 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/ledger_entry.php | 57 ++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/site/models/ledger_entry.php b/site/models/ledger_entry.php index 8fc8bad..4f6dafd 100644 --- a/site/models/ledger_entry.php +++ b/site/models/ledger_entry.php @@ -234,6 +234,63 @@ class LedgerEntry extends AppModel { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: reverse + * - Reverses the ledger entry + */ + + function reverse($id) { + // Get the LedgerEntry and related fields + $entry = $this->find + ('first', + array('contain' => array('MonetarySource.id', + 'Transaction.id', + 'DebitLedger.id', + 'DebitLedger.account_id', + 'CreditLedger.id', + 'CreditLedger.account_id', + 'Customer.id', + 'Lease.id', + ), + + 'fields' => array('LedgerEntry.*'), + + 'conditions' => array('LedgerEntry.id' => $id), + )); + //pr($entry); + + $A = new Account(); + + $ids = $this->Ledger->Account->postLedgerEntry + (//array('transaction_id' => $entry['Transaction']['id']), + null, + null, + array('debit_ledger_id' => $A->currentLedgerID($entry['CreditLedger']['account_id']), + 'credit_ledger_id' => $A->currentLedgerID($entry['DebitLedger']['account_id']), + 'effective_date' => $entry['LedgerEntry']['effective_date'], + //'effective_date' => $entry['LedgerEntry']['effective_date'], + 'amount' => $entry['LedgerEntry']['amount'], + 'lease_id' => $entry['Lease']['id'], + 'customer_id' => $entry['Customer']['id'], + 'comment' => "Reversal of Ledger Entry #{$id}", + ), + array('debit' => array(array('LedgerEntry' => array('id' => $entry['LedgerEntry']['id'], + 'amount' => $entry['LedgerEntry']['amount'], + ))), + 'credit' => array(array('LedgerEntry' => array('id' => $entry['LedgerEntry']['id'], + 'amount' => $entry['LedgerEntry']['amount'], + ))), + )); + + if ($ids['error']) + return null; + + return $ids['id']; + } + + /************************************************************************** ************************************************************************** ************************************************************************** From 288e4c05dee0102a42df7d3ecd411d3fb59b0684 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 11 Jul 2009 15:37:52 +0000 Subject: [PATCH 305/717] Added debug link to create all new ledgers git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@311 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 1 + 1 file changed, 1 insertion(+) diff --git a/site/app_controller.php b/site/app_controller.php index bdf14ea..1018b63 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -49,6 +49,7 @@ class AppController extends Controller { array('name' => 'Debug', 'header' => true), array('name' => 'Contacts', 'url' => array('controller' => 'contacts', 'action' => 'index')), array('name' => 'Ledgers', 'url' => array('controller' => 'ledgers', 'action' => 'index')), + array('name' => 'New Ledgers', 'url' => array('controller' => 'accounts', 'action' => 'newledger')), array('name' => 'RESET DATA', 'url' => array('controller' => 'accounts', 'action' => 'reset_data')), ); } From ccf0138eee3c3f6ec0b012c300bbe9754500d2c9 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 11 Jul 2009 15:50:48 +0000 Subject: [PATCH 306/717] Added flag to allow ledger entry reversals, regardless of the reconciled status. I'm not sure how we really want to handle reversals. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@312 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/leases_controller.php | 13 +++++++++++++ site/controllers/ledger_entries_controller.php | 5 ++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index d58bf8a..036825b 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -341,6 +341,19 @@ class LeasesController extends AppController { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: refund + * - Provides user with a refund + * REVISIT : 20090710 + * Should this be a customer function? + */ + + function refund($id) { + } + + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index 6675547..dfaa832 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -363,7 +363,10 @@ class LedgerEntriesController extends AppController { if ((!$entry['DebitLedger']['Account']['trackable'] || $stats['debit']['amount_reconciled'] == 0) && (!$entry['CreditLedger']['Account']['trackable'] || - $stats['credit']['amount_reconciled'] == 0)) + $stats['credit']['amount_reconciled'] == 0) + + || 1 // REVISIT : 20090711 : Testing + ) { // Set up dynamic menu items $this->sidemenu_links[] = From a462e9be1cbf48f9a9cf436c68e3450efe4d4103 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 11 Jul 2009 15:51:52 +0000 Subject: [PATCH 307/717] Accidentally checked in refundable stub on the last change set, so here is the database changes to go with it. Nothing has been done yet for refunds. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@313 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 61 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index a246bde..e11693b 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -847,6 +847,7 @@ CREATE TABLE `pmgr_accounts` ( `depositable` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Does this account receive deposits? `chargeable` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Can be used for charges? `payable` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Can be used for payments? + `refundable` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Can be used for refunds? -- Security Level `level` INT UNSIGNED DEFAULT 10, @@ -863,30 +864,44 @@ CREATE TABLE `pmgr_accounts` ( LOCK TABLES `pmgr_accounts` WRITE; INSERT INTO `pmgr_accounts` (`type`, `name`, `level`) VALUES - ('EQUITY', 'Equity', 1), - ('LIABILITY', 'Loan', 1); -INSERT INTO `pmgr_accounts` (`type`, `name`, `tillable`, `depositable`, `chargeable`, `payable`) + ('EQUITY', 'Equity', 1), + ('LIABILITY', 'Loan', 1); +INSERT INTO `pmgr_accounts` (`type`, `name`) VALUES - ('ASSET', 'A/R', 0, 0, 0, 0), - ('ASSET', 'Invoice', 0, 0, 0, 0), - ('ASSET', 'Receipt', 0, 0, 0, 0), - ('LIABILITY', 'A/P', 0, 0, 0, 0), - ('LIABILITY', 'Tax', 0, 0, 1, 0), --- ('LIABILITY', 'Customer Credit', 0, 0, 1, 1), - ('ASSET', 'Petty Cash', 0, 0, 0, 0), - ('ASSET', 'Bank', 0, 1, 0, 0), - ('ASSET', 'ACH', 0, 0, 0, 1), - ('ASSET', 'Cash', 1, 0, 0, 1), - ('ASSET', 'Check', 1, 0, 0, 1), - ('ASSET', 'Money Order', 1, 0, 0, 1), - ('LIABILITY', 'Security Deposit', 0, 0, 1, 0), - ('INCOME', 'Rent', 0, 0, 1, 0), - ('INCOME', 'Late Charge', 0, 0, 1, 0), - ('INCOME', 'Damage', 0, 0, 1, 0), - ('EXPENSE', 'Concession', 0, 0, 0, 1), - ('EXPENSE', 'Bad Debt', 0, 0, 0, 0), - ('EXPENSE', 'Maintenance', 0, 0, 0, 0); - + ('ASSET', 'A/R' ), + ('ASSET', 'Invoice' ), + ('ASSET', 'Receipt' ), +-- REVISIT : 20090710 : We don't really need NSF, as it +-- will always run a zero balance. However, it will help +-- us identify how serious the NSF situation is. + ('ASSET', 'NSF' ), + ('LIABILITY', 'A/P' ); +INSERT INTO `pmgr_accounts` (`type`, `name`, `tillable`, `payable`, `refundable`) + VALUES + ('ASSET', 'Cash', 1, 1, 1), + ('ASSET', 'Check', 1, 1, 0), + ('ASSET', 'Money Order', 1, 1, 0), + ('ASSET', 'ACH', 0, 1, 0), + ('EXPENSE', 'Concession', 0, 1, 0); +INSERT INTO `pmgr_accounts` (`type`, `name`, `tillable`, `payable`, `refundable`, `depositable`) + VALUES +-- REVISIT : 20090710 : We probably don't really want petty cash depositable + ('ASSET', 'Petty Cash', 0, 0, 1, 1); +INSERT INTO `pmgr_accounts` (`type`, `name`, `chargeable`, `trackable`) + VALUES + ('LIABILITY', 'Tax', 1, 1), + ('LIABILITY', 'Security Deposit', 1, 1), + ('INCOME', 'Rent', 1, 0), + ('INCOME', 'Late Charge', 1, 0), + ('INCOME', 'NSF Charge', 1, 0), + ('INCOME', 'Damage', 1, 0); +INSERT INTO `pmgr_accounts` (`type`, `name`, `depositable`) + VALUES + ('ASSET', 'Bank', 1); +INSERT INTO `pmgr_accounts` (`type`, `name`, `trackable`) + VALUES + ('EXPENSE', 'Bad Debt', 0), + ('EXPENSE', 'Maintenance', 0); UNLOCK TABLES; From 1994512d6e9af1f65c375881204c42492d39fdf8 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 11 Jul 2009 15:54:44 +0000 Subject: [PATCH 308/717] Added a file with some javascript date/time routines. I don't think we want it, but at the same time, I can't bring myself to toss it. May as well capture a revision and I can delete it later. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@314 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/webroot/js/pmgr.js.keep | 382 +++++++++++++++++++++++++++++++++++ 1 file changed, 382 insertions(+) create mode 100644 site/webroot/js/pmgr.js.keep diff --git a/site/webroot/js/pmgr.js.keep b/site/webroot/js/pmgr.js.keep new file mode 100644 index 0000000..f1a654a --- /dev/null +++ b/site/webroot/js/pmgr.js.keep @@ -0,0 +1,382 @@ +/** + * Function : dump() + * Arguments: The data - array,hash(associative array),object + * The level - OPTIONAL + * Returns : The textual representation of the array. + * This function was inspired by the print_r function of PHP. + * This will accept some data as the argument and return a + * text that will be a more readable version of the + * array/hash/object that is given. + * Docs: http://www.openjs.com/scripts/others/dump_function_php_print_r.php + */ +function dump(arr,level) { + var dumped_text = ""; + if(!level) level = 0; + + //The padding given at the beginning of the line. + var level_padding = ""; + for(var j=0;j \"" + value + "\"\n"; + } + } + } else { //Stings/Chars/Numbers etc. + dumped_text = "===>"+arr+"<===("+typeof(arr)+")"; + } + return dumped_text; +} + + +function var_dump(element, limit, depth) +{ + depth = depth?depth:0; + limit = limit?limit:1; + + returnString = '
      '; + + for(property in element) + { + //Property domConfig isn't accessable + if (property != 'domConfig') + { + returnString += '
    1. '+ property + ' (' + (typeof element[property]) +')'; + + if (typeof element[property] == 'number' || typeof element[property] == 'boolean') + returnString += ' : ' + element[property] + ''; + if (typeof element[property] == 'string' && element[property]) + returnString += ':
      ' + + element[property].replace(//g, '&gt;') + '
      '; + + if ((typeof element[property] == 'object') && (depth < limit)) + returnString += var_dump(element[property], limit, (depth + 1)); + + returnString += '
    2. '; + } + } + returnString += '
    '; + + if(depth == 0) + { + winpop = window.open("", "","width=800,height=600,scrollbars,resizable"); + winpop.document.write('
    '+returnString+ '
    '); + winpop.document.close(); + } + + return returnString; +} + + +function htmlEncode(s) +{ + //return s; + return s.replace(/&(?!\w+([;\s]|$))/g, "&") + .replace(//g, ">"); +} + +function addDiv(id_name, div_name, into_div_name, flash, html, script) { + var id = $('#'+id_name).val(); + + html = '
    ' + + html.replace(/%{id}/g, id) + .replace(/%{remove(:([^}]*))?}/g, + '' + + '' + + ("$2" == "" ? "$2" : 'remove') + '' + '') + + '
    '; + + if (script) { + html += ''; + } + + //$("#debug").append(htmlEncode(html)); + $("#"+into_div_name).append(html); + + if (flash) { + $('#'+div_name+'-'+id) + .animate({ backgroundColor: "yellow" }, 300) + .animate({ backgroundColor: "white" }, 500); + } + + id = id - 0 + 1; + $('#'+id_name).val(id); +} + +function removeElement(elem_id) { + $('#'+elem_id).remove(); +} + +// function +// var currentTime = new Date() +// var month = currentTime.getMonth() + 1 +// var day = currentTime.getDate() +// var year = currentTime.getFullYear() +// document.write(month + "/" + day + "/" + year) +// //--> +// var currentTime = new Date() +// var hours = currentTime.getHours() +// var minutes = currentTime.getMinutes() +// if (minutes < 10){ +// minutes = "0" + minutes +// } +// document.write(hours + ":" + minutes + " ") +// if(hours > 11){ +// document.write("PM") +// } else { +// document.write("AM") +// } +// //--> + +function fmtCurrency(amount) { + if (amount == null || isNaN(amount)) + return '-'; + + // Get rid of any extraneous characters, determine + // the sign, and round to the nearest cent. + amount = amount.toString().replace(/\$|\,/g,''); + sign = (amount == (amount = Math.abs(amount))); + amount = (amount+0.0000000001).toFixed(2); + + // Insert thousands separator + while (amount != (amount = amount.replace(/(\d)(\d\d\d[.,])/, "$1,$2"))); + + // Return formatted amount + return (sign?'$':'($') + amount + (sign?'':')'); +} + + +/* + * Date Format 1.2.2 + * (c) 2007-2008 Steven Levithan + * MIT license + * Includes enhancements by Scott Trenda and Kris Kowal + * + * Accepts a date, a mask, or a date and a mask. + * Returns a formatted version of the given date. + * The date defaults to the current date/time. + * The mask defaults to dateFormat.masks.default. + */ +var dateFormat = function () { + var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|\"[^\"]*\"|\'[^\']*\'/g, + timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, + timezoneClip = /[^-+\dA-Z]/g, + pad = function (val, len) { + val = String(val); + len = len || 2; + while (val.length < len) val = "0" + val; + return val; + }; + + // Regexes and supporting functions are cached through closure + return function (date, mask, utc) { + var dF = dateFormat; + + // You can't provide utc if you skip other args (use the "UTC:" mask prefix) + if (arguments.length == 1 && (typeof date == "string" || date instanceof String) && !/\d/.test(date)) { + mask = date; + date = undefined; + } + + // Passing date through Date applies Date.parse, if necessary + date = date ? new Date(date) : new Date(); + if (isNaN(date)) throw new SyntaxError("invalid date"); + + mask = String(dF.masks[mask] || mask || dF.masks["default"]); + + // Allow setting the utc argument via the mask + if (mask.slice(0, 4) == "UTC:") { + mask = mask.slice(4); + utc = true; + } + + var _ = utc ? "getUTC" : "get", + d = date[_ + "Date"](), + D = date[_ + "Day"](), + m = date[_ + "Month"](), + y = date[_ + "FullYear"](), + H = date[_ + "Hours"](), + M = date[_ + "Minutes"](), + s = date[_ + "Seconds"](), + L = date[_ + "Milliseconds"](), + o = utc ? 0 : date.getTimezoneOffset(), + flags = { + d: d, + dd: pad(d), + ddd: dF.i18n.dayNames[D], + dddd: dF.i18n.dayNames[D + 7], + m: m + 1, + mm: pad(m + 1), + mmm: dF.i18n.monthNames[m], + mmmm: dF.i18n.monthNames[m + 12], + yy: String(y).slice(2), + yyyy: y, + h: H % 12 || 12, + hh: pad(H % 12 || 12), + H: H, + HH: pad(H), + M: M, + MM: pad(M), + s: s, + ss: pad(s), + l: pad(L, 3), + L: pad(L > 99 ? Math.round(L / 10) : L), + t: H < 12 ? "a" : "p", + tt: H < 12 ? "am" : "pm", + T: H < 12 ? "A" : "P", + TT: H < 12 ? "AM" : "PM", + Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""), + o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), + S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10] + }; + + return mask.replace(token, function ($0) { + return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1); + }); + }; +}(); + +// Some common format strings +dateFormat.masks = { + "default": "ddd mmm dd yyyy HH:MM:ss", + shortDate: "m/d/yy", + mediumDate: "mmm d, yyyy", + longDate: "mmmm d, yyyy", + fullDate: "dddd, mmmm d, yyyy", + shortTime: "h:MM TT", + mediumTime: "h:MM:ss TT", + longTime: "h:MM:ss TT Z", + isoDate: "yyyy-mm-dd", + isoTime: "HH:MM:ss", + isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", + isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" +}; + +// Internationalization strings +dateFormat.i18n = { + dayNames: [ + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" + ], + monthNames: [ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" + ] +}; + +// For convenience... +Date.prototype.format = function (mask, utc) { + return dateFormat(this, mask, utc); +}; + + +// REVISIT : 20090617 +// I would rather use XML to pass from JS to PHP, but at the +// moment things were working just fine with serialize, and +// I'm not keen on redesigning it at the moment. So, here +// is a serialize implementation I found on the web. + +function serialize( mixed_value ) { + // http://kevin.vanzonneveld.net + // + original by: Arpad Ray (mailto:arpad@php.net) + // + improved by: Dino + // + bugfixed by: Andrej Pavlovic + // + bugfixed by: Garagoth + // + input by: DtTvB (http://dt.in.th/2008-09-16.string-length-in-bytes.html) + // + bugfixed by: Russell Walker + // % note: We feel the main purpose of this function should be to ease the transport of data between php & js + // % note: Aiming for PHP-compatibility, we have to translate objects to arrays + // * example 1: serialize(['Kevin', 'van', 'Zonneveld']); + // * returns 1: 'a:3:{i:0;s:5:"Kevin";i:1;s:3:"van";i:2;s:9:"Zonneveld";}' + // * example 2: serialize({firstName: 'Kevin', midName: 'van', surName: 'Zonneveld'}); + // * returns 2: 'a:3:{s:9:"firstName";s:5:"Kevin";s:7:"midName";s:3:"van";s:7:"surName";s:9:"Zonneveld";}' + + var _getType = function( inp ) { + var type = typeof inp, match; + var key; + if (type == 'object' && !inp) { + return 'null'; + } + if (type == "object") { + if (!inp.constructor) { + return 'object'; + } + var cons = inp.constructor.toString(); + match = cons.match(/(\w+)\(/); + if (match) { + cons = match[1].toLowerCase(); + } + var types = ["boolean", "number", "string", "array"]; + for (key in types) { + if (cons == types[key]) { + type = types[key]; + break; + } + } + } + return type; + }; + var type = _getType(mixed_value); + var val, ktype = ''; + + switch (type) { + case "function": + val = ""; + break; + case "undefined": + val = "N"; + break; + case "boolean": + val = "b:" + (mixed_value ? "1" : "0"); + break; + case "number": + val = (Math.round(mixed_value) == mixed_value ? "i" : "d") + ":" + mixed_value; + break; + case "string": + val = "s:" + encodeURIComponent(mixed_value).replace(/%../g, 'x').length + ":\"" + mixed_value + "\""; + break; + case "array": + case "object": + val = "a"; + /* + if (type == "object") { + var objname = mixed_value.constructor.toString().match(/(\w+)\(\)/); + if (objname == undefined) { + return; + } + objname[1] = serialize(objname[1]); + val = "O" + objname[1].substring(1, objname[1].length - 1); + } + */ + var count = 0; + var vals = ""; + var okey; + var key; + for (key in mixed_value) { + ktype = _getType(mixed_value[key]); + if (ktype == "function") { + continue; + } + + okey = (key.match(/^[0-9]+$/) ? parseInt(key, 10) : key); + vals += serialize(okey) + + serialize(mixed_value[key]); + count++; + } + val += ":" + count + ":{" + vals + "}"; + break; + } + if (type != "object" && type != "array") { + val += ";"; + } + return val; + +} From d2ac8019ee9ce1a1f8a29dfb0d730b80234ee4f5 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 11 Jul 2009 15:56:54 +0000 Subject: [PATCH 309/717] Not sure why I haven't already checked in the 'To Do' notes file that I've been using, but here it is. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@315 97e9348a-65ac-dc4b-aefc-98561f571b83 --- todo.notes | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 todo.notes diff --git a/todo.notes b/todo.notes new file mode 100644 index 0000000..83d021d --- /dev/null +++ b/todo.notes @@ -0,0 +1,113 @@ +Sub-Total is broken, since it will only subtotal the current +page of the grid. It needs to be implemented in SQL as it +was in early (VERY early) implementations. At that time, I +had to a use temporary variable to keep a running total. It +worked, but was MySQL specific. + +Sorting by Customer ID is broken. It must think it's already +sorted by ID because the first click shows the arrow as +DESC even though the sort is ASC. Subsequent clicks don't +change anything. You must sort on a different column first +then everything works. + +Handle a credit, ensuring that it's applied to new charges + - either automatically; + - by user opt-in to use credits when invoicing + - by user opt-in when entering a receipt + - by manually allowing a receipt of credits + +Get Petty Cash working. We'll need to add one or more expense +accounts. We'll also need to implement purchase order +functionality, or at least simple an expense page. + +Figure out how to utilize the security deposit, whether +as part of move-out only, or as one of the payment options. + +Automatic assessment of rents, or at least for now, one +click manual mechanism to assess rents correctly for all +tenants. + +Automatic assessment of late fees, or at least for now, one +click manual mechanism to assess late fees correctly for all +tenants. + +Update unit status between OCCUPIED / LATE / LOCKED depending +on the current situation. + +Have a report indicating Needs-to-be-Locked. Allow manager +to go through this list and check off the units actually +locked (which will update the unit status). Perhaps we +should add a needs-locked status. + +Same as above, except needs-to-be-unlocked. + +Determine when each unit is paid up until. There is actually +two things here: invoiced up until, and paid up until. One or +both of these should be displayed on the Lease view page. + +Make the default (initial) jqGrid sort order for balance be DESC. + +MUST reports: + - Delinquent customers + - Locked out units / customers + - To-Lock units + - Paid up until + +WANT reports: + - ??? + + + + + + + +---------------------------------------------------------------------- +---------------------------------------------------------------------- +---------------------------------------------------------------------- +---------------------------------------------------------------------- +---------------------------------------------------------------------- +-- DONE ! + + +VERIFY THAT OUR NEW BALANCE QUERY WORKS. +(The one that was added to lease). It works for +folks that have ledger entries, but I fear that the +inner join will prevent customers from showing up +in the list if they don't yet have any ledger entries +in account receivable. To resolve this we'll have to +go back to LEFT JOIN and check for NULL in our SUM() +statement. + +Fix sorting on Lease list by Lease Number. Have it +reference ID instead. + +Figure out why Brenda Harmon's lease #44, unit #B04, lists +the security deposit as $150. She's only paid $25, so it must +be a lease issue. + +Modify LedgerEntry to have through_date, since a single +invoice could have charges for several months rent. It's +not clear whether due_date should also be moved to +LedgerEntry, since some charges could have different due +dates. The problem is that I can't picture an invoice +having more than one due date. + +Consider adding a from_date to LedgerEntry as well. + +Fix Customers index list. To replicate, add a brand +new customer. Select Customers. Notice it says +'Current Customers', but actually includes the new +one in the list. + +There seems to be a problem with the account ledger for the +customer. To replicate, see Mancini's account (#47). There +are 4 entries in the Account ledger. One of them is was from +5/1/09. It's a receipt (Transaction #610, Entry #702). The +Transaction is for $111.33 as indicated, but the entry is only +for $16.33. + -- This was a problem with using notxgroup, the experimental + -- field that used to be hardcoded to false in ledger_entries.ctp + -- My rework eliminated that field, and everything was getting + -- grouped by transaction. + From 9529431be2f62e0aee3bbaac87cb09fcb26271f9 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 11 Jul 2009 16:50:13 +0000 Subject: [PATCH 310/717] Eliminated the unnecessary $A Account variable in the actual Account model (duh) git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@316 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/account.php | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/site/models/account.php b/site/models/account.php index ab6fa13..56b90f2 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -495,9 +495,6 @@ class Account extends AppModel { $monetary_data, $entry_data, $reconcile = null) { - // Create some models for convenience - $A = new Account(); - //pr(compact('transaction_data', 'monetary_data', 'entry_data', 'reconcile')); // Automatically figure out the customer if we have the lease @@ -538,12 +535,12 @@ class Account extends AppModel { // Convert Account ID to name or vice versa if (isset($monetary_data['account_id'])) { - $monetary_data['account_name'] = $A->name($monetary_data['account_id']); + $monetary_data['account_name'] = $this->name($monetary_data['account_id']); } elseif (isset($monetary_data['account_name'])) { - $monetary_data['account_id'] = $A->nameToID($monetary_data['account_name']); + $monetary_data['account_id'] = $this->nameToID($monetary_data['account_name']); } - if ($monetary_data['account_id'] == $A->cashAccountID()) { + if ($monetary_data['account_id'] == $this->cashAccountID()) { // No distinguishing features of Cash, just // use the shared monetary source $monetary_data['monetary_source_id'] = @@ -561,8 +558,8 @@ class Account extends AppModel { // Create a new one dedicated to this entry // Give it a fancy name based on the check number $monetary_data['MonetarySource']['name'] = $monetary_data['account_name']; - if ($monetary_data['account_name'] === $A->name($A->checkAccountID()) || - $monetary_data['account_name'] === $A->name($A->moneyOrderAccountID())) { + if ($monetary_data['account_name'] === $this->name($this->checkAccountID()) || + $monetary_data['account_name'] === $this->name($this->moneyOrderAccountID())) { $monetary_data['MonetarySource']['name'] .= ' #' . $monetary_data['MonetarySource']['data1']; } @@ -593,9 +590,9 @@ class Account extends AppModel { if (!isset($entry_data['debit_ledger_id'])) { $entry_data['debit_ledger_id'] = (isset($entry_data['debit_account_id']) - ? $A->currentLedgerID($entry_data['debit_account_id']) + ? $this->currentLedgerID($entry_data['debit_account_id']) : (isset($entry_data['debit_account_name']) - ? $A->currentLedgerID($A->nameToID($entry_data['debit_account_name'])) + ? $this->currentLedgerID($this->nameToID($entry_data['debit_account_name'])) : null ) ); @@ -605,9 +602,9 @@ class Account extends AppModel { if (!isset($entry_data['credit_ledger_id'])) { $entry_data['credit_ledger_id'] = (isset($entry_data['credit_account_id']) - ? $A->currentLedgerID($entry_data['credit_account_id']) + ? $this->currentLedgerID($entry_data['credit_account_id']) : (isset($entry_data['credit_account_name']) - ? $A->currentLedgerID($A->nameToID($entry_data['credit_account_name'])) + ? $this->currentLedgerID($this->nameToID($entry_data['credit_account_name'])) : null ) ); @@ -673,8 +670,8 @@ class Account extends AppModel { $ids = $this->postLedgerEntry ($split_transaction, null, - array('debit_ledger_id' => $A->currentLedgerID($A->receiptAccountID()), - 'credit_ledger_id' => $A->currentLedgerID($A->accountReceivableAccountID()), + array('debit_ledger_id' => $this->currentLedgerID($this->receiptAccountID()), + 'credit_ledger_id' => $this->currentLedgerID($this->accountReceivableAccountID()), 'amount' => $rec['applied'], 'lease_id' => $rec['lease_id'], 'customer_id' => $rec['customer_id'], From 0c13ef5cda92da9ee1f0375eebb64a0ebddccd37 Mon Sep 17 00:00:00 2001 From: abijah Date: Sat, 11 Jul 2009 16:50:52 +0000 Subject: [PATCH 311/717] captured another requirement and a todo git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@317 97e9348a-65ac-dc4b-aefc-98561f571b83 --- requirements.txt | 1 + todo.notes | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 99615f2..7030a2b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -66,3 +66,4 @@ Operations to be functional - Record Petty Cash to refund. X - Write Off Bad Debt X - Perform a Deposit and Close the Books + - Determine Rents Collected for a given period. diff --git a/todo.notes b/todo.notes index 83d021d..bb62b38 100644 --- a/todo.notes +++ b/todo.notes @@ -20,8 +20,8 @@ Get Petty Cash working. We'll need to add one or more expense accounts. We'll also need to implement purchase order functionality, or at least simple an expense page. -Figure out how to utilize the security deposit, whether -as part of move-out only, or as one of the payment options. +Reconcile all entries of a ledger to the c/f entry when +"closing" the ledger and creating a new one. Automatic assessment of rents, or at least for now, one click manual mechanism to assess rents correctly for all @@ -111,3 +111,6 @@ for $16.33. -- My rework eliminated that field, and everything was getting -- grouped by transaction. +Figure out how to utilize the security deposit, whether +as part of move-out only, or as one of the payment options. + From 6e1c684a06d0e16cbba99b4e5ac40ed80f2a675c Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 12 Jul 2009 18:01:01 +0000 Subject: [PATCH 312/717] Implemented a list that checks for collected rents. There is AccountsController::collected, which I'm keeping at the moment, but I decided to move the logic into ledger_entries, since ultimately that's what we want a list of and it doesn't make sense to add a bunch of LedgerEntry logic into the jqGrid query of AccountsController. Of course, right now there is hardcoded calendar functions, and hardcoded exclusion of the Concession Account. I will probably offer up two calendars to provide a range, and a list of checkboxes of each payable account. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@318 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 4 +- site/controllers/accounts_controller.php | 81 +++++++++++++++++++ .../controllers/ledger_entries_controller.php | 69 +++++++++++++++- site/views/elements/collected.ctp | 45 +++++++++++ 4 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 site/views/elements/collected.ctp diff --git a/site/app_controller.php b/site/app_controller.php index 1018b63..35a4729 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -88,12 +88,12 @@ class AppController extends Controller { * - called by function to create an index listing */ - function jqGridView($title, $action = null) { + function jqGridView($title, $action = null, $element = null) { $this->set('title', $title); // The resulting page will contain a jqGrid, which will // use ajax to obtain the actual data for this action $this->set('action', $action ? $action : $this->params['action']); - $this->render('/elements/' . $this->params['controller']); + $this->render('/elements/' . ($element ? $element : $this->params['controller'])); } /************************************************************************** diff --git a/site/controllers/accounts_controller.php b/site/controllers/accounts_controller.php index 49a4c44..8b17dfa 100644 --- a/site/controllers/accounts_controller.php +++ b/site/controllers/accounts_controller.php @@ -139,6 +139,84 @@ class AccountsController extends AppController { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * 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) { + //if ($this->data) { + //pr($this->data); + //} + +/* $tillable_account = $this->Account->relatedAccounts('tillable'); */ +/* $depositable_account = $this->Account->relatedAccounts('depositable'); */ + + $ledger_entries = + $this->Account->Ledger->LedgerEntry->find + ('all', + array('link' => array + ('Ledger' => + array('fields' => array('sequence'), + + 'Account' => + array('fields' => array('id', 'name')), + ), + + 'MonetarySource' => + array('fields' => array('name')), + + 'Customer' => + array('fields' => array('name')), + + 'Transaction' => + array('fields' => array('stamp')), + + // Income / Receipt flow + // debit: Receipt credit: A/R <-- this entry + // debit: A/R credit: Income <-- CRLE, below + // + // We're searching for the Receipt<->A/R entries, + // which are credits on the A/R account. Find the + // reconciling A/R entries (except for unassigned + // pre-payments, all A/R credits should have one). + 'CreditReconciliationLedgerEntry' => + array('alias' => 'RLedgerEntry', + 'fields' => true, + + 'Transaction' => + array('alias' => 'RTransaction', + 'fields' => array('stamp')), + + // Debit should be A/R; Credit is Account of interest + 'CreditLedger' => + array('alias' => 'RLedger', + 'fields' => true, + + 'Account' => + array('alias' => 'RAccount', + 'fields' => true, + + ), + ), + ), + ), + + 'fields' => array('LedgerEntry.*', 'Reconciliation.amount'), + 'conditions' => array(array('RAccount.id' => $id), + //array('Account.tillable' => 1), + ), + )); + + pr(compact('ledger_entries')); + + $title = 'Collected Whatever'; + $this->set(compact('title', 'ledger_entries')); + //$this->render('/empty'); + } + /************************************************************************** ************************************************************************** ************************************************************************** @@ -258,6 +336,9 @@ class AccountsController extends AppController { 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('controller' => 'ledger_entries', + 'action' => 'collected', $id)); // Prepare to render $title = 'Account: ' . $account['Account']['name']; diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index dfaa832..d6fbd0c 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -16,6 +16,16 @@ class LedgerEntriesController extends AppController { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: index / etc + * - Generate a listing of ledger_entries + */ + + function collected() { $this->jqGridView('Collected Entries', null, 'collected'); } + + /************************************************************************** ************************************************************************** ************************************************************************** @@ -56,6 +66,40 @@ class LedgerEntriesController extends AppController { ), ); + if ($params['action'] === 'collected') { + $link['DebitLedger']['fields'][] = 'sequence'; + $link['DebitLedger']['Account']['fields'][] = 'id'; + $link['DebitLedger']['Account']['fields'][] = 'name'; + + $link['MonetarySource']['fields'][] = 'name'; + $link['Customer']['fields'][] = 'name'; + $link['Transaction']['fields'][] = 'id'; + $link['Transaction']['fields'][] = 'stamp'; + + // Income / Receipt flow + // debit: Receipt credit: A/R <-- this entry + // debit: A/R credit: Income <-- CRLE, below + // + // We're searching for the Receipt<->A/R entries, + // which are credits on the A/R account. Find the + // reconciling A/R entries (except for unassigned + // pre-payments, all A/R credits should have one). + $link['CreditReconciliationLedgerEntry']['alias'] = 'RLedgerEntry'; + $link['CreditReconciliationLedgerEntry']['Transaction']['alias'] = 'RTransaction'; + + // Debit should be A/R; Credit is Account of interest + $link['CreditReconciliationLedgerEntry']['CreditLedger']['alias'] = 'RLedger'; + $link['CreditReconciliationLedgerEntry']['CreditLedger']['Account']['alias'] = 'RAccount'; + + $link['DebitReconciliationLedgerEntry']['alias'] = 'DRLE'; + $link['DebitReconciliationLedgerEntry']['linkalias'] = 'DRLE_R'; + $link['DebitReconciliationLedgerEntry']['DebitLedger']['alias'] = 'DL'; + $link['DebitReconciliationLedgerEntry']['DebitLedger']['Account']['alias'] = 'DA'; + + //$link['DebitReconciliationLedgerEntry']['conditions'] = + + } + if (isset($params['custom']['account_ftype'])) { $ftype = $params['custom']['account_ftype']; $ftype = ucfirst($ftype); @@ -130,7 +174,13 @@ class LedgerEntriesController extends AppController { ? $params['custom']['account_type'] : null); - return $model->ledgerContextFields2($ledger_id, $account_id, $account_type); + $fields = $model->ledgerContextFields2($ledger_id, $account_id, $account_type); + + if ($params['action'] === 'collected') { + $fields[] = 'Reconciliation.amount'; + } + + return $fields; } function jqGridDataConditions(&$params, &$model) { @@ -143,6 +193,23 @@ class LedgerEntriesController extends AppController { $conditions = parent::jqGridDataConditions($params, $model); + if ($params['action'] === 'collected') { + $conditions[] = array('RAccount.id' => $params['custom']['collected_account_id']); + //$conditions[] = array('DebitAccount.tillable' => 1); + //$conditions[] = array('RLedgerEntry.amount != LedgerEntry.amount'); + //$conditions[] = array('Reconciliation.amount < RLedgerEntry.amount'); + $conditions[] = array('DA.payable' => 1); + $conditions[] = array('NOT' => array('DA.name' => 'Concession')); + //$conditions[] = array('DA.name' => 'Check'); + //$conditions[] = array('DA.name' => 'Cash'); + //$conditions[] = array('Transaction.stamp >=' => '2009-03-26'); + //$conditions[] = array('Transaction.stamp <' => '2009-04-11'); + //$conditions[] = array('Transaction.stamp >=' => '2009-04-11'); + //$conditions[] = array('Transaction.stamp <' => '2009-05-09'); + $conditions[] = array('Transaction.stamp >=' => '2009-05-09'); + $conditions[] = array('Transaction.stamp <' => '2009-06-11'); + } + if ($params['action'] === 'ledger') { $conditions[] = $model->ledgerContextConditions($ledger_id, $account_type); } diff --git a/site/views/elements/collected.ctp b/site/views/elements/collected.ctp new file mode 100644 index 0000000..9ea52d1 --- /dev/null +++ b/site/views/elements/collected.ctp @@ -0,0 +1,45 @@ + 'RLedgerEntry.id', 'formatter' => 'id'); +$cols['RDate'] = array('index' => 'RTransaction.stamp', 'formatter' => 'date'); +$cols['REffective'] = array('index' => 'RLedgerEntry.effective_date', 'formatter' => 'date'); +$cols['RThrough'] = array('index' => 'RLedgerEntry.through_date', 'formatter' => 'date'); +$cols['RAccount'] = array('index' => 'RAccount.name', 'formatter' => 'name'); + +//$cols['Transaction'] = array('index' => 'Transaction.id', 'formatter' => 'id'); +$cols['Entry'] = array('index' => 'LedgerEntry.id', 'formatter' => 'id'); + +$cols['Date'] = array('index' => 'Transaction.stamp', 'formatter' => 'date'); + +$cols['Account'] = array('index' => 'DebitAccount.name', 'formatter' => 'name'); + +$cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'longname'); +//$cols['Lease'] = array('index' => 'Lease.number', 'formatter' => 'id'); +$cols['Unit'] = array('index' => 'Unit.name', 'formatter' => 'name'); + +//$cols['Source'] = array('index' => 'MonetarySource.name', 'formatter' => 'name'); +//$cols['Comment'] = array('index' => 'LedgerEntry.comment', 'formatter' => 'comment', 'width'=>150); + +$cols['RAmount'] = array('index' => 'RLedgerEntry.amount', 'formatter' => 'currency'); +$cols['Amount'] = array('index' => 'LedgerEntry.amount', 'formatter' => 'currency'); +$cols['Applied'] = array('index' => 'Reconciliation.amount', 'formatter' => 'currency'); + +$cols['Sub-Total'] = array('index' => 'subtotal', 'formatter' => 'currency', 'sortable' => false); + +// This element is non-standard. +// Let grid know who the controller is +$grid->controller = 'ledger_entries'; + +$collected_account_id = $this->passedArgs[0]; +$collected_not = (isset($this->passedArgs[1]) ? $this->passedArgs[1] : 0); +$grid->customData(compact('collected_account_id', 'collected_not')); + +// Render the grid +$grid +->limit(500) +->columns($cols) +->sortField('Date') +->render($this, isset($config) ? $config : null); From d6be905c083ac975c79389cf26792574cd06986f Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 12 Jul 2009 18:34:24 +0000 Subject: [PATCH 313/717] Added a couple more virtual functions for more controller flexibility. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@319 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/site/app_controller.php b/site/app_controller.php index 35a4729..0d962dd 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -118,7 +118,8 @@ class AppController extends Controller { // Establish the basic query and conditions $query = array_intersect_key($this->jqGridDataCountTables($params, $model), array('link'=>1, 'contain'=>1)); - $query['conditions'] = $this->jqGridDataConditions($params, $model); + $query['conditions'] = $this->jqGridDataCountConditions($params, $model); + $query['group'] = $this->jqGridDataCountGroup($params, $model); // DEBUG PURPOSES ONLY! $params['count_query'] = $query; @@ -234,6 +235,10 @@ class AppController extends Controller { return array('contain' => false); } + function jqGridDataCountConditions(&$params, &$model) { + return $this->jqGridDataConditions($params, $model); + } + function jqGridDataConditions(&$params, &$model) { $searches = array(); @@ -289,6 +294,10 @@ class AppController extends Controller { return null; } + function jqGridDataCountGroup(&$params, &$model) { + return null; + } + function jqGridDataGroup(&$params, &$model) { return $model->alias.'.'.$model->primaryKey; } From 6a0a77c1166f3bf81d2078c25a1b5dbfbeaf589c Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 12 Jul 2009 18:36:22 +0000 Subject: [PATCH 314/717] More todo items git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@320 97e9348a-65ac-dc4b-aefc-98561f571b83 --- todo.notes | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/todo.notes b/todo.notes index bb62b38..3451874 100644 --- a/todo.notes +++ b/todo.notes @@ -10,6 +10,19 @@ DESC even though the sort is ASC. Subsequent clicks don't change anything. You must sort on a different column first then everything works. +Seems like security deposit is suddenly broken. I believe +the customer/lease infobox used to report only PAID +security deposits, but it now seems like it's reporting ALL +security deposits charged. + +Having a grid of ledger entries grouped by transaction appears +to work, from the financial aspect, but the count of entries +is incorrect. The problem is the grouping only occurs after +the count, which it has to in order for the count to work. We +need to obliterate the group_by_tx parameter, and simply use +the transanction controller to generate the grid instead of +ledger_entries. + Handle a credit, ensuring that it's applied to new charges - either automatically; - by user opt-in to use credits when invoicing From b97d071bb4f762b99b5e8952234c5a5fa28129f9 Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 12 Jul 2009 20:15:56 +0000 Subject: [PATCH 315/717] New generic mechanism for subtotaling columns. This is NOT an ideal solution, as it only subtotals for the current grid page. Hopefully we can get something better into the app controller at some point git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@321 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 21 +++++++++++++++++++++ site/views/elements/ledger_entries.ctp | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/site/app_controller.php b/site/app_controller.php index 0d962dd..050d8ae 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -322,6 +322,14 @@ class AppController extends Controller { $model_alias = $model->alias; $id = $model->primaryKey; + $subtotals = array(); + foreach ($params['fields'] AS $field) { + if (preg_match('/subtotal-(.*)$/', $field, $matches)) + $subtotals[] = array('field' => $matches[1], + 'name' => $field, + 'amount' => 0); + } + foreach ($records AS &$record) { $record['jqGrid_id'] = $record[$model_alias][$id]; // Add the calculated fields (if any), to the model fields @@ -329,6 +337,19 @@ class AppController extends Controller { $record[$model_alias] += $record[0]; unset($record[0]); } + + foreach ($subtotals AS &$subtotal) { + $field = $subtotal['field']; + if (preg_match("/\./", $field)) { + list($tbl, $col) = explode(".", $field); + $record['subtotal-'.$tbl][$col] = + ($subtotal['amount'] += $record[$tbl][$col]); + } + else { + $record[$model->alias]['subtotal-'.$field] = + ($subtotal['amount'] += $record[$model->alias][$field]); + } + } } // DEBUG PURPOSES ONLY! diff --git a/site/views/elements/ledger_entries.ctp b/site/views/elements/ledger_entries.ctp index 2dca8c6..ededadc 100644 --- a/site/views/elements/ledger_entries.ctp +++ b/site/views/elements/ledger_entries.ctp @@ -25,7 +25,7 @@ $cols['Debit'] = array('index' => 'debit', 'formatter' => $cols['Credit'] = array('index' => 'credit', 'formatter' => 'currency'); $cols['Applied'] = array('index' => "Reconciliation.amount", 'formatter' => 'currency'); -$cols['Sub-Total'] = array('index' => 'subtotal', 'formatter' => 'currency', 'sortable' => false); +$cols['Sub-Total'] = array('index' => 'subtotal-LedgerEntry.amount', 'formatter' => 'currency', 'sortable' => false); // Since group_by_tx is a boolean, let's just get it From 2cd73ed9e8b057a6de31f249c8e5ec0b9db09e72 Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 12 Jul 2009 20:23:46 +0000 Subject: [PATCH 316/717] Experiment with converting the 'collected' grid results to be a query of the rent ledger entries that resolve out to payments, instead of payment entries that resolve rent entries. It's a subtle difference, but gives a couple benefits. First, rent looks like rent, meaning that if someone paid $30 in rent over 6 days at $5 per day, the collected rent entry shows $30, not 6 entries of $5. Depending on your perspective, that can be a good or bad thing. Since we're looking at collected entries of an account, I think each account entry should only get one line, so this seems like it's a logical fit. The second thing is that I might be able to do away with a collected page altogether, and simply add a 'collected' column to each account/ledger. Not sure on that, especially since we'll be wanting a date range, and probably a selection of which accounts consititute payment (such that the user could simply see rent collected in cash or similar). In any event, this is NOT working at the moment, I seem to be getting invalid data. To figure this out, I'm going to check in now, revert back, and print the results for reference, since it was working before this change, back at r320 git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@322 97e9348a-65ac-dc4b-aefc-98561f571b83 --- .../controllers/ledger_entries_controller.php | 123 +++++++++--------- site/views/elements/collected.ctp | 39 ++++-- 2 files changed, 87 insertions(+), 75 deletions(-) diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index d6fbd0c..e1467bf 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -66,40 +66,6 @@ class LedgerEntriesController extends AppController { ), ); - if ($params['action'] === 'collected') { - $link['DebitLedger']['fields'][] = 'sequence'; - $link['DebitLedger']['Account']['fields'][] = 'id'; - $link['DebitLedger']['Account']['fields'][] = 'name'; - - $link['MonetarySource']['fields'][] = 'name'; - $link['Customer']['fields'][] = 'name'; - $link['Transaction']['fields'][] = 'id'; - $link['Transaction']['fields'][] = 'stamp'; - - // Income / Receipt flow - // debit: Receipt credit: A/R <-- this entry - // debit: A/R credit: Income <-- CRLE, below - // - // We're searching for the Receipt<->A/R entries, - // which are credits on the A/R account. Find the - // reconciling A/R entries (except for unassigned - // pre-payments, all A/R credits should have one). - $link['CreditReconciliationLedgerEntry']['alias'] = 'RLedgerEntry'; - $link['CreditReconciliationLedgerEntry']['Transaction']['alias'] = 'RTransaction'; - - // Debit should be A/R; Credit is Account of interest - $link['CreditReconciliationLedgerEntry']['CreditLedger']['alias'] = 'RLedger'; - $link['CreditReconciliationLedgerEntry']['CreditLedger']['Account']['alias'] = 'RAccount'; - - $link['DebitReconciliationLedgerEntry']['alias'] = 'DRLE'; - $link['DebitReconciliationLedgerEntry']['linkalias'] = 'DRLE_R'; - $link['DebitReconciliationLedgerEntry']['DebitLedger']['alias'] = 'DL'; - $link['DebitReconciliationLedgerEntry']['DebitLedger']['Account']['alias'] = 'DA'; - - //$link['DebitReconciliationLedgerEntry']['conditions'] = - - } - if (isset($params['custom']['account_ftype'])) { $ftype = $params['custom']['account_ftype']; $ftype = ucfirst($ftype); @@ -123,6 +89,55 @@ class LedgerEntriesController extends AppController { ), ); } + elseif ($params['action'] === 'collected') { + // Income / Receipt / Money + // debit: A/R credit: Income <-- this entry + // debit: Receipt credit: A/R <-- ReceiptLedgerEntry, below + // debit: Money credit: Receipt <-- MoneyLedgerEntry, below + + $link['CreditLedger'] = + array('fields' => 'sequence', + 'Account' => + array('fields' => array('id', 'name'), + ), + ); + + $link['MonetarySource'] = array('fields' => array('name')); + $link['Customer'] = array('fields' => array('name')); + $link['Transaction'] = array('fields' => array('id', 'stamp')); + + // We're searching for the Receipt<->A/R entries, + // which are debits on the A/R account. Find the + // reconciling entries to that A/R debit. + $link['DebitReconciliationLedgerEntry'] = + array('alias' => 'ReceiptLedgerEntry', + + 'Transaction' => + array('alias' => 'ReceiptTransaction'), + + // Credit Ledger should be A/R; + // Debit Ledger should be Receipt + 'DebitLedger' => + array('alias' => 'ReceiptLedger', + 'Account' => array('alias' => 'ReceiptAccount'), + ), + + // Finally, the Money (Cash/Check/etc) Entry is the one + // which reconciles our ReceiptLedgerEntry debit + 'DebitReconciliationLedgerEntry' => + array('alias' => 'MoneyLedgerEntry', + 'linkalias' => 'MoneyLedgerEntryR', + + // Credit Ledger should be Receipt; + // Debit Ledger should be our Money Account + 'DebitLedger' => + array('alias' => 'MoneyLedger', + 'Account' => + array('alias' => 'MoneyAccount'), + ), + ), + ); + } else { $link['DebitLedger'] = array('fields' => array('id', 'sequence'), @@ -177,7 +192,7 @@ class LedgerEntriesController extends AppController { $fields = $model->ledgerContextFields2($ledger_id, $account_id, $account_type); if ($params['action'] === 'collected') { - $fields[] = 'Reconciliation.amount'; + $fields[] = 'SUM(Reconciliation.amount) AS applied'; } return $fields; @@ -194,20 +209,22 @@ class LedgerEntriesController extends AppController { $conditions = parent::jqGridDataConditions($params, $model); if ($params['action'] === 'collected') { - $conditions[] = array('RAccount.id' => $params['custom']['collected_account_id']); + $conditions[] = array('Account.id' => $params['custom']['collected_account_id']); //$conditions[] = array('DebitAccount.tillable' => 1); - //$conditions[] = array('RLedgerEntry.amount != LedgerEntry.amount'); - //$conditions[] = array('Reconciliation.amount < RLedgerEntry.amount'); - $conditions[] = array('DA.payable' => 1); - $conditions[] = array('NOT' => array('DA.name' => 'Concession')); + //$conditions[] = array('ReceiptLedgerEntry.amount != LedgerEntry.amount'); + //$conditions[] = array('Reconciliation.amount < ReceiptLedgerEntry.amount'); + $conditions[] = array('MoneyAccount.payable' => 1); + $conditions[] = array('NOT' => array('MoneyAccount.name' => 'Concession')); //$conditions[] = array('DA.name' => 'Check'); //$conditions[] = array('DA.name' => 'Cash'); //$conditions[] = array('Transaction.stamp >=' => '2009-03-26'); //$conditions[] = array('Transaction.stamp <' => '2009-04-11'); - //$conditions[] = array('Transaction.stamp >=' => '2009-04-11'); - //$conditions[] = array('Transaction.stamp <' => '2009-05-09'); - $conditions[] = array('Transaction.stamp >=' => '2009-05-09'); - $conditions[] = array('Transaction.stamp <' => '2009-06-11'); + $conditions[] = array('Transaction.stamp >=' => '2009-04-11'); + $conditions[] = array('Transaction.stamp <' => '2009-05-09'); + //$conditions[] = array('Transaction.stamp >=' => '2009-05-09'); + //$conditions[] = array('Transaction.stamp <' => '2009-06-11'); + //$conditions[] = array('ReceiptTransaction.stamp >=' => '2009-06-11'); + //$conditions[] = array('ReceiptTransaction.stamp <' => '2009-07-11'); } if ($params['action'] === 'ledger') { @@ -306,24 +323,6 @@ class LedgerEntriesController extends AppController { return $order; } - function jqGridRecordsPostProcess(&$params, &$model, &$records) { - parent::jqGridRecordsPostProcess($params, $model, $records); - - $subtotal = 0; - foreach ($records AS &$record) { - $amount = (isset($record['LedgerEntry']['balance']) - ? $record['LedgerEntry']['balance'] - : $record['LedgerEntry']['amount']); - $record['LedgerEntry']['subtotal'] = ($subtotal += $amount); - - continue; - // Experiment to minimize columns by putting the monetary source - // as the Account, when available - if ($record['MonetarySource']['name']) - $record['Account']['name'] = $record['MonetarySource']['name']; - } - } - function jqGridDataOutputRecordCell(&$params, &$model, &$record, $field, $data) { /* if ($field === 'CreditAccount.name') { */ /* $data .= '-OK'; */ diff --git a/site/views/elements/collected.ctp b/site/views/elements/collected.ctp index 9ea52d1..d7350d1 100644 --- a/site/views/elements/collected.ctp +++ b/site/views/elements/collected.ctp @@ -3,18 +3,30 @@ // Define the table columns $cols = array(); -$cols['REntry'] = array('index' => 'RLedgerEntry.id', 'formatter' => 'id'); -$cols['RDate'] = array('index' => 'RTransaction.stamp', 'formatter' => 'date'); -$cols['REffective'] = array('index' => 'RLedgerEntry.effective_date', 'formatter' => 'date'); -$cols['RThrough'] = array('index' => 'RLedgerEntry.through_date', 'formatter' => 'date'); -$cols['RAccount'] = array('index' => 'RAccount.name', 'formatter' => 'name'); - -//$cols['Transaction'] = array('index' => 'Transaction.id', 'formatter' => 'id'); +$cols['Transaction'] = array('index' => 'Transaction.id', 'formatter' => 'id'); $cols['Entry'] = array('index' => 'LedgerEntry.id', 'formatter' => 'id'); - $cols['Date'] = array('index' => 'Transaction.stamp', 'formatter' => 'date'); +$cols['Effective'] = array('index' => 'LedgerEntry.effective_date', 'formatter' => 'date'); +$cols['Through'] = array('index' => 'LedgerEntry.through_date', 'formatter' => 'date'); +//$cols['Account'] = array('index' => 'Account.name', 'formatter' => 'name'); -$cols['Account'] = array('index' => 'DebitAccount.name', 'formatter' => 'name'); +/* $cols['RTransaction'] = array('index' => 'ReceiptTransaction.id', 'formatter' => 'id'); */ +/* $cols['REntry'] = array('index' => 'ReceiptLedgerEntry.id', 'formatter' => 'id'); */ +/* $cols['RDate'] = array('index' => 'ReceiptTransaction.stamp', 'formatter' => 'date'); */ +/* $cols['REffective'] = array('index' => 'ReceiptLedgerEntry.effective_date', 'formatter' => 'date'); */ +/* $cols['RThrough'] = array('index' => 'ReceiptLedgerEntry.through_date', 'formatter' => 'date'); */ +/* $cols['RAccount'] = array('index' => 'ReceiptAccount.name', 'formatter' => 'name'); */ +/* $cols['RAmount'] = array('index' => 'ReceiptLedgerEntry.amount', 'formatter' => 'currency'); */ + +/* $cols['MTransaction'] = array('index' => 'MoneyTransaction.id', 'formatter' => 'id'); */ +/* $cols['MEntry'] = array('index' => 'MoneyLedgerEntry.id', 'formatter' => 'id'); */ +/* $cols['MDate'] = array('index' => 'MoneyTransaction.stamp', 'formatter' => 'date'); */ +/* $cols['MEffective'] = array('index' => 'MoneyLedgerEntry.effective_date', 'formatter' => 'date'); */ +/* $cols['MThrough'] = array('index' => 'MoneyLedgerEntry.through_date', 'formatter' => 'date'); */ +/* $cols['MAccount'] = array('index' => 'MoneyAccount.name', 'formatter' => 'name'); */ +/* $cols['MAmount'] = array('index' => 'MoneyLedgerEntry.amount', 'formatter' => 'currency'); */ + +$cols['Paid'] = array('index' => 'ReceiptTransaction.stamp', 'formatter' => 'date'); $cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'longname'); //$cols['Lease'] = array('index' => 'Lease.number', 'formatter' => 'id'); @@ -23,11 +35,12 @@ $cols['Unit'] = array('index' => 'Unit.name', 'formatter' => //$cols['Source'] = array('index' => 'MonetarySource.name', 'formatter' => 'name'); //$cols['Comment'] = array('index' => 'LedgerEntry.comment', 'formatter' => 'comment', 'width'=>150); -$cols['RAmount'] = array('index' => 'RLedgerEntry.amount', 'formatter' => 'currency'); $cols['Amount'] = array('index' => 'LedgerEntry.amount', 'formatter' => 'currency'); -$cols['Applied'] = array('index' => 'Reconciliation.amount', 'formatter' => 'currency'); +/* $cols['RAmount'] = array('index' => 'ReceiptLedgerEntry.amount', 'formatter' => 'currency'); */ +/* $cols['MAmount'] = array('index' => 'MoneyLedgerEntry.amount', 'formatter' => 'currency'); */ +$cols['Applied'] = array('index' => 'applied', 'formatter' => 'currency'); -$cols['Sub-Total'] = array('index' => 'subtotal', 'formatter' => 'currency', 'sortable' => false); +$cols['Sub-Total'] = array('index' => 'subtotal-applied', 'formatter' => 'currency', 'sortable' => false); // This element is non-standard. // Let grid know who the controller is @@ -41,5 +54,5 @@ $grid->customData(compact('collected_account_id', 'collected_not')); $grid ->limit(500) ->columns($cols) -->sortField('Date') +//->sortField('Date') ->render($this, isset($config) ? $config : null); From 03af4e731fe19e10a88e67a0fd8f20df26c95daa Mon Sep 17 00:00:00 2001 From: abijah Date: Sun, 12 Jul 2009 21:00:38 +0000 Subject: [PATCH 317/717] Fixed the last bug... I had just forgotten to use ReceiptTransaction for the dates in question. Also, I elminated the collected element, and just added a minor tweak to ledger_entries to make it work. I'll work on added user entered dates & accounts soon (perhaps next). git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@323 97e9348a-65ac-dc4b-aefc-98561f571b83 --- .../controllers/ledger_entries_controller.php | 27 +++++---- site/views/elements/collected.ctp | 58 ------------------- site/views/elements/ledger_entries.ctp | 22 +++++-- 3 files changed, 33 insertions(+), 74 deletions(-) delete mode 100644 site/views/elements/collected.ctp diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index e1467bf..ef8c603 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -23,7 +23,13 @@ class LedgerEntriesController extends AppController { * - Generate a listing of ledger_entries */ - function collected() { $this->jqGridView('Collected Entries', null, 'collected'); } + function collected($account_id) { + $A = new Account(); + $this->set('collected_account_id', $account_id); + $this->jqGridView('Collected ' . + $this->LedgerEntry->Ledger->Account->name($account_id) . + ' Entries'); + } /************************************************************************** @@ -191,9 +197,8 @@ class LedgerEntriesController extends AppController { $fields = $model->ledgerContextFields2($ledger_id, $account_id, $account_type); - if ($params['action'] === 'collected') { + if (count(array_intersect($params['fields'], array('applied'))) == 1) $fields[] = 'SUM(Reconciliation.amount) AS applied'; - } return $fields; } @@ -217,14 +222,14 @@ class LedgerEntriesController extends AppController { $conditions[] = array('NOT' => array('MoneyAccount.name' => 'Concession')); //$conditions[] = array('DA.name' => 'Check'); //$conditions[] = array('DA.name' => 'Cash'); - //$conditions[] = array('Transaction.stamp >=' => '2009-03-26'); - //$conditions[] = array('Transaction.stamp <' => '2009-04-11'); - $conditions[] = array('Transaction.stamp >=' => '2009-04-11'); - $conditions[] = array('Transaction.stamp <' => '2009-05-09'); - //$conditions[] = array('Transaction.stamp >=' => '2009-05-09'); - //$conditions[] = array('Transaction.stamp <' => '2009-06-11'); - //$conditions[] = array('ReceiptTransaction.stamp >=' => '2009-06-11'); - //$conditions[] = array('ReceiptTransaction.stamp <' => '2009-07-11'); + //$conditions[] = array('ReceiptTransaction.stamp >=' => '2009-03-26'); + //$conditions[] = array('ReceiptTransaction.stamp <' => '2009-04-11'); + //$conditions[] = array('ReceiptTransaction.stamp >=' => '2009-04-11'); + //$conditions[] = array('ReceiptTransaction.stamp <' => '2009-05-09'); + //$conditions[] = array('ReceiptTransaction.stamp >=' => '2009-05-09'); + //$conditions[] = array('ReceiptTransaction.stamp <' => '2009-06-11'); + $conditions[] = array('ReceiptTransaction.stamp >=' => '2009-06-11'); + $conditions[] = array('ReceiptTransaction.stamp <' => '2009-07-11'); } if ($params['action'] === 'ledger') { diff --git a/site/views/elements/collected.ctp b/site/views/elements/collected.ctp deleted file mode 100644 index d7350d1..0000000 --- a/site/views/elements/collected.ctp +++ /dev/null @@ -1,58 +0,0 @@ - 'Transaction.id', 'formatter' => 'id'); -$cols['Entry'] = array('index' => 'LedgerEntry.id', 'formatter' => 'id'); -$cols['Date'] = array('index' => 'Transaction.stamp', 'formatter' => 'date'); -$cols['Effective'] = array('index' => 'LedgerEntry.effective_date', 'formatter' => 'date'); -$cols['Through'] = array('index' => 'LedgerEntry.through_date', 'formatter' => 'date'); -//$cols['Account'] = array('index' => 'Account.name', 'formatter' => 'name'); - -/* $cols['RTransaction'] = array('index' => 'ReceiptTransaction.id', 'formatter' => 'id'); */ -/* $cols['REntry'] = array('index' => 'ReceiptLedgerEntry.id', 'formatter' => 'id'); */ -/* $cols['RDate'] = array('index' => 'ReceiptTransaction.stamp', 'formatter' => 'date'); */ -/* $cols['REffective'] = array('index' => 'ReceiptLedgerEntry.effective_date', 'formatter' => 'date'); */ -/* $cols['RThrough'] = array('index' => 'ReceiptLedgerEntry.through_date', 'formatter' => 'date'); */ -/* $cols['RAccount'] = array('index' => 'ReceiptAccount.name', 'formatter' => 'name'); */ -/* $cols['RAmount'] = array('index' => 'ReceiptLedgerEntry.amount', 'formatter' => 'currency'); */ - -/* $cols['MTransaction'] = array('index' => 'MoneyTransaction.id', 'formatter' => 'id'); */ -/* $cols['MEntry'] = array('index' => 'MoneyLedgerEntry.id', 'formatter' => 'id'); */ -/* $cols['MDate'] = array('index' => 'MoneyTransaction.stamp', 'formatter' => 'date'); */ -/* $cols['MEffective'] = array('index' => 'MoneyLedgerEntry.effective_date', 'formatter' => 'date'); */ -/* $cols['MThrough'] = array('index' => 'MoneyLedgerEntry.through_date', 'formatter' => 'date'); */ -/* $cols['MAccount'] = array('index' => 'MoneyAccount.name', 'formatter' => 'name'); */ -/* $cols['MAmount'] = array('index' => 'MoneyLedgerEntry.amount', 'formatter' => 'currency'); */ - -$cols['Paid'] = array('index' => 'ReceiptTransaction.stamp', 'formatter' => 'date'); - -$cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'longname'); -//$cols['Lease'] = array('index' => 'Lease.number', 'formatter' => 'id'); -$cols['Unit'] = array('index' => 'Unit.name', 'formatter' => 'name'); - -//$cols['Source'] = array('index' => 'MonetarySource.name', 'formatter' => 'name'); -//$cols['Comment'] = array('index' => 'LedgerEntry.comment', 'formatter' => 'comment', 'width'=>150); - -$cols['Amount'] = array('index' => 'LedgerEntry.amount', 'formatter' => 'currency'); -/* $cols['RAmount'] = array('index' => 'ReceiptLedgerEntry.amount', 'formatter' => 'currency'); */ -/* $cols['MAmount'] = array('index' => 'MoneyLedgerEntry.amount', 'formatter' => 'currency'); */ -$cols['Applied'] = array('index' => 'applied', 'formatter' => 'currency'); - -$cols['Sub-Total'] = array('index' => 'subtotal-applied', 'formatter' => 'currency', 'sortable' => false); - -// This element is non-standard. -// Let grid know who the controller is -$grid->controller = 'ledger_entries'; - -$collected_account_id = $this->passedArgs[0]; -$collected_not = (isset($this->passedArgs[1]) ? $this->passedArgs[1] : 0); -$grid->customData(compact('collected_account_id', 'collected_not')); - -// Render the grid -$grid -->limit(500) -->columns($cols) -//->sortField('Date') -->render($this, isset($config) ? $config : null); diff --git a/site/views/elements/ledger_entries.ctp b/site/views/elements/ledger_entries.ctp index ededadc..0dd3b03 100644 --- a/site/views/elements/ledger_entries.ctp +++ b/site/views/elements/ledger_entries.ctp @@ -24,7 +24,8 @@ $cols['Amount'] = array('index' => 'LedgerEntry.amount', 'formatter' => $cols['Debit'] = array('index' => 'debit', 'formatter' => 'currency'); $cols['Credit'] = array('index' => 'credit', 'formatter' => 'currency'); -$cols['Applied'] = array('index' => "Reconciliation.amount", 'formatter' => 'currency'); +$cols['Paid'] = array('index' => 'ReceiptTransaction.stamp', 'formatter' => 'date'); +$cols['Applied'] = array('index' => "applied", 'formatter' => 'currency'); $cols['Sub-Total'] = array('index' => 'subtotal-LedgerEntry.amount', 'formatter' => 'currency', 'sortable' => false); @@ -53,12 +54,15 @@ if ($group_by_tx) if ($group_by_tx) $grid->invalidFields(array('Effective', 'Through')); +if (!isset($collected_account_id)) + $grid->invalidFields('Paid'); + if (isset($account_ftype) || isset($ledger_id) || isset($account_id) || isset($ar_account)) $grid->invalidFields(array('Debit Account', 'Credit Account')); else $grid->invalidFields('Account'); -if (isset($no_account) || $group_by_tx) +if (isset($no_account) || $group_by_tx || isset($collected_account_id)) $grid->invalidFields(array('Account', 'Debit Account', 'Credit Account')); if (isset($ledger_id) || isset($account_id) || isset($ar_account)) @@ -74,14 +78,18 @@ if (isset($lease_id) || isset($customer_id)) if (isset($lease_id) || $group_by_tx) $grid->invalidFields(array('Lease', 'Unit')); -if (!isset($reconcile_id)) +if (!isset($reconcile_id) && !isset($collected_account_id)) $grid->invalidFields('Applied'); +if (isset($collected_account_id)) + $cols['Sub-Total']['index'] = 'subtotal-applied'; + if (isset($account_ftype)) $grid->invalidFields('Sub-Total'); -if (!isset($config['rows'])) { + +if (!isset($config['rows']) && !isset($collected_account_id)) { $config['action'] = 'ledger'; $grid->limit(50); } @@ -90,6 +98,10 @@ if (isset($reconcile_id)) { $grid->customData(compact('reconcile_id'))->limit(20); } +if (isset($collected_account_id)) { + $grid->customData(compact('collected_account_id'))->limit(500); +} + // Set up search fields if requested by caller if (isset($searchfields)) $grid->searchFields(array('Customer', 'Unit')); @@ -105,7 +117,7 @@ $grid ->sortField('Date') ->defaultFields(array('Entry', 'Date', 'Amount', 'Credit', 'Debit')) ->render($this, isset($config) ? $config : null, - array('Transaction', 'Entry', 'Date', 'Effective', + array('Transaction', 'Entry', 'Date', 'Effective', 'Paid', 'Account', 'Debit Account', 'Credit Account', 'Customer', 'Unit', 'Comment', From 8a3c6ae21b7c526591c6f2db91e8480cf3ed763a Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 13 Jul 2009 02:24:31 +0000 Subject: [PATCH 318/717] A working version of the collected report for accounts. There is still some error checking to do, since we don't want this report for just any account. Also, we may wish to do away with the form to prevent accidental submittal. Finally, it would be nice to do away with the button, and automatically update on date changes. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@324 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/accounts_controller.php | 84 ++-------- .../controllers/ledger_entries_controller.php | 53 +++---- site/models/account.php | 1 + site/views/accounts/collected.ctp | 145 ++++++++++++++++++ site/views/elements/form_table.ctp | 6 +- site/views/elements/ledger_entries.ctp | 11 +- 6 files changed, 195 insertions(+), 105 deletions(-) create mode 100644 site/views/accounts/collected.ctp diff --git a/site/controllers/accounts_controller.php b/site/controllers/accounts_controller.php index 8b17dfa..52e3a88 100644 --- a/site/controllers/accounts_controller.php +++ b/site/controllers/accounts_controller.php @@ -146,77 +146,26 @@ class AccountsController extends AppController { * - 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) { - //if ($this->data) { - //pr($this->data); - //} + function collected($id = null) { + if (!$id) { + $this->Session->setFlash(__('Invalid Item.', true)); + $this->redirect(array('action'=>'index')); + } -/* $tillable_account = $this->Account->relatedAccounts('tillable'); */ -/* $depositable_account = $this->Account->relatedAccounts('depositable'); */ + $payment_accounts = $this->Account->paymentAccounts(); + $default_accounts = array_diff_key($payment_accounts, + array($this->Account->concessionAccountID() => 1)); + $this->set(compact('payment_accounts', 'default_accounts')); - $ledger_entries = - $this->Account->Ledger->LedgerEntry->find - ('all', - array('link' => array - ('Ledger' => - array('fields' => array('sequence'), + $this->Account->recursive = -1; + $account = $this->Account->read(null, $id); + $account = $account['Account']; - 'Account' => - array('fields' => array('id', 'name')), - ), - - 'MonetarySource' => - array('fields' => array('name')), - - 'Customer' => - array('fields' => array('name')), - - 'Transaction' => - array('fields' => array('stamp')), - - // Income / Receipt flow - // debit: Receipt credit: A/R <-- this entry - // debit: A/R credit: Income <-- CRLE, below - // - // We're searching for the Receipt<->A/R entries, - // which are credits on the A/R account. Find the - // reconciling A/R entries (except for unassigned - // pre-payments, all A/R credits should have one). - 'CreditReconciliationLedgerEntry' => - array('alias' => 'RLedgerEntry', - 'fields' => true, - - 'Transaction' => - array('alias' => 'RTransaction', - 'fields' => array('stamp')), - - // Debit should be A/R; Credit is Account of interest - 'CreditLedger' => - array('alias' => 'RLedger', - 'fields' => true, - - 'Account' => - array('alias' => 'RAccount', - 'fields' => true, - - ), - ), - ), - ), - - 'fields' => array('LedgerEntry.*', 'Reconciliation.amount'), - 'conditions' => array(array('RAccount.id' => $id), - //array('Account.tillable' => 1), - ), - )); - - pr(compact('ledger_entries')); - - $title = 'Collected Whatever'; - $this->set(compact('title', 'ledger_entries')); - //$this->render('/empty'); + $title = ($account['name'] . ': Collected Report'); + $this->set(compact('account', 'title')); } + /************************************************************************** ************************************************************************** ************************************************************************** @@ -337,8 +286,7 @@ class AccountsController extends AppController { $this->sidemenu_links[] = array('name' => 'New Ledger', 'url' => array('action' => 'newledger', $id)); $this->sidemenu_links[] = - array('name' => 'Collected', 'url' => array('controller' => 'ledger_entries', - 'action' => 'collected', $id)); + array('name' => 'Collected', 'url' => array('action' => 'collected', $id)); // Prepare to render $title = 'Account: ' . $account['Account']['name']; diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index ef8c603..9e6ee26 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -16,22 +16,6 @@ class LedgerEntriesController extends AppController { } - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: index / etc - * - Generate a listing of ledger_entries - */ - - function collected($account_id) { - $A = new Account(); - $this->set('collected_account_id', $account_id); - $this->jqGridView('Collected ' . - $this->LedgerEntry->Ledger->Account->name($account_id) . - ' Entries'); - } - - /************************************************************************** ************************************************************************** ************************************************************************** @@ -214,22 +198,27 @@ class LedgerEntriesController extends AppController { $conditions = parent::jqGridDataConditions($params, $model); if ($params['action'] === 'collected') { - $conditions[] = array('Account.id' => $params['custom']['collected_account_id']); - //$conditions[] = array('DebitAccount.tillable' => 1); - //$conditions[] = array('ReceiptLedgerEntry.amount != LedgerEntry.amount'); - //$conditions[] = array('Reconciliation.amount < ReceiptLedgerEntry.amount'); - $conditions[] = array('MoneyAccount.payable' => 1); - $conditions[] = array('NOT' => array('MoneyAccount.name' => 'Concession')); - //$conditions[] = array('DA.name' => 'Check'); - //$conditions[] = array('DA.name' => 'Cash'); - //$conditions[] = array('ReceiptTransaction.stamp >=' => '2009-03-26'); - //$conditions[] = array('ReceiptTransaction.stamp <' => '2009-04-11'); - //$conditions[] = array('ReceiptTransaction.stamp >=' => '2009-04-11'); - //$conditions[] = array('ReceiptTransaction.stamp <' => '2009-05-09'); - //$conditions[] = array('ReceiptTransaction.stamp >=' => '2009-05-09'); - //$conditions[] = array('ReceiptTransaction.stamp <' => '2009-06-11'); - $conditions[] = array('ReceiptTransaction.stamp >=' => '2009-06-11'); - $conditions[] = array('ReceiptTransaction.stamp <' => '2009-07-11'); + extract($params['custom']); + + if (isset($collected_account_id)) + $conditions[] = array('Account.id' => $params['custom']['collected_account_id']); + else + die("INTERNAL ERROR: COLLECTED ACCOUNT ID NOT SET"); + + if (isset($collected_from_date)) + $conditions[] + = array('ReceiptTransaction.stamp >=' => + $this->LedgerEntry->Transaction->dateFormatBeforeSave($collected_from_date)); + + if (isset($collected_through_date)) + $conditions[] + = array('ReceiptTransaction.stamp <=' => + $this->LedgerEntry->Transaction->dateFormatBeforeSave($collected_through_date . ' 23:59:59')); + + if (isset($collected_payment_accounts)) + $conditions[] = array('MoneyAccount.id' => $collected_payment_accounts); + else + $conditions[] = array('MoneyAccount.payable' => 1); } if ($params['action'] === 'ledger') { diff --git a/site/models/account.php b/site/models/account.php index 56b90f2..f2fde75 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -119,6 +119,7 @@ class Account extends AppModel { function cashAccountID() { return $this->nameToID('Cash'); } function checkAccountID() { return $this->nameToID('Check'); } function moneyOrderAccountID() { return $this->nameToID('Money Order'); } + function concessionAccountID() { return $this->nameToID('Concession'); } function pettyCashAccountID() { return $this->nameToID('Petty Cash'); } function invoiceAccountID() { return $this->nameToID('Invoice'); } function receiptAccountID() { return $this->nameToID('Receipt'); } diff --git a/site/views/accounts/collected.ctp b/site/views/accounts/collected.ctp new file mode 100644 index 0000000..92b50e9 --- /dev/null +++ b/site/views/accounts/collected.ctp @@ -0,0 +1,145 @@ +' . "\n"; + +/********************************************************************** + ********************************************************************** + ********************************************************************** + ********************************************************************** + * Javascript + */ + +?> + + + +' . "\n"; + +echo $form->create(null, array('id' => 'receipt-form', + //'onsubmit' => 'updateEntriesGrid(); return false', + 'url' => array('controller' => 'transactions', + 'action' => 'postReceipt'))); + +echo $form->input("id", + array('id' => 'account-id', + 'type' => 'hidden', + 'value' => 0)); + +echo $this->element('form_table', + array('class' => "item account collected entry", + //'with_name_after' => ':', + 'field_prefix' => 'Tx.', + 'fields' => array + ("account_id" => array('name' => 'Account', + 'opts' => + array('type' => 'select', + 'multiple' => 'checkbox', + 'options' => $paymentAccounts, + 'selected' => array_keys($defaultAccounts), + ), + ), + "from_date" => array('opts' => + array('type' => 'text'), + 'between' => 'BOM', + ), + "through_date" => array('opts' => + array('type' => 'text'), + 'between' => 'EOM', + ), + ), + )); + +echo $form->button('Update', + array('onclick' => 'updateEntriesGrid(); return false', + )); + +echo $form->end(); + +echo $this->element('ledger_entries', array + (// Element configuration + 'collected_account_id' => $account['id'], + 'collected_payment_accounts' => array_keys($defaultAccounts), + + // Grid configuration + 'config' => array + ( + 'grid_div_id' => 'collected-entries', + 'grid_div_class' => 'text-below', + //'caption' => '', + 'caption' => 'Collected Charges', + ), + )); + +echo('
    ' . + '' . + '' . + '
    Balance:
    ' . + '
    ' . + "\n"); + +?> + + + +
    + +Clear Debug Output diff --git a/site/views/elements/form_table.ctp b/site/views/elements/form_table.ctp index cecc4ad..8a9b5fa 100644 --- a/site/views/elements/form_table.ctp +++ b/site/views/elements/form_table.ctp @@ -64,8 +64,10 @@ foreach ($fields AS $field => $config) { elseif (isset($field_prefix) && !isset($config['no_prefix'])) $field = $field_prefix . '.' . $field; - $config['opts']['label'] = false; - $config['opts']['div'] = false; + if (!isset($config['opts']['label'])) + $config['opts']['label'] = false; + if (!isset($config['opts']['div'])) + $config['opts']['div'] = false; $cells = array(); if ($include_before) { diff --git a/site/views/elements/ledger_entries.ctp b/site/views/elements/ledger_entries.ctp index 0dd3b03..ab25b89 100644 --- a/site/views/elements/ledger_entries.ctp +++ b/site/views/elements/ledger_entries.ctp @@ -88,6 +88,12 @@ if (isset($account_ftype)) $grid->invalidFields('Sub-Total'); +// Now that columns are defined, establish basic grid parameters +$grid +->columns($cols) +->sortField('Date') +->defaultFields(array('Entry', 'Date', 'Amount', 'Credit', 'Debit')); + if (!isset($config['rows']) && !isset($collected_account_id)) { $config['action'] = 'ledger'; @@ -99,7 +105,9 @@ if (isset($reconcile_id)) { } if (isset($collected_account_id)) { + $config['action'] = 'collected'; $grid->customData(compact('collected_account_id'))->limit(500); + $grid->sortField('Paid'); } // Set up search fields if requested by caller @@ -113,9 +121,6 @@ $grid->customData(compact('ledger_id', 'account_id', 'ar_account', // Render the grid $grid -->columns($cols) -->sortField('Date') -->defaultFields(array('Entry', 'Date', 'Amount', 'Credit', 'Debit')) ->render($this, isset($config) ? $config : null, array('Transaction', 'Entry', 'Date', 'Effective', 'Paid', 'Account', 'Debit Account', 'Credit Account', From 059dbd31909d7959062a6d36ff4913b7c56d26a2 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 13 Jul 2009 04:40:21 +0000 Subject: [PATCH 319/717] Fix to the sub-total column, which wasn't working for ledgers that have both debits and credits (and thus need a sub-total of balance, not amount git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@325 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/ledger_entries.ctp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/site/views/elements/ledger_entries.ctp b/site/views/elements/ledger_entries.ctp index ab25b89..ebd6b30 100644 --- a/site/views/elements/ledger_entries.ctp +++ b/site/views/elements/ledger_entries.ctp @@ -65,10 +65,13 @@ else if (isset($no_account) || $group_by_tx || isset($collected_account_id)) $grid->invalidFields(array('Account', 'Debit Account', 'Credit Account')); -if (isset($ledger_id) || isset($account_id) || isset($ar_account)) +if (isset($ledger_id) || isset($account_id) || isset($ar_account)) { $grid->invalidFields('Amount'); -else + $cols['Sub-Total']['index'] = 'subtotal-balance'; +} else { $grid->invalidFields(array('Debit', 'Credit')); + $cols['Sub-Total']['index'] = 'subtotal-LedgerEntry.amount'; +} // group_by_tx SHOULD wipe out Customer, but the reality // is that it works good at the present, so we'll leave it. @@ -80,8 +83,7 @@ if (isset($lease_id) || $group_by_tx) if (!isset($reconcile_id) && !isset($collected_account_id)) $grid->invalidFields('Applied'); - -if (isset($collected_account_id)) +else $cols['Sub-Total']['index'] = 'subtotal-applied'; if (isset($account_ftype)) From 865d9ee617a3c9d8bb42084aa634ca342097da56 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 13 Jul 2009 04:41:18 +0000 Subject: [PATCH 320/717] Definitely not yet what we need for reversing charges, but at least the recursive nature seems to be in the right direction. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@326 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/ledger_entry.php | 87 ++++++++++++++++++++++++++++++++---- 1 file changed, 79 insertions(+), 8 deletions(-) diff --git a/site/models/ledger_entry.php b/site/models/ledger_entry.php index 4f6dafd..e40a90f 100644 --- a/site/models/ledger_entry.php +++ b/site/models/ledger_entry.php @@ -241,7 +241,10 @@ class LedgerEntry extends AppModel { * - Reverses the ledger entry */ - function reverse($id) { + function reverse($id, $amount = null, $transaction_id = null, $rec_id = null) { +/* pr(array('LedgerEntry::reverse', */ +/* compact('id', 'amount', 'transaction_id', 'rec_id'))); */ + // Get the LedgerEntry and related fields $entry = $this->find ('first', @@ -251,39 +254,107 @@ class LedgerEntry extends AppModel { 'DebitLedger.account_id', 'CreditLedger.id', 'CreditLedger.account_id', + 'DebitReconciliationLedgerEntry' +/* => */ +/* array('DebitLedger.id', */ +/* 'DebitLedger.account_id', */ +/* 'CreditLedger.id', */ +/* 'CreditLedger.account_id', */ +/* ) */ + , + 'CreditReconciliationLedgerEntry' +/* => */ +/* array('DebitLedger.id', */ +/* 'DebitLedger.account_id', */ +/* 'CreditLedger.id', */ +/* 'CreditLedger.account_id', */ +/* ) */ + , 'Customer.id', 'Lease.id', ), 'fields' => array('LedgerEntry.*'), - 'conditions' => array('LedgerEntry.id' => $id), + 'conditions' => array(array('LedgerEntry.id' => $id), +/* array('NOT' => */ +/* array('OR' => */ +/* array(array('DebitReconciliationLedgerEntry.id' => $rec_id), */ +/* array('CreditReconciliationLedgerEntry.id' => $rec_id), */ +/* ), */ +/* ), */ +/* ), */ + ), )); //pr($entry); + if (!isset($amount)) + $amount = $entry['LedgerEntry']['amount']; + $A = new Account(); $ids = $this->Ledger->Account->postLedgerEntry - (//array('transaction_id' => $entry['Transaction']['id']), - null, + (array('transaction_id' => $transaction_id), null, array('debit_ledger_id' => $A->currentLedgerID($entry['CreditLedger']['account_id']), 'credit_ledger_id' => $A->currentLedgerID($entry['DebitLedger']['account_id']), 'effective_date' => $entry['LedgerEntry']['effective_date'], //'effective_date' => $entry['LedgerEntry']['effective_date'], - 'amount' => $entry['LedgerEntry']['amount'], + 'amount' => $amount, 'lease_id' => $entry['Lease']['id'], 'customer_id' => $entry['Customer']['id'], 'comment' => "Reversal of Ledger Entry #{$id}", ), array('debit' => array(array('LedgerEntry' => array('id' => $entry['LedgerEntry']['id'], - 'amount' => $entry['LedgerEntry']['amount'], + 'amount' => $amount, ))), 'credit' => array(array('LedgerEntry' => array('id' => $entry['LedgerEntry']['id'], - 'amount' => $entry['LedgerEntry']['amount'], - ))), + 'amount' => $amount, + ))), )); + if ($ids['error']) + return null; + + $tid = $ids['transaction_id']; + +/* pr(compact('entry')); */ + + foreach (array('Debit', 'Credit') AS $dc_type) { + foreach ($entry[$dc_type . 'ReconciliationLedgerEntry'] AS $RLE) { +/* pr(array('checkpoint' => "Reverse $dc_type LE", */ +/* compact('id', 'RLE'))); */ + if ($RLE['id'] == $rec_id) + continue; + + if (!$this->reverse($RLE['id'], $RLE['Reconciliation']['amount'], $tid, $id)) + $ids['error'] = true; + +/* $rids = $this->Ledger->Account->postLedgerEntry */ +/* (array('transaction_id' => $tid), */ +/* null, */ +/* array('debit_ledger_id' => $A->currentLedgerID($RLE['CreditLedger']['account_id']), */ +/* 'credit_ledger_id' => $A->currentLedgerID($RLE['DebitLedger']['account_id']), */ +/* 'effective_date' => $RLE['effective_date'], */ +/* //'effective_date' => $RLE['effective_date'], */ +/* 'amount' => $RLE['Reconciliation']['amount'], */ +/* 'lease_id' => $entry['Lease']['id'], */ +/* 'customer_id' => $entry['Customer']['id'], */ +/* 'comment' => "Reversal of Ledger Entry #{$RLE['id']}", */ +/* ), */ +/* array('debit' => array(array('LedgerEntry' => array('id' => $RLE['id'], */ +/* 'amount' => $RLE['Reconciliation']['amount'], */ +/* ))), */ +/* 'credit' => array(array('LedgerEntry' => array('id' => $RLE['id'], */ +/* 'amount' => $RLE['Reconciliation']['amount'], */ +/* ))), */ +/* )); */ + +/* if ($rids['error']) */ +/* $ids['error'] = true; */ + } + } + if ($ids['error']) return null; From 8b7c27b5dbda2a353a1d2803cafca33a3968ad87 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 13 Jul 2009 09:54:49 +0000 Subject: [PATCH 321/717] Added a ledger entry listing on the monetary source view page. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@327 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/ledger_entries_controller.php | 5 +++++ site/views/elements/ledger_entries.ctp | 2 +- site/views/monetary_sources/view.ctp | 16 ++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index 9e6ee26..d5165bc 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -282,6 +282,11 @@ class LedgerEntriesController extends AppController { array('Transaction.id' => $params['custom']['transaction_id']); } + if (isset($params['custom']['monetary_source_id'])) { + $conditions[] = + array('MonetarySource.id' => $params['custom']['monetary_source_id']); + } + return $conditions; } diff --git a/site/views/elements/ledger_entries.ctp b/site/views/elements/ledger_entries.ctp index ebd6b30..293f266 100644 --- a/site/views/elements/ledger_entries.ctp +++ b/site/views/elements/ledger_entries.ctp @@ -118,7 +118,7 @@ if (isset($searchfields)) // Include custom data $grid->customData(compact('ledger_id', 'account_id', 'ar_account', - 'account_type', 'account_ftype', + 'account_type', 'account_ftype', 'monetary_source_id', 'customer_id', 'lease_id', 'transaction_id', 'group_by_tx')); // Render the grid diff --git a/site/views/monetary_sources/view.ctp b/site/views/monetary_sources/view.ctp index 371cf1b..bc9ed3d 100644 --- a/site/views/monetary_sources/view.ctp +++ b/site/views/monetary_sources/view.ctp @@ -50,6 +50,22 @@ echo '
    ' . "\n"; echo '
    ' . "\n"; + +/********************************************************************** + * Ledger Entries + */ + +echo $this->element('ledger_entries', array + (// Element configuration + 'monetary_source_id' => $source['id'], + + // Grid configuration + 'config' => array + ('caption' => "Ledger Entries", + ), + )); + + /* End "detail supporting" div */ echo '
    ' . "\n"; From abc5f1feff3448cbc3945f3e2dbda94d6cc35cf3 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 13 Jul 2009 10:14:38 +0000 Subject: [PATCH 322/717] Implementing NSF in MonetarySourcesController. It's nowhere near done, but it seems we're headed in the right direction. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@328 97e9348a-65ac-dc4b-aefc-98561f571b83 --- .../monetary_sources_controller.php | 32 ++++ site/models/ledger_entry.php | 148 ++++++++++++++++ site/models/monetary_source.php | 159 ++++++++++++++++++ 3 files changed, 339 insertions(+) diff --git a/site/controllers/monetary_sources_controller.php b/site/controllers/monetary_sources_controller.php index cef0f05..9cc46a9 100644 --- a/site/controllers/monetary_sources_controller.php +++ b/site/controllers/monetary_sources_controller.php @@ -48,6 +48,22 @@ class MonetarySourcesController extends AppController { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: nsf + * - Marks a monetary source as having insufficient funds. + */ + + function nsf($id = null) { + if (!$id) { + $this->Session->setFlash(__('Invalid Item.', true)); + $this->redirect(array('action'=>'index')); + } + + $this->MonetarySource->nsf($id); + } + /************************************************************************** ************************************************************************** ************************************************************************** @@ -67,6 +83,22 @@ class MonetarySourcesController extends AppController { ('contain' => false, )); + // REVISIT : 20090713 + // Consider allowing the NSF operation only if the source is used on + // a ledger entry that is debited on a "payable" account (perhaps + // even restricted to "payable" ASSET accounts), credited on Receipt + // (or A/R), and reconciles the credit to an entry that debits on a + // "depositable" account. + + // Set up dynamic menu items + $this->sidemenu_links[] = + array('name' => 'Operations', 'header' => true); + + $this->sidemenu_links[] = + array('name' => 'NSF', + 'url' => array('action' => 'nsf', + $id)); + // Prepare to render. $title = "Monetary Source #{$monetary_source['MonetarySource']['id']}"; $this->set(compact('monetary_source', 'title')); diff --git a/site/models/ledger_entry.php b/site/models/ledger_entry.php index e40a90f..f947902 100644 --- a/site/models/ledger_entry.php +++ b/site/models/ledger_entry.php @@ -318,6 +318,154 @@ class LedgerEntry extends AppModel { $tid = $ids['transaction_id']; + pr(compact('entry')); + + foreach (array('Debit', 'Credit') AS $dc_type) { + foreach ($entry[$dc_type . 'ReconciliationLedgerEntry'] AS $RLE) { + pr(array('checkpoint' => "Reverse $dc_type LE", + compact('id', 'rec_id', 'RLE'))); + if ($RLE['id'] == $rec_id) { + pr(array('checkpoint' => "Skipping Reverse $dc_type LE, due to rec_id", + compact('id', 'RLE'))); + continue; + } + + if (!$this->reverse($RLE['id'], $RLE['Reconciliation']['amount'], $tid, $id)) + $ids['error'] = true; + +/* $rids = $this->Ledger->Account->postLedgerEntry */ +/* (array('transaction_id' => $tid), */ +/* null, */ +/* array('debit_ledger_id' => $A->currentLedgerID($RLE['CreditLedger']['account_id']), */ +/* 'credit_ledger_id' => $A->currentLedgerID($RLE['DebitLedger']['account_id']), */ +/* 'effective_date' => $RLE['effective_date'], */ +/* //'effective_date' => $RLE['effective_date'], */ +/* 'amount' => $RLE['Reconciliation']['amount'], */ +/* 'lease_id' => $entry['Lease']['id'], */ +/* 'customer_id' => $entry['Customer']['id'], */ +/* 'comment' => "Reversal of Ledger Entry #{$RLE['id']}", */ +/* ), */ +/* array('debit' => array(array('LedgerEntry' => array('id' => $RLE['id'], */ +/* 'amount' => $RLE['Reconciliation']['amount'], */ +/* ))), */ +/* 'credit' => array(array('LedgerEntry' => array('id' => $RLE['id'], */ +/* 'amount' => $RLE['Reconciliation']['amount'], */ +/* ))), */ +/* )); */ + +/* if ($rids['error']) */ +/* $ids['error'] = true; */ + } + } + + if ($ids['error']) + return null; + + return $ids['id']; + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: nsf + * - Flags the ledger entry as having insufficient funds + * - NOTE: nsf only works if given transaction t2b, below + * + * FEE RENT A/R RECEIPT CHECK NSF BANK + * ------- ------- ------- ------- ------- ------- ------- + * | |50 50| | | | | t1 + * | | | | | | | + * | | |50 50| | | | t2a + * | | | |50 50| | | t2b + * | | | | | | | + * | | | | |50 | 50| t3 + * | | | | | | | + * | | | | | 50| |50 t4a + * | | 50| | | |50 | t4b + * |35 | 35| | | | | t4b + * + */ + + function nsf($id, $amount = null, $transaction_id = null, $rec_id = null) { + pr(array('LedgerEntry::nsf', + compact('id', 'amount', 'transaction_id', 'rec_id'))); + + // Get the LedgerEntry and related fields + $entry = $this->find + ('first', + array('contain' => array(/* t2b */ + 'Transaction.id', + 'MonetarySource.id', + 'Customer.id', + 'Lease.id', + + /* e.g. CHECK */ +/* 'DebitLedger.account_id', */ + 'DebitLedger' => + array('fields' => array(), + 'Account' => + array('fields' => array('id', 'name'), + 'conditions' => + array(array('Account.payable' => 1), + array('Account.type' => 'ASSET')), + ), + ), + + /* e.g. RECEIPT */ +/* 'CreditLedger.account_id', */ + array('fields' => array(), + 'Account' => + array('fields' => array('id', 'name'), + 'conditions' => + array('Account.depositable' => 1), + ), + ), + + /* t3 */ + 'DebitReconciliationLedgerEntry' => + array(/* e.g. BANK */ + 'DebitLedger.account_id', + ), + ), + +/* 'fields' => array('LedgerEntry.*'), */ + + 'conditions' => array(array('LedgerEntry.id' => $id), + ), + )); + pr($entry); + + if (!isset($amount)) + $amount = $entry['LedgerEntry']['amount']; + + $A = new Account(); + + $ids = $this->Ledger->Account->postLedgerEntry + (array('transaction_id' => $transaction_id), + null, + array('debit_ledger_id' => $A->currentLedgerID($entry['CreditLedger']['account_id']), + 'credit_ledger_id' => $A->currentLedgerID($entry['DebitLedger']['account_id']), + 'effective_date' => $entry['LedgerEntry']['effective_date'], + //'effective_date' => $entry['LedgerEntry']['effective_date'], + 'amount' => $amount, + 'lease_id' => $entry['Lease']['id'], + 'customer_id' => $entry['Customer']['id'], + 'comment' => "Reversal of Ledger Entry #{$id}", + ), + array('debit' => array(array('LedgerEntry' => array('id' => $entry['LedgerEntry']['id'], + 'amount' => $amount, + ))), + 'credit' => array(array('LedgerEntry' => array('id' => $entry['LedgerEntry']['id'], + 'amount' => $amount, + ))), + )); + + if ($ids['error']) + return null; + + $tid = $ids['transaction_id']; + /* pr(compact('entry')); */ foreach (array('Debit', 'Credit') AS $dc_type) { diff --git a/site/models/monetary_source.php b/site/models/monetary_source.php index 32b99fb..dc30bec 100644 --- a/site/models/monetary_source.php +++ b/site/models/monetary_source.php @@ -15,5 +15,164 @@ class MonetarySource extends AppModel { 'LedgerEntry', ); + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: nsf + * - Flags the ledger entry as having insufficient funds + * - NOTE: nsf only works if given the monetary source id + * to transaction t2b, below + * + * FEE RENT A/R RECEIPT CHECK NSF BANK + * ------- ------- ------- ------- ------- ------- ------- + * | |50 50| | | | | t1 + * | | | | | | | + * | | |50 50| | | | t2a + * | | | |50 50| | | t2b + * | | | | | | | + * | | | | |50 | 50| t3 + * | | | | | | | + * | | | | | 50| |50 t4a + * | | 50| | | |50 | t4b + * |35 | 35| | | | | t4b + * + */ + + function nsf($id) { + pr(array('MonetarySource::nsf', + compact('id'))); + + $A = new Account(); + + // Get the LedgerEntries that use this monetary source + $entries = $this->find + ('all', + array('contain' => + array(/* t2b */ + 'LedgerEntry' => + array('Transaction.id', + 'MonetarySource.id', + 'Customer.id', + 'Lease.id', + + /* e.g. CHECK */ + 'DebitLedger' => + array('fields' => array(), + 'Account' => + array('fields' => array('id', 'name'), + 'conditions' => +/* array(array('Account.payable' => 1), */ +/* array('Account.type' => 'ASSET')), */ + array('Account.payable' => 1, + 'Account.type' => 'ASSET'), + ), + ), + + /* e.g. RECEIPT */ + 'CreditLedger' => + array('fields' => array(), + 'Account' => + array('fields' => array('id', 'name'), + 'conditions' => + array('Account.id' => $A->receiptAccountID()), + ), + ), + + /* t3 */ + 'CreditReconciliationLedgerEntry' => + array(/* e.g. BANK */ + 'DebitLedger' => + array('fields' => array(), + 'Account' => + array('fields' => array('id', 'name'), + 'conditions' => + array('Account.depositable' => 1), + ), + ), + ), + ), + ), + +/* 'fields' => array('LedgerEntry.*'), */ + + 'conditions' => array(array('MonetarySource.id' => $id), + ), + )); + pr($entries); + die(); + + if (!isset($amount)) + $amount = $entry['LedgerEntry']['amount']; + + $ids = $this->Ledger->Account->postLedgerEntry + (array('transaction_id' => $transaction_id), + null, + array('debit_ledger_id' => $A->currentLedgerID($entry['CreditLedger']['account_id']), + 'credit_ledger_id' => $A->currentLedgerID($entry['DebitLedger']['account_id']), + 'effective_date' => $entry['LedgerEntry']['effective_date'], + //'effective_date' => $entry['LedgerEntry']['effective_date'], + 'amount' => $amount, + 'lease_id' => $entry['Lease']['id'], + 'customer_id' => $entry['Customer']['id'], + 'comment' => "Reversal of Ledger Entry #{$id}", + ), + array('debit' => array(array('LedgerEntry' => array('id' => $entry['LedgerEntry']['id'], + 'amount' => $amount, + ))), + 'credit' => array(array('LedgerEntry' => array('id' => $entry['LedgerEntry']['id'], + 'amount' => $amount, + ))), + )); + + if ($ids['error']) + return null; + + $tid = $ids['transaction_id']; + +/* pr(compact('entry')); */ + + foreach (array('Debit', 'Credit') AS $dc_type) { + foreach ($entry[$dc_type . 'ReconciliationLedgerEntry'] AS $RLE) { +/* pr(array('checkpoint' => "Reverse $dc_type LE", */ +/* compact('id', 'RLE'))); */ + if ($RLE['id'] == $rec_id) + continue; + + if (!$this->reverse($RLE['id'], $RLE['Reconciliation']['amount'], $tid, $id)) + $ids['error'] = true; + +/* $rids = $this->Ledger->Account->postLedgerEntry */ +/* (array('transaction_id' => $tid), */ +/* null, */ +/* array('debit_ledger_id' => $A->currentLedgerID($RLE['CreditLedger']['account_id']), */ +/* 'credit_ledger_id' => $A->currentLedgerID($RLE['DebitLedger']['account_id']), */ +/* 'effective_date' => $RLE['effective_date'], */ +/* //'effective_date' => $RLE['effective_date'], */ +/* 'amount' => $RLE['Reconciliation']['amount'], */ +/* 'lease_id' => $entry['Lease']['id'], */ +/* 'customer_id' => $entry['Customer']['id'], */ +/* 'comment' => "Reversal of Ledger Entry #{$RLE['id']}", */ +/* ), */ +/* array('debit' => array(array('LedgerEntry' => array('id' => $RLE['id'], */ +/* 'amount' => $RLE['Reconciliation']['amount'], */ +/* ))), */ +/* 'credit' => array(array('LedgerEntry' => array('id' => $RLE['id'], */ +/* 'amount' => $RLE['Reconciliation']['amount'], */ +/* ))), */ +/* )); */ + +/* if ($rids['error']) */ +/* $ids['error'] = true; */ + } + } + + if ($ids['error']) + return null; + + return $ids['id']; + } + + } ?> \ No newline at end of file From 60f43efdb7119634fcee436305f63097f907a954 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 14 Jul 2009 20:48:16 +0000 Subject: [PATCH 323/717] The NSF functionality is working good from a strictly general ledger point of view. However, as it's implemented, it's leaving us unable to observe that we've actually experienced negative collected rent. This is a big problem, but I've put a couple notes in place on how I might try to proceed on this next, and am checking in this semi-working version. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@329 97e9348a-65ac-dc4b-aefc-98561f571b83 --- .../monetary_sources_controller.php | 6 +- site/models/account.php | 2 + site/models/monetary_source.php | 170 +++++++++++------- 3 files changed, 114 insertions(+), 64 deletions(-) diff --git a/site/controllers/monetary_sources_controller.php b/site/controllers/monetary_sources_controller.php index 9cc46a9..5fb50bd 100644 --- a/site/controllers/monetary_sources_controller.php +++ b/site/controllers/monetary_sources_controller.php @@ -61,7 +61,11 @@ class MonetarySourcesController extends AppController { $this->redirect(array('action'=>'index')); } - $this->MonetarySource->nsf($id); + // REVISIT : 20090713 + // For testing purposes, must be deleted + $stamp = '2009-07-09'; + + $this->MonetarySource->nsf($id, $stamp); } /************************************************************************** diff --git a/site/models/account.php b/site/models/account.php index f2fde75..66a69ef 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -114,6 +114,8 @@ class Account extends AppModel { function securityDepositAccountID() { return $this->nameToID('Security Deposit'); } function rentAccountID() { return $this->nameToID('Rent'); } function lateChargeAccountID() { return $this->nameToID('Late Charge'); } + function nsfAccountID() { return $this->nameToID('NSF'); } + function nsfChargeAccountID() { return $this->nameToID('NSF Charge'); } function taxAccountID() { return $this->nameToID('Tax'); } function accountReceivableAccountID() { return $this->nameToID('A/R'); } function cashAccountID() { return $this->nameToID('Cash'); } diff --git a/site/models/monetary_source.php b/site/models/monetary_source.php index dc30bec..368c8c7 100644 --- a/site/models/monetary_source.php +++ b/site/models/monetary_source.php @@ -36,18 +36,36 @@ class MonetarySource extends AppModel { * | | | | | 50| |50 t4a * | | 50| | | |50 | t4b * |35 | 35| | | | | t4b + + * - NOTE + * The above example is great, except it leave no way to resolve + * that the rent has not actually been collected. So, instead + * perhaps we need to run a negative credit to A/R, which we can + * use to reconcile against the Rent<->A/R double entry: + * + * | | | | | 50| |50 t4a + * | | |-50 | | -50| | t4b + * |35 | 35| | | | | t4b + + * OR perhaps even a negative entry all the way through to the + * bank, making the NSF appear not as a withdrawal, but as a + * negative deposit (i.e, and adjustment, just like it really is): + * + * | | | | | |-50 -50| t4a + * | | |-50 | | -50| | t4b + * |35 | 35| | | | | t4b * */ - function nsf($id) { + function nsf($id, $stamp = null) { pr(array('MonetarySource::nsf', compact('id'))); $A = new Account(); // Get the LedgerEntries that use this monetary source - $entries = $this->find - ('all', + $source = $this->find + ('first', array('contain' => array(/* t2b */ 'LedgerEntry' => @@ -71,7 +89,7 @@ class MonetarySource extends AppModel { /* e.g. RECEIPT */ 'CreditLedger' => - array('fields' => array(), + array('fields' => array('id'), 'Account' => array('fields' => array('id', 'name'), 'conditions' => @@ -83,7 +101,7 @@ class MonetarySource extends AppModel { 'CreditReconciliationLedgerEntry' => array(/* e.g. BANK */ 'DebitLedger' => - array('fields' => array(), + array('fields' => array('id'), 'Account' => array('fields' => array('id', 'name'), 'conditions' => @@ -99,78 +117,104 @@ class MonetarySource extends AppModel { 'conditions' => array(array('MonetarySource.id' => $id), ), )); - pr($entries); - die(); + pr($source); - if (!isset($amount)) - $amount = $entry['LedgerEntry']['amount']; + $nsf_account_id = $A->nsfAccountID(); + $nsf_fee_account_id = $A->nsfChargeAccountID(); + $ar_account_id = $A->accountReceivableAccountID(); - $ids = $this->Ledger->Account->postLedgerEntry - (array('transaction_id' => $transaction_id), + $total = 0; + $nsf_rec_ids = array(); + + $transaction_id = null; + foreach ($source['LedgerEntry'] AS $entry) { + if (count($entry['CreditReconciliationLedgerEntry']) < 1) + continue; + if (count($entry['CreditReconciliationLedgerEntry']) > 1) + die('Too many CRLEs'); + + $amount = $entry['amount']; + + $bank_account_id = $entry['CreditReconciliationLedgerEntry'][0]['DebitLedger']['account_id']; + + pr(array('checkpoint' => 'outerloop', + compact('id', $amount, 'bank_account_id', $entry))); + + $ids = $A->postLedgerEntry + (array('transaction_id' => $transaction_id), + null, + array('debit_ledger_id' => $A->currentLedgerID($nsf_account_id), + 'credit_ledger_id' => $A->currentLedgerID($bank_account_id), + 'effective_date' => $stamp, + 'amount' => $amount, + 'lease_id' => $entry['lease_id'], + 'customer_id' => $entry['customer_id'], + 'comment' => "NSF of Monetary Source #{$id}", + ), + array('credit' => array + (array('LedgerEntry' => array + ('id' => $entry['CreditReconciliationLedgerEntry'][0]['id'], + 'amount' => $amount, + ))), + )); + + if ($ids['error']) + return null; + + pr(array('checkpoint' => 'insert 1', + compact('ids'))); + + $total += $amount; + $nsf_rec_ids[] + = array('LedgerEntry' => array('id' => $ids['id'], 'amount' => $amount)); + } + + // Cheat for now + $lease_id = $source['LedgerEntry'][0]['lease_id']; + $customer_id = $source['LedgerEntry'][0]['customer_id']; + + $ids = $A->postLedgerEntry + (null, null, - array('debit_ledger_id' => $A->currentLedgerID($entry['CreditLedger']['account_id']), - 'credit_ledger_id' => $A->currentLedgerID($entry['DebitLedger']['account_id']), - 'effective_date' => $entry['LedgerEntry']['effective_date'], - //'effective_date' => $entry['LedgerEntry']['effective_date'], - 'amount' => $amount, - 'lease_id' => $entry['Lease']['id'], - 'customer_id' => $entry['Customer']['id'], - 'comment' => "Reversal of Ledger Entry #{$id}", + array('debit_ledger_id' => $A->currentLedgerID($ar_account_id), + 'credit_ledger_id' => $A->currentLedgerID($nsf_account_id), + 'effective_date' => $stamp, + 'amount' => $total, + 'lease_id' => $lease_id, + 'customer_id' => $customer_id, + 'comment' => "NSF back to A/R from Monetary Source #{$id}", ), - array('debit' => array(array('LedgerEntry' => array('id' => $entry['LedgerEntry']['id'], - 'amount' => $amount, - ))), - 'credit' => array(array('LedgerEntry' => array('id' => $entry['LedgerEntry']['id'], - 'amount' => $amount, - ))), - )); + array('credit' => $nsf_rec_ids) + ); if ($ids['error']) return null; + pr(array('checkpoint' => 'insert 2', + compact('ids'))); + $tid = $ids['transaction_id']; -/* pr(compact('entry')); */ - - foreach (array('Debit', 'Credit') AS $dc_type) { - foreach ($entry[$dc_type . 'ReconciliationLedgerEntry'] AS $RLE) { -/* pr(array('checkpoint' => "Reverse $dc_type LE", */ -/* compact('id', 'RLE'))); */ - if ($RLE['id'] == $rec_id) - continue; - - if (!$this->reverse($RLE['id'], $RLE['Reconciliation']['amount'], $tid, $id)) - $ids['error'] = true; - -/* $rids = $this->Ledger->Account->postLedgerEntry */ -/* (array('transaction_id' => $tid), */ -/* null, */ -/* array('debit_ledger_id' => $A->currentLedgerID($RLE['CreditLedger']['account_id']), */ -/* 'credit_ledger_id' => $A->currentLedgerID($RLE['DebitLedger']['account_id']), */ -/* 'effective_date' => $RLE['effective_date'], */ -/* //'effective_date' => $RLE['effective_date'], */ -/* 'amount' => $RLE['Reconciliation']['amount'], */ -/* 'lease_id' => $entry['Lease']['id'], */ -/* 'customer_id' => $entry['Customer']['id'], */ -/* 'comment' => "Reversal of Ledger Entry #{$RLE['id']}", */ -/* ), */ -/* array('debit' => array(array('LedgerEntry' => array('id' => $RLE['id'], */ -/* 'amount' => $RLE['Reconciliation']['amount'], */ -/* ))), */ -/* 'credit' => array(array('LedgerEntry' => array('id' => $RLE['id'], */ -/* 'amount' => $RLE['Reconciliation']['amount'], */ -/* ))), */ -/* )); */ - -/* if ($rids['error']) */ -/* $ids['error'] = true; */ - } - } + $ids = $A->postLedgerEntry + (array('transaction_id' => $tid), + null, + array('debit_ledger_id' => $A->currentLedgerID($ar_account_id), + 'credit_ledger_id' => $A->currentLedgerID($nsf_fee_account_id), + 'effective_date' => $stamp, + 'amount' => 35, + 'lease_id' => $lease_id, + 'customer_id' => $customer_id, + 'comment' => "NSF Fee for Monetary Source #{$id}", + ) + ); if ($ids['error']) return null; - return $ids['id']; + pr(array('checkpoint' => 'insert 3', + compact('ids'))); + + return true; } From 1d8ef76efa682fb0131ffd9ecaf9b28a6f05aeec Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 14 Jul 2009 21:44:19 +0000 Subject: [PATCH 324/717] Just updated the comments, and added e2a and e1 into the query. No functional change yet. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@330 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/monetary_source.php | 86 +++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 25 deletions(-) diff --git a/site/models/monetary_source.php b/site/models/monetary_source.php index 368c8c7..f6d5873 100644 --- a/site/models/monetary_source.php +++ b/site/models/monetary_source.php @@ -26,16 +26,16 @@ class MonetarySource extends AppModel { * * FEE RENT A/R RECEIPT CHECK NSF BANK * ------- ------- ------- ------- ------- ------- ------- - * | |50 50| | | | | t1 + * | |50 50| | | | | e1 * | | | | | | | - * | | |50 50| | | | t2a - * | | | |50 50| | | t2b + * | | |50 50| | | | e2a + * | | | |50 50| | | e2b * | | | | | | | - * | | | | |50 | 50| t3 + * | | | | |50 | 50| e3 * | | | | | | | - * | | | | | 50| |50 t4a - * | | 50| | | |50 | t4b - * |35 | 35| | | | | t4b + * | | | | | 50| |50 e4 + * | | 50| | | |50 | e5a + * |35 | 35| | | | | e5b * - NOTE * The above example is great, except it leave no way to resolve @@ -43,17 +43,17 @@ class MonetarySource extends AppModel { * perhaps we need to run a negative credit to A/R, which we can * use to reconcile against the Rent<->A/R double entry: * - * | | | | | 50| |50 t4a - * | | |-50 | | -50| | t4b - * |35 | 35| | | | | t4b + * | | | | | 50| |50 e4 + * | | |-50 | | -50| | e5a + * |35 | 35| | | | | e5b * OR perhaps even a negative entry all the way through to the * bank, making the NSF appear not as a withdrawal, but as a * negative deposit (i.e, and adjustment, just like it really is): * - * | | | | | |-50 -50| t4a - * | | |-50 | | -50| | t4b - * |35 | 35| | | | | t4b + * | | | | | |-50 -50| e4 + * | | |-50 | | -50| | e5a + * |35 | 35| | | | | e5b * */ @@ -67,17 +67,18 @@ class MonetarySource extends AppModel { $source = $this->find ('first', array('contain' => - array(/* t2b */ + array(/* e2b */ 'LedgerEntry' => array('Transaction.id', 'MonetarySource.id', 'Customer.id', 'Lease.id', - - /* e.g. CHECK */ - 'DebitLedger' => + + /* e2b debit */ + 'DebitLedger' => /* e.g. CHECK Ledger */ array('fields' => array(), - 'Account' => + + 'Account' => /* e.g. CHECK Account */ array('fields' => array('id', 'name'), 'conditions' => /* array(array('Account.payable' => 1), */ @@ -87,22 +88,50 @@ class MonetarySource extends AppModel { ), ), - /* e.g. RECEIPT */ - 'CreditLedger' => + /* e2b credit */ + 'CreditLedger' => /* i.e. RECEIPT Ledger */ array('fields' => array('id'), - 'Account' => + 'Account' => /* i.e. RECEIPT Account */ array('fields' => array('id', 'name'), 'conditions' => array('Account.id' => $A->receiptAccountID()), ), ), - /* t3 */ + /* e2a */ + 'DebitReconciliationLedgerEntry' => + array(/* e2a credit */ + 'CreditLedger' => /* i.e. A/R Ledger */ + array('fields' => array(), + + 'Account' => /* i.e. A/R Account */ + array('fields' => array(), + 'conditions' => + array('Account.id' => $A->accountReceivableAccountID()), + ), + ), + + /* e1 */ + 'DebitReconciliationLedgerEntry' => + array(/* e1 credit */ + 'CreditLedger' => /* e.g. Rent Ledger */ + array('fields' => array(), + + 'Account' => /* e.g. Rent Account */ + array('fields' => array(), + 'conditions' => + array('Account.id' => $A->accountReceivableAccountID()), + ), + ), + ), + ), + + /* e3 */ 'CreditReconciliationLedgerEntry' => - array(/* e.g. BANK */ - 'DebitLedger' => + array(/* e3 debit */ + 'DebitLedger' => /* e.g. BANK Ledger */ array('fields' => array('id'), - 'Account' => + 'Account' => /* e.g. BANK Account */ array('fields' => array('id', 'name'), 'conditions' => array('Account.depositable' => 1), @@ -127,19 +156,24 @@ class MonetarySource extends AppModel { $nsf_rec_ids = array(); $transaction_id = null; + // FOR EACH e2b foreach ($source['LedgerEntry'] AS $entry) { + // Count number of e3 entries if (count($entry['CreditReconciliationLedgerEntry']) < 1) continue; if (count($entry['CreditReconciliationLedgerEntry']) > 1) die('Too many CRLEs'); + // e2b amount $amount = $entry['amount']; + // e3 account $bank_account_id = $entry['CreditReconciliationLedgerEntry'][0]['DebitLedger']['account_id']; pr(array('checkpoint' => 'outerloop', compact('id', $amount, 'bank_account_id', $entry))); + // post new e4 $ids = $A->postLedgerEntry (array('transaction_id' => $transaction_id), null, @@ -173,6 +207,7 @@ class MonetarySource extends AppModel { $lease_id = $source['LedgerEntry'][0]['lease_id']; $customer_id = $source['LedgerEntry'][0]['customer_id']; + // post new e5a $ids = $A->postLedgerEntry (null, null, @@ -195,6 +230,7 @@ class MonetarySource extends AppModel { $tid = $ids['transaction_id']; + // post new e5b $ids = $A->postLedgerEntry (array('transaction_id' => $tid), null, From f5b87fa6b09ff541dc6d6f4ef31e8c784f41ac3a Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 15 Jul 2009 00:21:23 +0000 Subject: [PATCH 325/717] getting closer to a workable NSF solution. I don't like it, but it might allow us to move forward in the short term. This solution required a stupid kludge to get CakePHP to work with the necessary query, which sucks but is not too cumbersome. What isn't working at the moment, is for the NSF to show up on the lease account, which is what I'll try to work out next. Also, the monies deposited are not trackable, since I'm not reconciling them (due to the sign flip). Not sure if there is an easily workable solution. Also, to get the collected rent report to show this negative income, it requires the bank account be part of the query, which I accomplish in the short term by setting the 'payable' flag. I may need to fix/kludge this by running the NSF through the receipt account and adding the NSF account to the list on the collected page. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@331 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/ledger_entry.php | 10 ++ site/models/monetary_source.php | 166 ++++++++++++++++---------------- 2 files changed, 95 insertions(+), 81 deletions(-) diff --git a/site/models/ledger_entry.php b/site/models/ledger_entry.php index f947902..8adb64a 100644 --- a/site/models/ledger_entry.php +++ b/site/models/ledger_entry.php @@ -58,6 +58,16 @@ class LedgerEntry extends AppModel { 'foreignKey' => 'credit_ledger_entry_id', 'associationForeignKey' => 'debit_ledger_entry_id', ), + // STUPID CakePHP bug screws up when using Containable + // and CLASS contains CLASS. This extra HABTM give the + // option of multiple depths on one CLASS, since there + // isn't an alias specification for Containable. + 'DebitReconciliationLedgerEntry2' => array( + 'className' => 'LedgerEntry', + 'joinTable' => 'reconciliations', + 'foreignKey' => 'credit_ledger_entry_id', + 'associationForeignKey' => 'debit_ledger_entry_id', + ), 'CreditReconciliationLedgerEntry' => array( 'className' => 'LedgerEntry', 'joinTable' => 'reconciliations', diff --git a/site/models/monetary_source.php b/site/models/monetary_source.php index f6d5873..7221278 100644 --- a/site/models/monetary_source.php +++ b/site/models/monetary_source.php @@ -22,20 +22,22 @@ class MonetarySource extends AppModel { * function: nsf * - Flags the ledger entry as having insufficient funds * - NOTE: nsf only works if given the monetary source id - * to transaction t2b, below + * to transaction e3, below * * FEE RENT A/R RECEIPT CHECK NSF BANK * ------- ------- ------- ------- ------- ------- ------- - * | |50 50| | | | | e1 + * | |30 30| | | | | t1 e1a : R e2/e6a : + * | |20 20| | | | | t1 e1b : R e2/e6b : * | | | | | | | - * | | |50 50| | | | e2a - * | | | |50 50| | | e2b + * | | |50 50| | | | t2 e2 : R e3 : R e1a/e1b + * | | | |50 50| | | t2 e3 : R e4 : R e2 * | | | | | | | - * | | | | |50 | 50| e3 + * | | | | |50 | 50| t3 e4 : R e5 : R e3 * | | | | | | | - * | | | | | 50| |50 e4 - * | | 50| | | |50 | e5a - * |35 | 35| | | | | e5b + * | | | | | 50| |50 t4 e5 : R e4 : R e6a/e6b + * | | 30| | | |30 | t5 e6a : : R e5 + * | | 20| | | |20 | t5 e6b : : R e5 + * |35 | 35| | | | | t5 e7 * - NOTE * The above example is great, except it leave no way to resolve @@ -43,17 +45,19 @@ class MonetarySource extends AppModel { * perhaps we need to run a negative credit to A/R, which we can * use to reconcile against the Rent<->A/R double entry: * - * | | | | | 50| |50 e4 - * | | |-50 | | -50| | e5a - * |35 | 35| | | | | e5b + * | | | | | 50| |50 t4 e5 : R e4 : R e6a/e6b (?) + * | | |-30 | | -30| | t5 e6a : R e1a : R e5 (?) + * | | |-20 | | -20| | t5 e6b : R e1b : R e5 (?) + * |35 | 35| | | | | t5 e7 * OR perhaps even a negative entry all the way through to the * bank, making the NSF appear not as a withdrawal, but as a * negative deposit (i.e, and adjustment, just like it really is): * - * | | | | | |-50 -50| e4 - * | | |-50 | | -50| | e5a - * |35 | 35| | | | | e5b + * | | | | | |-50 -50| t4 e5 : R e4 (?) : R e6a/e6b + * | | |-30 | | -30| | t5 e6a : R e1a : R e5 + * | | |-20 | | -20| | t5 e6b : R e1b : R e5 + * |35 | 35| | | | | t5 e7 * */ @@ -67,14 +71,14 @@ class MonetarySource extends AppModel { $source = $this->find ('first', array('contain' => - array(/* e2b */ + array(/* e3 */ 'LedgerEntry' => array('Transaction.id', 'MonetarySource.id', 'Customer.id', 'Lease.id', - /* e2b debit */ + /* e3 debit */ 'DebitLedger' => /* e.g. CHECK Ledger */ array('fields' => array(), @@ -88,7 +92,7 @@ class MonetarySource extends AppModel { ), ), - /* e2b credit */ + /* e3 credit */ 'CreditLedger' => /* i.e. RECEIPT Ledger */ array('fields' => array('id'), 'Account' => /* i.e. RECEIPT Account */ @@ -98,9 +102,9 @@ class MonetarySource extends AppModel { ), ), - /* e2a */ + /* e2 */ 'DebitReconciliationLedgerEntry' => - array(/* e2a credit */ + array(/* e2 credit */ 'CreditLedger' => /* i.e. A/R Ledger */ array('fields' => array(), @@ -112,23 +116,14 @@ class MonetarySource extends AppModel { ), /* e1 */ - 'DebitReconciliationLedgerEntry' => - array(/* e1 credit */ - 'CreditLedger' => /* e.g. Rent Ledger */ - array('fields' => array(), - - 'Account' => /* e.g. Rent Account */ - array('fields' => array(), - 'conditions' => - array('Account.id' => $A->accountReceivableAccountID()), - ), - ), - ), + // STUPID CakePHP bug screws up CLASS contains CLASS. + // Use the same class, but with different name. + 'DebitReconciliationLedgerEntry2', ), - /* e3 */ + /* e4 */ 'CreditReconciliationLedgerEntry' => - array(/* e3 debit */ + array(/* e4 debit */ 'DebitLedger' => /* e.g. BANK Ledger */ array('fields' => array('id'), 'Account' => /* e.g. BANK Account */ @@ -153,86 +148,95 @@ class MonetarySource extends AppModel { $ar_account_id = $A->accountReceivableAccountID(); $total = 0; - $nsf_rec_ids = array(); + $e6_debit_rec_ids = array(); + $e6_credit_rec_ids = array(); - $transaction_id = null; - // FOR EACH e2b - foreach ($source['LedgerEntry'] AS $entry) { - // Count number of e3 entries - if (count($entry['CreditReconciliationLedgerEntry']) < 1) + $e5_transaction_id = null; + foreach ($source['LedgerEntry'] AS $e3) { + // We expect only a single e4 entry + $e4 = $e3['CreditReconciliationLedgerEntry']; + if (count($e4) < 1) continue; - if (count($entry['CreditReconciliationLedgerEntry']) > 1) - die('Too many CRLEs'); + if (count($e4) > 1) + die('Too many e4 entries'); - // e2b amount - $amount = $entry['amount']; + // Pullup e4 from the single member array + $e4 = $e4[0]; - // e3 account - $bank_account_id = $entry['CreditReconciliationLedgerEntry'][0]['DebitLedger']['account_id']; + // e3 amount + $amount = $e3['amount']; + $amount *= -1; - pr(array('checkpoint' => 'outerloop', - compact('id', $amount, 'bank_account_id', $entry))); + // e4 account + $bank_account_id = $e4['DebitLedger']['account_id']; - // post new e4 - $ids = $A->postLedgerEntry - (array('transaction_id' => $transaction_id), + // post new e5 + $e5_ids = $A->postLedgerEntry + (array('transaction_id' => $e5_transaction_id), null, - array('debit_ledger_id' => $A->currentLedgerID($nsf_account_id), - 'credit_ledger_id' => $A->currentLedgerID($bank_account_id), + array('debit_ledger_id' => $A->currentLedgerID($bank_account_id), + 'credit_ledger_id' => $A->currentLedgerID($nsf_account_id), 'effective_date' => $stamp, 'amount' => $amount, - 'lease_id' => $entry['lease_id'], - 'customer_id' => $entry['customer_id'], + 'lease_id' => $e3['lease_id'], + 'customer_id' => $e3['customer_id'], 'comment' => "NSF of Monetary Source #{$id}", - ), - array('credit' => array - (array('LedgerEntry' => array - ('id' => $entry['CreditReconciliationLedgerEntry'][0]['id'], - 'amount' => $amount, - ))), +/* ), */ +/* array('credit' => array */ +/* (array('LedgerEntry' => array */ +/* ('id' => $e4['id'], */ +/* 'amount' => $amount, */ +/* ))), */ )); - if ($ids['error']) + if ($e5_ids['error']) return null; - pr(array('checkpoint' => 'insert 1', - compact('ids'))); + pr(array('checkpoint' => 'Posted Ledger Entry e5', + compact('e5_ids'))); + + $e6_debit_rec_ids[] + = array('LedgerEntry' => array('id' => $e5_ids['id'], 'amount' => $amount)); + + foreach ($e3['DebitReconciliationLedgerEntry'] AS $e2) { + foreach ($e2['DebitReconciliationLedgerEntry2'] AS $e1) { + $e6_credit_rec_ids[] + = array('LedgerEntry' => array('id' => $e1['id'], 'amount' => -1*$e1['Reconciliation']['amount'])); + } + } $total += $amount; - $nsf_rec_ids[] - = array('LedgerEntry' => array('id' => $ids['id'], 'amount' => $amount)); } // Cheat for now $lease_id = $source['LedgerEntry'][0]['lease_id']; $customer_id = $source['LedgerEntry'][0]['customer_id']; - // post new e5a - $ids = $A->postLedgerEntry + // post new e6 + $e6_ids = $A->postLedgerEntry (null, null, - array('debit_ledger_id' => $A->currentLedgerID($ar_account_id), - 'credit_ledger_id' => $A->currentLedgerID($nsf_account_id), + array('debit_ledger_id' => $A->currentLedgerID($nsf_account_id), + 'credit_ledger_id' => $A->currentLedgerID($ar_account_id), 'effective_date' => $stamp, 'amount' => $total, 'lease_id' => $lease_id, 'customer_id' => $customer_id, 'comment' => "NSF back to A/R from Monetary Source #{$id}", ), - array('credit' => $nsf_rec_ids) + array('debit' => $e6_debit_rec_ids, + 'credit' => $e6_credit_rec_ids) ); - if ($ids['error']) + if ($e6_ids['error']) return null; - pr(array('checkpoint' => 'insert 2', - compact('ids'))); + pr(array('checkpoint' => 'Posted Ledger Entry e6', + compact('e6_ids', 'e6_debit_rec_ids', 'e6_credit_rec_ids'))); - $tid = $ids['transaction_id']; - - // post new e5b - $ids = $A->postLedgerEntry - (array('transaction_id' => $tid), + // post new e7 + $e7_ids = $A->postLedgerEntry + (array('transaction_id' => $e6_ids['transaction_id']), null, array('debit_ledger_id' => $A->currentLedgerID($ar_account_id), 'credit_ledger_id' => $A->currentLedgerID($nsf_fee_account_id), @@ -244,11 +248,11 @@ class MonetarySource extends AppModel { ) ); - if ($ids['error']) + if ($e7_ids['error']) return null; - pr(array('checkpoint' => 'insert 3', - compact('ids'))); + pr(array('checkpoint' => 'Posted Ledger Entry e7', + compact('e7_ids'))); return true; } From 6210838b228dc3bbc612569bc537ffa830f98deb Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 15 Jul 2009 01:05:44 +0000 Subject: [PATCH 326/717] Multiple e6 entries now ensure that NSF reconciles appropriately to e1 such that the lease is correctly taken into account. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@332 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/monetary_source.php | 115 +++++++++++++------------------- 1 file changed, 47 insertions(+), 68 deletions(-) diff --git a/site/models/monetary_source.php b/site/models/monetary_source.php index 7221278..184dad2 100644 --- a/site/models/monetary_source.php +++ b/site/models/monetary_source.php @@ -23,6 +23,10 @@ class MonetarySource extends AppModel { * - Flags the ledger entry as having insufficient funds * - NOTE: nsf only works if given the monetary source id * to transaction e3, below + * - NOTE: In order to show that the rent formerly considered + * "collected" is now recognized in reverse, we must + * credit A/R with a negative amount in order to + * reconcile it against the Rent<->A/R ledger entry. * * FEE RENT A/R RECEIPT CHECK NSF BANK * ------- ------- ------- ------- ------- ------- ------- @@ -34,26 +38,6 @@ class MonetarySource extends AppModel { * | | | | | | | * | | | | |50 | 50| t3 e4 : R e5 : R e3 * | | | | | | | - * | | | | | 50| |50 t4 e5 : R e4 : R e6a/e6b - * | | 30| | | |30 | t5 e6a : : R e5 - * | | 20| | | |20 | t5 e6b : : R e5 - * |35 | 35| | | | | t5 e7 - - * - NOTE - * The above example is great, except it leave no way to resolve - * that the rent has not actually been collected. So, instead - * perhaps we need to run a negative credit to A/R, which we can - * use to reconcile against the Rent<->A/R double entry: - * - * | | | | | 50| |50 t4 e5 : R e4 : R e6a/e6b (?) - * | | |-30 | | -30| | t5 e6a : R e1a : R e5 (?) - * | | |-20 | | -20| | t5 e6b : R e1b : R e5 (?) - * |35 | 35| | | | | t5 e7 - - * OR perhaps even a negative entry all the way through to the - * bank, making the NSF appear not as a withdrawal, but as a - * negative deposit (i.e, and adjustment, just like it really is): - * * | | | | | |-50 -50| t4 e5 : R e4 (?) : R e6a/e6b * | | |-30 | | -30| | t5 e6a : R e1a : R e5 * | | |-20 | | -20| | t5 e6b : R e1b : R e5 @@ -85,8 +69,6 @@ class MonetarySource extends AppModel { 'Account' => /* e.g. CHECK Account */ array('fields' => array('id', 'name'), 'conditions' => -/* array(array('Account.payable' => 1), */ -/* array('Account.type' => 'ASSET')), */ array('Account.payable' => 1, 'Account.type' => 'ASSET'), ), @@ -136,10 +118,7 @@ class MonetarySource extends AppModel { ), ), -/* 'fields' => array('LedgerEntry.*'), */ - - 'conditions' => array(array('MonetarySource.id' => $id), - ), + 'conditions' => array(array('MonetarySource.id' => $id)), )); pr($source); @@ -147,11 +126,7 @@ class MonetarySource extends AppModel { $nsf_fee_account_id = $A->nsfChargeAccountID(); $ar_account_id = $A->accountReceivableAccountID(); - $total = 0; - $e6_debit_rec_ids = array(); - $e6_credit_rec_ids = array(); - - $e5_transaction_id = null; + $t4_id = null; foreach ($source['LedgerEntry'] AS $e3) { // We expect only a single e4 entry $e4 = $e3['CreditReconciliationLedgerEntry']; @@ -164,16 +139,15 @@ class MonetarySource extends AppModel { $e4 = $e4[0]; // e3 amount - $amount = $e3['amount']; - $amount *= -1; + $amount = -1 * $e3['amount']; // e4 account $bank_account_id = $e4['DebitLedger']['account_id']; // post new e5 $e5_ids = $A->postLedgerEntry - (array('transaction_id' => $e5_transaction_id), - null, + (array('transaction_id' => $t4_id), + array('monetary_source_id' => $e3['monetary_source_id']), array('debit_ledger_id' => $A->currentLedgerID($bank_account_id), 'credit_ledger_id' => $A->currentLedgerID($nsf_account_id), 'effective_date' => $stamp, @@ -191,52 +165,57 @@ class MonetarySource extends AppModel { if ($e5_ids['error']) return null; - + $t4_id = $e5_ids['transaction_id']; + pr(array('checkpoint' => 'Posted Ledger Entry e5', - compact('e5_ids'))); - - $e6_debit_rec_ids[] - = array('LedgerEntry' => array('id' => $e5_ids['id'], 'amount' => $amount)); + compact('e5_ids', 'amount'))); + $t5_id = null; foreach ($e3['DebitReconciliationLedgerEntry'] AS $e2) { foreach ($e2['DebitReconciliationLedgerEntry2'] AS $e1) { - $e6_credit_rec_ids[] - = array('LedgerEntry' => array('id' => $e1['id'], 'amount' => -1*$e1['Reconciliation']['amount'])); + $amount = -1*$e1['Reconciliation']['amount']; + + // post new e6 + $e6_ids = $A->postLedgerEntry + (array('transaction_id' => $t5_id), + null, + array('debit_ledger_id' => $A->currentLedgerID($nsf_account_id), + 'credit_ledger_id' => $A->currentLedgerID($ar_account_id), + 'effective_date' => $stamp, + 'amount' => $amount, + 'lease_id' => $e1['lease_id'], + 'customer_id' => $e1['customer_id'], + 'comment' => "NSF back to A/R from Monetary Source #{$id}", + ), + array('debit' => + array(array('LedgerEntry' => + array('id' => $e5_ids['id'], + 'amount' => $amount))), + + 'credit' => + array(array('LedgerEntry' => + array('id' => $e1['id'], + 'amount' => $amount))), + ) + ); + + if ($e6_ids['error']) + return null; + $t5_id = $e6_ids['transaction_id']; + + pr(array('checkpoint' => 'Posted Ledger Entry e6', + compact('e6_ids', 'amount'))); } } - - $total += $amount; } // Cheat for now - $lease_id = $source['LedgerEntry'][0]['lease_id']; $customer_id = $source['LedgerEntry'][0]['customer_id']; - - // post new e6 - $e6_ids = $A->postLedgerEntry - (null, - null, - array('debit_ledger_id' => $A->currentLedgerID($nsf_account_id), - 'credit_ledger_id' => $A->currentLedgerID($ar_account_id), - 'effective_date' => $stamp, - 'amount' => $total, - 'lease_id' => $lease_id, - 'customer_id' => $customer_id, - 'comment' => "NSF back to A/R from Monetary Source #{$id}", - ), - array('debit' => $e6_debit_rec_ids, - 'credit' => $e6_credit_rec_ids) - ); - - if ($e6_ids['error']) - return null; - - pr(array('checkpoint' => 'Posted Ledger Entry e6', - compact('e6_ids', 'e6_debit_rec_ids', 'e6_credit_rec_ids'))); + $lease_id = null; // post new e7 $e7_ids = $A->postLedgerEntry - (array('transaction_id' => $e6_ids['transaction_id']), + (array('transaction_id' => $t5_id), null, array('debit_ledger_id' => $A->currentLedgerID($ar_account_id), 'credit_ledger_id' => $A->currentLedgerID($nsf_fee_account_id), From d1075a2ea2c2a7b717aaec49238fdc617c9c4866 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 15 Jul 2009 01:33:06 +0000 Subject: [PATCH 327/717] A final attempt to reconcile the cash in the bank account. It just wasn't designed this way, so I'll strip it out on the next checkin. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@333 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/monetary_source.php | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/site/models/monetary_source.php b/site/models/monetary_source.php index 184dad2..7c6c814 100644 --- a/site/models/monetary_source.php +++ b/site/models/monetary_source.php @@ -155,12 +155,12 @@ class MonetarySource extends AppModel { 'lease_id' => $e3['lease_id'], 'customer_id' => $e3['customer_id'], 'comment' => "NSF of Monetary Source #{$id}", -/* ), */ -/* array('credit' => array */ -/* (array('LedgerEntry' => array */ -/* ('id' => $e4['id'], */ -/* 'amount' => $amount, */ -/* ))), */ + ), + array('debit' => array + (array('LedgerEntry' => array + ('id' => $e4['id'], + 'amount' => $amount, + ))), )); if ($e5_ids['error']) @@ -187,15 +187,15 @@ class MonetarySource extends AppModel { 'customer_id' => $e1['customer_id'], 'comment' => "NSF back to A/R from Monetary Source #{$id}", ), - array('debit' => - array(array('LedgerEntry' => - array('id' => $e5_ids['id'], - 'amount' => $amount))), + array('debit' => array + (array('LedgerEntry' => + array('id' => $e5_ids['id'], + 'amount' => $amount))), - 'credit' => - array(array('LedgerEntry' => - array('id' => $e1['id'], - 'amount' => $amount))), + 'credit' => array + (array('LedgerEntry' => + array('id' => $e1['id'], + 'amount' => $amount))), ) ); From 50c4ee225f9b58d2cc25faba70c1807febdd21a7 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 15 Jul 2009 03:06:59 +0000 Subject: [PATCH 328/717] Finally, a working NSF implementation. Ledger Entry tracking stops at the Bank account, since we switch from positive to negative ledger entries. However, we're not going to reconcile debits to credits in the bank account anyway, so I just disabled tracking on the account. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@334 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 11 ++- site/controllers/accounts_controller.php | 2 + .../controllers/ledger_entries_controller.php | 7 +- site/models/monetary_source.php | 99 ++++++++++++------- site/views/accounts/collected.ctp | 5 + site/views/elements/ledger_entries.ctp | 8 +- 6 files changed, 85 insertions(+), 47 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index e11693b..a895ec1 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -883,10 +883,11 @@ INSERT INTO `pmgr_accounts` (`type`, `name`, `tillable`, `payable`, `refundable` ('ASSET', 'Money Order', 1, 1, 0), ('ASSET', 'ACH', 0, 1, 0), ('EXPENSE', 'Concession', 0, 1, 0); -INSERT INTO `pmgr_accounts` (`type`, `name`, `tillable`, `payable`, `refundable`, `depositable`) +INSERT INTO `pmgr_accounts` (`type`, `name`, `refundable`, `depositable`) VALUES --- REVISIT : 20090710 : We probably don't really want petty cash depositable - ('ASSET', 'Petty Cash', 0, 0, 1, 1); +-- REVISIT : 20090710 : We probably don't really want petty cash depositable. +-- This is just for testing our deposit code + ('ASSET', 'Petty Cash', 1, 1); INSERT INTO `pmgr_accounts` (`type`, `name`, `chargeable`, `trackable`) VALUES ('LIABILITY', 'Tax', 1, 1), @@ -895,9 +896,9 @@ INSERT INTO `pmgr_accounts` (`type`, `name`, `chargeable`, `trackable`) ('INCOME', 'Late Charge', 1, 0), ('INCOME', 'NSF Charge', 1, 0), ('INCOME', 'Damage', 1, 0); -INSERT INTO `pmgr_accounts` (`type`, `name`, `depositable`) +INSERT INTO `pmgr_accounts` (`type`, `name`, `depositable`, `trackable`) VALUES - ('ASSET', 'Bank', 1); + ('ASSET', 'Bank', 1, 0); INSERT INTO `pmgr_accounts` (`type`, `name`, `trackable`) VALUES ('EXPENSE', 'Bad Debt', 0), diff --git a/site/controllers/accounts_controller.php b/site/controllers/accounts_controller.php index 52e3a88..450631e 100644 --- a/site/controllers/accounts_controller.php +++ b/site/controllers/accounts_controller.php @@ -153,6 +153,8 @@ class AccountsController extends AppController { } $payment_accounts = $this->Account->paymentAccounts(); + $payment_accounts[$this->Account->nsfAccountID()] = + $this->Account->name($this->Account->nsfAccountID()); $default_accounts = array_diff_key($payment_accounts, array($this->Account->concessionAccountID() => 1)); $this->set(compact('payment_accounts', 'default_accounts')); diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index d5165bc..3879f8f 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -184,6 +184,9 @@ class LedgerEntriesController extends AppController { if (count(array_intersect($params['fields'], array('applied'))) == 1) $fields[] = 'SUM(Reconciliation.amount) AS applied'; + if ($params['action'] === 'collected') + $fields[] = 'MAX(ReceiptTransaction.stamp) AS last_paid'; + return $fields; } @@ -205,12 +208,12 @@ class LedgerEntriesController extends AppController { else die("INTERNAL ERROR: COLLECTED ACCOUNT ID NOT SET"); - if (isset($collected_from_date)) + if (!empty($collected_from_date)) $conditions[] = array('ReceiptTransaction.stamp >=' => $this->LedgerEntry->Transaction->dateFormatBeforeSave($collected_from_date)); - if (isset($collected_through_date)) + if (!empty($collected_through_date)) $conditions[] = array('ReceiptTransaction.stamp <=' => $this->LedgerEntry->Transaction->dateFormatBeforeSave($collected_through_date . ' 23:59:59')); diff --git a/site/models/monetary_source.php b/site/models/monetary_source.php index 7c6c814..0fe33a2 100644 --- a/site/models/monetary_source.php +++ b/site/models/monetary_source.php @@ -30,18 +30,20 @@ class MonetarySource extends AppModel { * * FEE RENT A/R RECEIPT CHECK NSF BANK * ------- ------- ------- ------- ------- ------- ------- - * | |30 30| | | | | t1 e1a : R e2/e6a : - * | |20 20| | | | | t1 e1b : R e2/e6b : + * | |30 30| | | | | t1 e1a : R e2/e7a : + * | |20 20| | | | | t1 e1b : R e2/e7b : * | | | | | | | - * | | |50 50| | | | t2 e2 : R e3 : R e1a/e1b + * | | |30 30| | | | t2 e2a : R e3 : R e1a + * | | |20 20| | | | t2 e2b : R e3 : R e1b * | | | |50 50| | | t2 e3 : R e4 : R e2 * | | | | | | | - * | | | | |50 | 50| t3 e4 : R e5 : R e3 + * | | | | |50 | 50| t3 e4 : : R e3 * | | | | | | | - * | | | | | |-50 -50| t4 e5 : R e4 (?) : R e6a/e6b - * | | |-30 | | -30| | t5 e6a : R e1a : R e5 - * | | |-20 | | -20| | t5 e6b : R e1b : R e5 - * |35 | 35| | | | | t5 e7 + * | | | | | |-50 -50| t4 e5 : : R e6 + * | | | |-50 | -50| | t5 e6 : R e5 : R e7a/e7b + * | | |-30 -30| | | | t6 e7a : R e6 : R e1a + * | | |-20 -20| | | | t6 e7b : R e6 : R e1b + * |35 | 35| | | | | t6 e8 * */ @@ -125,8 +127,10 @@ class MonetarySource extends AppModel { $nsf_account_id = $A->nsfAccountID(); $nsf_fee_account_id = $A->nsfChargeAccountID(); $ar_account_id = $A->accountReceivableAccountID(); + $receipt_account_id = $A->receiptAccountID(); $t4_id = null; + $t5_id = null; foreach ($source['LedgerEntry'] AS $e3) { // We expect only a single e4 entry $e4 = $e3['CreditReconciliationLedgerEntry']; @@ -139,7 +143,7 @@ class MonetarySource extends AppModel { $e4 = $e4[0]; // e3 amount - $amount = -1 * $e3['amount']; + $amount = -$e3['amount']; // e4 account $bank_account_id = $e4['DebitLedger']['account_id']; @@ -147,21 +151,16 @@ class MonetarySource extends AppModel { // post new e5 $e5_ids = $A->postLedgerEntry (array('transaction_id' => $t4_id), - array('monetary_source_id' => $e3['monetary_source_id']), + null, array('debit_ledger_id' => $A->currentLedgerID($bank_account_id), 'credit_ledger_id' => $A->currentLedgerID($nsf_account_id), 'effective_date' => $stamp, 'amount' => $amount, 'lease_id' => $e3['lease_id'], 'customer_id' => $e3['customer_id'], - 'comment' => "NSF of Monetary Source #{$id}", - ), - array('debit' => array - (array('LedgerEntry' => array - ('id' => $e4['id'], - 'amount' => $amount, - ))), - )); + 'comment' => "NSF Bank Reversal; Monetary Source #{$id}", + ) + ); if ($e5_ids['error']) return null; @@ -170,26 +169,54 @@ class MonetarySource extends AppModel { pr(array('checkpoint' => 'Posted Ledger Entry e5', compact('e5_ids', 'amount'))); - $t5_id = null; + // post new e6... this will be our crossover point + // from typical positive entries to negative entries. + // Therefore, no reconciliation on this account. + $e6_ids = $A->postLedgerEntry + (array('transaction_id' => $t5_id), + array('monetary_source_id' => $e3['monetary_source_id']), + array('debit_ledger_id' => $A->currentLedgerID($nsf_account_id), + 'credit_ledger_id' => $A->currentLedgerID($receipt_account_id), + 'effective_date' => $stamp, + 'amount' => $amount, + 'lease_id' => $e3['lease_id'], + 'customer_id' => $e3['customer_id'], + 'comment' => "NSF tracker; Monetary Source #{$id}", + ), + array('debit' => array + (array('LedgerEntry' => + array('id' => $e5_ids['id'], + 'amount' => $amount))), + ) + ); + + if ($e6_ids['error']) + return null; + $t5_id = $e6_ids['transaction_id']; + + pr(array('checkpoint' => 'Posted Ledger Entry e6', + compact('e6_ids', 'amount'))); + + $t6_id = null; foreach ($e3['DebitReconciliationLedgerEntry'] AS $e2) { foreach ($e2['DebitReconciliationLedgerEntry2'] AS $e1) { $amount = -1*$e1['Reconciliation']['amount']; - // post new e6 - $e6_ids = $A->postLedgerEntry - (array('transaction_id' => $t5_id), + // post new e7 + $e7_ids = $A->postLedgerEntry + (array('transaction_id' => $t6_id), null, - array('debit_ledger_id' => $A->currentLedgerID($nsf_account_id), + array('debit_ledger_id' => $A->currentLedgerID($receipt_account_id), 'credit_ledger_id' => $A->currentLedgerID($ar_account_id), 'effective_date' => $stamp, 'amount' => $amount, 'lease_id' => $e1['lease_id'], 'customer_id' => $e1['customer_id'], - 'comment' => "NSF back to A/R from Monetary Source #{$id}", + 'comment' => "NSF Receipt; Monetary Source #{$id}", ), array('debit' => array (array('LedgerEntry' => - array('id' => $e5_ids['id'], + array('id' => $e6_ids['id'], 'amount' => $amount))), 'credit' => array @@ -199,12 +226,12 @@ class MonetarySource extends AppModel { ) ); - if ($e6_ids['error']) + if ($e7_ids['error']) return null; - $t5_id = $e6_ids['transaction_id']; + $t6_id = $e7_ids['transaction_id']; - pr(array('checkpoint' => 'Posted Ledger Entry e6', - compact('e6_ids', 'amount'))); + pr(array('checkpoint' => 'Posted Ledger Entry e7', + compact('e7_ids', 'amount'))); } } } @@ -213,9 +240,9 @@ class MonetarySource extends AppModel { $customer_id = $source['LedgerEntry'][0]['customer_id']; $lease_id = null; - // post new e7 - $e7_ids = $A->postLedgerEntry - (array('transaction_id' => $t5_id), + // post new e8 + $e8_ids = $A->postLedgerEntry + (array('transaction_id' => $t6_id), null, array('debit_ledger_id' => $A->currentLedgerID($ar_account_id), 'credit_ledger_id' => $A->currentLedgerID($nsf_fee_account_id), @@ -223,15 +250,15 @@ class MonetarySource extends AppModel { 'amount' => 35, 'lease_id' => $lease_id, 'customer_id' => $customer_id, - 'comment' => "NSF Fee for Monetary Source #{$id}", + 'comment' => "NSF Fee; Monetary Source #{$id}", ) ); - if ($e7_ids['error']) + if ($e8_ids['error']) return null; - pr(array('checkpoint' => 'Posted Ledger Entry e7', - compact('e7_ids'))); + pr(array('checkpoint' => 'Posted Ledger Entry e8', + compact('e8_ids'))); return true; } diff --git a/site/views/accounts/collected.ctp b/site/views/accounts/collected.ctp index 92b50e9..6e43190 100644 --- a/site/views/accounts/collected.ctp +++ b/site/views/accounts/collected.ctp @@ -26,6 +26,11 @@ function resetForm() { /* datepickerBOM(null, 'TxFromDate'); */ /* datepickerNow('TxThroughDate', false); */ + // REVISIT : 20090714 + // Figure out how to just prevent jqGrid + // from loading in the first place + +/* $('#collected-entries-jqGrid').clearGridData(); */ /* updateEntriesGrid(); */ } diff --git a/site/views/elements/ledger_entries.ctp b/site/views/elements/ledger_entries.ctp index 293f266..890079e 100644 --- a/site/views/elements/ledger_entries.ctp +++ b/site/views/elements/ledger_entries.ctp @@ -24,7 +24,7 @@ $cols['Amount'] = array('index' => 'LedgerEntry.amount', 'formatter' => $cols['Debit'] = array('index' => 'debit', 'formatter' => 'currency'); $cols['Credit'] = array('index' => 'credit', 'formatter' => 'currency'); -$cols['Paid'] = array('index' => 'ReceiptTransaction.stamp', 'formatter' => 'date'); +$cols['Last Payment'] = array('index' => 'last_paid', 'formatter' => 'date'); $cols['Applied'] = array('index' => "applied", 'formatter' => 'currency'); $cols['Sub-Total'] = array('index' => 'subtotal-LedgerEntry.amount', 'formatter' => 'currency', 'sortable' => false); @@ -55,7 +55,7 @@ if ($group_by_tx) $grid->invalidFields(array('Effective', 'Through')); if (!isset($collected_account_id)) - $grid->invalidFields('Paid'); + $grid->invalidFields('Last Payment'); if (isset($account_ftype) || isset($ledger_id) || isset($account_id) || isset($ar_account)) $grid->invalidFields(array('Debit Account', 'Credit Account')); @@ -109,7 +109,7 @@ if (isset($reconcile_id)) { if (isset($collected_account_id)) { $config['action'] = 'collected'; $grid->customData(compact('collected_account_id'))->limit(500); - $grid->sortField('Paid'); + $grid->sortField('Last Payment'); } // Set up search fields if requested by caller @@ -124,7 +124,7 @@ $grid->customData(compact('ledger_id', 'account_id', 'ar_account', // Render the grid $grid ->render($this, isset($config) ? $config : null, - array('Transaction', 'Entry', 'Date', 'Effective', 'Paid', + array('Transaction', 'Entry', 'Date', 'Effective', 'Last Payment', 'Account', 'Debit Account', 'Credit Account', 'Customer', 'Unit', 'Comment', From 0649329dde3d1d1ccd34c03a1a540a190fb8557f Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 15 Jul 2009 05:42:10 +0000 Subject: [PATCH 329/717] Fixed the balance summary of the collected report, and marked off NSF and collected report requirements. git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@335 97e9348a-65ac-dc4b-aefc-98561f571b83 --- requirements.txt | 6 +- .../controllers/ledger_entries_controller.php | 14 +-- site/views/accounts/collected.ctp | 89 +++++++++++++------ 3 files changed, 74 insertions(+), 35 deletions(-) diff --git a/requirements.txt b/requirements.txt index 7030a2b..9a12ea2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -46,8 +46,8 @@ Operations to be functional X - Receive and record Cash X - Receive and record ACH Deposits x - Reverse rent charges (early moveout on prepaid occupancy) - - Handle NSF checks - - Assess NSF Fees + X - Handle NSF checks + X - Assess NSF Fees - Determine Lease Paid-Through status - Report: List of customers overdue - Flag unit as overlocked @@ -66,4 +66,4 @@ Operations to be functional - Record Petty Cash to refund. X - Write Off Bad Debt X - Perform a Deposit and Close the Books - - Determine Rents Collected for a given period. + X - Determine Rents Collected for a given period. diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index 3879f8f..92a26cb 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -325,12 +325,16 @@ class LedgerEntriesController extends AppController { return $order; } - function jqGridDataOutputRecordCell(&$params, &$model, &$record, $field, $data) { -/* if ($field === 'CreditAccount.name') { */ -/* $data .= '-OK'; */ -/* } */ + function jqGridDataOutputRecords(&$params, &$model, &$records) { - parent::jqGridDataOutputRecordCell($params, $model, $record, $field, $data); + if ($params['action'] === 'collected') { + $total = 0; + foreach ($records AS &$record) + $total += $record['LedgerEntry']['applied']; + echo ' ' . $total . '' . "\n"; + } + + parent::jqGridDataOutputRecords($params, $model, $records); } diff --git a/site/views/accounts/collected.ctp b/site/views/accounts/collected.ctp index 6e43190..1c2fd93 100644 --- a/site/views/accounts/collected.ctp +++ b/site/views/accounts/collected.ctp @@ -15,25 +15,14 @@ echo '' . "\n"; + +?> Clear Debug Output From b1914f7cca44ac94dd113663774b3cf5e57eb44b Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 15 Jul 2009 06:21:55 +0000 Subject: [PATCH 330/717] Standardized the grid events interface, to ease the burden on the views and ensure that the load functions could be used by the application without wiping out the debug functionality that was built into jqGrid.ctp git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629@336 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/accounts/collected.ctp | 6 +--- site/views/accounts/deposit.ctp | 5 +--- site/views/customers/receipt.ctp | 34 ++++++--------------- site/views/elements/jqGrid.ctp | 31 ++++++++++++++++--- site/views/leases/invoice.ctp | 26 ++++++---------- site/views/leases/move.ctp | 50 +++++++++++-------------------- 6 files changed, 64 insertions(+), 88 deletions(-) diff --git a/site/views/accounts/collected.ctp b/site/views/accounts/collected.ctp index 1c2fd93..386010a 100644 --- a/site/views/accounts/collected.ctp +++ b/site/views/accounts/collected.ctp @@ -130,10 +130,6 @@ echo '
    ' . "\n"; * Entries */ -$grid_setup = - array('loadComplete' => - array('--special' => "function() {url=jQuery('#collected-entries-jqGrid').getGridParam('url');url=url.replace(/\/debug.*$/,'?'); pd=jQuery('#collected-entries-jqGrid').getPostData();$.each(pd,function(i){ url+=i+'='+escape(pd[i])+'&'; }); jQuery('#collected-entries-jqGrid-query').html('Grid Query
    '); onGridLoadComplete();}")); - echo $this->element('ledger_entries', array (// Element configuration 'collected_account_id' => $account['id'], @@ -144,7 +140,7 @@ echo $this->element('ledger_entries', array ( 'grid_div_id' => 'collected-entries', 'grid_div_class' => 'text-below', - 'grid_setup' => $grid_setup, + 'grid_events' => array('loadComplete' => 'onGridLoadComplete()'), //'caption' => '', 'caption' => 'Collected ' . Inflector::pluralize($account['name']) ), diff --git a/site/views/accounts/deposit.ctp b/site/views/accounts/deposit.ctp index d60924e..31ba0a7 100644 --- a/site/views/accounts/deposit.ctp +++ b/site/views/accounts/deposit.ctp @@ -11,9 +11,6 @@ echo $form->create(null, array('id' => 'deposit-form', 'url' => array('controller' => 'accounts', 'action' => 'deposit'))); -$grid_setup = array(); -$grid_setup['hiddengrid'] = true; - foreach ($tillableAccount AS $acct) { //$acct = $acct['Account']; @@ -59,7 +56,7 @@ foreach ($tillableAccount AS $acct) { 'grid_div_id' => $grid_div_id, 'caption' => ('Items in '.$acct['Account']['name'].' Ledger'), - 'grid_setup' => $grid_setup, + 'grid_setup' => array('hiddengrid' => true), ), )); } diff --git a/site/views/customers/receipt.ctp b/site/views/customers/receipt.ctp index ac198d1..9c2c721 100644 --- a/site/views/customers/receipt.ctp +++ b/site/views/customers/receipt.ctp @@ -8,32 +8,9 @@ ********************************************************************** ********************************************************************** ********************************************************************** - * Grid Setup / Javascript + * Javascript */ -$grid_setup = array(); - -if (isset($customer['id'])) - $grid_setup['hiddengrid'] = true; - -$grid_setup['onSelectRow'] = array - ('--special' => - 'function(ids) { if (ids != null) { onRowSelect("#"+$(this).attr("id"), ids); } }' - ); - -$grid_setup['onHeaderClick'] = array - ('--special' => - 'function(gridstate) { onGridState("#"+$(this).attr("id"), gridstate); }' - ); - -// Customer -// Outstanding balance -// Balance on each lease -// Balance on personal account -// Multiple fields for payments (cash, check, charge, etc) -// How to apply (even split, oldest charges first, etc) - - ?> \ No newline at end of file From e47a2cc7aadb44c9107c1e96ebb4ada021f5ff32 Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 31 Jul 2009 16:48:27 +0000 Subject: [PATCH 446/717] Some cleanup from the last checkin git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@452 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/transactions_controller.php | 5 +++ site/views/tenders/deposit.ctp | 46 ++++---------------- 2 files changed, 13 insertions(+), 38 deletions(-) diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php index 3939155..960b3fd 100644 --- a/site/controllers/transactions_controller.php +++ b/site/controllers/transactions_controller.php @@ -192,27 +192,32 @@ class TransactionsController extends AppController { $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'][] = diff --git a/site/views/tenders/deposit.ctp b/site/views/tenders/deposit.ctp index cf19501..4616d18 100644 --- a/site/views/tenders/deposit.ctp +++ b/site/views/tenders/deposit.ctp @@ -13,7 +13,6 @@ echo $form->create(null, array('id' => 'deposit-form', 'action' => 'postDeposit'))); foreach ($depositTypes AS $type) { - //$acct = $acct['Account']; $names = Inflector::pluralize($type['name']); $radioOptions = @@ -39,7 +38,7 @@ foreach ($depositTypes AS $type) { // REVISIT : 20090729 // Would like to present an option for the user to close the ledger // associated with the form of tender, or to just leave it open. - // For now, just leave it open + // For now, just close it. echo "\n"; echo $form->input("TenderType.{$type['id']}.close", array('type' => 'hidden', @@ -74,24 +73,15 @@ foreach ($depositTypes AS $type) { array('hiddengrid' => true, 'multiselect' => true), - 'grid_events' => - array( -/* 'onHeaderClick' => */ -/* array('gridstate' => */ -/* 'onGridState("#"+$(this).attr("id"), gridstate)'), */ -/* 'gridComplete' => */ -/* array('' => "switchSelection({$type['id']})"), */ -/* 'loadBeforeSend' => */ -/* array('xhr' => "loadBeforeSend()"), */ - ), - 'caption' => "{$names} on hand", - 'filter' => array('deposit_transaction_id' => null, - 'TenderType.id' => $type['id']), + 'filter' => array('deposit_transaction_id' => null, + 'TenderType.id' => $type['id']), 'exclude' => array('Type'), ), )); + // Add a hidden item to hold the jqGrid selection, + // which we'll populate prior to form submission. echo "\n"; echo $form->input("TenderType.{$type['id']}.items", array('type' => 'hidden', @@ -111,17 +101,14 @@ echo '
    ' . "\n"; - -
    diff --git a/site/views/leases/bad_debt.ctp b/site/views/leases/bad_debt.ctp deleted file mode 100644 index fec8b58..0000000 --- a/site/views/leases/bad_debt.ctp +++ /dev/null @@ -1,80 +0,0 @@ -' . "\n"; - -echo ('
    ' . - - 'Lease #' . $lease['number'] . - ' / Customer #' . $customer['id'] . - ': ' . $customer['name'] . - ' / Unit ' . $unit['name'] . - - '
    ' . - '' . - '' . - '
    Balance:'.$lease['stats']['balance'].'
    ' . - '
    ' . - - '
    ' . "\n"); - - -echo $form->create(null, array('id' => 'receipt-form', - 'url' => array('controller' => 'transactions', - 'action' => 'postReceipt'))); - -echo $form->input("Customer.id", - array('id' => 'customer-id', - 'type' => 'hidden', - 'value' => $customer['id'])); - -echo $form->input("Lease.id", - array('id' => 'lease-id', - 'type' => 'hidden', - 'value' => $lease['id'])); - -echo $form->input("LedgerEntry.0.account_id", - array('id' => 'account-id', - 'type' => 'hidden', - 'value' => $account['id'])); - -echo $form->input("LedgerEntry.0.amount", - array('id' => 'amount', - 'type' => 'hidden', - 'value' => $lease['stats']['balance'])); - - -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' => 'Now', - ), - "comment" => array('opts' => array('size' => 50), - ), - ))); - -echo $form->end('Write Off Remaining Balance'); -?> - - - -
    diff --git a/site/views/transactions/bad_debt.ctp b/site/views/transactions/bad_debt.ctp new file mode 100644 index 0000000..668f260 --- /dev/null +++ b/site/views/transactions/bad_debt.ctp @@ -0,0 +1,89 @@ +' . "\n"; + +if (isset($lease)) { + $customer = $lease['Customer']; + $unit = $lease['Unit']; +} + +if (isset($customer['Customer'])) + $customer = $customer['Customer']; + +if (isset($lease['Lease'])) + $lease = $lease['Lease']; + +// We're not actually using a grid to select the customer / lease +// but we could/should be, and the result would be selection-text +echo ('
    ' . + '' . "\n"); + +echo ('' . + ' ' . + '' . "\n"); + +if (isset($lease)) + echo ('' . + ' ' . + '' . "\n"); + +echo ('' . + ' ' . + '' . "\n"); + +echo ('
    ' . $customer['name'] . '' . '(Customer #' . $customer['id'] . ')' . '
    ' . 'Unit ' . $unit['name'] . '' . '(Lease #' . $lease['number'] . ')' . '
    Remaining Balance:' . FormatHelper::currency($balance) . '
    ' . + '
    ' . "\n"); + + +echo $form->create(null, array('id' => 'receipt-form', + 'url' => array('controller' => 'transactions', + 'action' => 'postWriteOff'))) . "\n"; + +echo $form->input("Customer.id", + array('type' => 'hidden', + 'value' => $customer['id'])) . "\n"; + +if (isset($lease['id'])) + echo $form->input("Lease.id", + array('type' => 'hidden', + 'value' => $lease['id'])) . "\n"; + +echo $form->input("Entry.0.amount", + array('type' => 'hidden', + 'value' => $balance)) . "\n"; + +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' => 'Now', + ), + "comment" => array('opts' => array('size' => 50), + ), + ))) . "\n"; + +echo $form->end('Write Off Remaining Balance'); +?> + + + +
    From 094e15ddf9050dbfeb545afea0a4f36df546f6a5 Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 5 Aug 2009 00:06:46 +0000 Subject: [PATCH 479/717] Added a more descriptive fieldname for statement entry views. Instead of Transaction, it will be Receipt, Invoice, Deposit, etc. git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@487 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/statement_entries_controller.php | 2 +- site/views/statement_entries/view.ctp | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/site/controllers/statement_entries_controller.php b/site/controllers/statement_entries_controller.php index 2816a70..974b1b2 100644 --- a/site/controllers/statement_entries_controller.php +++ b/site/controllers/statement_entries_controller.php @@ -212,7 +212,7 @@ class StatementEntriesController extends AppController { $entry = $this->StatementEntry->find ('first', array('contain' => array - ('Transaction' => array('fields' => array('id', 'stamp')), + ('Transaction' => array('fields' => array('id', 'type', 'stamp')), 'Account' => array('id', 'name', 'type'), 'Customer' => array('fields' => array('id', 'name')), 'Lease' => array('fields' => array('id')), diff --git a/site/views/statement_entries/view.ctp b/site/views/statement_entries/view.ctp index 6116104..038afd6 100644 --- a/site/views/statement_entries/view.ctp +++ b/site/views/statement_entries/view.ctp @@ -15,15 +15,18 @@ $customer = $entry['Customer']; $lease = $entry['Lease']; $entry = $entry['StatementEntry']; +$Ttype = ucfirst(strtolower($transaction['type'])); + $rows = array(); $rows[] = array('ID', $entry['id']); -$rows[] = array('Transaction', $html->link('#'.$transaction['id'], +$rows[] = array($Ttype, $html->link('#'.$transaction['id'], array('controller' => 'transactions', 'action' => 'view', $transaction['id']))); $rows[] = array('Timestamp', FormatHelper::datetime($transaction['stamp'])); $rows[] = array('Effective', FormatHelper::date($entry['effective_date'])); -$rows[] = array('Through', FormatHelper::date($entry['through_date'])); +if (in_array($entry['type'], array('CHARGE', /*REVISIT 'VOUCHER-PAYMENT'*/))) + $rows[] = array('Through', FormatHelper::date($entry['through_date'])); $rows[] = array('Type', $entry['type']); $rows[] = array('Amount', FormatHelper::currency($entry['amount'])); $rows[] = array('Account', $html->link($account['name'], From cb969ba34047c77a0b19f090067941684f112b3e Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 5 Aug 2009 01:00:09 +0000 Subject: [PATCH 480/717] Discovered that the use of the term 'Payment' has been a misnomer. A company uses the term payment to indicate the monies it pays to _others_. Changing this leaves us without a good replacement term, but disbursement really seems to fit the bill. As comfortable as the term payment was, it was odd in many respects and disbursement does seem more appropriate. I'm sure there are several lingering bugs from this massive search/replace exercise, but this is a decent baseline for the change. git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@488 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 29 ++- scripts/sitelink2pmgr.pl | 9 +- site/controllers/accounts_controller.php | 2 +- site/controllers/customers_controller.php | 4 +- site/controllers/leases_controller.php | 4 +- .../statement_entries_controller.php | 22 +-- site/controllers/transactions_controller.php | 2 +- site/controllers/units_controller.php | 2 +- site/models/account.php | 10 +- site/models/customer.php | 21 +-- site/models/lease.php | 2 +- site/models/ledger_entry.php | 8 +- site/models/statement_entry.php | 166 +++++++++--------- site/models/tender.php | 4 +- site/models/tender_type.php | 2 +- site/models/transaction.php | 105 +++++++---- site/views/accounts/collected.ctp | 2 +- site/views/accounts/view.ctp | 4 +- site/views/elements/statement_entries.ctp | 2 +- site/views/ledgers/view.ctp | 2 +- site/views/statement_entries/view.ctp | 6 +- 21 files changed, 211 insertions(+), 197 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index 5719d05..c1864f5 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -855,8 +855,8 @@ CREATE TABLE `pmgr_accounts` ( -- normal circumstances, when a debit occurs. -- `trackable` TINYINT(1) UNSIGNED NOT NULL DEFAULT 1, `deposits` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Can be used for deposits? - `charges` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Can be used for charges? - `payments` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Can be used for payments? + `invoices` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Can be used for invoices? + `receipts` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Can be used for receipts? `refunds` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Can be used for refunds? -- Security Level @@ -884,7 +884,7 @@ INSERT INTO `pmgr_accounts` (`type`, `name`) -- us identify how serious the NSF situation is. ('ASSET', 'NSF' ), ('LIABILITY', 'A/P' ); -INSERT INTO `pmgr_accounts` (`type`, `name`, `payments`, `refunds`) +INSERT INTO `pmgr_accounts` (`type`, `name`, `receipts`, `refunds`) VALUES ('ASSET', 'Cash', 1, 1), ('ASSET', 'Check', 1, 0), @@ -898,7 +898,7 @@ INSERT INTO `pmgr_accounts` (`type`, `name`, `refunds`, `deposits`) -- REVISIT : 20090710 : We probably don't really want petty cash depositable. -- This is just for testing our deposit code ('ASSET', 'Petty Cash', 1, 1); -INSERT INTO `pmgr_accounts` (`type`, `name`, `charges`) +INSERT INTO `pmgr_accounts` (`type`, `name`, `invoices`) VALUES ('LIABILITY', 'Tax', 1), ('LIABILITY', 'Security Deposit', 1), @@ -963,11 +963,12 @@ CREATE TABLE `pmgr_transactions` ( `type` ENUM('INVOICE', 'RECEIPT', - 'DEPOSIT', - 'CLOSE', + 'VOUCHER', + 'DEPOSIT', -- Probably should use VOUCHER for DEPOSIT + 'CLOSE', -- Essentially an internal (not accounting) transaction -- 'CREDIT', -- 'REFUND', - 'TRANSFER') + 'TRANSFER') -- Unsure of TRANSFERs use NOT NULL, `stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, @@ -992,10 +993,6 @@ CREATE TABLE `pmgr_transactions` ( -- (e.g. A/R, Bank, etc) `account_id` INT(10) UNSIGNED DEFAULT NULL, `ledger_id` INT(10) UNSIGNED DEFAULT NULL, - - -- For convenience. Actually, INVOICE will always set crdr - -- to DEBIT, RECEIPT will use CREDIT, and DEPOSIT will use - -- DEBIT `crdr` ENUM('DEBIT', 'CREDIT') DEFAULT NULL, @@ -1024,9 +1021,6 @@ CREATE TABLE `pmgr_ledger_entries` ( -- The account/ledger of the entry `account_id` INT(10) UNSIGNED NOT NULL, `ledger_id` INT(10) UNSIGNED NOT NULL, - - -- For convenience. Actually, CHARGE will always set crdr - -- to CREDIT and PAYMENT will use DEBIT. `crdr` ENUM('DEBIT', 'CREDIT') NOT NULL, @@ -1073,7 +1067,8 @@ CREATE TABLE `pmgr_statement_entries` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `type` ENUM('CHARGE', - 'PAYMENT', + 'DISBURSEMENT', + 'VOUCHER-PAYMENT', -- REVISIT: Make PAYMENT 'SURPLUS', 'WAIVER', -- REVISIT : 20090730 @@ -1084,7 +1079,7 @@ CREATE TABLE `pmgr_statement_entries` ( `transaction_id` INT(10) UNSIGNED NOT NULL, - -- Effective date is when the charge/payment/transfer actually + -- Effective date is when the charge/disbursement/transfer actually -- takes effect (since it may not be at the time of the transaction). -- Through date is used if/when a charge covers a certain time period, -- like rent. A security deposit, for example, would not use the @@ -1109,7 +1104,7 @@ CREATE TABLE `pmgr_statement_entries` ( -- in the statement. Keeping it for now... `account_id` INT(10) UNSIGNED DEFAULT NULL, - -- Allow the payment to reconcile against the charge + -- Allow the disbursement to reconcile against the charge `charge_entry_id` INT(10) UNSIGNED DEFAULT NULL, `comment` VARCHAR(255) DEFAULT NULL, diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 7af758b..f81c5ba 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -1308,18 +1308,13 @@ foreach $row (@{query($sdbh, $query)}) # 'effective_date' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'effective_date'}, # 'effective_date' => $effective_date; # 'through_date' => $through_date; - 'lease_id' => ($row->{'entry_type'} eq 'CREDIT' - ? 0 - : $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}), + 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, 'amount' => $reconcile_amount, 'account_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'debit_account_id'}, }; - $row->{'ChargeID'} = undef - if $row->{'entry_type'} eq 'CREDIT'; - # Update the receipt & tender customer_id, now that we have payment info $newdb{'tables'}{'transactions'}{'rows'}[ $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'receipt_id'} @@ -1336,7 +1331,7 @@ foreach $row (@{query($sdbh, $query)}) # Add the Payment Statement Entry addRow('statement_entries', { 'transaction_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'receipt_id'}, - 'type' => $row->{'entry_type'} || 'PAYMENT', + 'type' => 'DISBURSEMENT', # 'effective_date' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'effective_date'}, # 'through_date' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'through_date'}, 'effective_date' => $effective_date, diff --git a/site/controllers/accounts_controller.php b/site/controllers/accounts_controller.php index ec35830..c43dfa3 100644 --- a/site/controllers/accounts_controller.php +++ b/site/controllers/accounts_controller.php @@ -141,7 +141,7 @@ class AccountsController extends AppController { $payment_accounts = $this->Account->collectableAccounts(); //$payment_accounts[$this->Account->nameToID('Closing')] = 'Closing'; //$payment_accounts[$this->Account->nameToID('Equity')] = 'Equity'; - $default_accounts = array_diff_key($this->Account->paymentAccounts(), + $default_accounts = array_diff_key($this->Account->receiptAccounts(), array($this->Account->concessionAccountID() => 1)); $this->set(compact('payment_accounts', 'default_accounts')); diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 56ad22f..38d608d 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -64,7 +64,7 @@ class CustomersController extends AppController { function gridDataFields(&$params, &$model) { $fields = parent::gridDataFields($params, $model); return array_merge($fields, - $this->Customer->StatementEntry->chargePaymentFields(true)); + $this->Customer->StatementEntry->chargeDisbursementFields(true)); } function gridDataConditions(&$params, &$model) { @@ -384,7 +384,7 @@ class CustomersController extends AppController { $default_type = $TT->defaultPaymentType(); $this->set(compact('payment_types', 'default_type')); - $title = ($customer['name'] . ': Payment Entry'); + $title = ($customer['name'] . ': Receipt Entry'); $this->set(compact('customer', 'charges', 'stats', 'title')); } diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index 2830569..edc1231 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -64,7 +64,7 @@ class LeasesController extends AppController { function gridDataFields(&$params, &$model) { $fields = parent::gridDataFields($params, $model); return array_merge($fields, - $this->Lease->StatementEntry->chargePaymentFields(true)); + $this->Lease->StatementEntry->chargeDisbursementFields(true)); } function gridDataConditions(&$params, &$model) { @@ -332,7 +332,7 @@ class LeasesController extends AppController { )); $A = new Account(); - $charge_accounts = $A->chargeAccounts(); + $charge_accounts = $A->invoiceAccounts(); $default_account = $A->rentAccountID(); $this->set(compact('charge_accounts', 'default_account')); diff --git a/site/controllers/statement_entries_controller.php b/site/controllers/statement_entries_controller.php index 974b1b2..b3d4599 100644 --- a/site/controllers/statement_entries_controller.php +++ b/site/controllers/statement_entries_controller.php @@ -49,21 +49,21 @@ class StatementEntriesController extends AppController { ); if (isset($params['post']['custom']['statement_entry_id'])) { - $link['PaymentEntry'] = array(); + $link['DisbursementEntry'] = array(); $link['ChargeEntry'] = array(); } /* if ($params['action'] === 'collected') { */ -/* $link['PaymentEntry'] = array('Receipt' => array('class' => 'Transaction')); */ +/* $link['DisbursementEntry'] = array('Receipt' => array('class' => 'Transaction')); */ /* $link['ChargeEntry'] = array('Invoice' => array('class' => 'Transaction')); */ /* } */ /* if (count(array_intersect($params['fields'], array('applied'))) == 1) { */ -/* $link['PaymentEntry'] = array(); */ +/* $link['DisbursementEntry'] = array(); */ /* $link['ChargeEntry'] = array(); */ /* } */ /* elseif (isset($params['post']['custom']['customer_id']) || isset($params['post']['custom']['lease_id'])) { */ -/* $link['PaymentEntry'] = array(); */ +/* $link['DisbursementEntry'] = array(); */ /* } */ return array('link' => $link); @@ -74,18 +74,18 @@ class StatementEntriesController extends AppController { if (in_array('applied', $params['post']['fields'])) { $fields[] = ("IF(StatementEntry.type = 'CHARGE'," . - " SUM(COALESCE(PaymentEntry.amount,0))," . + " SUM(COALESCE(DisbursementEntry.amount,0))," . " SUM(COALESCE(ChargeEntry.amount,0)))" . " AS 'applied'"); $fields[] = ("StatementEntry.amount - (" . "IF(StatementEntry.type = 'CHARGE'," . - " SUM(COALESCE(PaymentEntry.amount,0))," . + " SUM(COALESCE(DisbursementEntry.amount,0))," . " SUM(COALESCE(ChargeEntry.amount,0)))" . ") AS 'balance'"); } $fields = array_merge($fields, - $this->StatementEntry->chargePaymentFields()); + $this->StatementEntry->chargeDisbursementFields()); return $fields; } @@ -110,7 +110,7 @@ class StatementEntriesController extends AppController { if (isset($statement_entry_id)) { $conditions[] = array('OR' => array(array('ChargeEntry.id' => $statement_entry_id), - array('PaymentEntry.id' => $statement_entry_id))); + array('DisbursementEntry.id' => $statement_entry_id))); } return $conditions; @@ -144,13 +144,13 @@ class StatementEntriesController extends AppController { if (in_array('applied', $params['post']['fields'])) { $tquery = array_diff_key($query, array('fields'=>1,'group'=>1,'limit'=>1,'order'=>1)); $tquery['fields'] = array("IF(StatementEntry.type = 'CHARGE'," . - " SUM(COALESCE(PaymentEntry.amount,0))," . + " SUM(COALESCE(DisbursementEntry.amount,0))," . " SUM(COALESCE(ChargeEntry.amount,0)))" . " AS 'applied'", "StatementEntry.amount - (" . "IF(StatementEntry.type = 'CHARGE'," . - " SUM(COALESCE(PaymentEntry.amount,0))," . + " SUM(COALESCE(DisbursementEntry.amount,0))," . " SUM(COALESCE(ChargeEntry.amount,0)))" . ") AS 'balance'", ); @@ -266,7 +266,7 @@ class StatementEntriesController extends AppController { if (strtoupper($entry['StatementEntry']['type']) === 'CHARGE') $stats = $stats['Charge']; else - $stats = $stats['Payment']; + $stats = $stats['Disbursement']; if (strtoupper($entry['StatementEntry']['type']) === 'CHARGE' && diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php index 5fe0b5a..2173e54 100644 --- a/site/controllers/transactions_controller.php +++ b/site/controllers/transactions_controller.php @@ -114,7 +114,7 @@ class TransactionsController extends AppController { ************************************************************************** ************************************************************************** * action: postReceipt - * - handles the creation of a payment receipt + * - handles the creation of a receipt */ function postReceipt() { diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index 6ee1a15..1a9c96a 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -82,7 +82,7 @@ class UnitsController extends AppController { $fields = parent::gridDataFields($params, $model); return array_merge($fields, - $this->Unit->Lease->StatementEntry->chargePaymentFields(true)); + $this->Unit->Lease->StatementEntry->chargeDisbursementFields(true)); } function gridDataConditions(&$params, &$model) { diff --git a/site/models/account.php b/site/models/account.php index afc854a..b32844c 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -194,12 +194,12 @@ class Account extends AppModel { * - Returns an array of accounts suitable for activity xxx */ - function chargeAccounts() { - return $this->relatedAccounts('charges', array('order' => 'name')); + function invoiceAccounts() { + return $this->relatedAccounts('invoices', array('order' => 'name')); } - function paymentAccounts() { - return $this->relatedAccounts('payments', array('order' => 'name')); + function receiptAccounts() { + return $this->relatedAccounts('receipts', array('order' => 'name')); } function depositAccounts() { @@ -215,7 +215,7 @@ class Account extends AppModel { */ function collectableAccounts() { - $accounts = $this->paymentAccounts(); + $accounts = $this->receiptAccounts(); foreach(array($this->nsfAccountID(), $this->securityDepositAccountID()) diff --git a/site/models/customer.php b/site/models/customer.php index 762c86e..aa01afd 100644 --- a/site/models/customer.php +++ b/site/models/customer.php @@ -127,23 +127,6 @@ class Customer extends AppModel { } - /************************************************************************** - ************************************************************************** - ************************************************************************** - * function: excessPayments - * - Returns payments which have not yet been fully utilized - */ - - function excessPayments($id, $query = null) { - $this->prEnter(compact('id', 'query')); - $this->queryInit($query); - - $query['conditions'][] = array('StatementEntry.customer_id' => $id); - $set = $this->StatementEntry->reconciledSet('PAYMENT', $query, true); - return $this->prReturn($set); - } - - /************************************************************************** ************************************************************************** ************************************************************************** @@ -314,14 +297,14 @@ class Customer extends AppModel { /* $stats = $this->StatementEntry->find */ /* ('first', array */ /* ('contain' => false, */ -/* 'fields' => $this->StatementEntry->chargePaymentFields(true), */ +/* 'fields' => $this->StatementEntry->chargeDisbursementFields(true), */ /* 'conditions' => array('StatementEntry.customer_id' => $id), */ /* )); */ $find_stats = $this->StatementEntry->find ('first', array ('contain' => false, - 'fields' => $this->StatementEntry->chargePaymentFields(true), + 'fields' => $this->StatementEntry->chargeDisbursementFields(true), 'conditions' => array('StatementEntry.customer_id' => $id), )); $find_stats = $find_stats[0]; diff --git a/site/models/lease.php b/site/models/lease.php index 30965ca..42a7195 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -72,7 +72,7 @@ class Lease extends AppModel { ************************************************************************** * function: releaseSecurityDeposits * - Releases all security deposits associated with this lease. - * That simply makes a payment out of them, which can be used + * 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). */ diff --git a/site/models/ledger_entry.php b/site/models/ledger_entry.php index 3cb0b09..cb57dea 100644 --- a/site/models/ledger_entry.php +++ b/site/models/ledger_entry.php @@ -170,7 +170,7 @@ class LedgerEntry extends AppModel { //pr(array('stats()', compact('id', 'query', 'set'))); - $rtypes = array('charge', 'payment', + $rtypes = array('charge', 'disbursement', // 'debit', 'credit', ); @@ -178,10 +178,8 @@ class LedgerEntry extends AppModel { foreach($rtypes AS $rtype) { $Rtype = ucfirst($rtype); - if (($rtype == 'charge' && (!isset($set) || $set == 'PAYMENT')) || - ($rtype == 'payment' && (!isset($set) || $set == 'CHARGE')) -/* ($rtype == 'debit' && (!isset($set) || $set == 'CREDIT')) || */ -/* ($rtype == 'credit' && (!isset($set) || $set == 'DEBIT')) */ + if (($rtype == 'charge' && (!isset($set) || $set == 'DISBURSEMENT')) || + ($rtype == 'disbursement' && (!isset($set) || $set == 'CHARGE')) ) { $rquery = $query; diff --git a/site/models/statement_entry.php b/site/models/statement_entry.php index 885e243..8dce2cf 100644 --- a/site/models/statement_entry.php +++ b/site/models/statement_entry.php @@ -7,15 +7,15 @@ class StatementEntry extends AppModel { 'Lease', 'Account', - // The charge to which this payment applies (if it is one) + // The charge to which this disbursement applies (if it is one) 'ChargeEntry' => array( 'className' => 'StatementEntry', ), ); var $hasMany = array( - // The payments that apply to this charge (if it is one) - 'PaymentEntry' => array( + // The disbursements that apply to this charge (if it is one) + 'DisbursementEntry' => array( 'className' => 'StatementEntry', 'foreignKey' => 'charge_entry_id', ), @@ -27,11 +27,11 @@ class StatementEntry extends AppModel { /************************************************************************** ************************************************************************** ************************************************************************** - * function: chargePaymentFields + * function: chargeDisbursementFields */ - function chargePaymentFields($sum = false, $entry_name = 'StatementEntry') { + function chargeDisbursementFields($sum = false, $entry_name = 'StatementEntry') { $fields = array ( ($sum ? 'SUM(' : '') . @@ -40,14 +40,14 @@ class StatementEntry extends AppModel { ($sum ? ')' : '') . ' AS charge' . ($sum ? 's' : ''), ($sum ? 'SUM(' : '') . - //"IF({$entry_name}.type IN('PAYMENT', 'SURPLUS', 'WAIVER')," . + //"IF({$entry_name}.type IN('DISBURSEMENT', 'SURPLUS', 'WAIVER')," . "IF({$entry_name}.type NOT IN('CHARGE', 'VOID')," . " {$entry_name}.amount, NULL)" . - ($sum ? ')' : '') . ' AS payment' . ($sum ? 's' : ''), + ($sum ? ')' : '') . ' AS disbursement' . ($sum ? 's' : ''), ($sum ? 'SUM(' : '') . //"IF({$entry_name}.type = 'CHARGE', 1," . - //" IF({$entry_name}.type IN('PAYMENT', 'SURPLUS', 'WAIVER'), -1, 0))" . + //" IF({$entry_name}.type IN('DISBURSEMENT', 'SURPLUS', 'WAIVER'), -1, 0))" . "IF({$entry_name}.type = 'VOID', 0," . " IF({$entry_name}.type = 'CHARGE', 1, -1))" . " * IF({$entry_name}.amount, {$entry_name}.amount, 0)" . @@ -154,7 +154,7 @@ class StatementEntry extends AppModel { * function: reverse * - Reverses the charges * - * SAMPLE MOVE IN w/ PRE PAYMENT + * SAMPLE MOVE IN w/ PRE DISBURSEMENT * DEPOSIT RENT A/R RECEIPT CHECK PETTY BANK * ------- ------- ------- ------- ------- ------- ------- * |25 | 25| | | | | @@ -271,20 +271,20 @@ OPTION 2 function reconciledSetQuery($set, $query) { $this->queryInit($query); - if ($set == 'CHARGE' || $set == 'PAYMENT') + if ($set == 'CHARGE' || $set == 'DISBURSEMENT') $query['conditions'][] = array('StatementEntry.type' => $set); else die("INVALID RECONCILE SET"); if ($set == 'CHARGE') - $query['link']['PaymentEntry'] = array('fields' => array("SUM(PaymentEntry.amount) AS reconciled")); - if ($set == 'PAYMENT') + $query['link']['DisbursementEntry'] = array('fields' => array("SUM(DisbursementEntry.amount) AS reconciled")); + if ($set == 'DISBURSEMENT') $query['link']['ChargeEntry'] = array('fields' => array("SUM(ChargeEntry.amount) AS reconciled")); $query['group'] = 'StatementEntry.id'; // REVISIT: TESTING - //$query['link']['PaymentEntry'] = array('fields' => array("(`PaymentEntry.amount`+0) AS reconciled")); + //$query['link']['DisbursementEntry'] = array('fields' => array("(`DisbursementEntry.amount`+0) AS reconciled")); //$query['group'] = null; // END REVISIT @@ -316,7 +316,7 @@ OPTION 2 $reconciled = true; elseif ($entry['StatementEntry']['reconciled'] == 0) $reconciled = false; - else // Partial payment; depends on unrec + else // Partial disbursement; depends on unrec $reconciled = (!$unrec && $if_rec_include_partial); // Add to the set, if it's been requested @@ -334,7 +334,7 @@ OPTION 2 ************************************************************************** * function: reconciledEntries * - Returns a list of entries that reconcile against the given entry. - * (such as payments towards a charge). + * (such as disbursements towards a charge). */ function reconciledEntriesQuery($id, $query = null) { $this->queryInit($query, false); @@ -346,8 +346,8 @@ OPTION 2 $query['conditions'][] = array('StatementEntry.id' => $id); if ($this->data['StatementEntry']['type'] == 'CHARGE') - $query['link']['PaymentEntry'] = array(); - if ($this->data['StatementEntry']['type'] == 'PAYMENT') + $query['link']['DisbursementEntry'] = array(); + if ($this->data['StatementEntry']['type'] == 'DISBURSEMENT') $query['link']['ChargeEntry'] = array(); return $query; @@ -373,24 +373,24 @@ OPTION 2 * * REVISIT : 20090726 * This algorithm shouldn't be hardcoded. We need to allow - * the user to specify how payments should be applied. + * the user to specify how disbursements should be applied. * */ function assignCredits($query = null, $receipt_id = null, - $charge_ids = null, $payment_type = null, + $charge_ids = null, $disbursement_type = null, $customer_id = null, $lease_id = null) { $this->prFunctionLevel(25); $this->prEnter(compact('query', 'receipt_id', - 'charge_ids', 'payment_type', + '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($payment_type)) - $payment_type = 'PAYMENT'; + if (empty($disbursement_type)) + $disbursement_type = 'DISBURSEMENT'; $ret = array(); @@ -461,7 +461,7 @@ OPTION 2 // Initialize our list of used credits $used_credits = array(); - // Work through all unpaid charges, applying payments as we go + // Work through all unpaid charges, applying disbursements as we go foreach ($charges['entries'] AS $charge) { $this->pr(20, compact('charge'), @@ -489,9 +489,9 @@ OPTION 2 if (count($credits)) { // Peel off the first credit available $credit =& $credits[0]; - $payment_date = $credit['StatementEntry']['effective_date']; - $payment_transaction_id = $credit['StatementEntry']['transaction_id']; - $payment_account_id = $credit['StatementEntry']['account_id']; + $disbursement_date = $credit['StatementEntry']['effective_date']; + $disbursement_transaction_id = $credit['StatementEntry']['transaction_id']; + $disbursement_account_id = $credit['StatementEntry']['account_id']; if (!isset($credit['balance'])) $credit['balance'] = $credit['StatementEntry']['amount']; @@ -499,22 +499,22 @@ OPTION 2 elseif (!empty($receipt_credit['balance'])) { // Use our only receipt credit $credit =& $receipt_credit; - $payment_date = $credit['Transaction']['stamp']; - $payment_transaction_id = $credit['Transaction']['id']; - $payment_account_id = $credit['LedgerEntry']['account_id']; + $disbursement_date = $credit['Transaction']['stamp']; + $disbursement_transaction_id = $credit['Transaction']['id']; + $disbursement_account_id = $credit['LedgerEntry']['account_id']; } else { die("HOW DID WE GET HERE WITH NO SURPLUS?"); } - // Set the payment amount to the maximum amount + // Set the disbursement amount to the maximum amount // possible without exceeding the charge or credit balance - $payment_amount = min($charge['balance'], $credit['balance']); + $disbursement_amount = min($charge['balance'], $credit['balance']); if (!isset($credit['applied'])) $credit['applied'] = 0; - $credit['applied'] += $payment_amount; - $credit['balance'] -= $payment_amount; + $credit['applied'] += $disbursement_amount; + $credit['balance'] -= $disbursement_amount; $this->pr(20, compact('credit'), ($credit['balance'] > 0 ? 'Utilized' : 'Exhausted') . @@ -528,28 +528,28 @@ OPTION 2 if ($credit['balance'] <= 0 && count($credits)) $used_credits[] = array_shift($credits); - // Add a payment that uses the available credit to pay the charge - $payment = array('type' => $payment_type, - 'account_id' => $payment_account_id, - 'amount' => $payment_amount, - 'effective_date' => $payment_date, - 'transaction_id' => $payment_transaction_id, + // Add a disbursement that uses the available credit to pay the charge + $disbursement = array('type' => $disbursement_type, + 'account_id' => $disbursement_account_id, + 'amount' => $disbursement_amount, + 'effective_date' => $disbursement_date, + 'transaction_id' => $disbursement_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('payment'), - 'New Payment Entry'); + $this->pr(20, compact('disbursement'), + 'New Disbursement Entry'); - $result = $this->addStatementEntry($payment); - $ret['Payment'][] = $result; + $result = $this->addStatementEntry($disbursement); + $ret['Disbursement'][] = $result; if ($result['error']) $ret['error'] = true; - // Adjust the charge balance to reflect the new payment - $charge['balance'] -= $payment_amount; + // 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?"); @@ -564,7 +564,7 @@ OPTION 2 $used_credits[] = array_shift($credits); $this->pr(18, compact('credits', 'used_credits', 'receipt_credit'), - 'Payments added'); + 'Disbursements added'); // Clean up any explicit credits that have been used foreach ($used_credits AS $credit) { @@ -627,7 +627,7 @@ OPTION 2 // Determine the total in charges $charge_query = $query; unset($charge_query['link']['ChargeEntry']); - unset($charge_query['link']['PaymentEntry']); + unset($charge_query['link']['DisbursementEntry']); $charge_query['fields'] = array(); $charge_query['fields'][] = "SUM(StatementEntry.amount) AS total"; @@ -639,23 +639,23 @@ OPTION 2 'Charges'); // Tally the amount actually _paid_ to those charges - $charge_payment_query = $charge_query; - $charge_payment_query['link']['PaymentEntry'] = array('fields' => array()); - $charge_payment_query['fields'] = array(); - $charge_payment_query['fields'][] = "COALESCE(SUM(PaymentEntry.amount),0) AS paid"; - $charge_payment_query['conditions'][] = array('PaymentEntry.type' => 'PAYMENT'); - $result = $this->find('first', $charge_payment_query); + $charge_disbursement_query = $charge_query; + $charge_disbursement_query['link']['DisbursementEntry'] = array('fields' => array()); + $charge_disbursement_query['fields'] = array(); + $charge_disbursement_query['fields'][] = "COALESCE(SUM(DisbursementEntry.amount),0) AS paid"; + $charge_disbursement_query['conditions'][] = array('DisbursementEntry.type' => 'DISBURSEMENT'); + $result = $this->find('first', $charge_disbursement_query); $stats['Charge'] += $result[0]; - $this->pr(17, compact('charge_payment_query', 'result'), - 'Charge Payments'); + $this->pr(17, compact('charge_disbursement_query', 'result'), + 'Charge Disbursements'); // Tally the amount of charges that have been waived $charge_waiver_query = $charge_query; - $charge_waiver_query['link']['PaymentEntry'] = array('fields' => array()); + $charge_waiver_query['link']['DisbursementEntry'] = array('fields' => array()); $charge_waiver_query['fields'] = array(); - $charge_waiver_query['fields'][] = "COALESCE(SUM(PaymentEntry.amount),0) AS waived"; - $charge_waiver_query['conditions'][] = array('PaymentEntry.type' => 'WAIVER'); + $charge_waiver_query['fields'][] = "COALESCE(SUM(DisbursementEntry.amount),0) AS waived"; + $charge_waiver_query['conditions'][] = array('DisbursementEntry.type' => 'WAIVER'); $result = $this->find('first', $charge_waiver_query); $stats['Charge'] += $result[0]; @@ -671,46 +671,46 @@ OPTION 2 $stats['Charge']['balance'] = 0; - // Determine the total in payments, including those which + // Determine the total in disbursements, including those which // are charge waivers and those that do not even reconcile - // to charges (i.e. they are surplus payments). - $payment_query = $query; - unset($payment_query['link']['PaymentEntry']); - $payment_query['link']['ChargeEntry'] = array('fields' => array()); + // to charges (i.e. they are surplus disbursements). + $disbursement_query = $query; + unset($disbursement_query['link']['DisbursementEntry']); + $disbursement_query['link']['ChargeEntry'] = array('fields' => array()); - $payment_query['fields'] = array(); - $payment_query['fields'][] = "SUM(StatementEntry.amount) AS total"; - $payment_query['fields'][] = "COALESCE(SUM(IF(ChargeEntry.id IS NULL, 0, StatementEntry.amount)), 0) AS charged"; - $payment_query['fields'][] = "COALESCE(SUM(IF(ChargeEntry.id IS NULL, StatementEntry.amount, 0)), 0) AS surplus"; + $disbursement_query['fields'] = array(); + $disbursement_query['fields'][] = "SUM(StatementEntry.amount) AS total"; + $disbursement_query['fields'][] = "COALESCE(SUM(IF(ChargeEntry.id IS NULL, 0, StatementEntry.amount)), 0) AS charged"; + $disbursement_query['fields'][] = "COALESCE(SUM(IF(ChargeEntry.id IS NULL, StatementEntry.amount, 0)), 0) AS surplus"; - $payment_query['conditions'][] = array('StatementEntry.type' => array('PAYMENT', 'WAIVER', 'SURPLUS')); - $result = $this->find('first', $payment_query); - $stats['Payment'] = $result[0]; + $disbursement_query['conditions'][] = array('StatementEntry.type' => array('DISBURSEMENT', 'WAIVER', 'SURPLUS')); + $result = $this->find('first', $disbursement_query); + $stats['Disbursement'] = $result[0]; - $this->pr(17, compact('payment_query', 'result'), - 'Payments'); + $this->pr(17, compact('disbursement_query', 'result'), + 'Disbursements'); - // Compute some summary information for payments. + // Compute some summary information for disbursements. // Add a reconciled field just for consistency with Charge. - $stats['Payment']['reconciled'] = - $stats['Payment']['charged']; - $stats['Payment']['balance'] = - $stats['Payment']['total'] - $stats['Payment']['reconciled']; - if (!isset($stats['Payment']['balance'])) - $stats['Payment']['balance'] = 0; + $stats['Disbursement']['reconciled'] = + $stats['Disbursement']['charged']; + $stats['Disbursement']['balance'] = + $stats['Disbursement']['total'] - $stats['Disbursement']['reconciled']; + if (!isset($stats['Disbursement']['balance'])) + $stats['Disbursement']['balance'] = 0; // 'balance' is simply the difference between - // the balances of charges and payments - $stats['balance'] = $stats['Charge']['balance'] - $stats['Payment']['balance']; + // 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 payment + // 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']['paid'] - $stats['Payment']['total']; + $stats['account_balance'] = $stats['Charge']['paid'] - $stats['Disbursement']['total']; if (!isset($stats['account_balance'])) $stats['account_balance'] = 0; diff --git a/site/models/tender.php b/site/models/tender.php index 63161d1..c27dcde 100644 --- a/site/models/tender.php +++ b/site/models/tender.php @@ -92,8 +92,8 @@ class Tender extends AppModel { * - Add new LedgerEntry (L2a); T1; debit:NSF; -$A; N1 * - Add new LedgerEntry (L2b); T1; credit:A/R; -$A * - For Tx associated with LE associated with C1: - * - For each Payment SE of Tx: - * - Add new StatementEntry (S1n); T1; PAYMENT; -1*S1n.amount + * - For each Disbursement SE of Tx: + * - Add new StatementEntry (S1n); T1; DISBURSEMENT; -1*S1n.amount * - New Transaction (T2) (?????) * - Add new StatementEntry (S2); T2; CHARGE; NSF; $35 * - Add new LedgerEntry (L3a); T2; credit:NSF-Fee; $35 diff --git a/site/models/tender_type.php b/site/models/tender_type.php index 885e372..5d70cf0 100644 --- a/site/models/tender_type.php +++ b/site/models/tender_type.php @@ -112,4 +112,4 @@ class TenderType extends AppModel { return $stats[0]; } -} +} \ No newline at end of file diff --git a/site/models/transaction.php b/site/models/transaction.php index 7f4a8a1..ffd51f5 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -19,9 +19,9 @@ class Transaction extends AppModel { 'conditions' => array('Charge.type' => 'CHARGE') ), - 'Payment' => array( + 'Disbursement' => array( 'className' => 'StatementEntry', - 'conditions' => array('Payment.type' => 'PAYMENT') + 'conditions' => array('Disbursement.type' => 'DISBURSEMENT') ), 'Debit' => array( @@ -93,9 +93,9 @@ class Transaction extends AppModel { 'lease_id' => $lease_id, ); - // Go through the statement entries and flag as payments + // Go through the statement entries and flag as disbursements foreach ($data['Entry'] AS &$entry) - $entry += array('type' => 'PAYMENT', // not used + $entry += array('type' => 'DISBURSEMENT', // not used 'crdr' => 'DEBIT', 'account_id' => (isset($entry['Tender']['tender_type_id']) @@ -125,9 +125,9 @@ class Transaction extends AppModel { if (count($data['Entry']) != 1) die("INTERNAL ERROR: Should be one Entry for addWaiver"); - // Just make sure the payment(s) are marked as waivers + // Just make sure the disbursement(s) are marked as waivers // and that they go to cover the specific charge. - $data['Transaction']['payment_type'] = 'WAIVER'; + $data['Transaction']['disbursement_type'] = 'WAIVER'; $data['Transaction']['charge_entry_id'] = $charge_id; // In all other respects this is just a receipt. @@ -151,11 +151,13 @@ class Transaction extends AppModel { // Establish the transaction as a deposit $deposit =& $data['Transaction']; - $deposit['type'] = 'DEPOSIT'; - $deposit['crdr'] = 'DEBIT'; - $deposit['account_id'] = $account_id; - $deposit['customer_id'] = null; - $deposit['lease_id'] = null; + $deposit += + array('type' => 'DEPOSIT', + 'crdr' => 'DEBIT', + 'account_id' => $account_id, + 'customer_id' => null, + 'lease_id' => null, + ); // Save the list of IDs, so that we can mark their // deposit transaction after it has been created. @@ -201,10 +203,13 @@ class Transaction extends AppModel { // Establish the transaction as a close $close =& $data['Transaction']; - $close['type'] = 'CLOSE'; - $close['account_id'] = null; - $close['customer_id'] = null; - $close['lease_id'] = null; + $close += + array('type' => 'CLOSE', + 'crdr' => null, + 'account_id' => null, + 'customer_id' => null, + 'lease_id' => null, + ); $ledger_ids = array(); $data['Entry'] = array(); @@ -246,6 +251,44 @@ class Transaction extends AppModel { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: addVoucher + * - Adds a new voucher transaction, which is money outflow + */ + + function addVoucher($data) { + $this->prEnter(compact('data', 'customer_id', 'lease_id')); + + // REVISIT : 20090804 + // NOT IMPLEMENTED AT ALL. Just cut and paste so far + return array('error' => true); + + // Establish the transaction as an voucher + $voucher =& $data['Transaction']; + $voucher += + array('type' => 'VOUCHER', + 'crdr' => 'DEBIT', + 'account_id' => $this->Account->accountPayableAccountID(), + 'customer_id' => null, + 'lease_id' => null, + ); + + // Go through the statement entries and flag as charges + foreach ($data['Entry'] AS &$entry) + $entry += array('type' => 'CHARGE', + 'crdr' => 'CREDIT', + ); + + $ids = $this->addTransaction($data['Transaction'], $data['Entry']); + if (isset($ids['transaction_id'])) + $ids['voucher_id'] = $ids['transaction_id']; + + return $this->prReturn($ids); + } + + /************************************************************************** ************************************************************************** ************************************************************************** @@ -353,7 +396,7 @@ class Transaction extends AppModel { * * - Entry (array) * - [MANDATORY] - * - type (CHARGE, PAYMENT) + * - type (CHARGE, DISBURSEMENT) * - account_id * - crdr * - amount @@ -466,7 +509,7 @@ class Transaction extends AppModel { array_flip(array('customer_id', 'lease_id'))); $se['comment'] = $entry['statement_entry_comment']; - // (PAYMENTS will have statement entries created below, when + // (DISBURSEMENTS will have statement entries created below, when // assigning credits, and DEPOSITS don't have statement entries) if ($transaction['type'] != 'INVOICE' && $subtype !== 'NSF') $se = null; @@ -556,8 +599,8 @@ class Transaction extends AppModel { ($transaction['type'] == 'RECEIPT' && !empty($transaction['charge_entry_id']) ? $transaction['charge_entry_id'] : null), - (!empty($transaction['payment_type']) - ? $transaction['payment_type'] + (!empty($transaction['disbursement_type']) + ? $transaction['disbursement_type'] : null), $transaction['customer_id'], $transaction['lease_id'] @@ -587,7 +630,7 @@ class Transaction extends AppModel { // Enter the NSF // This is the transaction pulling money from the bank account // and recording it in the NSF account. It has nothing to do - // with the customer statement (charges, payments, credits, etc). + // with the customer statement (charges, disbursements, credits, etc). $bounce_result = $this->addDeposit (array('Transaction' => array(), 'Entry' => array(array('tender_id' => null, @@ -637,20 +680,20 @@ class Transaction extends AppModel { $rollback['Transaction']['customer_id'] = $tender['Tender']['customer_id']; $rollback['Transaction']['amount'] = -1 * $tender['LedgerEntry']['amount']; - foreach ($nsf_ledger_entry['Transaction']['StatementEntry'] AS $payment) { - if ($payment['type'] === 'SURPLUS') { - $payment['type'] = 'VOID'; - $this->StatementEntry->id = $payment['id']; - $this->StatementEntry->saveField('type', $payment['type']); + foreach ($nsf_ledger_entry['Transaction']['StatementEntry'] AS $disbursement) { + if ($disbursement['type'] === 'SURPLUS') { + $disbursement['type'] = 'VOID'; + $this->StatementEntry->id = $disbursement['id']; + $this->StatementEntry->saveField('type', $disbursement['type']); } else { $rollback['Entry'][] = - array('type' => $payment['type'], - 'amount' => -1 * $payment['amount'], + array('type' => $disbursement['type'], + 'amount' => -1 * $disbursement['amount'], 'account_id' => $this->Account->nsfAccountID(), - 'customer_id' => $payment['customer_id'], - 'lease_id' => $payment['lease_id'], - 'charge_entry_id' => $payment['charge_entry_id'], + 'customer_id' => $disbursement['customer_id'], + 'lease_id' => $disbursement['lease_id'], + 'charge_entry_id' => $disbursement['charge_entry_id'], 'effective_date' => $stamp, ); } @@ -742,7 +785,7 @@ class Transaction extends AppModel { } elseif ($table == 'StatementEntry') { $squery['fields'] = array_merge($squery['fields'], - $this->StatementEntry->chargePaymentFields(true)); + $this->StatementEntry->chargeDisbursementFields(true)); } else { $squery['fields'][] = "SUM({$table}.amount) AS total"; diff --git a/site/views/accounts/collected.ctp b/site/views/accounts/collected.ctp index e918bb2..2a80012 100644 --- a/site/views/accounts/collected.ctp +++ b/site/views/accounts/collected.ctp @@ -164,7 +164,7 @@ echo $this->element('statement_entries', array //'grid_setup' => array('hiddengrid' => true), //'caption' => '', 'caption' => 'Collected ' . Inflector::pluralize($account['name']), - 'filter' => array('StatementEntry.type' => 'PAYMENT', + 'filter' => array('StatementEntry.type' => 'DISBURSEMENT', 'ChargeEntry.account_id' => $account['id']), 'exclude' => array('Account', 'Charge'), ), diff --git a/site/views/accounts/view.ctp b/site/views/accounts/view.ctp index c4b3f3d..897ab78 100644 --- a/site/views/accounts/view.ctp +++ b/site/views/accounts/view.ctp @@ -82,7 +82,7 @@ echo $this->element('ledger_entries', array "(". $current_ledger['name'] .")"), 'filter' => array('Ledger.id' => $current_ledger['id']), 'exclude' => array('Account', 'Amount', 'Cr/Dr', 'Balance', - empty($account['payments']) ? 'Tender' : null), + empty($account['receipts']) ? 'Tender' : null), 'include' => array('Debit', 'Credit', 'Sub-Total'), ))); @@ -100,7 +100,7 @@ echo $this->element('ledger_entries', array 'caption' => "Entire Ledger", 'filter' => array('Account.id' => $account['id']), 'exclude' => array('Account', 'Amount', 'Cr/Dr', 'Balance', - empty($account['payments']) ? 'Tender' : null), + empty($account['receipts']) ? 'Tender' : null), 'include' => array('Debit', 'Credit', 'Sub-Total'), ))); diff --git a/site/views/elements/statement_entries.ctp b/site/views/elements/statement_entries.ctp index 9494b87..61b9882 100644 --- a/site/views/elements/statement_entries.ctp +++ b/site/views/elements/statement_entries.ctp @@ -18,7 +18,7 @@ $cols['Unit'] = array('index' => 'Unit.name', 'formatter' => $cols['Comment'] = array('index' => 'StatementEntry.comment', 'formatter' => 'comment', 'width'=>150); $cols['Charge'] = array('index' => 'charge', 'formatter' => 'currency'); -$cols['Payment'] = array('index' => 'payment', 'formatter' => 'currency'); +$cols['Payment'] = array('index' => 'disbursement', 'formatter' => 'currency'); $cols['Applied'] = array('index' => "applied", 'formatter' => 'currency'); $cols['Sub-Total'] = array('index' => 'subtotal-balance', 'formatter' => 'currency', 'sortable' => false); diff --git a/site/views/ledgers/view.ctp b/site/views/ledgers/view.ctp index 3ae23b7..a8a00f5 100644 --- a/site/views/ledgers/view.ctp +++ b/site/views/ledgers/view.ctp @@ -72,7 +72,7 @@ echo $this->element('ledger_entries', array 'filter' => array('Ledger.id' => $ledger['id']), 'exclude' => array('Ledger', 'Account', 'Amount', 'Cr/Dr', 'Balance', - empty($account['payments']) ? 'Tender' : null), + empty($account['receipts']) ? 'Tender' : null), 'include' => array('Debit', 'Credit', 'Sub-Total'), ))); diff --git a/site/views/statement_entries/view.ctp b/site/views/statement_entries/view.ctp index 038afd6..9413c0f 100644 --- a/site/views/statement_entries/view.ctp +++ b/site/views/statement_entries/view.ctp @@ -59,12 +59,12 @@ echo $this->element('table', */ if (strtoupper($entry['type']) === 'CHARGE') { - $applied_caption = "Payments Applied"; + $applied_caption = "Disbursements Applied"; //$remaining_caption = "Charge Balance"; } else { - $applied_caption = "Applied to Charges"; - //$remaining_caption = "Payment Balance"; + $applied_caption = "Dispursed to Charges"; + //$remaining_caption = "Disbursement Balance"; } $remaining_caption = "Remaining Balance"; From 5247bb8db69f8f8f3240aca3d25dd11628c5d4ad Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 5 Aug 2009 02:59:09 +0000 Subject: [PATCH 481/717] Modified to use toggle for 'this' debug pr block, instead of independent show/hide git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@489 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_model.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/site/app_model.php b/site/app_model.php index 79b0b10..456b381 100644 --- a/site/app_model.php +++ b/site/app_model.php @@ -221,8 +221,7 @@ class AppModel extends Model { echo ' stack'.";\n"; echo " this "; - echo 's'."/"; - echo 'h'."/"; + echo 't'."/"; echo 'n'.";\n"; echo " $class "; From cca698d43720abfea02238e78b56b5dd65de847c Mon Sep 17 00:00:00 2001 From: abijah Date: Wed, 5 Aug 2009 07:54:57 +0000 Subject: [PATCH 482/717] Several changes in an effort to support charge reversals. I can't imagine this is all working flawlessly, as I'm not quite sure how it even _should_ work. git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@490 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 28 ++- .../statement_entries_controller.php | 53 +---- site/models/statement_entry.php | 199 ++++++++---------- site/models/transaction.php | 169 ++++++++++----- site/views/statement_entries/view.ctp | 2 +- site/views/transactions/view.ctp | 5 +- 6 files changed, 236 insertions(+), 220 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index c1864f5..434c952 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -961,10 +961,15 @@ DROP TABLE IF EXISTS `pmgr_transactions`; CREATE TABLE `pmgr_transactions` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `type` ENUM('INVOICE', - 'RECEIPT', - 'VOUCHER', - 'DEPOSIT', -- Probably should use VOUCHER for DEPOSIT + -- REVISIT : 20090804 + -- I'm not sure about most of these terms. + -- Just as long as they're distinct though... I can rename them later + `type` ENUM('INVOICE', -- Sales Invoice + 'RECEIPT', -- Actual receipt of monies + 'PURCHASE_INVOICE', -- Committment to pay + 'CREDIT_NOTE', -- Inverse of Sales Invoice + 'PAYMENT', -- Actual payment + 'DEPOSIT', 'CLOSE', -- Essentially an internal (not accounting) transaction -- 'CREDIT', -- 'REFUND', @@ -1066,11 +1071,16 @@ DROP TABLE IF EXISTS `pmgr_statement_entries`; CREATE TABLE `pmgr_statement_entries` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, - `type` ENUM('CHARGE', - 'DISBURSEMENT', - 'VOUCHER-PAYMENT', -- REVISIT: Make PAYMENT - 'SURPLUS', - 'WAIVER', + -- REVISIT : 20090804 + -- I'm not sure about most of these terms. + -- Just as long as they're distinct though... I can rename them later + `type` ENUM('CHARGE', -- Invoiced Charge to Customer + 'DISBURSEMENT', -- Disbursement of Receipt Funds + 'REVERSAL', -- Reversal of a charge + 'VOUCHER', -- Agreement to pay + 'PAYMENT', -- Payment of a Voucher + 'SURPLUS', -- Surplus Receipt Funds + 'WAIVER', -- Waived Charge -- REVISIT : 20090730 -- VOID is used for handling NSF and perhaps charge reversals. -- It's not clear this is the best way to handle these things. diff --git a/site/controllers/statement_entries_controller.php b/site/controllers/statement_entries_controller.php index b3d4599..4366ccb 100644 --- a/site/controllers/statement_entries_controller.php +++ b/site/controllers/statement_entries_controller.php @@ -191,7 +191,7 @@ class StatementEntriesController extends AppController { function waive($id) { $this->StatementEntry->waive($id); - //$this->redirect(array('action'=>'view', $id)); + $this->redirect(array('action'=>'view', $id)); } @@ -223,44 +223,6 @@ class StatementEntriesController extends AppController { $reconciled = $this->StatementEntry->reconciledEntries($id); - -/* // REVISIT : 20090711 */ -/* // It's not clear whether we should be able to reverse charges that have */ -/* // already been paid/cleared/reconciled. Certainly, that will be the */ -/* // case when someone has pre-paid and then moves out early. However, this */ -/* // will work well for items accidentally charged but not yet paid for. */ -/* if ((!$entry['DebitLedger']['Account']['trackable'] || */ -/* $stats['debit']['amount_reconciled'] == 0) && */ -/* (!$entry['CreditLedger']['Account']['trackable'] || */ -/* $stats['credit']['amount_reconciled'] == 0) */ - -/* && 0 */ - -/* ) */ -/* { */ -/* // Set up dynamic menu items */ -/* $this->sidemenu_links[] = */ -/* array('name' => 'Operations', 'header' => true); */ - -/* $this->sidemenu_links[] = */ -/* array('name' => 'Undo', */ -/* 'url' => array('action' => 'reverse', */ -/* $id)); */ -/* } */ - -/* if ($this->StatementEntry->Ledger->Account->type */ -/* ($entry['CreditLedger']['Account']['id']) == 'INCOME') */ -/* { */ -/* // Set up dynamic menu items */ -/* $this->sidemenu_links[] = */ -/* array('name' => 'Operations', 'header' => true); */ - -/* $this->sidemenu_links[] = */ -/* array('name' => 'Reverse', */ -/* 'url' => array('action' => 'reverse', */ -/* $id)); */ -/* } */ - $stats = $this->StatementEntry->stats($id); if (strtoupper($entry['StatementEntry']['type']) === 'CHARGE') @@ -269,16 +231,21 @@ class StatementEntriesController extends AppController { $stats = $stats['Disbursement']; - if (strtoupper($entry['StatementEntry']['type']) === 'CHARGE' && - $stats['balance'] > 0) { + if (strtoupper($entry['StatementEntry']['type']) === 'CHARGE') { // Set up dynamic menu items $this->sidemenu_links[] = array('name' => 'Operations', 'header' => true); $this->sidemenu_links[] = - array('name' => 'Waive Balance', - 'url' => array('action' => 'waive', + 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. diff --git a/site/models/statement_entry.php b/site/models/statement_entry.php index 8dce2cf..6495f72 100644 --- a/site/models/statement_entry.php +++ b/site/models/statement_entry.php @@ -22,7 +22,7 @@ class StatementEntry extends AppModel { ); - var $default_log_level = array('log' => 30, 'show' => 15); + //var $default_log_level = array('log' => 30, 'show' => 15); /************************************************************************** ************************************************************************** @@ -40,15 +40,12 @@ class StatementEntry extends AppModel { ($sum ? ')' : '') . ' AS charge' . ($sum ? 's' : ''), ($sum ? 'SUM(' : '') . - //"IF({$entry_name}.type IN('DISBURSEMENT', 'SURPLUS', 'WAIVER')," . - "IF({$entry_name}.type NOT IN('CHARGE', 'VOID')," . + "IF({$entry_name}.type NOT IN('CHARGE', 'PAYMENT', 'VOID')," . " {$entry_name}.amount, NULL)" . ($sum ? ')' : '') . ' AS disbursement' . ($sum ? 's' : ''), ($sum ? 'SUM(' : '') . - //"IF({$entry_name}.type = 'CHARGE', 1," . - //" IF({$entry_name}.type IN('DISBURSEMENT', 'SURPLUS', 'WAIVER'), -1, 0))" . - "IF({$entry_name}.type = 'VOID', 0," . + "IF({$entry_name}.type IN ('VOID', 'PAYMENT'), 0," . " IF({$entry_name}.type = 'CHARGE', 1, -1))" . " * IF({$entry_name}.amount, {$entry_name}.amount, 0)" . ($sum ? ')' : '') . ' AS balance', @@ -154,110 +151,80 @@ class StatementEntry extends AppModel { * function: reverse * - Reverses the charges * - * SAMPLE MOVE IN w/ PRE DISBURSEMENT - * DEPOSIT RENT A/R RECEIPT CHECK PETTY BANK - * ------- ------- ------- ------- ------- ------- ------- - * |25 | 25| | | | | - * | |20 20| | | | | - * | |20 20| | | | | - * | |20 20| | | | | - * | | |25 25| | | | - * | | |20 20| | | | - * | | |20 20| | | | - * | | |20 20| | | | - * | | | |85 85| | | - * | | | | |85 | 85| - - * MOVE OUT and REFUND FINAL MONTH - * DEPOSIT RENT C/P RECEIPT CHECK PETTY BANK - * ------- ------- ------- ------- ------- ------- ------- - * 25| | |25 | | | | t20 e20a - * | 20| |20 | | | | t20 e20b - - * -ONE REFUND CHECK- - * | | 25| |25 | | | t30 e30a - * | | 20| |20 | | | t30 e30b - * | | | 45| | | |45 t40 e40 - * -OR MULTIPLE- - * | | 15| |15 | | | t50a e50a - * | | | 15| | |15 | t60a e60a - * | | 30| |30 | | | t50b e50b - * | | | 30| | | |30 t60b e60b - * | | | | | | | - - -OPTION 1 - * |-25 | -25| | | | | - * | |-20 -20| | | | | - * | | |-25 -25| | | | - * | | |-20 -20| | | | - -OPTION 2 - * |-25 | | -25| | | | - * | |-20 | -20| | | | - * | | | |-15 | -15| | - * | | | |-30 | | -30| - * | | | | | | | - * */ - function reverse($ledger_entries, $stamp = null) { - $this->prEnter(compact('ledger_entries', 'stamp')); + function reverse($id, $stamp = null) { + $this->prEnter(compact('id', 'stamp')); - // If the user only wants to reverse one ID, we'll allow it - if (!is_array($ledger_entries)) - $ledger_entries = $this->find - ('all', array - ('contain' => false, - 'conditions' => array('Entry.id' => $ledger_entries))); + $ret = array(); - $A = new Account(); + // Get the basic information about the entry to be reversed. + $this->recursive = -1; + $charge = $this->read(null, $id); + $charge = $charge['StatementEntry']; - $ar_account_id = $A->accountReceivableAccountID(); - $receipt_account_id = $A->receiptAccountID(); + $voided_entry_transactions = array(); + $reconciled = $this->reconciledEntries($id); + $this->pr(21, compact('reconciled')); - $transaction_id = null; - foreach ($ledger_entries AS $entry) { - $entry = $entry['Entry']; - $amount = -1*$entry['amount']; + if ($reconciled) { + foreach ($reconciled['entries'] AS $entry) { + $voided_entry_transactions[$entry['DisbursementEntry']['transaction_id']] + = array_intersect_key($entry['DisbursementEntry'], + array('customer_id'=>1, 'lease_id'=>1)); - if (isset($entry['credit_account_id'])) - $refund_account_id = $entry['credit_account_id']; - elseif (isset($entry['CreditLedger']['Account']['id'])) - $refund_account_id = $entry['CreditLedger']['Account']['id']; - elseif (isset($entry['credit_ledger_id'])) - $refund_account_id = $this->Ledger->accountID($entry['credit_ledger_id']); - else - return $this->prReturn(null); + $this->del($entry['DisbursementEntry']['id']); + continue; - // post new refund in the income account - $ids = $A->postEntry - (array('transaction_id' => $transaction_id), - null, - array('debit_ledger_id' => $A->currentLedgerID($ar_account_id), - 'credit_ledger_id' => $A->currentLedgerID($refund_account_id), - 'effective_date' => $entry['effective_date'], - 'through_date' => $entry['through_date'], - 'amount' => $amount, - 'lease_id' => $entry['lease_id'], - 'customer_id' => $entry['customer_id'], - 'comment' => "Refund; Entry #{$entry['id']}", - ), - array('debit' => array - (array('Entry' => - array('id' => $entry['id'], - 'amount' => $amount))), - ) - ); - - if ($ids['error']) - return $this->prReturn(null); - $transaction_id = $ids['transaction_id']; - - $this->pr(15, compact('ids', 'amount', 'refund_account_id', 'ar_account_id'), - 'Posted Refund Ledger Entry'); + $DE = new StatementEntry(); + $DE->id = $entry['DisbursementEntry']['id']; + $DE->saveField('type', 'VOID'); + $DE->saveField('charge_entry_id', null); + } + $this->pr(17, compact('voided_entry_transactions')); } - return $this->prReturn(true); + // Query the stats to get the remaining balance + $stats = $this->stats($id); + + // Build a transaction + $reversal = array('Transaction' => array(), 'Entry' => array()); + $reversal['Transaction']['stamp'] = $stamp; + $reversal['Transaction']['comment'] = "Credit Note: Charge Reversal"; + + if ($charge['type'] !== 'CHARGE') + die("INTERNAL ERROR: REVERSAL ITEM IS NOT CHARGE"); + + // Add the charge reversal + $reversal['Entry'][] = + array('amount' => $stats['Charge']['total'], + 'account_id' => $charge['account_id'], + 'comment' => 'Charge Reversal', + ); + + // Record the reversal transaction + $result = $this->Transaction->addReversal + ($reversal, $id, $charge['customer_id'], $charge['lease_id']); + $this->pr(21, compact('result')); + $ret['reversal'] = $result; + if ($result['error']) + $ret['error'] = true; + + foreach ($voided_entry_transactions AS $transaction_id => $tx) { + $result = $this->assignCredits + (null, + $transaction_id, + null, + null, + $tx['customer_id'], + $tx['lease_id'] + ); + $this->pr(21, compact('result')); + $ret['assigned'][] = $result; + if ($result['error']) + $ret['error'] = true; + } + + return $this->prReturn($ret + array('error' => false)); } @@ -421,23 +388,27 @@ OPTION 2 // Next, establish credit from the newly added receipt $receipt_credit = null; if (!empty($receipt_id)) { - $lquery = $query; - $lquery['link'] = array('StatementEntry' => $lquery['link']); - $lquery['link'] += array('LedgerEntry' => - array('conditions' => - //array(LedgerEntry.'crdr'=>'DEBIT'), - array('LedgerEntry.account_id !=' => $this->Account->accountReceivableAccountID()), - )); - $lquery['fields'] = array('Transaction.id', 'Transaction.stamp', 'Transaction.amount', - 'LedgerEntry.account_id'); - // Very specific case here... no extra conditions - unset($lquery['conditions']); - $this->Transaction->id = $receipt_id; + $lquery = + array('link' => + array('StatementEntry', + 'LedgerEntry' => + array('conditions' => + array('LedgerEntry.account_id !=' => + $this->Account->accountReceivableAccountID()), + ), + ), + 'conditions' => array('Transaction.id' => $receipt_id), + 'fields' => array('Transaction.id', 'Transaction.stamp', 'Transaction.amount'), + ); $receipt_credit = $this->Transaction->find('first', $lquery); if (!$receipt_credit) die("INTERNAL ERROR: UNABLE TO LOCATE RECEIPT"); - $receipt_credit['balance'] = $receipt_credit['Transaction']['amount']; + //$reconciled = $this->reconciledEntries($id); + + $stats = $this->Transaction->stats($receipt_id); + $receipt_credit['balance'] = + $receipt_credit['Transaction']['amount'] - $stats['Disbursement']['total']; $this->pr(18, compact('receipt_credit'), "Receipt Credit Added"); diff --git a/site/models/transaction.php b/site/models/transaction.php index ffd51f5..8cb3666 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -139,6 +139,69 @@ class Transaction extends AppModel { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: addReversal + * - Adds a new charge reversal + */ + + function addReversal($data, $charge_id, $customer_id, $lease_id = null) { + $this->prEnter(compact('data', 'charge_id', 'customer_id', 'lease_id')); + + if (count($data['Entry']) != 1) + die("INTERNAL ERROR: Should be one Entry for addWaiver"); + + $data['Transaction']['type'] = 'CREDIT_NOTE'; + $data['Transaction']['charge_entry_id'] = $charge_id; + //$data['Entry'][0]['amount'] *= -1; + //$data['Entry'][0]['type'] = 'DISBURSEMENT'; + $ids = $this->addReceipt($data, $customer_id, $lease_id); + if (isset($ids['transaction_id'])) + $ids['reversal_id'] = $ids['transaction_id']; + +/* $new_charge_id = $ids['entries'][0]['StatementEntry']['statement_entry_id']; */ +/* $this->StatementEntry->id = $new_charge_id; */ +/* $this->StatementEntry->saveField('charge_entry_id', $charge_id); */ + return $this->prReturn($ids); + + + // Just make sure the transaction is marked as an INVOICE + // and that it goes to cover the specific charge. + //$data['Transaction']['type'] = 'INVOICE'; + $data['Transaction']['charge_entry_id'] = $charge_id; + + // In all other respects this works just like a receipt. + $ids = $this->addReceipt($data, $customer_id, $lease_id); + if (isset($ids['transaction_id'])) + $ids['reversal_id'] = $ids['transaction_id']; + + return $this->prReturn($ids); + + // Establish the transaction as an Invoice Reversal + $reversal =& $data['Transaction']; + $reversal += + array('type' => 'INVOICE', //'CREDIT_NOTE', + 'crdr' => 'CREDIT', + 'account_id' => $this->Account->accountReceivableAccountID(), + 'customer_id' => $customer_id, + 'lease_id' => $lease_id, + ); + + // Go through the statement entries and flag as reversals + foreach ($data['Entry'] AS &$entry) + $entry += array('type' => 'CHARGE', //'REVERSAL', + 'crdr' => 'DEBIT', + ); + + $ids = $this->addTransaction($data['Transaction'], $data['Entry']); + if (isset($ids['transaction_id'])) + $ids['reversal_id'] = $ids['transaction_id']; + + return $this->prReturn($ids); + } + + /************************************************************************** ************************************************************************** ************************************************************************** @@ -251,49 +314,11 @@ class Transaction extends AppModel { } - /************************************************************************** - ************************************************************************** - ************************************************************************** - * function: addVoucher - * - Adds a new voucher transaction, which is money outflow - */ - - function addVoucher($data) { - $this->prEnter(compact('data', 'customer_id', 'lease_id')); - - // REVISIT : 20090804 - // NOT IMPLEMENTED AT ALL. Just cut and paste so far - return array('error' => true); - - // Establish the transaction as an voucher - $voucher =& $data['Transaction']; - $voucher += - array('type' => 'VOUCHER', - 'crdr' => 'DEBIT', - 'account_id' => $this->Account->accountPayableAccountID(), - 'customer_id' => null, - 'lease_id' => null, - ); - - // Go through the statement entries and flag as charges - foreach ($data['Entry'] AS &$entry) - $entry += array('type' => 'CHARGE', - 'crdr' => 'CREDIT', - ); - - $ids = $this->addTransaction($data['Transaction'], $data['Entry']); - if (isset($ids['transaction_id'])) - $ids['voucher_id'] = $ids['transaction_id']; - - return $this->prReturn($ids); - } - - /************************************************************************** ************************************************************************** ************************************************************************** * function: addRefund - * - Adds a new refund transaction + * - Adds a new refund */ function addRefund($data, $customer_id, $lease_id = null) { @@ -303,20 +328,21 @@ class Transaction extends AppModel { // NOT IMPLEMENTED AT ALL. Just cut and paste so far return array('error' => true); - // Establish the transaction as an refund + // Establish the transaction as a Refund $refund =& $data['Transaction']; $refund += - array('type' => 'VOUCHER', - 'crdr' => 'DEBIT', - 'account_id' => $this->Account->accountReceivableAccountID(), + array('type' => 'CREDIT_NOTE', + 'crdr' => 'CREDIT', + 'account_id' => $this->Account->accountPayableAccountID(), 'customer_id' => $customer_id, 'lease_id' => $lease_id, ); - // Go through the statement entries and flag as charges + // Go through the statement entries and flag as vouchers foreach ($data['Entry'] AS &$entry) - $entry += array('type' => 'CHARGE', - 'crdr' => 'CREDIT', + $entry += array('type' => 'VOUCHER', + 'crdr' => 'DEBIT', + 'account_id' => $this->Account->accountReceivableAccountID(), ); $ids = $this->addTransaction($data['Transaction'], $data['Entry']); @@ -327,6 +353,44 @@ class Transaction extends AppModel { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: addPayment + * - Adds a new payment transaction, which is money outflow + */ + + function addPayment($data, $customer_id, $lease_id = null) { + $this->prEnter(compact('data', 'customer_id', 'lease_id')); + + // REVISIT : 20090804 + // NOT IMPLEMENTED AT ALL. Just cut and paste so far + return array('error' => true); + + // Establish the transaction as an payment + $payment =& $data['Transaction']; + $payment += + array('type' => 'PAYMENT', + 'crdr' => 'DEBIT', + 'account_id' => $this->Account->accountPayableAccountID(), + 'customer_id' => $customer_id, + 'lease_id' => $lease_id, + ); + + // Go through the statement entries and flag as payments + foreach ($data['Entry'] AS &$entry) + $entry += array('type' => 'PAYMENT', + 'crdr' => 'CREDIT', + ); + + $ids = $this->addTransaction($data['Transaction'], $data['Entry']); + if (isset($ids['transaction_id'])) + $ids['payment_id'] = $ids['transaction_id']; + + return $this->prReturn($ids); + } + + /************************************************************************** ************************************************************************** ************************************************************************** @@ -511,7 +575,9 @@ class Transaction extends AppModel { // (DISBURSEMENTS will have statement entries created below, when // assigning credits, and DEPOSITS don't have statement entries) - if ($transaction['type'] != 'INVOICE' && $subtype !== 'NSF') + if (($transaction['account_id'] != $this->Account->accountReceivableAccountID() && + $transaction['account_id'] != $this->Account->nsfAccountID()) || + $transaction['crdr'] != 'DEBIT') $se = null; // NSF transactions don't use LedgerEntries @@ -588,15 +654,14 @@ class Transaction extends AppModel { } } - if (($transaction['type'] == 'INVOICE' || - $transaction['type'] == 'RECEIPT') && - $subtype !== 'NSF' && !$ret['error']) { + if ($transaction['account_id'] == $this->Account->accountReceivableAccountID() + && !$ret['error']) { $result = $this->StatementEntry->assignCredits (null, - ($transaction['type'] == 'RECEIPT' + ($transaction['crdr'] == 'CREDIT' ? $ret['transaction_id'] : null), - ($transaction['type'] == 'RECEIPT' && !empty($transaction['charge_entry_id']) + ($transaction['crdr'] == 'CREDIT' && !empty($transaction['charge_entry_id']) ? $transaction['charge_entry_id'] : null), (!empty($transaction['disbursement_type']) diff --git a/site/views/statement_entries/view.ctp b/site/views/statement_entries/view.ctp index 9413c0f..8c59c84 100644 --- a/site/views/statement_entries/view.ctp +++ b/site/views/statement_entries/view.ctp @@ -25,7 +25,7 @@ $rows[] = array($Ttype, $html->link('#'.$transaction['id'], $transaction['id']))); $rows[] = array('Timestamp', FormatHelper::datetime($transaction['stamp'])); $rows[] = array('Effective', FormatHelper::date($entry['effective_date'])); -if (in_array($entry['type'], array('CHARGE', /*REVISIT 'VOUCHER-PAYMENT'*/))) +if (in_array($entry['type'], array('CHARGE', 'PAYMENT'))) $rows[] = array('Through', FormatHelper::date($entry['through_date'])); $rows[] = array('Type', $entry['type']); $rows[] = array('Amount', FormatHelper::currency($entry['amount'])); diff --git a/site/views/transactions/view.ctp b/site/views/transactions/view.ctp index e73b9ee..2f0b62f 100644 --- a/site/views/transactions/view.ctp +++ b/site/views/transactions/view.ctp @@ -67,7 +67,10 @@ echo '
    ' . "\n"; * Statement Entries */ -if ($transaction['type'] === 'INVOICE' || $transaction['type'] === 'RECEIPT') { +if ($transaction['type'] === 'INVOICE' || + $transaction['type'] === 'RECEIPT' || + $transaction['type'] === 'CREDIT_NOTE' + ) { echo $this->element('statement_entries', array (// Grid configuration 'config' => array From 4d62d7da73043003d68619b29ca98a93b82faa3b Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 6 Aug 2009 02:52:45 +0000 Subject: [PATCH 483/717] More work on refund. I'm going to skip the whole voucher/credit_note bit and simply present a page that lets the user enter a date, an account, and the amount to refund, recording 1 payment transaction. git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@491 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/customers_controller.php | 5 +- site/controllers/leases_controller.php | 22 ++++----- site/models/account.php | 1 + site/models/customer.php | 56 ++++++----------------- site/models/lease.php | 45 ++++++++++++++++++ site/models/statement_entry.php | 39 +++++++++++++--- site/models/transaction.php | 16 +++---- 7 files changed, 111 insertions(+), 73 deletions(-) diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 38d608d..9d5e813 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -203,8 +203,7 @@ class CustomersController extends AppController { //pr($customer); // Figure out the outstanding balances for this customer - $stats = $this->Customer->stats($id); - $outstanding_balance = $stats['balance']; + $outstanding_balance = $this->Customer->balance($id); $outstanding_deposit = $this->Customer->securityDepositBalance($id); // Figure out if this customer has any non-closed leases @@ -407,7 +406,7 @@ class CustomersController extends AppController { )); pr(compact('entries')); - $this->Customer->StatementEntry->reverse($entries); + $this->Customer->refund($entries); } diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index edc1231..75d6474 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -239,12 +239,14 @@ class LeasesController extends AppController { */ function refund($id) { - // Obtain the overall lease balance - $stats = $this->Lease->stats($id); - $outstanding_balance = $stats['balance']; + $this->Lease->refund($id); + $this->render('/fake'); +/* // Obtain the overall lease balance */ +/* $stats = $this->Lease->stats($id); */ +/* $outstanding_balance = $stats['balance']; */ - $this->set(compact('lease', 'title', - 'outstanding_balance')); +/* $this->set(compact('lease', 'title', */ +/* 'outstanding_balance')); */ } @@ -381,13 +383,9 @@ class LeasesController extends AppController { $this->set('charge_gaps', $this->Lease->rentChargeGaps($id)); $this->set('charge_through', $this->Lease->rentChargeThrough($id)); - // Obtain the overall lease balance - $this->Lease->statsMerge($lease['Lease'], - array('stats' => $this->Lease->stats($id))); - $outstanding_balance = $lease['Lease']['stats']['balance']; - - // Determine the lease security deposit - $outstanding_deposit = $this->Lease->securityDepositBalance($lease['Lease']['id']); + // 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 if (!isset($lease['Lease']['close_date'])) { diff --git a/site/models/account.php b/site/models/account.php index b32844c..c841db1 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -128,6 +128,7 @@ class Account extends AppModel { function nsfChargeAccountID() { return $this->nameToID('NSF Charge'); } function taxAccountID() { return $this->nameToID('Tax'); } function accountReceivableAccountID() { return $this->nameToID('A/R'); } + function accountPayableAccountID() { return $this->nameToID('A/P'); } function cashAccountID() { return $this->nameToID('Cash'); } function checkAccountID() { return $this->nameToID('Check'); } function moneyOrderAccountID() { return $this->nameToID('Money Order'); } diff --git a/site/models/customer.php b/site/models/customer.php index aa01afd..42ac10e 100644 --- a/site/models/customer.php +++ b/site/models/customer.php @@ -127,49 +127,6 @@ class Customer extends AppModel { } - /************************************************************************** - ************************************************************************** - ************************************************************************** - * function: details - * - Returns detail information for the customer - */ - - function details($id = null) { - $this->prEnter(compact('id')); - - // Query the DB for need information. - $customer = $this->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), - )); - - // Figure out the outstanding balance for this customer - $customer['stats'] = $this->stats($id); - - // Figure out the total security deposit for the current lease. - $customer['deposits'] = $this->securityDeposits($id); - - return $this->prReturn($customer); - } - - /************************************************************************** ************************************************************************** ************************************************************************** @@ -271,6 +228,19 @@ class Customer extends AppModel { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: balance + * - Returns the balance of money owed on the lease + */ + + function balance($id) { + $stats = $this->stats($id); + return $stats['balance']; + } + + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/models/lease.php b/site/models/lease.php index 42a7195..1b72947 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -464,6 +464,51 @@ class Lease extends AppModel { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * 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: 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']); + } + + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/models/statement_entry.php b/site/models/statement_entry.php index 6495f72..ef02fdc 100644 --- a/site/models/statement_entry.php +++ b/site/models/statement_entry.php @@ -24,29 +24,54 @@ class StatementEntry extends AppModel { //var $default_log_level = array('log' => 30, 'show' => 15); + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: debit/creditTypes + */ + + function debitTypes() { + return array('CHARGE', 'VOUCHER'); + } + + function creditTypes() { + return array('DISBURSEMENT', 'WAIVER', 'SURPLUS'); + } + + /************************************************************************** ************************************************************************** ************************************************************************** * function: chargeDisbursementFields */ - function chargeDisbursementFields($sum = false, $entry_name = 'StatementEntry') { + $charges = array('CHARGE', 'VOUCHER'); + $nulls = array('PAYMENT', 'VOID'); + + foreach ($charges AS &$enum) + $enum = "'" . $enum . "'"; + foreach ($nulls AS &$enum) + $enum = "'" . $enum . "'"; + + $charge_set = implode(", ", $charges); + $null_set = implode(", ", $nulls); + $fields = array ( ($sum ? 'SUM(' : '') . - "IF({$entry_name}.type = 'CHARGE'," . + "IF({$entry_name}.type IN ({$charge_set})," . " {$entry_name}.amount, NULL)" . ($sum ? ')' : '') . ' AS charge' . ($sum ? 's' : ''), ($sum ? 'SUM(' : '') . - "IF({$entry_name}.type NOT IN('CHARGE', 'PAYMENT', 'VOID')," . + "IF({$entry_name}.type NOT IN({$charge_set}, ${null_set})," . " {$entry_name}.amount, NULL)" . ($sum ? ')' : '') . ' AS disbursement' . ($sum ? 's' : ''), ($sum ? 'SUM(' : '') . - "IF({$entry_name}.type IN ('VOID', 'PAYMENT'), 0," . - " IF({$entry_name}.type = 'CHARGE', 1, -1))" . + "IF({$entry_name}.type IN ({$null_set}), 0," . + " IF({$entry_name}.type IN ({$charge_set}), 1, -1))" . " * IF({$entry_name}.amount, {$entry_name}.amount, 0)" . ($sum ? ')' : '') . ' AS balance', ); @@ -602,7 +627,7 @@ class StatementEntry extends AppModel { $charge_query['fields'] = array(); $charge_query['fields'][] = "SUM(StatementEntry.amount) AS total"; - $charge_query['conditions'][] = array('StatementEntry.type' => 'CHARGE'); + $charge_query['conditions'][] = array('StatementEntry.type' => array('CHARGE', 'VOUCHER')); $result = $this->find('first', $charge_query); $stats['Charge'] = $result[0]; @@ -688,4 +713,4 @@ class StatementEntry extends AppModel { return $this->prReturn($stats); } -} +} \ No newline at end of file diff --git a/site/models/transaction.php b/site/models/transaction.php index 8cb3666..f7df39f 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -332,17 +332,17 @@ class Transaction extends AppModel { $refund =& $data['Transaction']; $refund += array('type' => 'CREDIT_NOTE', - 'crdr' => 'CREDIT', - 'account_id' => $this->Account->accountPayableAccountID(), + 'crdr' => 'DEBIT', + 'account_id' => $this->Account->accountReceivableAccountID(), 'customer_id' => $customer_id, 'lease_id' => $lease_id, ); // Go through the statement entries and flag as vouchers foreach ($data['Entry'] AS &$entry) - $entry += array('type' => 'VOUCHER', - 'crdr' => 'DEBIT', - 'account_id' => $this->Account->accountReceivableAccountID(), + $entry += array('type' => 'VOUCHER', + 'crdr' => 'CREDIT', + 'account_id' => $this->Account->accountPayableAccountID(), ); $ids = $this->addTransaction($data['Transaction'], $data['Entry']); @@ -575,9 +575,9 @@ class Transaction extends AppModel { // (DISBURSEMENTS will have statement entries created below, when // assigning credits, and DEPOSITS don't have statement entries) - if (($transaction['account_id'] != $this->Account->accountReceivableAccountID() && - $transaction['account_id'] != $this->Account->nsfAccountID()) || - $transaction['crdr'] != 'DEBIT') + if (empty($transaction['customer_id']) || + ($transaction['account_id'] == $this->Account->accountReceivableAccountID() && + $transaction['crdr'] == 'CREDIT')) $se = null; // NSF transactions don't use LedgerEntries From 5a7b087ddc662eaa557cf460b145eef79ba6c3f5 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 6 Aug 2009 05:04:34 +0000 Subject: [PATCH 484/717] Added ability to format currency without a dollar sign (i.e. in raw numerical format). git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@492 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/helpers/format.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/views/helpers/format.php b/site/views/helpers/format.php index b32d920..976d26c 100644 --- a/site/views/helpers/format.php +++ b/site/views/helpers/format.php @@ -19,13 +19,13 @@ class FormatHelper extends AppHelper { true)); } - function currency($amount, $spans = false) { + function currency($amount, $spans = false, $dollar_sign = null) { if (!isset($amount)) return '-'; //return null; $currency = self::$number->currency($amount, - 'USD', + isset($dollar_sign) ? $dollar_sign : 'USD', $spans ? array('before'=>'', 'after'=>'') : array()); if ($spans) From e784931fa82bcedacb710b152f2e91989562805a Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 6 Aug 2009 05:11:58 +0000 Subject: [PATCH 485/717] Implemented refund, at least for the most part. Minor testing, but looks promising. Because of this change the customer account entries grid appears odd, with a refunds showing up as a 'Charge'. So, I'm toying with the idea of having entries show up as customer 'Debits' and 'Credits'. I don't know if this will cause user confusion, but we'll play with it for a while and see. It actually reminds me a bit (coming full circle) of the earliest implementations, which kept track of a lease on its own account/ledger, in which credit/debit would be the exact correct terms. git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@493 97e9348a-65ac-dc4b-aefc-98561f571b83 --- db/schema.sql | 3 +- site/controllers/leases_controller.php | 42 ++++- .../statement_entries_controller.php | 2 +- site/controllers/transactions_controller.php | 50 +++++- site/models/account.php | 4 + site/models/statement_entry.php | 67 ++++---- site/models/transaction.php | 31 ++-- site/views/accounts/collected.ctp | 2 +- site/views/elements/statement_entries.ctp | 5 +- site/views/leases/refund.ctp | 162 +++++++++++------- site/views/statement_entries/view.ctp | 2 +- site/views/transactions/view.ctp | 2 +- 12 files changed, 238 insertions(+), 134 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index 434c952..88f7eee 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -886,7 +886,7 @@ INSERT INTO `pmgr_accounts` (`type`, `name`) ('LIABILITY', 'A/P' ); INSERT INTO `pmgr_accounts` (`type`, `name`, `receipts`, `refunds`) VALUES - ('ASSET', 'Cash', 1, 1), + ('ASSET', 'Cash', 1, 0), ('ASSET', 'Check', 1, 0), ('ASSET', 'Money Order', 1, 0), ('ASSET', 'ACH', 1, 0), @@ -1079,6 +1079,7 @@ CREATE TABLE `pmgr_statement_entries` ( 'REVERSAL', -- Reversal of a charge 'VOUCHER', -- Agreement to pay 'PAYMENT', -- Payment of a Voucher + 'REFUND', -- Payment due to refund 'SURPLUS', -- Surplus Receipt Funds 'WAIVER', -- Waived Charge -- REVISIT : 20090730 diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index 75d6474..3187622 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -239,14 +239,42 @@ class LeasesController extends AppController { */ function refund($id) { - $this->Lease->refund($id); - $this->render('/fake'); -/* // Obtain the overall lease balance */ -/* $stats = $this->Lease->stats($id); */ -/* $outstanding_balance = $stats['balance']; */ + $lease = $this->Lease->find + ('first', array + ('contain' => array + (// Models + 'Unit' => array('fields' => array('id', 'name')), + 'Customer' => array('fields' => array('id', 'name')), + ), -/* $this->set(compact('lease', 'title', */ -/* 'outstanding_balance')); */ + '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')); } diff --git a/site/controllers/statement_entries_controller.php b/site/controllers/statement_entries_controller.php index 4366ccb..48ef075 100644 --- a/site/controllers/statement_entries_controller.php +++ b/site/controllers/statement_entries_controller.php @@ -225,7 +225,7 @@ class StatementEntriesController extends AppController { $stats = $this->StatementEntry->stats($id); - if (strtoupper($entry['StatementEntry']['type']) === 'CHARGE') + if (in_array(strtoupper($entry['StatementEntry']['type']), $this->StatementEntry->debitTypes())) $stats = $stats['Charge']; else $stats = $stats['Disbursement']; diff --git a/site/controllers/transactions_controller.php b/site/controllers/transactions_controller.php index 2173e54..4f091a8 100644 --- a/site/controllers/transactions_controller.php +++ b/site/controllers/transactions_controller.php @@ -283,17 +283,61 @@ class TransactionsController extends AppController { if (empty($data['Lease']['id'])) $data['Lease']['id'] = null; + pr(compact('data')); + if (!$this->Transaction->addReceipt($data, $data['Customer']['id'], - $this->data['Lease']['id'])) { + $data['Lease']['id'])) { $this->Session->setFlash("WRITE OFF FAILED", true); // REVISIT 20090706: // Until we can work out the session problems, // just die. - die("

    RECEIPT FAILED

    "); + die("

    WRITE-OFF FAILED

    "); + } + + $this->render('/fake'); + + // 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('

    THIS IS NOT A POST FOR SOME REASON

    '); + 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 20090706: + // Until we can work out the session problems, + // just die. + die("

    REFUND FAILED

    "); } - pr(compact('data')); $this->render('/fake'); // Return to viewing the lease/customer diff --git a/site/models/account.php b/site/models/account.php index c841db1..ba55f32 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -207,6 +207,10 @@ class Account extends AppModel { return $this->relatedAccounts('deposits', array('order' => 'name')); } + function refundAccounts() { + return $this->relatedAccounts('refunds', array('order' => 'name')); + } + /************************************************************************** ************************************************************************** diff --git a/site/models/statement_entry.php b/site/models/statement_entry.php index ef02fdc..754eb32 100644 --- a/site/models/statement_entry.php +++ b/site/models/statement_entry.php @@ -31,13 +31,17 @@ class StatementEntry extends AppModel { */ function debitTypes() { - return array('CHARGE', 'VOUCHER'); + return array('CHARGE', 'PAYMENT', 'REFUND'); } function creditTypes() { return array('DISBURSEMENT', 'WAIVER', 'SURPLUS'); } + function voidTypes() { + return array('VOID'); + } + /************************************************************************** ************************************************************************** @@ -46,32 +50,36 @@ class StatementEntry extends AppModel { */ function chargeDisbursementFields($sum = false, $entry_name = 'StatementEntry') { - $charges = array('CHARGE', 'VOUCHER'); - $nulls = array('PAYMENT', 'VOID'); + $debits = $this->debitTypes(); + $credits = $this->creditTypes(); + $voids = $this->voidTypes(); - foreach ($charges AS &$enum) + foreach ($debits AS &$enum) $enum = "'" . $enum . "'"; - foreach ($nulls AS &$enum) + foreach ($credits AS &$enum) + $enum = "'" . $enum . "'"; + foreach ($voids AS &$enum) $enum = "'" . $enum . "'"; - $charge_set = implode(", ", $charges); - $null_set = implode(", ", $nulls); + $debit_set = implode(", ", $debits); + $credit_set = implode(", ", $credits); + $void_set = implode(", ", $voids); $fields = array ( ($sum ? 'SUM(' : '') . - "IF({$entry_name}.type IN ({$charge_set})," . + "IF({$entry_name}.type IN ({$debit_set})," . " {$entry_name}.amount, NULL)" . ($sum ? ')' : '') . ' AS charge' . ($sum ? 's' : ''), ($sum ? 'SUM(' : '') . - "IF({$entry_name}.type NOT IN({$charge_set}, ${null_set})," . + "IF({$entry_name}.type IN({$credit_set})," . " {$entry_name}.amount, NULL)" . ($sum ? ')' : '') . ' AS disbursement' . ($sum ? 's' : ''), ($sum ? 'SUM(' : '') . - "IF({$entry_name}.type IN ({$null_set}), 0," . - " IF({$entry_name}.type IN ({$charge_set}), 1, -1))" . + "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', ); @@ -263,23 +271,16 @@ class StatementEntry extends AppModel { function reconciledSetQuery($set, $query) { $this->queryInit($query); - if ($set == 'CHARGE' || $set == 'DISBURSEMENT') - $query['conditions'][] = array('StatementEntry.type' => $set); + 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"); - if ($set == 'CHARGE') - $query['link']['DisbursementEntry'] = array('fields' => array("SUM(DisbursementEntry.amount) AS reconciled")); - if ($set == 'DISBURSEMENT') - $query['link']['ChargeEntry'] = array('fields' => array("SUM(ChargeEntry.amount) AS reconciled")); - + $query['conditions'][] = array('StatementEntry.type' => $set); $query['group'] = 'StatementEntry.id'; - // REVISIT: TESTING - //$query['link']['DisbursementEntry'] = array('fields' => array("(`DisbursementEntry.amount`+0) AS reconciled")); - //$query['group'] = null; - // END REVISIT - return $query; } @@ -337,9 +338,9 @@ class StatementEntry extends AppModel { $query['conditions'][] = array('StatementEntry.id' => $id); - if ($this->data['StatementEntry']['type'] == 'CHARGE') + if (in_array($this->data['StatementEntry']['type'], $this->debitTypes())) $query['link']['DisbursementEntry'] = array(); - if ($this->data['StatementEntry']['type'] == 'DISBURSEMENT') + if (in_array($this->data['StatementEntry']['type'], $this->creditTypes())) $query['link']['ChargeEntry'] = array(); return $query; @@ -372,7 +373,7 @@ class StatementEntry extends AppModel { $charge_ids = null, $disbursement_type = null, $customer_id = null, $lease_id = null) { - $this->prFunctionLevel(25); + //$this->prFunctionLevel(25); $this->prEnter(compact('query', 'receipt_id', 'charge_ids', 'disbursement_type', 'customer_id', 'lease_id')); @@ -450,15 +451,19 @@ class StatementEntry extends AppModel { $lquery['conditions'][] = array('StatementEntry.lease_id' => $lease_id); } $lquery['order'] = 'StatementEntry.effective_date ASC'; - $charges = $this->reconciledSet('CHARGE', $lquery, true); - $this->pr(18, compact('charges'), - "Outstanding Charges Determined"); + $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"); + } // Initialize our list of used credits $used_credits = array(); // Work through all unpaid charges, applying disbursements as we go - foreach ($charges['entries'] AS $charge) { + foreach ($charges AS $charge) { $this->pr(20, compact('charge'), 'Process Charge'); @@ -627,7 +632,7 @@ class StatementEntry extends AppModel { $charge_query['fields'] = array(); $charge_query['fields'][] = "SUM(StatementEntry.amount) AS total"; - $charge_query['conditions'][] = array('StatementEntry.type' => array('CHARGE', 'VOUCHER')); + $charge_query['conditions'][] = array('StatementEntry.type' => $this->debitTypes()); $result = $this->find('first', $charge_query); $stats['Charge'] = $result[0]; diff --git a/site/models/transaction.php b/site/models/transaction.php index f7df39f..5f3b7ad 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -324,28 +324,21 @@ class Transaction extends AppModel { function addRefund($data, $customer_id, $lease_id = null) { $this->prEnter(compact('data', 'customer_id', 'lease_id')); - // REVISIT : 20090804 - // NOT IMPLEMENTED AT ALL. Just cut and paste so far - return array('error' => true); - - // Establish the transaction as a Refund + // Establish the transaction as a Refund. This is just like a + // Payment, except instead of paying out of the account payable, + // it comes from the customer credit in the account receivable. + // Someday, perhaps we'll just issue a Credit Note or similar, + // but for now, a refund means it's time to actually PAY. $refund =& $data['Transaction']; $refund += - array('type' => 'CREDIT_NOTE', - 'crdr' => 'DEBIT', - 'account_id' => $this->Account->accountReceivableAccountID(), - 'customer_id' => $customer_id, - 'lease_id' => $lease_id, - ); + array('account_id' => $this->Account->accountReceivableAccountID()); - // Go through the statement entries and flag as vouchers + // Also, to make it clear to the user, we flag as a REFUND + // even though that type works and operates just as PAYMENT foreach ($data['Entry'] AS &$entry) - $entry += array('type' => 'VOUCHER', - 'crdr' => 'CREDIT', - 'account_id' => $this->Account->accountPayableAccountID(), - ); + $entry += array('type' => 'REFUND'); - $ids = $this->addTransaction($data['Transaction'], $data['Entry']); + $ids = $this->addPayment($data, $customer_id, $lease_id); if (isset($ids['transaction_id'])) $ids['refund_id'] = $ids['transaction_id']; @@ -363,10 +356,6 @@ class Transaction extends AppModel { function addPayment($data, $customer_id, $lease_id = null) { $this->prEnter(compact('data', 'customer_id', 'lease_id')); - // REVISIT : 20090804 - // NOT IMPLEMENTED AT ALL. Just cut and paste so far - return array('error' => true); - // Establish the transaction as an payment $payment =& $data['Transaction']; $payment += diff --git a/site/views/accounts/collected.ctp b/site/views/accounts/collected.ctp index 2a80012..c70768d 100644 --- a/site/views/accounts/collected.ctp +++ b/site/views/accounts/collected.ctp @@ -166,7 +166,7 @@ echo $this->element('statement_entries', array 'caption' => 'Collected ' . Inflector::pluralize($account['name']), 'filter' => array('StatementEntry.type' => 'DISBURSEMENT', 'ChargeEntry.account_id' => $account['id']), - 'exclude' => array('Account', 'Charge'), + 'exclude' => array('Account', 'Charge', 'Type'), ), )); diff --git a/site/views/elements/statement_entries.ctp b/site/views/elements/statement_entries.ctp index 61b9882..997c504 100644 --- a/site/views/elements/statement_entries.ctp +++ b/site/views/elements/statement_entries.ctp @@ -17,8 +17,9 @@ $cols['Unit'] = array('index' => 'Unit.name', 'formatter' => $cols['Comment'] = array('index' => 'StatementEntry.comment', 'formatter' => 'comment', 'width'=>150); -$cols['Charge'] = array('index' => 'charge', 'formatter' => 'currency'); -$cols['Payment'] = array('index' => 'disbursement', 'formatter' => 'currency'); +$cols['Type'] = array('index' => 'StatementEntry.type', 'formatter' => 'enum', 'width'=>120); +$cols['Debit'] = array('index' => 'charge', 'formatter' => 'currency'); +$cols['Credit'] = array('index' => 'disbursement', 'formatter' => 'currency'); $cols['Applied'] = array('index' => "applied", 'formatter' => 'currency'); $cols['Sub-Total'] = array('index' => 'subtotal-balance', 'formatter' => 'currency', 'sortable' => false); diff --git a/site/views/leases/refund.ctp b/site/views/leases/refund.ctp index 31ba0a7..bdf06ed 100644 --- a/site/views/leases/refund.ctp +++ b/site/views/leases/refund.ctp @@ -1,74 +1,106 @@ ' . "\n"; -echo '

    Perform Bank Deposit

    ' . "\n"; -echo '

    Make sure to select the checkboxes below for only those types of currency (Cash, Check, etc) which you intend to actually deposit (you can see all the individual items by dropping down the list below the checkbox). Then, select the Deposit Account where you will make the deposit, and click "Perform Deposit" to close the books on the selected currency types and reset them to a zero balance. On the next page, you will be provided with a deposit slip to prepare the actual deposit.' . "\n"; +echo '

    ' . "\n"; +echo '

    Issue Refund

    ' . "\n"; +echo '

    Enter the amount to refund, and the account to pay it from.' . "\n"; echo '


    ' . "\n"; -//pr(compact('tillableAccount', 'depositableAccount')); - -echo $form->create(null, array('id' => 'deposit-form', - 'url' => array('controller' => 'accounts', - 'action' => 'deposit'))); - -foreach ($tillableAccount AS $acct) { - //$acct = $acct['Account']; - - echo "\n"; - echo $form->input('Tillable.Ledger.'.$acct['CurrentLedger']['id'].'.checked', - array(//'label' => $acct['Account']['name'], - 'type' => 'checkbox', - 'checked' => true, - 'value' => true, - 'label' => (" I have exactly " . - FormatHelper::currency($acct['Account']['stats']['Ledger']['balance']) . - " in " . ($acct['Account']['name'] === 'Cash' - ? 'Cash' - : Inflector::pluralize($acct['Account']['name'])) . - " and will be depositing it all.") - )); - echo "\n"; - echo $form->input('Tillable.Ledger.'.$acct['CurrentLedger']['id'].'.amount', - array('type' => 'hidden', - 'value' => $acct['Account']['stats']['Ledger']['balance'], - )); - echo "\n"; - echo $form->input('Tillable.Ledger.'.$acct['CurrentLedger']['id'].'.account_id', - array('type' => 'hidden', - 'value' => $acct['Account']['id'], - )); - echo "\n"; - echo $form->input('Tillable.Ledger.'.$acct['CurrentLedger']['id'].'.account_name', - array('type' => 'hidden', - 'value' => $acct['Account']['name'], - )); - echo "\n"; - - $grid_div_id = 'ledger_entries'.$acct['CurrentLedger']['id'].'-list'; - echo $this->element('ledger_entries', array - (// Element configuration - 'ledger_id' => $acct['CurrentLedger']['id'], - 'no_account' => true, - - // Grid configuration - 'config' => array - ( - 'grid_div_id' => $grid_div_id, - 'caption' => ('Items in '.$acct['Account']['name'].' Ledger'), - 'grid_setup' => array('hiddengrid' => true), - ), - )); +if (isset($lease)) { + $customer = $lease['Customer']; + $unit = $lease['Unit']; } -$options = array(); -foreach ($depositableAccount AS $acct) { - $options[$acct['Account']['id']] = $acct['Account']['name']; +if (isset($customer['Customer'])) + $customer = $customer['Customer']; + +if (isset($lease['Lease'])) + $lease = $lease['Lease']; + +// We're not actually using a grid to select the customer / lease +// but we could/should be, and the result would be selection-text +echo ('

    ' . + '' . "\n"); + +echo ('' . + ' ' . + '' . "\n"); + +if (isset($lease)) + echo ('' . + ' ' . + '' . "\n"); + +echo ('' . + ' ' . + '' . "\n"); + +echo ('
    ' . $customer['name'] . '' . '(Customer #' . $customer['id'] . ')' . '
    ' . 'Unit ' . $unit['name'] . '' . '(Lease #' . $lease['number'] . ')' . '
    Refundable Balance:' . FormatHelper::currency($balance) . '
    ' . + '
    ' . "\n"); + + +echo $form->create(null, array('id' => 'refund-form', + 'url' => array('controller' => 'transactions', + 'action' => 'postRefund'))); + + +// REVISIT : 20090805 +// Add Tender information to log specifically _how_ refund was paid. + +echo $this->element('form_table', + array('class' => "item refund transaction entry", + //'with_name_after' => ':', + 'field_prefix' => 'Transaction', + 'fields' => array + ("stamp" => array('opts' => + array('type' => 'text'), + 'between' => 'Now', + ), + "amount" => array('prefix' => 'Entry.0', + 'opts' => + array('value' => + FormatHelper::currency($balance, false, ''), + ), + ), + "account_id" => array('prefix' => 'Entry.0', + 'name' => 'Account', + 'opts' => + array('options' => $refundAccounts, + 'value' => $defaultAccount, + ), + ), + "comment" => array('opts' => array('size' => 50), + ), + ))) . "\n"; + +echo $form->input("Customer.id", + array('type' => 'hidden', + 'value' => $customer['id'])) . "\n"; + +if (isset($lease['id'])) + echo $form->input("Lease.id", + array('type' => 'hidden', + 'value' => $lease['id'])) . "\n"; + +echo $form->end('Issue Refund'); +?> + + + +
    diff --git a/site/views/statement_entries/view.ctp b/site/views/statement_entries/view.ctp index 8c59c84..d7f677e 100644 --- a/site/views/statement_entries/view.ctp +++ b/site/views/statement_entries/view.ctp @@ -63,7 +63,7 @@ if (strtoupper($entry['type']) === 'CHARGE') { //$remaining_caption = "Charge Balance"; } else { - $applied_caption = "Dispursed to Charges"; + $applied_caption = "Disbursed to Charges"; //$remaining_caption = "Disbursement Balance"; } diff --git a/site/views/transactions/view.ctp b/site/views/transactions/view.ctp index 2f0b62f..5099bd9 100644 --- a/site/views/transactions/view.ctp +++ b/site/views/transactions/view.ctp @@ -69,7 +69,7 @@ echo '
    ' . "\n"; if ($transaction['type'] === 'INVOICE' || $transaction['type'] === 'RECEIPT' || - $transaction['type'] === 'CREDIT_NOTE' + $transaction['type'] === 'PAYMENT' ) { echo $this->element('statement_entries', array (// Grid configuration From f3eaa40ea524880131b5a57e0fe32330909d0beb Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 6 Aug 2009 09:27:09 +0000 Subject: [PATCH 486/717] Added ability to edit a unit, except for sort/walk order. To handle those things we'll need to: save unit's old sort/walk position; adjust down (by one) all unit positions greater than the old position; adjust up (by one) all unit positions greater than or equal to the new unit position; update the unit's position. I'm not going to worry about it right now. git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@494 97e9348a-65ac-dc4b-aefc-98561f571b83 --- requirements.txt | 14 ++--- site/controllers/units_controller.php | 75 +++++++++++++++++++++++++++ site/models/unit.php | 61 ++++++++++++++++++++-- site/views/units/edit.ctp | 27 ++++++++++ 4 files changed, 167 insertions(+), 10 deletions(-) create mode 100644 site/views/units/edit.ctp diff --git a/requirements.txt b/requirements.txt index 3a41f4f..9903a40 100644 --- a/requirements.txt +++ b/requirements.txt @@ -50,19 +50,19 @@ Operations to be functional X - Assess NSF Fees X - Determine Lease Paid-Through status - Report: List of customers overdue - - Flag unit as overlocked - - Flag unit as evicting - - Flag unit as normal status - - Flag unit as dirty + X - Flag unit as overlocked + X - Flag unit as evicting + X - Flag unit as normal status + X - Flag unit as dirty - Enter notes when communicating with Customer X - Accept pre-payments X - Record Customer Move-Out from Unit ? - Record utilization of Security Deposit - - Record issuing of a refund + X - Record issuing of a refund - Record Deposit into Petty Cash - Record Payment from Petty Cash to expenses - - Record Petty Cash to refund. - ? - Write Off Bad Debt + X - Record Petty Cash to refund. + X - Write Off Bad Debt X - Perform a Deposit X - Close the Books (nightly / weekly, etc) X - Determine Rents Collected for a given period. diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index 1a9c96a..699d23a 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -236,6 +236,10 @@ class UnitsController extends AppController { $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[] = @@ -249,6 +253,10 @@ class UnitsController extends AppController { if (isset($unit['CurrentLease']['id']) && !isset($unit['CurrentLease']['close_date'])) { + $this->sidemenu_links[] = + array('name' => 'Charge', 'url' => array('controller' => 'leases', + 'action' => 'invoice', + $unit['CurrentLease']['id'])); $this->sidemenu_links[] = array('name' => 'Payment', 'url' => array('controller' => 'customers', 'action' => 'receipt', @@ -261,4 +269,71 @@ class UnitsController extends AppController { '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)); + + // For debugging, only if the redirects above have been + // commented out, otherwise this section isn't reached. + $this->render('/fake'); + return; + } + + 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')); + } + + } diff --git a/site/models/unit.php b/site/models/unit.php index a5abd89..9e2396b 100644 --- a/site/models/unit.php +++ b/site/models/unit.php @@ -27,6 +27,8 @@ class Unit extends AppModel { 'Lease', ); + //var $default_log_level = array('log' => 30, 'show' => 15); + /************************************************************************** ************************************************************************** ************************************************************************** @@ -50,7 +52,7 @@ class Unit extends AppModel { } function occupiedEnumValue() { - return statusValue('OCCUPIED'); + return $this->statusValue('OCCUPIED'); } function conditionOccupied() { @@ -68,18 +70,71 @@ class Unit extends AppModel { return ('Unit.status <= ' . $this->statusValue('UNAVAILABLE')); } + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * 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) { + 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; - //pr(compact('id', 'status')); $this->saveField('status', $status); + return $this->prReturn(true); } + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/views/units/edit.ctp b/site/views/units/edit.ctp new file mode 100644 index 0000000..22e389b --- /dev/null +++ b/site/views/units/edit.ctp @@ -0,0 +1,27 @@ +' . "\n"; + +echo $form->create('Unit', array('action' => 'edit')) . "\n"; +echo $form->input('id') . "\n"; + +echo($this->element + ('form_table', + array('class' => 'item unit detail', + 'caption' => isset($this->data['Unit']) ? 'Edit Unit' : 'New Unit', + 'fields' => array + ('name' => true, + 'unit_size_id' => true, + 'status' => array('opts' => + array('options' => $statusEnums, + ), + ), + 'deposit' => true, + 'rent' => true, + 'comment' => true, + ))) . "\n"); + +echo $form->submit('Update') . "\n"; +echo $form->submit('Cancel', array('name' => 'cancel')) . "\n"; +echo $form->end() . "\n"; +echo '
    ' . "\n"; From 58c4f28956dc6b265518cd8fe7a00105f8b43411 Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 6 Aug 2009 18:06:57 +0000 Subject: [PATCH 487/717] Added mechanism to do a full replacement of specified post parameters, instead of just merging. git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@495 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/site/app_controller.php b/site/app_controller.php index 9d306a5..b791b17 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -189,17 +189,26 @@ class AppController extends Controller { // 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['post']) && !empty($params['dynamic_post'])) - $params['post'] = $params['dynamic_post']; - elseif (!empty($params['post']) && !empty($params['dynamic_post'])) - //$params['post'] = array_merge($params['post'], $params['dynamic_post']); + 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'])) @@ -682,7 +691,7 @@ class AppController extends Controller { function gridDataPostProcessLinks(&$params, &$model, &$records, $links) { // Don't create any links if ordered not to. - if (isset($params['nolinks'])) + if (isset($params['post']['nolinks'])) return; foreach ($links AS $table => $fields) { From 8f7cf202e5e58c499e0cb400abed5719b102a53e Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 6 Aug 2009 18:08:21 +0000 Subject: [PATCH 488/717] Fixed the customer selection update for receipts, and added a mechanism to automatically update the oustanding charges grid after entering the receipt. git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@496 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/customers_controller.php | 20 +++++++++++++------- site/views/customers/receipt.ctp | 19 +++++++++++++++---- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 9d5e813..cd6c997 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -423,8 +423,8 @@ class CustomersController extends AppController { $this->layout = null; $this->autoLayout = false; $this->autoRender = false; - //Configure::write('debug', '0'); - //header("Content-type: text/xml;charset=utf-8"); + Configure::write('debug', '0'); + header("Content-type: text/xml;charset=utf-8"); App::import('Helper', 'Xml'); $xml = new XmlHelper(); @@ -432,16 +432,22 @@ class CustomersController extends AppController { // Find the unreconciled entries, then manipulate the structure // slightly to accomodate the format necessary for XML Helper. $unreconciled = $this->Customer->unreconciledCharges($id); + + foreach ($unreconciled['entries'] AS &$entry) + $entry = array_intersect_key($entry['StatementEntry'], + array('id'=>1)); + $unreconciled = array('entries' => - array_intersect_key($unreconciled['debit'], - array('entry'=>1, 'balance'=>1))); + array('entry' => $unreconciled['entries'], + 'balance' => $unreconciled['summary']['balance'])); // XML Helper will dump an empty tag if the array is empty - if (!count($unreconciled['entries']['entry'])) + if (empty($unreconciled['entries']['entry'])) unset($unreconciled['entries']['entry']); - //pr($unreconciled); - //$reconciled = $cust->reconcileNewStatementEntry($cust_id, 'credit', $amount); +/* pr(compact('unreconciled')); */ +/* echo htmlspecialchars($xml->serialize($unreconciled)); */ +/* $this->render('/fake'); */ $opts = array(); //$opts['format'] = 'tags'; diff --git a/site/views/customers/receipt.ctp b/site/views/customers/receipt.ctp index 113995b..9a7e6cf 100644 --- a/site/views/customers/receipt.ctp +++ b/site/views/customers/receipt.ctp @@ -70,6 +70,8 @@ function showResponse(responseText, statusText) { if (statusText == 'success') { // get a clean slate //resetForm(); + // REVISIT : 20090806 Add to resetForm() + updateCharges($("#customer-id").val()); } else { alert('not successful??'); @@ -109,8 +111,6 @@ function onRowSelect(grid_id, customer_id) { $(grid_id).getCell(customer_id, 'Customer-id') + ''); $("#receipt-customer-name").html($(grid_id).getCell(customer_id, 'Customer-name')); - $("#receipt-balance").html("Calculating..."); - $("#receipt-charges-caption").html("Please Wait..."); // Hide the "no customer" message and show the current customer $(".customer-selection-invalid").hide(); @@ -227,7 +227,10 @@ function switchPaymentType(paymentid_base, paymentid, radioid) { function updateChargesGrid(idlist) { - $('#charge-entries-jqGrid').setPostDataItem('idlist', serialize(idlist)); + var dynamic_post = new Array(); + dynamic_post['idlist'] = idlist; + + $('#charge-entries-jqGrid').setPostDataItem('dynamic_post_replace', serialize(dynamic_post)); $('#charge-entries-jqGrid') .setGridParam({ page: 1 }) .trigger("reloadGrid"); @@ -239,6 +242,8 @@ function updateCharges(id) { url += '/'+id; $('#charge-entries-jqGrid').clearGridData(); + $("#receipt-balance").html("Calculating..."); + $("#receipt-charges-caption").html("Please Wait..."); $.ajax({ type: "GET", @@ -252,7 +257,13 @@ function updateCharges(id) { $('#receipt-balance').html(fmtCurrency($('entries',xml).attr('balance'))); $("#receipt-charges-caption").html("Outstanding Charges"); updateChargesGrid(ids); - } + }, + error: function(XMLHttpRequest, textStatus, errorThrown) { +/* alert('ERROR'); */ +/* $('#debug').html('

    request
    '+escape(XMLHttpRequest)); */ +/* $('#debug').append('

    status
    '+escape(textStatus)); */ +/* $('#debug').append('

    error
    '+escape(errorThrown)); */ + } }); } From a69a56c7157763c064baebb43b3b6b290248dabd Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 6 Aug 2009 18:08:55 +0000 Subject: [PATCH 489/717] Fixed the button text for new customers git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@497 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/customers/edit.ctp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/views/customers/edit.ctp b/site/views/customers/edit.ctp index 9b66f61..96dd79f 100644 --- a/site/views/customers/edit.ctp +++ b/site/views/customers/edit.ctp @@ -251,7 +251,7 @@ echo($this->element 'comment' => true, ))) . "\n"); -echo $form->submit('Update') . "\n"; +echo $form->submit(isset($this->data['Customer']) ? 'Update' : 'Add New Customer') . "\n"; ?>

    @@ -268,7 +268,7 @@ echo $form->submit('Update') . "\n"; submit('Update') . "\n"; +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 '
    ' . "\n"; From d75cd10f490c27712bb85bc488ad3d8bf56d1f0d Mon Sep 17 00:00:00 2001 From: abijah Date: Thu, 6 Aug 2009 20:17:02 +0000 Subject: [PATCH 490/717] Added in internal error function, since the die() statements were hard to spot, and certainly not user friendly for the end user. git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@498 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/config/bootstrap.php | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/site/config/bootstrap.php b/site/config/bootstrap.php index 2c89c74..005be55 100644 --- a/site/config/bootstrap.php +++ b/site/config/bootstrap.php @@ -31,6 +31,39 @@ * You can also use this to include or require any files in your application. * */ + +function INTERNAL_ERROR($message) { + echo '
    '; + echo '

    INTERNAL ERROR:

    '; + echo '

    ' . $message . '

    '; + echo '

    This error was not caused by anything that you did wrong.'; + echo '
    It is a problem within the application itself and should be reported to the administrator.

    '; + + // Print out the entire stack trace + echo "
    Stack Trace:
      "; + $trace = debug_backtrace(false); + 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("
    1. $bfile:$bline (" . ($bclas ? "$bclas::$bfunc" : "entry point") . ")
    2. \n"); + } + echo '
    '; + + echo '
    '; + 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) From 1dd0b1486153be5473046d6b44ea29bbc74a6da5 Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 7 Aug 2009 00:10:28 +0000 Subject: [PATCH 491/717] More work with security deposits, reversals, and balances. I've tried to work many different corner cases, but know that not everything has been tested. I think the next steps for testing will be to put in some real data. git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@499 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/leases_controller.php | 2 - .../controllers/ledger_entries_controller.php | 10 + .../statement_entries_controller.php | 34 ++- site/models/lease.php | 16 +- site/models/statement_entry.php | 266 +++++++++--------- site/models/transaction.php | 55 +--- site/views/customers/view.ctp | 2 +- site/views/leases/view.ctp | 2 +- site/views/transactions/view.ctp | 1 + 9 files changed, 199 insertions(+), 189 deletions(-) diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index 3187622..c52f982 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -172,8 +172,6 @@ class LeasesController extends AppController { ); $this->redirect($this->data['redirect']); - $this->autoRender = false; - return; } if (!isset($id)) diff --git a/site/controllers/ledger_entries_controller.php b/site/controllers/ledger_entries_controller.php index 3d7fbb0..c41a482 100644 --- a/site/controllers/ledger_entries_controller.php +++ b/site/controllers/ledger_entries_controller.php @@ -16,6 +16,16 @@ class LedgerEntriesController extends AppController { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: index / current / past / all + * - Creates a list of ledger entries + */ + + function index() { $this->gridView('All Ledger Entries'); } + + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/controllers/statement_entries_controller.php b/site/controllers/statement_entries_controller.php index 48ef075..26bbd86 100644 --- a/site/controllers/statement_entries_controller.php +++ b/site/controllers/statement_entries_controller.php @@ -16,6 +16,16 @@ class StatementEntriesController extends AppController { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: index / current / past / all + * - Creates a list of statement entries + */ + + function index() { $this->gridView('All Statement Entries'); } + + /************************************************************************** ************************************************************************** ************************************************************************** @@ -232,14 +242,24 @@ class StatementEntriesController extends AppController { if (strtoupper($entry['StatementEntry']['type']) === 'CHARGE') { - // Set up dynamic menu items - $this->sidemenu_links[] = - array('name' => 'Operations', 'header' => true); - $this->sidemenu_links[] = - array('name' => 'Reverse', - 'url' => array('action' => 'reverse', - $id)); + $reversal = $this->StatementEntry->find + ('first', + array('link' => array('DisbursementEntry'), + 'conditions' => array(array('StatementEntry.id' => $id), + array('DisbursementEntry.type' => 'REVERSAL')), + )); + + // Set up dynamic menu items + if (empty($reversal) || $stats['balance'] > 0) + $this->sidemenu_links[] = + array('name' => 'Operations', 'header' => true); + + if (empty($reversal)) + $this->sidemenu_links[] = + array('name' => 'Reverse', + 'url' => array('action' => 'reverse', + $id)); if ($stats['balance'] > 0) $this->sidemenu_links[] = diff --git a/site/models/lease.php b/site/models/lease.php index 1b72947..3785fbf 100644 --- a/site/models/lease.php +++ b/site/models/lease.php @@ -99,9 +99,9 @@ class Lease extends AppModel { // Since security deposits are being released, this also means // any unpaid (or only partially paid) security deposit should - // have the remaining balance simply waived. + // have the remaining balance reversed. if ($charge['StatementEntry']['balance'] > 0) - $this->StatementEntry->waive($charge['StatementEntry']['id'], $stamp); + $this->StatementEntry->reverse($charge['StatementEntry']['id'], true, $stamp); $release['Entry'][] = array('amount' => $charge['StatementEntry']['reconciled'], @@ -521,10 +521,14 @@ class Lease extends AppModel { if (!$id) return $this->prReturn(null); - $this->queryInit($query); - $query['conditions'][] = array('StatementEntry.lease_id' => $id); - $stats = $this->StatementEntry->stats(null, $query); - return $this->prReturn($stats); + $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); } } diff --git a/site/models/statement_entry.php b/site/models/statement_entry.php index 754eb32..6de75b4 100644 --- a/site/models/statement_entry.php +++ b/site/models/statement_entry.php @@ -35,7 +35,7 @@ class StatementEntry extends AppModel { } function creditTypes() { - return array('DISBURSEMENT', 'WAIVER', 'SURPLUS'); + return array('DISBURSEMENT', 'WAIVER', 'REVERSAL', 'SURPLUS'); } function voidTypes() { @@ -143,7 +143,7 @@ class StatementEntry extends AppModel { ************************************************************************** ************************************************************************** * function: waive - * - Waives the charges + * - Waives the charge balance * */ function waive($id, $stamp = null) { @@ -154,6 +154,9 @@ class StatementEntry extends AppModel { $charge = $this->read(null, $id); $charge = $charge['StatementEntry']; + if ($charge['type'] !== 'CHARGE') + INTERNAL_ERROR("Waiver item is not CHARGE."); + // Query the stats to get the remaining balance $stats = $this->stats($id); @@ -162,9 +165,6 @@ class StatementEntry extends AppModel { $waiver['Transaction']['stamp'] = $stamp; $waiver['Transaction']['comment'] = "Charge Waiver"; - if ($charge['type'] !== 'CHARGE') - die("INTERNAL ERROR: WAIVER ITEM IS NOT CHARGE"); - // Add the charge waiver $waiver['Entry'][] = array('amount' => $stats['Charge']['balance'], @@ -185,7 +185,7 @@ class StatementEntry extends AppModel { * - Reverses the charges * */ - function reverse($id, $stamp = null) { + function reverse($id, $balance = false, $stamp = null) { $this->prEnter(compact('id', 'stamp')); $ret = array(); @@ -195,12 +195,18 @@ class StatementEntry extends AppModel { $charge = $this->read(null, $id); $charge = $charge['StatementEntry']; + if ($charge['type'] !== 'CHARGE') + INTERNAL_ERROR("Reversal item is not CHARGE."); + $voided_entry_transactions = array(); $reconciled = $this->reconciledEntries($id); $this->pr(21, compact('reconciled')); - if ($reconciled) { + if ($reconciled && !$balance) { foreach ($reconciled['entries'] AS $entry) { + if ($entry['DisbursementEntry']['type'] === 'REVERSAL') + INTERNAL_ERROR("Charge has already been reversed"); + $voided_entry_transactions[$entry['DisbursementEntry']['transaction_id']] = array_intersect_key($entry['DisbursementEntry'], array('customer_id'=>1, 'lease_id'=>1)); @@ -224,12 +230,9 @@ class StatementEntry extends AppModel { $reversal['Transaction']['stamp'] = $stamp; $reversal['Transaction']['comment'] = "Credit Note: Charge Reversal"; - if ($charge['type'] !== 'CHARGE') - die("INTERNAL ERROR: REVERSAL ITEM IS NOT CHARGE"); - // Add the charge reversal $reversal['Entry'][] = - array('amount' => $stats['Charge']['total'], + array('amount' => $stats['Charge']['balance'], 'account_id' => $charge['account_id'], 'comment' => 'Charge Reversal', ); @@ -285,7 +288,7 @@ class StatementEntry extends AppModel { } function reconciledSet($set, $query = null, $unrec = false, $if_rec_include_partial = false) { - //$this->prFunctionLevel(16); + //$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); @@ -338,10 +341,14 @@ class StatementEntry extends AppModel { $query['conditions'][] = array('StatementEntry.id' => $id); - if (in_array($this->data['StatementEntry']['type'], $this->debitTypes())) + if (in_array($this->data['StatementEntry']['type'], $this->debitTypes())) { $query['link']['DisbursementEntry'] = array(); - if (in_array($this->data['StatementEntry']['type'], $this->creditTypes())) + $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; } @@ -387,29 +394,39 @@ class StatementEntry extends AppModel { $ret = array(); - // First, find all known credits - $lquery = $query; - $lquery['conditions'][] = array('StatementEntry.type' => 'SURPLUS'); - // REVISIT : 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"); + // First, find all known credits, unless this call is to make + // credit adjustments to a specific charge + // REVISIT : 20090806 + // If the theory below is correct, we should only search for + // explicit credits if we don't have a receipt_id + if (empty($charge_ids)) { + $lquery = $query; + $lquery['conditions'][] = array('StatementEntry.type' => 'SURPLUS'); + // REVISIT : 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 { + if (empty($receipt_id)) + INTERNAL_ERROR("Can't make adjustments to a charge without a receipt ID."); + } // Next, establish credit from the newly added receipt $receipt_credit = null; @@ -428,7 +445,7 @@ class StatementEntry extends AppModel { ); $receipt_credit = $this->Transaction->find('first', $lquery); if (!$receipt_credit) - die("INTERNAL ERROR: UNABLE TO LOCATE RECEIPT"); + INTERNAL_ERROR("Unable to locate receipt."); //$reconciled = $this->reconciledEntries($id); @@ -462,6 +479,13 @@ class StatementEntry extends AppModel { // Initialize our list of used credits $used_credits = array(); + // REVISIT : 20090806 + // Testing a theory. We should never have + // explicit credits, as well as a new receipt, + // and yet have outstanding charges. + if (!empty($credits) && !empty($receipt_credit) && !empty($charges)) + INTERNAL_ERROR("Explicit credits that haven't already been applied."); + // Work through all unpaid charges, applying disbursements as we go foreach ($charges AS $charge) { @@ -473,21 +497,21 @@ class StatementEntry extends AppModel { // will handle everything just fine. However, this // just saves extra processing if/when there is no // means to resolve a charge anyway. - if (count($credits) == 0 && empty($receipt_credit['balance'])) { + if (empty($credits) && empty($receipt_credit['balance'])) { $this->pr(17, 'No more available credits'); break; } $charge['balance'] = $charge['StatementEntry']['balance']; while ($charge['balance'] > 0 && - (count($credits) || !empty($receipt_credit['balance']))) { + (!empty($credits) || !empty($receipt_credit['balance']))) { $this->pr(20, compact('charge'), 'Attempt Charge Reconciliation'); // Use explicit credits before using implicit credits // (Not sure it matters though). - if (count($credits)) { + if (!empty($credits)) { // Peel off the first credit available $credit =& $credits[0]; $disbursement_date = $credit['StatementEntry']['effective_date']; @@ -519,14 +543,14 @@ class StatementEntry extends AppModel { $this->pr(20, compact('credit'), ($credit['balance'] > 0 ? 'Utilized' : 'Exhausted') . - (count($credits) ? ' Credit' : ' Receipt')); + (!empty($credits) ? ' Credit' : ' Receipt')); if ($credit['balance'] < 0) die("HOW DID WE END UP WITH NEGATIVE SURPLUS BALANCE?"); // If we've exhausted the credit, get it out of the // available credit pool (but keep track of it for later). - if ($credit['balance'] <= 0 && count($credits)) + if ($credit['balance'] <= 0 && !empty($credits)) $used_credits[] = array_shift($credits); // Add a disbursement that uses the available credit to pay the charge @@ -588,21 +612,37 @@ class StatementEntry extends AppModel { if (!empty($receipt_credit['balance'])) { $credit =& $receipt_credit; - $this->pr(18, compact('credit'), - 'Create Explicit Credit'); + $explicit_credit = $this->find + ('first', array('contain' => false, + 'conditions' => + array(array('transaction_id' => $credit['Transaction']['id']), + array('type' => 'SURPLUS')), + )); - $result = $this->addStatementEntry - (array('type' => 'SURPLUS', - 'account_id' => $credit['LedgerEntry']['account_id'], - 'amount' => $credit['balance'], - 'effective_date' => $credit['Transaction']['stamp'], - 'transaction_id' => $credit['Transaction']['id'], - 'customer_id' => $customer_id, - 'lease_id' => $lease_id, - )); - $ret['Credit'] = $result; - if ($result['error']) - $ret['error'] = true; + if (empty($explicit_credit)) { + $this->pr(18, compact('credit'), + 'Create Explicit Credit'); + + $result = $this->addStatementEntry + (array('type' => 'SURPLUS', + 'account_id' => $credit['LedgerEntry']['account_id'], + 'amount' => $credit['balance'], + 'effective_date' => $credit['Transaction']['stamp'], + 'transaction_id' => $credit['Transaction']['id'], + 'customer_id' => $customer_id, + 'lease_id' => $lease_id, + )); + $ret['Credit'] = $result; + if ($result['error']) + $ret['error'] = true; + } + else { + $this->pr(18, compact('explicit_credit', 'credit'), + 'Update Explicit Credit'); + $EC = new StatementEntry(); + $EC->id = $explicit_credit['StatementEntry']['id']; + $EC->saveField('amount', $credit['balance']); + } } return $this->prReturn($ret + array('error' => false)); @@ -616,6 +656,7 @@ class StatementEntry extends AppModel { * - Returns summary data from the requested statement entry */ function stats($id = null, $query = null) { + $this->prFunctionLevel(array('log' => 19, 'show' => 10)); $this->prEnter(compact('id', 'query')); $this->queryInit($query); @@ -625,80 +666,51 @@ class StatementEntry extends AppModel { if (isset($id)) $query['conditions'][] = array('StatementEntry.id' => $id); - // Determine the total in charges - $charge_query = $query; - unset($charge_query['link']['ChargeEntry']); - unset($charge_query['link']['DisbursementEntry']); + $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(); + } - $charge_query['fields'] = array(); - $charge_query['fields'][] = "SUM(StatementEntry.amount) AS total"; - $charge_query['conditions'][] = array('StatementEntry.type' => $this->debitTypes()); - $result = $this->find('first', $charge_query); - $stats['Charge'] = $result[0]; + $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('charge_query', 'result'), - 'Charges'); + $this->pr(17, compact('this_query', 'result'), $this_name.'s'); - // Tally the amount actually _paid_ to those charges - $charge_disbursement_query = $charge_query; - $charge_disbursement_query['link']['DisbursementEntry'] = array('fields' => array()); - $charge_disbursement_query['fields'] = array(); - $charge_disbursement_query['fields'][] = "COALESCE(SUM(DisbursementEntry.amount),0) AS paid"; - $charge_disbursement_query['conditions'][] = array('DisbursementEntry.type' => 'DISBURSEMENT'); - $result = $this->find('first', $charge_disbursement_query); - $stats['Charge'] += $result[0]; - - $this->pr(17, compact('charge_disbursement_query', 'result'), - 'Charge Disbursements'); + // 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]; - // Tally the amount of charges that have been waived - $charge_waiver_query = $charge_query; - $charge_waiver_query['link']['DisbursementEntry'] = array('fields' => array()); - $charge_waiver_query['fields'] = array(); - $charge_waiver_query['fields'][] = "COALESCE(SUM(DisbursementEntry.amount),0) AS waived"; - $charge_waiver_query['conditions'][] = array('DisbursementEntry.type' => 'WAIVER'); - $result = $this->find('first', $charge_waiver_query); - $stats['Charge'] += $result[0]; - - $this->pr(17, compact('charge_waiver_query', 'result'), - 'Charge Waivers'); + $this->pr(17, compact('that_query', 'result'), "{$this_name}s: $that_type"); + $stats[$this_name]['reconciled'] += $stats[$this_name][$lc_that_type]; + } - // Compute some summary information for charges - $stats['Charge']['reconciled'] = - $stats['Charge']['paid'] + $stats['Charge']['waived']; - $stats['Charge']['balance'] = - $stats['Charge']['total'] - $stats['Charge']['reconciled']; - if (!isset($stats['Charge']['balance'])) - $stats['Charge']['balance'] = 0; - - - // Determine the total in disbursements, including those which - // are charge waivers and those that do not even reconcile - // to charges (i.e. they are surplus disbursements). - $disbursement_query = $query; - unset($disbursement_query['link']['DisbursementEntry']); - $disbursement_query['link']['ChargeEntry'] = array('fields' => array()); - - $disbursement_query['fields'] = array(); - $disbursement_query['fields'][] = "SUM(StatementEntry.amount) AS total"; - $disbursement_query['fields'][] = "COALESCE(SUM(IF(ChargeEntry.id IS NULL, 0, StatementEntry.amount)), 0) AS charged"; - $disbursement_query['fields'][] = "COALESCE(SUM(IF(ChargeEntry.id IS NULL, StatementEntry.amount, 0)), 0) AS surplus"; - - $disbursement_query['conditions'][] = array('StatementEntry.type' => array('DISBURSEMENT', 'WAIVER', 'SURPLUS')); - $result = $this->find('first', $disbursement_query); - $stats['Disbursement'] = $result[0]; - - $this->pr(17, compact('disbursement_query', 'result'), - 'Disbursements'); - - // Compute some summary information for disbursements. - // Add a reconciled field just for consistency with Charge. - $stats['Disbursement']['reconciled'] = - $stats['Disbursement']['charged']; - $stats['Disbursement']['balance'] = - $stats['Disbursement']['total'] - $stats['Disbursement']['reconciled']; - if (!isset($stats['Disbursement']['balance'])) - $stats['Disbursement']['balance'] = 0; + // 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 @@ -711,7 +723,7 @@ class StatementEntry extends AppModel { // stats with respect to a particular account. // It represents the difference between inflow // and outflow from that account. - $stats['account_balance'] = $stats['Charge']['paid'] - $stats['Disbursement']['total']; + $stats['account_balance'] = $stats['Charge']['reconciled'] - $stats['Disbursement']['total']; if (!isset($stats['account_balance'])) $stats['account_balance'] = 0; diff --git a/site/models/transaction.php b/site/models/transaction.php index 5f3b7ad..ca2f0d0 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -128,7 +128,7 @@ class Transaction extends AppModel { // Just make sure the disbursement(s) are marked as waivers // and that they go to cover the specific charge. $data['Transaction']['disbursement_type'] = 'WAIVER'; - $data['Transaction']['charge_entry_id'] = $charge_id; + $data['Transaction']['assign_charge_entry_id'] = $charge_id; // In all other respects this is just a receipt. $ids = $this->addReceipt($data, $customer_id, $lease_id); @@ -150,54 +150,19 @@ class Transaction extends AppModel { $this->prEnter(compact('data', 'charge_id', 'customer_id', 'lease_id')); if (count($data['Entry']) != 1) - die("INTERNAL ERROR: Should be one Entry for addWaiver"); + die("INTERNAL ERROR: Should be one Entry for addReversal"); + // Just make sure the disbursement(s) are marked as reversals + // and that they go to cover the specific charge. $data['Transaction']['type'] = 'CREDIT_NOTE'; - $data['Transaction']['charge_entry_id'] = $charge_id; - //$data['Entry'][0]['amount'] *= -1; - //$data['Entry'][0]['type'] = 'DISBURSEMENT'; + $data['Transaction']['disbursement_type'] = 'REVERSAL'; + $data['Transaction']['assign_charge_entry_id'] = $charge_id; + + // In all other respects this is just a receipt. $ids = $this->addReceipt($data, $customer_id, $lease_id); if (isset($ids['transaction_id'])) $ids['reversal_id'] = $ids['transaction_id']; -/* $new_charge_id = $ids['entries'][0]['StatementEntry']['statement_entry_id']; */ -/* $this->StatementEntry->id = $new_charge_id; */ -/* $this->StatementEntry->saveField('charge_entry_id', $charge_id); */ - return $this->prReturn($ids); - - - // Just make sure the transaction is marked as an INVOICE - // and that it goes to cover the specific charge. - //$data['Transaction']['type'] = 'INVOICE'; - $data['Transaction']['charge_entry_id'] = $charge_id; - - // In all other respects this works just like a receipt. - $ids = $this->addReceipt($data, $customer_id, $lease_id); - if (isset($ids['transaction_id'])) - $ids['reversal_id'] = $ids['transaction_id']; - - return $this->prReturn($ids); - - // Establish the transaction as an Invoice Reversal - $reversal =& $data['Transaction']; - $reversal += - array('type' => 'INVOICE', //'CREDIT_NOTE', - 'crdr' => 'CREDIT', - 'account_id' => $this->Account->accountReceivableAccountID(), - 'customer_id' => $customer_id, - 'lease_id' => $lease_id, - ); - - // Go through the statement entries and flag as reversals - foreach ($data['Entry'] AS &$entry) - $entry += array('type' => 'CHARGE', //'REVERSAL', - 'crdr' => 'DEBIT', - ); - - $ids = $this->addTransaction($data['Transaction'], $data['Entry']); - if (isset($ids['transaction_id'])) - $ids['reversal_id'] = $ids['transaction_id']; - return $this->prReturn($ids); } @@ -650,8 +615,8 @@ class Transaction extends AppModel { ($transaction['crdr'] == 'CREDIT' ? $ret['transaction_id'] : null), - ($transaction['crdr'] == 'CREDIT' && !empty($transaction['charge_entry_id']) - ? $transaction['charge_entry_id'] + ($transaction['crdr'] == 'CREDIT' && !empty($transaction['assign_charge_entry_id']) + ? $transaction['assign_charge_entry_id'] : null), (!empty($transaction['disbursement_type']) ? $transaction['disbursement_type'] diff --git a/site/views/customers/view.ctp b/site/views/customers/view.ctp index 76a6c1b..bd6908c 100644 --- a/site/views/customers/view.ctp +++ b/site/views/customers/view.ctp @@ -84,7 +84,7 @@ echo $this->element('statement_entries', array 'filter' => array('Customer.id' => $customer['Customer']['id'], 'type !=' => 'VOID'), 'exclude' => array('Customer'), - 'sort_column' => 'Date', + 'sort_column' => 'Effective', 'sort_order' => 'DESC', ))); diff --git a/site/views/leases/view.ctp b/site/views/leases/view.ctp index 57a0f5a..7eb7d3f 100644 --- a/site/views/leases/view.ctp +++ b/site/views/leases/view.ctp @@ -88,7 +88,7 @@ echo $this->element('statement_entries', array 'filter' => array('Lease.id' => $lease['id']), 'include' => array('Through'), 'exclude' => array('Customer', 'Lease', 'Unit'), - 'sort_column' => 'Date', + 'sort_column' => 'Effective', 'sort_order' => 'DESC', ))); diff --git a/site/views/transactions/view.ctp b/site/views/transactions/view.ctp index 5099bd9..f86b275 100644 --- a/site/views/transactions/view.ctp +++ b/site/views/transactions/view.ctp @@ -69,6 +69,7 @@ echo '
    ' . "\n"; if ($transaction['type'] === 'INVOICE' || $transaction['type'] === 'RECEIPT' || + $transaction['type'] === 'CREDIT_NOTE' || $transaction['type'] === 'PAYMENT' ) { echo $this->element('statement_entries', array From 2e36d463294c7d40770cc404e1777c9b6448670c Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 7 Aug 2009 03:55:01 +0000 Subject: [PATCH 492/717] Minor tweaks, a shame for checkin r500 :-( git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@500 97e9348a-65ac-dc4b-aefc-98561f571b83 --- requirements.txt | 2 +- scripts/sitelink2pmgr.pl | 19 +++++++++++++++++++ site/controllers/accounts_controller.php | 15 ++++++++------- site/models/statement_entry.php | 2 +- site/models/transaction.php | 4 ++-- site/views/accounts/collected.ctp | 2 +- 6 files changed, 32 insertions(+), 12 deletions(-) diff --git a/requirements.txt b/requirements.txt index 9903a40..fe668e5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -57,7 +57,7 @@ Operations to be functional - Enter notes when communicating with Customer X - Accept pre-payments X - Record Customer Move-Out from Unit - ? - Record utilization of Security Deposit + X - Record utilization of Security Deposit X - Record issuing of a refund - Record Deposit into Petty Cash - Record Payment from Petty Cash to expenses diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index f81c5ba..75edd3f 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -1466,6 +1466,25 @@ addRow('double_entries', { }); +###################################################################### +## Debug ... work from scratch +if (defined $work_from_scratch) { + # delete $newdb{'tables'}{'contacts'}{'rows'}; + # delete $newdb{'tables'}{'contacts_methods'}{'rows'}; + # delete $newdb{'tables'}{'contacts_addresses'}{'rows'}; + # delete $newdb{'tables'}{'contacts_emails'}{'rows'}; + # delete $newdb{'tables'}{'contacts_phones'}{'rows'}; + delete $newdb{'tables'}{'contacts_customers'}{'rows'}; + delete $newdb{'tables'}{'customers'}{'rows'}; + delete $newdb{'tables'}{'double_entries'}{'rows'}; + delete $newdb{'tables'}{'leases'}{'rows'}; + delete $newdb{'tables'}{'ledger_entries'}{'rows'}; + delete $newdb{'tables'}{'statement_entries'}{'rows'}; + delete $newdb{'tables'}{'tenders'}{'rows'}; + delete $newdb{'tables'}{'transactions'}{'rows'}; +} + + ###################################################################### ## Build the Database diff --git a/site/controllers/accounts_controller.php b/site/controllers/accounts_controller.php index c43dfa3..e7d9c0f 100644 --- a/site/controllers/accounts_controller.php +++ b/site/controllers/accounts_controller.php @@ -138,17 +138,18 @@ class AccountsController extends AppController { $this->redirect(array('action'=>'index')); } - $payment_accounts = $this->Account->collectableAccounts(); - //$payment_accounts[$this->Account->nameToID('Closing')] = 'Closing'; - //$payment_accounts[$this->Account->nameToID('Equity')] = 'Equity'; - $default_accounts = array_diff_key($this->Account->receiptAccounts(), - array($this->Account->concessionAccountID() => 1)); - $this->set(compact('payment_accounts', 'default_accounts')); - $this->Account->recursive = -1; $account = $this->Account->read(null, $id); $account = $account['Account']; + $payment_accounts = $this->Account->collectableAccounts(); + //$payment_accounts[$this->Account->nameToID('Closing')] = 'Closing'; + //$payment_accounts[$this->Account->nameToID('Equity')] = 'Equity'; + //$payment_accounts[$id] = 'Reversals'; + $default_accounts = array_diff_key($this->Account->receiptAccounts(), + array($this->Account->concessionAccountID() => 1)); + $this->set(compact('payment_accounts', 'default_accounts')); + $title = ($account['name'] . ': Collected Report'); $this->set(compact('account', 'title')); } diff --git a/site/models/statement_entry.php b/site/models/statement_entry.php index 6de75b4..c8bad09 100644 --- a/site/models/statement_entry.php +++ b/site/models/statement_entry.php @@ -186,7 +186,7 @@ class StatementEntry extends AppModel { * */ function reverse($id, $balance = false, $stamp = null) { - $this->prEnter(compact('id', 'stamp')); + $this->prEnter(compact('id', 'balance', 'stamp')); $ret = array(); diff --git a/site/models/transaction.php b/site/models/transaction.php index ca2f0d0..4e4de98 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -123,7 +123,7 @@ class Transaction extends AppModel { $this->prEnter(compact('data', 'charge_id', 'customer_id', 'lease_id')); if (count($data['Entry']) != 1) - die("INTERNAL ERROR: Should be one Entry for addWaiver"); + INTERNAL_ERROR("Should be one Entry for addWaiver"); // Just make sure the disbursement(s) are marked as waivers // and that they go to cover the specific charge. @@ -150,7 +150,7 @@ class Transaction extends AppModel { $this->prEnter(compact('data', 'charge_id', 'customer_id', 'lease_id')); if (count($data['Entry']) != 1) - die("INTERNAL ERROR: Should be one Entry for addReversal"); + INTERNAL_ERROR("Should be one Entry for addReversal"); // Just make sure the disbursement(s) are marked as reversals // and that they go to cover the specific charge. diff --git a/site/views/accounts/collected.ctp b/site/views/accounts/collected.ctp index c70768d..ce5d48a 100644 --- a/site/views/accounts/collected.ctp +++ b/site/views/accounts/collected.ctp @@ -164,7 +164,7 @@ echo $this->element('statement_entries', array //'grid_setup' => array('hiddengrid' => true), //'caption' => '', 'caption' => 'Collected ' . Inflector::pluralize($account['name']), - 'filter' => array('StatementEntry.type' => 'DISBURSEMENT', + 'filter' => array(//'StatementEntry.type' => 'DISBURSEMENT', 'ChargeEntry.account_id' => $account['id']), 'exclude' => array('Account', 'Charge', 'Type'), ), From 654eb0960e89ace34017cb01e69b80a162813962 Mon Sep 17 00:00:00 2001 From: abijah Date: Fri, 7 Aug 2009 22:52:01 +0000 Subject: [PATCH 493/717] Some of the finer detail work, mostly around pre-populating the move-in invoice with useful and correct data, and allowing the lease rent and deposit to be set at movein. git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@503 97e9348a-65ac-dc4b-aefc-98561f571b83 --- scripts/sitelink2pmgr.pl | 8 +- site/controllers/leases_controller.php | 32 +++++-- site/controllers/units_controller.php | 4 +- site/models/statement_entry.php | 2 +- site/models/transaction.php | 4 + site/models/unit.php | 46 ++++++++++ site/views/elements/form_table.ctp | 2 +- site/views/elements/table.ctp | 5 +- site/views/elements/units.ctp | 3 +- site/views/leases/invoice.ctp | 115 ++++++++++++++++++++++--- site/views/leases/move.ctp | 23 ++++- todo.notes | 3 + 12 files changed, 223 insertions(+), 24 deletions(-) diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 75edd3f..0027875 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -5,6 +5,7 @@ use Data::Dumper; use File::Copy; my $closing_one_transaction = 0; +my $work_from_scratch = 1; # Internally adjust all numbers coming from the database to # be in inches. Not necessary to go to this detail, but the @@ -1468,7 +1469,7 @@ addRow('double_entries', { ###################################################################### ## Debug ... work from scratch -if (defined $work_from_scratch) { +if ($work_from_scratch) { # delete $newdb{'tables'}{'contacts'}{'rows'}; # delete $newdb{'tables'}{'contacts_methods'}{'rows'}; # delete $newdb{'tables'}{'contacts_addresses'}{'rows'}; @@ -1482,6 +1483,11 @@ if (defined $work_from_scratch) { delete $newdb{'tables'}{'statement_entries'}{'rows'}; delete $newdb{'tables'}{'tenders'}{'rows'}; delete $newdb{'tables'}{'transactions'}{'rows'}; + + foreach (@{$newdb{'tables'}{'units'}{'rows'}}) { + $_->{'status'} = 'VACANT' + if defined $_ && ($_->{'status'} =~ /^(OCCUPIED)$/ || $_->{'name'} =~ /^Y/); + } } diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index c52f982..4e043c8 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -135,17 +135,22 @@ class LeasesController extends AppController { // Handle the move in based on the data given //pr(array('Move-in data', $this->data)); + foreach (array('deposit', 'rent') AS $currency) { + $this->data['Lease'][$currency] + = str_replace('$', '', $this->data['Lease'][$currency]); + } $lid = $this->Lease->moveIn($this->data['Lease']['customer_id'], $this->data['Lease']['unit_id'], - null, null, + $this->data['Lease']['deposit'], + $this->data['Lease']['rent'], $this->data['Lease']['movein_date'], $this->data['Lease']['comment'] ); // Since this is a new lease, go to the invoice // screen so we can start assessing charges. - $this->redirect(array('action'=>'invoice', $lid)); + $this->redirect(array('action'=>'invoice', $lid, 'move-in')); // For debugging, only if the redirect above have been // commented out, otherwise this section isn't reached. @@ -362,13 +367,30 @@ class LeasesController extends AppController { $A = new Account(); $charge_accounts = $A->invoiceAccounts(); $default_account = $A->rentAccountID(); - $this->set(compact('charge_accounts', 'default_account')); + $rent_account = $A->rentAccountID(); + $security_deposit_account = $A->securityDepositAccountID(); + $this->set(compact('charge_accounts', 'default_account', + 'rent_account', 'security_deposit_account')); // REVISIT 20090705: // Of course, the late charge should come from the late_schedule - $default_rent = $lease['Lease']['rent']; $default_late = 10; - $this->set(compact('default_rent', 'default_late')); + $this->set(compact('default_late')); + + if ($type === 'move-in') { + $movein = array(); + $movein['time'] = strtotime($lease['Lease']['movein_date']); + $movein['effective_time'] = strtotime($lease['Lease']['movein_date']); + $movein_date = getdate($movein['effective_time']); + $movein['through_time'] = mktime(0, 0, 0, $movein_date['mon'] + 1, 0, $movein_date['year']); + $days_in_month = idate('d', $movein['through_time']); + $movein['prorated_days'] = $days_in_month - $movein_date['mday'] + 1; + $movein['prorated_rent'] = $lease['Lease']['rent'] * $movein['prorated_days'] / $days_in_month; + $movein['prorated'] = $movein['prorated_days'] != $days_in_month; + $movein['deposit'] = $lease['Lease']['deposit']; + $this->set(compact('movein')); + } + $title = ('Lease #' . $lease['Lease']['number'] . ': ' . $lease['Unit']['name'] . ': ' . diff --git a/site/controllers/units_controller.php b/site/controllers/units_controller.php index 699d23a..5b452d7 100644 --- a/site/controllers/units_controller.php +++ b/site/controllers/units_controller.php @@ -245,10 +245,12 @@ class UnitsController extends AppController { $this->sidemenu_links[] = array('name' => 'Move-Out', 'url' => array('action' => 'move_out', $id)); - } else { + } elseif ($this->Unit->available($unit['Unit']['status'])) { $this->sidemenu_links[] = array('name' => 'Move-In', 'url' => array('action' => 'move_in', $id)); + } else { + // Unit is unavailable (dirty, damaged, reserved, business-use, etc) } if (isset($unit['CurrentLease']['id']) && diff --git a/site/models/statement_entry.php b/site/models/statement_entry.php index c8bad09..22aeb4f 100644 --- a/site/models/statement_entry.php +++ b/site/models/statement_entry.php @@ -656,7 +656,7 @@ class StatementEntry extends AppModel { * - Returns summary data from the requested statement entry */ function stats($id = null, $query = null) { - $this->prFunctionLevel(array('log' => 19, 'show' => 10)); + //$this->prFunctionLevel(array('log' => 19, 'show' => 10)); $this->prEnter(compact('id', 'query')); $this->queryInit($query); diff --git a/site/models/transaction.php b/site/models/transaction.php index 4e4de98..c58f4b1 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -475,6 +475,10 @@ class Transaction extends AppModel { // accidentally pick up stale data. $le1 = $le1_tender = $le2 = $se = null; + // Really, data should be sanitized at the controller, + // and not here. However, it's a one stop cleanup. + $entry['amount'] = str_replace('$', '', $entry['amount']); + // Add entry amount into the transaction total $transaction['amount'] += $entry['amount']; diff --git a/site/models/unit.php b/site/models/unit.php index 9e2396b..bd42691 100644 --- a/site/models/unit.php +++ b/site/models/unit.php @@ -55,10 +55,50 @@ class Unit extends AppModel { return $this->statusValue('OCCUPIED'); } + function statusCheck($id_or_enum, + $min = null, $min_strict = false, + $max = null, $max_strict = false) + { + $this->prEnter(compact('id_or_enum', 'min', 'min_strict', 'max', 'max_strict')); + + if (is_int($id_or_enum)) { + $this->id = $id_or_enum; + $id_or_enum = $this->field('status'); + } + + $enum_val = $this->statusValue($id_or_enum); + if (isset($min) && is_string($min)) + $min = $this->statusValue($min); + if (isset($max) && is_string($max)) + $max = $this->statusValue($max); + + $this->pr(17, compact('enum_val', 'min', 'min_strict', 'max', 'max_strict')); + + if (isset($min) && + ($enum_val < $min || + ($min_strict && $enum_val == $min))) + return $this->prReturn(false); + + if (isset($max) && + ($enum_val > $max || + ($max_strict && $enum_val == $max))) + return $this->prReturn(false); + + return $this->prReturn(true); + } + + function occupied($enum) { + return $this->statusCheck($enum, 'OCCUPIED', false, null, false); + } + function conditionOccupied() { return ('Unit.status >= ' . $this->statusValue('OCCUPIED')); } + function vacant($enum) { + return $this->statusCheck($enum, 'UNAVAILABLE', true, 'OCCUPIED', true); + } + function conditionVacant() { return ('Unit.status BETWEEN ' . ($this->statusValue('UNAVAILABLE')+1) . @@ -66,10 +106,16 @@ class Unit extends AppModel { ($this->statusValue('OCCUPIED')-1)); } + function unavailable($enum) { + return $this->statusCheck($enum, null, false, 'UNAVAILABLE', false); + } + function conditionUnavailable() { return ('Unit.status <= ' . $this->statusValue('UNAVAILABLE')); } + function available($enum) { return $this->vacant($enum); } + /************************************************************************** ************************************************************************** diff --git a/site/views/elements/form_table.ctp b/site/views/elements/form_table.ctp index 8a9b5fa..7394f83 100644 --- a/site/views/elements/form_table.ctp +++ b/site/views/elements/form_table.ctp @@ -123,7 +123,7 @@ foreach ($fields AS $field => $config) { } echo $this->element('table', - compact('class', 'caption', 'headers', + compact('id', 'class', 'caption', 'headers', 'rows', 'row_class', 'suppress_alternate_rows', 'column_class') ); diff --git a/site/views/elements/table.ctp b/site/views/elements/table.ctp index 7f2433f..aef240a 100644 --- a/site/views/elements/table.ctp +++ b/site/views/elements/table.ctp @@ -64,7 +64,10 @@ if (isset($rows) && is_array($rows) && count($rows)) { $class = implode(' ', $class); // OK, output the table HTML - echo('' . "\n"); + echo('' . "\n"); if (isset($caption)) echo(' ' . $caption . '' . "\n"); diff --git a/site/views/elements/units.ctp b/site/views/elements/units.ctp index cd1c523..b5b5220 100644 --- a/site/views/elements/units.ctp +++ b/site/views/elements/units.ctp @@ -8,6 +8,7 @@ $cols['ID'] = array('index' => 'Unit.id', 'formatter' => 'id'); $cols['Unit'] = array('index' => 'Unit.name', 'formatter' => 'shortname'); $cols['Size'] = array('index' => 'UnitSize.name', 'formatter' => 'shortname'); $cols['Rent'] = array('index' => 'Unit.rent', 'formatter' => 'currency'); +$cols['Deposit'] = array('index' => 'Unit.deposit', 'formatter' => 'currency'); $cols['Status'] = array('index' => 'Unit.status', 'formatter' => 'name'); // We have enough real estate $cols['Balance'] = array('index' => 'balance', 'formatter' => 'currency'); $cols['Comment'] = array('index' => 'Unit.comment', 'formatter' => 'comment'); @@ -19,4 +20,4 @@ $grid ->defaultFields(array('Sort', 'ID', 'Unit')) ->searchFields(array('Unit', 'Size', 'Status')) ->render($this, isset($config) ? $config : null, - array_diff(array_keys($cols), array('Walk', 'Comment'))); + array_diff(array_keys($cols), array('Walk', 'Deposit', 'Comment'))); diff --git a/site/views/leases/invoice.ctp b/site/views/leases/invoice.ctp index 0e530d6..fd74ac2 100644 --- a/site/views/leases/invoice.ctp +++ b/site/views/leases/invoice.ctp @@ -4,6 +4,13 @@ element('leases', array ('config' => array @@ -205,7 +286,7 @@ echo $this->element('leases', array 'grid_div_class' => 'text-below', 'caption' => ('Select Lease'), - 'grid_setup' => array('hiddengrid' => isset($lease['Lease']['id'])), + 'grid_setup' => array('hiddengrid' => isset($lease['id'])), 'grid_events' => array('onSelectRow' => array('ids' => 'if (ids != null){onRowSelect("#"+$(this).attr("id"), ids);}'), @@ -285,7 +366,17 @@ echo $form->submit('Generate Invoice') . "\n";

    Response

    Output

    + + + +
    From c33a823e50e7bbe12eb8028fc1711cbf865e8284 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 10 Aug 2009 18:58:41 +0000 Subject: [PATCH 504/717] Added Bad Debt as one of the accounts for the collected report git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@514 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/account.php | 1 + 1 file changed, 1 insertion(+) diff --git a/site/models/account.php b/site/models/account.php index ba55f32..a94baf5 100644 --- a/site/models/account.php +++ b/site/models/account.php @@ -223,6 +223,7 @@ class Account extends AppModel { $accounts = $this->receiptAccounts(); foreach(array($this->nsfAccountID(), + $this->badDebtAccountID(), $this->securityDepositAccountID()) AS $account_id) { $accounts[$account_id] = $this->name($account_id); From 98f3dd7688f967c17e239a57ed8253af495f6a86 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 10 Aug 2009 19:00:02 +0000 Subject: [PATCH 505/717] Added the close date to the leases grid, to make it clear which customer leases are still open. Perhaps we should exclude the field by default, and just add it into the customer view page. git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@515 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/leases.ctp | 1 + 1 file changed, 1 insertion(+) diff --git a/site/views/elements/leases.ctp b/site/views/elements/leases.ctp index 2ff2413..10872bb 100644 --- a/site/views/elements/leases.ctp +++ b/site/views/elements/leases.ctp @@ -11,6 +11,7 @@ $cols['Deposit'] = array('index' => 'Lease.deposit', 'formatter' => 'cur $cols['Signed'] = array('index' => 'Lease.lease_date', 'formatter' => 'date'); $cols['Move-In'] = array('index' => 'Lease.movein_date', 'formatter' => 'date'); $cols['Move-Out'] = array('index' => 'Lease.moveout_date', 'formatter' => 'date'); +$cols['Closed'] = array('index' => 'Lease.close_date', 'formatter' => 'date'); $cols['Balance'] = array('index' => 'balance', 'formatter' => 'currency'); $cols['Comment'] = array('index' => 'Lease.comment', 'formatter' => 'comment'); From eb28852b871535b0af8bbea73168b6defedfe151 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 10 Aug 2009 19:01:20 +0000 Subject: [PATCH 506/717] Added the ability to accept payments (or a write-off) on a closed lease, if there is a balance owing. Added the ability to do write off bad debt at the customer level, since some charges may not be on a lease, like the NSF fee. git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@516 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/customers_controller.php | 38 +++++++++++++++++++++-- site/controllers/leases_controller.php | 25 +++++++-------- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 290fc4a..42c5459 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -249,12 +249,17 @@ class CustomersController extends AppController { /* $id)); */ /* } */ - if ($show_payment) { + if ($show_payment || $outstanding_balance > 0) $this->sidemenu_links[] = array('name' => 'Payment', '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[] = @@ -439,6 +444,35 @@ class CustomersController extends AppController { } + /************************************************************************** + ************************************************************************** + ************************************************************************** + * 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'); + } + + /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index a9bdf4a..4362967 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -291,6 +291,7 @@ class LeasesController extends AppController { */ function bad_debt($id) { + $this->Lease->id = $id; $lease = $this->Lease->find ('first', array ('contain' => array @@ -298,20 +299,14 @@ class LeasesController extends AppController { '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), - ), )); // Make sure we have a valid lease to write off if (empty($lease)) $this->redirect(array('action' => 'view', $id)); - // Get the lease balance, part of lease stats - $stats = $this->Lease->stats($id); - $balance = $stats['balance']; + // Get the lease balance + $balance = $this->Lease->balance($id); // Prepare to render $title = ('Lease #' . $lease['Lease']['number'] . ': ' . @@ -465,8 +460,11 @@ class LeasesController extends AppController { $outstanding_balance = $this->Lease->balance($id); $outstanding_deposit = $this->Lease->securityDepositBalance($id); - // Set up dynamic menu items - if (!isset($lease['Lease']['close_date'])) { + // 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); @@ -475,9 +473,10 @@ class LeasesController extends AppController { array('name' => 'Move-Out', 'url' => array('action' => 'move_out', $id)); - $this->sidemenu_links[] = - array('name' => 'Charges', 'url' => array('action' => 'invoice', - $id)); + if (!isset($lease['Lease']['close_date'])) + $this->sidemenu_links[] = + array('name' => 'Charges', 'url' => array('action' => 'invoice', + $id)); $this->sidemenu_links[] = array('name' => 'Payments', 'url' => array('controller' => 'customers', From 19f8c18ce9140853c0bf5af33abe9854086b93d3 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 10 Aug 2009 19:20:29 +0000 Subject: [PATCH 507/717] Removed the two dangerous links from the Debug menu, as we're preparing to enter new data and don't want to zap it. git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@517 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/app_controller.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/app_controller.php b/site/app_controller.php index e8420b4..e0fd16d 100644 --- a/site/app_controller.php +++ b/site/app_controller.php @@ -52,8 +52,8 @@ class AppController extends Controller { array('onclick' => '$(".pr-section").show(); return false;')), array('name' => 'Contacts', 'url' => array('controller' => 'contacts', 'action' => 'index')), array('name' => 'Ledgers', 'url' => array('controller' => 'ledgers', 'action' => 'index')), - array('name' => 'New Ledgers', 'url' => array('controller' => 'accounts', 'action' => 'newledger')), - array('name' => 'RESET DATA', 'url' => array('controller' => 'accounts', 'action' => 'reset_data')), + //array('name' => 'New Ledgers', 'url' => array('controller' => 'accounts', 'action' => 'newledger')), + //array('name' => 'RESET DATA', 'url' => array('controller' => 'accounts', 'action' => 'reset_data')), ); } From 1ce71a39361933d844f7793b201464d801194eae Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 10 Aug 2009 22:22:56 +0000 Subject: [PATCH 508/717] Added automatic grid reload, since the default grid load is inconsistent with the displayed settings. The solution here sucks, but at least it avoids the inconsistency. git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@518 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/accounts/collected.ctp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/site/views/accounts/collected.ctp b/site/views/accounts/collected.ctp index ce5d48a..898297e 100644 --- a/site/views/accounts/collected.ctp +++ b/site/views/accounts/collected.ctp @@ -15,7 +15,8 @@ echo '' . "\n"); +} + +echo $form->submit('Update') . "\n"; +echo $form->submit('Cancel', array('name' => 'cancel')) . "\n"; +echo $form->end() . "\n"; +echo '
    ' . "\n"; From 4f11e27a7680fa2cc728126854ac5786a3048e38 Mon Sep 17 00:00:00 2001 From: abijah Date: Mon, 10 Aug 2009 23:57:20 +0000 Subject: [PATCH 511/717] Removed the debug portions of receipt entry, and added a checkbox to allow the user to either keep entering receipts, or have the page automatically transition to the customer page. git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@521 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/customers/receipt.ctp | 132 +++++++++++++------------------ 1 file changed, 53 insertions(+), 79 deletions(-) diff --git a/site/views/customers/receipt.ctp b/site/views/customers/receipt.ctp index 9a7e6cf..aff9faa 100644 --- a/site/views/customers/receipt.ctp +++ b/site/views/customers/receipt.ctp @@ -11,6 +11,9 @@ * Javascript */ +// Warnings _really_ screw up javascript +$saved_debug_state = Configure::read('debug'); +Configure::write('debug', '0'); ?> +--> ' . "\n"; +// Re-Enable warnings +Configure::write('debug', $saved_debug_state); echo $this->element('customers', array ('config' => array @@ -363,6 +352,10 @@ echo $this->element('form_table', ), ))); +echo "
    \n"; +echo $form->input('repeat', array('type' => 'checkbox', + 'id' => 'repeat', + 'label' => 'Enter Multiple Receipts')) . "\n"; echo $form->submit('Generate Receipt') . "\n"; ?> @@ -383,9 +376,13 @@ echo $form->submit('Generate Receipt') . "\n"; ' . "\n"; // End of the dialog DIV */ ?> -

    Request

    -

    Response

    -

    Output

    +
    + + +
    - -Clear Debug Output From b1a7f4193459a552c7d5ad89caa971cfbe2c91a7 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 11 Aug 2009 01:06:28 +0000 Subject: [PATCH 512/717] Renamed the menu items for invoice and receipt creation. git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@522 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/controllers/customers_controller.php | 2 +- site/controllers/leases_controller.php | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/site/controllers/customers_controller.php b/site/controllers/customers_controller.php index 42c5459..df2e679 100644 --- a/site/controllers/customers_controller.php +++ b/site/controllers/customers_controller.php @@ -251,7 +251,7 @@ class CustomersController extends AppController { if ($show_payment || $outstanding_balance > 0) $this->sidemenu_links[] = - array('name' => 'Payment', + array('name' => 'New Receipt', 'url' => array('action' => 'receipt', $id)); diff --git a/site/controllers/leases_controller.php b/site/controllers/leases_controller.php index 4362967..1db1927 100644 --- a/site/controllers/leases_controller.php +++ b/site/controllers/leases_controller.php @@ -475,13 +475,13 @@ class LeasesController extends AppController { if (!isset($lease['Lease']['close_date'])) $this->sidemenu_links[] = - array('name' => 'Charges', 'url' => array('action' => 'invoice', - $id)); + array('name' => 'New Invoice', 'url' => array('action' => 'invoice', + $id)); $this->sidemenu_links[] = - array('name' => 'Payments', 'url' => array('controller' => 'customers', - 'action' => 'receipt', - $lease['Customer']['id'])); + array('name' => 'New Receipt', 'url' => array('controller' => 'customers', + 'action' => 'receipt', + $lease['Customer']['id'])); /* if ($outstanding_balance < 0) */ /* $this->sidemenu_links[] = */ From 15f885ab8aec3557ec67b5b474f83bc96d5e5b96 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 11 Aug 2009 01:07:01 +0000 Subject: [PATCH 513/717] Fixed problem when effective_date is an empty string, as opposed to completely missing. git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@523 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/models/transaction.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/site/models/transaction.php b/site/models/transaction.php index 33fc004..0e85c06 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -630,7 +630,8 @@ class Transaction extends AppModel { if (!empty($se)) { $se['transaction_id'] = $ret['transaction_id']; - $se += array('effective_date' => $transaction_stamp); + if (empty($se['effective_date'])) + $se['effective_date'] = $transaction_stamp; $result = $this->StatementEntry->addStatementEntry($se); $ret['entries'][$e_index]['StatementEntry'] = $result; if ($result['error']) { From f0693bdc05a23dc083a484dbf7be80338886625e Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 11 Aug 2009 01:07:20 +0000 Subject: [PATCH 514/717] Whitespace only change git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@524 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/customers/receipt.ctp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/views/customers/receipt.ctp b/site/views/customers/receipt.ctp index aff9faa..d9e7ba5 100644 --- a/site/views/customers/receipt.ctp +++ b/site/views/customers/receipt.ctp @@ -51,9 +51,9 @@ function showResponse(responseText, statusText) { }); $('#results').html('

    Receipt Saved
    ' + - $("#receipt-customer-name").html() + - ' : ' + fmtCurrency(amount) + - '

    '); + $("#receipt-customer-name").html() + + ' : ' + fmtCurrency(amount) + + ''); if (!$("#repeat").attr("checked")) { window.location.href = From 72af3f3247e03f4a15a3bbbeaa64444a75246103 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 11 Aug 2009 01:08:39 +0000 Subject: [PATCH 515/717] Changed invoice generation to match the receipt changes in r521 (no more debug, transition to the lease after entry, etc). git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@525 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/leases/invoice.ctp | 222 +++++++++++++++++----------------- 1 file changed, 108 insertions(+), 114 deletions(-) diff --git a/site/views/leases/invoice.ctp b/site/views/leases/invoice.ctp index fd74ac2..07aca35 100644 --- a/site/views/leases/invoice.ctp +++ b/site/views/leases/invoice.ctp @@ -33,14 +33,8 @@ Configure::write('debug', '0'); success: showResponse, // post-submit callback // other available options: - //url: url, // override for form's 'action' attribute - //type: 'get', // 'get' or 'post', override for form's 'method' attribute - //dataType: null, // 'xml', 'script', or 'json' (expected server response type) //clearForm: true, // clear all form fields after successful submit //resetForm: true, // reset the form after successful submit - - // $.ajax options can be used here too, for example: - //timeout: 3000, }; // bind form using 'ajaxForm' @@ -49,16 +43,7 @@ Configure::write('debug', '0'); // pre-submit callback function verifyRequest(formData, jqForm, options) { - // formData is an array; here we use $.param to convert it to a string to display it - // but the form plugin does this for you automatically when it submits the data - //var_dump(formData); - //$('#request-debug').html('
    '+dump(formData)+'
    '); - $('#request-debug').html('Ommitted'); - //return false; - - $('#response-debug').html('Loading ...'); - $('#output-debug').html('Loading ...'); - + $('#results').html('Working ...'); // 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; @@ -66,108 +51,41 @@ function verifyRequest(formData, jqForm, options) { // post-submit callback function showResponse(responseText, statusText) { - // for normal html responses, the first argument to the success callback - // is the XMLHttpRequest object's responseText property - - // if the ajaxForm method was passed an Options Object with the dataType - // property set to 'xml' then the first argument to the success callback - // is the XMLHttpRequest object's responseXML property - - // if the ajaxForm method was passed an Options Object with the dataType - // property set to 'json' then the first argument to the success callback - // is the json data object returned by the server - if (statusText == 'success') { + var amount = 0; + $("input.invoice.amount").each(function(i) { + amount += (+ $(this).val().replace(/\$/,'')); + }); + + $('#results').html('

    Invoice Saved
    ' + + $("#invoice-customer").html() + + ' : ' + fmtCurrency(amount) + + '

    '); + + if (!$("#repeat").attr("checked")) { + window.location.href = + "url(array('controller' => 'leases', + 'action' => 'view')); ?>" + + "/" + $("#lease-id").val(); + return; + } + // get a clean slate //resetForm(); } else { - alert('not successful??'); + $('#results').html('

    Failed to save invoice!

    '); + alert('Failed to save invoice.'); } - - - $('#response-debug').html('
    '+dump(statusText)+'
    '); } // Reset the form -function resetForm() { - $("#charge-entry-id").val(1); +function resetForm(nocharge) { + $('#charge-entry-id').val(1); + $('#charges').html(''); - $("#invoice-lease").html("INTERNAL ERROR"); - $("#invoice-unit").html("INTERNAL ERROR"); - $("#invoice-customer").html("INTERNAL ERROR"); - $("#invoice-rent").html("INTERNAL ERROR"); - $("#invoice-late").html("INTERNAL ERROR"); - $("#invoice-deposit").html("INTERNAL ERROR"); - - - - - addChargeSource(false); - datepickerNow('TransactionStamp'); - - - - var id; - - $("#TransactionStamp").datepicker('disable'); - $("#TransactionStamp").val(""); - $('#TransactionStamp').after - (''); - $("#TransactionComment").val('Move-In Charges'); - - id = addChargeSource(false); - $('#Entry'+id+'Form').removeCol(2); - $('#Entry'+id+'Form input, #Entry'+id+'Form select').attr('disabled', true); - $('#Entry'+id+'EffectiveDate').val(""); - $('#Entry'+id+'EffectiveDate').after - (''); - $('#Entry'+id+'AccountId').val(); - $('#Entry'+id+'AccountId').after - (''); - $('#Entry'+id+'Amount').val(""); - $('#Entry'+id+'Amount').after - (''); - //$('#Entry'+id+'Comment').val('Move-In Security Deposit'); - $('#Entry'+id+'Comment').removeAttr('disabled'); - - - id = addChargeSource(false); - $('#Entry'+id+'Form').removeCol(2); - $('#Entry'+id+'Form input, #Entry'+id+'Form select').attr('disabled', true); - $('#Entry'+id+'EffectiveDate').val(""); - $('#Entry'+id+'EffectiveDate').after - (''); - $('#Entry'+id+'ThroughDate').val(""); - $('#Entry'+id+'ThroughDate').after - (''); - $('#Entry'+id+'AccountId').val(); - $('#Entry'+id+'AccountId').after - (''); - $('#Entry'+id+'Amount').val(""); - $('#Entry'+id+'Amount').after - (''); - $('#Entry'+id+'Comment').val('Move-In Rent' - ); - $('#Entry'+id+'Comment').removeAttr('disabled'); - - + if (!nocharge) + addChargeSource(false); } @@ -247,7 +165,7 @@ function addChargeSource(flash) { array('type' => 'text'), 'between' => 'EOM', ), - "amount" => true, + "amount" => array('opts' => array('class' => 'invoice amount')), "comment" => array('opts' => array('size' => 50)), ), ))) . "+\n"; @@ -348,6 +266,10 @@ echo $this->element('form_table', /* echo '' . "\n"; */ +echo "
    \n"; +echo $form->input('repeat', array('type' => 'checkbox', + 'id' => 'repeat', + 'label' => 'Enter Multiple Invoices')) . "\n"; echo $form->submit('Generate Invoice') . "\n"; ?> @@ -362,9 +284,8 @@ echo $form->submit('Generate Invoice') . "\n"; end('Generate Invoice'); ?> -

    Request

    -

    Response

    -

    Output

    +
    + + resetForm(); + datepickerNow('TransactionStamp'); + + + + var id; + resetForm(true); + + $("#TransactionStamp").datepicker('disable'); + $("#TransactionStamp").val(""); + $('#TransactionStamp').after + (''); + $("#TransactionComment").val('Move-In Charges'); + + id = addChargeSource(false); + $('#Entry'+id+'Form').removeCol(2); + $('#Entry'+id+'Form input, #Entry'+id+'Form select').attr('disabled', true); + $('#Entry'+id+'EffectiveDate').val(""); + $('#Entry'+id+'EffectiveDate').after + (''); + $('#Entry'+id+'AccountId').val(); + $('#Entry'+id+'AccountId').after + (''); + $('#Entry'+id+'Amount').val(""); + $('#Entry'+id+'Amount').after + (''); + //$('#Entry'+id+'Comment').val('Move-In Security Deposit'); + $('#Entry'+id+'Comment').removeAttr('disabled'); + + + id = addChargeSource(false); + $('#Entry'+id+'Form').removeCol(2); + $('#Entry'+id+'Form input, #Entry'+id+'Form select').attr('disabled', true); + $('#Entry'+id+'EffectiveDate').val(""); + $('#Entry'+id+'EffectiveDate').after + (''); + $('#Entry'+id+'ThroughDate').val(""); + $('#Entry'+id+'ThroughDate').after + (''); + $('#Entry'+id+'AccountId').val(); + $('#Entry'+id+'AccountId').after + (''); + $('#Entry'+id+'Amount').val(""); + $('#Entry'+id+'Amount').after + (''); + $('#Entry'+id+'Comment').val('Move-In Rent' + ); + $('#Entry'+id+'Comment').removeAttr('disabled'); + + + $("#lease-id").val(); @@ -408,5 +404,3 @@ Configure::write('debug', '0'); -->
    - -Clear Debug Output From 704412727d8367fafd50fd66fcfa8bb9dcc2ac6c Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 11 Aug 2009 04:11:45 +0000 Subject: [PATCH 516/717] Branch to roll up to the 3.5 version of jqGrid git-svn-id: file:///svn-source/pmgr/branches/jqgrid_3.5@526 97e9348a-65ac-dc4b-aefc-98561f571b83 From e9b9bdc42082186c8e64420b860d294af809f907 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 11 Aug 2009 04:43:33 +0000 Subject: [PATCH 517/717] Preliminary move to jqGrid 3.5.1. It has proven troublesome to change over, although really, I've only found one compatibility break so far. The real problem has been the elimination of the jqGrid loader code. We now have to build the jqGrid package through a selection form on the jqGrid download page, and the errors made it difficult to determine that the package configuration was the problem (such as destroying the entire page content). It's working alright at the moment. git-svn-id: file:///svn-source/pmgr/branches/jqgrid_3.5@527 97e9348a-65ac-dc4b-aefc-98561f571b83 --- site/views/elements/jqGrid.ctp | 55 +- site/views/layouts/default.ctp | 12 +- site/webroot/css/jqGrid/basic/grid.css | 447 - .../css/jqGrid/basic/images/cd_run.gif | Bin 1025 -> 0 bytes .../webroot/css/jqGrid/basic/images/dirty.gif | Bin 832 -> 0 bytes site/webroot/css/jqGrid/basic/images/down.gif | Bin 309 -> 0 bytes site/webroot/css/jqGrid/basic/images/find.gif | Bin 986 -> 0 bytes .../webroot/css/jqGrid/basic/images/first.gif | Bin 925 -> 0 bytes .../css/jqGrid/basic/images/folder.png | Bin 229 -> 0 bytes .../css/jqGrid/basic/images/grid-blue-ft.gif | Bin 821 -> 0 bytes .../css/jqGrid/basic/images/grid-blue-hd.gif | Bin 821 -> 0 bytes .../css/jqGrid/basic/images/headerbg.gif | Bin 87 -> 0 bytes .../css/jqGrid/basic/images/headerleft.gif | Bin 425 -> 0 bytes .../css/jqGrid/basic/images/headerright.gif | Bin 87 -> 0 bytes .../css/jqGrid/basic/images/ico-close.gif | Bin 957 -> 0 bytes site/webroot/css/jqGrid/basic/images/last.gif | Bin 923 -> 0 bytes .../webroot/css/jqGrid/basic/images/line3.gif | Bin 70 -> 0 bytes .../css/jqGrid/basic/images/loading.gif | Bin 771 -> 0 bytes .../webroot/css/jqGrid/basic/images/minus.gif | Bin 85 -> 0 bytes site/webroot/css/jqGrid/basic/images/next.gif | Bin 875 -> 0 bytes .../css/jqGrid/basic/images/nochild.gif | Bin 66 -> 0 bytes .../css/jqGrid/basic/images/off-first.gif | Bin 925 -> 0 bytes .../css/jqGrid/basic/images/off-last.gif | Bin 923 -> 0 bytes .../css/jqGrid/basic/images/off-next.gif | Bin 875 -> 0 bytes .../css/jqGrid/basic/images/off-prev.gif | Bin 879 -> 0 bytes site/webroot/css/jqGrid/basic/images/plus.gif | Bin 89 -> 0 bytes site/webroot/css/jqGrid/basic/images/prev.gif | Bin 879 -> 0 bytes .../css/jqGrid/basic/images/refresh.gif | Bin 581 -> 0 bytes .../css/jqGrid/basic/images/resize.gif | Bin 862 -> 0 bytes .../css/jqGrid/basic/images/row_add.gif | Bin 635 -> 0 bytes .../css/jqGrid/basic/images/row_delete.gif | Bin 634 -> 0 bytes .../css/jqGrid/basic/images/row_edit.gif | Bin 996 -> 0 bytes .../css/jqGrid/basic/images/sort_asc.gif | Bin 830 -> 0 bytes .../css/jqGrid/basic/images/sort_desc.gif | Bin 833 -> 0 bytes .../css/jqGrid/basic/images/spacer.gif | Bin 43 -> 0 bytes .../css/jqGrid/basic/images/tab_close-on.gif | Bin 351 -> 0 bytes .../css/jqGrid/basic/images/tree_leaf.gif | Bin 134 -> 0 bytes .../css/jqGrid/basic/images/tree_minus.gif | Bin 132 -> 0 bytes .../css/jqGrid/basic/images/tree_plus.gif | Bin 138 -> 0 bytes site/webroot/css/jqGrid/basic/images/up.gif | Bin 312 -> 0 bytes site/webroot/css/jqGrid/coffee/grid.css | 457 - .../css/jqGrid/coffee/images/cd_run.gif | Bin 1025 -> 0 bytes .../css/jqGrid/coffee/images/dirty.gif | Bin 832 -> 0 bytes .../webroot/css/jqGrid/coffee/images/down.gif | Bin 683 -> 0 bytes .../webroot/css/jqGrid/coffee/images/find.gif | Bin 986 -> 0 bytes .../css/jqGrid/coffee/images/first.gif | Bin 734 -> 0 bytes .../css/jqGrid/coffee/images/folder.png | Bin 229 -> 0 bytes .../css/jqGrid/coffee/images/grid-blue-ft.gif | Bin 165 -> 0 bytes .../css/jqGrid/coffee/images/grid-blue-hd.gif | Bin 165 -> 0 bytes .../css/jqGrid/coffee/images/headerbg.gif | Bin 105 -> 0 bytes .../css/jqGrid/coffee/images/headerleft.gif | Bin 236 -> 0 bytes .../css/jqGrid/coffee/images/headerright.gif | Bin 235 -> 0 bytes .../css/jqGrid/coffee/images/ico-close.gif | Bin 854 -> 0 bytes .../webroot/css/jqGrid/coffee/images/last.gif | Bin 737 -> 0 bytes .../css/jqGrid/coffee/images/line3.gif | Bin 70 -> 0 bytes .../css/jqGrid/coffee/images/loading.gif | Bin 771 -> 0 bytes .../css/jqGrid/coffee/images/minus.gif | Bin 85 -> 0 bytes .../webroot/css/jqGrid/coffee/images/next.gif | Bin 483 -> 0 bytes .../css/jqGrid/coffee/images/nochild.gif | Bin 66 -> 0 bytes .../css/jqGrid/coffee/images/off-first.gif | Bin 483 -> 0 bytes .../css/jqGrid/coffee/images/off-last.gif | Bin 485 -> 0 bytes .../css/jqGrid/coffee/images/off-next.gif | Bin 476 -> 0 bytes .../css/jqGrid/coffee/images/off-prev.gif | Bin 479 -> 0 bytes .../webroot/css/jqGrid/coffee/images/plus.gif | Bin 89 -> 0 bytes .../webroot/css/jqGrid/coffee/images/prev.gif | Bin 483 -> 0 bytes .../css/jqGrid/coffee/images/refresh.gif | Bin 581 -> 0 bytes .../css/jqGrid/coffee/images/resize.gif | Bin 862 -> 0 bytes .../css/jqGrid/coffee/images/row_add.gif | Bin 635 -> 0 bytes .../css/jqGrid/coffee/images/row_delete.gif | Bin 634 -> 0 bytes .../css/jqGrid/coffee/images/row_edit.gif | Bin 996 -> 0 bytes .../css/jqGrid/coffee/images/sort_asc.gif | Bin 114 -> 0 bytes .../css/jqGrid/coffee/images/sort_desc.gif | Bin 113 -> 0 bytes .../css/jqGrid/coffee/images/spacer.gif | Bin 43 -> 0 bytes .../css/jqGrid/coffee/images/tab_close-on.gif | Bin 351 -> 0 bytes .../css/jqGrid/coffee/images/tree_leaf.gif | Bin 134 -> 0 bytes .../css/jqGrid/coffee/images/tree_minus.gif | Bin 132 -> 0 bytes .../css/jqGrid/coffee/images/tree_plus.gif | Bin 138 -> 0 bytes site/webroot/css/jqGrid/coffee/images/up.gif | Bin 673 -> 0 bytes site/webroot/css/jqGrid/green/grid.css | 459 - .../css/jqGrid/green/images/cd_run.gif | Bin 1025 -> 0 bytes .../webroot/css/jqGrid/green/images/dirty.gif | Bin 832 -> 0 bytes site/webroot/css/jqGrid/green/images/down.gif | Bin 734 -> 0 bytes site/webroot/css/jqGrid/green/images/find.gif | Bin 986 -> 0 bytes .../webroot/css/jqGrid/green/images/first.gif | Bin 763 -> 0 bytes .../css/jqGrid/green/images/folder.png | Bin 229 -> 0 bytes .../css/jqGrid/green/images/grid-blue-ft.gif | Bin 165 -> 0 bytes .../css/jqGrid/green/images/grid-blue-hd.gif | Bin 165 -> 0 bytes .../css/jqGrid/green/images/headerbg.gif | Bin 105 -> 0 bytes .../css/jqGrid/green/images/headerleft.gif | Bin 236 -> 0 bytes .../css/jqGrid/green/images/headerright.gif | Bin 235 -> 0 bytes .../css/jqGrid/green/images/ico-close.gif | Bin 854 -> 0 bytes site/webroot/css/jqGrid/green/images/last.gif | Bin 760 -> 0 bytes site/webroot/css/jqGrid/green/images/leaf.gif | Bin 203 -> 0 bytes .../webroot/css/jqGrid/green/images/line3.gif | Bin 70 -> 0 bytes .../css/jqGrid/green/images/loading.gif | Bin 771 -> 0 bytes .../webroot/css/jqGrid/green/images/minus.gif | Bin 85 -> 0 bytes site/webroot/css/jqGrid/green/images/next.gif | Bin 1177 -> 0 bytes .../css/jqGrid/green/images/nochild.gif | Bin 66 -> 0 bytes .../css/jqGrid/green/images/off-first.gif | Bin 763 -> 0 bytes .../css/jqGrid/green/images/off-last.gif | Bin 760 -> 0 bytes .../css/jqGrid/green/images/off-next.gif | Bin 1177 -> 0 bytes .../css/jqGrid/green/images/off-prev.gif | Bin 1175 -> 0 bytes site/webroot/css/jqGrid/green/images/plus.gif | Bin 89 -> 0 bytes site/webroot/css/jqGrid/green/images/prev.gif | Bin 1175 -> 0 bytes .../css/jqGrid/green/images/refresh.gif | Bin 581 -> 0 bytes .../css/jqGrid/green/images/resize.gif | Bin 862 -> 0 bytes .../css/jqGrid/green/images/row_add.gif | Bin 635 -> 0 bytes .../css/jqGrid/green/images/row_delete.gif | Bin 634 -> 0 bytes .../css/jqGrid/green/images/row_edit.gif | Bin 996 -> 0 bytes .../css/jqGrid/green/images/sort_asc.gif | Bin 71 -> 0 bytes .../css/jqGrid/green/images/sort_desc.gif | Bin 55 -> 0 bytes .../css/jqGrid/green/images/spacer.gif | Bin 43 -> 0 bytes .../css/jqGrid/green/images/tab_close-on.gif | Bin 351 -> 0 bytes .../css/jqGrid/green/images/tree_leaf.gif | Bin 134 -> 0 bytes .../css/jqGrid/green/images/tree_minus.gif | Bin 132 -> 0 bytes .../css/jqGrid/green/images/tree_plus.gif | Bin 138 -> 0 bytes site/webroot/css/jqGrid/green/images/up.gif | Bin 735 -> 0 bytes site/webroot/css/jqGrid/jqModal.css | 31 - site/webroot/css/jqGrid/sand/grid.css | 460 - .../webroot/css/jqGrid/sand/images/cd_run.gif | Bin 1025 -> 0 bytes site/webroot/css/jqGrid/sand/images/dirty.gif | Bin 832 -> 0 bytes site/webroot/css/jqGrid/sand/images/down.gif | Bin 379 -> 0 bytes site/webroot/css/jqGrid/sand/images/find.gif | Bin 986 -> 0 bytes site/webroot/css/jqGrid/sand/images/first.gif | Bin 399 -> 0 bytes .../webroot/css/jqGrid/sand/images/folder.png | Bin 229 -> 0 bytes .../css/jqGrid/sand/images/grid-blue-ft.gif | Bin 165 -> 0 bytes .../css/jqGrid/sand/images/grid-blue-hd.gif | Bin 165 -> 0 bytes .../css/jqGrid/sand/images/headerbg.gif | Bin 105 -> 0 bytes .../css/jqGrid/sand/images/headerleft.gif | Bin 197 -> 0 bytes .../css/jqGrid/sand/images/headerright.gif | Bin 258 -> 0 bytes .../css/jqGrid/sand/images/ico-close.gif | Bin 957 -> 0 bytes site/webroot/css/jqGrid/sand/images/last.gif | Bin 398 -> 0 bytes site/webroot/css/jqGrid/sand/images/line3.gif | Bin 70 -> 0 bytes .../css/jqGrid/sand/images/loading.gif | Bin 771 -> 0 bytes site/webroot/css/jqGrid/sand/images/minus.gif | Bin 85 -> 0 bytes site/webroot/css/jqGrid/sand/images/next.gif | Bin 392 -> 0 bytes .../css/jqGrid/sand/images/nochild.gif | Bin 66 -> 0 bytes .../css/jqGrid/sand/images/off-first.gif | Bin 399 -> 0 bytes .../css/jqGrid/sand/images/off-last.gif | Bin 398 -> 0 bytes .../css/jqGrid/sand/images/off-next.gif | Bin 392 -> 0 bytes .../css/jqGrid/sand/images/off-prev.gif | Bin 389 -> 0 bytes site/webroot/css/jqGrid/sand/images/plus.gif | Bin 89 -> 0 bytes site/webroot/css/jqGrid/sand/images/prev.gif | Bin 389 -> 0 bytes .../css/jqGrid/sand/images/refresh.gif | Bin 581 -> 0 bytes .../webroot/css/jqGrid/sand/images/resize.gif | Bin 862 -> 0 bytes .../css/jqGrid/sand/images/row_add.gif | Bin 635 -> 0 bytes .../css/jqGrid/sand/images/row_delete.gif | Bin 634 -> 0 bytes .../css/jqGrid/sand/images/row_edit.gif | Bin 996 -> 0 bytes .../css/jqGrid/sand/images/sort_asc.gif | Bin 56 -> 0 bytes .../css/jqGrid/sand/images/sort_desc.gif | Bin 55 -> 0 bytes .../webroot/css/jqGrid/sand/images/spacer.gif | Bin 43 -> 0 bytes .../css/jqGrid/sand/images/tab_close-on.gif | Bin 351 -> 0 bytes .../css/jqGrid/sand/images/tree_leaf.gif | Bin 134 -> 0 bytes .../css/jqGrid/sand/images/tree_minus.gif | Bin 132 -> 0 bytes .../css/jqGrid/sand/images/tree_plus.gif | Bin 138 -> 0 bytes site/webroot/css/jqGrid/sand/images/up.gif | Bin 382 -> 0 bytes site/webroot/css/jqGrid/steel/grid.css | 599 -- .../css/jqGrid/steel/images/._sprite5.png | Bin 70 -> 0 bytes .../css/jqGrid/steel/images/._sprite5.psd | Bin 24138 -> 0 bytes .../css/jqGrid/steel/images/Arrow2 Down.png | Bin 387 -> 0 bytes .../css/jqGrid/steel/images/Arrow2 Up.png | Bin 428 -> 0 bytes site/webroot/css/jqGrid/steel/images/bg.gif | Bin 854 -> 0 bytes .../css/jqGrid/steel/images/cd_run.gif | Bin 1025 -> 0 bytes .../css/jqGrid/steel/images/control_090.png | Bin 393 -> 0 bytes .../css/jqGrid/steel/images/control_270.png | Bin 446 -> 0 bytes .../webroot/css/jqGrid/steel/images/dirty.gif | Bin 832 -> 0 bytes site/webroot/css/jqGrid/steel/images/down.gif | Bin 291 -> 0 bytes site/webroot/css/jqGrid/steel/images/fhbg.gif | Bin 836 -> 0 bytes site/webroot/css/jqGrid/steel/images/find.gif | Bin 1008 -> 0 bytes .../webroot/css/jqGrid/steel/images/find1.gif | Bin 986 -> 0 bytes .../webroot/css/jqGrid/steel/images/first.gif | Bin 925 -> 0 bytes .../webroot/css/jqGrid/steel/images/first.png | Bin 591 -> 0 bytes .../css/jqGrid/steel/images/folder.png | Bin 229 -> 0 bytes .../css/jqGrid/steel/images/headerleft1.gif | Bin 197 -> 0 bytes .../css/jqGrid/steel/images/headerright1.gif | Bin 258 -> 0 bytes .../css/jqGrid/steel/images/ico-close.gif | Bin 957 -> 0 bytes site/webroot/css/jqGrid/steel/images/last.gif | Bin 923 -> 0 bytes site/webroot/css/jqGrid/steel/images/last.png | Bin 583 -> 0 bytes .../webroot/css/jqGrid/steel/images/line3.gif | Bin 70 -> 0 bytes .../css/jqGrid/steel/images/loading.gif | Bin 771 -> 0 bytes .../webroot/css/jqGrid/steel/images/minus.gif | Bin 85 -> 0 bytes site/webroot/css/jqGrid/steel/images/next.gif | Bin 875 -> 0 bytes site/webroot/css/jqGrid/steel/images/next.png | Bin 469 -> 0 bytes .../css/jqGrid/steel/images/nochild.gif | Bin 66 -> 0 bytes .../webroot/css/jqGrid/steel/images/odown.gif | Bin 379 -> 0 bytes .../css/jqGrid/steel/images/off-first.gif | Bin 925 -> 0 bytes .../css/jqGrid/steel/images/off-last.gif | Bin 923 -> 0 bytes .../css/jqGrid/steel/images/off-next.gif | Bin 875 -> 0 bytes .../css/jqGrid/steel/images/off-prev.gif | Bin 879 -> 0 bytes site/webroot/css/jqGrid/steel/images/oup.gif | Bin 382 -> 0 bytes site/webroot/css/jqGrid/steel/images/plus.gif | Bin 89 -> 0 bytes site/webroot/css/jqGrid/steel/images/prev.gif | Bin 879 -> 0 bytes site/webroot/css/jqGrid/steel/images/prev.png | Bin 460 -> 0 bytes .../css/jqGrid/steel/images/refresh.gif | Bin 1015 -> 0 bytes .../css/jqGrid/steel/images/refresh1.gif | Bin 581 -> 0 bytes .../css/jqGrid/steel/images/resize.gif | Bin 862 -> 0 bytes .../css/jqGrid/steel/images/row_add.gif | Bin 994 -> 0 bytes .../css/jqGrid/steel/images/row_add1.gif | Bin 635 -> 0 bytes .../css/jqGrid/steel/images/row_delete.gif | Bin 989 -> 0 bytes .../css/jqGrid/steel/images/row_delete1.gif | Bin 634 -> 0 bytes .../css/jqGrid/steel/images/row_edit.gif | Bin 946 -> 0 bytes .../css/jqGrid/steel/images/row_edit1.gif | Bin 996 -> 0 bytes .../css/jqGrid/steel/images/sort_asc.gif | Bin 56 -> 0 bytes .../css/jqGrid/steel/images/sort_desc.gif | Bin 55 -> 0 bytes .../css/jqGrid/steel/images/spacer.gif | Bin 43 -> 0 bytes .../css/jqGrid/steel/images/sprite.png | Bin 3745 -> 0 bytes .../css/jqGrid/steel/images/sprite5.png | Bin 2823 -> 0 bytes .../css/jqGrid/steel/images/sprite5.psd | Bin 107682 -> 0 bytes .../css/jqGrid/steel/images/tab_close-on.gif | Bin 351 -> 0 bytes .../css/jqGrid/steel/images/tree_leaf.gif | Bin 134 -> 0 bytes .../css/jqGrid/steel/images/tree_minus.gif | Bin 132 -> 0 bytes .../css/jqGrid/steel/images/tree_plus.gif | Bin 138 -> 0 bytes site/webroot/css/jqGrid/steel/images/up.gif | Bin 297 -> 0 bytes site/webroot/css/jqGrid/steel/images/wbg.gif | Bin 868 -> 0 bytes site/webroot/css/jqGrid/ui.jqgrid.css | 2 + .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin .../images/ui-bg_flat_75_ffffff_40x100.png | Bin .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin .../images/ui-bg_glass_65_ffffff_1x400.png | Bin .../images/ui-bg_glass_75_dadada_1x400.png | Bin .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin .../images/ui-bg_glass_75_ffffff_1x400.png | Bin .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin .../ui-bg_inset-soft_95_fef1ec_1x100.png | Bin .../base/images/ui-icons_222222_256x240.png | Bin .../base/images/ui-icons_2e83ff_256x240.png | Bin .../base/images/ui-icons_454545_256x240.png | Bin .../base/images/ui-icons_888888_256x240.png | Bin .../base/images/ui-icons_cd0a0a_256x240.png | Bin .../{jquery => themes}/base/ui.accordion.css | 0 .../css/{jquery => themes}/base/ui.all.css | 0 .../css/{jquery => themes}/base/ui.base.css | 0 .../css/{jquery => themes}/base/ui.core.css | 0 .../{jquery => themes}/base/ui.datepicker.css | 0 .../css/{jquery => themes}/base/ui.dialog.css | 0 .../base/ui.progressbar.css | 0 .../{jquery => themes}/base/ui.resizable.css | 0 .../css/{jquery => themes}/base/ui.slider.css | 0 .../css/{jquery => themes}/base/ui.tabs.css | 0 .../css/{jquery => themes}/base/ui.theme.css | 0 .../ui-bg_diagonals-thick_15_0b3e6f_40x40.png | Bin .../ui-bg_dots-medium_30_0b58a2_4x4.png | Bin .../images/ui-bg_dots-small_20_333333_2x2.png | Bin .../images/ui-bg_dots-small_30_a32d00_2x2.png | Bin .../images/ui-bg_dots-small_40_00498f_2x2.png | Bin .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin .../images/ui-bg_flat_40_292929_40x100.png | Bin .../ui-bg_gloss-wave_20_111111_500x100.png | Bin .../dotluv/images/ui-icons_00498f_256x240.png | Bin .../dotluv/images/ui-icons_98d2fb_256x240.png | Bin .../dotluv/images/ui-icons_9ccdfc_256x240.png | Bin .../dotluv/images/ui-icons_ffffff_256x240.png | Bin .../css/{jquery => themes}/dotluv/ui.all.css | 0 .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin .../images/ui-bg_flat_75_ffffff_40x100.png | Bin .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin .../images/ui-bg_glass_65_ffffff_1x400.png | Bin .../images/ui-bg_glass_75_dadada_1x400.png | Bin .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin .../images/ui-icons_222222_256x240.png | Bin .../images/ui-icons_2e83ff_256x240.png | Bin .../images/ui-icons_454545_256x240.png | Bin .../images/ui-icons_888888_256x240.png | Bin .../images/ui-icons_cd0a0a_256x240.png | Bin .../{jquery => themes}/smoothness/ui.all.css | 0 .../images/ui-bg_flat_55_999999_40x100.png | Bin .../images/ui-bg_flat_75_aaaaaa_40x100.png | Bin .../images/ui-bg_glass_45_0078ae_1x400.png | Bin .../images/ui-bg_glass_55_f8da4e_1x400.png | Bin .../images/ui-bg_glass_75_79c9ec_1x400.png | Bin .../ui-bg_gloss-wave_45_e14f1c_500x100.png | Bin .../ui-bg_gloss-wave_50_6eac2c_500x100.png | Bin .../ui-bg_gloss-wave_75_2191c0_500x100.png | Bin .../ui-bg_inset-hard_100_fcfdfd_1x100.png | Bin .../start/images/ui-icons_0078ae_256x240.png | Bin .../start/images/ui-icons_056b93_256x240.png | Bin .../start/images/ui-icons_d8e7f3_256x240.png | Bin .../start/images/ui-icons_e0fdff_256x240.png | Bin .../start/images/ui-icons_f5e175_256x240.png | Bin .../start/images/ui-icons_f7a50d_256x240.png | Bin .../start/images/ui-icons_fcd113_256x240.png | Bin .../css/{jquery => themes}/start/ui.all.css | 0 site/webroot/js/jqGrid/grid.locale-en.js | 1 + site/webroot/js/jqGrid/jquery.jqGrid.js | 68 - site/webroot/js/jqGrid/jquery.jqGrid.min.js | 10 + site/webroot/js/jqGrid/js/JsonXml.js | 345 - site/webroot/js/jqGrid/js/grid.base.js | 1598 --- site/webroot/js/jqGrid/js/grid.celledit.js | 445 - site/webroot/js/jqGrid/js/grid.common.js | 356 - site/webroot/js/jqGrid/js/grid.custom.js | 437 - site/webroot/js/jqGrid/js/grid.formedit.js | 1307 --- site/webroot/js/jqGrid/js/grid.import.js | 132 - site/webroot/js/jqGrid/js/grid.inlinedit.js | 194 - site/webroot/js/jqGrid/js/grid.locale-bg.js | 113 - .../js/jqGrid/js/grid.locale-bg1251.js | 113 - site/webroot/js/jqGrid/js/grid.locale-cat.js | 107 - site/webroot/js/jqGrid/js/grid.locale-cs.js | 113 - site/webroot/js/jqGrid/js/grid.locale-de.js | 111 - site/webroot/js/jqGrid/js/grid.locale-dk.js | 109 - site/webroot/js/jqGrid/js/grid.locale-el.js | 112 - site/webroot/js/jqGrid/js/grid.locale-en.js | 120 - site/webroot/js/jqGrid/js/grid.locale-fa.js | 110 - site/webroot/js/jqGrid/js/grid.locale-fi.js | 109 - site/webroot/js/jqGrid/js/grid.locale-fr.js | 128 - site/webroot/js/jqGrid/js/grid.locale-is.js | 106 - site/webroot/js/jqGrid/js/grid.locale-it.js | 107 - site/webroot/js/jqGrid/js/grid.locale-jp.js | 113 - site/webroot/js/jqGrid/js/grid.locale-pl.js | 108 - .../webroot/js/jqGrid/js/grid.locale-pt-br.js | 108 - site/webroot/js/jqGrid/js/grid.locale-pt.js | 107 - site/webroot/js/jqGrid/js/grid.locale-ru.js | 108 - site/webroot/js/jqGrid/js/grid.locale-sp.js | 108 - site/webroot/js/jqGrid/js/grid.locale-sv.js | 110 - site/webroot/js/jqGrid/js/grid.locale-tr.js | 108 - site/webroot/js/jqGrid/js/grid.postext.js | 64 - site/webroot/js/jqGrid/js/grid.setcolumns.js | 78 - site/webroot/js/jqGrid/js/grid.subgrid.js | 255 - site/webroot/js/jqGrid/js/grid.tbltogrid.js | 105 - site/webroot/js/jqGrid/js/grid.treegrid.js | 428 - site/webroot/js/jqGrid/js/jqDnR.js | 52 - site/webroot/js/jqGrid/js/jqModal.js | 69 - site/webroot/js/jqGrid/js/jquery.fmatter.js | 426 - site/webroot/js/jqGrid/js/jquery.tablednd.js | 383 - site/webroot/js/jqGrid/js/json2.js | 104 - site/webroot/js/jqGrid/js/min/JsonXml-min.js | 1 - .../webroot/js/jqGrid/js/min/grid.base-min.js | 1 - .../js/jqGrid/js/min/grid.celledit-min.js | 1 - .../js/jqGrid/js/min/grid.common-min.js | 1 - .../js/jqGrid/js/min/grid.custom-min.js | 1 - .../js/jqGrid/js/min/grid.formedit-min.js | 1 - .../js/jqGrid/js/min/grid.import-min.js | 1 - .../js/jqGrid/js/min/grid.inlinedit-min.js | 1 - .../js/jqGrid/js/min/grid.locale-bg-min.js | 1 - .../jqGrid/js/min/grid.locale-bg1251-min.js | 1 - .../js/jqGrid/js/min/grid.locale-cat-min.js | 1 - .../js/jqGrid/js/min/grid.locale-cs-min.js | 1 - .../js/jqGrid/js/min/grid.locale-de-min.js | 1 - .../js/jqGrid/js/min/grid.locale-dk-min.js | 1 - .../js/jqGrid/js/min/grid.locale-el-min.js | 1 - .../js/jqGrid/js/min/grid.locale-en-min.js | 1 - .../js/jqGrid/js/min/grid.locale-fi-min.js | 1 - .../js/jqGrid/js/min/grid.locale-fr-min.js | 1 - .../js/jqGrid/js/min/grid.locale-is-min.js | 1 - .../js/jqGrid/js/min/grid.locale-it-min.js | 1 - .../js/jqGrid/js/min/grid.locale-jp-min.js | 1 - .../js/jqGrid/js/min/grid.locale-pl-min.js | 1 - .../js/jqGrid/js/min/grid.locale-pt-br-min.js | 1 - .../js/jqGrid/js/min/grid.locale-pt-min.js | 1 - .../js/jqGrid/js/min/grid.locale-ru-min.js | 1 - .../js/jqGrid/js/min/grid.locale-sp-min.js | 1 - .../js/jqGrid/js/min/grid.locale-tr-min.js | 1 - .../js/jqGrid/js/min/grid.postext-min.js | 1 - .../js/jqGrid/js/min/grid.setcolumns-min.js | 1 - .../js/jqGrid/js/min/grid.subgrid-min.js | 1 - .../js/jqGrid/js/min/grid.tbltogrid-min.js | 1 - .../js/jqGrid/js/min/grid.treegrid-min.js | 1 - site/webroot/js/jqGrid/js/min/jqDnR-min.js | 1 - site/webroot/js/jqGrid/js/min/jqModal-min.js | 1 - .../js/jqGrid/js/min/jquery.fmatter-min.js | 1 - .../js/jqGrid/js/min/jquery.tablednd-min.js | 1 - site/webroot/js/jqGrid/js/min/json2-min.js | 1 - site/webroot/js/jquery/jquery-ui.js | 9133 ----------------- site/webroot/js/jquery/jquery.js | 4376 -------- 366 files changed, 31 insertions(+), 25222 deletions(-) delete mode 100644 site/webroot/css/jqGrid/basic/grid.css delete mode 100644 site/webroot/css/jqGrid/basic/images/cd_run.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/dirty.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/down.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/find.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/first.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/folder.png delete mode 100644 site/webroot/css/jqGrid/basic/images/grid-blue-ft.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/grid-blue-hd.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/headerbg.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/headerleft.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/headerright.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/ico-close.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/last.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/line3.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/loading.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/minus.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/next.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/nochild.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/off-first.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/off-last.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/off-next.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/off-prev.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/plus.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/prev.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/refresh.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/resize.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/row_add.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/row_delete.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/row_edit.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/sort_asc.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/sort_desc.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/spacer.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/tab_close-on.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/tree_leaf.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/tree_minus.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/tree_plus.gif delete mode 100644 site/webroot/css/jqGrid/basic/images/up.gif delete mode 100644 site/webroot/css/jqGrid/coffee/grid.css delete mode 100644 site/webroot/css/jqGrid/coffee/images/cd_run.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/dirty.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/down.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/find.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/first.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/folder.png delete mode 100644 site/webroot/css/jqGrid/coffee/images/grid-blue-ft.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/grid-blue-hd.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/headerbg.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/headerleft.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/headerright.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/ico-close.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/last.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/line3.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/loading.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/minus.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/next.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/nochild.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/off-first.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/off-last.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/off-next.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/off-prev.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/plus.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/prev.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/refresh.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/resize.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/row_add.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/row_delete.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/row_edit.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/sort_asc.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/sort_desc.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/spacer.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/tab_close-on.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/tree_leaf.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/tree_minus.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/tree_plus.gif delete mode 100644 site/webroot/css/jqGrid/coffee/images/up.gif delete mode 100644 site/webroot/css/jqGrid/green/grid.css delete mode 100644 site/webroot/css/jqGrid/green/images/cd_run.gif delete mode 100644 site/webroot/css/jqGrid/green/images/dirty.gif delete mode 100644 site/webroot/css/jqGrid/green/images/down.gif delete mode 100644 site/webroot/css/jqGrid/green/images/find.gif delete mode 100644 site/webroot/css/jqGrid/green/images/first.gif delete mode 100644 site/webroot/css/jqGrid/green/images/folder.png delete mode 100644 site/webroot/css/jqGrid/green/images/grid-blue-ft.gif delete mode 100644 site/webroot/css/jqGrid/green/images/grid-blue-hd.gif delete mode 100644 site/webroot/css/jqGrid/green/images/headerbg.gif delete mode 100644 site/webroot/css/jqGrid/green/images/headerleft.gif delete mode 100644 site/webroot/css/jqGrid/green/images/headerright.gif delete mode 100644 site/webroot/css/jqGrid/green/images/ico-close.gif delete mode 100644 site/webroot/css/jqGrid/green/images/last.gif delete mode 100644 site/webroot/css/jqGrid/green/images/leaf.gif delete mode 100644 site/webroot/css/jqGrid/green/images/line3.gif delete mode 100644 site/webroot/css/jqGrid/green/images/loading.gif delete mode 100644 site/webroot/css/jqGrid/green/images/minus.gif delete mode 100644 site/webroot/css/jqGrid/green/images/next.gif delete mode 100644 site/webroot/css/jqGrid/green/images/nochild.gif delete mode 100644 site/webroot/css/jqGrid/green/images/off-first.gif delete mode 100644 site/webroot/css/jqGrid/green/images/off-last.gif delete mode 100644 site/webroot/css/jqGrid/green/images/off-next.gif delete mode 100644 site/webroot/css/jqGrid/green/images/off-prev.gif delete mode 100644 site/webroot/css/jqGrid/green/images/plus.gif delete mode 100644 site/webroot/css/jqGrid/green/images/prev.gif delete mode 100644 site/webroot/css/jqGrid/green/images/refresh.gif delete mode 100644 site/webroot/css/jqGrid/green/images/resize.gif delete mode 100644 site/webroot/css/jqGrid/green/images/row_add.gif delete mode 100644 site/webroot/css/jqGrid/green/images/row_delete.gif delete mode 100644 site/webroot/css/jqGrid/green/images/row_edit.gif delete mode 100644 site/webroot/css/jqGrid/green/images/sort_asc.gif delete mode 100644 site/webroot/css/jqGrid/green/images/sort_desc.gif delete mode 100644 site/webroot/css/jqGrid/green/images/spacer.gif delete mode 100644 site/webroot/css/jqGrid/green/images/tab_close-on.gif delete mode 100644 site/webroot/css/jqGrid/green/images/tree_leaf.gif delete mode 100644 site/webroot/css/jqGrid/green/images/tree_minus.gif delete mode 100644 site/webroot/css/jqGrid/green/images/tree_plus.gif delete mode 100644 site/webroot/css/jqGrid/green/images/up.gif delete mode 100644 site/webroot/css/jqGrid/jqModal.css delete mode 100644 site/webroot/css/jqGrid/sand/grid.css delete mode 100644 site/webroot/css/jqGrid/sand/images/cd_run.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/dirty.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/down.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/find.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/first.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/folder.png delete mode 100644 site/webroot/css/jqGrid/sand/images/grid-blue-ft.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/grid-blue-hd.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/headerbg.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/headerleft.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/headerright.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/ico-close.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/last.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/line3.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/loading.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/minus.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/next.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/nochild.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/off-first.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/off-last.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/off-next.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/off-prev.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/plus.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/prev.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/refresh.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/resize.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/row_add.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/row_delete.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/row_edit.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/sort_asc.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/sort_desc.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/spacer.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/tab_close-on.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/tree_leaf.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/tree_minus.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/tree_plus.gif delete mode 100644 site/webroot/css/jqGrid/sand/images/up.gif delete mode 100644 site/webroot/css/jqGrid/steel/grid.css delete mode 100644 site/webroot/css/jqGrid/steel/images/._sprite5.png delete mode 100644 site/webroot/css/jqGrid/steel/images/._sprite5.psd delete mode 100644 site/webroot/css/jqGrid/steel/images/Arrow2 Down.png delete mode 100644 site/webroot/css/jqGrid/steel/images/Arrow2 Up.png delete mode 100644 site/webroot/css/jqGrid/steel/images/bg.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/cd_run.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/control_090.png delete mode 100644 site/webroot/css/jqGrid/steel/images/control_270.png delete mode 100644 site/webroot/css/jqGrid/steel/images/dirty.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/down.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/fhbg.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/find.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/find1.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/first.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/first.png delete mode 100644 site/webroot/css/jqGrid/steel/images/folder.png delete mode 100644 site/webroot/css/jqGrid/steel/images/headerleft1.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/headerright1.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/ico-close.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/last.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/last.png delete mode 100644 site/webroot/css/jqGrid/steel/images/line3.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/loading.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/minus.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/next.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/next.png delete mode 100644 site/webroot/css/jqGrid/steel/images/nochild.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/odown.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/off-first.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/off-last.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/off-next.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/off-prev.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/oup.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/plus.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/prev.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/prev.png delete mode 100644 site/webroot/css/jqGrid/steel/images/refresh.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/refresh1.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/resize.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/row_add.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/row_add1.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/row_delete.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/row_delete1.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/row_edit.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/row_edit1.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/sort_asc.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/sort_desc.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/spacer.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/sprite.png delete mode 100644 site/webroot/css/jqGrid/steel/images/sprite5.png delete mode 100644 site/webroot/css/jqGrid/steel/images/sprite5.psd delete mode 100644 site/webroot/css/jqGrid/steel/images/tab_close-on.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/tree_leaf.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/tree_minus.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/tree_plus.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/up.gif delete mode 100644 site/webroot/css/jqGrid/steel/images/wbg.gif create mode 100644 site/webroot/css/jqGrid/ui.jqgrid.css rename site/webroot/css/{jquery => themes}/base/images/ui-bg_flat_0_aaaaaa_40x100.png (100%) rename site/webroot/css/{jquery => themes}/base/images/ui-bg_flat_75_ffffff_40x100.png (100%) rename site/webroot/css/{jquery => themes}/base/images/ui-bg_glass_55_fbf9ee_1x400.png (100%) rename site/webroot/css/{jquery => themes}/base/images/ui-bg_glass_65_ffffff_1x400.png (100%) rename site/webroot/css/{jquery => themes}/base/images/ui-bg_glass_75_dadada_1x400.png (100%) rename site/webroot/css/{jquery => themes}/base/images/ui-bg_glass_75_e6e6e6_1x400.png (100%) rename site/webroot/css/{jquery => themes}/base/images/ui-bg_glass_75_ffffff_1x400.png (100%) rename site/webroot/css/{jquery => themes}/base/images/ui-bg_glass_95_fef1ec_1x400.png (100%) rename site/webroot/css/{jquery => themes}/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png (100%) rename site/webroot/css/{jquery => themes}/base/images/ui-bg_inset-soft_95_fef1ec_1x100.png (100%) rename site/webroot/css/{jquery => themes}/base/images/ui-icons_222222_256x240.png (100%) rename site/webroot/css/{jquery => themes}/base/images/ui-icons_2e83ff_256x240.png (100%) rename site/webroot/css/{jquery => themes}/base/images/ui-icons_454545_256x240.png (100%) rename site/webroot/css/{jquery => themes}/base/images/ui-icons_888888_256x240.png (100%) rename site/webroot/css/{jquery => themes}/base/images/ui-icons_cd0a0a_256x240.png (100%) rename site/webroot/css/{jquery => themes}/base/ui.accordion.css (100%) rename site/webroot/css/{jquery => themes}/base/ui.all.css (100%) rename site/webroot/css/{jquery => themes}/base/ui.base.css (100%) rename site/webroot/css/{jquery => themes}/base/ui.core.css (100%) rename site/webroot/css/{jquery => themes}/base/ui.datepicker.css (100%) rename site/webroot/css/{jquery => themes}/base/ui.dialog.css (100%) rename site/webroot/css/{jquery => themes}/base/ui.progressbar.css (100%) rename site/webroot/css/{jquery => themes}/base/ui.resizable.css (100%) rename site/webroot/css/{jquery => themes}/base/ui.slider.css (100%) rename site/webroot/css/{jquery => themes}/base/ui.tabs.css (100%) rename site/webroot/css/{jquery => themes}/base/ui.theme.css (100%) rename site/webroot/css/{jquery => themes}/dotluv/images/ui-bg_diagonals-thick_15_0b3e6f_40x40.png (100%) rename site/webroot/css/{jquery => themes}/dotluv/images/ui-bg_dots-medium_30_0b58a2_4x4.png (100%) rename site/webroot/css/{jquery => themes}/dotluv/images/ui-bg_dots-small_20_333333_2x2.png (100%) rename site/webroot/css/{jquery => themes}/dotluv/images/ui-bg_dots-small_30_a32d00_2x2.png (100%) rename site/webroot/css/{jquery => themes}/dotluv/images/ui-bg_dots-small_40_00498f_2x2.png (100%) rename site/webroot/css/{jquery => themes}/dotluv/images/ui-bg_flat_0_aaaaaa_40x100.png (100%) rename site/webroot/css/{jquery => themes}/dotluv/images/ui-bg_flat_40_292929_40x100.png (100%) rename site/webroot/css/{jquery => themes}/dotluv/images/ui-bg_gloss-wave_20_111111_500x100.png (100%) rename site/webroot/css/{jquery => themes}/dotluv/images/ui-icons_00498f_256x240.png (100%) rename site/webroot/css/{jquery => themes}/dotluv/images/ui-icons_98d2fb_256x240.png (100%) rename site/webroot/css/{jquery => themes}/dotluv/images/ui-icons_9ccdfc_256x240.png (100%) rename site/webroot/css/{jquery => themes}/dotluv/images/ui-icons_ffffff_256x240.png (100%) rename site/webroot/css/{jquery => themes}/dotluv/ui.all.css (100%) rename site/webroot/css/{jquery => themes}/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png (100%) rename site/webroot/css/{jquery => themes}/smoothness/images/ui-bg_flat_75_ffffff_40x100.png (100%) rename site/webroot/css/{jquery => themes}/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png (100%) rename site/webroot/css/{jquery => themes}/smoothness/images/ui-bg_glass_65_ffffff_1x400.png (100%) rename site/webroot/css/{jquery => themes}/smoothness/images/ui-bg_glass_75_dadada_1x400.png (100%) rename site/webroot/css/{jquery => themes}/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png (100%) rename site/webroot/css/{jquery => themes}/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png (100%) rename site/webroot/css/{jquery => themes}/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png (100%) rename site/webroot/css/{jquery => themes}/smoothness/images/ui-icons_222222_256x240.png (100%) rename site/webroot/css/{jquery => themes}/smoothness/images/ui-icons_2e83ff_256x240.png (100%) rename site/webroot/css/{jquery => themes}/smoothness/images/ui-icons_454545_256x240.png (100%) rename site/webroot/css/{jquery => themes}/smoothness/images/ui-icons_888888_256x240.png (100%) rename site/webroot/css/{jquery => themes}/smoothness/images/ui-icons_cd0a0a_256x240.png (100%) rename site/webroot/css/{jquery => themes}/smoothness/ui.all.css (100%) rename site/webroot/css/{jquery => themes}/start/images/ui-bg_flat_55_999999_40x100.png (100%) rename site/webroot/css/{jquery => themes}/start/images/ui-bg_flat_75_aaaaaa_40x100.png (100%) rename site/webroot/css/{jquery => themes}/start/images/ui-bg_glass_45_0078ae_1x400.png (100%) rename site/webroot/css/{jquery => themes}/start/images/ui-bg_glass_55_f8da4e_1x400.png (100%) rename site/webroot/css/{jquery => themes}/start/images/ui-bg_glass_75_79c9ec_1x400.png (100%) rename site/webroot/css/{jquery => themes}/start/images/ui-bg_gloss-wave_45_e14f1c_500x100.png (100%) rename site/webroot/css/{jquery => themes}/start/images/ui-bg_gloss-wave_50_6eac2c_500x100.png (100%) rename site/webroot/css/{jquery => themes}/start/images/ui-bg_gloss-wave_75_2191c0_500x100.png (100%) rename site/webroot/css/{jquery => themes}/start/images/ui-bg_inset-hard_100_fcfdfd_1x100.png (100%) rename site/webroot/css/{jquery => themes}/start/images/ui-icons_0078ae_256x240.png (100%) rename site/webroot/css/{jquery => themes}/start/images/ui-icons_056b93_256x240.png (100%) rename site/webroot/css/{jquery => themes}/start/images/ui-icons_d8e7f3_256x240.png (100%) rename site/webroot/css/{jquery => themes}/start/images/ui-icons_e0fdff_256x240.png (100%) rename site/webroot/css/{jquery => themes}/start/images/ui-icons_f5e175_256x240.png (100%) rename site/webroot/css/{jquery => themes}/start/images/ui-icons_f7a50d_256x240.png (100%) rename site/webroot/css/{jquery => themes}/start/images/ui-icons_fcd113_256x240.png (100%) rename site/webroot/css/{jquery => themes}/start/ui.all.css (100%) create mode 100644 site/webroot/js/jqGrid/grid.locale-en.js delete mode 100644 site/webroot/js/jqGrid/jquery.jqGrid.js create mode 100644 site/webroot/js/jqGrid/jquery.jqGrid.min.js delete mode 100644 site/webroot/js/jqGrid/js/JsonXml.js delete mode 100644 site/webroot/js/jqGrid/js/grid.base.js delete mode 100644 site/webroot/js/jqGrid/js/grid.celledit.js delete mode 100644 site/webroot/js/jqGrid/js/grid.common.js delete mode 100644 site/webroot/js/jqGrid/js/grid.custom.js delete mode 100644 site/webroot/js/jqGrid/js/grid.formedit.js delete mode 100644 site/webroot/js/jqGrid/js/grid.import.js delete mode 100644 site/webroot/js/jqGrid/js/grid.inlinedit.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-bg.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-bg1251.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-cat.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-cs.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-de.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-dk.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-el.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-en.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-fa.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-fi.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-fr.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-is.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-it.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-jp.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-pl.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-pt-br.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-pt.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-ru.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-sp.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-sv.js delete mode 100644 site/webroot/js/jqGrid/js/grid.locale-tr.js delete mode 100644 site/webroot/js/jqGrid/js/grid.postext.js delete mode 100644 site/webroot/js/jqGrid/js/grid.setcolumns.js delete mode 100644 site/webroot/js/jqGrid/js/grid.subgrid.js delete mode 100644 site/webroot/js/jqGrid/js/grid.tbltogrid.js delete mode 100644 site/webroot/js/jqGrid/js/grid.treegrid.js delete mode 100644 site/webroot/js/jqGrid/js/jqDnR.js delete mode 100644 site/webroot/js/jqGrid/js/jqModal.js delete mode 100644 site/webroot/js/jqGrid/js/jquery.fmatter.js delete mode 100644 site/webroot/js/jqGrid/js/jquery.tablednd.js delete mode 100644 site/webroot/js/jqGrid/js/json2.js delete mode 100644 site/webroot/js/jqGrid/js/min/JsonXml-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.base-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.celledit-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.common-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.custom-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.formedit-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.import-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.inlinedit-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-bg-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-bg1251-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-cat-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-cs-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-de-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-dk-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-el-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-en-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-fi-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-fr-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-is-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-it-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-jp-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-pl-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-pt-br-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-pt-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-ru-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-sp-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.locale-tr-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.postext-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.setcolumns-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.subgrid-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.tbltogrid-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/grid.treegrid-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/jqDnR-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/jqModal-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/jquery.fmatter-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/jquery.tablednd-min.js delete mode 100644 site/webroot/js/jqGrid/js/min/json2-min.js delete mode 100644 site/webroot/js/jquery/jquery-ui.js delete mode 100644 site/webroot/js/jquery/jquery.js diff --git a/site/views/elements/jqGrid.ctp b/site/views/elements/jqGrid.ctp index ba86642..f090b91 100644 --- a/site/views/elements/jqGrid.ctp +++ b/site/views/elements/jqGrid.ctp @@ -46,12 +46,12 @@ if (!isset($grid_setup)) $grid_setup = array(); // Do some prework to bring in the appropriate libraries -$imgpath = '/pmgr/site/css/jqGrid/basic/images'; -$html->css('jqGrid/basic/grid', null, null, false); -$html->css('jqGrid/jqModal', null, null, false); -$javascript->link('jqGrid/jquery.jqGrid.js', false); -$javascript->link('jqGrid/js/jqModal', false); -$javascript->link('jqGrid/js/jqDnR', false); +$html->css('jqGrid/ui.jqgrid', null, null, false); +//$html->css('jqGrid/jqModal', null, null, false); +$javascript->link('jqGrid/grid.locale-en', false); +$javascript->link('jqGrid/jquery.jqGrid.min', false); +//$javascript->link('jqGrid/js/jqModal', false); +//$javascript->link('jqGrid/js/jqDnR', false); $javascript->link('pmgr_jqGrid', false); @@ -231,7 +231,6 @@ $jqGrid_setup = array_merge 'sortname' => $sortname, 'sortorder' => $sortorder, 'caption' => $caption, - 'imgpath' => $imgpath, 'viewrecords' => true, 'pager' => $grid_id.'-pager', ), @@ -251,16 +250,16 @@ $jqGrid_setup = array_merge diff --git a/site/views/layouts/default.ctp b/site/views/layouts/default.ctp index 22f33ce..5cb289a 100644 --- a/site/views/layouts/default.ctp +++ b/site/views/layouts/default.ctp @@ -35,12 +35,12 @@ echo $html->css('layout') . "\n"; echo $html->css('print', null, array('media' => 'print')) . "\n"; echo $html->css('sidemenu') . "\n"; - //echo $html->css('jquery/base/ui.all') . "\n"; - //echo $html->css('jquery/smoothness/ui.all') . "\n"; - //echo $html->css('jquery/dotluv/ui.all') . "\n"; - echo $html->css('jquery/start/ui.all') . "\n"; - echo $javascript->link('jquery/jquery') . "\n"; - echo $javascript->link('jquery/jquery-ui') . "\n"; + echo $javascript->link('http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js') . "\n"; + echo $javascript->link('http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js') . "\n"; + //echo $html->css('themes/base/ui.all') . "\n"; + //echo $html->css('themes/smoothness/ui.all') . "\n"; + //echo $html->css('themes/dotluv/ui.all') . "\n"; + echo $html->css('themes/start/ui.all') . "\n"; echo $javascript->link('jquery.form') . "\n"; echo $javascript->link('pmgr') . "\n"; echo $scripts_for_layout . "\n"; diff --git a/site/webroot/css/jqGrid/basic/grid.css b/site/webroot/css/jqGrid/basic/grid.css deleted file mode 100644 index 84ed2c4..0000000 --- a/site/webroot/css/jqGrid/basic/grid.css +++ /dev/null @@ -1,447 +0,0 @@ -.GridHeader { -} -.Header { - width: 100%; - } - -.Header th { - font-size: 100%; font-weight: bold; text-align: left; - padding: 2px; - background-image: url(images/headerbg.gif) ; - color: #FFFFFF; - width: 100%; - white-space: nowrap; - } - -.HeaderLeft { - background-image: url(images/headerleft.gif); - } - -.HeaderRight { - background-image: url(images/headerright.gif); - } -.HeaderButton { - background-image: url(images/headerbg.gif); -} -.HeaderButton img{ - width: 17px; -} - -.HeaderLeft img{ - width: 14px; - } - -.HeaderRight img{ - width: 10px; - } - -.GridHeader table {margin:0;} -.GridHeader td, tr {padding:0;} -/* Grid */ -table.scroll { - table-layout: fixed; - /*border-right: 1px solid #D4D0C8;*/ - margin-bottom:0; -} -table.scroll tbody tr { - background-color: #ffffff; -} - -table.scroll tbody tr.alt { - background-color: #F9F9F9; -} - -table.scroll tr.over td{ - background-color: #E1DCF4; -} - - table.scroll tr.selected td { - background: #3d84cc; - color: White; -} - - table.scroll tbody td { - padding: 2px; - text-align: left; - border-bottom: 1px solid #D4D0C8; - border-left: 1px solid #D4D0C8; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - height : auto; -} - - table.scroll thead th { - padding: 2px; - border-bottom: 1px solid #CBC7B8; - border-left: 1px solid #D4D0C8; - text-align: left; - font-weight: normal; - overflow: hidden; - white-space: nowrap; - background-image: url(images/grid-blue-hd.gif); - height : 17px; -} - - table.scroll th div { - overflow: hidden; -/* white-space: nowrap;*/ - word-wrap: break-word; - height : 17px; -} - table.scroll th span { - cursor: e-resize; -/* border-right: 1px solid #D6D2C2; */ - width: 10px; - float: right; - display: block; - margin: -2px -1px -2px 0px; - height: 17px; - overflow: hidden; - white-space: nowrap; -} - -/* End Grid */ - -/* Pager */ -div.scroll { - vertical-align: top; - height: 23px; - white-space: nowrap; - text-align: center; - background-image: url(images/grid-blue-ft.gif); -} -div.scroll span { - vertical-align : top; -} -.selbox { - font-size: x-small; - vertical-align : top; -} -input.selbox{ - font-size: x-small; - vertical-align : top; -} -.pgbuttons { - margin-top :2px; -} -.nav-table-left { - padding:1px; - float: left; -/* position:absolute;*/ -} -.nav-table-right { - padding:1px; - float: right; -} - -table.navtable {margin-bottom:0; width: auto;} -table.navtable tr{ - background-image: url(images/grid-blue-ft.gif); -} - -table.navtable td.nav-button { - border: 1px solid #E2ECF8; - white-space: nowrap; -} - -table.navtable td.nav-hover { - border: 1px solid #83B4D8; -} - -table.tbutton tr td{ - border : none; - padding:0px; -} - -img.jsHover { /*not used */ - border: 1px solid #99CCFF; -} -/* End Pager */ -/*multiselect checkbox */ -.cbox { - height: 10px; - width: 10px; - /*border:1px solid #999;*/ -} -/* end multiselect */ - - -/* loading div */ -div.loading { - position: absolute; - padding: 3px; - text-align: center; - font-weight: bold; - background: red; - color: white; - display: none; -} - -div.loadingui { - display:none; - z-index:6000; - position:absolute; -} - - -div.loadingui div.msgbox { - position: relative; - z-index:6001; - left: 35%; - top:45%; - background: url(images/loading.gif) no-repeat left; - width: 100px; - border: 2px solid #B2D2FF; - text-align: right; - height: auto; - padding:2px; - margin: 0px; -} -/* end loading div */ -/* toolbar */ -div.userdata { - margin-top: 0px; - background-color : #EAF9F9; - height : 20px; - overflow: hidden; -} -/* end toolbar */ -/*Subgrid text mode*/ -.subgrid { - height: 100%; - overflow: auto; -} -.tablediv { - background-color: White; - border-spacing: 1px; /*cellspacing:poor IE support for this*/ - border-collapse: separate; - width:100%; /* FF hack poor when scroling subgrid */ -} -.celldiv { - float: left; - display: table-cell; - border: 1px dotted #CCCCCC; - overflow: auto; - white-space: normal; -} -.celldivth { - float: left; /*fix for buggy browsers*/ - border: 1px solid #CCCCCC; - background-color: #99CCFF; - border-bottom: 1px solid #CBC7B8; - text-align: left; - overflow: auto; -} -.rowdiv { - display: table-row; - background: #F9F9F9 none; - color: #000000; - width: 100%; - overflow:auto; -} -/* End Subgrid */ - -/* InLine editing */ -input.editable[type="text"] { - font-size: x-small; - overflow: hidden; - height : 15px; -} -input.editable[type="checkbox"] { -} - -textarea.editable { - overflow: hidden; -} - -select.editable { - font-size: x-small; -} -/* End Inline Editing */ - -/*Modal Window */ -.modaltext{ - text-align : left; -} -.modalwin{ - border:1px solid #555555; - background:#F9F9F9; - text-align:left; - margin: 0 auto; - overflow: auto; -} - - -.modalhead { - background-image: url(images/grid-blue-hd.gif); - height: 20px; - -} -.modalcontent { - overflow: auto; - margin-bottom: 9px; - margin-left: 5px; -} -/* end Modal window*/ -/* Search window */ -input.search { - margin: 2px; - width: 70px; - font-size: 10px; - color: #15428B; -} - -select.search { - margin: 2px; - width: 70px; - font-size: 10px; - color: #15428B; -} -.buttonsearch { - width : 50px; - font-size: 10px; - color: #15428B; -} -/*End search */ - -/* Form edit */ - -.FormGrid { - margin: 0px; -} -.EditTable { - width: 100%; -} - -.FormData { /* tr */ - -} - -#FormError td { - font-size: 90%; - color: #FF0000; - vertical-align: top; - background-color: #f7f7f7; -} - -.CaptionTD{ /* td */ - font-weight: normal; text-align: left; vertical-align: top; - padding: 1px; - border-top: 1px solid #D4D0C8; - white-space: nowrap; - color: #000000; -} -.DataTD { /* td */ - padding: 1px; - border-top: 1px solid #D4D0C8; - vertical-align: top; -} -.navButton{ - border-top: 1px solid #D4D0C8; - border-bottom: 1px solid #D4D0C8; - text-align: center; -} -.navButton input{ - width:17px; -} -input.EditButton { /* buttons are at footer tr */ - font-size: 10px; - color: #15428B; -} -td.EditButton { - text-align: right; - border-top: 1px solid #D4D0C8; - border-bottom: 1px solid #D4D0C8; -} - -.FormElement { /* form element - input -text,textarea,checkbox - select */ - -} -.FormElement { - font-size: 10px; -} -input[type="text"].FormElement{ - color: #15428B; -} -input[type="checkbox"].FormElement{ - width: 15px; - color: #15428B; -} -input[type="textarea"].FormElement{ - color: #15428B; -} -select.FormElement { - font-size: 10px; - color: #15428B; -} -/* End Eorm edit */ - -/* Delete Dialog */ -.DelButton > input { /* buttons are at footer tr */ - font-size: 10px; - color: #15428B; -} -.DelButton { - text-align: right; -} -/* End Delete Dialog */ - -img.jqResize { - position:absolute; - bottom: 0px; - right: 0px; - cursor :se-resize; -} -.dirty-cell { - background: transparent url(images/dirty.gif) no-repeat 0 0; -} -#DelError td { - font-size: 90%; - color: #FF0000; - vertical-align: top; - background-color: #f7f7f7; -} -/* Tree Grid */ -.tree-wrap -{ - float: left; - position: relative; - height: 18px; - white-space: nowrap; - overflow: hidden; -} -.tree-minus -{ - position: absolute; - height: 18px; - width: 16px; - overflow: hidden; - background: url(images/tree_minus.gif) no-repeat; -} -.tree-plus -{ - position: absolute; - height: 18px; - width: 16px; - overflow: hidden; - background: url(images/tree_plus.gif) no-repeat; -} -.tree-leaf -{ - position: absolute; - height: 18px; - width: 16px; - overflow: hidden; - background: url(images/tree_leaf.gif) no-repeat; -} -.treeclick -{ - cursor: pointer; -} -.edit-cell { - background-color: #E1DCF4 !important; -} -.selected-row, .selected-row TD { - background-color: #3d84cc; -} \ No newline at end of file diff --git a/site/webroot/css/jqGrid/basic/images/cd_run.gif b/site/webroot/css/jqGrid/basic/images/cd_run.gif deleted file mode 100644 index c2b8f4edabad00e11a69889bae33c9b91717c6f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1025 zcmeH`?=RGG0LMQU8fEQ@HZxmSY}CT(N~kT4B&L>@)!OVlX_bChJ@KTaU)ItX!ktsO z!+3x!r-*Ru<{W3byVdBr)7^bJ9Ot;>zOJu#{0Tkp{owuV{owt2?|trkYFvCSo3P2c zkch^xB`dHDxLj)kR%`^ZuInMX}|&SUUO;Y553``C@OE_#M6>@q6ruc7M;dQ0V8%8 ze$9T+qxlEKUqx@`1P!t&@muMm;aussL}kUI)mp2?%8Elqp>eExewNCUr&kRwXE$Xr z4D+z_?gLe-)`N;_X>+&w)a$qzCtaz2Hn|Fk4hn_oadB<06~a-BtM$i zl(u_1UbzZ-z2$gm^ssv2R_p!mORF@!DO6(`NUV?U`7)s0fXlhgeHmF*Cv&?ujD~4x z+sG7y*3Myt!dSd`vFWo>vxKfblWYn@mhBPAfBidwgS0n`5Ft6b9o_x}@imYbzmT+c zfjlXvD&^zqZ@>lyj2t2o f3la`CGVn;rtSCr4)W)vpHOFJ)qNAORj11NQ63h`c diff --git a/site/webroot/css/jqGrid/basic/images/down.gif b/site/webroot/css/jqGrid/basic/images/down.gif deleted file mode 100644 index 808d921109cc45d98a755011cd02a6ab4c3c8e66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 309 zcmZ?wbhEHb6krfwSZd9n;xR$PcbabSJmbh^776R^Gq%g7ebrAnub+BZC+&to(h0+? z+ZK6u?22#Om)=#$`lM6%&ZOvtUENQY`~yz8SG-D3_*Y->sJic0{m|jRLvX{j;Fi0g zt@k3@@B4Rs^Y8o{*!(cO{XtmE%gC-r@!b#NdmbkAJW1_;ojLJw#+0YolV9ggdy_l! zS^AvcnX~?9%=uY3>v`S$cTEePx32r&yZS@Ny8qL*ykEHQ!=kd5>5s6g>2 z3nK%AJ%bJd5P)v+tO2Y= Bm5TrX diff --git a/site/webroot/css/jqGrid/basic/images/find.gif b/site/webroot/css/jqGrid/basic/images/find.gif deleted file mode 100644 index 39a0dac9ddcce982cb99dd4229089a0a810cd371..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 986 zcmZ?wbhEHb6krfw_};{@bm`4|_x^9)dVBixQ`4rMYX2PF^(|)Q%8SdE-L_w0f9Kv; zjp>H<^_vzgy71-qm*vZEuUK*Jz=3y*7oT-GsGGPup{#6nRn@BH%g^-p@6XL$(BHqO zw|C#=%g;7%zIo~D(>Zev{Q3Lm|NsBXmtUSU=h%`Z7x?PA&!7Khzshdix*H1f#7>?1 zps`%NzJ9}zBah`5h@Cm}pu2n9(xtaHZ+`gc*QctgwQjXBr%%7|nip~F*7sAVp5MCl z^Zon(=1XjE-TKhmyLR#7Q)_qZ-MaOHjZN(x(>lDzVyj1NZbJrhO!IOgpSmfH~m+o1We# z15FOb3!)5$Y)4K8JMnci`QC~+d2vy5yOcwh#GVG_3(O2GuUHC;k0eZy^4ag{ zZHv4+cEz{tOYf>=ebOm>XHxXSuI{Hx{sE`lD_*51{Hrf`RNeQhe(3PuA-LgMaLe7$ z)_W1{_x-!R`FH*eYuz6C>RX^ z>V<&fPZnkd21y1TkddG~!N5_)V9X)ov0=f%X7@MtwUbVx|CCuD_3M1(}kL@rTAt`?@NJD7g1T-cVt+{lozLxII0fq`Ms9dUP2 S4@VK8*$kepelF{r5}E+oVobaM diff --git a/site/webroot/css/jqGrid/basic/images/grid-blue-ft.gif b/site/webroot/css/jqGrid/basic/images/grid-blue-ft.gif deleted file mode 100644 index cd094e9671ae64690869967e5079549e55f1eb51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 821 zcmZ?wbhEHbWMmL!_|Cv^v*lLz=6id7 o^S3?nnD(r5*{f6A-fDZ_uA=K5H7NRlhVmDjn1+k{blZ5X6^D|cw6R0k)7n5yb zZE29zl^5qxm(!AvR^sPlmXuOa6%de@&{2>P=HXLRX5PdsF0H`N#3anm z!@6%DkCF_Nps1k8&XYSmL`50SU$}Vb@|COCuHU$M>-L?y_wGM<_~`MIr_Y|hc=_t} qo44=YfB5+6^OvvRzW@07>o+jS|1&Ui$#`s7aIl#}_#HPBgEau)H?u4N diff --git a/site/webroot/css/jqGrid/basic/images/headerright.gif b/site/webroot/css/jqGrid/basic/images/headerright.gif deleted file mode 100644 index 3ef5e02449a2d8023f8ae24ee2806887e938de25..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 87 zcmZ?wbhEHbv*lLz=6id7 o^S3?nnD(r5*{f6A-fz>x6;A zVHOq!Hjfa6LWZNAV%#Aq5rqw{ZGtLZ5)4d-82hC89V8eU65E*h#SH#LC>&^J7E=wV zseF*)Jk>5bZ;NCCQ(zyLTiBC=28YWG8m(S`IvAcYvdC$_idl8(2_v6a4ag{ zZHv4+cEz{tOYf>=ebOm>XHxXSuI{Hx{sE`lD_*51{Hrf`RNeQhe(3PuA-LgMaLe7$ z)_W1{_x-!R`FH*eYuz6C>RX^ z>V<&fPZnkd21y1TkddG~!N5_$V9X)ov0=f%X7)sh7DeV(M==$yO&0_YC2+|IvM<}Q z@ZbVY8B+}&lf=VK2L;XIwg}8jWa;H%bG(qjsCck}MX*~6o0a?iZC!S=m6P3Ss?}nCh;l#D>+~DyLOwL V>$-Y2<`-MpBadm%W{NOa0{{&)7qb8W diff --git a/site/webroot/css/jqGrid/basic/images/loading.gif b/site/webroot/css/jqGrid/basic/images/loading.gif deleted file mode 100644 index e846e1d6c58796558015ffee1fdec546bc207ee8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 771 zcmZ?wbhEHb6krfw*v!MQYQ=(yeQk4RPu{+D?cCXuwr^cCp}%d_ius2R?!0jBXnAQ) zOH<|l|Nj|aK=D7fpKD04vtxj(k)8oFBT!uNCkrbB0}q1^NDatX1{VJbCr|b)oWWMT zS%hVC ~NwO_yO%;SvZ5MdNYf|QNy-I*%yJaj+uTdt+qbZ z4E`Fzb8m}I&!N8OKmWEcCmrLs^Hs&3i)mt@hQVdcqghkaBs*D}tG_lKew4?rTjzIZ z9tSone1TS+TR7tu^CunG)Y7Jg#sw#)sG9C!c0I%LEzP)9;hqRf&)s$D8d5Db{TBs% zgl0~5QQ91luq4Q9tJgt4QLbaxZvAaKeCM9!oy85dg4k>TdBSVqjHub_PG=PO&J-rx z7oYTuF+kH|tG-UK+EkUhDjYx?zW?T|lx>+aOQm zzL$v$zBLo4Cj=G&tw{H}dW?tlTkS)SY4<#NS92z*EY-MMB6Ftp`R=*=*Ev7cS+X%W zMCur^FdlokL}1Y+&aasU2J4#EOuNlnb9CmqgLCGTSY!1BD42pkHY^XidQ5=>YQx%` z*%Pm9D!CkBu&tMWm(%-ejACVWGS2RX5=QOJ$1*tr7F}F+*-OA+Ly&Isg|AEuUYicA z#%IG6kPXkHt{zk2M6zK@Vu^4Q(1zE$?yY6M!^&jQ+2^E?!p7{g*|X6}vuRC3p@jk0 W117c83?+LXEZI4G$p&LV25SKE>nb+@ diff --git a/site/webroot/css/jqGrid/basic/images/minus.gif b/site/webroot/css/jqGrid/basic/images/minus.gif deleted file mode 100644 index ef04a54696e17442f7d3a858b18e2da9db1c2e34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85 zcmZ?wbhEHb6k-r!n8?8J|NsA%mKFvuL-8jIs|W)#gAR}jloeuNU{agYzw-23{>5Bd lu8B3=Q%KlX>BCkwzhTj{h;`hYUHRJn(^Q}S;uB@C1^}ss9ftq_ diff --git a/site/webroot/css/jqGrid/basic/images/next.gif b/site/webroot/css/jqGrid/basic/images/next.gif deleted file mode 100644 index 960163530132545abe690cb8e49c5fef0f923344..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 875 zcmZ?wbhEHb6krfwXlGzh@tC0DJ54uuo^j+di-h&|8QW#kzUrr(*H68ylXk-(>4ag{ zZHv4+cEz{tOYf>=ebOm>XHxXSuI{Hx{sE`lD_*51{Hrf`RNeQhe(3PuA-LgMaLe7$ z)_W1{_x-!R`FH*eYuz6C>RX^ z>V<&fPZnkd21y1TkddG~!NB3cV9X)ov0=f%W)9;69vKr@Ionu*A5?G{Hgn3DYJ|un wK6d5q<#D`_!KiqUp-ntt3Jb$U#ts%8MWY1*!jGC}2?&SWIk{Q=U;~3S0KQg&YXATM diff --git a/site/webroot/css/jqGrid/basic/images/nochild.gif b/site/webroot/css/jqGrid/basic/images/nochild.gif deleted file mode 100644 index cf6c61ce9550a7c2a8b546151b7349027979b35f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66 zcmZ?wbhEHb%@85yhrgPhY%v@z$+dw{PFR zd-v{x2M-uV!Dt8!L;Mq+#E6<8x|aFW_O4e+3))3Q*|Q=94?bWMk!6jGP<+(r$fM>Xwqe7gmNr&4?FkK$jz>EMMFb>zJ~*Z~ zvMU=|C?p6pu`gocw@ENKkig96%Ptk5a9{xwcPOV4M}k2k%Q{v@i4+D0okN>5F7xql HFjxZs_zi%( diff --git a/site/webroot/css/jqGrid/basic/images/off-last.gif b/site/webroot/css/jqGrid/basic/images/off-last.gif deleted file mode 100644 index 869706777ce1e5c8350e0086f6febc18aa2bf814..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 923 zcmZ?wbhEHb6krfwXlGzZPfyRu$tfx-s;H=_udjFb@6guP*52OU-QC^W+uPUI*Wcei zY0{+0lP6D^GG*q>nX_llo;Ppa!i5VLFJ8Q4$&%&Em#6pV(z;0OW5pDfG_ z46F<~Am@Pc1OrC}12>0^$A$$5o7t@;-Y_UNJMxKf6&W}lT+k*Y$eyJjc<@21kdg?` z9)m}X2f37ODg+`IICZeGskVGL@ZdlLlaQT?!H)&bz6?zAIR*(A8e5nhSgkHN9C*OQ m>dC5ipkT8?(+Va*AAy7q4&fY(0%9#)p=)k#W@Tbxum%8@3U^Ha diff --git a/site/webroot/css/jqGrid/basic/images/off-next.gif b/site/webroot/css/jqGrid/basic/images/off-next.gif deleted file mode 100644 index 90a7756f6fd77f74fd2b5786dd3586b5c50c8d89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 875 zcmZ?wbhEHb6krfwXlGzZPfxF?sBrl2(B9tO-QC^S*Vo_QKWWmWDO0A*oH=vh!iCG1 zFJG}@#i~`SHg4Rwb?esc+qduBx%1@7lc!IgzIgHC?c28*M!{$Z4A~G+{K>+|z`(?y z1M&eVPcU$JFtBpScx+g3u$hC^!6V}XBXb*zY)A!1phGj4Fjq*7gQ62lFOR54M?r!E kLmQ{U6cz@-#wJD`MJWvdVWq}d0_-7oPHt8|*uY>70KTb0MF0Q* diff --git a/site/webroot/css/jqGrid/basic/images/off-prev.gif b/site/webroot/css/jqGrid/basic/images/off-prev.gif deleted file mode 100644 index 37154d62406ddc064dba311b95f554e49ad38003..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 879 zcmZ?wbhEHb6krfwXlGzZPfyRu$tfx-s;H=_udjFb@6g=b+}hgO*4EbD-QC;U+t=4O zY0{+0lPAxdIdk5;dGqJbU$}7L;>C-XELpN*#fp_HSMJ!cW9QDDr%#{0ef##^yLTBz z!Dt8!oe)s`$->OQz{;Qlaxy4SFmU)VaC69bY*=uxnSOV diff --git a/site/webroot/css/jqGrid/basic/images/plus.gif b/site/webroot/css/jqGrid/basic/images/plus.gif deleted file mode 100644 index abb84bdfbfa5fbd6f188a3a65eec7b077229eef3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89 zcmZ?wbhEHb6k-r!n8?8J|NsA%mKFvuL-8jIs|W)#gAR}jloeuNVA7h?zw-23{>5Bd pu8B3=Q+S}8BR4s7p_$&y1Do!qcNrAyQ&FEhP4(+PeoY1jYXCC)AI<;( diff --git a/site/webroot/css/jqGrid/basic/images/prev.gif b/site/webroot/css/jqGrid/basic/images/prev.gif deleted file mode 100644 index eb70cf8f6a3b7f524bbeb3656d875a823b27fd7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 879 zcmZ?wbhEHb6krfwXlGzh@tC0DJ54uuo^j+di-h&|8QW#kzUrr(*H68ylXk-(>4ag{ zZHv4+cEz{tOYf>=ebOm>XHxXSuI{Hx{sE`lD_*51{Hrf`RNeQhe(3PuA-LgMaLe7$ z)_W1{_x-!R`FH*eYuz6C>RX^ z>V<&fPZnkd21y1TkddG~!NB3eV9X)ov0=f%W)AK)kBA8^Y;DZmPc|?ZI=9Q{X*oQZ zkbJD2lgIqQijPiCj2*mD6%7sx9yN0CvxS^laG;@KrlbJNftid9=jS`{vav8&0{~Hw Bh1385 diff --git a/site/webroot/css/jqGrid/basic/images/refresh.gif b/site/webroot/css/jqGrid/basic/images/refresh.gif deleted file mode 100644 index fb74a02ad4fb7d0fe7ad2070ff5dad786bdf417d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 581 zcmV-L0=oT2Nk%w1VGsZi0Oo%HS+f74(f_^H^St8!pws{6^#85G9r?e+XDgwaf&=_-KIbiV&XdBcje<1CBig{9V;%>LHl^u^-;dBOj%-~Sqb?D+Zo zq169wr`*on^GL1#QhvfJm;ZIX{}gn_DwX_CiPpO0|4N42OQGS`=Jxjc|4**}g{k0g zs^mnP;GMqakiO?Mi{iZH|0;RV5LmHmv+rx1)$8*7Wt-jo{{J_3$x@@?L#O|CxA+{8 z_+X~&B7oMa%r~jYN|0jFZ#NGCY%KwPx!A^8LW004ggEC2ui z01yBW000M~fPaF6goTDME!3Lt_(C_8KpQC&7}GEM^~Z-N~M7f&2nV;(pqTytgy zf_n&kMhy}Sg&TuvVF^S(ez1a6Un5HpX?cTQEQEGfDXQQBphXHDCRWfm5>RHvhaw>~ TY>_8q${jvKpvc=OC=dWU{>VZe diff --git a/site/webroot/css/jqGrid/basic/images/resize.gif b/site/webroot/css/jqGrid/basic/images/resize.gif deleted file mode 100644 index 05c807bbcee95410e01fed7a9900bba24ba3a339..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 862 zcmZ?wbhEHb6krfw_|Cx4($aG6+PVLuU^E0qWC$q!WMO1rU}Vr?00K~+VBoN3VCInV z*s$PWGl#HN%n5^rhBiJ%6A=c7M^0U0qDdtyHYOcukv5m(d0DvR_yjgjuO$%ysYiPB Klk<2u7_0#kRTRwt diff --git a/site/webroot/css/jqGrid/basic/images/row_add.gif b/site/webroot/css/jqGrid/basic/images/row_add.gif deleted file mode 100644 index 847ea1d9bde19af1c36349ff7d9c413d986002eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 635 zcmaKp+e_1N7>D2KR7R!CW1e-1qE1RP@epY=b()!#n2B0ak;RU>FF~S3iUWh2X=|9kO{keHQPkupOdPWT!*ziXV>+5)M zfMa81YYR;#Q-41JJt&n*P=ijV0|`hZ5^BF%zgK~;_*$)2uh)Ydy1Tpaa|KRT;`d%8 zH|=(^w}%u(;fH%R8^QNwjg5_?qolpPoit_8G|^}@DwS$y2Sp;0!C=5Q#h`-iZ3GJN zTbspVIXc1@zxh_H6`k4826)U5dUX|@PAATq#bWXPJ`N2L&;h=^O`5Zy85|BWGD0>s z@bD02G8uFLQCz^O2S%f@W%KUtE^cljP8;yk{jRPqnx=80#OWkNlUZ9^i}p-V0#0`> zFC)GyU0g(*dkI1SE!b=}#Uc-17eO6JrBbumED#8ULLtug;dtT9%mOrk%S99l1=49? zf`(tY3#1bafMfYRJw5ofYG8mYE#cZ4uB@DRz<-H8U^3wNQSQm=qzQQaY?5=i;)hIT zUU0B)Y-|x*E@!4BG2G6@xP!D_Ru@V6CS9}i_R%&L#bz+lBlz(yYn=}j>E;%Zo$>V6 zRga+1Xb#27^$)p{757-gyLjhWIOQYp3o9uO^ez{ql_s92IQ}=nqT;H&1D+>%CVElf zej#O1ftMZy2u~*$UgqdquaD=bQ?^@D|EeL^;a<N^h$ISJ6 ys5|1%`ty7_t|zUDIRH6drcPOdsE^!o$smuFTr=UAosTJW4DwA0Rl})l$odBY{~Kli diff --git a/site/webroot/css/jqGrid/basic/images/row_delete.gif b/site/webroot/css/jqGrid/basic/images/row_delete.gif deleted file mode 100644 index bd6e784c5f61c4dcde504e280a2c8bebc629dfc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 634 zcmV-=0)_oYNk%w1VGsZi0Oo%HnVGYblaqdae#AO8d3kwlZEcj4l*J?ykB^V<@Bjb3 zS88f%XlQ8vqdldiv!S80ot?A)XD#{p|E;aF;^P19?f=);|K;WXqN20v>i^&0|Nope z*x3Jyii(z&mY$xohlhv%nKPQ2v-9)+|DHJT@c;jyI{&Fd;NbuK{Qr@Wk=51ztgN$* zjg5qagpiPscXxNUBq7?`|FSbIr>C>76bZYKP_uV0up}e@tw(Wjar8+XzakLvsD|^i zp8v{%|J9+hbuRy1CEniu+1da1_y4FSC)1{iw03sAprFpW!RON7)6@U^`~R^jD5j>l z|7|(HFDd_}KmXsZ|E@^F!ovT3KmW#l|I2jLG!@+3|J}B}!W|R;t3|*mA^(~*|8gw< z|Nq@T9H*zJ|4tXdKRy4rRR3Wqvx7VTZ7affc+Yxt|FBB`v`({fE4aA0yt=yo!d(Bw zU#O_FtE;pB*`@#7q_cD^#5E!RTOf3FbnNW^|6CQjAQkfR|NsC0A^8LW004ggEC2ui z01yBW000NqfPWqy1_l9#Dk?7sj4gkE0bwZ;6C))R85kE78Xb=>DNU4?n3|j*k1Y}s zMJ#>^rJEWqj~x>eEOc`;4h|0w9}u*EAaZdEXl89}IX6-!8v>6mSau3Fbw5;HK@B8d z(tid$15-y)K36Aq-XR2!Ra{VOGihExCvMOoFpqCWR>Yh+pyWv~5dZ+_c{FAVj|e-| zBtS7lgbWTAbUadXAcBxQeU_lm0s!NR0*`Qj$%2Orp8P14gdfE diff --git a/site/webroot/css/jqGrid/basic/images/row_edit.gif b/site/webroot/css/jqGrid/basic/images/row_edit.gif deleted file mode 100644 index 12cc7e6fbb0215bbafaea389043a9eeb2aa674c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 996 zcmZ?wbhEHb6krfw_&$xHv~8F-0yB!+ZZex?%*0$^a!S&6qXJwUj>c`3c{%yVg;#*p__x_Hps;&R{@qc6E=GCju zZr}bm>a<1dQR~HvFTHy8Yw3x&SBEDYIr4Jl$_tAZpZfjx_o-7KE?#`{;>G`p9cf#( zJnZh?+uOVL*yOqp5Z!cYXv#@Y!SXf)<*O=wYFW`^SNvK16TW98cPn(t$7!G{`{x@^R<`PWZj8$x_$eMZ2j05%^VY6ivG*MIJSv+q)dOjy9sz!=Up?PM}1D+i1FjypFGGqLkF@@@0ku&}9PhFbuW1>=Mh6CEUsXT*3s zUN}LHkx|ElaYKT_LcL&#A1@7-otkA)px`0F(bg_**?)*-V=$+uh$=5v9i!9ACI!!w zc^L*S3l{LWHab0cXv}hf+noLPpA(4=F8o&J3bG#h)yUAf^t80Ld^gF}W}@SOWlZ0R#L1 diff --git a/site/webroot/css/jqGrid/basic/images/tab_close-on.gif b/site/webroot/css/jqGrid/basic/images/tab_close-on.gif deleted file mode 100644 index 822726888b5dec2b575c81f700a8ede0922d9033..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 351 zcmZ?wbhEHbQ=gxgiOWV%C@c;k+Pobd~85s64Fnsj!Il{p3IWu!F z1H&^0hPM(D|I5qY>*;-Pbo>+^{)U_TV?e+L28L@uHQCwkb#*^_d+%ppc*?-=!N%sD zqT*!+hIcwT+ZY%wF))0Ji`&J(unBBF1GRzTPZmZ71{DS!kij57F|gG*Oe*lu;bT0J zvWa6ui&E>0l*d0UX0C3q`TL1t6 diff --git a/site/webroot/css/jqGrid/basic/images/tree_leaf.gif b/site/webroot/css/jqGrid/basic/images/tree_leaf.gif deleted file mode 100644 index febfda63651a83fd2614e6fb61e973c5330fbb40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 134 zcmZ?wbhEHb6lM@-*v!KaP`15m{XrJ9x%Z!a?Av@OsAg0C+)chETbWJgzW?&ir|MAA zg3Sy_K=CIFBLf2ugAPaxWCjC^@r09}tM^*GKD+z>0~47J2A;bUB^((`IyMS4UeIK8 dye$*JvQ|8uL10F}!X-r~bFAiH@MdAK1^}~nFHQge diff --git a/site/webroot/css/jqGrid/basic/images/tree_minus.gif b/site/webroot/css/jqGrid/basic/images/tree_minus.gif deleted file mode 100644 index bdfa2ecfc397e0665a8c7bdb746b1ba7a9f64a40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132 zcmZ?wbhEHb6lM@-Sj5Wk|NsBwIp>nk{hu>uPI7WGkjnrDia%Kx85md@bU-|iS_Wp% zh+TL78B8-=BFzx6yFl&El-hs;6_2m6tg+a)N{EB$_dSLkXSVb{=aE}0w&P{f;dvJi gdR=pKU$((xlF9tQ)w+Z^fq{)d2gqgs zsbygH&)9Wm-xE()md?$giG_TO$18&w8e#%d+BoMdTre%a_tfFX*YsyuTi^5ikj+xL pQ0Z}o@~al#r%WueUek}Obl)o86s7hyoKdOw{EIDBdp#H!tO1AYH}e1h diff --git a/site/webroot/css/jqGrid/basic/images/up.gif b/site/webroot/css/jqGrid/basic/images/up.gif deleted file mode 100644 index 13f75f0e36d8276404ea02ab6c26bae607cd26c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 312 zcmZ?wbhEHb6krfwSZd9n;xR$PcbabSJmbh^776R^Gq%g7ebrAnub+BZC+&to(h0+? z+ZK6u?22#Om)=#$`lM6%&ZOvtUENQY`~yz8SG-D3_*Y->sJic0{m|jRLvX{j;Fi0g zt@k3@@B4Rs^Y8o{*!(cO{XtmE%gC-r@!b#NdmbkAJW1_;ojLJw#+0YolV9ggdy_l! zS^AvcnX~?9%=uY3>v`S$cTEePx32r&yZS@Ny8qL*ykEHQ!=kd5>5s6g>2 z3nK%AJ%bJd5P^o=c5Jvi9-1%%}FELGeX(lWAg@=9mU@^ECZ F1_1I2nbH6N diff --git a/site/webroot/css/jqGrid/coffee/grid.css b/site/webroot/css/jqGrid/coffee/grid.css deleted file mode 100644 index 0d146a2..0000000 --- a/site/webroot/css/jqGrid/coffee/grid.css +++ /dev/null @@ -1,457 +0,0 @@ -.GridHeader { -} -.Header { - width: 100%; - } - -.Header th { - font-size: 100%; font-weight: bold; text-align: left; - padding: 2px; - background-image: url(images/headerbg.gif); color: #ffffff; - width: 100%; - white-space: nowrap; - } - -.HeaderLeft { - background-image: url(images/headerleft.gif); - } - -.HeaderRight { - background-image: url(images/headerright.gif); - } -.HeaderButton { - background-image: url(images/headerbg.gif); -} -.HeaderButton img{ - width: 21px; -} - -.HeaderLeft img{ - width: 4px; - } - -.HeaderRight img{ - width: 9px; - } -.GridHeader table {margin:0;} -.GridHeader td, tr {padding:0;} - - -/* Grid */ -table.scroll { - border-right: 1px solid #FFFFFF; - table-layout: fixed; - margin-bottom:0; -} -table.scroll tbody tr { - background-color: #eceae3; -} - -table.scroll tbody tr.alt{ - background-color: #e3dfd1; -} - -table.scroll tr.over td{ - background-color: #D2B48C; -} - - -table.scroll tr.selected td { - background-color: #c9b9b1; - color: Black; -} - -table.scroll tbody tr td { - font-size: 90%; - padding: 2px; - text-align: left; - border-left: 1px solid #FFFFFF; - border-bottom: 1px solid #FFFFFF; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - height : auto; -} - -table.scroll thead tr th { - font-size: 90%; - font-weight: normal; - padding: 2px; - border-left: 1px solid #FFFFFF; - border-bottom: 1px solid #FFFFFF; - text-align: left; - overflow: hidden; - white-space: nowrap; - background: url(images/grid-blue-hd.gif) transparent repeat-x; - height : 18px; -} -table.scroll thead tr th div img { - width: 9px; -} - -table.scroll th div { - overflow: hidden; -/* white-space: nowrap;*/ - word-wrap: break-word; - height : 18px; -} - table.scroll th span { - cursor: e-resize; -/* border-right: 1px solid #D6D2C2; */ - width: 5px; - float: right; - position: relative; - display: block; - margin: -1px -1px -1px 0px; - height: 18px; - overflow: hidden; - white-space: nowrap; -} - -table.scroll thead { -} - -/* End Grid */ - -/* Pager */ -div.scroll { - vertical-align: top; - height: 23px; - text-align: center; - white-space: nowrap; - background-image: url(images/grid-blue-ft.gif); - border-right: 1px solid #FFFFFF; - border-left: 1px solid #FFFFFF; - border-bottom: 1px solid #FFFFFF; -} -div.scroll span { - vertical-align : top; -} -.selbox { - font-size: x-small; - vertical-align : top; -} -input.selbox{ - font-size: x-small; - vertical-align : top; -} -.pgbuttons { - margin-top :1px; -} -.nav-table-left { - padding:1px; - float: left; - margin-top:2px; -/* position:absolute;*/ -} -.nav-table-right { - padding:1px; - float: right; - margin-top:2px; -} -table.navtable {margin-bottom:0; width: auto;} -table.navtable tbody tr { - background-image: url(images/grid-blue-ft.gif); -} -table.navtable tbody tr td.nav-button { - border: 1px solid #FFFFFF; - white-space: nowrap; -} -table.navtable tbody tr td.nav-hover { - border: 1px solid #c9b9b1; -} -table.tbutton tbody tr td { - border : none; - padding:0px; -} -img.jsHover { /*not used */ - border: 1px solid #99CCFF; -} -/* End Pager */ -/*multiselect checkbox */ -.cbox { - height: 10px; - width: 10px; -/* text-align: center;*/ -/*border:1px solid #999;*/ -} -/* end multiselect */ - - -/* loading div */ -div.loading { - position: absolute; - padding: 3px; - text-align: center; - font-weight: bold; - background: red; - color: white; - display: none; -} -div.loadingui { - display:none; - z-index:6000; - position:absolute; -} - - -div.loadingui div.msgbox { - position: relative; - z-index:6001; - left: 35%; - top:45%; - background: url(images/loading.gif) no-repeat left; - width: 100px; - border: 2px solid #B2D2FF; - text-align: right; - height: auto; - padding:2px; - margin: 0px; -} - -/* end loading div */ -/*toolbar */ -div.userdata { - margin-top: 0px; - background-color : #e3dfd1; - height : 20px; - overflow: hidden; -} -/* end toolbar */ -/*Subgrid text mode*/ -.subgrid { - height: 100%; - overflow: auto; -} -.tablediv { - background-color: White; - border-spacing: 1px; /*cellspacing:poor IE support for this*/ - border-collapse: separate; - width:100%; /* FF hack poor when scroling subgrid */ -} -.celldiv { - float: left; - display: table-cell; - border: 1px dotted #CCCCCC; - overflow: auto; - white-space: normal; -} -.celldivth { - float: left; /*fix for buggy browsers*/ - border: 1px solid #CCCCCC; - background-color: #99CCFF; - border-bottom: 1px solid #CBC7B8; - text-align: left; - overflow: auto; -} -.rowdiv { - display: table-row; - background: #F9F9F9 none; - color: #000000; - width: 100%; - overflow:auto; -} -/* End Subgrid */ - -/* InLine editing */ -input.editable[type="text"] { - font-size: x-small; - overflow: hidden; -} -input.editable[type="checkbox"] { -} - -textarea.editable { - overflow: hidden; -} - -select.editable { - font-size: x-small; -} -/* End Inline Editing */ - -/*Modal Window */ -.modaltext{ - text-align : left; -} -.modalwin{ - border:1px solid #555555; - background:#F9F9F9; - text-align:left; - margin: 0 auto; - overflow: auto; -} - - -.modalhead { - background-image: url(images/grid-blue-hd.gif); - height: 20px; - -} -.modalcontent { - overflow: auto; - margin-bottom: 9px; - margin-left: 5px; -} -/* end Modal window*/ -/* Search window */ -input.search { - margin: 2px; - width: 70px; - font-size: 10px; - color: #15428B; -} - -select.search { - margin: 2px; - width: 70px; - font-size: 10px; - color: #15428B; -} -.buttonsearch { - width : 50px; - font-size: 10px; - color: #15428B; -} -/*End search */ - -/* Form edit */ - -.FormGrid { - margin: 0px; -} -.EditTable { - width: 100%; -} - -.FormData { /* tr */ - -} - -#FormError td { - font-size: 90%; - color: #FF0000; - vertical-align: top; - background-color: #f7f7f7; -} - -.CaptionTD{ /* td */ - font-weight: normal; text-align: left; vertical-align: top; - padding: 1px; - border-top: 1px solid #D4D0C8; - white-space: nowrap; - color: #000000; -} -.DataTD { /* td */ - padding: 1px; - border-top: 1px solid #D4D0C8; - vertical-align: top; -} -.navButton{ - border-top: 1px solid #D4D0C8; - border-bottom: 1px solid #D4D0C8; - text-align: center; -} -.navButton input{ - width:19px; -} -input.EditButton { /* buttons are at footer tr */ - font-size: 10px; - color: #15428B; -} -td.EditButton { - text-align: right; - border-top: 1px solid #D4D0C8; - border-bottom: 1px solid #D4D0C8; -} - -.FormElement { /* form element - input -text,textarea,checkbox - select */ - -} -.FormElement { - font-size: 10px; -} -input[type="text"].FormElement{ - color: #15428B; -} -input[type="checkbox"].FormElement{ - width: 15px; - color: #15428B; -} -input[type="textarea"].FormElement{ - color: #15428B; -} -select.FormElement { - font-size: 10px; - color: #15428B; -} -/* End Eorm edit */ - -/* Delete Dialog */ -.DelButton > input { /* buttons are at footer tr */ - font-size: 10px; - color: #15428B; -} -.DelButton { - text-align: right; -} -/* End Delete Dialog */ - -img.jqResize { - position:absolute; - bottom: 0px; - right: 0px; - cursor :se-resize; -} -.dirty-cell { - background: transparent url(images/dirty.gif) no-repeat 0 0; -} -#DelError td { - font-size: 90%; - color: #FF0000; - vertical-align: top; - background-color: #f7f7f7; -} -/* Tree Grid */ -.tree-wrap -{ - float: left; - position: relative; - height: 18px; - white-space: nowrap; - overflow: hidden; -} -.tree-minus -{ - position: absolute; - height: 18px; - width: 16px; - overflow: hidden; - background: url(images/tree_minus.gif) no-repeat; -} -.tree-plus -{ - position: absolute; - height: 18px; - width: 16px; - overflow: hidden; - background: url(images/tree_plus.gif) no-repeat; -} -.tree-leaf -{ - position: absolute; - height: 18px; - width: 16px; - overflow: hidden; - background: url(images/tree_leaf.gif) no-repeat; -} -.treeclick -{ - cursor: pointer; -} -.edit-cell { - background-color: #D2B48C !important; -} -.selected-row, .selected-row TD { - background-color: #c9b9b1; -} \ No newline at end of file diff --git a/site/webroot/css/jqGrid/coffee/images/cd_run.gif b/site/webroot/css/jqGrid/coffee/images/cd_run.gif deleted file mode 100644 index c2b8f4edabad00e11a69889bae33c9b91717c6f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1025 zcmeH`?=RGG0LMQU8fEQ@HZxmSY}CT(N~kT4B&L>@)!OVlX_bChJ@KTaU)ItX!ktsO z!+3x!r-*Ru<{W3byVdBr)7^bJ9Ot;>zOJu#{0Tkp{owuV{owt2?|trkYFvCSo3P2c zkch^xB`dHDxLj)kR%`^ZuInMX}|&SUUO;Y553``C@OE_#M6>@q6ruc7M;dQ0V8%8 ze$9T+qxlEKUqx@`1P!t&@muMm;aussL}kUI)mp2?%8Elqp>eExewNCUr&kRwXE$Xr z4D+z_?gLe-)`N;_X>+&w)a$qzCtaz2Hn|Fk4hn_oadB<06~a-BtM$i zl(u_1UbzZ-z2$gm^ssv2R_p!mORF@!DO6(`NUV?U`7)s0fXlhgeHmF*Cv&?ujD~4x z+sG7y*3Myt!dSd`vFWo>vxKfblWYn@mhBPAfBidwgS0n`5Ft6b9o_x}@imYbzmT+c zfjlXvD&^zqZ@>lyj2t2o f3la`CGVn;rtSCr4)W)vpHOFJ)qNAORj11NQ63h`c diff --git a/site/webroot/css/jqGrid/coffee/images/down.gif b/site/webroot/css/jqGrid/coffee/images/down.gif deleted file mode 100644 index 2b88b365010addc8c963519197e932ffafdaaf5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 683 zcmZ?wbhEHb6lD-)I2Owg=V{%V9^9G{+@2NIksa2V6W*B<(Ulv~l^4~W7uA^`+npcX z14IQt6w_N6+gljdR}|M*oX}qaM2Qp2k|tNCPpM3sQk5~a8i+Ed)n-qx&6-h{GowCt zW&;rA&2BE7*H*Huy>M}F&Eme=C4F_P`zn`Cs9)1xwQOS3+6mQbC)Tc;RJUPD!^UYX z>t=Uvoz<~*cIWoF-P`B&Y+g8N>yl}^7fsr|bn0FpS~hk6iW&P?&fL9v?!nb_4y~Pc zc>lYqgH~+}`g-16mI=XSuu}w=(Y*}_{`>NABR-fLn=Jd|BXLheUw`aq-y&KQ( z+jQyB_A5tsT|2Sw`pE+~P93~?`q0fYhi{)ddiUbV` zcMl)`fWV+&3vLOm)_6Lb2YPnzvkNWqMx&!`=v`?i~C2m9{aodd@mmr zjJ9+XUf^l1rY9#L*vu!u>|Xq6GW$e3feogcqt>gjReAghXgDe`Z_SDi2?5Gi<_mBz itvRsdrF##9NK=LAl7z#p?3}E6ZXW`i!j?ENSOWkKt$g$V diff --git a/site/webroot/css/jqGrid/coffee/images/find.gif b/site/webroot/css/jqGrid/coffee/images/find.gif deleted file mode 100644 index 39a0dac9ddcce982cb99dd4229089a0a810cd371..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 986 zcmZ?wbhEHb6krfw_};{@bm`4|_x^9)dVBixQ`4rMYX2PF^(|)Q%8SdE-L_w0f9Kv; zjp>H<^_vzgy71-qm*vZEuUK*Jz=3y*7oT-GsGGPup{#6nRn@BH%g^-p@6XL$(BHqO zw|C#=%g;7%zIo~D(>Zev{Q3Lm|NsBXmtUSU=h%`Z7x?PA&!7Khzshdix*H1f#7>?1 zps`%NzJ9}zBah`5h@Cm}pu2n9(xtaHZ+`gc*QctgwQjXBr%%7|nip~F*7sAVp5MCl z^Zon(=1XjE-TKhmyLR#7Q)_qZ-MaOHjZN(x(>lDzVyj1NZbJrhO!IOgpSmfH~m+o1We# z15FOb3!)5$Y)4K8JMnci`QC~+d2vy5yOcwh#GVG_3(O2GuUHC;k0eZy^ssDnG@cb6Va6$(VZ97lONqv5ZzlC+gB9V zUy?ATGHq&g#`M~(8Fe``>T_o{91Nlp?brVhIO;Mx6bO= zI=gfG-0to3dNwVXxOw5E70VXxUNmX%(y4owO zd53{$-Tb2)79HKV=-8$uhqf#~v1QrrotsZ>Uv+xN>NC67o!hhF+}@4n_iZ|IXwR90 zTQ42je&y({(K=Gfbb5UwyNotBhd1gt5LP$ocg1e`00E6OB7Dg_HdIlW^ zAOJ-c1N*;*`ljY4MFCDm4u0vD-d=GgWph_wS94`1k-ioi9$jyrg^PT=b-6TW+pt@C ztzEa?%ZgR8*OSM>W9P2jyDT`2TEsQnjvPI9T!YWP$(_l``GPY8!^O)Not>BzT4fyW z-MjqY;e7`gLF;+}9lJMgF56vZc>7j|+r*#K%=Y*1kC*>2`c!v}^oTqnOa7pe|yvBjVJSmBG9`E<8$$9yE8Yj@X>^H(`O(Vi8uWITGI6-gNRY ztK@JsGB9@vDHlARrqFn>;g)Zc49A8A2M=@bOX+YVG+YmCVP#@MtwUbVx|CCuD_3M1(}kL@rTAt`?@NJD7g1T-cVt+{lozLxII0fq`Ms9dUP2 S4@VK8*$kepelF{r5}E+oVobaM diff --git a/site/webroot/css/jqGrid/coffee/images/grid-blue-ft.gif b/site/webroot/css/jqGrid/coffee/images/grid-blue-ft.gif deleted file mode 100644 index 317d17250a97150b7b6addd8f6823c5281db905e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 165 zcmZ?wbhEHbWMr7eaD;(j-|B@we|*1p^}_eBU%r0&@cF~Lk8j_+e0=};gFCOEJwCo| z-NTz#p4_>yf9>M4`?ue|aQf|wXQy^;x^m*+q4mpdoH_R6+t>H6UtT=C=i8T0M>elw zzyOLrS-@gCAQEIJ1FKR(0Ix)#gxC}rj?EnWsyf9>M4`?ue|aQf|wXQy^;x^m*+q4mpdoH_R6+t>H6UtT=C=i8T0M>elw zzyOLrS-@gCAQEIJ1FKR(0Ix)#gxC}rj?EnWsn`gA{nAbbG xD0)^!0s{;v{$v3&bwDJ@3M5UJo4TMr{m|wW>nGR$|NozX5K#Qd!pOiN!k`0E2(pubHB-UW zk~d-26cJya+g2AgoGJOtQ(?#8^!|H8LxBd1K;H>vg@ZXpjIAq7xEvzZhczUgzRSe- zz(8Vw#_ZF}w^W_Y+kOATjvBx9x8MKRQ+NLT@Ba;rP0cN>ZS5VMUEMvsef<+APMSPr K>a+qy25SI)OM5UJo4TMr{m|wW>nGR$|NozX5K#Qd!pOiN!k`0E2(pubHA6w6 ztJgWuXO`bY7u^CIhjR({4`1e}InUg0}HO*98rch80n(8Jf#hv&!sy zpzq+QH`)Egma4OPyYGM4QRBD%_WK`u>dwFa{lB5Hskx=Kt-YhOtGlPSuYbbCNt35c JEl^~z1^~M|T`B+o diff --git a/site/webroot/css/jqGrid/coffee/images/ico-close.gif b/site/webroot/css/jqGrid/coffee/images/ico-close.gif deleted file mode 100644 index e4c743e2b23c118fae6775d488796140257df1b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 854 zcmZ?wbhEHb6krfwXlG!U!@#hVfnhBJ!&U}{y$lS;7#PkmF#P}jpJ5b?hQJ620mYvz zKwti6&;j`slqVQCj2Rd?WIQ%3IM~b~tQDj2;Q(V3pP*F@M?%t}PBGD>lpTS}Ze8rg TX(ked37%~l!K+dv1Q@IV#VZ{# diff --git a/site/webroot/css/jqGrid/coffee/images/last.gif b/site/webroot/css/jqGrid/coffee/images/last.gif deleted file mode 100644 index 061006fe2342173fac9891c41e1e4793b8f7ffc7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 737 zcmZ?wbhEHb6lV}+I2OPV=V{%V9^9G{+>ssDnG@cb6Va6$(VZ97lONqv5ZzlC+gB9V zUy?ATGHq&g#`M~(8Fe``>T_o{91Nlp?brVhIO;Mx6bO= zI=gfG-0to3dNwVXxOw5E70VXxUNmX%(y4owO zd53{$-Tb2)79HKV=-8$uhqf#~v1QrrotsZ>Uv+xN>NC67o!hhF+}@4n_iZ|IXwR90 zTQ42je&y({(K=Gfbb5UwyNotBhd1gt5LP$ocg1e`00E6OB7Dg_HdIlW^ zAOJ-c1N*;*`ljY4MFCDm4u0vD-d=GgWph_wS94`1k-ioi9$jyrg^PT=b-6TW+pt@C ztzEa?%ZgR8*OSM>W9P2jyDT`2TEsQnjvPI9T!YWP$(_l``GPY8!^O)Not>BzT4fyW z-Mh^2;L&{t8A0oM0Uf)y?;hG+e)m>~+r*#K%=Y&m+lQC`R^3q8@W``4#!5)b=STj+ zJ{d+I8%Kf1ZAZJ!|1ln@P-bK7%`pXCKfj49COYhg#%4&{K_^N8x$HEX*~6o0a?iZC!S=m6P3Ss?}nCh;l#D>+~DyLOwL V>$-Y2<`-MpBadm%W{NOa0{{&)7qb8W diff --git a/site/webroot/css/jqGrid/coffee/images/loading.gif b/site/webroot/css/jqGrid/coffee/images/loading.gif deleted file mode 100644 index e846e1d6c58796558015ffee1fdec546bc207ee8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 771 zcmZ?wbhEHb6krfw*v!MQYQ=(yeQk4RPu{+D?cCXuwr^cCp}%d_ius2R?!0jBXnAQ) zOH<|l|Nj|aK=D7fpKD04vtxj(k)8oFBT!uNCkrbB0}q1^NDatX1{VJbCr|b)oWWMT zS%hVC ~NwO_yO%;SvZ5MdNYf|QNy-I*%yJaj+uTdt+qbZ z4E`Fzb8m}I&!N8OKmWEcCmrLs^Hs&3i)mt@hQVdcqghkaBs*D}tG_lKew4?rTjzIZ z9tSone1TS+TR7tu^CunG)Y7Jg#sw#)sG9C!c0I%LEzP)9;hqRf&)s$D8d5Db{TBs% zgl0~5QQ91luq4Q9tJgt4QLbaxZvAaKeCM9!oy85dg4k>TdBSVqjHub_PG=PO&J-rx z7oYTuF+kH|tG-UK+EkUhDjYx?zW?T|lx>+aOQm zzL$v$zBLo4Cj=G&tw{H}dW?tlTkS)SY4<#NS92z*EY-MMB6Ftp`R=*=*Ev7cS+X%W zMCur^FdlokL}1Y+&aasU2J4#EOuNlnb9CmqgLCGTSY!1BD42pkHY^XidQ5=>YQx%` z*%Pm9D!CkBu&tMWm(%-ejACVWGS2RX5=QOJ$1*tr7F}F+*-OA+Ly&Isg|AEuUYicA z#%IG6kPXkHt{zk2M6zK@Vu^4Q(1zE$?yY6M!^&jQ+2^E?!p7{g*|X6}vuRC3p@jk0 W117c83?+LXEZI4G$p&LV25SKE>nb+@ diff --git a/site/webroot/css/jqGrid/coffee/images/minus.gif b/site/webroot/css/jqGrid/coffee/images/minus.gif deleted file mode 100644 index ef04a54696e17442f7d3a858b18e2da9db1c2e34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85 zcmZ?wbhEHb6k-r!n8?8J|NsA%mKFvuL-8jIs|W)#gAR}jloeuNU{agYzw-23{>5Bd lu8B3=Q%KlX>BCkwzhTj{h;`hYUHRJn(^Q}S;uB@C1^}ss9ftq_ diff --git a/site/webroot/css/jqGrid/coffee/images/next.gif b/site/webroot/css/jqGrid/coffee/images/next.gif deleted file mode 100644 index dd6d89a98c66a70b6b889e2aff71a612eeee2151..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 483 zcmV<90UZ8ENk%w1VHE%s0Hr+uUP(KJXH$h}Q;2I;iELMiY*>nISc`62jBi_va9fRW zU5;{Ik91&^d1jS+XqSCzn0{=Se{G(Ibf$-Kqm6v5k9w_;d$5#%uA7UsnuxWViMO4L zx1Nl%p_03zlD(ysy{47FsF=U0nZc`^!mXaet)9cKpT)4E#j&EsvZTngrpmXf%ebq| zyROc>u+F`)&%UzK!nf4Ly4J|P*vi4#%fi{r!`sfq-O_CX>@2HRA^-&M@dak03rDV0SW*=04x9i000#L6#xJR=fIzE z`0GFt0mK7CYz`>`Ps_%$wLAiebI2&^cHr<%S5j;bu$+3$&cO;zh6_ip+v_gGQ*`V5 z|9~P6LIN~3hlcSHf0!0}!laz`8l$bLa5fCIYpP(|9p`auS2`n+HtE!f)sw@Nn zFEF*XwwAXrFG(pazreqi!M`a44<0MZ%PW@5%N`0C7An=&me$!S77afFCn(|JisI!c zCy+l97bflQ@9-B4Lkb)t_xSnv90pAV8X*D-92i2wfGr3rd;r0)A&3tZ`fd5)K){3x Z8$4{dFhRh)i9;eRkVQa2Hzz>=06Q9e=G6cI diff --git a/site/webroot/css/jqGrid/coffee/images/nochild.gif b/site/webroot/css/jqGrid/coffee/images/nochild.gif deleted file mode 100644 index cf6c61ce9550a7c2a8b546151b7349027979b35f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66 zcmZ?wbhEHb%@85yhr?yqt6 z+`IPt-i;UcZ@qkY`}LFiZ=O7O`|Q!X7mwe)c=G<`(~oane17-(>&JKBK7aiF<wc6hbmm72G|20~i#4vM_Qn z*fZ!b00GFe3~bL2%rE%iEy2Oqr0AH#$KS-k@zkkNsi`@bLo+2}?S>skPl+h_o=Dh| zwfp|+iwwF~M4VRbsawx4YU0E$s@c-o)-D<)!KB{X%fQe#p|6)of|FNm)~pG0=FV2* zbrV-zx^#l-1cqhH#NFjpHf~%sVbeBw4<+T@ySMDwudL)Lqj2=-7KUS|WV{6B&Yzzk zx9Y+LL2qu^Tel|MxqDldo3mT`>C*|%UObbYX3x$e`SH`|FFaB9W&C2l|NQ;KU*EQ( z&|%?%gUuo`XFP))8e2F8l>H_wcyLCnoJqi-Lf|1IGfSkNkYSSxr?9#s1A{dHm6R0g diff --git a/site/webroot/css/jqGrid/coffee/images/off-last.gif b/site/webroot/css/jqGrid/coffee/images/off-last.gif deleted file mode 100644 index 280affb194c9e9ec659a65726e09e17428e5a069..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 485 zcmZ?wbhEHb6lD-)SgOx3e^Te3MHBZdp0t1YwEfGcA6zx-=!ONScC0$TcjKkQ+pZkm zaplO)YsdHAI(zu`*&}z(AG>?yqt6 z+`IPt-i;UcZ@qkY`}LFiZ=O7O`|Q!X7mwe)c=G<`(~oane17-(>&JKBK7aiF<wc6hbmm72G|20~i#4vM_Qn z*fZ!b00GFe3~VnC%rE%iEy2Oqr0AH#$KS-k@zkkNsi`@bLo+2}?S>skPl+h_o=Dh| zwfp|+iwwF~M4VRbsawx4YU0E$s@c-o)-D<)!KB{X%fQe#p|6)of|FNm)~pE(bLP!f z<8>2PUABC#>V)OX#NFjpHf~axJ7KemyoZwVp1pgv?o(Fslu?yqt6 z+`IPt-i;UcZ@qkY`}LFiZ=O7O`|Q!X7mwe)c=G<`(~oane17-(>&JKBK7aiF<wc6hbmm72G|20~i#4vM_Qn z*fZ!b00GFe3~Ub$%rE%iEy2Oqr0AH#$KS-k@zkkNsi`@bLo+2}?S>skPl+h_o=Dh| zwfp|+iwwF~M4VRbsawx4YU0E$s@c-o)-D<)!KB{X$H34xsh3HDlUHr#tO*RW=Be?z ziK{MIsyb)cQgL^Am38aa&DpR{-a|=w$IhK|b}1`)$|xK?yqt6 z+`IPt-i;UcZ@qkY`}LFiZ=O7O`|Q!X7mwe)c=G<`(~oane17-(>&JKBK7aiF<wc6hbmm72G|20~i#4vM_Qn z*fZ!b00GFe3~Y}N%rEHhl;B`&Qf!p8YM<4tz~rB)Fot3efT~N-zVMFQ#7k9S_8i|ioIT)+~mR%Hk diff --git a/site/webroot/css/jqGrid/coffee/images/plus.gif b/site/webroot/css/jqGrid/coffee/images/plus.gif deleted file mode 100644 index abb84bdfbfa5fbd6f188a3a65eec7b077229eef3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89 zcmZ?wbhEHb6k-r!n8?8J|NsA%mKFvuL-8jIs|W)#gAR}jloeuNVA7h?zw-23{>5Bd pu8B3=Q+S}8BR4s7p_$&y1Do!qcNrAyQ&FEhP4(+PeoY1jYXCC)AI<;( diff --git a/site/webroot/css/jqGrid/coffee/images/prev.gif b/site/webroot/css/jqGrid/coffee/images/prev.gif deleted file mode 100644 index 6ea081390805b75ce76bcc318bb8745089b8c10c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 483 zcmV<90UZ8ENk%w1VHE%s0Hr+uUP(KJXH$h}Q;2I;iELMiY*>nISc`62jBi_va9fRW zU5;{Ik91&^d1jS+XqSCzn0{=Se{G(Ibf$-Kqm6v5k9w_;d$5#%uA7UsnuxWViMO4L zx1Nl%p_03zlD(ysy{47FsF=U0nZc`^!mXaet)9cKpT)4E#j&EsvZTngrpmXf%ebq| zyROc>u+F`)&%UzK!nf4Ly4J|P*vi4#%fi{r!`sfq-O_CX>@2HRA^-&M@dak03rDV0SW*=04x9i000#L6#xJR=fIzE z`0GFt0mK7CYz`>`Ps_%$wLAiebI2&^cHr<%S5j;bu$+3$&cO;zh6_ip+v_gGQ*`V5 z|9~P6LIN~3hlqy&0Esm;0!0}!la!N-0F{#&5fCIYpP(|Ap`auS2`n+HtCy>;F)RcD zFEF*Wm$tdJFG(pazrdHk!!0QU4<0MZ%PW`6%N`0C7An=&)tA@R77afFCn(|K;fv!a zCy+l97bflQ@9-B4Lkb)t_xSnv90pAV8X*D-92i2wfGr3rd;r0)A&3tZ`fd5)K){3x Z8$4{dFhRh)i9;eRkVQa2Hzz>=06S8#=Uo5* diff --git a/site/webroot/css/jqGrid/coffee/images/refresh.gif b/site/webroot/css/jqGrid/coffee/images/refresh.gif deleted file mode 100644 index fb74a02ad4fb7d0fe7ad2070ff5dad786bdf417d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 581 zcmV-L0=oT2Nk%w1VGsZi0Oo%HS+f74(f_^H^St8!pws{6^#85G9r?e+XDgwaf&=_-KIbiV&XdBcje<1CBig{9V;%>LHl^u^-;dBOj%-~Sqb?D+Zo zq169wr`*on^GL1#QhvfJm;ZIX{}gn_DwX_CiPpO0|4N42OQGS`=Jxjc|4**}g{k0g zs^mnP;GMqakiO?Mi{iZH|0;RV5LmHmv+rx1)$8*7Wt-jo{{J_3$x@@?L#O|CxA+{8 z_+X~&B7oMa%r~jYN|0jFZ#NGCY%KwPx!A^8LW004ggEC2ui z01yBW000M~fPaF6goTDME!3Lt_(C_8KpQC&7}GEM^~Z-N~M7f&2nV;(pqTytgy zf_n&kMhy}Sg&TuvVF^S(ez1a6Un5HpX?cTQEQEGfDXQQBphXHDCRWfm5>RHvhaw>~ TY>_8q${jvKpvc=OC=dWU{>VZe diff --git a/site/webroot/css/jqGrid/coffee/images/resize.gif b/site/webroot/css/jqGrid/coffee/images/resize.gif deleted file mode 100644 index 05c807bbcee95410e01fed7a9900bba24ba3a339..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 862 zcmZ?wbhEHb6krfw_|Cx4($aG6+PVLuU^E0qWC$q!WMO1rU}Vr?00K~+VBoN3VCInV z*s$PWGl#HN%n5^rhBiJ%6A=c7M^0U0qDdtyHYOcukv5m(d0DvR_yjgjuO$%ysYiPB Klk<2u7_0#kRTRwt diff --git a/site/webroot/css/jqGrid/coffee/images/row_add.gif b/site/webroot/css/jqGrid/coffee/images/row_add.gif deleted file mode 100644 index 847ea1d9bde19af1c36349ff7d9c413d986002eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 635 zcmaKp+e_1N7>D2KR7R!CW1e-1qE1RP@epY=b()!#n2B0ak;RU>FF~S3iUWh2X=|9kO{keHQPkupOdPWT!*ziXV>+5)M zfMa81YYR;#Q-41JJt&n*P=ijV0|`hZ5^BF%zgK~;_*$)2uh)Ydy1Tpaa|KRT;`d%8 zH|=(^w}%u(;fH%R8^QNwjg5_?qolpPoit_8G|^}@DwS$y2Sp;0!C=5Q#h`-iZ3GJN zTbspVIXc1@zxh_H6`k4826)U5dUX|@PAATq#bWXPJ`N2L&;h=^O`5Zy85|BWGD0>s z@bD02G8uFLQCz^O2S%f@W%KUtE^cljP8;yk{jRPqnx=80#OWkNlUZ9^i}p-V0#0`> zFC)GyU0g(*dkI1SE!b=}#Uc-17eO6JrBbumED#8ULLtug;dtT9%mOrk%S99l1=49? zf`(tY3#1bafMfYRJw5ofYG8mYE#cZ4uB@DRz<-H8U^3wNQSQm=qzQQaY?5=i;)hIT zUU0B)Y-|x*E@!4BG2G6@xP!D_Ru@V6CS9}i_R%&L#bz+lBlz(yYn=}j>E;%Zo$>V6 zRga+1Xb#27^$)p{757-gyLjhWIOQYp3o9uO^ez{ql_s92IQ}=nqT;H&1D+>%CVElf zej#O1ftMZy2u~*$UgqdquaD=bQ?^@D|EeL^;a<N^h$ISJ6 ys5|1%`ty7_t|zUDIRH6drcPOdsE^!o$smuFTr=UAosTJW4DwA0Rl})l$odBY{~Kli diff --git a/site/webroot/css/jqGrid/coffee/images/row_delete.gif b/site/webroot/css/jqGrid/coffee/images/row_delete.gif deleted file mode 100644 index bd6e784c5f61c4dcde504e280a2c8bebc629dfc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 634 zcmV-=0)_oYNk%w1VGsZi0Oo%HnVGYblaqdae#AO8d3kwlZEcj4l*J?ykB^V<@Bjb3 zS88f%XlQ8vqdldiv!S80ot?A)XD#{p|E;aF;^P19?f=);|K;WXqN20v>i^&0|Nope z*x3Jyii(z&mY$xohlhv%nKPQ2v-9)+|DHJT@c;jyI{&Fd;NbuK{Qr@Wk=51ztgN$* zjg5qagpiPscXxNUBq7?`|FSbIr>C>76bZYKP_uV0up}e@tw(Wjar8+XzakLvsD|^i zp8v{%|J9+hbuRy1CEniu+1da1_y4FSC)1{iw03sAprFpW!RON7)6@U^`~R^jD5j>l z|7|(HFDd_}KmXsZ|E@^F!ovT3KmW#l|I2jLG!@+3|J}B}!W|R;t3|*mA^(~*|8gw< z|Nq@T9H*zJ|4tXdKRy4rRR3Wqvx7VTZ7affc+Yxt|FBB`v`({fE4aA0yt=yo!d(Bw zU#O_FtE;pB*`@#7q_cD^#5E!RTOf3FbnNW^|6CQjAQkfR|NsC0A^8LW004ggEC2ui z01yBW000NqfPWqy1_l9#Dk?7sj4gkE0bwZ;6C))R85kE78Xb=>DNU4?n3|j*k1Y}s zMJ#>^rJEWqj~x>eEOc`;4h|0w9}u*EAaZdEXl89}IX6-!8v>6mSau3Fbw5;HK@B8d z(tid$15-y)K36Aq-XR2!Ra{VOGihExCvMOoFpqCWR>Yh+pyWv~5dZ+_c{FAVj|e-| zBtS7lgbWTAbUadXAcBxQeU_lm0s!NR0*`Qj$%2Orp8P14gdfE diff --git a/site/webroot/css/jqGrid/coffee/images/row_edit.gif b/site/webroot/css/jqGrid/coffee/images/row_edit.gif deleted file mode 100644 index 12cc7e6fbb0215bbafaea389043a9eeb2aa674c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 996 zcmZ?wbhEHb6krfw_&$xHv~8F-0yB!+ZZex?%*0$^a!S&6qXJwUj>c`3c{%yVg;#*p__x_Hps;&R{@qc6E=GCju zZr}bm>a<1dQR~HvFTHy8Yw3x&SBEDYIr4Jl$_tAZpZfjx_o-7KE?#`{;>G`p9cf#( zJnZh?+uOVL*yOqp5Z!cYXv#@Y!SXf)<*O=wYFW`^SNvK16TW98cPn(t$7!G{`{x@^R<`PWZj8$x_$eMZ2j05%^VY6ivG*MIJSv+q)dOjy9sz!=Up?PM}1D+i1FjypFGGqLkF@@@0ku&}9PhFbuW1>=Mh6CEUsXT*3s zUN}LHkx|ElaYKT_LcL&#A1@7-otkA)px`0F(bg_**?)*-V=$+uh$=5v9i!9ACI!!w zc^L*S3l{LWHab0cXv}hf+noLPpA(4=F8o&J3bG zP=Vr47DkYW4u}Am!N4Lf;32te>B=|(k-%Fb60Vso2Nl=64rD!{aGqJ{PDPzNgEasG Cwj|^L diff --git a/site/webroot/css/jqGrid/coffee/images/sort_desc.gif b/site/webroot/css/jqGrid/coffee/images/sort_desc.gif deleted file mode 100644 index 490adfb701f4b08bb1675fe337116a3103872d60..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 113 zcmZ?wbhEHb-r5N@t9vUL zP=Vr47DkYW4u}Am!N4LHaKclS(}G>8!NXNTP4#h)yUAf^t80Ld^gF}W}@SOWlZ0R#L1 diff --git a/site/webroot/css/jqGrid/coffee/images/tab_close-on.gif b/site/webroot/css/jqGrid/coffee/images/tab_close-on.gif deleted file mode 100644 index 822726888b5dec2b575c81f700a8ede0922d9033..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 351 zcmZ?wbhEHbQ=gxgiOWV%C@c;k+Pobd~85s64Fnsj!Il{p3IWu!F z1H&^0hPM(D|I5qY>*;-Pbo>+^{)U_TV?e+L28L@uHQCwkb#*^_d+%ppc*?-=!N%sD zqT*!+hIcwT+ZY%wF))0Ji`&J(unBBF1GRzTPZmZ71{DS!kij57F|gG*Oe*lu;bT0J zvWa6ui&E>0l*d0UX0C3q`TL1t6 diff --git a/site/webroot/css/jqGrid/coffee/images/tree_leaf.gif b/site/webroot/css/jqGrid/coffee/images/tree_leaf.gif deleted file mode 100644 index febfda63651a83fd2614e6fb61e973c5330fbb40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 134 zcmZ?wbhEHb6lM@-*v!KaP`15m{XrJ9x%Z!a?Av@OsAg0C+)chETbWJgzW?&ir|MAA zg3Sy_K=CIFBLf2ugAPaxWCjC^@r09}tM^*GKD+z>0~47J2A;bUB^((`IyMS4UeIK8 dye$*JvQ|8uL10F}!X-r~bFAiH@MdAK1^}~nFHQge diff --git a/site/webroot/css/jqGrid/coffee/images/tree_minus.gif b/site/webroot/css/jqGrid/coffee/images/tree_minus.gif deleted file mode 100644 index bdfa2ecfc397e0665a8c7bdb746b1ba7a9f64a40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132 zcmZ?wbhEHb6lM@-Sj5Wk|NsBwIp>nk{hu>uPI7WGkjnrDia%Kx85md@bU-|iS_Wp% zh+TL78B8-=BFzx6yFl&El-hs;6_2m6tg+a)N{EB$_dSLkXSVb{=aE}0w&P{f;dvJi gdR=pKU$((xlF9tQ)w+Z^fq{)d2gqgs zsbygH&)9Wm-xE()md?$giG_TO$18&w8e#%d+BoMdTre%a_tfFX*YsyuTi^5ikj+xL pQ0Z}o@~al#r%WueUek}Obl)o86s7hyoKdOw{EIDBdp#H!tO1AYH}e1h diff --git a/site/webroot/css/jqGrid/coffee/images/up.gif b/site/webroot/css/jqGrid/coffee/images/up.gif deleted file mode 100644 index b49eaa97043ab88b42ac33307e34fa6f1d998f6b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 673 zcmZ?wbhEHb6lD-)I2Oqe=V{%V9^9G{+>ssDnG@cb6VaI)(FH_#kzILFJ^9f+1<}2Q zv3*5xy~S~T#qoV53H>0H*k77Bu{?QFdGh3nv?-NoldICFR%cAD$(&Z3HN7@#MqSQ~ z`rMffxicFJ7BuJ0Yb%-8Ub?KkaB*+Vn*OR~lN#4ftlcoBVbk>1b+fy-&hFekw|o1% zp6&DccFgbFyl~QrWec|~p0ab%q}_`q?Oi%`@3N`;SIpSIa^~*Ua}Tbbb7<|n!)xd5 zTfgw|y7@;pEIPVz(XmZSPHb6rc-zWT+gF|1zWVfz)n|6EJGW=UxxE|D@7r|g(Do}w zcU?QN@A`@TH%=YAdHT@JGly@VJ9_ux$@`a2Ke&4K!PRpQubuxt5J2%K3nLdpJ%bJd z5P;%@f&E`YeN&SJAFC)ABe$%&aC3jNkO-5afs>cJjTV!%!h|McP7McVR}XI=Uq62n zPW}mota|p2OP8+~JEm zj)#UZ)yt`v-(h(9>eZFda8pBG&F6<+e|sD5Alb}_MizOZ!n(L6;VKJhb|U#_Xh?vv8~m+_eGZP0U!seGjLYQ~vu1O*n7+)T46j|b7)i}x7vB$sO&1J!tM?uSc1!@vRRh*j{ RSXgAtHY6n6S?s`I4FJeff$jhR diff --git a/site/webroot/css/jqGrid/green/grid.css b/site/webroot/css/jqGrid/green/grid.css deleted file mode 100644 index 6f28c5c..0000000 --- a/site/webroot/css/jqGrid/green/grid.css +++ /dev/null @@ -1,459 +0,0 @@ -.GridHeader { -} -.Header { - width: 100%; - } - -.Header th { - font-size: 100%; font-weight: bold; text-align: left; - padding: 3px; - background-image: url('images/headerbg.gif'); color: #ffffff; - width: 100%; - white-space: nowrap; - } - -.HeaderLeft { - background-image: url(images/headerleft.gif); - } - -.HeaderRight { - background-image: url(images/headerright.gif); - } -.HeaderButton { - background-image: url(images/headerbg.gif); -} -.HeaderButton img{ - width: 20px; -} - -.HeaderLeft img{ - width: 4px; - } - -.HeaderRight img{ - width: 9px; - } -.GridHeader table {margin:0;} -.GridHeader td, tr {padding:0;} - -/* Grid */ -table.scroll { - table-layout: fixed; - margin-bottom :0px; -} -table.scroll tbody tr { - background-color: #fffcf2; -} - -table.scroll tbody tr.alt { - background-color: #ecf7e4; -} - -table.scroll tr.over td{ - background-color: #FFDEAD; -} - - table.scroll tbody tr.selected td { - background: #3c964b; - color: #ecf7e4; -} - - table.scroll tbody td { - - padding: 2px; - text-align: left; - border-bottom: 1px solid #3c964b; - border-left: 1px solid #3c964b; - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - height : auto; -} - -table.scroll thead th { - - padding: 2px; - border-bottom: 1px solid #3c964b; - border-left: 1px solid #3c964b; - text-align: left; - font-weight: normal; - overflow: hidden; - white-space: nowrap; - background-image: url(images/grid-blue-hd.gif); - height : 17px; -} - -table.scroll th div { - overflow: hidden; -/* white-space: nowrap;*/ - word-wrap: break-word; - height : 17px; -} -table.scroll th span { - cursor: e-resize; - width: 10px; - float: right; - display: block; - margin: -2px -1px -2px 0px; - height: 18px; - overflow: hidden; - white-space: nowrap; -} - -table.scroll thead { -} - -/* End Grid */ - -/* Pager */ -div.scroll { - vertical-align: top; - height: 23px; - white-space: nowrap; - text-align: center; - background-image: url(images/grid-blue-ft.gif); -/* - border-left: 1px solid #3c964b; - border-right: 1px solid #3c964b; - border-bottom: 1px solid #3c964b; -*/ -} -div.scroll span { - vertical-align : top; -} -.selbox { - font-size: x-small; - vertical-align : top; -} -input.selbox{ - font-size: x-small; - vertical-align : top; -} -.pgbuttons { - margin-top :2px; - width: 19px; -} -.nav-table-left { - padding:1px; - float: left; -/* position:absolute;*/ -} -.nav-table-right { - padding:1px; - float: right; -} -table.navtable {margin-bottom:0; width: auto;} - -table.navtable tr{ - background-image: url(images/grid-blue-ft.gif); -} - -table.navtable td.nav-button { -/* margin-top:2px;*/ - border: 1px solid #E2ECF8; - white-space: nowrap; -} - -table.navtable td.nav-hover { - border: 1px solid #3c964b; -} - -table.tbutton tr td{ - border : none; - padding:0px; -} - - -img.jsHover { /*not used */ - border: 1px solid #99CCFF; -} -/* End Pager */ -/*multiselect checkbox */ -.cbox { - height: 10px; - width: 10px; - /*border:1px solid #999;*/ -} -/* end multiselect */ - - -/* loading div */ -div.loading { - position: absolute; - padding: 3px; - text-align: center; - font-weight: bold; - background: red; - color: white; - display: none; -} - -div.loadingui { - display:none; - z-index:6000; - position:absolute; -} - - -div.loadingui div.msgbox { - position: relative; - z-index:6001; - left: 35%; - top:45%; - background: url(images/loading.gif) no-repeat left; - width: 100px; - border: 2px solid #B2D2FF; - text-align: right; - height: auto; - padding:2px; - margin: 0px; -} - -/* end loading div */ -/* toolbar */ -div.userdata { - margin-top: 0px; - background-color : #fffcf2; - height : 20px; - border-left: 1px solid #3c964b; - border-right: 1px solid #3c964b; - overflow: hidden; -} -/* end toolbar */ -/*Subgrid text mode*/ -.subgrid { - height: 100%; - overflow: auto; -} -.tablediv { - background-color: White; - border-spacing: 1px; /*cellspacing:poor IE support for this*/ - border-collapse: separate; - width:100%; /* FF hack poor when scroling subgrid */ -} -.celldiv { - float: left; - display: table-cell; - border: 1px dotted #CCCCCC; - overflow: auto; - white-space: normal; -} -.celldivth { - float: left; /*fix for buggy browsers*/ - border: 1px solid #CCCCCC; - background-color: #99CCFF; - border-bottom: 1px solid #CBC7B8; - text-align: left; - overflow: auto; -} -.rowdiv { - display: table-row; - background: #F9F9F9 none; - color: #000000; - width: 100%; - overflow:auto; -} -/* End Subgrid */ - -/* InLine editing */ -input.editable[type="text"] { - font-size: x-small; - overflow: hidden; -} -input.editable[type="checkbox"] { -} - -textarea.editable { - overflow-y: auto; -} - -select.editable { - font-size: x-small; -} -/* End Inline Editing */ - - -/* Modal window */ -.modaltext{ /*caption */ - text-align : left; -} -.modalwin{ - border:1px solid #555555; - text-align:left; - margin: 0 auto; - background: #F9F9F9; - overflow: auto; -} - -.modalhead{ - background-image: url(images/grid-blue-hd.gif); - height: 20px; -} -.modalcontent { - overflow : auto; - background:#F9F9F9; - margin-bottom: 10px; - margin-left: 5px; -} -/* End modal window */ -/*search dialog */ -input.search { - margin: 2px; - width: 70px; - font-size: 10px; - color: #15428B; -} - -select.search { - margin: 2px; - width: 70px; - font-size: 10px; - color: #15428B; -} -.buttonsearch { - width : 50px; - font-size: 10px; - color: #15428B; -} -/*End search */ - -/* Form edit */ - -.FormGrid { - margin: 0px; -} -.EditTable { - width: 100%; -} - -.FormData { /* tr */ - -} -#FormError td { - font-size: 90%; - color: #FF0000; - vertical-align: top; - background-color: #f7f7f7; -} - -.CaptionTD{ /* td */ - font-weight: normal; text-align: left; vertical-align: top; - padding: 1px; - border-top: 1px solid #D4D0C8; - white-space: nowrap; - color: #000000; -} -.DataTD { /* td */ - padding: 1px; - border-top: 1px solid #D4D0C8; - vertical-align: top; -} -.navButton{ - border-top: 1px solid #D4D0C8; - border-bottom: 1px solid #D4D0C8; - text-align: center; -} -.navButton input { - width:18px; -} -input.EditButton { /* buttons are at footer tr */ - font-size: 10px; - color: #15428B; -} -td.EditButton { - text-align: right; - border-top: 1px solid #D4D0C8; - border-bottom: 1px solid #D4D0C8; -} - -.FormElement { /* form element - input -text,textarea,checkbox - select */ - -} -.FormElement { - font-size: 10px; -} -input[type="text"].FormElement{ - color: #15428B; -} -input[type="checkbox"].FormElement{ - width: 15px; - color: #15428B; -} -input[type="textarea"].FormElement{ - color: #15428B; -} -select.FormElement { - font-size: 10px; - color: #15428B; -} -/* End Eorm edit */ - -/*delete dialog */ -.DelButton > input { /* buttons are at footer tr */ - font-size: 10px; - color: #15428B; -} -.DelButton { - text-align: right; -} -/* End Delete Dialog */ -/* Resizing corner */ -img.jqResize { - position:absolute; - bottom: 0px; - right: 0px; - cursor :se-resize; -} -.dirty-cell { - background: transparent url(images/dirty.gif) no-repeat 0 0; -} -#DelError td { - font-size: 90%; - color: #FF0000; - vertical-align: top; - background-color: #f7f7f7; -} - -/* Tree Grid */ -.tree-wrap -{ - float: left; - position: relative; - height: 18px; - white-space: nowrap; - overflow: hidden; -} -.tree-minus -{ - position: absolute; - height: 18px; - width: 16px; - overflow: hidden; - background: url(images/tree_minus.gif) no-repeat; -} -.tree-plus -{ - position: absolute; - height: 18px; - width: 16px; - overflow: hidden; - background: url(images/tree_plus.gif) no-repeat; -} -.tree-leaf -{ - position: absolute; - height: 18px; - width: 16px; - overflow: hidden; - background: url(images/tree_leaf.gif) no-repeat; -} -.treeclick -{ - cursor: pointer; -} -.edit-cell { - background-color: #FFDEAD !important; -} -.selected-row, .selected-row TD { - background-color: #3c964b; -} diff --git a/site/webroot/css/jqGrid/green/images/cd_run.gif b/site/webroot/css/jqGrid/green/images/cd_run.gif deleted file mode 100644 index c2b8f4edabad00e11a69889bae33c9b91717c6f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1025 zcmeH`?=RGG0LMQU8fEQ@HZxmSY}CT(N~kT4B&L>@)!OVlX_bChJ@KTaU)ItX!ktsO z!+3x!r-*Ru<{W3byVdBr)7^bJ9Ot;>zOJu#{0Tkp{owuV{owt2?|trkYFvCSo3P2c zkch^xB`dHDxLj)kR%`^ZuInMX}|&SUUO;Y553``C@OE_#M6>@q6ruc7M;dQ0V8%8 ze$9T+qxlEKUqx@`1P!t&@muMm;aussL}kUI)mp2?%8Elqp>eExewNCUr&kRwXE$Xr z4D+z_?gLe-)`N;_X>+&w)a$qzCtaz2Hn|Fk4hn_oadB<06~a-BtM$i zl(u_1UbzZ-z2$gm^ssv2R_p!mORF@!DO6(`NUV?U`7)s0fXlhgeHmF*Cv&?ujD~4x z+sG7y*3Myt!dSd`vFWo>vxKfblWYn@mhBPAfBidwgS0n`5Ft6b9o_x}@imYbzmT+c zfjlXvD&^zqZ@>lyj2t2o f3la`CGVn;rtSCr4)W)vpHOFJ)qNAORj11NQ63h`c diff --git a/site/webroot/css/jqGrid/green/images/down.gif b/site/webroot/css/jqGrid/green/images/down.gif deleted file mode 100644 index 4fc7f661166f982c90b243de2e18f98d944f00d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 734 zcmZ?wbhEHb6lD-)_{PBS|MSWJ|NkGjvS8Bwrr4zkR+BwlW(HVI@^qUW=(r@vdWx6t zyfBwp0k$)I>d*8{x;)oqO<3oJsW#KS-8V&+Y{)O(kng-A#JtPZdwZ6!^LS?Fi@rMj`;pdv$`)#x0~x{H`~`?VSvx}IL~d-QG2t(cBcU?vY+RF z^WlcOk2hOS_AEW#RCugDWLIjy&LsQ!{y_C92TM{87ANcn*%i1m$!|vjP?=@FJJ2ye zhuO^V0U8Lj#dTdc&?Oe#ZehFAf!eJmdRX?k15F00ndV)2vaReyOTzvFpdnt{Vm!7+ z0Tnnc4RTx@Xwl~m)Me4@2Gnle?V5O?Fn)hN&~Tu4a*xzxAE^Rr2L?s^`N^&4CeFIH zWX9D+vHNnP_vWM@DoZ<93bX>~NNb=PpsRpJ^|+a}JDavTnY1{WG&=&3ag(FZ_E?~$ zE~`VGSB1K*4+lCG80+Z^fuWv3hXDvcal*jF3n{6@6lNfi}h!vRg2!7u~boB*d?jN6czdC**%#ujsr(Hnw5Ev zX?`im;cY3yV0tr{5Aeqab{+k*DoT-8sV`51*Or{3jIV zF5eQMC!>63j;3(hQ4u?v@NHMxPadAkp6+JhsLYykzOT@FLSmADG7~4eMa74U%uXH7 z7TYB>UlbfZIa%8JSIx>pZJazin>61<8Z!5b3wSp~?7HH?*ks7T5s@mw!C(ylj!i3~ diff --git a/site/webroot/css/jqGrid/green/images/find.gif b/site/webroot/css/jqGrid/green/images/find.gif deleted file mode 100644 index 39a0dac9ddcce982cb99dd4229089a0a810cd371..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 986 zcmZ?wbhEHb6krfw_};{@bm`4|_x^9)dVBixQ`4rMYX2PF^(|)Q%8SdE-L_w0f9Kv; zjp>H<^_vzgy71-qm*vZEuUK*Jz=3y*7oT-GsGGPup{#6nRn@BH%g^-p@6XL$(BHqO zw|C#=%g;7%zIo~D(>Zev{Q3Lm|NsBXmtUSU=h%`Z7x?PA&!7Khzshdix*H1f#7>?1 zps`%NzJ9}zBah`5h@Cm}pu2n9(xtaHZ+`gc*QctgwQjXBr%%7|nip~F*7sAVp5MCl z^Zon(=1XjE-TKhmyLR#7Q)_qZ-MaOHjZN(x(>lDzVyj1NZbJrhO!IOgpSmfH~m+o1We# z15FOb3!)5$Y)4K8JMnci`QC~+d2vy5yOcwh#GVG_3(O2GuUHC;k0eZy^BM|}UKS=|?=+s*Z}o9*kcFu-SfoaeUasJ&TXyVHOc+0XO8 z`EbMC$D6GudzKz=Dm+#nvMV)UXOjJVf1vu5gC!{kixc*P>ayr{18O(#c1=7`7{5OsXgJV2xkqZUk5mD*1B0Ud{N&bi6K7pp zGUMu^*nPRtdvnqcm8Bgl1zG`gq%}|t&{aUAdfd#~olRSvOj?{wnjL}2xXICHdo0jW zm(`)pt3ut@hXb9;00xRbSr|bK9S{ME69)GG4Gc}qddw^w$s8=qdd+>!`l3n3<_Shw znU!3k`u$Bzau%s6e1?h3vn(aKnfjS{{FV6y{Svdco5xBEv#o8?mo?;1yDPYiKc*=D1%QiGx(bAV0aB6l&DxL+S4 zC5;k9#B^1DT$sdhMBLWCZo_5CiLSiTteZpvw=Ch}khQv@*c-9fF+f*bj4@I9NSA0? z*!oS`MGw3L`3fa86E3Bl6e>%bz9n(`5p8z9?-2|k4IhvBPS{<3cTeSFmebd*@MtwUbVx|CCuD_3M1(}kL@rTAt`?@NJD7g1T-cVt+{lozLxII0fq`Ms9dUP2 S4@VK8*$kepelF{r5}E+oVobaM diff --git a/site/webroot/css/jqGrid/green/images/grid-blue-ft.gif b/site/webroot/css/jqGrid/green/images/grid-blue-ft.gif deleted file mode 100644 index 801cb7ab84ff050da7d56996237cbb01f28c2a0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 165 zcmZ?wbhEHbWMr7eaD;*3|A&45|Ni{{{oen--~a#l`tQ%@|9?LI`}OkQ&*%Stz5e&< z`2Qad|NVUO@5BE8U(Wvje*6FLxBow%`v3LHzmJFhf4lMj?~nh#-~an^@&Dg%|2_fD zLkEgKS-?U%AQEIJ1FKR(0Ix)#gxC}rj?EnWsPx# diff --git a/site/webroot/css/jqGrid/green/images/grid-blue-hd.gif b/site/webroot/css/jqGrid/green/images/grid-blue-hd.gif deleted file mode 100644 index 801cb7ab84ff050da7d56996237cbb01f28c2a0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 165 zcmZ?wbhEHbWMr7eaD;*3|A&45|Ni{{{oen--~a#l`tQ%@|9?LI`}OkQ&*%Stz5e&< z`2Qad|NVUO@5BE8U(Wvje*6FLxBow%`v3LHzmJFhf4lMj?~nh#-~an^@&Dg%|2_fD zLkEgKS-?U%AQEIJ1FKR(0Ix)#gxC}rj?EnWsPx# diff --git a/site/webroot/css/jqGrid/green/images/headerbg.gif b/site/webroot/css/jqGrid/green/images/headerbg.gif deleted file mode 100644 index 13ec9692105714f409ddd31475f0fcf2c9de833e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105 zcmZ?wbhEHbWMr7eu$h6udYX6L>2CYEejb~n689JQ??{Z;lW8-skV5@bKu&t-L}|BghP89o&! z+v-ktr>xA_cz$8zo-FrGkse#4diS;^9VmM6>@Wi%p!k!8k%2*kK?kG|WG4e_rh=;_ zZ^Eo8BECMituAahQ}UUo!j8e|{r8530u2^{z7xs{2Xl-VTUVHHIYg`vYe+nOmx=Fz zfy4rh*{7FpsXCjt`~HU=HGb=FzyGnP?)>}T{~H>cnp;}i+B-VCx_f&2`X@}BGskV5@bKu&t-L}|BghP89o&! z+v-ktr>xA_cz$8zo-FrGkse#4diS;^9VmM6>@Wi%p!k!8k%2*kK?kG|WG4e_hJr#@ zuXCW!EWe2^x&<~4=MwH8zRXc`p1E;>0f&M_zneqS$rvWC3mPH~E2362G?%SrmD%?| z-@#FDviplIRcG^d-~X_q#&7-Y_doX3oqzxPe?wzab4zPmdq-zicTaC$|AdK?CQq4K IpvYhi0FO3U+yDRo diff --git a/site/webroot/css/jqGrid/green/images/ico-close.gif b/site/webroot/css/jqGrid/green/images/ico-close.gif deleted file mode 100644 index e4c743e2b23c118fae6775d488796140257df1b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 854 zcmZ?wbhEHb6krfwXlG!U!@#hVfnhBJ!&U}{y$lS;7#PkmF#P}jpJ5b?hQJ620mYvz zKwti6&;j`slqVQCj2Rd?WIQ%3IM~b~tQDj2;Q(V3pP*F@M?%t}PBGD>lpTS}Ze8rg TX(ked37%~l!K+dv1Q@IV#VZ{# diff --git a/site/webroot/css/jqGrid/green/images/last.gif b/site/webroot/css/jqGrid/green/images/last.gif deleted file mode 100644 index 4f635292cb7622ad2a151f15a80d2c88021a2373..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 760 zcmZ?wbhEHb6lD-)Xk%db|M}$q|NjqMSukmTQ|!_N+ZjG~vwdA=1z1h?beS38xFpDG zlBe73KA5YsWJ7-OhJ5E0A!!Fo zJvK+VtO_-4b1psJRCugD_ec#;FAzB`3pVd^HS2JR-Ip7&C$s<3tnLfb?dJLcZ4B9! z3be~%VZhCY8}2^dY(3f2V`~&pFkoj=!v2EnBUR~#%7BI^?9T^ES@yfTtq%t}1L#_t z89uJ-!hsqCcP4pnk9AocYCqrKex5(jB8xtEi*7edFbT8*sJQZETiJ;gtBD?o2MXi& z=Q}M8a$Fo}(d!0OY~Jl^GtC?5&Gz$?ThC3Lb#2LvtBa!d=0xqy3fr9?wmZ!lC=0Y2 zXj+dO(0m{=Yj-wnb@JL414QndBZ1)nbP3Q^CM`}T&5l51+~k;Yuq5SRvEPma-yQMJ zt3rXn!hi}Cf3h%wM07v|C{7sI|2Hr+H5)Lq@I>*jFdH=YH5*Dsnv^OkSj6Y>N*eYz zF)5eDMDxp=FSoFg;bZD&Vh_+15cW5h-d-B4A;!73$xumNAXb21vCQnGnYyl!EZs$s)gM#hZ^8=XWcM zRK$3?IQa|8TiCzKOkcvur0pRxccGI~dtkfDiY>*TK6`b#+F#&U>2x(-R59b0u1C|6 zW=S_*E(r_gZL*QfthWlkK6ohCz+)78qKDCG`a21ulxYSpwT`n`G8oECi4LgnPFLHm OIf^b_5|vym4AuZPQ7B6Q diff --git a/site/webroot/css/jqGrid/green/images/leaf.gif b/site/webroot/css/jqGrid/green/images/leaf.gif deleted file mode 100644 index bc5934e14b002ae664a10099d3cba0210e73b9c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 203 zcmZ?wbhEHb6k-r!IKsg2|NsBrzkfe__UzH4N4IX>x_0f_!Gi}^u3R}|#*8UbrgU_4 z`1$#{xw$zxImyb(N=izKii)zZumE*25C;^0vapH(tajqjFC}wc#;SFz zC+*QMTEUrc-(})8a|InX*~6o0a?iZC!S=m6P3Ss?}nCh;l#D>+~DyLOwL V>$-Y2<`-MpBadm%W{NOa0{{&)7qb8W diff --git a/site/webroot/css/jqGrid/green/images/loading.gif b/site/webroot/css/jqGrid/green/images/loading.gif deleted file mode 100644 index e846e1d6c58796558015ffee1fdec546bc207ee8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 771 zcmZ?wbhEHb6krfw*v!MQYQ=(yeQk4RPu{+D?cCXuwr^cCp}%d_ius2R?!0jBXnAQ) zOH<|l|Nj|aK=D7fpKD04vtxj(k)8oFBT!uNCkrbB0}q1^NDatX1{VJbCr|b)oWWMT zS%hVC ~NwO_yO%;SvZ5MdNYf|QNy-I*%yJaj+uTdt+qbZ z4E`Fzb8m}I&!N8OKmWEcCmrLs^Hs&3i)mt@hQVdcqghkaBs*D}tG_lKew4?rTjzIZ z9tSone1TS+TR7tu^CunG)Y7Jg#sw#)sG9C!c0I%LEzP)9;hqRf&)s$D8d5Db{TBs% zgl0~5QQ91luq4Q9tJgt4QLbaxZvAaKeCM9!oy85dg4k>TdBSVqjHub_PG=PO&J-rx z7oYTuF+kH|tG-UK+EkUhDjYx?zW?T|lx>+aOQm zzL$v$zBLo4Cj=G&tw{H}dW?tlTkS)SY4<#NS92z*EY-MMB6Ftp`R=*=*Ev7cS+X%W zMCur^FdlokL}1Y+&aasU2J4#EOuNlnb9CmqgLCGTSY!1BD42pkHY^XidQ5=>YQx%` z*%Pm9D!CkBu&tMWm(%-ejACVWGS2RX5=QOJ$1*tr7F}F+*-OA+Ly&Isg|AEuUYicA z#%IG6kPXkHt{zk2M6zK@Vu^4Q(1zE$?yY6M!^&jQ+2^E?!p7{g*|X6}vuRC3p@jk0 W117c83?+LXEZI4G$p&LV25SKE>nb+@ diff --git a/site/webroot/css/jqGrid/green/images/minus.gif b/site/webroot/css/jqGrid/green/images/minus.gif deleted file mode 100644 index ef04a54696e17442f7d3a858b18e2da9db1c2e34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85 zcmZ?wbhEHb6k-r!n8?8J|NsA%mKFvuL-8jIs|W)#gAR}jloeuNU{agYzw-23{>5Bd lu8B3=Q%KlX>BCkwzhTj{h;`hYUHRJn(^Q}S;uB@C1^}ss9ftq_ diff --git a/site/webroot/css/jqGrid/green/images/next.gif b/site/webroot/css/jqGrid/green/images/next.gif deleted file mode 100644 index f611e6fb5fc410c56669de244b3884cd6228dc14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1177 zcmZ?wbhEHb6lD-)XlG#f|M}$q|NjqMSzzAfYSHUv+3#MmA%D{Trs56xu}c$t=Y?5M z_H>&a=rSw7WoCf=e1DfUVJ@pe>(BH|x;)orhL6=GPpiqERuesd+D)1rJ1nUD9?H1i`rftrSOM>j?`gw1UjoO=KJHy9%ns@ZxoQOS{rN^5JkJaZM zsR7yrL^jjCJ+?;q?uZZBmD+!4R`-SJK#dLy1AMl}d2Wlo`EbMC$D4st0XvgSTb;6x zRHYv(3*4FHw<7^)5zrYxd)?NDyKjzkT^H`LISR-%>u@n^cedzr2f7gGFuU2lPRoLU z4zQW#4Mac}IxP)yTpVcG=kB~B1c)k6ww0Y|0V)Hk0eZIm{N&bi6K7ppGUMtZuWd15 zyVJvVrvcpqG%8_#e*FG?h%TUZiyk-QCP$!W&AVNJ+JPwXKw-lE0-#HP=A;}fNjX^T zyeiaZdo0i#lNKjnaJj4w1qLR=C>Xd9Q2fcl2(n!VM1b-H1IK>`Mh=-3j~$rUV0ZqR8BnFKiT1uN~Pk1g$-;m89o;_JZ*2E zU2$baz@r6A56E(b`3M+0I(6HWPP%r}fZ4r8T$WMdz~aO+5(YXimKYqo>M~Q#QlZ3= z!J&Pgu4zWgNht+}{_QqRQv!q9*{JSC)9=Is7YX@G_h-bces+m2mjsL)g4=l5c!#BnMtY$kqM^ki`MVa8kwnS0Q zB8wHzFHCEe(G2eB5LbMp$H1b{wqU`5`Sx9k&Iy8tDkOCr#TcyjTwoIuH@Tr8#*}ox zMPBj;!&L_+iwA6MGG!-@w21t=FxgxG$iu^(>c1Wym(JHYILVzuDS%bR`^Seie(xh2 T149g^r3yH489oVgV6X-Nqt{HN diff --git a/site/webroot/css/jqGrid/green/images/nochild.gif b/site/webroot/css/jqGrid/green/images/nochild.gif deleted file mode 100644 index cf6c61ce9550a7c2a8b546151b7349027979b35f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66 zcmZ?wbhEHb%@85yhr4qh^AbhUvsW=;hoj1Z7;^cwn$5-Cpxa{8g-YYYJ>bE`KyY=zjO^g0&@n)VwO^VHG!SUZ%$tjWE~!1=wfg?%mG?I_UFd5#-vcxOs0QfZuD%J&10p7+157c z%Np{h@$)5E1e^@W@X(Orp35L&E|{L4Vic39bw|tHL{q>_ltHiBPenPEkkr^FWa`sX|x{zpQrTn`>3PfLAC%;auzK8BZFD0|05!i@g8< diff --git a/site/webroot/css/jqGrid/green/images/off-last.gif b/site/webroot/css/jqGrid/green/images/off-last.gif deleted file mode 100644 index 79e7176700bf94f2e5d6617b6ba8c3ad3fcd04d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 760 zcmZ?wbhEHb6lD-)Xk%db|M}$q|NpPQ*uMM0s#(`(cU+p%b$M#{o3y0d!jtz`>tuUv6^ArMWuK7ad@ zee-TFpLSzG<=M8wFHRnKethq-*R!n{M##6-ruZY=}41n8>rGp*%kT7anZO!KzKd$&H` zyX5ZL#dp^L!vu&JP=Vr47DkYW4u}B72?P8828O0)17;SUC>|DOgXX?wL&->!Qbh%e z_#9qI!~P~F<+7M)etGld7FIHRO#Mvk0h$8B{^ru#OM^AUIM+5AD#;7P3h*nInVmFK z*AHSa3>+rR9w(klEI+TUrRGafsxVVy~$e_FBh??Vd1<@HjybfF)pz5GnemG?I`Jlp|P zHs{u|?N9ar^#W1t`L4>dZ4Ao_3;hoiMA8hToG^Op*r1cNCuX(WL@QafNo*&=) z>h1oO_ct!Px4zBouDG%y;L(Dm2V}Xzd<2Xgow{vGCtbT~!0g^4F3Tu!U~%FZ2?L!M zOAHQPb(tw=sZip`;Ltu#*EFN$q?7_f|8|?EDFH%_E>oM*c6hAV+30?o!HDUzr_e#R zPDM7&XEzhvIA-o=Ogi$S!R0isgec!T&PNuFhsi9 zGzKO(9MWj`S99~Ps>y6Y{#_9Y4_p-4wF9qd#53PK)yy8(#(!YL2bNjJ;hW-rRIu{o_L$zxR=ifguLdQU#p244(u#FjxZs=~JwC diff --git a/site/webroot/css/jqGrid/green/images/off-prev.gif b/site/webroot/css/jqGrid/green/images/off-prev.gif deleted file mode 100644 index 4a3b5e468308f63da350eb2673262e90ea0af965..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1175 zcmZ?wbhEHb6lD-)XlG#f|M}$q|NpPQ*j{t4v;KTf!-d`zw-@eyunI`dx;}ftm1!*( zC-hvN+I@Kn5H(-ypK)W+nKu`2f4tXqd20Km$xRpfff~!tv|M?AW5dH8{a0u8UYRlT z=Hh8L7RTEmEvp|ccNj9(;bh@Xo4Dk9KW(v=iuApnHJ2fC#9i?tFLYnP#9LYtMDfy|oU{uq?W>8fZfKnO0z+O~0`aD8eub1}+2?f3h%wY}Wx1pgh6A z@t=W_L*~b02PQTp2^EVE$qNoQItWAvHXV2ER?_+r+op8VwUZZ?xU);hGD;k1Ug#rf zsQY4t$3aup$trdVHI57q+UM!nl=YlE<Mfw4ux@Z*xhz1pl3D>?&=n`WhOF1{s z#TE!iDJ}~r(R|qUP*lL!Y(@NjM!jCuN8VEoa5Eg_P}R_QalPNEQ%Fyxr`%B_g^_`U zC$}K*U=w!{;{w*8FNFsM0(ey#nDZhQJZuYc(Re6eyOYIP#(7G_BKf*KAKgTBDpM4g e!Vd@@70Blibd`~IeVP=>rnp4FS&o&3!5RP=%B9Z$ diff --git a/site/webroot/css/jqGrid/green/images/plus.gif b/site/webroot/css/jqGrid/green/images/plus.gif deleted file mode 100644 index abb84bdfbfa5fbd6f188a3a65eec7b077229eef3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 89 zcmZ?wbhEHb6k-r!n8?8J|NsA%mKFvuL-8jIs|W)#gAR}jloeuNVA7h?zw-23{>5Bd pu8B3=Q+S}8BR4s7p_$&y1Do!qcNrAyQ&FEhP4(+PeoY1jYXCC)AI<;( diff --git a/site/webroot/css/jqGrid/green/images/prev.gif b/site/webroot/css/jqGrid/green/images/prev.gif deleted file mode 100644 index fd845ac60e9d8d9796fdf6852fca711a82129e28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1175 zcmZ?wbhEHb6lD-)XlG#f|M}$q|NjqMSzzAfYSHUv+3#MmA%D{Trs56xu}c$t=Y?5M z_H>&a=rSw7WoCfYWKWkhVfANvCS9IuH`~`{hL6=m51>YqX2;G8Q)Bn#IxGyZpXcwo zF5G2RsQaeKw1cI#KsA#*t*3Ya&9UfqGi`JB-X04Sw4UZ2wKpqzZ%)LX%+ljcg~#f1 zkJJFI10tL0-X2?{K;}>Lc3U6rxFpDKuAlFYcpw94c>kqY-4~|&Y>)HY7Jc*KhP#h9 z1679XN;PeD%05z+eyA*PXOiEJgs|Od0Xvg`mI7TEwmTiDz+-b1&`I|5{mnXD%-WqT z`rLsocUl$QG=nF^qzN3jxKSEQ}!AbwC6tPcU%&XJF)z`SI9+iA_mD#o|Nq zg2Rmt0uh2u$6dRXw0^`mGCW!6z^MPJM^Lztb>d{#a~6$?4;D7C#g%y+xX^l{eRjo# zH5HE*EOk)eittcSR&46FDV=of=Lq!5(k_bhxa4rJHtWQS&H&@)3Cb1^*bW>#?#V7~K1E{540Yy7%4sPa zd$f(6-p0RS%vdYgV0~RzG+8sD_NI2_K&dqbN1p-ov%K}O?AGSRd6)-ki z5x<{NuUGYv_ml(N3H8fsa?|14H(o^XvcN9rsWMJXREeJf=#9hR=fHmk#;X#1_ zUX=#syod!4+k#v)9tzm*WO0^po)WQ0zHZM)HxZr66a}X61A<2d@_7VZWu#r7CPlI- NE)j5+V`X8m1^{(TMf?B& diff --git a/site/webroot/css/jqGrid/green/images/refresh.gif b/site/webroot/css/jqGrid/green/images/refresh.gif deleted file mode 100644 index fb74a02ad4fb7d0fe7ad2070ff5dad786bdf417d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 581 zcmV-L0=oT2Nk%w1VGsZi0Oo%HS+f74(f_^H^St8!pws{6^#85G9r?e+XDgwaf&=_-KIbiV&XdBcje<1CBig{9V;%>LHl^u^-;dBOj%-~Sqb?D+Zo zq169wr`*on^GL1#QhvfJm;ZIX{}gn_DwX_CiPpO0|4N42OQGS`=Jxjc|4**}g{k0g zs^mnP;GMqakiO?Mi{iZH|0;RV5LmHmv+rx1)$8*7Wt-jo{{J_3$x@@?L#O|CxA+{8 z_+X~&B7oMa%r~jYN|0jFZ#NGCY%KwPx!A^8LW004ggEC2ui z01yBW000M~fPaF6goTDME!3Lt_(C_8KpQC&7}GEM^~Z-N~M7f&2nV;(pqTytgy zf_n&kMhy}Sg&TuvVF^S(ez1a6Un5HpX?cTQEQEGfDXQQBphXHDCRWfm5>RHvhaw>~ TY>_8q${jvKpvc=OC=dWU{>VZe diff --git a/site/webroot/css/jqGrid/green/images/resize.gif b/site/webroot/css/jqGrid/green/images/resize.gif deleted file mode 100644 index 05c807bbcee95410e01fed7a9900bba24ba3a339..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 862 zcmZ?wbhEHb6krfw_|Cx4($aG6+PVLuU^E0qWC$q!WMO1rU}Vr?00K~+VBoN3VCInV z*s$PWGl#HN%n5^rhBiJ%6A=c7M^0U0qDdtyHYOcukv5m(d0DvR_yjgjuO$%ysYiPB Klk<2u7_0#kRTRwt diff --git a/site/webroot/css/jqGrid/green/images/row_add.gif b/site/webroot/css/jqGrid/green/images/row_add.gif deleted file mode 100644 index 847ea1d9bde19af1c36349ff7d9c413d986002eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 635 zcmaKp+e_1N7>D2KR7R!CW1e-1qE1RP@epY=b()!#n2B0ak;RU>FF~S3iUWh2X=|9kO{keHQPkupOdPWT!*ziXV>+5)M zfMa81YYR;#Q-41JJt&n*P=ijV0|`hZ5^BF%zgK~;_*$)2uh)Ydy1Tpaa|KRT;`d%8 zH|=(^w}%u(;fH%R8^QNwjg5_?qolpPoit_8G|^}@DwS$y2Sp;0!C=5Q#h`-iZ3GJN zTbspVIXc1@zxh_H6`k4826)U5dUX|@PAATq#bWXPJ`N2L&;h=^O`5Zy85|BWGD0>s z@bD02G8uFLQCz^O2S%f@W%KUtE^cljP8;yk{jRPqnx=80#OWkNlUZ9^i}p-V0#0`> zFC)GyU0g(*dkI1SE!b=}#Uc-17eO6JrBbumED#8ULLtug;dtT9%mOrk%S99l1=49? zf`(tY3#1bafMfYRJw5ofYG8mYE#cZ4uB@DRz<-H8U^3wNQSQm=qzQQaY?5=i;)hIT zUU0B)Y-|x*E@!4BG2G6@xP!D_Ru@V6CS9}i_R%&L#bz+lBlz(yYn=}j>E;%Zo$>V6 zRga+1Xb#27^$)p{757-gyLjhWIOQYp3o9uO^ez{ql_s92IQ}=nqT;H&1D+>%CVElf zej#O1ftMZy2u~*$UgqdquaD=bQ?^@D|EeL^;a<N^h$ISJ6 ys5|1%`ty7_t|zUDIRH6drcPOdsE^!o$smuFTr=UAosTJW4DwA0Rl})l$odBY{~Kli diff --git a/site/webroot/css/jqGrid/green/images/row_delete.gif b/site/webroot/css/jqGrid/green/images/row_delete.gif deleted file mode 100644 index bd6e784c5f61c4dcde504e280a2c8bebc629dfc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 634 zcmV-=0)_oYNk%w1VGsZi0Oo%HnVGYblaqdae#AO8d3kwlZEcj4l*J?ykB^V<@Bjb3 zS88f%XlQ8vqdldiv!S80ot?A)XD#{p|E;aF;^P19?f=);|K;WXqN20v>i^&0|Nope z*x3Jyii(z&mY$xohlhv%nKPQ2v-9)+|DHJT@c;jyI{&Fd;NbuK{Qr@Wk=51ztgN$* zjg5qagpiPscXxNUBq7?`|FSbIr>C>76bZYKP_uV0up}e@tw(Wjar8+XzakLvsD|^i zp8v{%|J9+hbuRy1CEniu+1da1_y4FSC)1{iw03sAprFpW!RON7)6@U^`~R^jD5j>l z|7|(HFDd_}KmXsZ|E@^F!ovT3KmW#l|I2jLG!@+3|J}B}!W|R;t3|*mA^(~*|8gw< z|Nq@T9H*zJ|4tXdKRy4rRR3Wqvx7VTZ7affc+Yxt|FBB`v`({fE4aA0yt=yo!d(Bw zU#O_FtE;pB*`@#7q_cD^#5E!RTOf3FbnNW^|6CQjAQkfR|NsC0A^8LW004ggEC2ui z01yBW000NqfPWqy1_l9#Dk?7sj4gkE0bwZ;6C))R85kE78Xb=>DNU4?n3|j*k1Y}s zMJ#>^rJEWqj~x>eEOc`;4h|0w9}u*EAaZdEXl89}IX6-!8v>6mSau3Fbw5;HK@B8d z(tid$15-y)K36Aq-XR2!Ra{VOGihExCvMOoFpqCWR>Yh+pyWv~5dZ+_c{FAVj|e-| zBtS7lgbWTAbUadXAcBxQeU_lm0s!NR0*`Qj$%2Orp8P14gdfE diff --git a/site/webroot/css/jqGrid/green/images/row_edit.gif b/site/webroot/css/jqGrid/green/images/row_edit.gif deleted file mode 100644 index 12cc7e6fbb0215bbafaea389043a9eeb2aa674c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 996 zcmZ?wbhEHb6krfw_&$xHv~8F-0yB!+ZZex?%*0$^a!S&6qXJwUj>c`3c{%yVg;#*p__x_Hps;&R{@qc6E=GCju zZr}bm>a<1dQR~HvFTHy8Yw3x&SBEDYIr4Jl$_tAZpZfjx_o-7KE?#`{;>G`p9cf#( zJnZh?+uOVL*yOqp5Z!cYXv#@Y!SXf)<*O=wYFW`^SNvK16TW98cPn(t$7!G{`{x@^R<`PWZj8$x_$eMZ2j05%^VY6ivG*MIJSv+q)dOjy9sz!=Up?PM}1D+i1FjypFGGqLkF@@@0ku&}9PhFbuW1>=Mh6CEUsXT*3s zUN}LHkx|ElaYKT_LcL&#A1@7-otkA)px`0F(bg_**?)*-V=$+uh$=5v9i!9ACI!!w zc^L*S3l{LWHab0cXv}hf+noLPpA(4=F8o&J3bGDLRwuPJ~Ql006h`7a9Nn diff --git a/site/webroot/css/jqGrid/green/images/sort_desc.gif b/site/webroot/css/jqGrid/green/images/sort_desc.gif deleted file mode 100644 index b21e55eeeba355f3f8b225d8f09440d777685b46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55 zcmZ?wbhEHbgvl+zaWZp_P-ptBi F4FGR`4K4rx diff --git a/site/webroot/css/jqGrid/green/images/spacer.gif b/site/webroot/css/jqGrid/green/images/spacer.gif deleted file mode 100644 index 5bfd67a2d6f72ac3a55cbfcea5866e841d22f5d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43 mcmZ?wbhEHbWMp7uXkdT>#h)yUAf^t80Ld^gF}W}@SOWlZ0R#L1 diff --git a/site/webroot/css/jqGrid/green/images/tab_close-on.gif b/site/webroot/css/jqGrid/green/images/tab_close-on.gif deleted file mode 100644 index 822726888b5dec2b575c81f700a8ede0922d9033..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 351 zcmZ?wbhEHbQ=gxgiOWV%C@c;k+Pobd~85s64Fnsj!Il{p3IWu!F z1H&^0hPM(D|I5qY>*;-Pbo>+^{)U_TV?e+L28L@uHQCwkb#*^_d+%ppc*?-=!N%sD zqT*!+hIcwT+ZY%wF))0Ji`&J(unBBF1GRzTPZmZ71{DS!kij57F|gG*Oe*lu;bT0J zvWa6ui&E>0l*d0UX0C3q`TL1t6 diff --git a/site/webroot/css/jqGrid/green/images/tree_leaf.gif b/site/webroot/css/jqGrid/green/images/tree_leaf.gif deleted file mode 100644 index febfda63651a83fd2614e6fb61e973c5330fbb40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 134 zcmZ?wbhEHb6lM@-*v!KaP`15m{XrJ9x%Z!a?Av@OsAg0C+)chETbWJgzW?&ir|MAA zg3Sy_K=CIFBLf2ugAPaxWCjC^@r09}tM^*GKD+z>0~47J2A;bUB^((`IyMS4UeIK8 dye$*JvQ|8uL10F}!X-r~bFAiH@MdAK1^}~nFHQge diff --git a/site/webroot/css/jqGrid/green/images/tree_minus.gif b/site/webroot/css/jqGrid/green/images/tree_minus.gif deleted file mode 100644 index bdfa2ecfc397e0665a8c7bdb746b1ba7a9f64a40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132 zcmZ?wbhEHb6lM@-Sj5Wk|NsBwIp>nk{hu>uPI7WGkjnrDia%Kx85md@bU-|iS_Wp% zh+TL78B8-=BFzx6yFl&El-hs;6_2m6tg+a)N{EB$_dSLkXSVb{=aE}0w&P{f;dvJi gdR=pKU$((xlF9tQ)w+Z^fq{)d2gqgs zsbygH&)9Wm-xE()md?$giG_TO$18&w8e#%d+BoMdTre%a_tfFX*YsyuTi^5ikj+xL pQ0Z}o@~al#r%WueUek}Obl)o86s7hyoKdOw{EIDBdp#H!tO1AYH}e1h diff --git a/site/webroot/css/jqGrid/green/images/up.gif b/site/webroot/css/jqGrid/green/images/up.gif deleted file mode 100644 index d2a0ee8e6003dc3b4693e65328032d5e150c3345..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 735 zcmZ?wbhEHb6lD-)IL65E|MSWJ|NkGjvS8Bwrr4zkR+BwlW(HVI@^qUW=(r@vdWx6t zyfBwp0k$)I>d*8{x;)oqO<3oJsW#KS-8V&+Y{)O(kng-A#JtPZdwZ6!^LS?Fi@rMj`;pdv$`)#x0~x{H`~`?VSvx}IL~d-QG2t(cBcU?vY+RF z^WlcOk2hOS_AEW#RCugDWLIjy&LsQ!{y_C92TM{87ANcn*%i1m$!|vjP?=@FJJ2ye zhuO^V0U8Lj#dTdc&?Oe#ZehFAf!eJmdRX?k15F00ndV)2vaReyOTzvFpdnt{Vm!7+ z0Tnnc4RTx@Xwl~m)Me4@2Gnle?V5O?Fn)hN&~Tu4a*xzxAE^Rr2L?s^`N^&4CeFIH zWX9D+vHNnP_vWM@DoZ<93bX>~NNb=PpsRpJ^|+a}JDavTnY1{WG&=&3ag(FZ_E?~$ zE~`VGSB1K*4+lCG80+Z^fuWv3hXDvcal*jtGTzO)xldK zuEJQmTBN71o{QVSCnq$%*4o_P&s=s^3tK^cu9HGljg1ALil8CS>bZqpdEQ}G_BBBn ze#+_m{&KUpqQyfT4<4=w)=o@KPgAz&X)V6!$oS;x(-eOG)TCCohnJpxG~yFXF>aNA zfBBF-qjRuLUjgIeBL{hzxSqXO9G2JBA(>gw(#hy{ac;r>rlZv>m`=?yFgm8PMcMu2 z>WU|6C4W}9U1XmWac_anb|W9DmgsjEb}mR!+u3J+aN89;SfJY7FDK+RWkX}R@N%a@J(0|s2WOQ|_j7grd7~k~U=08R CVLKH7 diff --git a/site/webroot/css/jqGrid/jqModal.css b/site/webroot/css/jqGrid/jqModal.css deleted file mode 100644 index 5d37b21..0000000 --- a/site/webroot/css/jqGrid/jqModal.css +++ /dev/null @@ -1,31 +0,0 @@ -/* jqModal base Styling courtesy of; - Brice Burgess */ - -/* The Window's CSS z-index value is respected (takes priority). If none is supplied, - the Window's z-index value will be set to 3000 by default (in jqModal.js). You - can change this value by either; - a) supplying one via CSS - b) passing the "zIndex" parameter. E.g. (window).jqm({zIndex: 500}); */ - -.jqmWindow { - display: none; - - position: fixed; - width: 600px; -} - -.jqmOverlay { background-color: #000; } - -/* Background iframe styling for IE6. Prevents ActiveX bleed-through (',prp=formatCol(pos,irow);return""+v+""},addRowNum=function(pos,irow,pG,rN){var v=(parseInt(pG)-1)*parseInt(rN)+1+irow,prp=formatCol(pos,irow);return'"+v+""},reader=function(datatype){var field,f=[],j=0,i;for(i=0;i0?rcnt:0}}else{return}var i,fpos,ir=0,v,row,gi=0,si=0,ni=0,idn,getId,f=[],rd={},rl=ts.rows.length,xmlr,rid,rowData=[],ari=0,cn=(ts.p.altRows===true)?ts.p.altclass:"",cn1;if(!ts.p.xmlReader.repeatitems){f=reader("xml")}if(ts.p.keyIndex===false){idn=ts.p.xmlReader.id;if(idn.indexOf("[")===-1){getId=function(trow,k){return $(idn,trow).text()||k}}else{getId=function(trow,k){return trow.getAttribute(idn.replace(/[\[\]]/g,""))||k}}}else{getId=function(trow){return(f.length-1>=ts.p.keyIndex)?$(f[ts.p.keyIndex],trow).text():$(ts.p.xmlReader.cell+":eq("+ts.p.keyIndex+")",trow).text()}}$(ts.p.xmlReader.page,xml).each(function(){ts.p.page=this.textContent||this.text||1});$(ts.p.xmlReader.total,xml).each(function(){ts.p.lastpage=this.textContent||this.text||1});$(ts.p.xmlReader.records,xml).each(function(){ts.p.records=this.textContent||this.text||0});$(ts.p.xmlReader.userdata,xml).each(function(){ts.p.userData[this.getAttribute("name")]=this.textContent||this.text});var gxml=$(ts.p.xmlReader.root+" "+ts.p.xmlReader.row,xml),gl=gxml.length,j=0;if(gxml&&gl){var rn=ts.p.rowNum;while(j';if(ts.p.rownumbers===true){rowData[ari++]=addRowNum(0,j,ts.p.page,ts.p.rowNum);ni=1}if(ts.p.multiselect===true){rowData[ari++]=addMulti(rid,ni,j);gi=1}if(ts.p.subGrid===true){rowData[ari++]=$(ts).addSubGridCell(gi+ni,j+rcnt);si=1}if(ts.p.xmlReader.repeatitems===true){$(ts.p.xmlReader.cell,xmlr).each(function(k){v=this.textContent||this.text;rd[ts.p.colModel[k+gi+si+ni].name]=v;rowData[ari++]=addCell(rid,v,k+gi+si+ni,j+rcnt,xmlr)})}else{for(i=0;i";if(ts.p.gridview===false){if(ts.p.treeGrid===true){fpos=ts.p.treeANode>=-1?ts.p.treeANode:0;row=$(rowData.join(""))[0];try{$(ts).setTreeNode(rd,row)}catch(e){}rl===0?$("tbody:first",t).append(row):$(ts.rows[j+fpos+rcnt]).after(row)}else{$("tbody:first",t).append(rowData.join(""))}if(ts.p.subGrid===true){try{$(ts).addSubGrid(ts.rows[ts.rows.length-1],gi+ni)}catch(e){}}if(afterInsRow){ts.p.afterInsertRow(rid,rd,xmlr)}rowData=[];ari=0}rd={};ir++;j++;if(rn!=-1&&ir>rn){break}}}if(ts.p.gridview===true){$("table:first",t).append(rowData.join(""))}ts.p.totaltime=new Date()-startReq;if(ir>0){ts.grid.cols=ts.rows[0].cells;if(ts.p.records===0){ts.p.records=gl}}rowData=null;if(!ts.p.treeGrid&&!ts.p.scroll){ts.grid.bDiv.scrollTop=0;ts.p.reccount=ir}ts.p.treeANode=-1;if(ts.p.userDataOnFooter){$(ts).footerData("set",ts.p.userData,true)}updatepager(false)},addJSONData=function(data,t,rcnt){var startReq=new Date();ts.p.reccount=0;if(data){if(ts.p.treeANode===-1&&ts.p.scroll===false){$("tbody",t).empty();rcnt=0}else{rcnt=rcnt>0?rcnt:0}}else{return}var ir=0,v,i,j,row,f=[],cur,gi=0,si=0,ni=0,len,drows,idn,rd={},fpos,rl=ts.rows.length,idr,rowData=[],ari=0,cn=(ts.p.altRows===true)?ts.p.altclass:"",cn1;ts.p.page=data[ts.p.jsonReader.page]||1;ts.p.lastpage=data[ts.p.jsonReader.total]||1;ts.p.records=data[ts.p.jsonReader.records]||0;ts.p.userData=data[ts.p.jsonReader.userdata]||{};if(!ts.p.jsonReader.repeatitems){f=reader("json")}if(ts.p.keyIndex===false){idn=ts.p.jsonReader.id;if(f.length>0&&!isNaN(idn)){idn=f[idn]}}else{idn=f.length>0?f[ts.p.keyIndex]:ts.p.keyIndex}drows=data[ts.p.jsonReader.root];if(drows){len=drows.length,i=0;var rn=ts.p.rowNum;while(i';if(ts.p.rownumbers===true){rowData[ari++]=addRowNum(0,i,ts.p.page,ts.p.rowNum);ni=1}if(ts.p.multiselect){rowData[ari++]=addMulti(idr,ni,i);gi=1}if(ts.p.subGrid){rowData[ari++]=$(ts).addSubGridCell(gi+ni,i+rcnt);si=1}if(ts.p.jsonReader.repeatitems===true){if(ts.p.jsonReader.cell){cur=cur[ts.p.jsonReader.cell]}for(j=0;j";if(ts.p.gridview===false){if(ts.p.treeGrid===true){fpos=ts.p.treeANode>=-1?ts.p.treeANode:0;row=$(rowData.join(""))[0];try{$(ts).setTreeNode(rd,row)}catch(e){}rl===0?$("tbody:first",t).append(row):$(ts.rows[i+fpos+rcnt]).after(row)}else{$("tbody:first",t).append(rowData.join(""))}if(ts.p.subGrid===true){try{$(ts).addSubGrid(ts.rows[ts.rows.length-1],gi+ni)}catch(e){}}if(afterInsRow){ts.p.afterInsertRow(idr,rd,cur)}rowData=[];ari=0}rd={};ir++;i++;if(rn!=-1&&ir>rn){break}}if(ts.p.gridview===true){$("table:first",t).append(rowData.join(""))}ts.p.totaltime=new Date()-startReq;if(ir>0){ts.grid.cols=ts.rows[0].cells;if(ts.p.records===0){ts.p.records=len}}}if(!ts.p.treeGrid&&!ts.p.scroll){ts.grid.bDiv.scrollTop=0}ts.p.reccount=ir;ts.p.treeANode=-1;if(ts.p.userDataOnFooter){$(ts).footerData("set",ts.p.userData,true)}updatepager(false)},updatepager=function(rn){var cp,last,base,bs,from,to,tot,fmt;base=(parseInt(ts.p.page)-1)*parseInt(ts.p.rowNum);if(ts.p.pager){if(ts.p.loadonce){cp=last=1;ts.p.lastpage=ts.page=1;$(".selbox",ts.p.pager).attr("disabled",true)}else{cp=IntNum(ts.p.page);last=IntNum(ts.p.lastpage);$(".selbox",ts.p.pager).attr("disabled",false)}if(ts.p.pginput===true){$(".ui-pg-input",ts.p.pager).val(ts.p.page);$("#sp_1",ts.p.pager).html(ts.p.lastpage)}if(ts.p.viewrecords){bs=ts.p.scroll===true?0:base;if(ts.p.reccount===0){$(".ui-paging-info",ts.p.pager).html(ts.p.emptyrecords)}else{from=bs+1;to=base+ts.p.reccount;tot=ts.p.records;if($.fmatter){fmt=$.jgrid.formatter.integer||{};from=$.fmatter.util.NumberFormat(from,fmt);to=$.fmatter.util.NumberFormat(to,fmt);tot=$.fmatter.util.NumberFormat(tot,fmt)}$(".ui-paging-info",ts.p.pager).html($.jgrid.format(ts.p.recordtext,from,to,tot))}}if(ts.p.pgbuttons===true){if(cp<=0){cp=last=1}if(cp==1){$("#first, #prev",ts.p.pager).addClass("ui-state-disabled").removeClass("ui-state-hover")}else{$("#first, #prev",ts.p.pager).removeClass("ui-state-disabled")}if(cp==last){$("#next, #last",ts.p.pager).addClass("ui-state-disabled").removeClass("ui-state-hover")}else{$("#next, #last",ts.p.pager).removeClass("ui-state-disabled")}}}if(rn===true&&ts.p.rownumbers===true){$("td.jqgrid-rownum",ts.rows).each(function(i){$(this).html(base+1+i)})}if($.isFunction(ts.p.gridComplete)){ts.p.gridComplete()}},populate=function(){if(!ts.grid.hDiv.loading){var prm={},dt,dstr;prm[ts.p.prmNames.search]=ts.p.search;prm[ts.p.prmNames.nd]=new Date().getTime();prm[ts.p.prmNames.rows]=ts.p.rowNum;prm[ts.p.prmNames.page]=ts.p.page;prm[ts.p.prmNames.sort]=ts.p.sortname;prm[ts.p.prmNames.order]=ts.p.sortorder;$.extend(ts.p.postData,prm);var rcnt=ts.p.scroll===false?0:ts.rows.length-1;if($.isFunction(ts.p.datatype)){ts.p.datatype(ts.p.postData,"load_"+ts.p.id);return}else{if(beReq){ts.p.beforeRequest()}}dt=ts.p.datatype.toLowerCase();switch(dt){case"json":case"xml":case"script":$.ajax({url:ts.p.url,type:ts.p.mtype,dataType:dt,data:ts.p.postData,complete:function(req,st){if(st=="success"||(req.statusText=="OK"&&req.status=="200")){if(dt==="json"||dt==="script"){addJSONData($.jgrid.parse(req.responseText),ts.grid.bDiv,rcnt)}if(dt==="xml"){addXmlData(req.responseXML,ts.grid.bDiv,rcnt)}if(loadComplete){loadComplete(req)}}req=null;endReq()},error:function(xhr,st,err){if(loadError){loadError(xhr,st,err)}endReq();xhr=null},beforeSend:function(xhr){beginReq();if(loadBeforeSend){loadBeforeSend(xhr)}}});if(ts.p.loadonce||ts.p.treeGrid){ts.p.datatype="local"}break;case"xmlstring":beginReq();addXmlData(dstr=$.jgrid.stringToDoc(ts.p.datastr),ts.grid.bDiv);ts.p.datatype="local";if(loadComplete){loadComplete(dstr)}ts.p.datastr=null;endReq();break;case"jsonstring":beginReq();if(typeof ts.p.datastr=="string"){dstr=$.jgrid.parse(ts.p.datastr)}else{dstr=ts.p.datastr}addJSONData(dstr,ts.grid.bDiv);ts.p.datatype="local";if(loadComplete){loadComplete(dstr)}ts.p.datastr=null;endReq();break;case"local":case"clientside":beginReq();ts.p.datatype="local";sortArrayData();endReq();break}}},beginReq=function(){ts.grid.hDiv.loading=true;if(ts.p.hiddengrid){return}switch(ts.p.loadui){case"disable":break;case"enable":$("#load_"+ts.p.id).show();break;case"block":$("#lui_"+ts.p.id).show();$("#load_"+ts.p.id).show();break}},endReq=function(){ts.grid.hDiv.loading=false;switch(ts.p.loadui){case"disable":break;case"enable":$("#load_"+ts.p.id).hide();break;case"block":$("#lui_"+ts.p.id).hide();$("#load_"+ts.p.id).hide();break}},sortArrayData=function(){var stripNum=/[\$,%]/g;var rows=[],col=0,st,sv,findSortKey,newDir=(ts.p.sortorder=="asc")?1:-1;$.each(ts.p.colModel,function(i,v){if(this.index==ts.p.sortname||this.name==ts.p.sortname){col=ts.p.lastsort=i;st=this.sorttype;return false}});if(st=="float"||st=="number"||st=="currency"){findSortKey=function($cell){var key=parseFloat($cell.replace(stripNum,""));return isNaN(key)?0:key}}else{if(st=="int"||st=="integer"){findSortKey=function($cell){return IntNum($cell.replace(stripNum,""))}}else{if(st=="date"){findSortKey=function($cell){var fd=ts.p.colModel[col].datefmt||"Y-m-d";return parseDate(fd,$cell).getTime()}}else{findSortKey=function($cell){return $.trim($cell.toUpperCase())}}}}$.each(ts.rows,function(index,row){try{sv=$.unformat($(row).children("td").eq(col),{colModel:ts.p.colModel[col]},col,true)}catch(_){sv=$(row).children("td").eq(col).text()}row.sortKey=findSortKey(sv);rows[index]=this});if(ts.p.treeGrid){$(ts).SortTree(newDir)}else{rows.sort(function(a,b){if(a.sortKeyb.sortKey){return newDir}return 0});if(rows[0]){$("td",rows[0]).each(function(k){$(this).css("width",grid.headers[k].width+"px")});grid.cols=rows[0].cells}$.each(rows,function(index,row){$("tbody",ts.grid.bDiv).append(row);row.sortKey=null})}if(ts.p.multiselect){$("tbody tr",ts.grid.bDiv).removeClass("ui-state-highlight");$("[id^=jqg_]",ts.rows).attr("checked",false);$("#cb_jqg",ts.grid.hDiv).attr("checked",false);ts.p.selarrrow=[]}ts.grid.bDiv.scrollTop=0},parseDate=function(format,date){var tsp={m:1,d:1,y:1970,h:0,i:0,s:0},k,hl,dM;date=date.split(/[\\\/:_;.\t\T\s-]/);format=format.split(/[\\\/:_;.\t\T\s-]/);var dfmt=$.jgrid.formatter.date.monthNames;for(k=0,hl=format.length;k11){date[k]=dM+1-12}}tsp[format[k].toLowerCase()]=parseInt(date[k],10)}tsp.m=parseInt(tsp.m,10)-1;var ty=tsp.y;if(ty>=70&&ty<=99){tsp.y=1900+tsp.y}else{if(ty>=0&&ty<=69){tsp.y=2000+tsp.y}}return new Date(tsp.y,tsp.m,tsp.d,tsp.h,tsp.i,tsp.s,0)},setPager=function(){var sep="",pgid=$(ts.p.pager).attr("id")||"pager",pginp=(ts.p.pginput===true)?""+$.jgrid.format(ts.p.pgtext||"","","")+"":"",pgl="",str,pgcnt,lft,cent,rgt,twd,tdw,i,clearVals=function(onpaging){if($.isFunction(ts.p.onPaging)){ts.p.onPaging(onpaging)}ts.p.selrow=null;if(ts.p.multiselect){ts.p.selarrrow=[];$("#cb_jqg",ts.grid.hDiv).attr("checked",false)}ts.p.savedRow=[]};pgcnt="pg_"+pgid;lft=pgid+"_left";cent=pgid+"_center";rgt=pgid+"_right";$(ts.p.pager).addClass("ui-jqgrid-pager corner-bottom").append("
    ");if(ts.p.pgbuttons===true){pgl+="";pgl+="";pgl+=pginp!=""?sep+pginp+sep:"";pgl+="";pgl+=""}else{if(pginp!=""){pgl+=pginp}}if(ts.p.rowList.length>0){str="";pgl+=""+str+""}pgl+="";if(ts.p.viewrecords===true){$("td#"+pgid+"_"+ts.p.recordpos,"#"+pgcnt).append("
    ")}$("td#"+pgid+"_"+ts.p.pagerpos,"#"+pgcnt).append(pgl);tdw=$(".ui-jqgrid").css("font-size")||"11px";$("body").append("");twd=$(pgl).clone().appendTo("#testpg").width();setTimeout(function(){$("#testpg").remove()},1000);if(twd>0){twd+=25;$("td#"+pgid+"_"+ts.p.pagerpos,"#"+pgcnt).width(twd)}ts.p._nvtd=[];ts.p._nvtd[0]=twd?Math.floor((ts.p.width-twd)/2):Math.floor(ts.p.width/3);ts.p._nvtd[1]=0;pgl=null;$(".ui-pg-selbox","#"+pgcnt).bind("change",function(){ts.p.rowNum=this.value;clearVals("records");populate();return false});if(ts.p.pgbuttons===true){$(".ui-pg-button","#"+pgcnt).hover(function(e){if($(this).hasClass("ui-state-disabled")){this.style.cursor="default"}else{$(this).addClass("ui-state-hover");this.style.cursor="pointer"}},function(e){if($(this).hasClass("ui-state-disabled")){}else{$(this).removeClass("ui-state-hover");this.style.cursor="default"}});$("#first, #prev, #next, #last",ts.p.pager).click(function(e){var cp=IntNum(ts.p.page),last=IntNum(ts.p.lastpage),selclick=false,fp=true,pp=true,np=true,lp=true;if(last===0||last===1){fp=false;pp=false;np=false;lp=false}else{if(last>1&&cp>=1){if(cp===1){fp=false;pp=false}else{if(cp>1&&cp1&&cp===0){np=false;lp=false;cp=last-1}}}if(this.id==="first"&&fp){ts.p.page=1;selclick=true}if(this.id==="prev"&&pp){ts.p.page=(cp-1);selclick=true}if(this.id==="next"&&np){ts.p.page=(cp+1);selclick=true}if(this.id==="last"&&lp){ts.p.page=last;selclick=true}if(selclick){clearVals(this.id);populate()}return false})}if(ts.p.pginput===true){$("input.ui-pg-input","#"+pgcnt).keypress(function(e){var key=e.charCode?e.charCode:e.keyCode?e.keyCode:0;if(key==13){ts.p.page=($(this).val()>0)?$(this).val():ts.p.page;clearVals("user");populate();return false}return this})}},sortData=function(index,idxcol,reload,sor){if(!ts.p.colModel[idxcol].sortable){return}var imgs,so;if(ts.p.savedRow.length>0){return}if(!reload){if(ts.p.lastsort==idxcol){if(ts.p.sortorder=="asc"){ts.p.sortorder="desc"}else{if(ts.p.sortorder=="desc"){ts.p.sortorder="asc"}}}else{ts.p.sortorder="asc"}ts.p.page=1}if(sor){if(ts.p.lastsort==idxcol&&ts.p.sortorder==sor){return}else{ts.p.sortorder=sor}}var thd=$("thead:first",ts.grid.hDiv).get(0);$("tr th:eq("+ts.p.lastsort+") span.ui-grid-ico-sort",thd).addClass("ui-state-disabled");$("tr th:eq("+ts.p.lastsort+")",thd).attr("aria-selected","false");$("tr th:eq("+idxcol+") span.ui-icon-"+ts.p.sortorder,thd).removeClass("ui-state-disabled");$("tr th:eq("+idxcol+")",thd).attr("aria-selected","true");if(!ts.p.viewsortcols[0]){if(ts.p.lastsort!=idxcol){$("tr th:eq("+ts.p.lastsort+") span.s-ico",thd).hide();$("tr th:eq("+idxcol+") span.s-ico",thd).show()}}ts.p.lastsort=idxcol;index=index.substring(5);ts.p.sortname=ts.p.colModel[idxcol].index||index;so=ts.p.sortorder;if(onSortCol){onSortCol(index,idxcol,so)}if(ts.p.datatype=="local"){if(ts.p.deselectAfterSort){$(ts).resetSelection()}}else{ts.p.selrow=null;if(ts.p.multiselect){$("#cb_jqg",ts.grid.hDiv).attr("checked",false)}ts.p.selarrrow=[];ts.p.savedRow=[]}if(ts.p.scroll===true){$("tbody tr",ts.grid.bDiv).remove()}if(ts.p.subGrid&&ts.p.datatype=="local"){$("td.sgexpanded","#"+ts.p.id).each(function(){$(this).trigger("click")})}populate();if(ts.p.sortname!=index&&idxcol){ts.p.lastsort=idxcol}},setColWidth=function(){var initwidth=0,brd=ts.p.cellLayout,vc=0,lvc,scw=ts.p.scrollOffset,cw,hs=false,aw,tw=0,gw=0,msw=ts.p.multiselectWidth,sgw=ts.p.subGridWidth,rnw=ts.p.rownumWidth,cl=ts.p.cellLayout,cr;$.each(ts.p.colModel,function(i){if(typeof this.hidden==="undefined"){this.hidden=false}if(this.hidden===false){initwidth+=IntNum(this.width);vc++}});if(isNaN(ts.p.width)){ts.p.width=grid.width=initwidth}else{grid.width=ts.p.width}ts.p.tblwidth=initwidth;if(ts.p.shrinkToFit===false&&ts.p.forceFit===true){ts.p.forceFit=false}if(ts.p.shrinkToFit===true){if(isSafari){brd=0;msw+=cl;sgw+=cl;rnw+=cl}if(ts.p.multiselect){tw=msw;gw=msw+brd;vc--}if(ts.p.subGrid){tw+=sgw;gw+=sgw+brd;vc--}if(ts.p.rownumbers){tw+=rnw;gw+=rnw+brd;vc--}aw=grid.width-brd*vc-gw;if(isNaN(ts.p.height)){}else{aw-=scw;hs=true}initwidth=0;$.each(ts.p.colModel,function(i){if(this.hidden===false&&this.name!=="cb"&&this.name!=="subgrid"&&this.name!=="rn"){cw=Math.floor(aw/(ts.p.tblwidth-tw)*this.width);this.width=cw;initwidth+=cw;lvc=i}});cr=0;if(hs&&grid.width-gw-(initwidth+brd*vc)!==scw){cr=grid.width-gw-(initwidth+brd*vc)-scw}else{if(!hs&&Math.abs(grid.width-gw-(initwidth+brd*vc))!==1){cr=grid.width-gw-(initwidth+brd*vc)}}ts.p.colModel[lvc].width+=cr;ts.p.tblwidth=initwidth+tw+cr}},nextVisible=function(iCol){var ret=iCol,j=iCol,i;for(i=iCol+1;i");this.p.colModel.unshift({name:"cb",width:isSafari?ts.p.multiselectWidth+ts.p.cellLayout:ts.p.multiselectWidth,sortable:false,resizable:false,hidedlg:true,search:false,align:"center"})}if(this.p.rownumbers){this.p.colNames.unshift("");this.p.colModel.unshift({name:"rn",width:ts.p.rownumWidth,sortable:false,resizable:false,hidedlg:true,search:false,align:"center"})}ts.p.xmlReader=$.extend({root:"rows",row:"row",page:"rows>page",total:"rows>total",records:"rows>records",repeatitems:true,cell:"cell",id:"[id]",userdata:"userdata",subgrid:{root:"rows",row:"row",repeatitems:true,cell:"cell"}},ts.p.xmlReader);ts.p.jsonReader=$.extend({root:"rows",page:"page",total:"total",records:"records",repeatitems:true,cell:"cell",id:"id",userdata:"userdata",subgrid:{root:"rows",repeatitems:true,cell:"cell"}},ts.p.jsonReader);if(ts.p.scroll===true){ts.p.pgbuttons=false;ts.p.pginput=false;ts.p.rowList=[]}var thead="",tdc,idn,w,res,sort,td,ptr,tbody,imgs,iac="",idc="";if(ts.p.shrinkToFit===true&&ts.p.forceFit===true){for(i=ts.p.colModel.length-1;i>=0;i--){if(!ts.p.colModel[i].hidden){ts.p.colModel[i].resizable=false;break}}}if(ts.p.viewsortcols[1]=="horizontal"){iac=" ui-i-asc";idc=" ui-i-desc"}tdc=isMSIE?"class='ui-th-div-ie'":"";imgs="";for(i=0;i";idn=ts.p.colModel[i].index||ts.p.colModel[i].name;thead+="
    "+ts.p.colNames[i];if(idn==ts.p.sortname){ts.p.lastsort=i}thead+=imgs+"
    "}thead+="";$(this).append(thead);$("thead tr:first th",this).hover(function(){$(this).addClass("ui-state-hover")},function(){$(this).removeClass("ui-state-hover")});if(this.p.multiselect){var onSA=true,emp=[],chk;if(typeof ts.p.onSelectAll!=="function"){onSA=false}$("#cb_jqg",this).bind("click",function(){if(this.checked){$("[id^=jqg_]",ts.rows).attr("checked",true);$(ts.rows).each(function(i){if(!$(this).hasClass("subgrid")){$(this).addClass("ui-state-highlight").attr("aria-selected","true");ts.p.selarrrow[i]=ts.p.selrow=this.id}});chk=true;emp=[]}else{$("[id^=jqg_]",ts.rows).attr("checked",false);$(ts.rows).each(function(i){if(!$(this).hasClass("subgrid")){$(this).removeClass("ui-state-highlight").attr("aria-selected","false");emp[i]=this.id}});ts.p.selarrrow=[];ts.p.selrow=null;chk=false}if(onSA){ts.p.onSelectAll(chk?ts.p.selarrrow:emp,chk)}})}$.each(ts.p.colModel,function(i){if(!this.width){this.width=150}});if(ts.p.autowidth===true){var pw=$(eg).innerWidth();ts.p.width=pw>0?pw:"nw"}setColWidth();$(eg).css("width",grid.width+"px").append("
     
    ");$(gv).css("width",grid.width+"px");thead=$("thead:first",ts).get(0);var tfoot="";$("tr:first th",thead).each(function(j){var ht=$("div",this)[0];w=ts.p.colModel[j].width;if(typeof ts.p.colModel[j].resizable==="undefined"){ts.p.colModel[j].resizable=true}res=document.createElement("span");$(res).html(" ");if(ts.p.colModel[j].resizable){$(this).addClass(ts.p.resizeclass);$(res).mousedown(function(e){if(ts.p.forceFit===true){ts.p.nv=nextVisible(j)}grid.dragStart(j,e,getOffset(j));return false}).addClass("ui-jqgrid-resize")}else{res=""}$(this).css("width",w+"px").prepend(res);if(ts.p.colModel[j].hidden){$(this).css("display","none")}grid.headers[j]={width:w,el:this};sort=ts.p.colModel[j].sortable;if(typeof sort!=="boolean"){ts.p.colModel[j].sortable=true;sort=true}var nm=ts.p.colModel[j].name;if(!(nm=="cb"||nm=="subgrid"||nm=="rn")){if(ts.p.viewsortcols[2]==false){$(".ui-grid-ico-sort",this).click(function(){sortData(ht.id,j,true,$(this).attr("sort"));return false})}else{$("div",this).addClass("ui-jqgrid-sortable").click(function(){sortData(ht.id,j);return false})}}if(sort){if(ts.p.viewsortcols[0]){$("div span.s-ico",this).show();if(j==ts.p.lastsort){$("div span.ui-icon-"+ts.p.sortorder,this).removeClass("ui-state-disabled")}}else{if(j==ts.p.lastsort){$("div span.s-ico",this).show();$("div span.ui-icon-"+ts.p.sortorder,this).removeClass("ui-state-disabled")}}}tfoot+=""});tfoot+="
     
    ";tbody=document.createElement("tbody");this.appendChild(tbody);$(this).addClass("ui-jqgrid-btable");var hTable=$("
    ").append(thead),hg=(ts.p.caption&&ts.p.hiddengrid===true)?true:false,hb=$("
    ");grid.hDiv=document.createElement("div");$(grid.hDiv).css({width:grid.width+"px"}).addClass("ui-state-default ui-jqgrid-hdiv").append(hb).bind("selectstart",function(){return false});$(hb).append(hTable);if(hg){$(grid.hDiv).hide();ts.p.gridstate="hidden"}ts.p._height=0;if(ts.p.pager){if(typeof ts.p.pager=="string"){if(ts.p.pager.substr(0,1)!="#"){ts.p.pager="#"+ts.p.pager}}$(ts.p.pager).css({width:grid.width+"px"}).appendTo(eg).addClass("ui-state-default ui-jqgrid-pager");ts.p._height+=parseInt($(ts.p.pager).height(),10);if(hg){$(ts.p.pager).hide()}setPager()}if(ts.p.cellEdit===false&&ts.p.hoverrows===true){$(ts).bind("mouseover",function(e){ptr=$(e.target).parents("tr.jqgrow");if($(ptr).attr("class")!=="subgrid"){$(ptr).addClass("ui-state-hover")}return false}).bind("mouseout",function(e){ptr=$(e.target).parents("tr.jqgrow");$(ptr).removeClass("ui-state-hover");return false})}var ri,ci;$(ts).before(grid.hDiv).click(function(e){td=e.target;var scb=$(td).hasClass("cbox");ptr=$(td,ts.rows).parents("tr.jqgrow");if($(ptr).length===0){return false}var cSel=true;if(bSR){cSel=bSR(ptr[0].id)}if(td.tagName=="A"){return true}if(cSel===true){if(ts.p.cellEdit===true){if(ts.p.multiselect&&scb){$(ts).setSelection(false,true,ptr)}else{ri=ptr[0].rowIndex;ci=!$(td).is("td")?$(td).parents("td:first")[0].cellIndex:td.cellIndex;if(isMSIE){ci=$.jgrid.getAbsoluteIndex(ptr[0],ci)}try{$(ts).editCell(ri,ci,true)}catch(e){}}}else{if(!ts.p.multikey){if(ts.p.multiselect&&ts.p.multiboxonly){if(scb){$(ts).setSelection(false,true,ptr)}else{$(ts.p.selarrrow).each(function(i,n){var ind=ts.rows.namedItem(n);$(ind).removeClass("ui-state-highlight");$("#jqg_"+n.replace(".","\\."),ind).attr("checked",false)});ts.p.selarrrow=[];$("#cb_jqg",ts.grid.hDiv).attr("checked",false);$(ts).setSelection(false,true,ptr)}}else{$(ts).setSelection(false,true,ptr)}}else{if(e[ts.p.multikey]){$(ts).setSelection(false,true,ptr)}else{if(ts.p.multiselect&&scb){scb=$("[id^=jqg_]",ptr).attr("checked");$("[id^=jqg_]",ptr).attr("checked",!scb)}}}}if(onSC){ri=ptr[0].id;ci=!$(td).is("td")?$(td).parents("td:first")[0].cellIndex:td.cellIndex;if(isMSIE){ci=$.jgrid.getAbsoluteIndex(ptr[0],ci)}onSC(ri,ci,$(td).html(),td)}}e.stopPropagation()}).bind("reloadGrid",function(e){if(ts.p.treeGrid===true){ts.p.datatype=ts.p.treedatatype}if(ts.p.datatype=="local"){$(ts).resetSelection()}else{if(!ts.p.treeGrid){ts.p.selrow=null;if(ts.p.multiselect){ts.p.selarrrow=[];$("#cb_jqg",ts.grid.hDiv).attr("checked",false)}if(ts.p.cellEdit){ts.p.savedRow=[]}}}if(ts.p.scroll===true){$("tbody tr",ts.grid.bDiv).remove()}ts.grid.populate();return false});if(ondblClickRow){$(this).dblclick(function(e){td=(e.target);ptr=$(td,ts.rows).parents("tr.jqgrow");if($(ptr).length===0){return false}ri=ptr[0].rowIndex;ci=!$(td).is("td")?$(td).parents("td:first")[0].cellIndex:td.cellIndex;if(isMSIE){ci=$.jgrid.getAbsoluteIndex(ptr[0],ci)}ts.p.ondblClickRow($(ptr).attr("id"),ri,ci);return false})}if(onRightClickRow){$(this).bind("contextmenu",function(e){td=e.target;ptr=$(td,ts.rows).parents("tr.jqgrow");if($(ptr).length===0){return false}if(!ts.p.multiselect){$(ts).setSelection(false,true,ptr)}ri=ptr[0].rowIndex;ci=!$(td).is("td")?$(td).parents("td:first")[0].cellIndex:td.cellIndex;if(isMSIE){ci=$.jgrid.getAbsoluteIndex(ptr[0],ci)}ts.p.onRightClickRow($(ptr).attr("id"),ri,ci);return false})}grid.bDiv=document.createElement("div");$(grid.bDiv).append(this).addClass("ui-jqgrid-bdiv").css({height:ts.p.height+(isNaN(ts.p.height)?"":"px"),width:(grid.width)+"px"}).scroll(function(e){grid.scrollGrid()});$("table:first",grid.bDiv).css({width:ts.p.tblwidth+"px"});if(isMSIE){if($("tbody",this).size()===2){$("tbody:first",this).remove()}if(ts.p.multikey){$(grid.bDiv).bind("selectstart",function(){return false})}}else{if(ts.p.multikey){$(grid.bDiv).bind("mousedown",function(){return false})}}if(hg){$(grid.bDiv).hide()}grid.cDiv=document.createElement("div");var arf=ts.p.hidegrid===true?$("").addClass("ui-jqgrid-titlebar-close HeaderButton").hover(function(){arf.addClass("ui-state-hover")},function(){arf.removeClass("ui-state-hover")}).append(""):"";$(grid.cDiv).append(arf).append(""+ts.p.caption+"").addClass("ui-jqgrid-titlebar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix");$(grid.cDiv).insertBefore(grid.hDiv);if(ts.p.toolbar[0]){grid.uDiv=document.createElement("div");if(ts.p.toolbar[1]=="top"){$(grid.uDiv).insertBefore(grid.hDiv)}else{if(ts.p.toolbar[1]=="bottom"){$(grid.uDiv).insertAfter(grid.hDiv)}}if(ts.p.toolbar[1]=="both"){grid.ubDiv=document.createElement("div");$(grid.uDiv).insertBefore(grid.hDiv).addClass("ui-userdata ui-state-default").attr("id","t_"+this.id);$(grid.ubDiv).insertAfter(grid.hDiv).addClass("ui-userdata ui-state-default").attr("id","tb_"+this.id);ts.p._height+=IntNum($(grid.ubDiv).height());if(hg){$(grid.ubDiv).hide()}}else{$(grid.uDiv).width(grid.width).addClass("ui-userdata ui-state-default").attr("id","t_"+this.id)}ts.p._height+=IntNum($(grid.uDiv).height());if(hg){$(grid.uDiv).hide()}}if(ts.p.footerrow){grid.sDiv=document.createElement("div");hb=$("
    ");$(grid.sDiv).addClass("ui-jqgrid-sdiv").append(hb).insertAfter(grid.hDiv).width(grid.width);$(hb).append(tfoot);grid.footers=$(".ui-jqgrid-ftable",grid.sDiv)[0].rows[0].cells;if(ts.p.rownumbers){grid.footers[0].className="ui-state-default jqgrid-rownum"}if(hg){$(grid.sDiv).hide()}}if(ts.p.caption){ts.p._height+=parseInt($(grid.cDiv,ts).height(),10);var tdt=ts.p.datatype;if(ts.p.hidegrid===true){$(".ui-jqgrid-titlebar-close",grid.cDiv).toggle(function(){$(".ui-jqgrid-bdiv, .ui-jqgrid-hdiv","#gview_"+ts.p.id).slideUp("fast");if(ts.p.pager){$(ts.p.pager).slideUp("fast")}if(ts.p.toolbar[0]===true){if(ts.p.toolbar[1]=="both"){$(grid.ubDiv).slideUp("fast")}$(grid.uDiv).slideUp("fast")}if(ts.p.footerrow){$(".ui-jqgrid-sdiv","#gbox_"+ts.p.id).slideUp("fast")}$("span",this).removeClass("ui-icon-circle-triangle-n").addClass("ui-icon-circle-triangle-s");ts.p.gridstate="hidden";if(onHdCl){if(!hg){ts.p.onHeaderClick(ts.p.gridstate)}}},function(){$(".ui-jqgrid-hdiv, .ui-jqgrid-bdiv","#gview_"+ts.p.id).slideDown("fast");if(ts.p.pager){$(ts.p.pager).slideDown("fast")}if(ts.p.toolbar[0]===true){if(ts.p.toolbar[1]=="both"){$(grid.ubDiv).slideDown("fast")}$(grid.uDiv).slideDown("fast")}if(ts.p.footerrow){$(".ui-jqgrid-sdiv","#gbox_"+ts.p.id).slideDown("fast")}$("span",this).removeClass("ui-icon-circle-triangle-s").addClass("ui-icon-circle-triangle-n");if(hg){ts.p.datatype=tdt;populate();hg=false}ts.p.gridstate="visible";if(onHdCl){ts.p.onHeaderClick(ts.p.gridstate)}});if(hg){$(".ui-jqgrid-titlebar-close",grid.cDiv).trigger("click");ts.p.datatype="local"}}}else{$(grid.cDiv).hide()}$(grid.hDiv).after(grid.bDiv).mousemove(function(e){if(grid.resizing){grid.dragMove(e)}return false});ts.p._height+=parseInt($(grid.hDiv).height(),10);$(document).mouseup(function(e){if(grid.resizing){grid.dragEnd();return false}return true});this.updateColumns=function(){var r=this.rows[0],self=this;if(r){$("td",r).each(function(k){$(this).css("width",self.grid.headers[k].width+"px")});this.grid.cols=r.cells}return this};ts.formatCol=function(a,b){return formatCol(a,b)};ts.sortData=function(a,b,c){sortData(a,b,c)};ts.updatepager=function(a){updatepager(a)};ts.formatter=function(rowId,cellval,colpos,rwdat,act){return formatter(rowId,cellval,colpos,rwdat,act)};$.extend(grid,{populate:function(){populate()}});this.grid=grid;ts.addXmlData=function(d){addXmlData(d,ts.grid.bDiv)};ts.addJSONData=function(d){addJSONData(d,ts.grid.bDiv)};populate();ts.p.hiddengrid=false;$(window).unload(function(){$(this).empty();this.grid=null;this.p=null})})};$.fn.extend({getGridParam:function(pName){var $t=this[0];if(!$t.grid){return}if(!pName){return $t.p}else{return $t.p[pName]?$t.p[pName]:null}},setGridParam:function(newParams){return this.each(function(){if(this.grid&&typeof(newParams)==="object"){$.extend(true,this.p,newParams)}})},getDataIDs:function(){var ids=[],i=0,len;this.each(function(){len=this.rows.length;if(len&&len>0){while(i=0){if(ner>olr){scrGrid(ner,"d")}else{scrGrid(ner,"u")}}}if(!$t.p.multiselect){if($(pt).attr("class")!=="subgrid"){if($t.p.selrow){$("tr#"+$t.p.selrow.replace(".","\\."),$t.grid.bDiv).removeClass("ui-state-highlight").attr("aria-selected","false")}$t.p.selrow=selection;$(pt).addClass("ui-state-highlight").attr("aria-selected","true");if($t.p.onSelectRow&&onsr){$t.p.onSelectRow($t.p.selrow,true)}}}else{$t.p.selrow=selection;ia=$.inArray($t.p.selrow,$t.p.selarrrow);if(ia===-1){if($(pt).attr("class")!=="subgrid"){$(pt).addClass("ui-state-highlight").attr("aria-selected","true")}stat=true;$("#jqg_"+$t.p.selrow.replace(".","\\."),$t.rows).attr("checked",stat);$t.p.selarrrow.push($t.p.selrow);if($t.p.onSelectRow&&onsr){$t.p.onSelectRow($t.p.selrow,stat)}}else{if($(pt).attr("class")!=="subgrid"){$(pt).removeClass("ui-state-highlight").attr("aria-selected","false")}stat=false;$("#jqg_"+$t.p.selrow.replace(".","\\."),$t.rows).attr("checked",stat);$t.p.selarrrow.splice(ia,1);if($t.p.onSelectRow&&onsr){$t.p.onSelectRow($t.p.selrow,stat)}tpsr=$t.p.selarrrow[0];$t.p.selrow=(tpsr=="undefined")?null:tpsr}}function scrGrid(iR,tp){var ch=$($t.grid.bDiv)[0].clientHeight,st=$($t.grid.bDiv)[0].scrollTop,nROT=$t.rows[iR].offsetTop+$t.rows[iR].clientHeight,pROT=$t.rows[iR].offsetTop;if(tp=="d"){if(nROT>=ch){$($t.grid.bDiv)[0].scrollTop=st+nROT-pROT}}if(tp=="u"){if(pROT span:first",ind).html(vl).attr("title",$.jgrid.stripHtml(vl))}else{$("td:eq("+i+")",ind).html(vl).attr("title",$.jgrid.stripHtml(vl))}success=true}})}});return success},addRowData:function(rowid,data,pos,src){if(!pos){pos="last"}var success=false,nm,row,gi=0,si=0,ni=0,sind,i,v,prp="";if(data){this.each(function(){var t=this;rowid=typeof(rowid)!="undefined"?rowid+"":t.p.records+1;row='';if(t.p.rownumbers===true){prp=t.formatCol(ni,1);row+='0";ni=1}if(t.p.multiselect){v='';prp=t.formatCol(ni,1);row+='"+v+"";gi=1}if(t.p.subGrid===true){row+=$(t).addSubGridCell(gi+ni,1);si=1}for(i=gi+si+ni;i'+v+""}row+="";if(t.p.subGrid===true){row=$(row)[0];$(t).addSubGrid(row,gi+ni)}if(t.rows.length===0){$("table:first",t.grid.bDiv).append(row)}else{switch(pos){case"last":$(t.rows[t.rows.length-1]).after(row);break;case"first":$(t.rows[0]).before(row);break;case"after":sind=t.rows.namedItem(src);sind!=null?$(t.rows[sind.rowIndex+1]).hasClass("ui-subgrid")?$(t.rows[sind.rowIndex+1]).after(row):$(sind).after(row):"";break;case"before":sind=t.rows.namedItem(src);sind!=null?$(sind).before(row):"";break}}t.p.records++;t.p.reccount++;if(pos==="first"||(pos==="before"&&sind===0)||t.rows.length===1){t.updateColumns()}if(t.p.altRows===true){var cn=t.p.altclass;if(pos=="last"){if(t.rows.length%2==1){$(t.rows[t.rows.length-1]).addClass(cn)}}else{$(t.rows).each(function(i){if(i%2==1){$(this).addClass(cn)}else{$(this).removeClass(cn)}})}}try{t.p.afterInsertRow(rowid,data)}catch(e){}t.updatepager(true);success=true})}return success},footerData:function(action,data,format){var nm,success=false,res={};function isEmpty(obj){for(var i in obj){return false}return true}if(typeof(action)=="undefined"){action="get"}if(typeof(format)!="boolean"){format=true}action=action.toLowerCase();this.each(function(){var t=this,vl,ind;if(!t.grid||!t.p.footerrow){return false}if(action=="set"){if(isEmpty(data)){return false}}success=true;$(this.p.colModel).each(function(i){nm=this.name;if(action=="set"){if(data[nm]!=undefined){vl=format?t.formatter("",data[nm],i,data,"edit"):data[nm];$("tr.footrow td:eq("+i+")",t.grid.sDiv).html(vl).attr("title",$.jgrid.stripHtml(vl));success=true}}else{if(action=="get"){res[nm]=$("tr.footrow td:eq("+i+")",t.grid.sDiv).html()}}})});return action=="get"?res:success},ShowHideCol:function(colname,show){return this.each(function(){var $t=this,fndh=false;if(!$t.grid){return}if(typeof colname==="string"){colname=[colname]}show=show!="none"?"":"none";var sw=show==""?true:false;$(this.p.colModel).each(function(i){if($.inArray(this.name,colname)!==-1&&this.hidden===sw){$("tr",$t.grid.hDiv).each(function(){$("th:eq("+i+")",this).css("display",show)});$($t.rows).each(function(j){$("td:eq("+i+")",$t.rows[j]).css("display",show)});if($t.p.footerrow){$("td:eq("+i+")",$t.grid.sDiv).css("display",show)}if(show=="none"){$t.p.tblwidth-=this.width}else{$t.p.tblwidth+=this.width}this.hidden=!sw;fndh=true}});if(fndh===true){$("table:first",$t.grid.hDiv).width($t.p.tblwidth);$("table:first",$t.grid.bDiv).width($t.p.tblwidth);$t.grid.hDiv.scrollLeft=$t.grid.bDiv.scrollLeft;if($t.p.footerrow){$("table:first",$t.grid.sDiv).width($t.p.tblwidth);$t.grid.sDiv.scrollLeft=$t.grid.bDiv.scrollLeft}}})},hideCol:function(colname){return this.each(function(){$(this).ShowHideCol(colname,"none")})},showCol:function(colname){return this.each(function(){$(this).ShowHideCol(colname,"")})},setGridWidth:function(nwidth,shrink){return this.each(function(){var $t=this,cw,initwidth=0,brd=$t.p.cellLayout,lvc,vc=0,isSafari,hs=false,scw=$t.p.scrollOffset,aw,gw=0,tw=0,msw=$t.p.multiselectWidth,sgw=$t.p.subGridWidth,rnw=$t.p.rownumWidth,cl=$t.p.cellLayout,cr;if(!$t.grid){return}if(typeof shrink!="boolean"){shrink=$t.p.shrinkToFit}if(isNaN(nwidth)){return}if(nwidth==$t.grid.width){return}else{$t.grid.width=$t.p.width=nwidth}$("#gbox_"+$t.p.id).css("width",nwidth+"px");$("#gview_"+$t.p.id).css("width",nwidth+"px");$($t.grid.bDiv).css("width",nwidth+"px");$($t.grid.hDiv).css("width",nwidth+"px");if($t.p.pager){$($t.p.pager).css("width",nwidth+"px")}if($t.p.toolbar[0]===true){$($t.grid.uDiv).css("width",nwidth+"px");if($t.p.toolbar[1]=="both"){$($t.grid.ubDiv).css("width",nwidth+"px")}}if($t.p.footerrow){$($t.grid.sDiv).css("width",nwidth+"px")}if(shrink===false&&$t.p.forceFit==true){$t.p.forceFit=false}if(shrink===true){$.each($t.p.colModel,function(i){if(this.hidden===false){initwidth+=parseInt(this.width,10);vc++}});isSafari=$.browser.safari?true:false;if(isSafari){brd=0;msw+=cl;sgw+=cl;rnw+=cl}if($t.p.multiselect){tw=msw;gw=msw+brd;vc--}if($t.p.subGrid){tw+=sgw;gw+=sgw+brd;vc--}if($t.p.rownumbers){tw+=rnw;gw+=rnw+brd;vc--}$t.p.tblwidth=initwidth;aw=nwidth-brd*vc-gw;if(!isNaN($t.p.height)){if($($t.grid.bDiv)[0].clientHeight<$($t.grid.bDiv)[0].scrollHeight){hs=true;aw-=scw}}initwidth=0;var cl=$t.grid.cols.length>0;$.each($t.p.colModel,function(i){var tn=this.name;if(this.hidden===false&&tn!=="cb"&&tn!=="subgrid"&&tn!=="rn"){cw=Math.floor((aw)/($t.p.tblwidth-tw)*this.width);this.width=cw;initwidth+=cw;$t.grid.headers[i].width=cw;$t.grid.headers[i].el.style.width=cw+"px";if($t.p.footerrow){$t.grid.footers[i].style.width=cw+"px"}if(cl){$t.grid.cols[i].style.width=cw+"px"}lvc=i}});cr=0;if(hs&&nwidth-gw-(initwidth+brd*vc)!==scw){cr=nwidth-gw-(initwidth+brd*vc)-scw}else{if(Math.abs(nwidth-gw-(initwidth+brd*vc))!==1){cr=nwidth-gw-(initwidth+brd*vc)}}$t.p.colModel[lvc].width+=cr;cw=$t.p.colModel[lvc].width;$t.grid.headers[lvc].width=cw;$t.grid.headers[lvc].el.style.width=cw+"px";if(cl>0){$t.grid.cols[lvc].style.width=cw+"px"}$t.p.tblwidth=initwidth+tw+cr;$("table:first",$t.grid.bDiv).css("width",initwidth+tw+cr+"px");$("table:first",$t.grid.hDiv).css("width",initwidth+tw+cr+"px");$t.grid.hDiv.scrollLeft=$t.grid.bDiv.scrollLeft;if($t.p.footerrow){$t.grid.footers[lvc].style.width=cw+"px";$("table:first",$t.grid.sDiv).css("width",initwidth+tw+cr+"px")}}})},setGridHeight:function(nh){return this.each(function(){var $t=this;if(!$t.grid){return}$($t.grid.bDiv).css({height:nh+(isNaN(nh)?"":"px")});$t.p.height=nh})},setCaption:function(newcap){return this.each(function(){this.p.caption=newcap;$("span.ui-jqgrid-title",this.grid.cDiv).html(newcap);$(this.grid.cDiv).show()})},setLabel:function(colname,nData,prop,attrp){return this.each(function(){var $t=this,pos=-1;if(!$t.grid){return}if(isNaN(colname)){$($t.p.colModel).each(function(i){if(this.name==colname){pos=i;return false}})}else{pos=parseInt(colname,10)}if(pos>=0){var thecol=$("tr.ui-jqgrid-labels th:eq("+pos+")",$t.grid.hDiv);if(nData){$("div",thecol).html(nData)}if(prop){if(typeof prop==="string"){$(thecol).addClass(prop)}else{$(thecol).css(prop)}}if(typeof attrp==="object"){$(thecol).attr(attrp)}}})},setCell:function(rowid,colname,nData,cssp,attrp){return this.each(function(){var $t=this,pos=-1,v;if(!$t.grid){return}if(isNaN(colname)){$($t.p.colModel).each(function(i){if(this.name==colname){pos=i;return false}})}else{pos=parseInt(colname,10)}if(pos>=0){var ind=$t.rows.namedItem(rowid);if(ind){var tcell=$("td:eq("+pos+")",ind);if(nData!==""){v=$t.formatter(rowid,nData,pos,ind,"edit");$(tcell).html(v).attr("title",$.jgrid.stripHtml(v))}if(cssp){if(typeof cssp==="string"){$(tcell).addClass(cssp)}else{$(tcell).css(cssp)}}if(typeof attrp==="object"){$(tcell).attr(attrp)}}}})},getCell:function(rowid,col){var ret=false;this.each(function(){var $t=this,pos=-1;if(!$t.grid){return}if(isNaN(col)){$($t.p.colModel).each(function(i){if(this.name===col){pos=i;return false}})}else{pos=parseInt(col,10)}if(pos>=0){var ind=$t.rows.namedItem(rowid);if(ind){ret=$.jgrid.htmlDecode($("td:eq("+pos+")",ind).html())}}});return ret},getCol:function(col){var ret=[];this.each(function(){var $t=this,pos=-1;if(!$t.grid){return}if(isNaN(col)){$($t.p.colModel).each(function(i){if(this.name===col){pos=i;return false}})}else{pos=parseInt(col,10)}if(pos>=0){var ln=$t.rows.length,i=0;if(ln&&ln>0){while(i0){if(nDotIndex<0){sOutput+=sDecimalSeparator;nDotIndex=sOutput.length-1}else{if(sDecimalSeparator!=="."){sOutput=sOutput.replace(".",sDecimalSeparator)}}while((sOutput.length-1-nDotIndex)-1)?nDotIndex:sOutput.length;var sNewOutput=sOutput.substring(nDotIndex);var nCount=-1;for(var i=nDotIndex;i>0;i--){nCount++;if((nCount%3===0)&&(i!==nDotIndex)&&(!bNegative||(i>1))){sNewOutput=sThousandsSeparator+sNewOutput}sNewOutput=sOutput.charAt(i-1)+sNewOutput}sOutput=sNewOutput}sOutput=(opts.prefix)?opts.prefix+sOutput:sOutput;sOutput=(opts.suffix)?sOutput+opts.suffix:sOutput;return sOutput}else{return nData}},DateFormat:function(format,date,newformat,opts){var token=/\\.|[dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU]/g,timezone=/\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,timezoneClip=/[^-+\dA-Z]/g,pad=function(value,length){value=String(value);length=parseInt(length)||2;while(value.length11){date[k]=dM+1-12}}ts[format[k].toLowerCase()]=parseInt(date[k],10)}ts.m=parseInt(ts.m)-1;var ty=ts.y;if(ty>=70&&ty<=99){ts.y=1900+ts.y}else{if(ty>=0&&ty<=69){ts.y=2000+ts.y}}timestamp=new Date(ts.y,ts.m,ts.d,ts.h,ts.i,ts.s,0);if(opts.masks.newformat){newformat=opts.masks.newformat}else{if(!newformat){newformat="Y-m-d"}}var G=timestamp.getHours(),i=timestamp.getMinutes(),j=timestamp.getDate(),n=timestamp.getMonth()+1,o=timestamp.getTimezoneOffset(),s=timestamp.getSeconds(),u=timestamp.getMilliseconds(),w=timestamp.getDay(),Y=timestamp.getFullYear(),N=(w+6)%7+1,z=(new Date(Y,n-1,j)-new Date(Y,0,1))/86400000,flags={d:pad(j),D:dateFormat.i18n.dayNames[w],j:j,l:dateFormat.i18n.dayNames[w+7],N:N,S:opts.S(j),w:w,z:z,W:N<5?Math.floor((z+N-1)/7)+1:Math.floor((z+N-1)/7)||((new Date(Y-1,0,1).getDay()+6)%7<4?53:52),F:dateFormat.i18n.monthNames[n-1+12],m:pad(n),M:dateFormat.i18n.monthNames[n-1],n:n,t:"?",L:"?",o:"?",Y:Y,y:String(Y).substring(2),a:G<12?opts.AmPm[0]:opts.AmPm[1],A:G<12?opts.AmPm[2]:opts.AmPm[3],B:"?",g:G%12||12,G:G,h:pad(G%12||12),H:pad(G),i:pad(i),s:pad(s),u:u,e:"?",I:"?",O:(o>0?"-":"+")+pad(Math.floor(Math.abs(o)/60)*100+Math.abs(o)%60,4),P:"?",T:(String(timestamp).match(timezone)||[""]).pop().replace(timezoneClip,""),Z:"?",c:"?",r:"?",U:Math.floor(timestamp/1000)};return newformat.replace(token,function($0){return $0 in flags?flags[$0]:$0.substring(1)})}};$.fn.fmatter.defaultFormat=function(cellval,opts){return(isValue(cellval)&&cellval!=="")?cellval:opts.defaultValue?opts.defaultValue:" "};$.fn.fmatter.email=function(cellval,opts){if(!isEmpty(cellval)){return'
    '+cellval+""}else{return $.fn.fmatter.defaultFormat(cellval,opts)}};$.fn.fmatter.checkbox=function(cval,opts){var op=$.extend({},opts.checkbox),ds;if(!isUndefined(opts.colModel.formatoptions)){op=$.extend({},op,opts.colModel.formatoptions)}if(op.disabled===true){ds="disabled"}else{ds=""}cval=cval+"";cval=cval.toLowerCase();var bchk=cval.search(/(false|0|no|off)/i)<0?" checked='checked' ":"";return'"},$.fn.fmatter.link=function(cellval,opts){var op={target:opts.target};var target="";if(!isUndefined(opts.colModel.formatoptions)){op=$.extend({},op,opts.colModel.formatoptions)}if(op.target){target="target="+op.target}if(!isEmpty(cellval)){return"'+cellval+""}else{return $.fn.fmatter.defaultFormat(cellval,opts)}};$.fn.fmatter.showlink=function(cellval,opts){var op={baseLinkUrl:opts.baseLinkUrl,showAction:opts.showAction,addParam:opts.addParam,target:opts.target,idName:opts.idName},target="";if(!isUndefined(opts.colModel.formatoptions)){op=$.extend({},op,opts.colModel.formatoptions)}if(op.target){target="target="+op.target}idUrl=op.baseLinkUrl+op.showAction+"?"+op.idName+"="+opts.rowId+op.addParam;if(isString(cellval)){return"'+cellval+""}else{return $.fn.fmatter.defaultFormat(cellval,opts)}};$.fn.fmatter.integer=function(cellval,opts){var op=$.extend({},opts.integer);if(!isUndefined(opts.colModel.formatoptions)){op=$.extend({},op,opts.colModel.formatoptions)}if(isEmpty(cellval)){return op.defaultValue}return $.fmatter.util.NumberFormat(cellval,op)};$.fn.fmatter.number=function(cellval,opts){var op=$.extend({},opts.number);if(!isUndefined(opts.colModel.formatoptions)){op=$.extend({},op,opts.colModel.formatoptions)}if(isEmpty(cellval)){return op.defaultValue}return $.fmatter.util.NumberFormat(cellval,op)};$.fn.fmatter.currency=function(cellval,opts){var op=$.extend({},opts.currency);if(!isUndefined(opts.colModel.formatoptions)){op=$.extend({},op,opts.colModel.formatoptions)}if(isEmpty(cellval)){return op.defaultValue}return $.fmatter.util.NumberFormat(cellval,op)};$.fn.fmatter.date=function(cellval,opts,act){var op=$.extend({},opts.date);if(!isUndefined(opts.colModel.formatoptions)){op=$.extend({},op,opts.colModel.formatoptions)}if(!op.reformatAfterEdit&&act=="edit"){return $.fn.fmatter.defaultFormat(cellval,opts)}else{if(!isEmpty(cellval)){return $.fmatter.util.DateFormat(op.srcformat,cellval,op.newformat,op)}else{return $.fn.fmatter.defaultFormat(cellval,opts)}}};$.fn.fmatter.select=function(cellval,opts,act){if(act=="edit"){return $.fn.fmatter.defaultFormat(cellval,opts)}else{if(!isEmpty(cellval)){var oSelect=false;if(!isUndefined(opts.colModel.editoptions)){oSelect=opts.colModel.editoptions.value}if(oSelect){var ret=[],msl=opts.colModel.editoptions.multiple===true?true:false,scell=[],sv;if(msl){scell=cellval.split(",");scell=$.map(scell,function(n){return $.trim(n)})}if(isString(oSelect)){var so=oSelect.split(";"),j=0;for(var i=0;i-1){ret[j]=sv[1];j++}}else{if($.trim(sv[0])==$.trim(cellval)){ret[0]=sv[1];break}}}}else{if(isObject(oSelect)){if(msl){ret=jQuery.map(scel,function(n,i){return oSelect[n]})}ret[0]=oSelect[cellval]||""}}return ret.join(", ")}else{return $.fn.fmatter.defaultFormat(cellval,opts)}}}};$.unformat=function(cellval,options,pos,cnt){var ret,formatType=options.colModel.formatter,op=options.colModel.formatoptions||{},unformatFunc=options.colModel.unformat||($.fn.fmatter[formatType]&&$.fn.fmatter[formatType].unformat);if(unformatFunc!=="undefined"&&isFunction(unformatFunc)){ret=unformatFunc($(cellval).text(),options)}else{if(formatType!=="undefined"&&isString(formatType)){var opts=$.jgrid.formatter||{},stripTag;switch(formatType){case"integer":op=$.extend({},opts.integer,op);stripTag=eval("/"+op.thousandsSeparator+"/g");ret=$(cellval).text().replace(stripTag,"");break;case"number":op=$.extend({},opts.number,op);stripTag=eval("/"+op.thousandsSeparator+"/g");ret=$(cellval).text().replace(op.decimalSeparator,".").replace(stripTag,"");break;case"currency":op=$.extend({},opts.currency,op);stripTag=eval("/"+op.thousandsSeparator+"/g");ret=$(cellval).text().replace(op.decimalSeparator,".").replace(op.prefix,"").replace(op.suffix,"").replace(stripTag,"");break;case"checkbox":var cbv=(options.colModel.editoptions)?options.colModel.editoptions.value.split(":"):["Yes","No"];ret=$("input",cellval).attr("checked")?cbv[0]:cbv[1];break;default:ret=$(cellval).text();break}}}return ret?ret:cnt===true?$(cellval).text():$.jgrid.htmlDecode($(cellval).html())};function fireFormatter(formatType,cellval,opts,rwd,act){formatType=formatType.toLowerCase();var v=cellval;if($.fn.fmatter[formatType]){v=$.fn.fmatter[formatType](cellval,opts,act)}return v}function debug($obj){if(window.console&&window.console.log){window.console.log($obj)}}isValue=function(o){return(isObject(o)||isString(o)||isNumber(o)||isBoolean(o))};isBoolean=function(o){return typeof o==="boolean"};isNull=function(o){return o===null};isNumber=function(o){return typeof o==="number"&&isFinite(o)};isString=function(o){return typeof o==="string"};isEmpty=function(o){if(!isString(o)&&isValue(o)){return false}else{if(!isValue(o)){return true}}o=$.trim(o).replace(/\ \;/ig,"").replace(/\ \;/ig,"");return o===""};isUndefined=function(o){return typeof o==="undefined"};isObject=function(o){return(o&&(typeof o==="object"||isFunction(o)))||false};isFunction=function(o){return typeof o==="function"}})(jQuery);(function(a){a.fn.extend({getColProp:function(d){var b={},f=this[0];if(!f.grid){return}var e=f.p.colModel;for(var c=0;c0){a(e).each(function(m){i=this;k=h.rows.namedItem(i[c]);if(k){g=i[c];if(d===true){if(h.p.jsonReader.repeatitems===true){if(h.p.jsonReader.cell){i=i[h.p.jsonReader.cell]}for(var l=0;l span:first",k).html(j).attr("title",a.jgrid.stripHtml(j))}else{a("td:eq("+l+")",k).html(j).attr("title",a.jgrid.stripHtml(j))}}f=true;return true}}a(h.p.colModel).each(function(n){b=d===true?this.jsonmap||this.name:this.name;if(i[b]!=undefined){j=h.formatter(g,i[b],n,i,"edit");if(h.p.treeGrid===true&&b==h.p.ExpandColumn){a("td:eq("+n+") > span:first",k).html(j).attr("title",a.jgrid.stripHtml(j))}else{a("td:eq("+n+")",k).html(j).attr("title",a.jgrid.stripHtml(j))}f=true}})}})}});return f},filterGrid:function(c,b){b=a.extend({gridModel:false,gridNames:false,gridToolbar:false,filterModel:[],formtype:"horizontal",autosearch:true,formclass:"filterform",tableclass:"filtertable",buttonclass:"filterbutton",searchButton:"Search",clearButton:"Clear",enableSearch:false,enableClear:false,beforeSearch:null,afterSearch:null,beforeClear:null,afterClear:null,url:"",marksearched:true},b||{});return this.each(function(){var l=this;this.p=b;if(this.p.filterModel.length==0&&this.p.gridModel===false){alert("No filter is set");return}if(!c){alert("No target grid is set!");return}this.p.gridid=c.indexOf("#")!=-1?c:"#"+c;var d=a(this.p.gridid).getGridParam("colModel");if(d){if(this.p.gridModel===true){var e=a(this.p.gridid)[0];var g;a.each(d,function(o,p){var m=[];this.search=this.search===false?false:true;if(this.editrules&&this.editrules.searchhidden===true){g=true}else{if(this.hidden===true){g=false}else{g=true}}if(this.search===true&&g===true){if(l.p.gridNames===true){m.label=e.p.colNames[o]}else{m.label=""}m.name=this.name;m.index=this.index||this.name;m.stype=this.edittype||"text";if(m.stype!="select"){m.stype="text"}m.defval=this.defval||"";m.surl=this.surl||"";m.sopt=this.editoptions||{};m.width=this.width;l.p.filterModel.push(m)}})}else{a.each(l.p.filterModel,function(o,p){for(var m=0;m0?true:false;a.extend(o.p.postData,q);var s;if(l.p.url){s=a(o).getGridParam("url");a(o).setGridParam({url:l.p.url})}a(o).setGridParam({search:r,page:1}).trigger("reloadGrid");if(s){a(o).setGridParam({url:s})}if(a.isFunction(l.p.afterSearch)){l.p.afterSearch()}};var k=function(){var q={},n,p=0;var o=a(l.p.gridid)[0],m;if(a.isFunction(l.p.beforeClear)){l.p.beforeClear()}a.each(l.p.filterModel,function(t,w){m=this.index;n=(this.defval)?this.defval:"";if(!this.stype){this.stype=="text"}switch(this.stype){case"select":var v;a("select[name="+m+"] option",l).each(function(x){if(x==0){this.selected=true}if(a(this).text()==n){this.selected=true;v=a(this).val();return false}});if(v){q[m]=v;if(l.p.marksearched){a("#jqgh_"+this.name,o.grid.hDiv).addClass("dirty-cell")}p++}else{if(l.p.marksearched){a("#jqgh_"+this.name,o.grid.hDiv).removeClass("dirty-cell")}try{delete o.p.postData[this.index]}catch(u){}}break;case"text":a("input[name="+m+"]",l).val(n);if(n){q[m]=n;if(l.p.marksearched){a("#jqgh_"+this.name,o.grid.hDiv).addClass("dirty-cell")}p++}else{if(l.p.marksearched){a("#jqgh_"+this.name,o.grid.hDiv).removeClass("dirty-cell")}try{delete o.p.postData[this.index]}catch(u){}}break}});var r=p>0?true:false;a.extend(o.p.postData,q);var s;if(l.p.url){s=a(o).getGridParam("url");a(o).setGridParam({url:l.p.url})}a(o).setGridParam({search:r,page:1}).trigger("reloadGrid");if(s){a(o).setGridParam({url:s})}if(a.isFunction(l.p.afterClear)){l.p.afterClear()}};var i=function(){var q=document.createElement("tr");var n,s,m,o,r,p;if(l.p.formtype=="horizontal"){a(f).append(q)}a.each(l.p.filterModel,function(A,v){o=document.createElement("td");a(o).append("");r=document.createElement("td");var z=this;if(!this.stype){this.stype="text"}switch(this.stype){case"select":if(this.surl){a(r).load(this.surl,function(){if(z.defval){a("select",this).val(z.defval)}a("select",this).attr({name:z.index||z.name,id:"sg_"+z.name});if(z.sopt){a("select",this).attr(z.sopt)}if(l.p.gridToolbar===true&&z.width){a("select",this).width(z.width)}if(l.p.autosearch===true){a("select",this).change(function(E){h();return false})}})}else{if(z.sopt.value){var t=z.sopt.value;var w=document.createElement("select");a(w).attr({name:z.index||z.name,id:"sg_"+z.name}).attr(z.sopt);if(typeof t==="string"){var u=t.split(";"),D,x;for(var y=0;y");if(z.sopt){a("input",r).attr(z.sopt)}if(l.p.gridToolbar===true&&z.width){if(a.browser.msie){a("input",r).width(z.width-4)}else{a("input",r).width(z.width-2)}}if(l.p.autosearch===true){a("input",r).keypress(function(F){var E=F.charCode?F.charCode:F.keyCode?F.keyCode:0;if(E==13){h();return false}return this})}break}if(l.p.formtype=="horizontal"){if(l.p.gridToolbar===true&&l.p.gridNames===false){a(q).append(r)}else{a(q).append(o).append(r)}a(q).append(r)}else{n=document.createElement("tr");a(n).append(o).append(r);a(f).append(n)}});r=document.createElement("td");if(l.p.enableSearch===true){s="";a(r).append(s);a("input#sButton",r).click(function(){h();return false})}if(l.p.enableClear===true){m="";a(r).append(m);a("input#cButton",r).click(function(){k();return false})}if(l.p.enableClear===true||l.p.enableSearch===true){if(l.p.formtype=="horizontal"){a(q).append(r)}else{n=document.createElement("tr");a(n).append(" ").append(r);a(f).append(n)}}};var j=a("
    ");var f=a("
    ");a(j).append(f);i();a(this).append(j);this.triggerSearch=function(){h()};this.clearSearch=function(){k()}})},filterToolbar:function(b){b=a.extend({autosearch:true,beforeSearch:null,afterSearch:null,beforeClear:null,afterClear:null,searchurl:""},b||{});return this.each(function(){var g=this;var c=function(){var o={},n=0,m,l;g.p.searchdata={};if(a.isFunction(b.beforeSearch)){b.beforeSearch()}a.each(g.p.colModel,function(r,t){l=this.index||this.name;switch(this.stype){case"select":m=a("select[name="+l+"]",g.grid.hDiv).val();if(m){o[l]=m;n++}else{try{delete g.p.postData[l]}catch(s){}}break;case"text":m=a("input[name="+l+"]",g.grid.hDiv).val();if(m){o[l]=m;n++}else{try{delete g.p.postData[l]}catch(s){}}break}});var p=n>0?true:false;a.extend(g.p.postData,o);var q;if(g.p.searchurl){q=g.p.url;a(g).setGridParam({url:g.p.searchurl})}a(g).setGridParam({search:p,page:1}).trigger("reloadGrid");if(q){a(g).setGridParam({url:q})}if(a.isFunction(b.afterSearch)){b.afterSearch()}};var j=function(){var o={},m,n=0,l;if(a.isFunction(b.beforeClear)){b.beforeClear()}a.each(g.p.colModel,function(r,u){m=(this.searchoptions&&this.searchoptions.defaultValue)?this.searchoptions.defaultValue:"";l=this.index||this.name;switch(this.stype){case"select":var t;a("select[name="+l+"] option",g.grid.hDiv).each(function(v){if(v==0){this.selected=true}if(a(this).text()==m){this.selected=true;t=a(this).val();return false}});if(t){o[l]=t;n++}else{try{delete g.p.postData[l]}catch(s){}}break;case"text":a("input[name="+l+"]",g.grid.hDiv).val(m);if(m){o[l]=m;n++}else{try{delete g.p.postData[l]}catch(s){}}break}});var p=n>0?true:false;a.extend(g.p.postData,o);var q;if(g.p.searchurl){q=g.p.url;a(g).setGridParam({url:g.p.searchurl})}a(g).setGridParam({search:p,page:1}).trigger("reloadGrid");if(q){a(g).setGridParam({url:q})}if(a.isFunction(b.afterClear)){b.afterClear()}};var k=function(){var l=a("tr.ui-search-toolbar",g.grid.hDiv);if(l.css("display")=="none"){l.show()}else{l.hide()}};function f(l,n){var m=a(l);if(m[0]!=null){jQuery.each(n,function(){if(this.data!=null){m.bind(this.type,this.data,this.fn)}else{m.bind(this.type,this.fn)}})}}var h=a(""),d,i,e;a.each(g.p.colModel,function(s,o){var u=this;d=a("");i=a("
    ");if(this.hidden===true){a(d).css("display","none")}this.search=this.search===false?false:true;if(typeof this.stype=="undefined"){this.stype="text"}e=a.extend({},this.searchoptions||{});if(this.search){switch(this.stype){case"select":if(this.surl){a(i).load(this.surl,{_nsd:(new Date().getTime())},function(){if(e.defaultValue){a("select",this).val(e.defaultValue)}a("select",this).attr({name:u.index||u.name,id:"gs_"+u.name});if(e.attr){a("select",this).attr(e.attr)}a("select",this).css({width:"100%"});if(e.dataInit!=null){e.dataInit(a("select",this)[0])}if(e.dataEvents!=null){f(a("select",this)[0],e.dataEvents)}if(b.autosearch===true){a("select",this).change(function(n){c();return false})}})}else{if(u.editoptions&&u.editoptions.value){var l=u.editoptions.value,p=document.createElement("select");p.style.width="100%";a(p).attr({name:u.index||u.name,id:"gs_"+u.name});if(typeof l==="string"){var m=l.split(";"),w,q;for(var r=0;r");if(e.attr){a("input",i).attr(e.attr)}if(e.dataInit!=null){e.dataInit(a("input",i)[0])}if(e.dataEvents!=null){f(a("input",i)[0],e.dataEvents)}if(b.autosearch===true){a("input",i).keypress(function(x){var n=x.charCode?x.charCode:x.keyCode?x.keyCode:0;if(n==13){c();return false}return this})}break}}a(d).append(i);a(h).append(d)});a("table thead",g.grid.hDiv).append(h);this.triggerToolbar=function(){c()};this.clearToolbar=function(){j()};this.toggleToolbar=function(){k()}})}})})(jQuery);var showModal=function(a){a.w.show()};var closeModal=function(a){a.w.hide().attr("aria-hidden","true");if(a.o){a.o.remove()}};var createModal=function(i,d,a,k,m,l){var h=document.createElement("div");h.className="ui-widget ui-widget-content ui-corner-all ui-jqdialog";h.id=i.themodal;var b=document.createElement("div");b.className="ui-jqdialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix";b.id=i.modalhead;jQuery(b).append(""+a.caption+"");var j=jQuery("").hover(function(){j.addClass("ui-state-hover")},function(){j.removeClass("ui-state-hover")}).append("");jQuery(b).append(j);var g=document.createElement("div");jQuery(g).addClass("ui-jqdialog-content ui-widget-content").attr("id",i.modalcontent);jQuery(g).append(d);h.appendChild(g);jQuery(h).prepend(b);if(l===true){jQuery("body").append(h)}else{jQuery(h).insertBefore(k)}if(typeof a.jqModal==="undefined"){a.jqModal=true}if(jQuery.fn.jqm&&a.jqModal===true){if(a.left==0&&a.top==0){var f=[];f=findPos(m);a.left=f[0]+4;a.top=f[1]+4}}jQuery("a.ui-jqdialog-titlebar-close",b).click(function(o){var n=jQuery("#"+i.themodal).data("onClose")||a.onClose;var p=jQuery("#"+i.themodal).data("gbox")||a.gbox;hideModal("#"+i.themodal,{gb:p,jqm:a.jqModal,onClose:n});return false});if(a.width==0||!a.width){a.width=300}if(a.height==0||!a.height){a.height=200}if(!a.zIndex){a.zIndex=950}jQuery(h).css({top:a.top+"px",left:a.left+"px",width:isNaN(a.width)?"auto":a.width+"px",height:isNaN(a.height)?"auto":a.height+"px",zIndex:a.zIndex,overflow:"hidden"}).attr({tabIndex:"-1",role:"dialog","aria-labelledby":i.modalhead,"aria-hidden":"true"});if(typeof a.drag=="undefined"){a.drag=true}if(typeof a.resize=="undefined"){a.resize=true}if(a.drag){jQuery(b).css("cursor","move");if(jQuery.fn.jqDrag){jQuery(h).jqDrag(b)}else{try{jQuery(h).draggable({handle:jQuery("#"+b.id)})}catch(c){}}}if(a.resize){if(jQuery.fn.jqResize){jQuery(h).append("
    ");jQuery("#"+i.themodal).jqResize(".jqResize",i.scrollelm?"#"+i.scrollelm:false)}else{try{jQuery(h).resizable({handles:"se",alsoResize:i.scrollelm?"#"+i.scrollelm:false})}catch(c){}}}if(a.closeOnEscape===true){jQuery(h).keydown(function(o){if(o.which==27){var n=jQuery("#"+i.themodal).data("onClose")||a.onClose;hideModal(this,{gb:a.gbox,jqm:a.jqModal,onClose:n})}})}};var viewModal=function(a,c){c=jQuery.extend({toTop:true,overlay:10,modal:false,onShow:showModal,onHide:closeModal,gbox:"",jqm:true,jqM:true},c||{});if(jQuery.fn.jqm&&c.jqm==true){if(c.jqM){jQuery(a).attr("aria-hidden","false").jqm(c).jqmShow()}else{jQuery(a).attr("aria-hidden","false").jqmShow()}}else{if(c.gbox!=""){jQuery(".jqgrid-overlay:first",c.gbox).show();jQuery(a).data("gbox",c.gbox)}jQuery(a).show().attr("aria-hidden","false");try{jQuery(":input:visible",a)[0].focus()}catch(b){}}return false};var hideModal=function(a,d){d=jQuery.extend({jqm:true,gb:""},d||{});if(d.onClose){var b=d.onClose(a);if(typeof b=="boolean"&&!b){return}}if(jQuery.fn.jqm&&d.jqm===true){jQuery(a).attr("aria-hidden","true").jqmHide()}else{if(d.gb!=""){try{jQuery(".jqgrid-overlay:first",d.gb).hide()}catch(c){}}jQuery(a).hide().attr("aria-hidden","true")}};function info_dialog(a,d,b){var c="
    ";c+="

    "+d+"

    ";c+="";c+="
    ";createModal({themodal:"info_dialog",modalhead:"info_head",modalcontent:"info_content"},c,{width:290,height:120,drag:false,resize:false,caption:""+a+"",left:250,top:170,closeOnEscape:true},"","",true);jQuery("#closedialog","#info_id").addClass("ui-state-default ui-corner-all").height(21).css({padding:" .2em .5em",cursor:"pointer"}).hover(function(){jQuery(this).addClass("ui-state-hover")},function(){jQuery(this).removeClass("ui-state-hover")});if(jQuery.fn.jqm){}else{jQuery("#closedialog","#info_id").click(function(f){hideModal("#info_dialog");return false})}viewModal("#info_dialog",{onHide:function(e){e.w.hide().remove();if(e.o){e.o.remove()}},modal:true})}function findPos(a){var b=curtop=0;if(a.offsetParent){do{b+=a.offsetLeft;curtop+=a.offsetTop}while(a=a.offsetParent)}return[b,curtop]}function isArray(a){if(a.constructor.toString().indexOf("Array")==-1){return false}else{return true}}function createEl(h,r,f){var g="";if(r.defaultValue){delete r.defaultValue}function o(i,e){if(jQuery.isFunction(e.dataInit)){i.id=e.id;e.dataInit(i);delete e.id;delete e.dataInit}if(e.dataEvents){jQuery.each(e.dataEvents,function(){if(this.data!=null){jQuery(i).bind(this.type,this.data,this.fn)}else{jQuery(i).bind(this.type,this.fn)}});delete e.dataEvents}return e}switch(h){case"textarea":g=document.createElement("textarea");if(!r.cols){jQuery(g).css("width","98%")}if(f==" "||f==" "||(f.length==1&&f.charCodeAt(0)==160)){f=""}g.value=f;r=o(g,r);jQuery(g).attr(r);break;case"checkbox":g=document.createElement("input");g.type="checkbox";if(!r.value){var p=f.toLowerCase();if(p.search(/(false|0|no|off|undefined)/i)<0&&p!==""){g.checked=true;g.defaultChecked=true;g.value=f}else{g.value="on"}jQuery(g).attr("offval","off")}else{var a=r.value.split(":");if(f===a[0]){g.checked=true;g.defaultChecked=true}g.value=a[0];jQuery(g).attr("offval",a[1]);try{delete r.value}catch(l){}}r=o(g,r);jQuery(g).attr(r);break;case"select":g=document.createElement("select");var q=r.multiple===true?true:false;if(r.dataUrl!=null){jQuery.get(r.dataUrl,{_nsd:(new Date().getTime())},function(s){try{delete r.dataUrl;delete r.value}catch(t){}var i=jQuery(s).html();jQuery(g).append(i);r=o(g,r);if(typeof r.size==="undefined"){r.size=q?3:1}jQuery(g).attr(r);setTimeout(function(){jQuery("option",g).each(function(e){if(jQuery(this).html()==f){this.selected="selected";return false}})},0)},"html")}else{if(r.value){var j=[],k;if(q){j=f.split(",");j=jQuery.map(j,function(e){return jQuery.trim(e)});if(typeof r.size==="undefined"){r.size=3}}else{r.size=1}if(typeof r.value==="string"){var c=r.value.split(";"),n,d;try{delete r.value}catch(l){}r=o(g,r);jQuery(g).attr(r);for(k=0;k-1){d.selected="selected"}g.appendChild(d)}}else{if(typeof r.value==="object"){var b=r.value;try{delete r.value}catch(l){}r=o(g,r);jQuery(g).attr(r);k=0;for(var m in b){k++;d=document.createElement("option");d.value=m;d.innerHTML=b[m];if(!q&&b[m]==f){d.selected="selected"}if(q&&jQuery.inArray(jQuery.trim(b[m]),j)>-1){d.selected="selected"}g.appendChild(d)}}}}}break;case"text":case"password":case"button":g=document.createElement("input");g.type=h;g.value=jQuery.jgrid.htmlDecode(f);r=o(g,r);if(!r.size){jQuery(g).css({width:"98%"})}jQuery(g).attr(r);break;case"image":case"file":g=document.createElement("input");g.type=h;r=o(g,r);jQuery(g).attr(r);break}return g}function checkValues(c,l,j){var f,h,m;if(typeof(l)=="string"){for(h=0,len=j.p.colModel.length;h=0){var f=j.p.colModel[l].editrules}}if(f){if(!m){m=j.p.colNames[l]}if(f.required===true){if(c.match(/^s+$/)||c==""){return[false,m+": "+jQuery.jgrid.edit.msg.required,""]}}var d=f.required===false?false:true;if(f.number===true){if(!(d===false&&isEmpty(c))){if(isNaN(c)){return[false,m+": "+jQuery.jgrid.edit.msg.number,""]}}}if(typeof f.minValue!="undefined"&&!isNaN(f.minValue)){if(parseFloat(c)parseFloat(f.maxValue)){return[false,m+": "+jQuery.jgrid.edit.msg.maxValue+" "+f.maxValue,""]}}var a;if(f.email===true){if(!(d===false&&isEmpty(c))){a=/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i;if(!a.test(c)){return[false,m+": "+jQuery.jgrid.edit.msg.email,""]}}}if(f.integer===true){if(!(d===false&&isEmpty(c))){if(isNaN(c)){return[false,m+": "+jQuery.jgrid.edit.msg.integer,""]}if((c%1!=0)||(c.indexOf(".")!=-1)){return[false,m+": "+jQuery.jgrid.edit.msg.integer,""]}}}if(f.date===true){if(!(d===false&&isEmpty(c))){var b=j.p.colModel[l].datefmt||"Y-m-d";if(!checkDate(b,c)){return[false,m+": "+jQuery.jgrid.edit.msg.date+" - "+b,""]}}}if(f.url===true){if(!(d===false&&isEmpty(c))){a=/^(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;if(!a.test(c)){return[false,m+": "+jQuery.jgrid.edit.msg.url,""]}}}}return[true,"",""]}function checkDate(l,c){var e={},n;l=l.toLowerCase();if(l.indexOf("/")!=-1){n="/"}else{if(l.indexOf("-")!=-1){n="-"}else{if(l.indexOf(".")!=-1){n="."}else{n="/"}}}l=l.split(n);c=c.split(n);if(c.length!=3){return false}var f=-1,m,g=-1,d=-1;for(var h=0;h12){return false}}if(g===-1){return false}else{k=e[l[g]].toString();if(k.length<1||e[l[g]]<1||e[l[g]]>31||(e[l[d]]==2&&e[l[g]]>daysInFebruary(e[l[f]]))||e[l[g]]>a[e[l[d]]]){return false}}return true}function daysInFebruary(a){return(((a%4==0)&&((!(a%100==0))||(a%400==0)))?29:28)}function DaysArray(b){for(var a=1;a<=b;a++){this[a]=31;if(a==4||a==6||a==9||a==11){this[a]=30}if(a==2){this[a]=29}}return this}function isEmpty(a){if(a.match(/^s+$/)||a==""){return true}else{return false}};(function(b){var a=null;b.fn.extend({searchGrid:function(c){c=b.extend({recreateFilter:false,drag:true,sField:"searchField",sValue:"searchString",sOper:"searchOper",sFilter:"filters",beforeShowSearch:null,afterShowSearch:null,onInitializeSearch:null,closeAfterSearch:false,closeOnEscape:false,multipleSearch:false,sopt:null,onClose:null},b.jgrid.search,c||{});return this.each(function(){var l=this;if(!l.grid){return}if(b.fn.searchFilter){var g="fbox_"+l.p.id;if(c.recreateFilter===true){b("#"+g).remove()}if(b("#"+g).html()!=null){if(b.isFunction(c.beforeShowSearch)){c.beforeShowSearch(b("#"+g))}f();if(b.isFunction(c.afterShowSearch)){c.afterShowSearch(b("#"+g))}}else{var n=[],u=jQuery("#"+l.p.id).getGridParam("colNames"),r=jQuery("#"+l.p.id).getGridParam("colModel"),t=["eq","ne","lt","le","gt","ge","bw","bn","in","ni","ew","en","cn","nc"],i,q,h;b.each(r,function(x,C){var z=(typeof C.search==="undefined")?true:C.search,y=(C.hidden===true),k=b.extend({},{text:u[x],value:C.index||C.name},this.searchoptions),w=(k.searchhidden===true)||true;if(typeof k.sopt=="undefined"){k.sopt=t}h=0;k.ops=[];for(i=0;i0){var p=jQuery.fn.searchFilter.defaults.operators;if(c.sopt!=null){p=[];h=0;for(i=0;c.sopt.length<0;i++){if((q=b.inArray(c.sopt[i],t))!=-1){p[h]={op:c.sopt[i],text:c.odata[q]};h++}}}b("").insertBefore("#gview_"+l.p.id);jQuery("#"+g).searchFilter(n,{groupOps:c.groupOps,operators:p,onClose:d,resetText:c.Reset,searchText:c.Find,windowTitle:c.caption,rulesText:c.rulesText,matchText:c.matchText,onSearch:s,onReset:m,stringResult:c.multipleSearch});b(".ui-widget-overlay","#"+g).remove();if(c.drag===true){b("#"+g+" table thead tr:first td:first").css("cursor","move");if(jQuery.fn.jqDrag){jQuery("#"+g).jqDrag(b("#"+g+" table thead tr:first td:first"))}else{try{b("#"+g).draggable({handle:jQuery("#"+g+" table thead tr:first td:first")})}catch(o){}}}if(c.multipleSearch===false){b(".ui-del, .ui-add, .ui-del, .ui-add-last, .matchText, .rulesText","#"+g).hide();b("select[name='groupOp']","#"+g).hide()}if(b.isFunction(c.onInitializeSearch)){c.onInitializeSearch(b("#"+g))}if(b.isFunction(c.beforeShowSearch)){c.beforeShowSearch(b("#"+g))}f();if(b.isFunction(c.afterShowSearch)){c.afterShowSearch(b("#"+g))}if(c.closeOnEscape===true){jQuery("#"+g).keydown(function(j){if(j.which==27){d(b("#"+g))}})}}}}function s(v){var e=(v!==undefined),k=jQuery("#"+l.p.id),j=[];if(c.multipleSearch===false){j[c.sField]=v.rules[0].field;j[c.sValue]=v.rules[0].data;j[c.sOper]=v.rules[0].op}else{j[c.sFilter]=v}k[0].p.search=e;b.extend(k[0].p.postData,j);k[0].p.page=1;k.trigger("reloadGrid");if(c.closeAfterSearch){d(b("#"+g))}}function m(v){var e=(v!==undefined),k=jQuery("#"+l.p.id),j=[];k[0].p.search=e;if(c.multipleSearch===false){j[c.sField]=j[c.sValue]=j[c.sOper]=""}else{j[c.sFilter]=""}b.extend(k[0].p.postData,j);k[0].p.page=1;k.trigger("reloadGrid")}function d(e){if(c.onClose){var j=c.onClose(e);if(typeof j=="boolean"&&!j){return}}e.hide();b(".jqgrid-overlay","#gbox_"+l.p.id).hide()}function f(){b("#"+g).show();b(".jqgrid-overlay","#gbox_"+l.p.id).show();try{b(":input:visible","#"+g)[0].focus()}catch(e){}}})},editGridRow:function(c,d){d=b.extend({top:0,left:0,width:300,height:"auto",dataheight:"auto",modal:false,drag:true,resize:true,url:null,mtype:"POST",closeAfterAdd:false,closeAfterEdit:false,reloadAfterSubmit:true,onInitializeForm:null,beforeInitData:null,beforeShowForm:null,afterShowForm:null,beforeSubmit:null,afterSubmit:null,onclickSubmit:null,afterComplete:null,onclickPgButtons:null,afterclickPgButtons:null,editData:{},recreateForm:false,jqModal:true,closeOnEscape:false,addedrow:"first",topinfo:"",bottominfo:"",saveicon:[],closeicon:[],savekey:[false,13],navkeys:[false,38,40],checkOnSubmit:false,checkOnUpdate:false,_savedData:{},onClose:null},b.jgrid.edit,d||{});a=d;return this.each(function(){var e=this;if(!e.grid||!c){return}var B=e.p.id,x="FrmGrid_"+B,t="TblGrid_"+B,h={themodal:"editmod"+B,modalhead:"edithd"+B,modalcontent:"editcnt"+B,scrollelm:x},C=b.isFunction(a.beforeShowForm)?a.beforeShowForm:false,N=b.isFunction(a.afterShowForm)?a.afterShowForm:false,M=b.isFunction(a.beforeInitData)?a.beforeInitData:false,n=b.isFunction(a.onInitializeForm)?a.onInitializeForm:false,H=null,I=1,p=0,u,D,E,Q,G,A;if(c=="new"){c="_empty";d.caption=d.addCaption}else{d.caption=d.editCaption}if(d.recreateForm===true&&b("#"+h.themodal).html()!=null){b("#"+h.themodal).remove()}var j=true;if(d.checkOnUpdate&&d.jqModal&&!d.modal){j=false}if(b("#"+h.themodal).html()!=null){b(".ui-jqdialog-title","#"+h.modalhead).html(d.caption);b("#FormError","#"+t).hide();if(M){M(b("#"+x))}m(c,e,x);if(c=="_empty"){b("#pData, #nData","#"+t+"_2").hide()}else{b("#pData, #nData","#"+t+"_2").show()}if(d.processing===true){d.processing=false;b("#sData","#"+t).removeClass("ui-state-active")}if(b("#"+x).data("disabled")===true){b(".confirm","#"+h.themodal).hide();b("#"+x).data("disabled",false)}if(C){C(b("#"+x))}b("#"+h.themodal).data("onClose",a.onClose);viewModal("#"+h.themodal,{gbox:"#gbox_"+B,jqm:d.jqModal,jqM:false,closeoverlay:j,modal:d.modal});if(!j){b(".jqmOverlay").click(function(){if(!f()){return false}hideModal("#"+h.themodal,{gb:"#gbox_"+B,jqm:d.jqModal,onClose:a.onClose});return false})}if(N){N(b("#"+x))}}else{b(e.p.colModel).each(function(V){var W=this.formoptions;I=Math.max(I,W?W.colpos||0:0);p=Math.max(p,W?W.rowpos||0:0)});var q=isNaN(d.dataheight)?d.dataheight:d.dataheight+"px";var L,S=b("
    ").data("disabled",false),z=b("
    ");b(S).append(z);L=b("");L[0].rp=0;b(z).append(L);if(a.topinfo){L=b(""+a.topinfo+"");L[0].rp=0;b(z).append(L)}if(M){M(b("#"+x))}var y=r(c,e,z,I),k="",l="",g=""+d.bSubmit+"",s=""+d.bCancel+"";var P="";if(a.bottominfo){P+=""}P+="
    "+g+" "+s+"
    "+a.bottominfo+"
    ";if(p>0){var w=[];b.each(b(z)[0].rows,function(V,W){w[V]=W});w.sort(function(W,V){if(W.rp>V.rp){return 1}if(W.rp").append(S).append(P);createModal(h,O,d,"#gview_"+e.p.id,b("#gview_"+e.p.id)[0]);O=null;P=null;jQuery("#"+h.themodal).keydown(function(V){if(b("#"+x).data("disabled")===true){return false}if(a.savekey[0]===true&&V.which==a.savekey[1]){b("#sData","#"+t+"_2").trigger("click");return false}if(V.which===27){if(!f()){return false}if(o){hideModal(this,{gb:d.gbox,jqm:d.jqModal,onClose:a.onClose})}return false}if(a.navkeys[0]===true){if(b("#id_g","#"+t).val()=="_empty"){return true}if(V.which==a.navkeys[1]){b("#pData","#"+t+"_2").trigger("click");return false}if(V.which==a.navkeys[2]){b("#nData","#"+t+"_2").trigger("click");return false}}});if(d.checkOnUpdate){b("a.ui-jqdialog-titlebar-close span","#"+h.themodal).removeClass("jqmClose");b("a.ui-jqdialog-titlebar-close","#"+h.themodal).unbind("click").click(function(){if(!f()){return false}hideModal("#"+h.themodal,{gb:"#gbox_"+B,jqm:d.jqModal,onClose:a.onClose});return false})}d.saveicon=b.extend([true,"left","ui-icon-disk"],d.saveicon);d.closeicon=b.extend([true,"left","ui-icon-close"],d.closeicon);if(d.saveicon[0]==true){b("#sData","#"+t+"_2").addClass(d.saveicon[1]=="right"?"fm-button-icon-right":"fm-button-icon-left").append("")}if(d.closeicon[0]==true){b("#cData","#"+t+"_2").addClass(d.closeicon[1]=="right"?"fm-button-icon-right":"fm-button-icon-left").append("")}if(a.checkOnSubmit||a.checkOnUpdate){g=""+d.bYes+"";l=""+d.bNo+"";s=""+d.bExit+"";var F,v=d.zIndex||999;v++;if(b.browser.msie&&b.browser.version==6){F=''}else{F=""}b("
    "+d.saveData+"

    "+g+l+s+"
    ").insertAfter("#"+x);b("#sNew","#"+h.themodal).click(function(){i([true,"",""]);b("#"+x).data("disabled",false);b(".confirm","#"+h.themodal).hide();return false});b("#nNew","#"+h.themodal).click(function(){b(".confirm","#"+h.themodal).hide();b("#"+x).data("disabled",false);setTimeout(function(){b(":input","#"+x)[0].focus()},0);return false});b("#cNew","#"+h.themodal).click(function(){b(".confirm","#"+h.themodal).hide();b("#"+x).data("disabled",false);hideModal("#"+h.themodal,{gb:"#gbox_"+B,jqm:d.jqModal,onClose:a.onClose});return false})}if(n){n(b("#"+x))}if(c=="_empty"){b("#pData,#nData","#"+t+"_2").hide()}else{b("#pData,#nData","#"+t+"_2").show()}if(C){C(b("#"+x))}b("#"+h.themodal).data("onClose",a.onClose);viewModal("#"+h.themodal,{gbox:"#gbox_"+B,jqm:d.jqModal,closeoverlay:j,modal:d.modal});if(!j){b(".jqmOverlay").click(function(){if(!f()){return false}hideModal("#"+h.themodal,{gb:"#gbox_"+B,jqm:d.jqModal,onClose:a.onClose});return false})}if(N){N(b("#"+x))}b(".fm-button","#"+h.themodal).hover(function(){b(this).addClass("ui-state-hover")},function(){b(this).removeClass("ui-state-hover")});b("#sData","#"+t+"_2").click(function(V){D={};Q={};b("#FormError","#"+t).hide();T();if(D.id=="_empty"){i()}else{if(d.checkOnSubmit===true){G=b.extend({},D,Q);A=J(G,a._savedData);if(A){b("#"+x).data("disabled",true);b(".confirm","#"+h.themodal).show()}else{i()}}else{i()}}return false});b("#cData","#"+t+"_2").click(function(V){if(!f()){return false}hideModal("#"+h.themodal,{gb:"#gbox_"+B,jqm:d.jqModal,onClose:a.onClose});return false});b("#nData","#"+t+"_2").click(function(V){if(!f()){return false}b("#FormError","#"+t).hide();var W=U();W[0]=parseInt(W[0]);if(W[0]!=-1&&W[1][W[0]+1]){if(b.isFunction(d.onclickPgButtons)){d.onclickPgButtons("next",b("#"+x),W[1][W[0]])}m(W[1][W[0]+1],e,x);b(e).setSelection(W[1][W[0]+1]);if(b.isFunction(d.afterclickPgButtons)){d.afterclickPgButtons("next",b("#"+x),W[1][W[0]+1])}K(W[0]+1,W[1].length-1)}return false});b("#pData","#"+t+"_2").click(function(W){if(!f()){return false}b("#FormError","#"+t).hide();var V=U();if(V[0]!=-1&&V[1][V[0]-1]){if(b.isFunction(d.onclickPgButtons)){d.onclickPgButtons("prev",b("#"+x),V[1][V[0]])}m(V[1][V[0]-1],e,x);b(e).setSelection(V[1][V[0]-1]);if(b.isFunction(d.afterclickPgButtons)){d.afterclickPgButtons("prev",b("#"+x),V[1][V[0]-1])}K(V[0]-1,V[1].length-1)}return false})}var R=U();K(R[0],R[1].length-1);function K(W,X,V){if(W==0){b("#pData","#"+t+"_2").addClass("ui-state-disabled")}else{b("#pData","#"+t+"_2").removeClass("ui-state-disabled")}if(W==X){b("#nData","#"+t+"_2").addClass("ui-state-disabled")}else{b("#nData","#"+t+"_2").removeClass("ui-state-disabled")}}function U(){var W=b(e).getDataIDs(),V=b("#id_g","#"+t).val(),X=b.inArray(V,W);return[X,W]}function f(){var V=true;b("#FormError","#"+t).hide();if(a.checkOnUpdate){D={};Q={};T();G=b.extend({},D,Q);A=J(G,a._savedData);if(A){b("#"+x).data("disabled",true);b(".confirm","#"+h.themodal).show();V=false}}return V}function T(){b(".FormElement","#"+t).each(function(W){switch(b(this).get(0).type){case"checkbox":if(b(this).attr("checked")){D[this.name]=b(this).val()}else{var V=b(this).attr("offval");D[this.name]=V;Q[this.name]=V}break;case"select-one":D[this.name]=b("option:selected",this).val();Q[this.name]=b("option:selected",this).text();break;case"select-multiple":D[this.name]=b(this).val();if(D[this.name]){D[this.name]=D[this.name].join(",")}else{D[this.name]=""}var X=[];b("option:selected",this).each(function(Y,Z){X[Y]=b(Z).text()});Q[this.name]=X.join(",");break;case"password":case"text":case"textarea":case"button":D[this.name]=b(this).val();D[this.name]=!e.p.autoencode?D[this.name]:b.jgrid.htmlEncode(D[this.name]);break}});return true}function r(Y,ae,ab,aj){var V,W,ag,ah=0,al,am,af,ak=[],ac=false,ad,X,Z="  ",aa="";for(var ai=1;ai<=aj;ai++){aa+=Z}if(Y!="_empty"){ac=b(ae).getInd(Y)}b(ae.p.colModel).each(function(aq){V=this.name;if(this.editrules&&this.editrules.edithidden==true){W=false}else{W=this.hidden===true?true:false}am=W?"style='display:none'":"";if(V!=="cb"&&V!=="subgrid"&&this.editable===true&&V!=="rn"){if(ac===false){al=""}else{if(V==ae.p.ExpandColumn&&ae.p.treeGrid===true){al=b("td:eq("+aq+")",ae.rows[ac]).text()}else{try{al=b.unformat(b("td:eq("+aq+")",ae.rows[ac]),{colModel:this},aq)}catch(ao){al=b("td:eq("+aq+")",ae.rows[ac]).html()}}}var ap=b.extend({},this.editoptions||{},{id:V,name:V});frmopt=b.extend({},{elmprefix:"",elmsuffix:"",rowabove:false,rowcontent:""},this.formoptions||{}),ad=parseInt(frmopt.rowpos)||ah+1,X=parseInt((parseInt(frmopt.colpos)||1)*2);if(Y=="_empty"&&ap.defaultValue){al=b.isFunction(ap.defaultValue)?ap.defaultValue():ap.defaultValue}if(!this.edittype){this.edittype="text"}af=createEl(this.edittype,ap,al);if(al==""&&this.edittype=="checkbox"){al=b(af).attr("offval")}if(a.checkOnSubmit||a.checkOnUpdate){a._savedData[V]=al}b(af).addClass("FormElement");ag=b(ab).find("tr[rowpos="+ad+"]");if(frmopt.rowabove){var ar=b(""+frmopt.rowcontent+"");b(ab).append(ar);ar[0].rp=ad}if(ag.length==0){ag=b("").addClass("FormData").attr("id","tr_"+V);b(ag).append(aa);b(ab).append(ag);ag[0].rp=ad}b("td:eq("+(X-2)+")",ag[0]).html(typeof frmopt.label==="undefined"?ae.p.colNames[aq]:frmopt.label);b("td:eq("+(X-1)+")",ag[0]).append(frmopt.elmprefix).append(af).append(frmopt.elmsuffix);ak[ah]=aq;ah++}});if(ah>0){var an=b("");an[0].rp=ah+999;b(ab).append(an);if(a.checkOnSubmit||a.checkOnUpdate){a._savedData.id=Y}}return ak}function m(W,ab,X){var af,ad,Y=0,ac,aa,V,Z,ae;if(a.checkOnSubmit||a.checkOnUpdate){a._savedData={};a._savedData.id=W}if(W=="_empty"){b(ab.p.colModel).each(function(ag){af=this.name.replace(".","\\.");V=b.extend({},this.editoptions||{});aa=b("#"+af,"#"+X);if(aa[0]!=null){Z="";if(V.defaultValue){Z=b.isFunction(V.defaultValue)?V.defaultValue():V.defaultValue;if(aa[0].type=="checkbox"){ae=Z.toLowerCase();if(ae.search(/(false|0|no|off|undefined)/i)<0&&ae!==""){aa[0].checked=true;aa[0].defaultChecked=true;aa[0].value=Z}else{aa.attr({checked:"",defaultChecked:""})}}else{aa.val(Z)}}else{if(aa[0].type=="checkbox"){aa[0].checked=false;aa[0].defaultChecked=false;Z=b(aa).attr("offval")}else{aa.val(Z)}}if(a.checkOnSubmit===true||a.checkOnUpdate){a._savedData[af]=Z}}});b("#id_g","#"+X).val("_empty");return}b("table:first tr#"+W+" td",ab.grid.bDiv).each(function(ah){af=ab.p.colModel[ah].name.replace(".","\\.");if(ab.p.colModel[ah].editrules&&ab.p.colModel[ah].editrules.edithidden===true){ad=false}else{ad=ab.p.colModel[ah].hidden===true?true:false}if(af!=="cb"&&af!=="subgrid"&&ab.p.colModel[ah].editable===true){if(af==ab.p.ExpandColumn&&ab.p.treeGrid===true){ac=b(this).text()}else{try{ac=b.unformat(this,{colModel:ab.p.colModel[ah]},ah)}catch(ag){ac=b(this).html()}}if(a.checkOnSubmit===true||a.checkOnUpdate){a._savedData[af]=ac}switch(ab.p.colModel[ah].edittype){case"password":case"text":case"button":case"image":ac=b.jgrid.htmlDecode(ac);b("#"+af,"#"+X).val(ac);break;case"textarea":if(ac==" "||ac==" "||(ac.length==1&&ac.charCodeAt(0)==160)){ac=""}b("#"+af,"#"+X).val(ac);break;case"select":ac=b.jgrid.htmlDecode(ac);b("#"+af+" option","#"+X).each(function(ai){if(!ab.p.colModel[ah].editoptions.multiple&&ac==b(this).text()){this.selected=true}else{if(ab.p.colModel[ah].editoptions.multiple){if(b.inArray(b(this).text(),ac.split(","))>-1){this.selected=true}else{this.selected=false}}else{this.selected=false}}});break;case"checkbox":ac=ac.toLowerCase();if(ac.search(/(false|0|no|off|undefined)/i)<0&&ac!==""){b("#"+af,"#"+X).attr("checked",true);b("#"+af,"#"+X).attr("defaultChecked",true)}else{b("#"+af,"#"+X).attr("checked",false);b("#"+af,"#"+X).attr("defaultChecked","")}break}Y++}});if(Y>0){b("#id_g","#"+t).val(W)}return Y}function i(){var Y,W=[true,"",""],V={};for(var X in D){W=checkValues(D[X],X,e);if(W[0]==false){break}}if(W[0]){if(b.isFunction(a.onclickSubmit)){V=a.onclickSubmit(a,D)||{}}if(b.isFunction(a.beforeSubmit)){W=a.beforeSubmit(D,b("#"+x))}}u=a.url?a.url:e.p.editurl;if(W[0]){if(!u){W[0]=false;W[1]+=" "+b.jgrid.errors.nourl}}if(W[0]===false){b("#FormError>td","#"+t).html(W[1]);b("#FormError","#"+t).show();return}if(!d.processing){d.processing=true;b("#sData","#"+t+"_2").addClass("ui-state-active");D.oper=D.id=="_empty"?"add":"edit";D=b.extend(D,a.editData,V);b.ajax({url:u,type:a.mtype,data:D,complete:function(aa,Z){if(Z!="success"){W[0]=false;W[1]=Z+" Status: "+aa.statusText+" Error code: "+aa.status}else{if(b.isFunction(a.afterSubmit)){W=a.afterSubmit(aa,D)}}if(W[0]===false){b("#FormError>td","#"+t).html(W[1]);b("#FormError","#"+t).show()}else{D=b.extend(D,Q);if(D.id=="_empty"){if(!W[2]){W[2]=parseInt(e.p.records)+1}D.id=W[2];if(a.closeAfterAdd){if(a.reloadAfterSubmit){b(e).trigger("reloadGrid")}else{b(e).addRowData(W[2],D,d.addedrow);b(e).setSelection(W[2])}hideModal("#"+h.themodal,{gb:"#gbox_"+B,jqm:d.jqModal,onClose:a.onClose})}else{if(a.clearAfterAdd){if(a.reloadAfterSubmit){b(e).trigger("reloadGrid")}else{b(e).addRowData(W[2],D,d.addedrow)}m("_empty",e,x)}else{if(a.reloadAfterSubmit){b(e).trigger("reloadGrid")}else{b(e).addRowData(W[2],D,d.addedrow)}}}}else{if(a.reloadAfterSubmit){b(e).trigger("reloadGrid");if(!a.closeAfterEdit){b(e).setSelection(D.id)}}else{if(e.p.treeGrid===true){b(e).setTreeRow(D.id,D)}else{b(e).setRowData(D.id,D)}}if(a.closeAfterEdit){hideModal("#"+h.themodal,{gb:"#gbox_"+B,jqm:d.jqModal,onClose:a.onClose})}}if(b.isFunction(a.afterComplete)){Y=aa;setTimeout(function(){a.afterComplete(Y,D,b("#"+x));Y=null},500)}}d.processing=false;if(a.checkOnSubmit||a.checkOnUpdate){b("#"+x).data("disabled",false);if(a._savedData.id!="_empty"){a._savedData=D}}b("#sData","#"+t+"_2").removeClass("ui-state-active");try{b(":input:visible","#"+x)[0].focus()}catch(ab){}},error:function(ab,Z,aa){b("#FormError>td","#"+t).html(Z+" : "+aa);b("#FormError","#"+t).show();d.processing=false;b("#"+x).data("disabled",false);b("#sData","#"+t+"_2").removeClass("ui-state-active")}})}}function J(Y,V){var W=false,X;for(X in Y){if(Y[X]!=V[X]){W=true;break}}return W}})},viewGridRow:function(c,d){d=b.extend({top:0,left:0,width:0,height:"auto",dataheight:"auto",modal:false,drag:true,resize:true,jqModal:true,closeOnEscape:false,labelswidth:"30%",closeicon:[],navkeys:[false,38,40],onClose:null},b.jgrid.view,d||{});return this.each(function(){var w=this;if(!w.grid||!c){return}if(!d.imgpath){d.imgpath=w.p.imgpath}var q=w.p.id,y="ViewGrid_"+q,r="ViewTbl_"+q,i={themodal:"viewmod"+q,modalhead:"viewhd"+q,modalcontent:"viewcnt"+q,scrollelm:y},g=1,e=0;if(b("#"+i.themodal).html()!=null){b(".ui-jqdialog-title","#"+i.modalhead).html(d.caption);b("#FormError","#"+r).hide();l(c,w);viewModal("#"+i.themodal,{gbox:"#gbox_"+q,jqm:d.jqModal,jqM:false,modal:d.modal});j()}else{b(w.p.colModel).each(function(C){var D=this.formoptions;g=Math.max(g,D?D.colpos||0:0);e=Math.max(e,D?D.rowpos||0:0)});var x=isNaN(d.dataheight)?d.dataheight:d.dataheight+"px";var v,A=b("
    "),k=b("
    ");b(A).append(k);var u=m(c,w,k,g),s="",t="",B=""+d.bClose+"";if(e>0){var f=[];b.each(b(k)[0].rows,function(C,D){f[C]=D});f.sort(function(D,C){if(D.rp>C.rp){return 1}if(D.rp").append(A).append("
    "+B+"
    ");createModal(i,z,d,"#gview_"+w.p.id,b("#gview_"+w.p.id)[0]);z=null;jQuery("#"+i.themodal).keydown(function(C){if(C.which===27){if(p){hideModal(this,{gb:d.gbox,jqm:d.jqModal,onClose:d.onClose})}return false}if(d.navkeys[0]===true){if(C.which===d.navkeys[1]){b("#pData","#"+r+"_2").trigger("click");return false}if(C.which===d.navkeys[2]){b("#nData","#"+r+"_2").trigger("click");return false}}});d.closeicon=b.extend([true,"left","ui-icon-close"],d.closeicon);if(d.closeicon[0]==true){b("#cData","#"+r+"_2").addClass(d.closeicon[1]=="right"?"fm-button-icon-right":"fm-button-icon-left").append("")}viewModal("#"+i.themodal,{gbox:"#gbox_"+q,jqm:d.jqModal,modal:d.modal});b(".fm-button:not(.ui-state-disabled)","#"+r+"_2").hover(function(){b(this).addClass("ui-state-hover")},function(){b(this).removeClass("ui-state-hover")});j();b("#cData","#"+r+"_2").click(function(C){hideModal("#"+i.themodal,{gb:"#gbox_"+q,jqm:d.jqModal,onClose:d.onClose});return false});b("#nData","#"+r+"_2").click(function(C){b("#FormError","#"+r).hide();var D=h();D[0]=parseInt(D[0]);if(D[0]!=-1&&D[1][D[0]+1]){if(b.isFunction(d.onclickPgButtons)){d.onclickPgButtons("next",b("#"+y),D[1][D[0]])}l(D[1][D[0]+1],w);b(w).setSelection(D[1][D[0]+1]);if(b.isFunction(d.afterclickPgButtons)){d.afterclickPgButtons("next",b("#"+y),D[1][D[0]+1])}n(D[0]+1,D[1].length-1)}j();return false});b("#pData","#"+r+"_2").click(function(D){b("#FormError","#"+r).hide();var C=h();if(C[0]!=-1&&C[1][C[0]-1]){if(b.isFunction(d.onclickPgButtons)){d.onclickPgButtons("prev",b("#"+y),C[1][C[0]])}l(C[1][C[0]-1],w);b(w).setSelection(C[1][C[0]-1]);if(b.isFunction(d.afterclickPgButtons)){d.afterclickPgButtons("prev",b("#"+y),C[1][C[0]-1])}n(C[0]-1,C[1].length-1)}j();return false})}function j(){if(d.closeOnEscape===true||d.navkeys[0]===true){setTimeout(function(){b(".ui-jqdialog-titlebar-close","#"+i.modalhead).focus()},0)}}var o=h();n(o[0],o[1].length-1);function n(D,E,C){if(D==0){b("#pData","#"+r+"_2").addClass("ui-state-disabled")}else{b("#pData","#"+r+"_2").removeClass("ui-state-disabled")}if(D==E){b("#nData","#"+r+"_2").addClass("ui-state-disabled")}else{b("#nData","#"+r+"_2").removeClass("ui-state-disabled")}}function h(){var D=b(w).getDataIDs(),C=b("#id_g","#"+r).val(),E=b.inArray(C,D);return[E,D]}function m(I,O,M,U){var E,H,P,X,C,S=0,W,Y,V=[],N=false,K="  ",L="",F="  ",J=["integer","number","currency"],R=0,Q=0,G,D;for(var T=1;T<=U;T++){L+=T==1?K:F}b(O.p.colModel).each(function(aa){if(this.editrules&&this.editrules.edithidden===true){H=false}else{H=this.hidden===true?true:false}if(!H&&this.align==="right"){if(this.formatter&&b.inArray(this.formatter,J)!==-1){R=Math.max(R,parseInt(this.width,10))}else{Q=Math.max(Q,parseInt(this.width,10))}}});G=R!==0?R:Q!==0?Q:0;N=b(O).getInd(I);b(O.p.colModel).each(function(ab){E=this.name;D=false;if(this.editrules&&this.editrules.edithidden===true){H=false}else{H=this.hidden===true?true:false}Y=H?"style='display:none'":"";if(E!=="cb"&&E!=="subgrid"&&this.editable===true){if(N===false){W=""}else{if(E==O.p.ExpandColumn&&O.p.treeGrid===true){W=b("td:eq("+ab+")",O.rows[N]).text()}else{W=b("td:eq("+ab+")",O.rows[N]).html()}}D=this.align==="right"&&G!==0?true:false;var aa=b.extend({},this.editoptions||{},{id:E,name:E}),af=b.extend({},{rowabove:false,rowcontent:""},this.formoptions||{}),ac=parseInt(af.rowpos)||S+1,ae=parseInt((parseInt(af.colpos)||1)*2);if(af.rowabove){var ad=b(""+af.rowcontent+"");b(M).append(ad);ad[0].rp=ac}P=b(M).find("tr[rowpos="+ac+"]");if(P.length==0){P=b("").addClass("FormData").attr("id","trv_"+E);b(P).append(L);b(M).append(P);P[0].rp=ac}b("td:eq("+(ae-2)+")",P[0]).html(""+(typeof af.label==="undefined"?O.p.colNames[ab]:af.label)+"");b("td:eq("+(ae-1)+")",P[0]).append(""+W+"").attr("id","v_"+E);if(D){b("td:eq("+(ae-1)+") span",P[0]).css({"text-align":"right",width:G+"px"})}V[S]=ab;S++}});if(S>0){var Z=b("");Z[0].rp=S+99;b(M).append(Z)}return V}function l(G,H){var C,I,F=0,E,D;b("#"+G+" td",H.grid.bDiv).each(function(J){C=H.p.colModel[J].name.replace(".","\\.");if(H.p.colModel[J].editrules&&H.p.colModel[J].editrules.edithidden===true){I=false}else{I=H.p.colModel[J].hidden===true?true:false}if(C!=="cb"&&C!=="subgrid"&&H.p.colModel[J].editable===true){if(C==H.p.ExpandColumn&&H.p.treeGrid===true){E=b(this).text()}else{E=b(this).html()}D=b.extend({},H.p.colModel[J].editoptions||{});C="v_"+C;b("#"+C+" span","#"+r).html(E);if(I){b("#"+C,"#"+r).parents("tr:first").hide()}F++}});if(F>0){b("#id_g","#"+r).val(G)}return F}})},delGridRow:function(c,d){d=b.extend({top:0,left:0,width:240,height:"auto",dataheight:"auto",modal:false,drag:true,resize:true,url:"",mtype:"POST",reloadAfterSubmit:true,beforeShowForm:null,afterShowForm:null,beforeSubmit:null,onclickSubmit:null,afterSubmit:null,jqModal:true,closeOnEscape:false,delData:{},delicon:[],cancelicon:[],onClose:null},b.jgrid.del,d||{});a=d;return this.each(function(){var l=this;if(!l.grid){return}if(!c){return}var m=typeof d.beforeShowForm==="function"?true:false,g=typeof d.afterShowForm==="function"?true:false,e=l.p.id,f={},j="DelTbl_"+e,h={themodal:"delmod"+e,modalhead:"delhd"+e,modalcontent:"delcnt"+e,scrollelm:j};if(isArray(c)){c=c.join()}if(b("#"+h.themodal).html()!=null){b("#DelData>td","#"+j).text(c);b("#DelError","#"+j).hide();if(d.processing===true){d.processing=false;b("#dData","#"+j).removeClass("ui-state-active")}if(m){d.beforeShowForm(b("#"+j))}viewModal("#"+h.themodal,{gbox:"#gbox_"+e,jqm:d.jqModal,jqM:false,modal:d.modal});if(g){d.afterShowForm(b("#"+j))}}else{var n=isNaN(d.dataheight)?d.dataheight:d.dataheight+"px";var k="
    ";k+="";k+="";k+="";k+='";k+="
    '+d.msg+"
     
    ";var i=""+d.bSubmit+"",o=""+d.bCancel+"";k+="
    "+i+" "+o+"
    ";d.gbox="#gbox_"+e;createModal(h,k,d,"#gview_"+l.p.id,b("#gview_"+l.p.id)[0]);b(".fm-button","#"+j+"_2").hover(function(){b(this).addClass("ui-state-hover")},function(){b(this).removeClass("ui-state-hover")});d.delicon=b.extend([true,"left","ui-icon-scissors"],d.delicon);d.cancelicon=b.extend([true,"left","ui-icon-cancel"],d.cancelicon);if(d.delicon[0]==true){b("#dData","#"+j+"_2").addClass(d.delicon[1]=="right"?"fm-button-icon-right":"fm-button-icon-left").append("")}if(d.cancelicon[0]==true){b("#eData","#"+j+"_2").addClass(d.cancelicon[1]=="right"?"fm-button-icon-right":"fm-button-icon-left").append("")}b("#dData","#"+j+"_2").click(function(s){var q=[true,""];f={};var r=b("#DelData>td","#"+j).text();if(typeof d.onclickSubmit==="function"){f=d.onclickSubmit(a)||{}}if(typeof d.beforeSubmit==="function"){q=d.beforeSubmit(r)}var p=a.url?a.url:l.p.editurl;if(!p){q[0]=false;q[1]+=" "+b.jgrid.errors.nourl}if(q[0]===false){b("#DelError>td","#"+j).html(q[1]);b("#DelError","#"+j).show()}else{if(!d.processing){d.processing=true;b(this).addClass("ui-state-active");var t=b.extend({oper:"del",id:r},d.delData,f);b.ajax({url:p,type:d.mtype,data:t,complete:function(x,v){if(v!="success"){q[0]=false;q[1]=v+" Status: "+x.statusText+" Error code: "+x.status}else{if(typeof a.afterSubmit==="function"){q=a.afterSubmit(x,r)}}if(q[0]===false){b("#DelError>td","#"+j).html(q[1]);b("#DelError","#"+j).show()}else{if(a.reloadAfterSubmit){if(l.p.treeGrid){b(l).setGridParam({treeANode:0,datatype:l.p.treedatatype})}b(l).trigger("reloadGrid")}else{var u=[];u=r.split(",");if(l.p.treeGrid===true){try{b(l).delTreeNode(u[0])}catch(y){}}else{for(var w=0;wtd","#"+j).html(u+" : "+v);b("#DelError","#"+j).show();d.processing=false;b("#dData","#"+j+"_2").removeClass("ui-state-active")}})}}return false});b("#eData","#"+j+"_2").click(function(p){hideModal("#"+h.themodal,{gb:"#gbox_"+e,jqm:d.jqModal,onClose:a.onClose});return false});if(m){d.beforeShowForm(b("#"+j))}viewModal("#"+h.themodal,{gbox:"#gbox_"+e,jqm:d.jqModal,modal:d.modal});if(g){d.afterShowForm(b("#"+j))}}if(d.closeOnEscape===true){setTimeout(function(){b(".ui-jqdialog-titlebar-close","#"+h.modalhead).focus()},0)}})},navGrid:function(f,h,e,g,d,c,i){h=b.extend({edit:true,editicon:"ui-icon-pencil",add:true,addicon:"ui-icon-plus",del:true,delicon:"ui-icon-trash",search:true,searchicon:"ui-icon-search",refresh:true,refreshicon:"ui-icon-refresh",refreshstate:"firstpage",view:false,viewicon:"ui-icon-document",position:"left",closeOnEscape:true},b.jgrid.nav,h||{});return this.each(function(){var j={themodal:"alertmod",modalhead:"alerthd",modalcontent:"alertcnt"},n=this,m,s,o,k;if(!n.grid){return}if(b("#"+j.themodal).html()==null){if(typeof window.innerWidth!="undefined"){m=window.innerWidth,s=window.innerHeight}else{if(typeof document.documentElement!="undefined"&&typeof document.documentElement.clientWidth!="undefined"&&document.documentElement.clientWidth!=0){m=document.documentElement.clientWidth,s=document.documentElement.clientHeight}else{m=1024;s=768}}createModal(j,"
    "+h.alerttext+"
    ",{gbox:"#gbox_"+n.p.id,jqModal:true,drag:true,resize:true,caption:h.alertcap,top:s/2-25,left:m/2-100,width:200,height:"auto",closeOnEscape:h.closeOnEscape},"","",true)}var p,q=b(""),r="",l=b(n.p.pager).attr("id")||"pager";if(h.add){g=g||{};p=b("");b(p).append("
    "+h.addtext+"
    ");b("tr",q).append(p);b(p,q).attr({title:h.addtitle||"",id:g.id||"add_"+n.p.id}).click(function(){if(typeof h.addfunc=="function"){h.addfunc()}else{b(n).editGridRow("new",g)}return false}).hover(function(){b(this).addClass("ui-state-hover")},function(){b(this).removeClass("ui-state-hover")});p=null}if(h.edit){p=b("");e=e||{};b(p).append("
    "+h.edittext+"
    ");b("tr",q).append(p);b(p,q).attr({title:h.edittitle||"",id:e.id||"edit_"+n.p.id}).click(function(){var t=n.p.selrow;if(t){if(typeof h.editfunc=="function"){h.editfunc(t)}else{b(n).editGridRow(t,e)}}else{viewModal("#"+j.themodal,{gbox:"#gbox_"+n.p.id,jqm:true});b("#jqg_alrt").focus()}return false}).hover(function(){b(this).addClass("ui-state-hover")},function(){b(this).removeClass("ui-state-hover")});p=null}if(h.view){p=b("");i=i||{};b(p).append("
    "+h.viewtext+"
    ");b("tr",q).append(p);b(p,q).attr({title:h.viewtitle||"",id:i.id||"view_"+n.p.id}).click(function(){var t=n.p.selrow;if(t){b(n).viewGridRow(t,i)}else{viewModal("#"+j.themodal,{gbox:"#gbox_"+n.p.id,jqm:true});b("#jqg_alrt").focus()}return false}).hover(function(){b(this).addClass("ui-state-hover")},function(){b(this).removeClass("ui-state-hover")});p=null}if(h.del){p=b("");d=d||{};b(p).append("
    "+h.deltext+"
    ");b("tr",q).append(p);b(p,q).attr({title:h.deltitle||"",id:d.id||"del_"+n.p.id}).click(function(){var t;if(n.p.multiselect){t=n.p.selarrrow;if(t.length==0){t=null}}else{t=n.p.selrow}if(t){b(n).delGridRow(t,d)}else{viewModal("#"+j.themodal,{gbox:"#gbox_"+n.p.id,jqm:true});b("#jqg_alrt").focus()}return false}).hover(function(){b(this).addClass("ui-state-hover")},function(){b(this).removeClass("ui-state-hover")});p=null}if(h.add||h.edit||h.del||h.view){b("tr",q).append(r)}if(h.search){p=b("");c=c||{};b(p).append("
    "+h.searchtext+"
    ");b("tr",q).append(p);b(p,q).attr({title:h.searchtitle||"",id:c.id||"search_"+n.p.id}).click(function(){b(n).searchGrid(c);return false}).hover(function(){b(this).addClass("ui-state-hover")},function(){b(this).removeClass("ui-state-hover")});p=null}if(h.refresh){p=b("");b(p).append("
    "+h.refreshtext+"
    ");b("tr",q).append(p);b(p,q).attr({title:h.refreshtitle||"",id:"refresh_"+n.p.id}).click(function(){n.p.search=false;try{var u=n.p.id;b("#fbox_"+u).searchFilter().reset()}catch(v){}switch(h.refreshstate){case"firstpage":n.p.page=1;b(n).trigger("reloadGrid");break;case"current":var t=n.p.multiselect===true?n.p.selarrrow:n.p.selrow;b(n).trigger("reloadGrid");setTimeout(function(){if(n.p.multiselect===true){if(t.length>0){for(var w=0;w