Compare commits
468 Commits
statement_
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bda18fc78a | ||
|
|
d903fcb9e3 | ||
|
|
01a6984a53 | ||
|
|
30fdc10648 | ||
|
|
87d6d93493 | ||
|
|
11a9ca903b | ||
|
|
0d59351341 | ||
|
|
13f62edbd7 | ||
|
|
ec0363325c | ||
|
|
e08afdd8b1 | ||
|
|
8249ecc5cd | ||
|
|
f50db1a34b | ||
|
|
f85481c7ec | ||
|
|
75c635a5ea | ||
|
|
4cc81c2ebc | ||
|
|
20df22a002 | ||
|
|
49a379d799 | ||
|
|
98d9849914 | ||
|
|
20284046c3 | ||
|
|
99a98cbc7d | ||
|
|
fc9226594c | ||
|
|
352bdbbf49 | ||
|
|
11fbdf0701 | ||
|
|
2519f4c8a7 | ||
|
|
b6ed57c02c | ||
|
|
4dffa540a0 | ||
|
|
3d1c4d2492 | ||
|
|
c4f6f76edb | ||
|
|
d95045cb15 | ||
|
|
0c95431128 | ||
|
|
c76ba261d8 | ||
|
|
954f0d7968 | ||
|
|
920dba3a4d | ||
|
|
fff2e84fb1 | ||
|
|
11aacd5803 | ||
|
|
34844760e8 | ||
|
|
b1113e826f | ||
|
|
112a128492 | ||
|
|
d96145530c | ||
|
|
a602fce3ab | ||
|
|
6849c2caae | ||
|
|
b83c870eed | ||
|
|
11b54588ff | ||
|
|
214aa4d348 | ||
|
|
f281295084 | ||
|
|
68cbca5e28 | ||
|
|
4892143c0c | ||
|
|
1be8df7a75 | ||
|
|
285c682b1e | ||
|
|
3acdec1458 | ||
|
|
e0b41ca4f7 | ||
|
|
780c614c78 | ||
|
|
f49a23b2fd | ||
|
|
07461f4419 | ||
|
|
48631cffee | ||
|
|
68e6dc2d20 | ||
|
|
2f2a4642fb | ||
|
|
2602a6fa7c | ||
|
|
2489b67542 | ||
|
|
821ffc4726 | ||
|
|
7770f13bf3 | ||
|
|
0a594bb5a9 | ||
|
|
b3d43d754b | ||
|
|
a47d5d54b4 | ||
|
|
b6e2b781ef | ||
|
|
8f5c3031fc | ||
|
|
f01e62fc6e | ||
|
|
9952673655 | ||
|
|
ccd1af6154 | ||
|
|
ce633d816a | ||
|
|
83bfb8d32d | ||
|
|
28817cea38 | ||
|
|
3dca204ac6 | ||
|
|
2fb2e6f5aa | ||
|
|
44def81c81 | ||
|
|
03da3afb98 | ||
|
|
3b885e2686 | ||
|
|
e162d35d56 | ||
|
|
3b3ed7a264 | ||
|
|
3b5aa78a47 | ||
|
|
721faa129b | ||
|
|
78806de606 | ||
|
|
d4ea5eea1f | ||
|
|
9213c1c21d | ||
|
|
9674812e78 | ||
|
|
8bda7c2cb0 | ||
|
|
375d63485c | ||
|
|
26045a3db7 | ||
|
|
04ac012754 | ||
|
|
e6f662f0a1 | ||
|
|
04b3c06cda | ||
|
|
24da6d75b5 | ||
|
|
542ae17afd | ||
|
|
97fffaa610 | ||
|
|
3eb5139b62 | ||
|
|
5245393a04 | ||
|
|
e59df1dffb | ||
|
|
61da97974b | ||
|
|
6482cfd4cc | ||
|
|
c3e51a7a6b | ||
|
|
de069ef186 | ||
|
|
5047abba6a | ||
|
|
4e8426fd79 | ||
|
|
6630cdfcd6 | ||
|
|
48d332f40f | ||
|
|
3ede96dad9 | ||
|
|
3e3dff31a8 | ||
|
|
3642724b5e | ||
|
|
0ad68f4d6a | ||
|
|
2628edfbdd | ||
|
|
740bcbedc0 | ||
|
|
2f3046294d | ||
|
|
7a2034aea0 | ||
|
|
bb4046e1da | ||
|
|
f717713842 | ||
|
|
5008452089 | ||
|
|
68a1397ad6 | ||
|
|
ef64644536 | ||
|
|
72ea84ad88 | ||
|
|
0f3aa42f57 | ||
|
|
fb23b7ffaa | ||
|
|
b731ee6165 | ||
|
|
34dcbd8b43 | ||
|
|
87a2ea5cd6 | ||
|
|
6492cd8b22 | ||
|
|
f6a18cbb6c | ||
|
|
7198d7e6f4 | ||
|
|
d79077e279 | ||
|
|
cea9332ac6 | ||
|
|
bf8aaea041 | ||
|
|
63704682fa | ||
|
|
63de5641a0 | ||
|
|
5f6a9ed53f | ||
|
|
328d0f8f51 | ||
|
|
aee6832374 | ||
|
|
63e22ec9bf | ||
|
|
fde8923814 | ||
|
|
696017a82a | ||
|
|
7bcee943a5 | ||
|
|
0c9b945f7b | ||
|
|
5b5707df5e | ||
|
|
c21cdcd9a2 | ||
|
|
a79adbce2d | ||
|
|
a3b376544c | ||
|
|
43c957baa2 | ||
|
|
a66024c889 | ||
|
|
aed090fbe2 | ||
|
|
7904372dff | ||
|
|
1d4dcbd2b0 | ||
|
|
f5f09421c1 | ||
|
|
4d525f6ac9 | ||
|
|
0b773cfc35 | ||
|
|
387e08da06 | ||
|
|
5ef877f64b | ||
|
|
c889e4f4e1 | ||
|
|
b938b5f028 | ||
|
|
1e34cc1de8 | ||
|
|
80fe5ca4de | ||
|
|
fbd716634a | ||
|
|
046cf5fe63 | ||
|
|
2fd2dc603c | ||
|
|
439e9a3de6 | ||
|
|
caee1c90a1 | ||
|
|
08486fc101 | ||
|
|
0758865aae | ||
|
|
85b189a50e | ||
|
|
3ff5967415 | ||
|
|
b2a85a5197 | ||
|
|
f8cdea8872 | ||
|
|
c3ad1b0ea1 | ||
|
|
56bec8d05c | ||
|
|
b89750a4ef | ||
|
|
20309fba39 | ||
|
|
241028603b | ||
|
|
8663c25806 | ||
|
|
03d947a069 | ||
|
|
294aabbb29 | ||
|
|
94188e3f92 | ||
|
|
c261735197 | ||
|
|
63c95da9f3 | ||
|
|
ae1dccfb14 | ||
|
|
9bc699bf51 | ||
|
|
7a1aa536fa | ||
|
|
de9a4acd5d | ||
|
|
bd4610abb3 | ||
|
|
60ec105fca | ||
|
|
67a0c07bc6 | ||
|
|
fc332bef0e | ||
|
|
92668bcca1 | ||
|
|
73eeba04fe | ||
|
|
a1bab966ed | ||
|
|
ee9ff354b2 | ||
|
|
a9410b1351 | ||
|
|
5ad28c809b | ||
|
|
89d7f22e4a | ||
|
|
11be0ff9cb | ||
|
|
65c3f28484 | ||
|
|
4e1ffd14b4 | ||
|
|
2d3b962fe1 | ||
|
|
1d921358a8 | ||
|
|
9a819c72a8 | ||
|
|
24e208bf17 | ||
|
|
86b0c14eda | ||
|
|
da88975fed | ||
|
|
f545502162 | ||
|
|
513182a6d5 | ||
|
|
7b76fd8f0a | ||
|
|
63bb788fdf | ||
|
|
d8760cf2b6 | ||
|
|
feb15cac49 | ||
|
|
40047d89d8 | ||
|
|
94cc553723 | ||
|
|
166a4f44d9 | ||
|
|
633a019fc5 | ||
|
|
bddcca8d9e | ||
|
|
6e6f7f4f43 | ||
|
|
64ce95e404 | ||
|
|
55bcdca935 | ||
|
|
6f035c2052 | ||
|
|
538c8077d2 | ||
|
|
e37e40f355 | ||
|
|
9fca2e7d4f | ||
|
|
5c7df5f2eb | ||
|
|
e0e7fcfc51 | ||
|
|
8ce654d22d | ||
|
|
6cd45236d9 | ||
|
|
009503bf7b | ||
|
|
4f652eb9a1 | ||
|
|
0b9061794e | ||
|
|
1055a00476 | ||
|
|
4f758b5480 | ||
|
|
ec2ea2a60e | ||
|
|
196a7ae6e6 | ||
|
|
24ad1ef49c | ||
|
|
019b59fdbc | ||
|
|
8892583db4 | ||
|
|
ab840075c2 | ||
|
|
10fe7bf230 | ||
|
|
5bcd424055 | ||
|
|
7cb0381060 | ||
|
|
935920a38a | ||
|
|
df3bbb698e | ||
|
|
a2c1779454 | ||
|
|
7a50d02a44 | ||
|
|
22edc5a524 | ||
|
|
bc33f3cb2c | ||
|
|
e3a606ebf0 | ||
|
|
8e91eadf53 | ||
|
|
7e665af8be | ||
|
|
2727812144 | ||
|
|
dd7135df49 | ||
|
|
0297266a34 | ||
|
|
3b1e06bade | ||
|
|
ce54ed2341 | ||
|
|
b4097850dd | ||
|
|
ac23a1be18 | ||
|
|
88d468d20c | ||
|
|
bb9ce64657 | ||
|
|
77a01a16c4 | ||
|
|
d26b6e99bd | ||
|
|
3096759738 | ||
|
|
011481be2d | ||
|
|
21e11298eb | ||
|
|
8b93f6ad91 | ||
|
|
9b9c6d8f29 | ||
|
|
44cda10211 | ||
|
|
0a62c8a816 | ||
|
|
c23d4c6209 | ||
|
|
9923ccc6c3 | ||
|
|
c4d4c3c989 | ||
|
|
b94c8e56b4 | ||
|
|
bde335f68c | ||
|
|
515046efd6 | ||
|
|
8c334f236d | ||
|
|
18848db6b1 | ||
|
|
e4d20cc849 | ||
|
|
355af40ed5 | ||
|
|
9f1a6b8087 | ||
|
|
77de94df54 | ||
|
|
00a306355a | ||
|
|
f7c2493f99 | ||
|
|
2bc2fb951b | ||
|
|
cc86bb99c1 | ||
|
|
eebb7c7c94 | ||
|
|
88a1a62087 | ||
|
|
29c157475b | ||
|
|
237e744002 | ||
|
|
6c38b08700 | ||
|
|
29bb08adca | ||
|
|
ca69698693 | ||
|
|
9274bb9b0c | ||
|
|
32ea8734e1 | ||
|
|
5bb240708f | ||
|
|
3e366d3dad | ||
|
|
0de2931f66 | ||
|
|
966dc495e2 | ||
|
|
df869ef70a | ||
|
|
8dcf5956fe | ||
|
|
654e79803f | ||
|
|
dcbff5a956 | ||
|
|
b1fb5e29db | ||
|
|
a6c3b612ba | ||
|
|
ee9ae2079c | ||
|
|
58495d5607 | ||
|
|
ebcc494e36 | ||
|
|
835853c51c | ||
|
|
622eca3f1a | ||
|
|
65b132ac8e | ||
|
|
410e588e97 | ||
|
|
9aba878ee6 | ||
|
|
bd90424080 | ||
|
|
a939b0839b | ||
|
|
2d8c536f33 | ||
|
|
2d51340a56 | ||
|
|
98c4a66f2f | ||
|
|
29b829d3af | ||
|
|
d0aa3799fa | ||
|
|
5e78d32ec4 | ||
|
|
a76421c858 | ||
|
|
28086651e5 | ||
|
|
da80c3623e | ||
|
|
309512dde0 | ||
|
|
8b1d3c9830 | ||
|
|
31265104e1 | ||
|
|
c719d11df2 | ||
|
|
e6d65a5212 | ||
|
|
e21233954a | ||
|
|
d36cfd9653 | ||
|
|
d141f61055 | ||
|
|
4b8dc3da02 | ||
|
|
709689b15b | ||
|
|
3eb989e03c | ||
|
|
eb019dd9e5 | ||
|
|
719373e534 | ||
|
|
1c5d97f06d | ||
|
|
589168440c | ||
|
|
73c5a20158 | ||
|
|
a44654ec01 | ||
|
|
7a331d5f4f | ||
|
|
daf9fe9391 | ||
|
|
d8767cfb73 | ||
|
|
64792e6fe2 | ||
|
|
424276eeb4 | ||
|
|
377a4cc88c | ||
|
|
170f660528 | ||
|
|
90ecbda541 | ||
|
|
4afe0bd77b | ||
|
|
8440a7c833 | ||
|
|
00d509f23d | ||
|
|
080c82fc10 | ||
|
|
1b02be19f0 | ||
|
|
366d59a5e6 | ||
|
|
2634cf824a | ||
|
|
1429fe720b | ||
|
|
754cdb8522 | ||
|
|
a1a68f3209 | ||
|
|
8843d24baa | ||
|
|
892618db36 | ||
|
|
3decfff33b | ||
|
|
945221d565 | ||
|
|
a968d7abe6 | ||
|
|
8b6b8884f7 | ||
|
|
14805190fc | ||
|
|
a1bdecfcaa | ||
|
|
4896834a96 | ||
|
|
a9c3c40053 | ||
|
|
4125d7ba16 | ||
|
|
26d9b1bc38 | ||
|
|
f30e536e47 | ||
|
|
96a030e340 | ||
|
|
460e9a2e64 | ||
|
|
6e63365604 | ||
|
|
4f85dc243e | ||
|
|
30f755cf42 | ||
|
|
170ba466de | ||
|
|
d2d1bb3fc4 | ||
|
|
d024d333d2 | ||
|
|
778bb43895 | ||
|
|
41321481c7 | ||
|
|
fe9f6ce949 | ||
|
|
f81bfdecc2 | ||
|
|
8dd6fc957d | ||
|
|
d92acf12de | ||
|
|
43d1d2ccf5 | ||
|
|
c06399cf86 | ||
|
|
d1187f9bdd | ||
|
|
b7a77757f9 | ||
|
|
5f199d97fe | ||
|
|
fc292e3366 | ||
|
|
94e300a129 | ||
|
|
791b2d8ab1 | ||
|
|
091920d80a | ||
|
|
1511986ed0 | ||
|
|
1e88e1fce2 | ||
|
|
a2014a916e | ||
|
|
bd52030984 | ||
|
|
f23726783e | ||
|
|
1d27b4dcb5 | ||
|
|
e74f8987d9 | ||
|
|
9c55a047a8 | ||
|
|
6f2038f7b0 | ||
|
|
ec22f4b003 | ||
|
|
70629e360b | ||
|
|
fc4e812d67 | ||
|
|
b6ee958c35 | ||
|
|
f82df229f2 | ||
|
|
96c499786c | ||
|
|
52e0181bfb | ||
|
|
b65c5c1dbf | ||
|
|
cbdce4f166 | ||
|
|
e9b9bdc420 | ||
|
|
704412727d | ||
|
|
72af3f3247 | ||
|
|
f0693bdc05 | ||
|
|
15f885ab8a | ||
|
|
b1a7f41934 | ||
|
|
4f11e27a76 | ||
|
|
f8aef6e794 | ||
|
|
e100c9a88f | ||
|
|
1ce71a3936 | ||
|
|
19f8c18ce9 | ||
|
|
eb28852b87 | ||
|
|
98f3dd7688 | ||
|
|
c33a823e50 | ||
|
|
1f97e8db35 | ||
|
|
76df8c924f | ||
|
|
598ce5784b | ||
|
|
cdb7d4b15c | ||
|
|
07a2be05f7 | ||
|
|
fd1a1f43d4 | ||
|
|
2e2147b238 | ||
|
|
a0c00f1a35 | ||
|
|
868e23b982 | ||
|
|
e6b0313523 | ||
|
|
654eb0960e | ||
|
|
2e36d46329 | ||
|
|
1dd0b14861 | ||
|
|
d75cd10f49 | ||
|
|
a69a56c715 | ||
|
|
8f7cf202e5 | ||
|
|
58c4f28956 | ||
|
|
f3eaa40ea5 | ||
|
|
e784931fa8 | ||
|
|
5a7b087ddc | ||
|
|
4d62d7da73 | ||
|
|
cca698d437 | ||
|
|
5247bb8db6 | ||
|
|
cb969ba340 | ||
|
|
094e15ddf9 | ||
|
|
670f0894ea | ||
|
|
9e20473b3b | ||
|
|
11d5deac85 | ||
|
|
67280c89e7 | ||
|
|
1afed6a6e0 | ||
|
|
0ff91bf4d8 | ||
|
|
4d4e96fe1c | ||
|
|
32a98b4b6e | ||
|
|
817b74b085 | ||
|
|
dc1bb56188 | ||
|
|
4707f3314d | ||
|
|
ac2b1530fc | ||
|
|
a5d3ff0b70 | ||
|
|
adc87c0763 | ||
|
|
7d81b9766b | ||
|
|
1aa6273ade | ||
|
|
2c08405d5a | ||
|
|
e2ed6ed1c7 | ||
|
|
562ffc9e4b |
@@ -1,3 +0,0 @@
|
|||||||
@echo off
|
|
||||||
%~dp0\scripts\sitelink2pmgr.pl %~dp0\db\schema.sql %~dp0db\vss.mdb %*
|
|
||||||
echo Done!
|
|
||||||
475
db/schema.sql
475
db/schema.sql
@@ -25,9 +25,9 @@
|
|||||||
-- REVISIT <AP>: 20090511
|
-- REVISIT <AP>: 20090511
|
||||||
-- By not specifying the database, the script can
|
-- By not specifying the database, the script can
|
||||||
-- make the determination of which one to use.
|
-- make the determination of which one to use.
|
||||||
-- DROP DATABASE IF EXISTS `property_manager`;
|
DROP DATABASE IF EXISTS `property_manager`;
|
||||||
-- CREATE DATABASE `property_manager`;
|
CREATE DATABASE `property_manager`;
|
||||||
-- USE `property_manager`;
|
USE `property_manager`;
|
||||||
|
|
||||||
|
|
||||||
-- ######################################################################
|
-- ######################################################################
|
||||||
@@ -241,7 +241,7 @@ CREATE TABLE `pmgr_contacts_methods` (
|
|||||||
-- ######################################################################
|
-- ######################################################################
|
||||||
-- ######################################################################
|
-- ######################################################################
|
||||||
-- ##
|
-- ##
|
||||||
-- ## GROUPS
|
-- ## GROUPS / USERS
|
||||||
-- ##
|
-- ##
|
||||||
|
|
||||||
|
|
||||||
@@ -256,59 +256,15 @@ CREATE TABLE `pmgr_groups` (
|
|||||||
-- code may not be userful
|
-- code may not be userful
|
||||||
`code` VARCHAR(12) NOT NULL, -- User style "id"
|
`code` VARCHAR(12) NOT NULL, -- User style "id"
|
||||||
`name` VARCHAR(80) NOT NULL,
|
`name` VARCHAR(80) NOT NULL,
|
||||||
|
|
||||||
|
-- Lower ranks are given higher priority
|
||||||
|
`rank` SMALLINT UNSIGNED NOT NULL DEFAULT 100,
|
||||||
`comment` VARCHAR(255) DEFAULT NULL,
|
`comment` VARCHAR(255) DEFAULT NULL,
|
||||||
|
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
-- ----------------------------------------------------------------------
|
|
||||||
-- ----------------------------------------------------------------------
|
|
||||||
-- TABLE pmgr_group_options
|
|
||||||
|
|
||||||
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,
|
|
||||||
`comment` VARCHAR(255) DEFAULT NULL,
|
|
||||||
|
|
||||||
PRIMARY KEY (`group_id`, `name`)
|
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
|
|
||||||
-- ----------------------------------------------------------------------
|
|
||||||
-- ----------------------------------------------------------------------
|
|
||||||
-- TABLE pmgr_group_permissions
|
|
||||||
|
|
||||||
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',
|
|
||||||
'DENIED',
|
|
||||||
'FORCED')
|
|
||||||
NOT NULL DEFAULT 'ALLOWED',
|
|
||||||
`comment` VARCHAR(255) DEFAULT NULL,
|
|
||||||
|
|
||||||
PRIMARY KEY (`group_id`, `name`)
|
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- ######################################################################
|
|
||||||
-- ######################################################################
|
|
||||||
-- ######################################################################
|
|
||||||
-- ######################################################################
|
|
||||||
-- ######################################################################
|
|
||||||
-- ######################################################################
|
|
||||||
-- ######################################################################
|
|
||||||
-- ######################################################################
|
|
||||||
-- ######################################################################
|
|
||||||
-- ##
|
|
||||||
-- ## USERS
|
|
||||||
-- ##
|
|
||||||
|
|
||||||
|
|
||||||
-- ----------------------------------------------------------------------
|
-- ----------------------------------------------------------------------
|
||||||
-- ----------------------------------------------------------------------
|
-- ----------------------------------------------------------------------
|
||||||
@@ -318,14 +274,10 @@ DROP TABLE IF EXISTS `pmgr_users`;
|
|||||||
CREATE TABLE `pmgr_users` (
|
CREATE TABLE `pmgr_users` (
|
||||||
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
`code` VARCHAR(12) NOT NULL, -- User style "id"
|
`code` VARCHAR(12) NOT NULL, -- User style "id"
|
||||||
|
`login` VARCHAR(30) NOT NULL,
|
||||||
-- 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 information for this user
|
||||||
`contact_id` INT(10) UNSIGNED NOT NULL,
|
`contact_id` INT(10) UNSIGNED DEFAULT NULL,
|
||||||
|
|
||||||
-- Specific comments
|
-- Specific comments
|
||||||
`comment` VARCHAR(255) DEFAULT NULL,
|
`comment` VARCHAR(255) DEFAULT NULL,
|
||||||
@@ -334,18 +286,208 @@ CREATE TABLE `pmgr_users` (
|
|||||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ##
|
||||||
|
-- ## OPTIONS
|
||||||
|
-- ##
|
||||||
|
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- TABLE pmgr_options
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `pmgr_options`;
|
||||||
|
CREATE TABLE `pmgr_options` (
|
||||||
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` VARCHAR(50) NOT NULL,
|
||||||
|
`comment` VARCHAR(255) DEFAULT NULL,
|
||||||
|
UNIQUE KEY `name_key` (`name`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- TABLE pmgr_option_values
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `pmgr_option_values`;
|
||||||
|
CREATE TABLE `pmgr_option_values` (
|
||||||
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`option_id` INT(10) UNSIGNED NOT NULL,
|
||||||
|
`value` VARCHAR(255) NOT NULL,
|
||||||
|
`comment` VARCHAR(255) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- TABLE pmgr_default_options
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `pmgr_default_options`;
|
||||||
|
CREATE TABLE `pmgr_default_options` (
|
||||||
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`option_value_id` INT(10) UNSIGNED NOT NULL,
|
||||||
|
`comment` VARCHAR(255) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- TABLE pmgr_group_options
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `pmgr_group_options`;
|
||||||
|
CREATE TABLE `pmgr_group_options` (
|
||||||
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`group_id` INT(10) UNSIGNED NOT NULL,
|
||||||
|
`option_value_id` INT(10) UNSIGNED NOT NULL,
|
||||||
|
`comment` VARCHAR(255) DEFAULT NULL,
|
||||||
|
KEY `group_key` (`group_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
-- ----------------------------------------------------------------------
|
-- ----------------------------------------------------------------------
|
||||||
-- ----------------------------------------------------------------------
|
-- ----------------------------------------------------------------------
|
||||||
-- TABLE pmgr_user_options
|
-- TABLE pmgr_user_options
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `pmgr_user_options`;
|
DROP TABLE IF EXISTS `pmgr_user_options`;
|
||||||
CREATE TABLE `pmgr_user_options` (
|
CREATE TABLE `pmgr_user_options` (
|
||||||
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
`user_id` INT(10) UNSIGNED NOT NULL,
|
`user_id` INT(10) UNSIGNED NOT NULL,
|
||||||
`name` VARCHAR(50) NOT NULL,
|
`option_value_id` INT(10) UNSIGNED NOT NULL,
|
||||||
`value` VARCHAR(255) NOT NULL,
|
|
||||||
`comment` VARCHAR(255) DEFAULT NULL,
|
`comment` VARCHAR(255) DEFAULT NULL,
|
||||||
|
KEY `user_key` (`user_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
PRIMARY KEY (`user_id`, `name`)
|
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- TABLE pmgr_site_options
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `pmgr_site_options`;
|
||||||
|
CREATE TABLE `pmgr_site_options` (
|
||||||
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`site_id` INT(10) UNSIGNED NOT NULL,
|
||||||
|
`option_value_id` INT(10) UNSIGNED NOT NULL,
|
||||||
|
`comment` VARCHAR(255) DEFAULT NULL,
|
||||||
|
KEY `site_key` (`site_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ##
|
||||||
|
-- ## PERMISSIONS
|
||||||
|
-- ##
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- TABLE pmgr_permissions
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `pmgr_permissions`;
|
||||||
|
CREATE TABLE `pmgr_permissions` (
|
||||||
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` VARCHAR(50) NOT NULL,
|
||||||
|
`comment` VARCHAR(255) DEFAULT NULL,
|
||||||
|
UNIQUE KEY `name_key` (`name`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- TABLE pmgr_permission_values
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `pmgr_permission_values`;
|
||||||
|
CREATE TABLE `pmgr_permission_values` (
|
||||||
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`permission_id` INT(10) UNSIGNED NOT NULL,
|
||||||
|
`access` ENUM('ALLOW',
|
||||||
|
'DENY')
|
||||||
|
NOT NULL DEFAULT 'DENY',
|
||||||
|
`level` SMALLINT UNSIGNED DEFAULT NULL,
|
||||||
|
`comment` VARCHAR(255) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- TABLE pmgr_default_permissions
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `pmgr_default_permissions`;
|
||||||
|
CREATE TABLE `pmgr_default_permissions` (
|
||||||
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`permission_value_id` INT(10) UNSIGNED NOT NULL,
|
||||||
|
`comment` VARCHAR(255) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- TABLE pmgr_group_permissions
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `pmgr_group_permissions`;
|
||||||
|
CREATE TABLE `pmgr_group_permissions` (
|
||||||
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`group_id` INT(10) UNSIGNED NOT NULL,
|
||||||
|
`permission_value_id` INT(10) UNSIGNED NOT NULL,
|
||||||
|
`comment` VARCHAR(255) DEFAULT NULL,
|
||||||
|
KEY `group_key` (`group_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- TABLE pmgr_user_permissions
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `pmgr_user_permissions`;
|
||||||
|
CREATE TABLE `pmgr_user_permissions` (
|
||||||
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`user_id` INT(10) UNSIGNED NOT NULL,
|
||||||
|
`permission_value_id` INT(10) UNSIGNED NOT NULL,
|
||||||
|
`comment` VARCHAR(255) DEFAULT NULL,
|
||||||
|
KEY `user_key` (`user_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- TABLE pmgr_site_permissions
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `pmgr_site_permissions`;
|
||||||
|
CREATE TABLE `pmgr_site_permissions` (
|
||||||
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
`site_id` INT(10) UNSIGNED NOT NULL,
|
||||||
|
`permission_value_id` INT(10) UNSIGNED NOT NULL,
|
||||||
|
`comment` VARCHAR(255) DEFAULT NULL,
|
||||||
|
KEY `site_key` (`site_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
@@ -380,46 +522,6 @@ CREATE TABLE `pmgr_sites` (
|
|||||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
|
||||||
-- ----------------------------------------------------------------------
|
|
||||||
-- ----------------------------------------------------------------------
|
|
||||||
-- TABLE pmgr_site_options
|
|
||||||
|
|
||||||
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,
|
|
||||||
`comment` VARCHAR(255) DEFAULT NULL,
|
|
||||||
|
|
||||||
PRIMARY KEY (`site_id`, `name`)
|
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
|
|
||||||
-- ----------------------------------------------------------------------
|
|
||||||
-- ----------------------------------------------------------------------
|
|
||||||
-- 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 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 `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,
|
|
||||||
`comment` VARCHAR(255) DEFAULT NULL,
|
|
||||||
|
|
||||||
PRIMARY KEY (`site_id`, `user_id`, `group_id`)
|
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
|
|
||||||
-- ----------------------------------------------------------------------
|
-- ----------------------------------------------------------------------
|
||||||
-- ----------------------------------------------------------------------
|
-- ----------------------------------------------------------------------
|
||||||
-- TABLE pmgr_site_areas
|
-- TABLE pmgr_site_areas
|
||||||
@@ -437,6 +539,38 @@ CREATE TABLE `pmgr_site_areas` (
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ######################################################################
|
||||||
|
-- ##
|
||||||
|
-- ## MEMBERSHIPS
|
||||||
|
-- ##
|
||||||
|
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- ----------------------------------------------------------------------
|
||||||
|
-- TABLE pmgr_memberships
|
||||||
|
--
|
||||||
|
-- Which users are allowed to access which sites,
|
||||||
|
-- and under which set of group permissions (possibly multiple)
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `pmgr_memberships`;
|
||||||
|
CREATE TABLE `pmgr_memberships` (
|
||||||
|
`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;
|
||||||
|
|
||||||
|
|
||||||
-- ######################################################################
|
-- ######################################################################
|
||||||
-- ######################################################################
|
-- ######################################################################
|
||||||
-- ######################################################################
|
-- ######################################################################
|
||||||
@@ -471,13 +605,10 @@ CREATE TABLE `pmgr_units` (
|
|||||||
'DIRTY',
|
'DIRTY',
|
||||||
'VACANT',
|
'VACANT',
|
||||||
'OCCUPIED',
|
'OCCUPIED',
|
||||||
'LATE', -- NOT SURE
|
|
||||||
'LOCKED',
|
'LOCKED',
|
||||||
'LIENED')
|
'LIENED')
|
||||||
NOT NULL DEFAULT 'VACANT',
|
NOT NULL DEFAULT 'VACANT',
|
||||||
|
|
||||||
`current_lease_id` INT(10) UNSIGNED DEFAULT NULL,
|
|
||||||
|
|
||||||
`sort_order` MEDIUMINT UNSIGNED NOT NULL,
|
`sort_order` MEDIUMINT UNSIGNED NOT NULL,
|
||||||
`walk_order` MEDIUMINT UNSIGNED NOT NULL,
|
`walk_order` MEDIUMINT UNSIGNED NOT NULL,
|
||||||
|
|
||||||
@@ -644,6 +775,17 @@ CREATE TABLE `pmgr_customers` (
|
|||||||
-- contacts_customers table?
|
-- contacts_customers table?
|
||||||
`primary_contact_id` INT(10) UNSIGNED NOT NULL,
|
`primary_contact_id` INT(10) UNSIGNED NOT NULL,
|
||||||
|
|
||||||
|
-- Number of different leases for this customer.
|
||||||
|
-- It's not good to have redundant information,
|
||||||
|
-- but these fields change infrequently, and make
|
||||||
|
-- certain queries much easier, most notably for
|
||||||
|
-- the grid query, in which linking customer to
|
||||||
|
-- lease results in repeated statement entries
|
||||||
|
-- when a customer has more than one lease.
|
||||||
|
`lease_count` SMALLINT UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
`current_lease_count` SMALLINT UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
`past_lease_count` SMALLINT UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
|
||||||
`comment` VARCHAR(255) DEFAULT NULL,
|
`comment` VARCHAR(255) DEFAULT NULL,
|
||||||
|
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
@@ -714,6 +856,9 @@ CREATE TABLE `pmgr_leases` (
|
|||||||
`notice_received_date` DATE DEFAULT NULL,
|
`notice_received_date` DATE DEFAULT NULL,
|
||||||
`close_date` DATE DEFAULT NULL,
|
`close_date` DATE DEFAULT NULL,
|
||||||
|
|
||||||
|
`charge_through_date` DATE DEFAULT NULL,
|
||||||
|
`paid_through_date` DATE DEFAULT NULL,
|
||||||
|
|
||||||
`deposit` FLOAT(12,2) DEFAULT NULL,
|
`deposit` FLOAT(12,2) DEFAULT NULL,
|
||||||
`rent` FLOAT(12,2) DEFAULT NULL,
|
`rent` FLOAT(12,2) DEFAULT NULL,
|
||||||
|
|
||||||
@@ -844,8 +989,8 @@ CREATE TABLE `pmgr_accounts` (
|
|||||||
-- normal circumstances, when a debit occurs.
|
-- normal circumstances, when a debit occurs.
|
||||||
-- `trackable` TINYINT(1) UNSIGNED NOT NULL DEFAULT 1,
|
-- `trackable` TINYINT(1) UNSIGNED NOT NULL DEFAULT 1,
|
||||||
`deposits` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Can be used for deposits?
|
`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?
|
`invoices` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Can be used for invoices?
|
||||||
`payments` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Can be used for payments?
|
`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?
|
`refunds` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0, -- Can be used for refunds?
|
||||||
|
|
||||||
-- Security Level
|
-- Security Level
|
||||||
@@ -861,46 +1006,46 @@ CREATE TABLE `pmgr_accounts` (
|
|||||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
LOCK TABLES `pmgr_accounts` WRITE;
|
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`)
|
INSERT INTO `pmgr_accounts` (`type`, `name`)
|
||||||
VALUES
|
VALUES
|
||||||
('ASSET', 'A/R' ),
|
('ASSET', 'A/R' ),
|
||||||
-- REVISIT <AP>: 20090710 : We don't really need NSF, as it
|
('LIABILITY', 'A/P' ),
|
||||||
-- will always run a zero balance. However, it will help
|
('LIABILITY', 'Credit' );
|
||||||
-- us identify how serious the NSF situation is.
|
INSERT INTO `pmgr_accounts` (`type`, `name`, `receipts`)
|
||||||
|
VALUES
|
||||||
|
('ASSET', 'Cash', 1),
|
||||||
|
('ASSET', 'Check', 1),
|
||||||
|
('ASSET', 'Money Order', 1),
|
||||||
|
('ASSET', 'ACH', 1),
|
||||||
|
('EXPENSE', 'Concession', 1);
|
||||||
|
INSERT INTO `pmgr_accounts` (`type`, `name`)
|
||||||
|
VALUES
|
||||||
('ASSET', 'NSF' ),
|
('ASSET', 'NSF' ),
|
||||||
('LIABILITY', 'A/P' );
|
('EXPENSE', 'Waiver' ),
|
||||||
INSERT INTO `pmgr_accounts` (`type`, `name`, `payments`, `refunds`)
|
('EXPENSE', 'Bad Debt' );
|
||||||
|
INSERT INTO `pmgr_accounts` (`type`, `name`, `invoices`)
|
||||||
VALUES
|
VALUES
|
||||||
('ASSET', 'Cash', 1, 1),
|
('LIABILITY', 'Tax', 0),
|
||||||
('ASSET', 'Check', 1, 0),
|
|
||||||
('ASSET', 'Money Order', 1, 0),
|
|
||||||
('ASSET', 'ACH', 1, 0),
|
|
||||||
('ASSET', 'Closing', 0, 0), -- REVISIT <AP>: Temporary
|
|
||||||
('EXPENSE', 'Concession', 1, 0);
|
|
||||||
INSERT INTO `pmgr_accounts` (`type`, `name`, `refunds`, `deposits`)
|
|
||||||
VALUES
|
|
||||||
-- REVISIT <AP>: 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`)
|
|
||||||
VALUES
|
|
||||||
('LIABILITY', 'Tax', 1),
|
|
||||||
('LIABILITY', 'Security Deposit', 1),
|
('LIABILITY', 'Security Deposit', 1),
|
||||||
('INCOME', 'Rent', 1),
|
('INCOME', 'Rent', 1),
|
||||||
('INCOME', 'Late Charge', 1),
|
('INCOME', 'Late Charge', 1),
|
||||||
('INCOME', 'NSF Charge', 1),
|
('INCOME', 'NSF Charge', 1),
|
||||||
|
('INCOME', 'Cleaning', 1),
|
||||||
('INCOME', 'Damage', 1);
|
('INCOME', 'Damage', 1);
|
||||||
INSERT INTO `pmgr_accounts` (`type`, `name`, `deposits`, `refunds`)
|
|
||||||
VALUES
|
|
||||||
('ASSET', 'Bank', 1, 1);
|
|
||||||
INSERT INTO `pmgr_accounts` (`type`, `name`)
|
INSERT INTO `pmgr_accounts` (`type`, `name`)
|
||||||
VALUES
|
VALUES
|
||||||
('EXPENSE', 'Bad Debt' ),
|
|
||||||
('EXPENSE', 'Maintenance' );
|
('EXPENSE', 'Maintenance' );
|
||||||
|
INSERT INTO `pmgr_accounts` (`type`, `name`, `refunds`)
|
||||||
|
VALUES
|
||||||
|
('ASSET', 'Petty Cash', 1);
|
||||||
|
INSERT INTO `pmgr_accounts` (`type`, `name`, `level`, `deposits`, `refunds`)
|
||||||
|
VALUES
|
||||||
|
('ASSET', 'Bank', 6, 1, 1);
|
||||||
|
INSERT INTO `pmgr_accounts` (`type`, `name`, `level`)
|
||||||
|
VALUES
|
||||||
|
('ASSET', 'Closing', 6),
|
||||||
|
('LIABILITY', 'Loan', 1),
|
||||||
|
('EQUITY', 'Equity', 1);
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
|
||||||
@@ -949,14 +1094,21 @@ DROP TABLE IF EXISTS `pmgr_transactions`;
|
|||||||
CREATE TABLE `pmgr_transactions` (
|
CREATE TABLE `pmgr_transactions` (
|
||||||
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
|
||||||
`type` ENUM('INVOICE',
|
-- REVISIT <AP>: 20090804
|
||||||
'RECEIPT',
|
-- 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',
|
'DEPOSIT',
|
||||||
'CLOSE',
|
'AUTO_DEPOSIT', -- Fundamentally same as DEPOSIT
|
||||||
|
'WITHDRAWAL',
|
||||||
|
'CLOSE', -- Essentially an internal (not accounting) transaction
|
||||||
-- 'CREDIT',
|
-- 'CREDIT',
|
||||||
-- 'REFUND',
|
-- 'REFUND',
|
||||||
-- 'WAIVER',
|
'TRANSFER') -- Unsure of TRANSFERs use
|
||||||
'TRANSFER')
|
|
||||||
NOT NULL,
|
NOT NULL,
|
||||||
|
|
||||||
`stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
`stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
@@ -981,10 +1133,6 @@ CREATE TABLE `pmgr_transactions` (
|
|||||||
-- (e.g. A/R, Bank, etc)
|
-- (e.g. A/R, Bank, etc)
|
||||||
`account_id` INT(10) UNSIGNED DEFAULT NULL,
|
`account_id` INT(10) UNSIGNED DEFAULT NULL,
|
||||||
`ledger_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',
|
`crdr` ENUM('DEBIT',
|
||||||
'CREDIT')
|
'CREDIT')
|
||||||
DEFAULT NULL,
|
DEFAULT NULL,
|
||||||
@@ -1013,9 +1161,6 @@ CREATE TABLE `pmgr_ledger_entries` (
|
|||||||
-- The account/ledger of the entry
|
-- The account/ledger of the entry
|
||||||
`account_id` INT(10) UNSIGNED NOT NULL,
|
`account_id` INT(10) UNSIGNED NOT NULL,
|
||||||
`ledger_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',
|
`crdr` ENUM('DEBIT',
|
||||||
'CREDIT')
|
'CREDIT')
|
||||||
NOT NULL,
|
NOT NULL,
|
||||||
@@ -1061,19 +1206,27 @@ DROP TABLE IF EXISTS `pmgr_statement_entries`;
|
|||||||
CREATE TABLE `pmgr_statement_entries` (
|
CREATE TABLE `pmgr_statement_entries` (
|
||||||
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
|
||||||
`type` ENUM('CHARGE',
|
-- REVISIT <AP>: 20090804
|
||||||
'PAYMENT',
|
-- I'm not sure about most of these terms.
|
||||||
'SURPLUS',
|
-- 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
|
||||||
|
'WRITEOFF', -- Write-off bad debt
|
||||||
|
'VOUCHER', -- Agreement to pay
|
||||||
|
'PAYMENT', -- Payment of a Voucher
|
||||||
|
'REFUND', -- Payment due to refund
|
||||||
|
'SURPLUS', -- Surplus Receipt Funds
|
||||||
|
'WAIVER', -- Waived Charge
|
||||||
-- REVISIT <AP>: 20090730
|
-- REVISIT <AP>: 20090730
|
||||||
-- VOID is just to test out a theory
|
-- VOID is used for handling NSF and perhaps charge reversals.
|
||||||
-- for handling NSF and charge reversals
|
-- It's not clear this is the best way to handle these things.
|
||||||
'WAIVE',
|
|
||||||
'VOID')
|
'VOID')
|
||||||
NOT NULL,
|
NOT NULL,
|
||||||
|
|
||||||
`transaction_id` INT(10) UNSIGNED NOT NULL,
|
`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).
|
-- 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,
|
-- Through date is used if/when a charge covers a certain time period,
|
||||||
-- like rent. A security deposit, for example, would not use the
|
-- like rent. A security deposit, for example, would not use the
|
||||||
@@ -1098,9 +1251,12 @@ CREATE TABLE `pmgr_statement_entries` (
|
|||||||
-- in the statement. Keeping it for now...
|
-- in the statement. Keeping it for now...
|
||||||
`account_id` INT(10) UNSIGNED DEFAULT NULL,
|
`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,
|
`charge_entry_id` INT(10) UNSIGNED DEFAULT NULL,
|
||||||
|
|
||||||
|
-- The transaction that reversed this charge, if any
|
||||||
|
`reverse_transaction_id` INT(10) UNSIGNED DEFAULT NULL,
|
||||||
|
|
||||||
`comment` VARCHAR(255) DEFAULT NULL,
|
`comment` VARCHAR(255) DEFAULT NULL,
|
||||||
|
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
@@ -1125,6 +1281,9 @@ CREATE TABLE `pmgr_tender_types` (
|
|||||||
-- include credit cards, debit cards, and ACH transfers.
|
-- include credit cards, debit cards, and ACH transfers.
|
||||||
`tillable` TINYINT(1) UNSIGNED NOT NULL DEFAULT 1,
|
`tillable` TINYINT(1) UNSIGNED NOT NULL DEFAULT 1,
|
||||||
|
|
||||||
|
-- Should these items be deposited automatically?
|
||||||
|
`auto_deposit` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
|
||||||
|
|
||||||
-- Names of the 4 data fields (or NULL if not used)
|
-- Names of the 4 data fields (or NULL if not used)
|
||||||
-- Not the most robust of solutions, especially since
|
-- Not the most robust of solutions, especially since
|
||||||
-- it requires (or strongly implicates) that all fields
|
-- it requires (or strongly implicates) that all fields
|
||||||
@@ -1137,11 +1296,21 @@ CREATE TABLE `pmgr_tender_types` (
|
|||||||
`data3_name` VARCHAR(80) DEFAULT NULL,
|
`data3_name` VARCHAR(80) DEFAULT NULL,
|
||||||
`data4_name` VARCHAR(80) DEFAULT NULL,
|
`data4_name` VARCHAR(80) DEFAULT NULL,
|
||||||
|
|
||||||
|
-- The field from pmgr_tenders that is used for helping
|
||||||
|
-- to name the tender. For example, a Check tender type
|
||||||
|
-- might specify data1 as the field, so that tenders
|
||||||
|
-- would be named "Check #0000"
|
||||||
|
`naming_field` VARCHAR(80) DEFAULT 'id',
|
||||||
|
|
||||||
-- When we accept legal tender of this form, where does
|
-- When we accept legal tender of this form, where does
|
||||||
-- it go? Each type of legal tender can specify an
|
-- it go? Each type of legal tender can specify an
|
||||||
-- account, either distinct or non-distinct from others
|
-- account, either distinct or non-distinct from others
|
||||||
`account_id` INT(10) UNSIGNED NOT NULL,
|
`account_id` INT(10) UNSIGNED NOT NULL,
|
||||||
|
|
||||||
|
-- Which account should these items be deposited in?
|
||||||
|
-- This may or may not actually be used for all types
|
||||||
|
-- but will likely get used for auto deposit items.
|
||||||
|
`deposit_account_id` INT(10) UNSIGNED DEFAULT NULL,
|
||||||
|
|
||||||
`comment` VARCHAR(255) DEFAULT NULL,
|
`comment` VARCHAR(255) DEFAULT NULL,
|
||||||
|
|
||||||
@@ -1191,6 +1360,8 @@ CREATE TABLE `pmgr_tenders` (
|
|||||||
`ledger_entry_id` INT(10) UNSIGNED NOT NULL,
|
`ledger_entry_id` INT(10) UNSIGNED NOT NULL,
|
||||||
-- The ledger entry if this tender is marked NSF
|
-- The ledger entry if this tender is marked NSF
|
||||||
`nsf_ledger_entry_id` INT(10) UNSIGNED DEFAULT NULL,
|
`nsf_ledger_entry_id` INT(10) UNSIGNED DEFAULT NULL,
|
||||||
|
-- The ledger entry if this actual deposit transaction
|
||||||
|
`deposit_ledger_entry_id` INT(10) UNSIGNED DEFAULT NULL,
|
||||||
-- The deposit transaction that included these monies
|
-- The deposit transaction that included these monies
|
||||||
`deposit_transaction_id` INT(10) UNSIGNED DEFAULT NULL,
|
`deposit_transaction_id` INT(10) UNSIGNED DEFAULT NULL,
|
||||||
-- The NSF transaction coming back from the bank.
|
-- The NSF transaction coming back from the bank.
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
N - GATE
|
|
||||||
N - ACH / CREDIT CARD PROCESSING
|
|
||||||
Y - CREDIT CARD ENTRY
|
|
||||||
Y - ACH ENTRY
|
|
||||||
P - INVENTORY TRACKING / POS
|
|
||||||
Y - UNIT TYPES
|
|
||||||
Y - UNIT SIZES
|
|
||||||
Y - UNITS
|
|
||||||
Y - MOVE IN / OUT
|
|
||||||
Y - UNIT TRANSFERS
|
|
||||||
Y - LEASE TRACKING (PDF Generation)
|
|
||||||
Y - LETTERS (PDF Generation)
|
|
||||||
Y - REMINDERS
|
|
||||||
Y - MULTIPLE LATE RENT SCHEDULES (Tenant A vs Tenant B)
|
|
||||||
Y - ACCOUNTING (assign charges to accounts)
|
|
||||||
Y - DETAILED REPORTING (HTML & PDF)
|
|
||||||
Y - SITE MAP; HOT CLICKABLE
|
|
||||||
P - PROSPECTIVE TENANTS
|
|
||||||
Y - MARKETING
|
|
||||||
P - RESERVATIONS
|
|
||||||
P - MOVE OUT NOTICES
|
|
||||||
P - MULTI-SITE (One database, multiple sites)
|
|
||||||
Y - GENERATE GEOGRAPHIC MAP OF CUSTOMERS USING GOOGLE!
|
|
||||||
- Major advantage here... MapPoint only choice with competitors
|
|
||||||
Y - WEB BASED
|
|
||||||
Y - CUSTOMER VIEW / MANAGER VIEW
|
|
||||||
Y - CUSTOMERS CAN CREATE ACCOUNTS, VIEW HISTORY
|
|
||||||
Y - CUSTOMERS CAN SIGN UP FOR AUTO PAY
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
----------------------------------------------------------------------
|
|
||||||
Operations to be functional
|
|
||||||
'X' marks functionality sufficiently completed
|
|
||||||
|
|
||||||
X - Create Customer ID/Account
|
|
||||||
X - Add Contact information to Customer
|
|
||||||
X - Move Customer into Unit
|
|
||||||
? - Enter Rent Concessions given
|
|
||||||
X - Asses Rent Charges
|
|
||||||
X - Asses Late Charges
|
|
||||||
X - Asses Security Deposits
|
|
||||||
X - Receive and record Checks
|
|
||||||
X - Receive and record Money Orders
|
|
||||||
X - Receive and record Cash
|
|
||||||
X - Receive and record ACH Deposits
|
|
||||||
? - Reverse rent charges (early moveout on prepaid occupancy)
|
|
||||||
X - Handle NSF checks
|
|
||||||
X - Assess NSF Fees
|
|
||||||
X - Determine Lease Paid-Through status
|
|
||||||
- Report: List of customers overdue
|
|
||||||
- Flag unit as overlocked
|
|
||||||
- Flag unit as evicting
|
|
||||||
- Flag unit as normal status
|
|
||||||
- Flag unit as dirty
|
|
||||||
- Enter notes when communicating with Customer
|
|
||||||
X - Accept pre-payments
|
|
||||||
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
|
|
||||||
X - Perform a Deposit
|
|
||||||
X - Close the Books (nightly / weekly, etc)
|
|
||||||
X - Determine Rents Collected for a given period.
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,20 @@
|
|||||||
<IfModule mod_rewrite.c>
|
<IfModule mod_rewrite.c>
|
||||||
RewriteEngine on
|
RewriteEngine on
|
||||||
RewriteRule ^$ webroot/ [L]
|
|
||||||
RewriteRule (.*) webroot/$1 [L]
|
RewriteRule ^$ webroot/ [L]
|
||||||
</IfModule>
|
|
||||||
|
# Need this prevent a 400 error without trailing /
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
RewriteRule (.*) webroot/$1 [L]
|
||||||
|
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
# Need to make sure directories can't be listed, since the rewrite
|
||||||
|
# rule excludes rewriting when an actual directory is requested
|
||||||
|
Options -Indexes
|
||||||
|
|
||||||
|
# Provide a mechanism for user authentication
|
||||||
|
AuthType Basic
|
||||||
|
AuthName "Valley Storage"
|
||||||
|
AuthUserFile "/home/perki2/valley_storage.pmgr.htpasswd"
|
||||||
|
Require valid-user
|
||||||
|
|||||||
@@ -35,49 +35,458 @@
|
|||||||
* @subpackage cake.app
|
* @subpackage cake.app
|
||||||
*/
|
*/
|
||||||
class AppController extends Controller {
|
class AppController extends Controller {
|
||||||
|
var $uses = array('Option', 'Permission');
|
||||||
var $helpers = array('Html', 'Form', 'Javascript', 'Format', 'Time', 'Grid');
|
var $helpers = array('Html', 'Form', 'Javascript', 'Format', 'Time', 'Grid');
|
||||||
var $components = array('DebugKit.Toolbar');
|
//var $components = array('DebugKit.Toolbar');
|
||||||
|
|
||||||
function sideMenuLinks() {
|
var $sidemenu = array('areas' => array('SITE' => false, 'REPORT' => false, 'CONTROLLER' => false, 'ACTION' => false, 'SANDBOX' => false));
|
||||||
return array(
|
var $std_area = 10;
|
||||||
array('name' => 'Common', 'header' => true),
|
var $admin_area = 20;
|
||||||
array('name' => 'Site Map', 'url' => array('controller' => 'maps', 'action' => 'view', 1)),
|
var $dev_area = 30;
|
||||||
array('name' => 'Units', 'url' => array('controller' => 'units', 'action' => 'index')),
|
var $op_area = 40;
|
||||||
array('name' => 'Leases', 'url' => array('controller' => 'leases', 'action' => 'index')),
|
var $new_area = 50;
|
||||||
array('name' => 'Customers', 'url' => array('controller' => 'customers', 'action' => 'index')),
|
|
||||||
array('name' => 'Accounts', 'url' => array('controller' => 'accounts', 'action' => 'index')),
|
function __construct() {
|
||||||
array('name' => 'Debug', 'header' => true),
|
$this->params['dev'] = false;
|
||||||
array('name' => 'Contacts', 'url' => array('controller' => 'contacts', 'action' => 'index')),
|
$this->params['admin'] = false;
|
||||||
array('name' => 'Ledgers', 'url' => array('controller' => 'ledgers', 'action' => 'index')),
|
parent::__construct();
|
||||||
array('name' => 'New Ledgers', 'url' => array('controller' => 'accounts', 'action' => 'newledger')),
|
|
||||||
array('name' => 'RESET DATA', 'url' => array('controller' => 'accounts', 'action' => 'reset_data')),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: dev/admin()
|
||||||
|
* - Indicates if the user has dev/admin access
|
||||||
|
*/
|
||||||
|
function dev() { return !empty($this->params['dev']); }
|
||||||
|
function admin() { return !empty($this->params['admin']); }
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: sideMenuAreaVerify
|
||||||
|
* - Verifies the validity of the sidemenu area/subarea/priority,
|
||||||
|
* and ensures the class member is set to appropriately handle it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function sideMenuAreaVerify(&$area, $subarea, $priority = null) {
|
||||||
|
$area = strtoupper($area);
|
||||||
|
if (!array_key_exists($area, $this->sidemenu['areas']))
|
||||||
|
$this->INTERNAL_ERROR("Sidemenu link '{$area}': Unknown");
|
||||||
|
|
||||||
|
if ($area == 'SITE')
|
||||||
|
$name = 'Navigation';
|
||||||
|
elseif ($area == 'CONTROLLER')
|
||||||
|
$name = Inflector::humanize($this->params['controller']);
|
||||||
|
elseif ($area == 'ACTION')
|
||||||
|
$name = Inflector::humanize(Inflector::singularize($this->params['controller']));
|
||||||
|
elseif ($area == 'REPORT')
|
||||||
|
$name = 'Reports';
|
||||||
|
elseif ($area == 'SANDBOX')
|
||||||
|
$name = 'Sandbox';
|
||||||
|
|
||||||
|
if (empty($this->sidemenu['areas'][$area]))
|
||||||
|
$this->sidemenu['areas'][$area]
|
||||||
|
= array('enable' => true, 'name' => $name, 'subareas' => array());
|
||||||
|
|
||||||
|
if (empty($subarea))
|
||||||
|
return;
|
||||||
|
|
||||||
|
$subname = $name;
|
||||||
|
if ($subarea == $this->std_area)
|
||||||
|
$subname .= '';
|
||||||
|
elseif ($subarea == $this->op_area)
|
||||||
|
//$subname .= '-Ops';
|
||||||
|
$subname = 'Actions';
|
||||||
|
elseif ($subarea == $this->new_area)
|
||||||
|
//$subname .= '-New';
|
||||||
|
$subname = 'Creation';
|
||||||
|
elseif ($subarea == $this->admin_area)
|
||||||
|
$subname .= '-Admin';
|
||||||
|
elseif ($subarea == $this->dev_area)
|
||||||
|
$subname .= '-Dev';
|
||||||
|
else
|
||||||
|
$subname .= '-' . $subarea;
|
||||||
|
|
||||||
|
if (empty($this->sidemenu['areas'][$area]['subareas'][$subarea]))
|
||||||
|
$this->sidemenu['areas'][$area]['subareas'][$subarea]
|
||||||
|
= array('enable' => true, 'name' => $subname, 'priorities' => array());
|
||||||
|
|
||||||
|
if (empty($priority))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (empty($this->sidemenu['areas'][$area]['subareas'][$subarea]['priorities'][$priority]))
|
||||||
|
$this->sidemenu['areas'][$area]['subareas'][$subarea]['priorities'][$priority]
|
||||||
|
= array();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: sideMenuAreaName
|
||||||
|
* - Sets the name of the sidemenu area/subarea
|
||||||
|
*/
|
||||||
|
|
||||||
|
function sideMenuAreaName($name, $area, $subarea = null) {
|
||||||
|
$this->sideMenuAreaVerify($area, $subarea);
|
||||||
|
if (empty($subarea))
|
||||||
|
$this->sidemenu['areas'][$area]['name'] = $name;
|
||||||
|
else
|
||||||
|
$this->sidemenu['areas'][$area]['subareas'][$subarea]['name'] = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: sideMenuAreaActivate
|
||||||
|
* - Sets the selected area/subarea to be active when the
|
||||||
|
* page is first loaded.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function sideMenuAreaActivate($area, $subarea = null) {
|
||||||
|
$this->sidemenu['active'] = compact('area', 'subarea');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: sideMenuEnable
|
||||||
|
* - Enables/Disables an area or subarea of the sidemenu
|
||||||
|
*/
|
||||||
|
|
||||||
|
function sideMenuEnable($area, $subarea = null, $enable = true) {
|
||||||
|
$this->sideMenuAreaVerify($area, $subarea);
|
||||||
|
if (isset($subarea))
|
||||||
|
$this->sidemenu['areas'][$area]['subareas'][$subarea]['enable'] = $enable;
|
||||||
|
else
|
||||||
|
$this->sidemenu['areas'][$area]['enable'] = $enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: addSideMenuLink
|
||||||
|
* - Adds another link to the sidemenu area/subarea/priority
|
||||||
|
*/
|
||||||
|
|
||||||
|
function addSideMenuLink($name, $url, $extra, $area, $subarea = null, $priority = 10) {
|
||||||
|
if (empty($subarea))
|
||||||
|
$subarea = $this->std_area;
|
||||||
|
$this->sideMenuAreaVerify($area, $subarea);
|
||||||
|
$this->sidemenu['areas'][$area]['subareas'][$subarea]['priorities'][$priority][]
|
||||||
|
= array('name' => $name, 'url' => $url) + (empty($extra) ? array() : $extra);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: addDefaultSideMenuLinks
|
||||||
|
* - Adds the standard links present on all generated pages
|
||||||
|
*/
|
||||||
|
|
||||||
|
function addDefaultSideMenuLinks() {
|
||||||
|
|
||||||
|
$this->addSideMenuLink('Site Map',
|
||||||
|
array('controller' => 'maps', 'action' => 'view', 1), null,
|
||||||
|
'SITE');
|
||||||
|
$this->addSideMenuLink('Unit Sizes',
|
||||||
|
array('controller' => 'unit_sizes', 'action' => 'index'), null,
|
||||||
|
'SITE');
|
||||||
|
$this->addSideMenuLink('Units',
|
||||||
|
array('controller' => 'units', 'action' => 'index'), null,
|
||||||
|
'SITE');
|
||||||
|
$this->addSideMenuLink('Locks',
|
||||||
|
array('controller' => 'locks', 'action' => 'index'), null,
|
||||||
|
'SITE');
|
||||||
|
$this->addSideMenuLink('Leases',
|
||||||
|
array('controller' => 'leases', 'action' => 'index'), null,
|
||||||
|
'SITE');
|
||||||
|
$this->addSideMenuLink('Customers',
|
||||||
|
array('controller' => 'customers', 'action' => 'index'), null,
|
||||||
|
'SITE');
|
||||||
|
$this->addSideMenuLink('Deposits',
|
||||||
|
array('controller' => 'transactions', 'action' => 'deposit'), null,
|
||||||
|
'SITE');
|
||||||
|
|
||||||
|
$this->addSideMenuLink('Accounts',
|
||||||
|
array('controller' => 'accounts', 'action' => 'index'), null,
|
||||||
|
'SITE', $this->admin_area);
|
||||||
|
$this->addSideMenuLink('Contacts',
|
||||||
|
array('controller' => 'contacts', 'action' => 'index'), null,
|
||||||
|
'SITE', $this->admin_area);
|
||||||
|
$this->addSideMenuLink('Ledgers',
|
||||||
|
array('controller' => 'ledgers', 'action' => 'index'), null,
|
||||||
|
'SITE', $this->admin_area);
|
||||||
|
$this->addSideMenuLink('Tenders',
|
||||||
|
array('controller' => 'tenders', 'action' => 'index'), null,
|
||||||
|
'SITE', $this->admin_area);
|
||||||
|
$this->addSideMenuLink('Transactions',
|
||||||
|
array('controller' => 'transactions', 'action' => 'index'), null,
|
||||||
|
'SITE', $this->admin_area);
|
||||||
|
$this->addSideMenuLink('Ldgr Entries',
|
||||||
|
array('controller' => 'ledger_entries', 'action' => 'index'), null,
|
||||||
|
'SITE', $this->admin_area);
|
||||||
|
$this->addSideMenuLink('Stmt Entries',
|
||||||
|
array('controller' => 'statement_entries', 'action' => 'index'), null,
|
||||||
|
'SITE', $this->admin_area);
|
||||||
|
|
||||||
|
$this->addSideMenuLink('Un-Nuke',
|
||||||
|
'#', array('htmlAttributes' =>
|
||||||
|
array('onclick' => '$(".pr-section").show(); return false;')),
|
||||||
|
'SITE', $this->dev_area);
|
||||||
|
$this->addSideMenuLink('New Ledgers',
|
||||||
|
array('controller' => 'accounts', 'action' => 'newledger'), null,
|
||||||
|
'SITE', $this->dev_area);
|
||||||
|
//array('name' => 'RESET DATA', array('controller' => 'accounts', 'action' => 'reset_data'));
|
||||||
|
|
||||||
|
|
||||||
|
$this->addSideMenuLink('New Receipt',
|
||||||
|
array('controller' => 'customers', 'action' => 'receipt'), null,
|
||||||
|
'SITE', $this->op_area);
|
||||||
|
$this->addSideMenuLink('New Invoice',
|
||||||
|
array('controller' => 'leases', 'action' => 'invoice'), null,
|
||||||
|
'SITE', $this->op_area);
|
||||||
|
$this->addSideMenuLink('Move-In',
|
||||||
|
array('controller' => 'customers', 'action' => 'move_in'), null,
|
||||||
|
'SITE', $this->op_area);
|
||||||
|
$this->addSideMenuLink('Move-Out',
|
||||||
|
array('controller' => 'leases', 'action' => 'move_out'), null,
|
||||||
|
'SITE', $this->op_area);
|
||||||
|
$this->addSideMenuLink('New Deposit',
|
||||||
|
array('controller' => 'tenders', 'action' => 'deposit'), null,
|
||||||
|
'SITE', $this->op_area);
|
||||||
|
if ($this->admin())
|
||||||
|
$this->addSideMenuLink('Assess Charges',
|
||||||
|
array('controller' => 'leases', 'action' => 'assess_all'), null,
|
||||||
|
'SITE', $this->op_area);
|
||||||
|
|
||||||
|
if ($this->admin()) {
|
||||||
|
$acct = new Account;
|
||||||
|
$this->addSideMenuLink('Collected Rent',
|
||||||
|
array('controller' => 'accounts',
|
||||||
|
'action' => 'collected',
|
||||||
|
$acct->rentAccountID()), null,
|
||||||
|
'REPORT');
|
||||||
|
$this->addSideMenuLink('Unpaid Charges',
|
||||||
|
array('controller' => 'statement_entries', 'action' => 'unpaid'), null,
|
||||||
|
'REPORT');
|
||||||
|
$this->addSideMenuLink('Unit Summary',
|
||||||
|
array('controller' => 'units', 'action' => 'overview'), null,
|
||||||
|
'REPORT');
|
||||||
|
$this->addSideMenuLink('Lease Up',
|
||||||
|
array('controller' => 'leases', 'action' => 'overview'), null,
|
||||||
|
'REPORT');
|
||||||
|
/* $this->addSideMenuLink('Monthly Income', */
|
||||||
|
/* array('controller' => 'statement_entries', 'action' => 'incomebymonth'), null, */
|
||||||
|
/* 'REPORT'); */
|
||||||
|
/* $this->addSideMenuLink('Monthly Expenses', */
|
||||||
|
/* array('controller' => 'statement_entries', 'action' => 'expensebymonth'), null, */
|
||||||
|
/* 'REPORT'); */
|
||||||
|
/* $this->addSideMenuLink('Quickbook Invoice', */
|
||||||
|
/* array('controller' => 'statement_entries', 'action' => 'incomebymonth', 4, 1), null, */
|
||||||
|
/* 'REPORT'); */
|
||||||
|
/* $this->addSideMenuLink('Quickbook Credits', */
|
||||||
|
/* array('controller' => 'statement_entries', 'action' => 'expensebymonth', 4, 0), null, */
|
||||||
|
/* 'REPORT'); */
|
||||||
|
$this->addSideMenuLink('Monthly Income',
|
||||||
|
array('controller' => 'statement_entries', 'action' => 'netbymonth'), null,
|
||||||
|
'REPORT');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->sideMenuEnable('REPORT', null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$url_components = array('plugin', 'controller', 'action', 'named');
|
||||||
|
if (devbox()) {
|
||||||
|
/* $sources = ConnectionManager::sourceList(); */
|
||||||
|
/* $db = ConnectionManager::getDataSource($sources[0])->config['database']; */
|
||||||
|
/* $this->sideMenuAreaName($db, 'SANDBOX', $this->std_area); */
|
||||||
|
$this->sideMenuAreaName('DevBox', 'SANDBOX', $this->std_area);
|
||||||
|
$this->addSideMenuLink('Rebuild DevBox',
|
||||||
|
array('controller' => 'util', 'action' => 'rebuild_devbox'), null,
|
||||||
|
'SANDBOX');
|
||||||
|
}
|
||||||
|
elseif (sandbox()) {
|
||||||
|
$this->addSideMenuLink('Rebuild Sandbox',
|
||||||
|
array('controller' => 'util', 'action' => 'rebuild_sandbox'), null,
|
||||||
|
'SANDBOX');
|
||||||
|
$this->addSideMenuLink('Leave Sandbox',
|
||||||
|
array('sand_route' => false)
|
||||||
|
+ array_intersect_key($this->params, array_flip($url_components))
|
||||||
|
+ $this->params['pass'],
|
||||||
|
null, 'SANDBOX');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->addSideMenuLink('Enter Sandbox',
|
||||||
|
array('sand_route' => true)
|
||||||
|
+ array_intersect_key($this->params, array_flip($url_components))
|
||||||
|
+ $this->params['pass'],
|
||||||
|
null, 'SANDBOX');
|
||||||
|
}
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090824
|
||||||
|
// Depending on preference, we may put this into the gridView
|
||||||
|
// function, making the links available only when navigating.
|
||||||
|
$this->addGridViewSideMenuLinks();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtual: addGridViewSideMenuLinks
|
||||||
|
* - Adds the grid view specific navigation links, if overridden.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function addGridViewSideMenuLinks() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* hook: beforeFilter
|
||||||
|
* - Called just before the action function
|
||||||
|
*/
|
||||||
|
|
||||||
|
function beforeFilter() {
|
||||||
|
$this->params['user'] = $this->Permission->User->currentUser();
|
||||||
|
$this->params['admin'] = $this->Option->enabled('admin');
|
||||||
|
$this->params['dev'] = devbox();
|
||||||
|
|
||||||
|
if ($this->dev() && !$this->Option->enabled('dev'))
|
||||||
|
$this->redirect("/");
|
||||||
|
|
||||||
|
if (!$this->dev())
|
||||||
|
Configure::write('debug', '0');
|
||||||
|
|
||||||
|
$this->addDefaultSideMenuLinks();
|
||||||
|
//$this->sideMenuEnable('SITE', $this->op_area, false);
|
||||||
|
|
||||||
|
foreach ($this->sidemenu['areas'] AS $area_name => $area) {
|
||||||
|
if (!$this->dev())
|
||||||
|
$this->sideMenuEnable($area_name, $this->dev_area, false);
|
||||||
|
if (!$this->admin())
|
||||||
|
$this->sideMenuEnable($area_name, $this->admin_area, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->authorize("controller.{$this->params['controller']}");
|
||||||
|
$this->authorize("action.{$this->params['controller']}.{$this->params['action']}");
|
||||||
|
|
||||||
|
$this->log('----------------------------------------------------------------------', 'request');
|
||||||
|
$this->log('----------------------------------------------------------------------', 'request');
|
||||||
|
$this->log($this->params, 'request');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* hook: beforeRender
|
||||||
|
* - Called just before rendering the page
|
||||||
|
*/
|
||||||
|
|
||||||
function beforeRender() {
|
function beforeRender() {
|
||||||
$this->set('sidemenu', $this->sideMenuLinks());
|
// Stupid Cake... our constructor sets admin/dev,
|
||||||
|
// but cake stomps it somewhere along the way
|
||||||
|
// after constructing the CakeError controller.
|
||||||
|
if ($this->name === 'CakeError') {
|
||||||
|
$this->params['dev'] = false;
|
||||||
|
$this->params['admin'] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->sidemenu['areas'] AS $aname => &$area) {
|
||||||
|
if (empty($area['enable']))
|
||||||
|
$area = array();
|
||||||
|
if (empty($area['subareas']))
|
||||||
|
continue;
|
||||||
|
ksort($area['subareas']);
|
||||||
|
|
||||||
|
foreach ($area['subareas'] AS $sname => &$subarea) {
|
||||||
|
if (empty($subarea['enable']))
|
||||||
|
$subarea = array();
|
||||||
|
if (empty($subarea['priorities']))
|
||||||
|
continue;
|
||||||
|
ksort($subarea['priorities']);
|
||||||
|
|
||||||
|
foreach ($subarea['priorities'] AS $pname => &$priority) {
|
||||||
|
if (empty($priority))
|
||||||
|
unset($subarea['priorities'][$pname]);
|
||||||
|
}
|
||||||
|
unset($priority);
|
||||||
|
|
||||||
|
if (empty($subarea['priorities']))
|
||||||
|
unset($area['subareas'][$sname]);
|
||||||
|
}
|
||||||
|
unset($subarea);
|
||||||
|
|
||||||
|
if (empty($area['subareas']))
|
||||||
|
unset($this->sidemenu['areas'][$aname]);
|
||||||
|
}
|
||||||
|
unset($area);
|
||||||
|
|
||||||
|
// Activate a default section (unless already specified)
|
||||||
|
foreach (array_reverse(array_diff_key($this->sidemenu['areas'], array('SANDBOX'=>1))) AS $area_name => $area) {
|
||||||
|
if (empty($area))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (empty($this->sidemenu['active']) ||
|
||||||
|
empty($this->sidemenu['areas'][$this->sidemenu['active']['area']]))
|
||||||
|
$this->sideMenuAreaActivate($area_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If generating reports, don't display the controller menu.
|
||||||
|
// Each report comes from a controller, but there is no need
|
||||||
|
// to present the controller actions, so remove that section
|
||||||
|
// from the menu.
|
||||||
|
if ($this->sidemenu['active']['area'] == 'REPORT')
|
||||||
|
$this->sideMenuEnable('CONTROLLER', null, false);
|
||||||
|
|
||||||
|
//pr($this->sidemenu);
|
||||||
|
$this->set('sidemenu', $this->sidemenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
function reset_data() {
|
|
||||||
$this->layout = null;
|
/**************************************************************************
|
||||||
$this->autoLayout = false;
|
**************************************************************************
|
||||||
$this->autoRender = false;
|
**************************************************************************
|
||||||
Configure::write('debug', '0');
|
* override: redirect
|
||||||
$script = $_SERVER['DOCUMENT_ROOT'] . '/pmgr/build.cmd';
|
*/
|
||||||
echo "<P>" . date('r') . "\n";
|
|
||||||
//echo "<P>Script: $script" . "\n";
|
function redirect($url, $status = null, $exit = true) {
|
||||||
$db = & $this->Account->getDataSource();
|
// OK, since the controller will not be able to
|
||||||
$script .= ' "' . $db->config['database'] . '"';
|
// utilize our overriden url function in AppHelper,
|
||||||
$script .= ' "' . $db->config['login'] . '"';
|
// we'll have to do it manually here.
|
||||||
$script .= ' "' . $db->config['password'] . '"';
|
App::import('Helper', 'Html');
|
||||||
$handle = popen($script . ' 2>&1', 'r');
|
$url = HtmlHelper::url($url, true);
|
||||||
//echo "<P>Handle: $handle; " . gettype($handle) . "\n";
|
|
||||||
echo "<P><PRE>\n";
|
if (headers_sent() ||
|
||||||
while (($read = fread($handle, 2096))) {
|
($this->dev() && $this->Option->enabled('dev'))) {
|
||||||
echo $read;
|
// If we've already sent the headers, it's because
|
||||||
|
// we're debugging, and our debug output has gotten
|
||||||
|
// out before the redirect. That's probably a good
|
||||||
|
// thing, as we don't typically want pages to be
|
||||||
|
// jerked out from under us while trying to read
|
||||||
|
// the debug output. So, since we can't redirect
|
||||||
|
// anyway, we may as well go with the flow and just
|
||||||
|
// render this page instead, using an empty template
|
||||||
|
$this->set('message',
|
||||||
|
("Intended redirect:<P><BR>" .
|
||||||
|
'<A HREF="'.$url.'">'.$url.'</A>'));
|
||||||
|
|
||||||
|
echo $this->render('/empty');
|
||||||
|
if ($exit)
|
||||||
|
$this->_stop();
|
||||||
}
|
}
|
||||||
echo "</PRE>\n";
|
|
||||||
pclose($handle);
|
return parent::redirect($url, $status, $exit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -87,8 +496,14 @@ class AppController extends Controller {
|
|||||||
* helper: gridView
|
* helper: gridView
|
||||||
* - called by derived controllers to create an index listing
|
* - called by derived controllers to create an index listing
|
||||||
*/
|
*/
|
||||||
|
function index() {
|
||||||
|
$names = Inflector::humanize(Inflector::pluralize($this->params['controller']));
|
||||||
|
$this->gridView('All ' . $names, 'all');
|
||||||
|
}
|
||||||
|
|
||||||
function gridView($title, $action = null, $element = null) {
|
function gridView($title, $action = null, $element = null) {
|
||||||
|
$this->sideMenuEnable('SITE', $this->op_area);
|
||||||
|
$this->sideMenuAreaActivate('CONTROLLER');
|
||||||
$this->set('title', $title);
|
$this->set('title', $title);
|
||||||
// The resulting page will contain a grid, which will
|
// The resulting page will contain a grid, which will
|
||||||
// use ajax to obtain the actual data for this action
|
// use ajax to obtain the actual data for this action
|
||||||
@@ -127,6 +542,9 @@ class AppController extends Controller {
|
|||||||
// Retreive the appropriate subset of data
|
// Retreive the appropriate subset of data
|
||||||
$records = $this->gridDataRecords($params, $model, $pagination);
|
$records = $this->gridDataRecords($params, $model, $pagination);
|
||||||
|
|
||||||
|
// If subtotaling, figure out the running total before pagination...
|
||||||
|
$this->gridDataRecordsRunningSubtotal($params, $model, $pagination);
|
||||||
|
|
||||||
// Post process the records
|
// Post process the records
|
||||||
$this->gridDataPostProcess($params, $model, $records);
|
$this->gridDataPostProcess($params, $model, $records);
|
||||||
|
|
||||||
@@ -159,16 +577,10 @@ class AppController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function gridDataSetup(&$params) {
|
function gridDataSetup(&$params) {
|
||||||
// Assume we're debugging.
|
// Debug only if requested
|
||||||
// The actual grid request will set this to false
|
$params['debug'] = !empty($this->passedArgs['debug']);
|
||||||
$debug = true;
|
|
||||||
|
|
||||||
if (isset($this->passedArgs['debug']))
|
if ($params['debug']) {
|
||||||
$debug = $this->passedArgs['debug'];
|
|
||||||
|
|
||||||
$params['debug'] = $debug;
|
|
||||||
|
|
||||||
if ($debug) {
|
|
||||||
ob_start();
|
ob_start();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -187,17 +599,26 @@ class AppController extends Controller {
|
|||||||
// This SHOULD always be set, except when debugging
|
// This SHOULD always be set, except when debugging
|
||||||
if (isset($params['post']))
|
if (isset($params['post']))
|
||||||
$params['post'] = unserialize($params['post']);
|
$params['post'] = unserialize($params['post']);
|
||||||
|
else
|
||||||
|
$params['post'] = array();
|
||||||
|
|
||||||
// Unserialize our complex structure of dynamic post data
|
// Unserialize our complex structure of dynamic post data
|
||||||
if (isset($params['dynamic_post']))
|
if (isset($params['dynamic_post']))
|
||||||
$params['dynamic_post'] = unserialize($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
|
// Merge the static and dynamic post data
|
||||||
if (empty($params['post']) && !empty($params['dynamic_post']))
|
if (!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']);
|
|
||||||
$params['post'] = array_merge_recursive($params['post'], $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
|
// This SHOULD always be set, except when debugging
|
||||||
if (!isset($params['post']['fields']))
|
if (!isset($params['post']['fields']))
|
||||||
@@ -222,6 +643,7 @@ class AppController extends Controller {
|
|||||||
$xml = preg_replace("/</", "<", $xml);
|
$xml = preg_replace("/</", "<", $xml);
|
||||||
$xml = preg_replace("/>/", ">", $xml);
|
$xml = preg_replace("/>/", ">", $xml);
|
||||||
echo ("\n<PRE>\n$xml\n</PRE>\n");
|
echo ("\n<PRE>\n$xml\n</PRE>\n");
|
||||||
|
$this->render_empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,21 +658,21 @@ class AppController extends Controller {
|
|||||||
$query = array_intersect_key($this->gridDataCountTableSet($params, $model),
|
$query = array_intersect_key($this->gridDataCountTableSet($params, $model),
|
||||||
array('link'=>1, 'contain'=>1));
|
array('link'=>1, 'contain'=>1));
|
||||||
|
|
||||||
|
// Conditions for the count
|
||||||
|
$query['fields'] = array($this->gridDataCountField($params, $model));
|
||||||
|
|
||||||
// Conditions for the count
|
// Conditions for the count
|
||||||
$query['conditions'] = $this->gridDataCountConditionSet($params, $model);
|
$query['conditions'] = $this->gridDataCountConditionSet($params, $model);
|
||||||
|
|
||||||
// Grouping (which would not be typical)
|
// Grouping (which would not be typical)
|
||||||
$query['group'] = $this->gridDataCountGroup($params, $model);
|
$query['group'] = $this->gridDataCountGroup($params, $model);
|
||||||
|
|
||||||
// DEBUG PURPOSES ONLY!
|
|
||||||
$params['count_query'] = $query;
|
|
||||||
|
|
||||||
// Get the number of records prior to pagination
|
// Get the number of records prior to pagination
|
||||||
return $this->gridDataCountExecute($params, $model, $query);
|
return $this->gridDataCountExecute($params, $model, $query);
|
||||||
}
|
}
|
||||||
|
|
||||||
function gridDataCountExecute(&$params, &$model, $query) {
|
function gridDataCountExecute(&$params, &$model, $query) {
|
||||||
return $model->find('count', $query);
|
return $this->gridDataFind($params, $model, 'count', $query);
|
||||||
}
|
}
|
||||||
|
|
||||||
function gridDataCountTables(&$params, &$model) {
|
function gridDataCountTables(&$params, &$model) {
|
||||||
@@ -268,6 +690,10 @@ class AppController extends Controller {
|
|||||||
array('link'=>1, 'contain'=>1));
|
array('link'=>1, 'contain'=>1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function gridDataCountField(&$params, &$model) {
|
||||||
|
return "COUNT(DISTINCT `".$model->alias.'`.`'.$model->primaryKey."`) AS 'count'";
|
||||||
|
}
|
||||||
|
|
||||||
function gridDataCountConditions(&$params, &$model) {
|
function gridDataCountConditions(&$params, &$model) {
|
||||||
// Same conditions for counting as for retreiving
|
// Same conditions for counting as for retreiving
|
||||||
return $this->gridDataConditions($params, $model);
|
return $this->gridDataConditions($params, $model);
|
||||||
@@ -468,6 +894,9 @@ class AppController extends Controller {
|
|||||||
$page = ($params['page'] <= 1) ? 1 : (($params['page'] > $total) ? $total : $params['page']);
|
$page = ($params['page'] <= 1) ? 1 : (($params['page'] > $total) ? $total : $params['page']);
|
||||||
$start = $limit * ($page - 1);
|
$start = $limit * ($page - 1);
|
||||||
|
|
||||||
|
// Adjust the limit upward, if multiple pages were requested.
|
||||||
|
$limit *= empty($params['npage']) ? 1 : $params['npage'];
|
||||||
|
|
||||||
return compact('record_count', 'limit', 'page', 'start', 'total');
|
return compact('record_count', 'limit', 'page', 'start', 'total');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -499,14 +928,11 @@ class AppController extends Controller {
|
|||||||
isset($params['sidx']) ? $params['sidx'] : null,
|
isset($params['sidx']) ? $params['sidx'] : null,
|
||||||
isset($params['sord']) ? $params['sord'] : null);
|
isset($params['sord']) ? $params['sord'] : null);
|
||||||
|
|
||||||
// DEBUG PURPOSES ONLY!
|
|
||||||
$params['query'] = $query;
|
|
||||||
|
|
||||||
return $this->gridDataRecordsExecute($params, $model, $query);
|
return $this->gridDataRecordsExecute($params, $model, $query);
|
||||||
}
|
}
|
||||||
|
|
||||||
function gridDataRecordsExecute(&$params, &$model, $query) {
|
function gridDataRecordsExecute(&$params, &$model, $query) {
|
||||||
return $model->find('all', $query);
|
return $this->gridDataFind($params, $model, 'all', $query);
|
||||||
}
|
}
|
||||||
|
|
||||||
function gridDataTables(&$params, &$model) {
|
function gridDataTables(&$params, &$model) {
|
||||||
@@ -548,12 +974,24 @@ class AppController extends Controller {
|
|||||||
'value' => $params['filtValue']);
|
'value' => $params['filtValue']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Translate a user specified date into the SQL date format
|
||||||
|
foreach ($searches AS &$search) {
|
||||||
|
if (preg_match('/(_date|stamp)$/', $search['field']) &&
|
||||||
|
preg_match('%(\d{1,2})[-/](\d{1,2})[-/](\d{2,4})%', $search['value'], $matches)) {
|
||||||
|
$search['value'] = sprintf('%04d%02d%02d',
|
||||||
|
$matches[3] + ($matches[3] < 50 ? 2000 : ($matches[3] < 100 ? 1900 : 0)),
|
||||||
|
$matches[2], $matches[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($search);
|
||||||
|
|
||||||
$ops = array('eq' => array('op' => null, 'pre' => '', 'post' => ''),
|
$ops = array('eq' => array('op' => null, 'pre' => '', 'post' => ''),
|
||||||
'ne' => array('op' => '<>', 'pre' => '', 'post' => ''),
|
'ne' => array('op' => '<>', 'pre' => '', 'post' => ''),
|
||||||
'lt' => array('op' => '<', 'pre' => '', 'post' => ''),
|
'lt' => array('op' => '<', 'pre' => '', 'post' => ''),
|
||||||
'le' => array('op' => '<=', 'pre' => '', 'post' => ''),
|
'le' => array('op' => '<=', 'pre' => '', 'post' => ''),
|
||||||
'gt' => array('op' => '>', 'pre' => '', 'post' => ''),
|
'gt' => array('op' => '>', 'pre' => '', 'post' => ''),
|
||||||
'ge' => array('op' => '>=', 'pre' => '', 'post' => ''),
|
'ge' => array('op' => '>=', 'pre' => '', 'post' => ''),
|
||||||
|
'in' => array('op' => 'IN', 'pre' => '(', 'post' => ')'),
|
||||||
'bw' => array('op' => 'LIKE', 'pre' => '', 'post' => '%'),
|
'bw' => array('op' => 'LIKE', 'pre' => '', 'post' => '%'),
|
||||||
'ew' => array('op' => 'LIKE', 'pre' => '%', 'post' => ''),
|
'ew' => array('op' => 'LIKE', 'pre' => '%', 'post' => ''),
|
||||||
'cn' => array('op' => 'LIKE', 'pre' => '%', 'post' => '%'),
|
'cn' => array('op' => 'LIKE', 'pre' => '%', 'post' => '%'),
|
||||||
@@ -603,6 +1041,60 @@ class AppController extends Controller {
|
|||||||
return $start . ', ' . $limit;
|
return $start . ', ' . $limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function gridDataFind(&$params, &$model, $type, $query) {
|
||||||
|
if ($params['debug'])
|
||||||
|
$params['queries'][] = compact('type', 'query');
|
||||||
|
|
||||||
|
return $model->find($type, $query);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataRecordsRunningSubtotal(&$params, $model, $pagination) {
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090722
|
||||||
|
// Horrible solution to something that should be done
|
||||||
|
// in SQL. Doesn't really work, but for a grid that contains
|
||||||
|
// ALL records, and is sorted on the correct field, it does
|
||||||
|
// actually work.
|
||||||
|
//
|
||||||
|
// If this function worked correctly, this mechanism would also
|
||||||
|
// work for grids that did not contain ALL records.
|
||||||
|
|
||||||
|
$subtotals = array();
|
||||||
|
foreach ($params['post']['fields'] AS $field) {
|
||||||
|
if (preg_match('/subtotal-(.*)$/', $field, $matches))
|
||||||
|
$subtotals[] = array('field' => $matches[1],
|
||||||
|
'name' => $field,
|
||||||
|
'amount' => 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This part, if functioning, should do a sub-total off all records
|
||||||
|
// that are not part of the grid, instead of starting at zero, so that
|
||||||
|
// the totals come out correctly for the each record entry.
|
||||||
|
|
||||||
|
/* $pagination['start'] = $pagination['start'] + $pagination['limit']; */
|
||||||
|
/* $pagination['limit'] = 10000000; */
|
||||||
|
|
||||||
|
/* // Retreive the appropriate subset of data */
|
||||||
|
/* $params_copy = $params; */
|
||||||
|
/* $records = $this->gridDataRecords($params_copy, $model, $pagination); */
|
||||||
|
|
||||||
|
/* foreach ($records AS &$record) { */
|
||||||
|
/* foreach ($subtotals AS &$subtotal) { */
|
||||||
|
/* $field = $subtotal['field']; */
|
||||||
|
/* if (preg_match("/\./", $field)) { */
|
||||||
|
/* list($tbl, $col) = explode(".", $field); */
|
||||||
|
/* $record['subtotal-'.$tbl][$col] = */
|
||||||
|
/* ($subtotal['amount'] += $record[$tbl][$col]); */
|
||||||
|
/* } */
|
||||||
|
/* else { */
|
||||||
|
/* $record[$model->alias]['subtotal-'.$field] = */
|
||||||
|
/* ($subtotal['amount'] += $record[$model->alias][$field]); */
|
||||||
|
/* } */
|
||||||
|
/* } */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
$params['subtotals'] = $subtotals;
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -623,6 +1115,7 @@ class AppController extends Controller {
|
|||||||
$this->gridDataPostProcessLinks($params, $model, $records, array());
|
$this->gridDataPostProcessLinks($params, $model, $records, array());
|
||||||
|
|
||||||
// DEBUG PURPOSES ONLY!
|
// DEBUG PURPOSES ONLY!
|
||||||
|
//if ($params['debug'])
|
||||||
//$params['records'] = $records;
|
//$params['records'] = $records;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -641,7 +1134,7 @@ class AppController extends Controller {
|
|||||||
foreach ($records AS &$record) {
|
foreach ($records AS &$record) {
|
||||||
// Add the calculated fields (if any), to the model fields
|
// Add the calculated fields (if any), to the model fields
|
||||||
if (isset($record[0])) {
|
if (isset($record[0])) {
|
||||||
$record[$model_alias] += $record[0];
|
$record[$model_alias] = $record[0] + $record[$model_alias];
|
||||||
unset($record[0]);
|
unset($record[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -652,15 +1145,11 @@ class AppController extends Controller {
|
|||||||
|
|
||||||
// REVISIT <AP>: 20090722
|
// REVISIT <AP>: 20090722
|
||||||
// Horrible solution to something that should be done
|
// Horrible solution to something that should be done
|
||||||
// in SQL. But, it works for now, so what the heck...
|
// in SQL. Doesn't really work, but for a grid that contains
|
||||||
|
// ALL records, and is sorted on the correct field, it does
|
||||||
|
// actually work.
|
||||||
|
|
||||||
$subtotals = array();
|
$subtotals = $params['subtotals'];
|
||||||
foreach ($params['post']['fields'] AS $field) {
|
|
||||||
if (preg_match('/subtotal-(.*)$/', $field, $matches))
|
|
||||||
$subtotals[] = array('field' => $matches[1],
|
|
||||||
'name' => $field,
|
|
||||||
'amount' => 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($records AS &$record) {
|
foreach ($records AS &$record) {
|
||||||
foreach ($subtotals AS &$subtotal) {
|
foreach ($subtotals AS &$subtotal) {
|
||||||
@@ -680,12 +1169,15 @@ class AppController extends Controller {
|
|||||||
|
|
||||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
// Don't create any links if ordered not to.
|
// Don't create any links if ordered not to.
|
||||||
if (isset($params['nolinks']))
|
if (isset($params['post']['nolinks']))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
App::import('Helper', 'Html');
|
||||||
|
|
||||||
foreach ($links AS $table => $fields) {
|
foreach ($links AS $table => $fields) {
|
||||||
$special = array('controller', 'id');
|
$special = array('controller', 'action', 'id');
|
||||||
$controller = Inflector::pluralize(Inflector::underscore($table));
|
$controller = Inflector::pluralize(Inflector::underscore($table));
|
||||||
|
$action = 'view';
|
||||||
$id = 'id';
|
$id = 'id';
|
||||||
extract(array_intersect_key($fields, array_flip($special)));
|
extract(array_intersect_key($fields, array_flip($special)));
|
||||||
foreach ($records AS &$record) {
|
foreach ($records AS &$record) {
|
||||||
@@ -697,12 +1189,13 @@ class AppController extends Controller {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// DEBUG PURPOSES ONLY!
|
// DEBUG PURPOSES ONLY!
|
||||||
|
//if ($params['debug'])
|
||||||
//$params['linkrecord'][] = compact('table', 'field', 'id', 'controller', 'record');
|
//$params['linkrecord'][] = compact('table', 'field', 'id', 'controller', 'record');
|
||||||
$record[$table][$field] =
|
$record[$table][$field] =
|
||||||
'<A HREF="' .
|
'<A HREF="' .
|
||||||
Router::url(array('controller' => $controller,
|
HtmlHelper::url(array('controller' => $controller,
|
||||||
'action' => 'view',
|
'action' => $action,
|
||||||
$record[$table][$id])) .
|
$record[$table][$id])) .
|
||||||
'">' .
|
'">' .
|
||||||
$record[$table][$field] .
|
$record[$table][$field] .
|
||||||
'</A>';
|
'</A>';
|
||||||
@@ -727,9 +1220,8 @@ class AppController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function gridDataOutputHeader(&$params, &$model) {
|
function gridDataOutputHeader(&$params, &$model) {
|
||||||
if (!$params['debug']) {
|
if (!$params['debug'])
|
||||||
header("Content-type: text/xml;charset=utf-8");
|
header("Content-type: text/xml;charset=utf-8");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function gridDataOutputXMLHeader(&$params, &$model) {
|
function gridDataOutputXMLHeader(&$params, &$model) {
|
||||||
@@ -745,7 +1237,8 @@ class AppController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function gridDataOutputSummary(&$params, &$model, $pagination) {
|
function gridDataOutputSummary(&$params, &$model, $pagination) {
|
||||||
echo " <params><![CDATA[\n" . print_r($params, true) . "\n]]></params>\n";
|
if ($params['debug'])
|
||||||
|
echo " <params><![CDATA[\n" . print_r($params, true) . "\n]]></params>\n";
|
||||||
echo " <page>{$pagination['page']}</page>\n";
|
echo " <page>{$pagination['page']}</page>\n";
|
||||||
echo " <total>{$pagination['total']}</total>\n";
|
echo " <total>{$pagination['total']}</total>\n";
|
||||||
echo " <records>{$pagination['record_count']}</records>\n";
|
echo " <records>{$pagination['record_count']}</records>\n";
|
||||||
@@ -786,11 +1279,33 @@ class AppController extends Controller {
|
|||||||
|
|
||||||
function gridDataOutputRecordCell(&$params, &$model, &$record, $field, $data) {
|
function gridDataOutputRecordCell(&$params, &$model, &$record, $field, $data) {
|
||||||
// be sure to put text data in CDATA
|
// be sure to put text data in CDATA
|
||||||
if (preg_match("/^\d*$/", $data))
|
if (preg_match("/^[\d.]*$/", $data))
|
||||||
echo " <cell>$data</cell>\n";
|
echo " <cell>$data</cell>\n";
|
||||||
else
|
else
|
||||||
echo " <cell><![CDATA[$data]]></cell>\n";
|
echo " <cell><![CDATA[$data]]></cell>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function authorize($name) {
|
||||||
|
if ($this->Permission->deny($name))
|
||||||
|
$this->UNAUTHORIZED("Unauthorized: $name");
|
||||||
|
}
|
||||||
|
|
||||||
|
function UNAUTHORIZED($msg) {
|
||||||
|
//$this->redirect('controller' => '???', 'action' => 'login');
|
||||||
|
//$this->render('/unauthorized');
|
||||||
|
$this->set('message', '<H2>' . $msg . '</H2>');
|
||||||
|
$this->render_empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
function INTERNAL_ERROR($msg, $depth = 0) {
|
||||||
|
INTERNAL_ERROR($msg, false, $depth+1);
|
||||||
|
$this->render_empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
function render_empty() {
|
||||||
|
echo $this->render('/empty');
|
||||||
|
$this->_stop();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
@@ -37,5 +37,14 @@ App::import('Core', 'Helper');
|
|||||||
* @subpackage cake.cake
|
* @subpackage cake.cake
|
||||||
*/
|
*/
|
||||||
class AppHelper extends Helper {
|
class AppHelper extends Helper {
|
||||||
|
|
||||||
|
function url($url = null, $full = false) {
|
||||||
|
foreach(array('sand_route', 'dev_route') AS $mod) {
|
||||||
|
if (isset($this->params[$mod]) && is_array($url) && !isset($url[$mod]))
|
||||||
|
$url[$mod] = $this->params[$mod];
|
||||||
|
}
|
||||||
|
return parent::url($url, $full);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
@@ -42,6 +42,10 @@ class AppModel extends Model {
|
|||||||
var $useNullForEmpty = true;
|
var $useNullForEmpty = true;
|
||||||
var $formatDateFields = true;
|
var $formatDateFields = true;
|
||||||
|
|
||||||
|
// Loaded related models with no association
|
||||||
|
var $knows = array();
|
||||||
|
var $app_knows = array('Option');
|
||||||
|
|
||||||
// Default Log Level, if not specified at the function level
|
// Default Log Level, if not specified at the function level
|
||||||
var $default_log_level = 5;
|
var $default_log_level = 5;
|
||||||
|
|
||||||
@@ -58,16 +62,35 @@ class AppModel extends Model {
|
|||||||
var $max_log_level;
|
var $max_log_level;
|
||||||
|
|
||||||
|
|
||||||
// REVISIT <AP>: 20090730
|
/**************************************************************************
|
||||||
// Why is this constructor crashing?
|
**************************************************************************
|
||||||
// Clearly it's in some sort of infinite
|
**************************************************************************
|
||||||
// loop, but it seems the correct way
|
* function: __construct
|
||||||
// to have a constructor call the parent...
|
*/
|
||||||
|
|
||||||
|
function __construct($id = false, $table = null, $ds = null) {
|
||||||
|
parent::__construct($id, $table, $ds);
|
||||||
|
|
||||||
|
$this->knows = array_merge($this->app_knows, $this->knows);
|
||||||
|
//$this->pr(1, array('knows' => $this->knows));
|
||||||
|
foreach ($this->knows as $alias => $modelName) {
|
||||||
|
if (is_numeric($alias)) {
|
||||||
|
$alias = $modelName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't overwrite any existing alias
|
||||||
|
if (!empty($this->{$alias}) || get_class($this) == $alias)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$model = array('class' => $modelName, 'alias' => $alias);
|
||||||
|
if (PHP5) {
|
||||||
|
$this->{$alias} = ClassRegistry::init($model);
|
||||||
|
} else {
|
||||||
|
$this->{$alias} =& ClassRegistry::init($model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* function __construct() { */
|
|
||||||
/* parent::__construct(); */
|
|
||||||
/* $this->prClassLevel(5, 'Model'); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -81,7 +104,8 @@ class AppModel extends Model {
|
|||||||
$caller = array_shift($trace);
|
$caller = array_shift($trace);
|
||||||
$caller = array_shift($trace);
|
$caller = array_shift($trace);
|
||||||
if (empty($class))
|
if (empty($class))
|
||||||
$class = $caller['class'];
|
$class = get_class($this);
|
||||||
|
$this->pr(50, compact('class', 'level'));
|
||||||
$this->class_log_level[$class] = $level;
|
$this->class_log_level[$class] = $level;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,9 +114,10 @@ class AppModel extends Model {
|
|||||||
$caller = array_shift($trace);
|
$caller = array_shift($trace);
|
||||||
$caller = array_shift($trace);
|
$caller = array_shift($trace);
|
||||||
if (empty($class))
|
if (empty($class))
|
||||||
$class = $caller['class'];
|
$class = get_class($this);
|
||||||
if (empty($function))
|
if (empty($function))
|
||||||
$function = $caller['function'];
|
$function = $caller['function'];
|
||||||
|
$this->pr(50, compact('class', 'function', 'level'));
|
||||||
$this->function_log_level["{$class}-{$function}"] = $level;
|
$this->function_log_level["{$class}-{$function}"] = $level;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,20 +139,48 @@ class AppModel extends Model {
|
|||||||
$line = $caller['line'];
|
$line = $caller['line'];
|
||||||
|
|
||||||
// So, this caller holds the calling function name
|
// So, this caller holds the calling function name
|
||||||
$caller = array_shift($trace);
|
$caller = $trace[0];
|
||||||
$function = $caller['function'];
|
$function = $caller['function'];
|
||||||
$class = $caller['class'];
|
$class = $caller['class'];
|
||||||
//$class = $this->name;
|
//$class = $this->name;
|
||||||
|
|
||||||
// Adjust the log level from default, if necessary
|
// Use class or function specific log level if available
|
||||||
if (isset($this->class_log_level[$class]))
|
if (isset($this->class_log_level[$class]))
|
||||||
$log_level = $this->class_log_level[$class];
|
$log_level = $this->class_log_level[$class];
|
||||||
if (isset($this->function_log_level["{$class}-{$function}"]))
|
if (isset($this->function_log_level["{$class}-{$function}"]))
|
||||||
$log_level = $this->function_log_level["{$class}-{$function}"];
|
$log_level = $this->function_log_level["{$class}-{$function}"];
|
||||||
if (isset($this->min_log_level))
|
|
||||||
$log_level = max($log_level, $this->min_log_level);
|
// Establish log level minimums
|
||||||
if (isset($this->max_log_level))
|
$min_log_level = $this->min_log_level;
|
||||||
$log_level = min($log_level, $this->max_log_level);
|
if (is_array($this->min_log_level)) {
|
||||||
|
$min_show_level = $min_log_level['show'];
|
||||||
|
$min_log_level = $min_log_level['log'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Establish log level maximums
|
||||||
|
$max_log_level = $this->max_log_level;
|
||||||
|
if (is_array($this->max_log_level)) {
|
||||||
|
$max_show_level = $max_log_level['show'];
|
||||||
|
$max_log_level = $max_log_level['log'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the applicable log and show levels
|
||||||
|
if (is_array($log_level)) {
|
||||||
|
$show_level = $log_level['show'];
|
||||||
|
$log_level = $log_level['log'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust log level up/down to min/max
|
||||||
|
if (isset($min_log_level))
|
||||||
|
$log_level = max($log_level, $min_log_level);
|
||||||
|
if (isset($max_log_level))
|
||||||
|
$log_level = min($log_level, $max_log_level);
|
||||||
|
|
||||||
|
// Adjust show level up/down to min/max
|
||||||
|
if (isset($min_show_level))
|
||||||
|
$show_level = max($show_level, $min_show_level);
|
||||||
|
if (isset($max_show_level))
|
||||||
|
$show_level = min($show_level, $max_show_level);
|
||||||
|
|
||||||
// If the level is insufficient, bail out
|
// If the level is insufficient, bail out
|
||||||
if ($level > $log_level)
|
if ($level > $log_level)
|
||||||
@@ -141,13 +194,87 @@ class AppModel extends Model {
|
|||||||
$mixed = $chk + array($mixed);
|
$mixed = $chk + array($mixed);
|
||||||
}
|
}
|
||||||
|
|
||||||
echo '<DIV CLASS="pr-caller">';
|
static $pr_unique_number = 0;
|
||||||
echo '<strong>' . substr(str_replace(ROOT, '', $file), 1) . '</strong>';
|
$pr_id = 'pr-section-class-' . $class . '-print-' . (++$pr_unique_number);
|
||||||
echo ' (line <strong>' . $line . '</strong>)';
|
$pr_trace_id = $pr_id . '-trace';
|
||||||
echo ' : level-' . $level;
|
$pr_output_id = $pr_id . '-output';
|
||||||
echo '</DIV>' . "\n";
|
|
||||||
|
|
||||||
pr(array("{$class}::{$function}()" => $mixed), false, false);
|
$pr_entire_base_class = "pr-section";
|
||||||
|
$pr_entire_class_class = $pr_entire_base_class . '-class-' . $class;
|
||||||
|
$pr_entire_function_class = $pr_entire_class_class . '-function-' . $function;
|
||||||
|
$pr_entire_class = "$pr_entire_base_class $pr_entire_class_class $pr_entire_function_class";
|
||||||
|
$pr_header_class = "pr-caller";
|
||||||
|
$pr_trace_class = "pr-trace";
|
||||||
|
$pr_output_base_class = 'pr-output';
|
||||||
|
$pr_output_class_class = $pr_output_base_class . '-class-' . $class;
|
||||||
|
$pr_output_function_class = $pr_output_class_class . '-function-' . $function;
|
||||||
|
$pr_output_class = "$pr_output_base_class $pr_output_class_class $pr_output_function_class";
|
||||||
|
|
||||||
|
echo '<DIV class="'.$pr_entire_class.'" id="'.$pr_id.'">'."\n";
|
||||||
|
echo '<DIV class="'.$pr_header_class.'">'."\n";
|
||||||
|
echo '<DIV class="'.$pr_trace_class.'" id="'.$pr_trace_id.'" style="display:none;">'."\n";
|
||||||
|
echo '<HR />' . "\n";
|
||||||
|
|
||||||
|
// Flip trace around so the sequence flows from top to bottom
|
||||||
|
// Then print out the entire stack trace (in hidden div)
|
||||||
|
$trace = array_reverse($trace);
|
||||||
|
for ($i = 0; $i < count($trace); ++$i) {
|
||||||
|
$bline = $trace[$i]['line'];
|
||||||
|
$bfile = $trace[$i]['file'];
|
||||||
|
$bfile = str_replace(ROOT.DS, '', $bfile);
|
||||||
|
$bfile = str_replace(CAKE_CORE_INCLUDE_PATH.DS, '', $bfile);
|
||||||
|
|
||||||
|
if ($i > 0) {
|
||||||
|
$bfunc = $trace[$i-1]['function'];
|
||||||
|
$bclas = $trace[$i-1]['class'];
|
||||||
|
} else {
|
||||||
|
$bfunc = null;
|
||||||
|
$bclas = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo("$bfile:$bline (" . ($bclas ? "$bclas::$bfunc" : "entry point") . ")<BR>\n");
|
||||||
|
//echo(($bclas ? "$bclas::$bfunc" : "entry point") . "; $bfile : $bline<BR>\n");
|
||||||
|
}
|
||||||
|
echo '</DIV>' . "\n"; // End pr_trace_class
|
||||||
|
$file = str_replace(ROOT.DS, '', $file);
|
||||||
|
$file = str_replace(CAKE_CORE_INCLUDE_PATH.DS, '', $file);
|
||||||
|
|
||||||
|
echo "<strong>$file:$line ($class::$function)</strong>" . ";\n";
|
||||||
|
/* $log_show_level = isset($show_level) ? $show_level : '?'; */
|
||||||
|
/* echo ' L' . $level . "({$log_level}/{$log_show_level})" . ";\n"; */
|
||||||
|
echo ' L' . $level . ";\n";
|
||||||
|
echo ' <A HREF="#" onclick="$' . "('#{$pr_trace_id}').slideToggle(); return false;" . '">stack</A>'.";\n";
|
||||||
|
|
||||||
|
echo " this ";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('#{$pr_output_id}').slideToggle(); return false;" . '">t</A>'."/";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('#{$pr_id}').hide(); return false;" . '">n</A>'.";\n";
|
||||||
|
|
||||||
|
echo " $class ";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('.{$pr_output_class_class}').slideDown(); return false;" . '">s</A>'."/";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('.{$pr_output_class_class}').slideUp(); return false;" . '">h</A>'."/";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('.{$pr_entire_class_class}').hide(); return false;" . '">n</A>'.";\n";
|
||||||
|
|
||||||
|
echo " $function ";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('.{$pr_output_function_class}').slideDown(); return false;" . '">s</A>'."/";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('.{$pr_output_function_class}').slideUp(); return false;" . '">h</A>'."/";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('.{$pr_entire_function_class}').hide(); return false;" . '">n</A>'.";\n";
|
||||||
|
|
||||||
|
echo " all ";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('.{$pr_output_base_class}').show(); return false;" . '">s</A>'."/";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('.{$pr_output_base_class}').hide(); return false;" . '">h</A>'."/";
|
||||||
|
echo '<A HREF="#" onclick="$' . "('.{$pr_entire_base_class}').hide(); return false;" . '">n</A>'."\n";
|
||||||
|
|
||||||
|
echo '</DIV>' . "\n"; // End pr_header_class
|
||||||
|
|
||||||
|
if (isset($show_level) && $level > $show_level)
|
||||||
|
$display = 'none';
|
||||||
|
else
|
||||||
|
$display = 'block';
|
||||||
|
|
||||||
|
echo '<DIV class="'.$pr_output_class.'" id="'.$pr_output_id.'" style="display:'.$display.';">'."\n";
|
||||||
|
pr($mixed, false, false);
|
||||||
|
echo '</DIV>' . "\n"; // End pr_output_class
|
||||||
|
echo '</DIV>' . "\n"; // End pr_entire_class
|
||||||
}
|
}
|
||||||
|
|
||||||
function pr($level, $mixed, $checkpoint = null) {
|
function pr($level, $mixed, $checkpoint = null) {
|
||||||
@@ -178,7 +305,9 @@ class AppModel extends Model {
|
|||||||
if (preg_match("/^_/", $name) && !$all)
|
if (preg_match("/^_/", $name) && !$all)
|
||||||
unset($vars[$name]);
|
unset($vars[$name]);
|
||||||
}
|
}
|
||||||
pr($vars);
|
//$vars['class'] = get_class_vars(get_class($this));
|
||||||
|
|
||||||
|
$this->pr(1, $vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -300,6 +429,10 @@ class AppModel extends Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function filter_null($array) {
|
||||||
|
return array_diff_key($array, array_filter($array, 'is_null'));
|
||||||
|
}
|
||||||
|
|
||||||
function recursive_array_replace($find, $replace, &$data) {
|
function recursive_array_replace($find, $replace, &$data) {
|
||||||
if (!isset($data))
|
if (!isset($data))
|
||||||
return;
|
return;
|
||||||
@@ -374,4 +507,12 @@ class AppModel extends Model {
|
|||||||
return date('Y-m-d', strtotime($dateString));
|
return date('Y-m-d', strtotime($dateString));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function INTERNAL_ERROR($msg, $depth = 0, $force_stop = false) {
|
||||||
|
INTERNAL_ERROR($msg, $force_stop, $depth+1);
|
||||||
|
echo $this->requestAction(array('controller' => 'util',
|
||||||
|
'action' => 'render_empty'),
|
||||||
|
array('return', 'bare' => false)
|
||||||
|
);
|
||||||
|
$this->_stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,99 @@
|
|||||||
* You can also use this to include or require any files in your application.
|
* You can also use this to include or require any files in your application.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
function _box($type) {
|
||||||
|
static $box = array('type' => null, 'test' => array());
|
||||||
|
if (!isset($box['type']) && !isset($box['test'][$type])) {
|
||||||
|
$r = Router::requestRoute();
|
||||||
|
/* if (!preg_match("/gridData/", $_SERVER['REQUEST_URI'])) { */
|
||||||
|
/* print("<PRE>Route:\n");print_r($r);print("\n</PRE>\n"); */
|
||||||
|
/* } */
|
||||||
|
$box['test'][$type] = !empty($r[3]["${type}_route"]);
|
||||||
|
if ($box['test'][$type])
|
||||||
|
$box['type'] = $type;
|
||||||
|
}
|
||||||
|
return $box['type'] == $type;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sandbox() { return _box('sand'); }
|
||||||
|
function devbox() { return _box('dev'); }
|
||||||
|
|
||||||
|
function server_request_var($var) {
|
||||||
|
if (preg_match("/^HTTP_ACCEPT|REMOTE_PORT/", $var))
|
||||||
|
return false;
|
||||||
|
return (preg_match("/^HTTP|REQUEST|REMOTE/", $var));
|
||||||
|
}
|
||||||
|
|
||||||
|
function INTERNAL_ERROR($message, $exit = true, $drop = 0) {
|
||||||
|
$O = new Object();
|
||||||
|
for ($i=0; $i<3; ++$i) {
|
||||||
|
$O->log(str_repeat("\\", 80));
|
||||||
|
$O->log(str_repeat("/", 80));
|
||||||
|
}
|
||||||
|
$O->log("INTERNAL ERROR: $message");
|
||||||
|
echo '<DIV class="internal-error" style="color:#000; background:#c22; padding:0.5em 1.5em 0.5em 1.5em;">' . "\n";
|
||||||
|
echo '<H1 style="color:#000; margin-bottom:0.2em; font-size:2em;">INTERNAL ERROR:</H1>' . "\n";
|
||||||
|
echo '<H2 style="color:#000; margin-top:0; margin-left:1.5em; font-size:1.5em">' . $message . '</H2>' . "\n";
|
||||||
|
echo '<H4 style="color:#000;">This error was not caused by anything that you did wrong.' . "\n";
|
||||||
|
echo '<BR>It is a problem within the application itself and should be reported to the administrator.</H4>' . "\n";
|
||||||
|
|
||||||
|
// Print out the entire stack trace
|
||||||
|
$O->log(str_repeat("-", 30));
|
||||||
|
$O->log("Stack:");
|
||||||
|
echo '<HR style="margin-top:1.0em; margin-bottom:0.5em;">' . "\nStack Trace:\n";
|
||||||
|
echo '<OL style="margin-top:0.5em; margin-left:0.0em";>' . "\n";
|
||||||
|
$trace = array_slice(debug_backtrace(false), $drop);
|
||||||
|
for ($i = 0; $i < count($trace); ++$i) {
|
||||||
|
$bline = $trace[$i]['line'];
|
||||||
|
$bfile = $trace[$i]['file'];
|
||||||
|
$bfile = str_replace(ROOT.DS, '', $bfile);
|
||||||
|
$bfile = str_replace(CAKE_CORE_INCLUDE_PATH.DS, '', $bfile);
|
||||||
|
|
||||||
|
if ($i < count($trace)-1) {
|
||||||
|
$bfunc = $trace[$i+1]['function'];
|
||||||
|
$bclas = $trace[$i+1]['class'];
|
||||||
|
} else {
|
||||||
|
$bfunc = null;
|
||||||
|
$bclas = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$O->log(" $bfile:$bline (" . ($bclas ? "$bclas::$bfunc" : "entry point") . ")");
|
||||||
|
echo("<LI>$bfile:$bline (" . ($bclas ? "$bclas::$bfunc" : "entry point") . ")</LI>\n");
|
||||||
|
}
|
||||||
|
echo "</OL>\n";
|
||||||
|
|
||||||
|
$O->log(str_repeat("-", 30));
|
||||||
|
$O->log("HTTP Request:");
|
||||||
|
echo '<HR style="margin-top:1.0em; margin-bottom:0.5em;">' . "\nHTTP Request:\n";
|
||||||
|
echo '<UL style="margin-top:0.5em; margin-left:0.0em";>' . "\n";
|
||||||
|
foreach($_REQUEST AS $k => $v) {
|
||||||
|
$O->log(sprintf(" %-20s => %s", $k, $v));
|
||||||
|
echo("<LI>$k => $v</LI>\n");
|
||||||
|
}
|
||||||
|
echo "</UL>\n";
|
||||||
|
|
||||||
|
$O->log(str_repeat("-", 30));
|
||||||
|
$O->log("Server:");
|
||||||
|
$SRV = array_intersect_key($_SERVER, array_flip(array_filter(array_keys($_SERVER), 'server_request_var')));
|
||||||
|
echo '<HR style="margin-top:1.0em; margin-bottom:0.5em;">' . "\nServer:\n";
|
||||||
|
echo '<UL style="margin-top:0.5em; margin-left:0.0em";>' . "\n";
|
||||||
|
foreach($SRV AS $k => $v) {
|
||||||
|
if ($k == 'REQUEST_TIME')
|
||||||
|
$v = date('c', $v);
|
||||||
|
$O->log(sprintf(" %-20s => %s", $k, $v));
|
||||||
|
echo("<LI>$k => $v</LI>\n");
|
||||||
|
}
|
||||||
|
echo "</UL>\n";
|
||||||
|
|
||||||
|
echo '<HR style="margin-top:1.0em; margin-bottom:0.5em;">' . "\n";
|
||||||
|
echo date('c') . "<BR>\n";
|
||||||
|
|
||||||
|
echo '</DIV>';
|
||||||
|
if ($exit)
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The settings below can be used to set additional paths to models, views and controllers.
|
* 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)
|
* This is related to Ticket #470 (https://trac.cakephp.org/ticket/470)
|
||||||
|
|||||||
@@ -117,7 +117,7 @@
|
|||||||
/**
|
/**
|
||||||
* The name of CakePHP's session cookie.
|
* The name of CakePHP's session cookie.
|
||||||
*/
|
*/
|
||||||
Configure::write('Session.cookie', 'CAKEPHP');
|
Configure::write('Session.cookie', 'PMGR');
|
||||||
/**
|
/**
|
||||||
* Session time out time (in seconds).
|
* Session time out time (in seconds).
|
||||||
* Actual value depends on 'Security.level' setting.
|
* Actual value depends on 'Security.level' setting.
|
||||||
|
|||||||
@@ -5,10 +5,17 @@ class DATABASE_CONFIG {
|
|||||||
'driver' => 'mysql',
|
'driver' => 'mysql',
|
||||||
'persistent' => false,
|
'persistent' => false,
|
||||||
'host' => 'localhost',
|
'host' => 'localhost',
|
||||||
'login' => 'pmgr',
|
'login' => 'perki2_pmgruser',
|
||||||
'password' => 'pmgruser',
|
'password' => 'pmgrauth',
|
||||||
'database' => 'property_manager',
|
'database' => 'perki2_pmgr',
|
||||||
'prefix' => 'pmgr_',
|
'prefix' => '',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
function __construct() {
|
||||||
|
if (devbox())
|
||||||
|
$this->default['database'] = 'perki2_pmgr_dev';
|
||||||
|
if (sandbox())
|
||||||
|
$this->default['database'] = 'perki2_pmgr_sand';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
@@ -27,11 +27,49 @@
|
|||||||
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
$default_path = array('controller' => 'maps', 'action' => 'view', '1');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Here, we are connecting '/' (base path) to our site map.
|
* Here, we are connecting '/' (base path) to our site map.
|
||||||
* It's hardcoded to map #1, but at some point we'll implement
|
* It's hardcoded to map #1, but at some point we'll implement
|
||||||
* a login mechanism and the default path will be to log on instead.
|
* a login mechanism and the default path will be to log on instead.
|
||||||
*/
|
*/
|
||||||
Router::connect('/', array('controller' => 'maps', 'action' => 'view', '1'));
|
Router::connect('/', $default_path);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Route for sandbox functionality
|
||||||
|
*/
|
||||||
|
Router::connect('/sand',
|
||||||
|
array('sand_route' => true) + $default_path);
|
||||||
|
Router::connect('/sand/:controller/:action/*',
|
||||||
|
array('sand_route' => true, 'action' => null));
|
||||||
|
/* Unfortunately, for some reason we need an extra route to solve
|
||||||
|
* a bug with form generation. When $this->data is set by the
|
||||||
|
* controller, and a URL is generated by the FormHelper, this
|
||||||
|
* route is required to ensure the form action is correct. An
|
||||||
|
* example of a broken page is for /customers/edit/XX. It appears
|
||||||
|
* the page location uses the route above, it's only URL generation
|
||||||
|
* that seems to be broken.
|
||||||
|
*/
|
||||||
|
Router::connect('/sand/:controller/:action/:id/*',
|
||||||
|
array('sand_route' => true,'action' => null, 'id'=>null));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Route for developement functionality
|
||||||
|
*/
|
||||||
|
Router::connect('/dev',
|
||||||
|
array('dev_route' => true) + $default_path);
|
||||||
|
Router::connect('/dev/:controller/:action/*',
|
||||||
|
array('dev_route' => true, 'action' => null));
|
||||||
|
/* Unfortunately, for some reason we need an extra route to solve
|
||||||
|
* a bug with form generation. When $this->data is set by the
|
||||||
|
* controller, and a URL is generated by the FormHelper, this
|
||||||
|
* route is required to ensure the form action is correct. An
|
||||||
|
* example of a broken page is for /customers/edit/XX. It appears
|
||||||
|
* the page location uses the route above, it's only URL generation
|
||||||
|
* that seems to be broken.
|
||||||
|
*/
|
||||||
|
Router::connect('/dev/:controller/:action/:id/*',
|
||||||
|
array('dev_route' => true,'action' => null, 'id'=>null));
|
||||||
|
|
||||||
?>
|
?>
|
||||||
@@ -2,33 +2,38 @@
|
|||||||
|
|
||||||
class AccountsController extends AppController {
|
class AccountsController extends AppController {
|
||||||
|
|
||||||
var $uses = array('Account', 'LedgerEntry');
|
|
||||||
|
|
||||||
var $sidemenu_links =
|
|
||||||
array(array('name' => 'Accounts', 'header' => true),
|
|
||||||
array('name' => 'All', 'url' => array('controller' => 'accounts', 'action' => 'all')),
|
|
||||||
array('name' => 'Asset', 'url' => array('controller' => 'accounts', 'action' => 'asset')),
|
|
||||||
array('name' => 'Liability', 'url' => array('controller' => 'accounts', 'action' => 'liability')),
|
|
||||||
array('name' => 'Equity', 'url' => array('controller' => 'accounts', 'action' => 'equity')),
|
|
||||||
array('name' => 'Income', 'url' => array('controller' => 'accounts', 'action' => 'income')),
|
|
||||||
array('name' => 'Expense', 'url' => array('controller' => 'accounts', 'action' => 'expense')),
|
|
||||||
array('name' => 'Deposits', 'header' => true),
|
|
||||||
array('name' => 'Prior Deposits', 'url' => array('controller' => 'transactions', 'action' => 'deposit')),
|
|
||||||
array('name' => 'New Deposit', 'url' => array('controller' => 'tenders', 'action' => 'deposit')),
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* override: sideMenuLinks
|
* override: addGridViewSideMenuLinks
|
||||||
* - Generates controller specific links for the side menu
|
* - Adds grid view navigation side menu links
|
||||||
*/
|
*/
|
||||||
function sideMenuLinks() {
|
|
||||||
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
function addGridViewSideMenuLinks() {
|
||||||
|
parent::addGridViewSideMenuLinks();
|
||||||
|
|
||||||
|
$this->addSideMenuLink('Asset',
|
||||||
|
array('controller' => 'accounts', 'action' => 'asset'), null,
|
||||||
|
'CONTROLLER', $this->admin_area);
|
||||||
|
$this->addSideMenuLink('Liability',
|
||||||
|
array('controller' => 'accounts', 'action' => 'liability'), null,
|
||||||
|
'CONTROLLER', $this->admin_area);
|
||||||
|
$this->addSideMenuLink('Equity',
|
||||||
|
array('controller' => 'accounts', 'action' => 'equity'), null,
|
||||||
|
'CONTROLLER', $this->admin_area);
|
||||||
|
$this->addSideMenuLink('Income',
|
||||||
|
array('controller' => 'accounts', 'action' => 'income'), null,
|
||||||
|
'CONTROLLER', $this->admin_area);
|
||||||
|
$this->addSideMenuLink('Expense',
|
||||||
|
array('controller' => 'accounts', 'action' => 'expense'), null,
|
||||||
|
'CONTROLLER', $this->admin_area);
|
||||||
|
$this->addSideMenuLink('All',
|
||||||
|
array('controller' => 'accounts', 'action' => 'all'), null,
|
||||||
|
'CONTROLLER', $this->admin_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -42,7 +47,7 @@ class AccountsController extends AppController {
|
|||||||
function equity() { $this->gridView('Equity Accounts'); }
|
function equity() { $this->gridView('Equity Accounts'); }
|
||||||
function income() { $this->gridView('Income Accounts'); }
|
function income() { $this->gridView('Income Accounts'); }
|
||||||
function expense() { $this->gridView('Expense Accounts'); }
|
function expense() { $this->gridView('Expense Accounts'); }
|
||||||
function all() { $this->gridView('All Accounts', 'all'); }
|
function all() { $this->gridView('All Accounts', 'all'); }
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
@@ -93,6 +98,9 @@ class AccountsController extends AppController {
|
|||||||
$conditions[] = array('Account.type' => strtoupper($params['action']));
|
$conditions[] = array('Account.type' => strtoupper($params['action']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$conditions[] = array('Account.level >=' =>
|
||||||
|
$this->Permission->level('controller.accounts'));
|
||||||
|
|
||||||
return $conditions;
|
return $conditions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,17 +146,15 @@ class AccountsController extends AppController {
|
|||||||
$this->redirect(array('action'=>'index'));
|
$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->paymentAccounts(),
|
|
||||||
array($this->Account->concessionAccountID() => 1));
|
|
||||||
$this->set(compact('payment_accounts', 'default_accounts'));
|
|
||||||
|
|
||||||
$this->Account->recursive = -1;
|
$this->Account->recursive = -1;
|
||||||
$account = $this->Account->read(null, $id);
|
$account = $this->Account->read(null, $id);
|
||||||
$account = $account['Account'];
|
$account = $account['Account'];
|
||||||
|
|
||||||
|
$accounts = $this->Account->collectableAccounts();
|
||||||
|
$payment_accounts = $accounts['all'];
|
||||||
|
$default_accounts = $accounts['default'];
|
||||||
|
$this->set(compact('payment_accounts', 'default_accounts'));
|
||||||
|
|
||||||
$title = ($account['name'] . ': Collected Report');
|
$title = ($account['name'] . ': Collected Report');
|
||||||
$this->set(compact('account', 'title'));
|
$this->set(compact('account', 'title'));
|
||||||
}
|
}
|
||||||
@@ -162,12 +168,6 @@ class AccountsController extends AppController {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function view($id = null) {
|
function view($id = null) {
|
||||||
if (!$id) {
|
|
||||||
$this->Session->setFlash(__('Invalid Item.', true));
|
|
||||||
$this->redirect(array('action'=>'index'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get details about the account and its ledgers (no ledger entries yet)
|
|
||||||
$account = $this->Account->find
|
$account = $this->Account->find
|
||||||
('first',
|
('first',
|
||||||
array('contain' =>
|
array('contain' =>
|
||||||
@@ -179,33 +179,32 @@ class AccountsController extends AppController {
|
|||||||
array('CloseTransaction' => array
|
array('CloseTransaction' => array
|
||||||
('order' => array('CloseTransaction.stamp' => 'DESC'))),
|
('order' => array('CloseTransaction.stamp' => 'DESC'))),
|
||||||
),
|
),
|
||||||
'conditions' => array(array('Account.id' => $id)),
|
'conditions' => array(array('Account.id' => $id),
|
||||||
|
array('Account.level >=' =>
|
||||||
|
$this->Permission->level('controller.accounts')),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Get all ledger entries of the CURRENT ledger
|
if (empty($account)) {
|
||||||
$entries = $this->Account->ledgerEntries($id);
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
//pr(compact('entries'));
|
$this->redirect(array('action'=>'index'));
|
||||||
$account['CurrentLedger']['LedgerEntry'] = $entries;
|
}
|
||||||
|
|
||||||
// Obtain stats across ALL ledgers for the summary infobox
|
// Obtain stats across ALL ledgers for the summary infobox
|
||||||
$stats = $this->Account->stats($id, true);
|
$stats = $this->Account->stats($id, true);
|
||||||
$stats = $stats['Ledger'];
|
$stats = $stats['Ledger'];
|
||||||
|
|
||||||
$this->sidemenu_links[] =
|
$this->addSideMenuLink('New Ledger',
|
||||||
array('name' => 'Operations', 'header' => true);
|
array('action' => 'newledger', $id), null,
|
||||||
$this->sidemenu_links[] =
|
'ACTION', $this->admin_area);
|
||||||
array('name' => 'New Ledger', 'url' => array('action' => 'newledger', $id));
|
$this->addSideMenuLink('Collected',
|
||||||
$this->sidemenu_links[] =
|
array('action' => 'collected', $id), null,
|
||||||
array('name' => 'Collected', 'url' => array('action' => 'collected', $id));
|
'ACTION', $this->admin_area);
|
||||||
|
|
||||||
// Prepare to render
|
// Prepare to render
|
||||||
$title = 'Account: ' . $account['Account']['name'];
|
$title = 'Account: ' . $account['Account']['name'];
|
||||||
$this->set(compact('account', 'title', 'stats'));
|
$this->set(compact('account', 'title', 'stats'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function tst($id) {
|
|
||||||
//$entries = $this->Account->($id);
|
|
||||||
pr($entries);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,19 +2,7 @@
|
|||||||
|
|
||||||
class ContactsController extends AppController {
|
class ContactsController extends AppController {
|
||||||
|
|
||||||
var $sidemenu_links = array();
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* override: sideMenuLinks
|
|
||||||
* - Generates controller specific links for the side menu
|
|
||||||
*/
|
|
||||||
function sideMenuLinks() {
|
|
||||||
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -35,19 +23,34 @@ class ContactsController extends AppController {
|
|||||||
* to jqGrid.
|
* to jqGrid.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
function gridDataFilterTablesConfig(&$params, &$model, $table) {
|
||||||
|
$config = parent::gridDataFilterTablesConfig($params, $model, $table);
|
||||||
|
|
||||||
|
// Special case for Customer; We need the Contact/Customer relationship
|
||||||
|
if ($table == 'Customer')
|
||||||
|
$config = array('fields' => array('ContactsCustomer.type',
|
||||||
|
'ContactsCustomer.active'),
|
||||||
|
'conditions' => array('ContactsCustomer.active' => true),
|
||||||
|
);
|
||||||
|
|
||||||
|
return $config;
|
||||||
|
}
|
||||||
|
|
||||||
function gridDataOrder(&$params, &$model, $index, $direction) {
|
function gridDataOrder(&$params, &$model, $index, $direction) {
|
||||||
$order = parent::gridDataOrder($params, $model, $index, $direction);
|
$order = parent::gridDataOrder($params, $model, $index, $direction);
|
||||||
if ($index === 'Contact.last_name') {
|
|
||||||
$order[] = 'Contact.first_name ' . $direction;
|
// After sorting by whatever the user wants, add these
|
||||||
}
|
// defaults into the sort mechanism. If we're already
|
||||||
if ($index === 'Contact.first_name') {
|
// sorting by one of them, it will only be redundant,
|
||||||
$order[] = 'Contact.last_name ' . $direction;
|
// and should cause no harm (possible a longer query?)
|
||||||
}
|
$order[] = 'Contact.last_name ' . $direction;
|
||||||
|
$order[] = 'Contact.first_name ' . $direction;
|
||||||
|
|
||||||
return $order;
|
return $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
$links['Contact'] = array('id');
|
$links['Contact'] = array('display_name');
|
||||||
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,13 +81,9 @@ class ContactsController extends AppController {
|
|||||||
));
|
));
|
||||||
|
|
||||||
// Set up dynamic menu items
|
// Set up dynamic menu items
|
||||||
$this->sidemenu_links[] =
|
$this->addSideMenuLink('Edit',
|
||||||
array('name' => 'Operations', 'header' => true);
|
array('action' => 'edit', $id), null,
|
||||||
|
'ACTION');
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Edit',
|
|
||||||
'url' => array('action' => 'edit',
|
|
||||||
$id));
|
|
||||||
|
|
||||||
// Prepare to render.
|
// Prepare to render.
|
||||||
$title = 'Contact: ' . $contact['Contact']['display_name'];
|
$title = 'Contact: ' . $contact['Contact']['display_name'];
|
||||||
@@ -126,8 +125,6 @@ class ContactsController extends AppController {
|
|||||||
|
|
||||||
// Now that the work is done, let the user view the updated contact
|
// Now that the work is done, let the user view the updated contact
|
||||||
$this->redirect(array('action'=>'view', $this->data['Contact']['id']));
|
$this->redirect(array('action'=>'view', $this->data['Contact']['id']));
|
||||||
//$this->render('/empty');
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($id) {
|
if ($id) {
|
||||||
|
|||||||
@@ -1,28 +1,42 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class CustomersController extends AppController {
|
class CustomersController extends AppController {
|
||||||
var $sidemenu_links =
|
|
||||||
array(array('name' => 'Customers', 'header' => true),
|
|
||||||
array('name' => 'Current', 'url' => array('controller' => 'customers', 'action' => 'current')),
|
|
||||||
array('name' => 'Past', 'url' => array('controller' => 'customers', 'action' => 'past')),
|
|
||||||
array('name' => 'All', 'url' => array('controller' => 'customers', 'action' => 'all')),
|
|
||||||
array('name' => 'Add Customer', 'url' => array('controller' => 'customers', 'action' => 'add')),
|
|
||||||
);
|
|
||||||
|
|
||||||
//var $components = array('RequestHandler');
|
var $components = array('RequestHandler');
|
||||||
|
|
||||||
|
// DEBUG FUNCTION ONLY!
|
||||||
|
// Call without id to update ALL customers
|
||||||
|
function force_update($id = null) {
|
||||||
|
$this->Customer->update($id);
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* override: sideMenuLinks
|
* override: addGridViewSideMenuLinks
|
||||||
* - Generates controller specific links for the side menu
|
* - Adds grid view navigation side menu links
|
||||||
*/
|
*/
|
||||||
function sideMenuLinks() {
|
|
||||||
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
function addGridViewSideMenuLinks() {
|
||||||
|
parent::addGridViewSideMenuLinks();
|
||||||
|
|
||||||
|
$this->addSideMenuLink('Current',
|
||||||
|
array('controller' => 'customers', 'action' => 'current'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('Past',
|
||||||
|
array('controller' => 'customers', 'action' => 'past'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('All',
|
||||||
|
array('controller' => 'customers', 'action' => 'all'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
|
||||||
|
/* $this->addSideMenuLink('New Customer', */
|
||||||
|
/* array('controller' => 'customers', 'action' => 'add'), null, */
|
||||||
|
/* 'CONTROLLER', $this->new_area); */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -50,7 +64,6 @@ class CustomersController extends AppController {
|
|||||||
('link' =>
|
('link' =>
|
||||||
array(// Models
|
array(// Models
|
||||||
'PrimaryContact',
|
'PrimaryContact',
|
||||||
'CurrentLease' => array('fields' => array()),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -64,63 +77,49 @@ class CustomersController extends AppController {
|
|||||||
|
|
||||||
function gridDataFields(&$params, &$model) {
|
function gridDataFields(&$params, &$model) {
|
||||||
$fields = parent::gridDataFields($params, $model);
|
$fields = parent::gridDataFields($params, $model);
|
||||||
$fields[] = ('COUNT(DISTINCT CurrentLease.id) AS lease_count');
|
|
||||||
return array_merge($fields,
|
return array_merge($fields,
|
||||||
$this->Customer->StatementEntry->chargePaymentFields(true));
|
$this->Customer->StatementEntry->chargeDisbursementFields(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
function gridDataConditions(&$params, &$model) {
|
function gridDataConditions(&$params, &$model) {
|
||||||
$conditions = parent::gridDataConditions($params, $model);
|
$conditions = parent::gridDataConditions($params, $model);
|
||||||
|
|
||||||
if ($params['action'] === 'current') {
|
if ($params['action'] === 'current') {
|
||||||
$conditions[] = 'CurrentLease.id IS NOT NULL';
|
$conditions[] = array('Customer.current_lease_count >' => 0);
|
||||||
}
|
}
|
||||||
elseif ($params['action'] === 'past') {
|
elseif ($params['action'] === 'past') {
|
||||||
$conditions[] = 'CurrentLease.id IS NULL';
|
$conditions[] = array('Customer.current_lease_count' => 0);
|
||||||
|
$conditions[] = array('Customer.past_lease_count >' => 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $conditions;
|
return $conditions;
|
||||||
}
|
}
|
||||||
|
|
||||||
function gridDataOrder(&$params, &$model, $index, $direction) {
|
function gridDataFilterTablesConfig(&$params, &$model, $table) {
|
||||||
$order = array();
|
$config = parent::gridDataFilterTablesConfig($params, $model, $table);
|
||||||
$order[] = parent::gridDataOrder($params, $model, $index, $direction);
|
|
||||||
|
|
||||||
if ($index !== 'PrimaryContact.last_name')
|
// Special case for Contact; We need the Contact/Customer relationship
|
||||||
$order[] = parent::gridDataOrder($params, $model,
|
if ($table == 'Contact')
|
||||||
'PrimaryContact.last_name', $direction);
|
$config = array('fields' => array('ContactsCustomer.type',
|
||||||
if ($index !== 'PrimaryContact.first_name')
|
'ContactsCustomer.active'),
|
||||||
$order[] = parent::gridDataOrder($params, $model,
|
'conditions' => array('ContactsCustomer.active' => true),
|
||||||
'PrimaryContact.first_name', $direction);
|
);
|
||||||
if ($index !== 'Customer.id')
|
|
||||||
$order[] = parent::gridDataOrder($params, $model,
|
|
||||||
'Customer.id', $direction);
|
|
||||||
|
|
||||||
return $order;
|
return $config;
|
||||||
}
|
}
|
||||||
|
|
||||||
function gridDataCount(&$params, &$model) {
|
function gridDataOrder(&$params, &$model, $index, $direction) {
|
||||||
|
$order = parent::gridDataOrder($params, $model, $index, $direction);
|
||||||
|
|
||||||
if ($params['action'] != 'current')
|
// After sorting by whatever the user wants, add these
|
||||||
return parent::gridDataCount($params, $model);
|
// defaults into the sort mechanism. If we're already
|
||||||
|
// sorting by one of them, it will only be redundant,
|
||||||
|
// and should cause no harm (possible a longer query?)
|
||||||
|
$order[] = 'PrimaryContact.last_name ' . $direction;
|
||||||
|
$order[] = 'PrimaryContact.first_name ' . $direction;
|
||||||
|
$order[] = 'Customer.id ' . $direction;
|
||||||
|
|
||||||
// OK, for current customers, we have an issue.
|
return $order;
|
||||||
// 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, but that simply won't work
|
|
||||||
// for the count. However, it's not difficult to simply
|
|
||||||
// derive it since 'current' customers are mutually
|
|
||||||
// exclusive to 'past' customers.
|
|
||||||
|
|
||||||
$tmp_params = $params;
|
|
||||||
$tmp_params['action'] = 'all';
|
|
||||||
$all_count = parent::gridDataCount($tmp_params, $model);
|
|
||||||
$tmp_params['action'] = 'past';
|
|
||||||
$past_count = parent::gridDataCount($tmp_params, $model);
|
|
||||||
|
|
||||||
// The current customer count is simply calculated
|
|
||||||
// as all customers that are not past customers.
|
|
||||||
return $all_count - $past_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
@@ -136,14 +135,18 @@ class CustomersController extends AppController {
|
|||||||
* - Sets up the move-in page for the given customer.
|
* - Sets up the move-in page for the given customer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function move_in($id = null) {
|
function move_in($id = null, $unit_id = null) {
|
||||||
$customer = array();
|
$customer = array();
|
||||||
$unit = array();
|
$unit = array();
|
||||||
|
|
||||||
if (isset($id)) {
|
if (!empty($id)) {
|
||||||
$this->Customer->recursive = -1;
|
$this->Customer->recursive = -1;
|
||||||
$customer = current($this->Customer->read(null, $id));
|
$customer = current($this->Customer->read(null, $id));
|
||||||
}
|
}
|
||||||
|
if (!empty($unit_id)) {
|
||||||
|
$this->Customer->Lease->Unit->recursive = -1;
|
||||||
|
$unit = current($this->Customer->Lease->Unit->read(null, $unit_id));
|
||||||
|
}
|
||||||
$this->set(compact('customer', 'unit'));
|
$this->set(compact('customer', 'unit'));
|
||||||
|
|
||||||
$title = 'Customer Move-In';
|
$title = 'Customer Move-In';
|
||||||
@@ -203,57 +206,118 @@ class CustomersController extends AppController {
|
|||||||
$this->redirect(array('action'=>'index'));
|
$this->redirect(array('action'=>'index'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* //$result = $this->Customer->securityDeposits($id); */
|
// Get details on this customer, its contacts and leases
|
||||||
/* $result = $this->Customer->excessPayments($id); */
|
$customer = $this->Customer->find
|
||||||
/* //$result = $this->Customer->unreconciledCharges($id); */
|
('first', array
|
||||||
/* echo('<HR>'); */
|
('contain' => array
|
||||||
/* pr($result); */
|
(// Models
|
||||||
/* $this->autoRender = false; */
|
'Contact' =>
|
||||||
/* return; */
|
array('order' => array('Contact.display_name'),
|
||||||
|
// Models
|
||||||
|
'ContactPhone',
|
||||||
|
'ContactEmail',
|
||||||
|
'ContactAddress',
|
||||||
|
),
|
||||||
|
'Lease' =>
|
||||||
|
array('Unit' =>
|
||||||
|
array('order' => array('sort_order'),
|
||||||
|
'fields' => array('id', 'name'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
$customer = $this->Customer->details($id);
|
'conditions' => array('Customer.id' => $id),
|
||||||
|
));
|
||||||
//pr($customer);
|
//pr($customer);
|
||||||
$outstanding_balance = $customer['stats']['balance'];
|
|
||||||
|
// Determine how long this customer has been with us.
|
||||||
|
$leaseinfo = $this->Customer->find
|
||||||
|
('first', array
|
||||||
|
('link' => array('Lease' => array('fields' => array())),
|
||||||
|
'fields' => array('MIN(Lease.movein_date) AS since',
|
||||||
|
'IF(Customer.current_lease_count = 0, MAX(Lease.moveout_date), NULL) AS until'),
|
||||||
|
'conditions' => array('Customer.id' => $id),
|
||||||
|
'group' => 'Customer.id',
|
||||||
|
));
|
||||||
|
$this->set($leaseinfo[0]);
|
||||||
|
|
||||||
|
// Figure out the outstanding balances for this customer
|
||||||
|
//$this->set('stats', $this->Customer->stats($id));
|
||||||
|
$outstanding_balance = $this->Customer->balance($id);
|
||||||
$outstanding_deposit = $this->Customer->securityDepositBalance($id);
|
$outstanding_deposit = $this->Customer->securityDepositBalance($id);
|
||||||
|
|
||||||
// Figure out if this customer has any non-closed leases
|
// Figure out if this customer has any non-closed leases
|
||||||
$show_moveout = false;
|
$show_moveout = false; $moveout_lease_id = null;
|
||||||
$show_payment = false;
|
$show_payment = false; $payment_lease_id = null;
|
||||||
foreach ($customer['Lease'] AS $lease) {
|
foreach ($customer['Lease'] AS $lease) {
|
||||||
if (!isset($lease['close_date']))
|
if (!isset($lease['close_date'])) {
|
||||||
|
if ($show_payment)
|
||||||
|
$payment_lease_id = null;
|
||||||
|
else
|
||||||
|
$payment_lease_id = $lease['id'];
|
||||||
$show_payment = true;
|
$show_payment = true;
|
||||||
if (!isset($lease['moveout_date']))
|
}
|
||||||
|
if (!isset($lease['moveout_date'])) {
|
||||||
|
if ($show_moveout)
|
||||||
|
$moveout_lease_id = null;
|
||||||
|
else
|
||||||
|
$moveout_lease_id = $lease['id'];
|
||||||
$show_moveout = true;
|
$show_moveout = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up dynamic menu items
|
// Set up dynamic menu items
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Operations', 'header' => true);
|
|
||||||
|
|
||||||
$this->sidemenu_links[] =
|
if ($show_payment || $outstanding_balance > 0)
|
||||||
array('name' => 'Edit',
|
$this->addSideMenuLink('New Receipt',
|
||||||
'url' => array('action' => 'edit',
|
array('action' => 'receipt', $id), null,
|
||||||
$id));
|
'ACTION');
|
||||||
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Move-In',
|
|
||||||
'url' => array('action' => 'move_in',
|
|
||||||
$id));
|
|
||||||
|
|
||||||
/* if ($show_moveout) { */
|
|
||||||
/* $this->sidemenu_links[] = */
|
|
||||||
/* array('name' => 'Move-Out', */
|
|
||||||
/* 'url' => array('action' => 'move_out', */
|
|
||||||
/* $id)); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
if ($show_payment) {
|
if ($show_payment) {
|
||||||
$this->sidemenu_links[] =
|
/* $ids = $this->Customer->leaseIds($id, true); */
|
||||||
array('name' => 'Payment',
|
/* if (count($ids) == 1) */
|
||||||
'url' => array('action' => 'receipt',
|
/* $lease_id = $ids[0]; */
|
||||||
$id));
|
/* else */
|
||||||
|
/* $lease_id = null; */
|
||||||
|
|
||||||
|
$this->addSideMenuLink('New Invoice',
|
||||||
|
array('controller' => 'leases',
|
||||||
|
'action' => 'invoice',
|
||||||
|
$payment_lease_id), null,
|
||||||
|
'ACTION');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->addSideMenuLink('Move-In',
|
||||||
|
array('action' => 'move_in', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
|
||||||
|
if ($show_moveout) {
|
||||||
|
$this->addSideMenuLink('Move-Out',
|
||||||
|
array('controller' => 'leases',
|
||||||
|
'action' => 'move_out',
|
||||||
|
$moveout_lease_id), null,
|
||||||
|
'ACTION');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$show_moveout && $outstanding_balance > 0)
|
||||||
|
$this->addSideMenuLink('Write-Off',
|
||||||
|
array('action' => 'bad_debt', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
|
||||||
|
if ($outstanding_balance < 0)
|
||||||
|
$this->addSideMenuLink('Issue Refund',
|
||||||
|
array('action' => 'refund', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
|
||||||
|
$this->addSideMenuLink('Edit',
|
||||||
|
array('action' => 'edit', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
|
||||||
|
if ($this->admin())
|
||||||
|
$this->addSideMenuLink('Merge',
|
||||||
|
array('action' => 'merge', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
|
||||||
// Prepare to render.
|
// Prepare to render.
|
||||||
$title = 'Customer: ' . $customer['Customer']['name'];
|
$title = 'Customer: ' . $customer['Customer']['name'];
|
||||||
$this->set(compact('customer', 'title',
|
$this->set(compact('customer', 'title',
|
||||||
@@ -275,23 +339,20 @@ class CustomersController extends AppController {
|
|||||||
if (isset($this->params['form']['cancel'])) {
|
if (isset($this->params['form']['cancel'])) {
|
||||||
if (isset($this->data['Customer']['id']))
|
if (isset($this->data['Customer']['id']))
|
||||||
$this->redirect(array('action'=>'view', $this->data['Customer']['id']));
|
$this->redirect(array('action'=>'view', $this->data['Customer']['id']));
|
||||||
else
|
|
||||||
$this->redirect(array('action'=>'index'));
|
$this->redirect(array('action'=>'index'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we have at least one contact
|
// Make sure we have at least one contact
|
||||||
if (!isset($this->data['Contact']) || count($this->data['Contact']) == 0) {
|
if (!isset($this->data['Contact']) || count($this->data['Contact']) == 0) {
|
||||||
$this->Session->setFlash("MUST SPECIFY AT LEAST ONE CONTACT", true);
|
$this->Session->setFlash("MUST SPECIFY AT LEAST ONE CONTACT", true);
|
||||||
$this->redirect(array('action'=>'view', $this->data['Customer']['id']));
|
$this->redirect(array('action'=>'view', $this->data['Customer']['id']));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure there is a primary contact
|
// Make sure there is a primary contact
|
||||||
if (!isset($this->data['Customer']['primary_contact_entry'])) {
|
if (!isset($this->data['Customer']['primary_contact_entry'])) {
|
||||||
$this->Session->setFlash("MUST SPECIFY A PRIMARY CONTACT", true);
|
$this->Session->setFlash("MUST SPECIFY A PRIMARY CONTACT", true);
|
||||||
$this->redirect(array('action'=>'view', $this->data['Customer']['id']));
|
$this->redirect(array('action'=>'view', $this->data['Customer']['id']));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go through each customer and strip the bogus ID if new
|
// Go through each customer and strip the bogus ID if new
|
||||||
@@ -308,21 +369,56 @@ class CustomersController extends AppController {
|
|||||||
pr("CUSTOMER SAVE FAILED");
|
pr("CUSTOMER SAVE FAILED");
|
||||||
}
|
}
|
||||||
|
|
||||||
// If existing customer, then view it. Otherwise, since
|
// If existing customer, then view it.
|
||||||
// this is a new customer, go to the move in screen.
|
|
||||||
if ($this->data['Customer']['id'])
|
if ($this->data['Customer']['id'])
|
||||||
$this->redirect(array('action'=>'view', $this->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
|
// Since this is a new customer, go to the move in screen.
|
||||||
// commented out, otherwise this section isn't reached.
|
// First set the move-in unit id, if there is one, ...
|
||||||
$this->render('/empty');
|
if (empty($this->data['movein']['Unit']['id']))
|
||||||
return;
|
$unit_id = null;
|
||||||
|
else
|
||||||
|
$unit_id = $this->data['movein']['Unit']['id'];
|
||||||
|
|
||||||
|
// ... then redirect
|
||||||
|
$this->redirect(array('action'=>'move_in',
|
||||||
|
$this->Customer->id,
|
||||||
|
$unit_id,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($id) {
|
if ($id) {
|
||||||
$this->data = $this->Customer->details($id);
|
// REVISIT <AP>: 20090816
|
||||||
|
// This should never need to be done by a controller.
|
||||||
|
// However, until things stabilize, this gives the
|
||||||
|
// user a way to update any cached items on the
|
||||||
|
// customer, by just clicking Edit then Cancel.
|
||||||
|
$this->Customer->update($id);
|
||||||
|
|
||||||
|
// Get details on this customer, its contacts and leases
|
||||||
|
$customer = $this->Customer->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array
|
||||||
|
(// Models
|
||||||
|
'Contact' =>
|
||||||
|
array('order' => array('Contact.display_name'),
|
||||||
|
// Models
|
||||||
|
'ContactPhone',
|
||||||
|
'ContactEmail',
|
||||||
|
'ContactAddress',
|
||||||
|
),
|
||||||
|
'Lease' =>
|
||||||
|
array('Unit' =>
|
||||||
|
array('order' => array('sort_order'),
|
||||||
|
'fields' => array('id', 'name'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
'conditions' => array('Customer.id' => $id),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->data = $customer;
|
||||||
$title = 'Customer: ' . $this->data['Customer']['name'] . " : Edit";
|
$title = 'Customer: ' . $this->data['Customer']['name'] . " : Edit";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -351,10 +447,46 @@ class CustomersController extends AppController {
|
|||||||
* - Add a new customer
|
* - Add a new customer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function add() {
|
function add($unit_id = null) {
|
||||||
|
$this->set('movein', array('Unit' => array('id' => $unit_id)));
|
||||||
$this->edit();
|
$this->edit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: merge
|
||||||
|
* - Merges two customers
|
||||||
|
*/
|
||||||
|
|
||||||
|
function merge($id = null) {
|
||||||
|
if ($id) {
|
||||||
|
$this->Customer->recursive = -1;
|
||||||
|
$customer = $this->Customer->read(null, $id);
|
||||||
|
$customer = $customer['Customer'];
|
||||||
|
if (empty($customer))
|
||||||
|
$this->INTERNAL_ERROR("Customer $id does not exist");
|
||||||
|
$this->set('dst_customer', $customer);
|
||||||
|
$this->set('dst_name', $customer['name']);
|
||||||
|
$this->set('dst_id', $id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->INTERNAL_ERROR("Merge called with invalid customer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mergeFinal() {
|
||||||
|
if (!$this->RequestHandler->isPost()) {
|
||||||
|
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$post = $this->params['form'];
|
||||||
|
$this->Customer->merge($post['dst-id'], $post['src-id'],
|
||||||
|
unserialize($post['contact-ids']));
|
||||||
|
$this->redirect(array('action'=>'view', $post['dst-id']));
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -367,20 +499,9 @@ class CustomersController extends AppController {
|
|||||||
$this->Customer->recursive = -1;
|
$this->Customer->recursive = -1;
|
||||||
$customer = $this->Customer->read(null, $id);
|
$customer = $this->Customer->read(null, $id);
|
||||||
$customer = $customer['Customer'];
|
$customer = $customer['Customer'];
|
||||||
$unreconciled = $this->Customer->unreconciledCharges($id);
|
|
||||||
//pr($unreconciled);
|
|
||||||
$charges = $unreconciled['entries'];
|
|
||||||
$stats = $unreconciled['summary']['Charge'];
|
|
||||||
// Kludge until we update receipt to have the unpaid
|
|
||||||
// charges grid generated from a dynamic query instead
|
|
||||||
// of simply pre-providing the list of charge IDs
|
|
||||||
foreach ($charges AS &$charge)
|
|
||||||
$charge['id'] = $charge['StatementEntry']['id'];
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$customer = null;
|
$customer = null;
|
||||||
$charges = array();
|
|
||||||
$stats = array('balance' => 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$TT = new TenderType();
|
$TT = new TenderType();
|
||||||
@@ -388,8 +509,8 @@ class CustomersController extends AppController {
|
|||||||
$default_type = $TT->defaultPaymentType();
|
$default_type = $TT->defaultPaymentType();
|
||||||
$this->set(compact('payment_types', 'default_type'));
|
$this->set(compact('payment_types', 'default_type'));
|
||||||
|
|
||||||
$title = ($customer['name'] . ': Payment Entry');
|
$title = ($customer['name'] . ': Receipt Entry');
|
||||||
$this->set(compact('customer', 'charges', 'stats', 'title'));
|
$this->set(compact('customer', 'title'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -400,58 +521,64 @@ class CustomersController extends AppController {
|
|||||||
* - Refunds customer charges
|
* - Refunds customer charges
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function refund() {
|
function refund($id) {
|
||||||
$entries = $this->Customer->StatementEntry->find
|
$customer = $this->Customer->find
|
||||||
('all', array
|
('first', array
|
||||||
('contain' => false,
|
('contain' => false,
|
||||||
'conditions' => array('StatementEntry.id' =>
|
'conditions' => array(array('Customer.id' => $id),
|
||||||
//array(199,200,201)
|
|
||||||
61
|
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
pr(compact('entries'));
|
if (empty($customer)) {
|
||||||
|
$this->redirect(array('action'=>'view', $id));
|
||||||
|
}
|
||||||
|
|
||||||
$this->Customer->StatementEntry->reverse($entries);
|
// Determine the customer balance, bailing if the customer owes money
|
||||||
|
$balance = $this->Customer->balance($id);
|
||||||
|
if ($balance >= 0) {
|
||||||
|
$this->redirect(array('action'=>'view', $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// The refund will be for a positive amount
|
||||||
|
$balance *= -1;
|
||||||
|
|
||||||
|
// Get the accounts capable of paying the refund
|
||||||
|
$refundAccounts = $this->Customer->StatementEntry->Account->refundAccounts();
|
||||||
|
$defaultAccount = current($refundAccounts);
|
||||||
|
$this->set(compact('refundAccounts', 'defaultAccount'));
|
||||||
|
|
||||||
|
// Prepare to render
|
||||||
|
$title = ($customer['Customer']['name'] . ': Refund');
|
||||||
|
$this->set(compact('title', 'customer', 'balance'));
|
||||||
|
$this->render('/transactions/refund');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* action: unreconciled
|
* action: bad_debt
|
||||||
* - returns the list of unreconciled entries
|
* - Sets up the write-off entry page, so that the
|
||||||
|
* user can write off remaining charges of a customer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function unreconciled($id) {
|
function bad_debt($id) {
|
||||||
|
$this->Customer->id = $id;
|
||||||
|
$customer = $this->Customer->find
|
||||||
|
('first', array
|
||||||
|
('contain' => false,
|
||||||
|
));
|
||||||
|
|
||||||
//$this->layout = 'ajax';
|
// Make sure we have a valid customer to write off
|
||||||
$this->layout = null;
|
if (empty($customer))
|
||||||
$this->autoLayout = false;
|
$this->redirect(array('action' => 'index'));
|
||||||
$this->autoRender = false;
|
|
||||||
//Configure::write('debug', '0');
|
|
||||||
//header("Content-type: text/xml;charset=utf-8");
|
|
||||||
|
|
||||||
App::import('Helper', 'Xml');
|
// Get the customer balance
|
||||||
$xml = new XmlHelper();
|
$balance = $this->Customer->balance($id);
|
||||||
|
|
||||||
// Find the unreconciled entries, then manipulate the structure
|
// Prepare to render
|
||||||
// slightly to accomodate the format necessary for XML Helper.
|
$title = ($customer['Customer']['name'] . ': Write Off Bad Debt');
|
||||||
$unreconciled = $this->Customer->unreconciledCharges($id);
|
$this->set(compact('title', 'customer', 'balance'));
|
||||||
$unreconciled = array('entries' =>
|
$this->render('/transactions/bad_debt');
|
||||||
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->reconcileNewStatementEntry($cust_id, 'credit', $amount);
|
|
||||||
|
|
||||||
$opts = array();
|
|
||||||
//$opts['format'] = 'tags';
|
|
||||||
echo $xml->header();
|
|
||||||
echo $xml->serialize($unreconciled, $opts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,20 +2,7 @@
|
|||||||
|
|
||||||
class DoubleEntriesController extends AppController {
|
class DoubleEntriesController extends AppController {
|
||||||
|
|
||||||
var $sidemenu_links = array();
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* override: sideMenuLinks
|
|
||||||
* - Generates controller specific links for the side menu
|
|
||||||
*/
|
|
||||||
function sideMenuLinks() {
|
|
||||||
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -36,6 +23,34 @@ class DoubleEntriesController extends AppController {
|
|||||||
'conditions' => array('DoubleEntry.id' => $id),
|
'conditions' => array('DoubleEntry.id' => $id),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
$entry += $this->DoubleEntry->DebitEntry->Transaction->find
|
||||||
|
('first',
|
||||||
|
array('contain' => false,
|
||||||
|
'conditions' => array('id' => $entry['DebitEntry']['transaction_id']),
|
||||||
|
));
|
||||||
|
|
||||||
|
$entry += $this->DoubleEntry->DebitEntry->find
|
||||||
|
('first',
|
||||||
|
array('contain' => array('Ledger' => array('Account')),
|
||||||
|
'conditions' => array('DebitEntry.id' => $entry['DebitEntry']['id']),
|
||||||
|
));
|
||||||
|
$entry['Ledger']['link'] =
|
||||||
|
$entry['Ledger']['Account']['level'] >=
|
||||||
|
$this->Permission->level('controller.accounts');
|
||||||
|
$entry['DebitLedger'] = $entry['Ledger'];
|
||||||
|
unset($entry['Ledger']);
|
||||||
|
|
||||||
|
$entry += $this->DoubleEntry->CreditEntry->find
|
||||||
|
('first',
|
||||||
|
array('contain' => array('Ledger' => array('Account')),
|
||||||
|
'conditions' => array('CreditEntry.id' => $entry['CreditEntry']['id']),
|
||||||
|
));
|
||||||
|
$entry['Ledger']['link'] =
|
||||||
|
$entry['Ledger']['Account']['level'] >=
|
||||||
|
$this->Permission->level('controller.accounts');
|
||||||
|
$entry['CreditLedger'] = $entry['Ledger'];
|
||||||
|
unset($entry['Ledger']);
|
||||||
|
|
||||||
// Prepare to render.
|
// Prepare to render.
|
||||||
$title = "Double Ledger Entry #{$entry['DoubleEntry']['id']}";
|
$title = "Double Ledger Entry #{$entry['DoubleEntry']['id']}";
|
||||||
$this->set(compact('entry', 'title'));
|
$this->set(compact('entry', 'title'));
|
||||||
|
|||||||
@@ -2,25 +2,32 @@
|
|||||||
|
|
||||||
class LeasesController extends AppController {
|
class LeasesController extends AppController {
|
||||||
|
|
||||||
var $sidemenu_links =
|
|
||||||
array(array('name' => 'Leases', 'header' => true),
|
|
||||||
array('name' => 'Active', 'url' => array('controller' => 'leases', 'action' => 'active')),
|
|
||||||
array('name' => 'Closed', 'url' => array('controller' => 'leases', 'action' => 'closed')),
|
|
||||||
array('name' => 'All', 'url' => array('controller' => 'leases', 'action' => 'all')),
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* override: sideMenuLinks
|
* override: addGridViewSideMenuLinks
|
||||||
* - Generates controller specific links for the side menu
|
* - Adds grid view navigation side menu links
|
||||||
*/
|
*/
|
||||||
function sideMenuLinks() {
|
|
||||||
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
function addGridViewSideMenuLinks() {
|
||||||
|
parent::addGridViewSideMenuLinks();
|
||||||
|
|
||||||
|
$this->addSideMenuLink('Active',
|
||||||
|
array('controller' => 'leases', 'action' => 'active'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('Closed',
|
||||||
|
array('controller' => 'leases', 'action' => 'closed'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('Delinquent',
|
||||||
|
array('controller' => 'leases', 'action' => 'delinquent'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('All',
|
||||||
|
array('controller' => 'leases', 'action' => 'all'), null,
|
||||||
|
'CONTROLLER');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -28,10 +35,11 @@ class LeasesController extends AppController {
|
|||||||
* - Generate a listing of leases
|
* - Generate a listing of leases
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function index() { $this->all(); }
|
function index() { $this->active(); }
|
||||||
function active() { $this->gridView('Active Leases'); }
|
function active() { $this->gridView('Active Leases', 'active'); }
|
||||||
function closed() { $this->gridView('Closed Leases'); }
|
function delinquent() { $this->gridView('Delinquent Leases'); }
|
||||||
function all() { $this->gridView('All Leases', 'all'); }
|
function closed() { $this->gridView('Closed Leases'); }
|
||||||
|
function all() { $this->gridView('All Leases'); }
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
@@ -63,8 +71,10 @@ class LeasesController extends AppController {
|
|||||||
|
|
||||||
function gridDataFields(&$params, &$model) {
|
function gridDataFields(&$params, &$model) {
|
||||||
$fields = parent::gridDataFields($params, $model);
|
$fields = parent::gridDataFields($params, $model);
|
||||||
|
$fields[] = ("IF(" . $this->Lease->conditionDelinquent() . "," .
|
||||||
|
" 'DELINQUENT', 'CURRENT') AS 'status'");
|
||||||
return array_merge($fields,
|
return array_merge($fields,
|
||||||
$this->Lease->StatementEntry->chargePaymentFields(true));
|
$this->Lease->StatementEntry->chargeDisbursementFields(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
function gridDataConditions(&$params, &$model) {
|
function gridDataConditions(&$params, &$model) {
|
||||||
@@ -73,6 +83,9 @@ class LeasesController extends AppController {
|
|||||||
if ($params['action'] === 'active') {
|
if ($params['action'] === 'active') {
|
||||||
$conditions[] = 'Lease.close_date IS NULL';
|
$conditions[] = 'Lease.close_date IS NULL';
|
||||||
}
|
}
|
||||||
|
elseif ($params['action'] === 'delinquent') {
|
||||||
|
$conditions[] = $this->Lease->conditionDelinquent();
|
||||||
|
}
|
||||||
elseif ($params['action'] === 'closed') {
|
elseif ($params['action'] === 'closed') {
|
||||||
$conditions[] = 'Lease.close_date IS NOT NULL';
|
$conditions[] = 'Lease.close_date IS NOT NULL';
|
||||||
}
|
}
|
||||||
@@ -135,21 +148,22 @@ class LeasesController extends AppController {
|
|||||||
|
|
||||||
// Handle the move in based on the data given
|
// Handle the move in based on the data given
|
||||||
//pr(array('Move-in data', $this->data));
|
//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'],
|
$lid = $this->Lease->moveIn($this->data['Lease']['customer_id'],
|
||||||
$this->data['Lease']['unit_id'],
|
$this->data['Lease']['unit_id'],
|
||||||
null, null,
|
$this->data['Lease']['deposit'],
|
||||||
|
$this->data['Lease']['rent'],
|
||||||
$this->data['Lease']['movein_date'],
|
$this->data['Lease']['movein_date'],
|
||||||
$this->data['Lease']['comment']
|
$this->data['Lease']['comment']
|
||||||
);
|
);
|
||||||
|
|
||||||
// Since this is a new lease, go to the invoice
|
// Since this is a new lease, go to the invoice
|
||||||
// screen so we can start assessing charges.
|
// 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.
|
|
||||||
$this->render('/empty');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
@@ -162,169 +176,119 @@ class LeasesController extends AppController {
|
|||||||
function move_out($id = null) {
|
function move_out($id = null) {
|
||||||
if ($this->data) {
|
if ($this->data) {
|
||||||
// Handle the move out based on the data given
|
// 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',
|
'VACANT',
|
||||||
$this->data['Lease']['moveout_date'],
|
$this->data['Lease']['moveout_date']
|
||||||
//true // Close this lease, if able
|
|
||||||
false
|
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->redirect($this->data['redirect']);
|
$lease = $this->Lease->find
|
||||||
$this->autoRender = false;
|
('first', array
|
||||||
return;
|
('contain' => array('Customer.id'),
|
||||||
|
'conditions' => array(array('Lease.id' => $this->data['Lease']['id'])),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->redirect(array('controller' => 'customers',
|
||||||
|
'action' => 'view',
|
||||||
|
$lease['Customer']['id']));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($id))
|
if (isset($id)) {
|
||||||
die("Oh Nooooo!!");
|
$lease = $this->Lease->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array
|
||||||
|
(// Models
|
||||||
|
'Unit' =>
|
||||||
|
array('order' => array('sort_order'),
|
||||||
|
'fields' => array('id', 'name'),
|
||||||
|
),
|
||||||
|
|
||||||
$lease = $this->Lease->find
|
'Customer' =>
|
||||||
('first', array
|
array('fields' => array('id', 'name'),
|
||||||
('contain' => array
|
),
|
||||||
(// Models
|
),
|
||||||
'Unit' =>
|
|
||||||
array('order' => array('sort_order'),
|
|
||||||
'fields' => array('id', 'name'),
|
|
||||||
),
|
|
||||||
|
|
||||||
'Customer' =>
|
'conditions' => array(array('Lease.id' => $id),
|
||||||
array('fields' => array('id', 'name'),
|
array('Lease.close_date' => null),
|
||||||
),
|
),
|
||||||
),
|
));
|
||||||
|
$this->set('customer', $lease['Customer']);
|
||||||
|
$this->set('unit', $lease['Unit']);
|
||||||
|
$this->set('lease', $lease['Lease']);
|
||||||
|
|
||||||
'conditions' => array(array('Lease.id' => $id),
|
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
|
||||||
array('Lease.close_date' => null),
|
$lease['Unit']['name'] . ': ' .
|
||||||
),
|
$lease['Customer']['name'] . ': Move-Out');
|
||||||
));
|
}
|
||||||
$this->set('customer', $lease['Customer']);
|
else {
|
||||||
$this->set('unit', $lease['Unit']);
|
$title = 'Move-Out';
|
||||||
$this->set('lease', $lease['Lease']);
|
}
|
||||||
|
|
||||||
$redirect = array('controller' => 'leases',
|
$this->set(compact('title'));
|
||||||
'action' => 'view',
|
|
||||||
$id);
|
|
||||||
|
|
||||||
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
|
|
||||||
$lease['Unit']['name'] . ': ' .
|
|
||||||
$lease['Customer']['name'] . ': Prepare Move-Out');
|
|
||||||
$this->set(compact('title', 'redirect'));
|
|
||||||
$this->render('/leases/move');
|
$this->render('/leases/move');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* /\************************************************************************** */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
/* * action: promote_credit */
|
||||||
|
/* * - Moves any lease credit up to the customer level, so that */
|
||||||
|
/* * it may be used for charges other than those on this lease. */
|
||||||
|
/* *\/ */
|
||||||
|
|
||||||
|
/* function promote_surplus($id) { */
|
||||||
|
/* $this->Lease->promoteSurplus($id); */
|
||||||
|
/* $this->redirect(array('controller' => 'leases', */
|
||||||
|
/* 'action' => 'view', */
|
||||||
|
/* $id)); */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* action: apply_deposit
|
* action: refund
|
||||||
* - Applies the security deposit to charges. This is much
|
* - Provides lease customer with a refund
|
||||||
* like a receipt, but it's separated to keep it simple and
|
|
||||||
* to prevent feature overload on the receipt page.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function apply_deposit($id = null) {
|
function refund($id) {
|
||||||
// Create some models for convenience
|
|
||||||
$A = new Account();
|
|
||||||
|
|
||||||
if ($this->data) {
|
|
||||||
// Handle the move out based on the data given
|
|
||||||
pr($this->data);
|
|
||||||
$this->Lease->releaseSecurityDeposits($this->data['Lease']['id']);
|
|
||||||
die();
|
|
||||||
|
|
||||||
// Assume this will succeed
|
|
||||||
$ret = true;
|
|
||||||
|
|
||||||
// Go through the entered payments
|
|
||||||
$receipt_transaction = array_intersect_key($this->data,
|
|
||||||
array('Transaction'=>1,
|
|
||||||
'transaction_id'=>1));
|
|
||||||
foreach ($data['StatementEntry'] 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->StatementEntry->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');
|
|
||||||
|
|
||||||
if ($ids['error'])
|
|
||||||
$ret = false;
|
|
||||||
|
|
||||||
$db = &$model->getDataSource();
|
|
||||||
$fields = $db->fields($model, $model->alias);
|
|
||||||
$fields[] = ("SUM(IF(Account.id IS NULL, 0," .
|
|
||||||
" IF(LedgerEntry.debit_ledger_id = Account.id," .
|
|
||||||
" 1, -1))" .
|
|
||||||
" * IF(LedgerEntry.amount IS NULL, 0, LedgerEntry.amount))" .
|
|
||||||
" AS 'balance'");
|
|
||||||
return $fields;
|
|
||||||
$receipt_transaction = array_intersect_key($ids,
|
|
||||||
array('transaction_id'=>1,
|
|
||||||
'split_transaction_id'=>1));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->Lease->moveOut($this->data['Lease']['id'],
|
|
||||||
'VACANT',
|
|
||||||
$this->data['Lease']['moveout_date'],
|
|
||||||
//true // Close this lease, if able
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->redirect(array('controller' => 'leases',
|
|
||||||
'action' => 'view',
|
|
||||||
$this->data['Lease']['id']));
|
|
||||||
$this->autoRender = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$A = new Account();
|
|
||||||
|
|
||||||
$lease = $this->Lease->find
|
$lease = $this->Lease->find
|
||||||
('first', array
|
('first', array
|
||||||
('contain' => array
|
('contain' => array
|
||||||
(// Models
|
(// Models
|
||||||
'Unit' =>
|
'Unit' => array('fields' => array('id', 'name')),
|
||||||
array('order' => array('sort_order'),
|
'Customer' => array('fields' => array('id', 'name')),
|
||||||
'fields' => array('id', 'name'),
|
|
||||||
),
|
|
||||||
|
|
||||||
'Customer' =>
|
|
||||||
array('fields' => array('id', 'name'),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
|
||||||
'conditions' => array(array('Lease.id' => $id),
|
'conditions' => array(array('Lease.id' => $id),
|
||||||
|
// Make sure lease is not closed...
|
||||||
array('Lease.close_date' => null),
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
// Get the lease balance, part of lease stats
|
// The refund will be for a positive amount
|
||||||
$this->Lease->statsMerge($lease['Lease'],
|
$balance *= -1;
|
||||||
array('stats' => $this->Lease->stats($id)));
|
|
||||||
|
|
||||||
// Determine the lease security deposit
|
// Get the accounts capable of paying the refund
|
||||||
$deposit_balance = $this->Lease->securityDeposits($lease['Lease']['id']);
|
$refundAccounts = $this->Lease->StatementEntry->Account->refundAccounts();
|
||||||
$this->set(compact('deposit_balance'));
|
$defaultAccount = current($refundAccounts);
|
||||||
$this->set('customer', $lease['Customer']);
|
$this->set(compact('refundAccounts', 'defaultAccount'));
|
||||||
$this->set('unit', $lease['Unit']);
|
|
||||||
$this->set('lease', $lease['Lease']);
|
|
||||||
$this->set('account', array('id' => $A->securityDepositAccountID()));
|
|
||||||
|
|
||||||
/* $redirect = array('controller' => 'leases', */
|
|
||||||
/* 'action' => 'view', */
|
|
||||||
/* $id); */
|
|
||||||
|
|
||||||
|
// Prepare to render
|
||||||
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
|
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
|
||||||
$lease['Unit']['name'] . ': ' .
|
$lease['Unit']['name'] . ': ' .
|
||||||
$lease['Customer']['name'] . ': Utilize Security Deposit');
|
$lease['Customer']['name'] . ': Refund');
|
||||||
$this->set(compact('title', 'redirect'));
|
$this->set(compact('title', 'lease', 'balance'));
|
||||||
|
$this->render('/transactions/refund');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -332,82 +296,34 @@ class LeasesController extends AppController {
|
|||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* action: bad_debt
|
* action: bad_debt
|
||||||
* - Writes off remaining charges on a lease.
|
* - Sets up the write-off entry page, so that the
|
||||||
* REVISIT <AP>: 20090710
|
* user can write off remaining charges on a lease.
|
||||||
* Should this be a customer function? What customer
|
|
||||||
* would have only one lease that results in bad debt.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function bad_debt($id) {
|
function bad_debt($id) {
|
||||||
$A = new Account();
|
$this->Lease->id = $id;
|
||||||
|
|
||||||
$lease = $this->Lease->find
|
$lease = $this->Lease->find
|
||||||
('first', array
|
('first', array
|
||||||
('contain' => array
|
('contain' => array
|
||||||
(// Models
|
(// Models
|
||||||
'Unit' =>
|
'Unit' => array('fields' => array('id', 'name')),
|
||||||
array('order' => array('sort_order'),
|
'Customer' => array('fields' => array('id', 'name')),
|
||||||
'fields' => array('id', 'name'),
|
|
||||||
),
|
|
||||||
|
|
||||||
'Customer' =>
|
|
||||||
array('fields' => array('id', 'name'),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
|
||||||
'conditions' => array(array('Lease.id' => $id),
|
|
||||||
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
|
// Get the lease balance
|
||||||
$this->Lease->statsMerge($lease['Lease'],
|
$balance = $this->Lease->balance($id);
|
||||||
array('stats' => $this->Lease->stats($id)));
|
|
||||||
|
|
||||||
// Determine the lease security deposit
|
|
||||||
$deposit_balance = $this->Lease->securityDepositBalance($lease['Lease']['id']);
|
|
||||||
if ($deposit_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); */
|
|
||||||
|
|
||||||
|
// Prepare to render
|
||||||
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
|
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
|
||||||
$lease['Unit']['name'] . ': ' .
|
$lease['Unit']['name'] . ': ' .
|
||||||
$lease['Customer']['name'] . ': Write Off Bad Debt');
|
$lease['Customer']['name'] . ': Write Off Bad Debt');
|
||||||
$this->set(compact('title', 'redirect'));
|
$this->set(compact('title', 'lease', 'balance'));
|
||||||
}
|
$this->render('/transactions/bad_debt');
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* action: refund
|
|
||||||
* - Provides user with a refund
|
|
||||||
* REVISIT <AP>: 20090710
|
|
||||||
* Should this be a customer function?
|
|
||||||
*/
|
|
||||||
|
|
||||||
function refund($id) {
|
|
||||||
/* // Obtain the overall lease balance */
|
|
||||||
/* $stats = $this->Lease->stats($id); */
|
|
||||||
/* $outstanding_balance = $stats['balance']; */
|
|
||||||
|
|
||||||
/* // Determine the lease security deposit */
|
|
||||||
/* $deposits = $this->Lease->securityDeposits($id); */
|
|
||||||
/* $outstanding_deposit = $deposits['summary']['balance']; */
|
|
||||||
|
|
||||||
|
|
||||||
/* $this->set(compact('lease', 'title', */
|
|
||||||
/* 'outstanding_deposit', */
|
|
||||||
/* 'outstanding_balance')); */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -421,10 +337,30 @@ class LeasesController extends AppController {
|
|||||||
function close($id) {
|
function close($id) {
|
||||||
// REVISIT <AP>: 20090708
|
// REVISIT <AP>: 20090708
|
||||||
// We should probably seek confirmation first...
|
// We should probably seek confirmation first...
|
||||||
|
if (!$this->Lease->closeable($id)) {
|
||||||
|
$this->INTERNAL_ERROR("This lease is not ready to close");
|
||||||
|
$this->redirect(array('action'=>'view', $id));
|
||||||
|
}
|
||||||
|
|
||||||
$this->Lease->close($id);
|
$this->Lease->close($id);
|
||||||
$this->redirect(array('action'=>'view', $id));
|
$this->redirect(array('action'=>'view', $id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: open
|
||||||
|
* - Re-opens a lease for further action
|
||||||
|
*/
|
||||||
|
|
||||||
|
function open($id) {
|
||||||
|
// REVISIT <AP>: 20131204
|
||||||
|
// We should probably seek confirmation first, since this wipes out
|
||||||
|
// the old close date, with no way to restore that date.
|
||||||
|
$this->Lease->reopen($id);
|
||||||
|
$this->redirect(array('action'=>'view', $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -455,15 +391,36 @@ class LeasesController extends AppController {
|
|||||||
));
|
));
|
||||||
|
|
||||||
$A = new Account();
|
$A = new Account();
|
||||||
$charge_accounts = $A->chargeAccounts();
|
$charge_accounts = $A->invoiceAccounts();
|
||||||
$default_account = $A->rentAccountID();
|
$default_account = $A->rentAccountID();
|
||||||
$this->set(compact('charge_accounts', 'default_account'));
|
$rent_account = $A->rentAccountID();
|
||||||
|
$security_deposit_account = $A->securityDepositAccountID();
|
||||||
|
$this->set(compact('charge_accounts', 'default_account',
|
||||||
|
'rent_account', 'security_deposit_account'));
|
||||||
|
|
||||||
// REVISIT <AP> 20090705:
|
// REVISIT <AP> 20090705:
|
||||||
// Of course, the late charge should come from the late_schedule
|
// Of course, the late charge should come from the late_schedule
|
||||||
$default_rent = $lease['Lease']['rent'];
|
|
||||||
$default_late = 10;
|
$default_late = 10;
|
||||||
$this->set(compact('default_rent', 'default_late'));
|
$this->set(compact('default_late'));
|
||||||
|
|
||||||
|
if ($type === 'move-in') {
|
||||||
|
// Make sure we have a valid lease that we're moving in
|
||||||
|
if (empty($lease))
|
||||||
|
$this->redirect(array('action' => 'index'));
|
||||||
|
|
||||||
|
$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'] . ': ' .
|
$title = ('Lease #' . $lease['Lease']['number'] . ': ' .
|
||||||
$lease['Unit']['name'] . ': ' .
|
$lease['Unit']['name'] . ': ' .
|
||||||
@@ -472,6 +429,85 @@ class LeasesController extends AppController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: assess_rent/late
|
||||||
|
* - Assesses the new monthly rent/late charge, if need be
|
||||||
|
*/
|
||||||
|
|
||||||
|
function assess_rent($date = null) {
|
||||||
|
$this->Lease->assessMonthlyRentAll($date);
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
function assess_late($date = null) {
|
||||||
|
$this->Lease->assessMonthlyLateAll($date);
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
function assess_all($date = null) {
|
||||||
|
$this->Lease->assessMonthlyRentAll($date);
|
||||||
|
$this->Lease->assessMonthlyLateAll($date);
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: overview
|
||||||
|
* - Displays lease up information
|
||||||
|
*/
|
||||||
|
function overview($months = 12) {
|
||||||
|
|
||||||
|
$overview = array('months' => array());
|
||||||
|
|
||||||
|
for ($month = 0; $month < $months; ++$month) {
|
||||||
|
//for ($month = 12; $month >= 0; --$month) {
|
||||||
|
$this_month = "(DATE(NOW() - INTERVAL $month MONTH - INTERVAL DAY(NOW())-1 DAY))";
|
||||||
|
$next_month = "($this_month + INTERVAL 1 MONTH)";
|
||||||
|
|
||||||
|
$row = $this->Lease->find
|
||||||
|
('first', array('link' => array(),
|
||||||
|
'fields' => array("MONTHNAME($this_month) AS month",
|
||||||
|
"YEAR($this_month) AS year"),
|
||||||
|
));
|
||||||
|
|
||||||
|
$mname = $row[0]['month'] .', '. $row[0]['year'];
|
||||||
|
$overview['months'][$mname] = array('name' => $mname);
|
||||||
|
|
||||||
|
foreach(array('start' => array('before' => $this_month, 'after' => $this_month),
|
||||||
|
'finish' => array('before' => $next_month, 'after' => $next_month),
|
||||||
|
'peak' => array('before' => $next_month, 'after' => $this_month))
|
||||||
|
AS $type => $parm) {
|
||||||
|
$count = $this->Lease->find
|
||||||
|
('count',
|
||||||
|
array('link' => array(),
|
||||||
|
'conditions' => array("movein_date < {$parm['before']}",
|
||||||
|
"(moveout_date IS NULL OR moveout_date >= {$parm['after']})",
|
||||||
|
),
|
||||||
|
));
|
||||||
|
$overview['months'][$mname][$type] = $count;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(array('movein', 'moveout') AS $mvinout) {
|
||||||
|
$count = $this->Lease->find
|
||||||
|
('count',
|
||||||
|
array('link' => array(),
|
||||||
|
'conditions' => array("{$mvinout}_date < $next_month",
|
||||||
|
"{$mvinout}_date >= $this_month")
|
||||||
|
));
|
||||||
|
$overview['months'][$mname][$mvinout] = $count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable the Reports menu section
|
||||||
|
$this->sideMenuAreaActivate('REPORT');
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$this->set('title', 'Lease Up Report');
|
||||||
|
$this->set(compact('overview'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -490,70 +526,72 @@ class LeasesController extends AppController {
|
|||||||
('first',
|
('first',
|
||||||
array('contain' =>
|
array('contain' =>
|
||||||
array(// Models
|
array(// Models
|
||||||
'LeaseType',
|
'LeaseType(id,name)',
|
||||||
'Unit',
|
'Unit(id,name)',
|
||||||
'Customer',
|
'Customer(id,name)',
|
||||||
),
|
),
|
||||||
|
'fields' => array('Lease.*', $this->Lease->delinquentField()),
|
||||||
'conditions' => array(array('Lease.id' => $id)),
|
'conditions' => array(array('Lease.id' => $id)),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
$lease['Lease'] += $lease[0];
|
||||||
|
unset($lease[0]);
|
||||||
|
|
||||||
$lease['Lease']['paid_through'] = $this->Lease->rentPaidThrough($id);
|
// Figure out the outstanding balances for this lease
|
||||||
|
$outstanding_balance = $this->Lease->balance($id);
|
||||||
|
$outstanding_deposit = $this->Lease->securityDepositBalance($id);
|
||||||
$this->set('charge_gaps', $this->Lease->rentChargeGaps($id));
|
|
||||||
$this->set('charge_through', $this->Lease->rentChargeThrough($id));
|
|
||||||
|
|
||||||
// Obtain the overall lease balance
|
|
||||||
$this->Lease->statsMerge($lease['Lease'],
|
|
||||||
array('stats' => $this->Lease->stats($id)));
|
|
||||||
$outstanding_balance = $lease['Lease']['stats']['balance'];
|
|
||||||
|
|
||||||
// Determine the lease security deposit
|
|
||||||
$outstanding_deposit = $this->Lease->securityDepositBalance($lease['Lease']['id']);
|
|
||||||
|
|
||||||
// Set up dynamic menu items
|
|
||||||
if (!isset($lease['Lease']['close_date'])) {
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Operations', 'header' => true);
|
|
||||||
|
|
||||||
|
// 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) {
|
||||||
if (!isset($lease['Lease']['moveout_date']))
|
if (!isset($lease['Lease']['moveout_date']))
|
||||||
$this->sidemenu_links[] =
|
$this->addSideMenuLink('Move-Out',
|
||||||
array('name' => 'Move-Out', 'url' => array('action' => 'move_out',
|
array('action' => 'move_out', $id), null,
|
||||||
$id));
|
'ACTION');
|
||||||
|
|
||||||
$this->sidemenu_links[] =
|
if (!isset($lease['Lease']['close_date']))
|
||||||
array('name' => 'Charges', 'url' => array('action' => 'invoice',
|
$this->addSideMenuLink('New Invoice',
|
||||||
$id));
|
array('action' => 'invoice', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
|
||||||
$this->sidemenu_links[] =
|
$this->addSideMenuLink('New Receipt',
|
||||||
array('name' => 'Payments', 'url' => array('controller' => 'customers',
|
array('controller' => 'customers',
|
||||||
'action' => 'receipt',
|
'action' => 'receipt',
|
||||||
$lease['Customer']['id']));
|
$lease['Customer']['id']), null,
|
||||||
|
'ACTION');
|
||||||
|
|
||||||
if (isset($lease['Lease']['moveout_date']) && $outstanding_deposit > 0 && $outstanding_balance > 0)
|
// REVISIT <AP>:
|
||||||
$this->sidemenu_links[] =
|
// Not allowing refund to be issued from the lease, as
|
||||||
array('name' => 'Apply Deposit', 'url' => array('action' => 'apply_deposit',
|
// in fact, we should never have a positive lease balance.
|
||||||
$id));
|
// I'll flag this at the moment, since we might get one
|
||||||
|
// when a charge is reimbursed; a bug that we'll either
|
||||||
|
// need to fix, or we'll have to revisit this assumption.
|
||||||
|
if ($outstanding_balance < 0)
|
||||||
|
$this->INTERNAL_ERROR("Should not have a customer lease credit.");
|
||||||
|
|
||||||
if (isset($lease['Lease']['moveout_date']) &&
|
/* if ($outstanding_balance < 0) */
|
||||||
$outstanding_balance <= 0 &&
|
/* $this->addSideMenuLink('Issue Refund', */
|
||||||
($outstanding_deposit - $outstanding_balance) > 0)
|
/* array('action' => 'refund', $id), null, */
|
||||||
$this->sidemenu_links[] =
|
/* 'ACTION'); */
|
||||||
array('name' => 'Issue Refund', 'url' => array('action' => 'refund',
|
|
||||||
$id));
|
|
||||||
|
|
||||||
if (isset($lease['Lease']['moveout_date']) && $outstanding_deposit == 0 && $outstanding_balance > 0)
|
if (isset($lease['Lease']['moveout_date']) && $outstanding_balance > 0)
|
||||||
$this->sidemenu_links[] =
|
$this->addSideMenuLink('Write-Off',
|
||||||
array('name' => 'Write-Off', 'url' => array('action' => 'bad_debt',
|
array('action' => 'bad_debt', $id), null,
|
||||||
$id));
|
'ACTION');
|
||||||
|
|
||||||
if ($this->Lease->closeable($id))
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'Close', 'url' => array('action' => 'close',
|
|
||||||
$id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->Lease->closeable($id))
|
||||||
|
$this->addSideMenuLink('Close',
|
||||||
|
array('action' => 'close', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
|
||||||
|
if ($this->Lease->isClosed($id))
|
||||||
|
$this->addSideMenuLink('Re-Open',
|
||||||
|
array('action' => 'open', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
|
||||||
// Prepare to render
|
// Prepare to render
|
||||||
$title = 'Lease: #' . $lease['Lease']['id'];
|
$title = 'Lease: #' . $lease['Lease']['id'];
|
||||||
$this->set(compact('lease', 'title',
|
$this->set(compact('lease', 'title',
|
||||||
|
|||||||
@@ -2,20 +2,17 @@
|
|||||||
|
|
||||||
class LedgerEntriesController extends AppController {
|
class LedgerEntriesController extends AppController {
|
||||||
|
|
||||||
var $sidemenu_links = array();
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* override: sideMenuLinks
|
* action: index / current / past / all
|
||||||
* - Generates controller specific links for the side menu
|
* - Creates a list of ledger entries
|
||||||
*/
|
*/
|
||||||
function sideMenuLinks() {
|
|
||||||
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
function index() { $this->gridView('All Ledger Entries'); }
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -120,8 +117,12 @@ class LedgerEntriesController extends AppController {
|
|||||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
$links['LedgerEntry'] = array('id');
|
$links['LedgerEntry'] = array('id');
|
||||||
$links['Transaction'] = array('id');
|
$links['Transaction'] = array('id');
|
||||||
$links['Ledger'] = array('id');
|
// REVISIT <AP>: 20090827
|
||||||
$links['Account'] = array('controller' => 'accounts', 'name');
|
// Need to take 'level' into account
|
||||||
|
if ($this->Permission->allow('controller.accounts')) {
|
||||||
|
$links['Ledger'] = array('id');
|
||||||
|
$links['Account'] = array('name');
|
||||||
|
}
|
||||||
$links['Tender'] = array('name');
|
$links['Tender'] = array('name');
|
||||||
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||||
}
|
}
|
||||||
@@ -135,12 +136,6 @@ class LedgerEntriesController extends AppController {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function view($id = null) {
|
function view($id = null) {
|
||||||
if (!$id) {
|
|
||||||
$this->Session->setFlash(__('Invalid Item.', true));
|
|
||||||
$this->redirect(array('controller' => 'accounts', 'action'=>'index'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the Entry and related fields
|
|
||||||
$entry = $this->LedgerEntry->find
|
$entry = $this->LedgerEntry->find
|
||||||
('first',
|
('first',
|
||||||
array('contain' => array
|
array('contain' => array
|
||||||
@@ -153,13 +148,16 @@ class LedgerEntriesController extends AppController {
|
|||||||
array('fields' => array('id', 'sequence', 'name'),
|
array('fields' => array('id', 'sequence', 'name'),
|
||||||
'Account' =>
|
'Account' =>
|
||||||
array('fields' => array('id', 'name', 'type'),
|
array('fields' => array('id', 'name', 'type'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
'Tender' =>
|
'Tender' =>
|
||||||
array('fields' => array('id', 'name'),
|
array('fields' => array('id', 'name'),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
'DebitDoubleEntry' => array('id'),
|
||||||
|
'CreditDoubleEntry' => array('id'),
|
||||||
|
|
||||||
'DebitEntry' => array('fields' => array('id', 'crdr')),
|
'DebitEntry' => array('fields' => array('id', 'crdr')),
|
||||||
'CreditEntry' => array('fields' => array('id', 'crdr')),
|
'CreditEntry' => array('fields' => array('id', 'crdr')),
|
||||||
),
|
),
|
||||||
@@ -167,6 +165,11 @@ class LedgerEntriesController extends AppController {
|
|||||||
'conditions' => array('LedgerEntry.id' => $id),
|
'conditions' => array('LedgerEntry.id' => $id),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
if (empty($entry) || empty($entry['Ledger']['Account'])) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('controller' => 'accounts', 'action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
if (!empty($entry['DebitEntry']) && !empty($entry['CreditEntry']))
|
if (!empty($entry['DebitEntry']) && !empty($entry['CreditEntry']))
|
||||||
die("LedgerEntry has both a matching DebitEntry and CreditEntry");
|
die("LedgerEntry has both a matching DebitEntry and CreditEntry");
|
||||||
if (empty($entry['DebitEntry']) && empty($entry['CreditEntry']))
|
if (empty($entry['DebitEntry']) && empty($entry['CreditEntry']))
|
||||||
@@ -181,6 +184,18 @@ class LedgerEntriesController extends AppController {
|
|||||||
else
|
else
|
||||||
$entry['MatchingEntry'] = $entry['DebitEntry'][0];
|
$entry['MatchingEntry'] = $entry['DebitEntry'][0];
|
||||||
|
|
||||||
|
if (empty($entry['DebitDoubleEntry']['id']))
|
||||||
|
$entry['DoubleEntry'] = $entry['CreditDoubleEntry'];
|
||||||
|
else
|
||||||
|
$entry['DoubleEntry'] = $entry['DebitDoubleEntry'];
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090816
|
||||||
|
// This page doesn't seem very useful, let's just keep it
|
||||||
|
// all to the double entry view.
|
||||||
|
$this->redirect(array('controller' => 'double_entries',
|
||||||
|
'action' => 'view',
|
||||||
|
$entry['DoubleEntry']['id']));
|
||||||
|
|
||||||
// Prepare to render.
|
// Prepare to render.
|
||||||
$title = "Ledger Entry #{$entry['LedgerEntry']['id']}";
|
$title = "Ledger Entry #{$entry['LedgerEntry']['id']}";
|
||||||
$this->set(compact('entry', 'title'));
|
$this->set(compact('entry', 'title'));
|
||||||
|
|||||||
@@ -2,25 +2,29 @@
|
|||||||
|
|
||||||
class LedgersController extends AppController {
|
class LedgersController extends AppController {
|
||||||
|
|
||||||
var $sidemenu_links =
|
|
||||||
array(array('name' => 'Ledgers', 'header' => true),
|
|
||||||
array('name' => 'Current', 'url' => array('controller' => 'ledgers', 'action' => 'current')),
|
|
||||||
array('name' => 'Closed', 'url' => array('controller' => 'ledgers', 'action' => 'closed')),
|
|
||||||
array('name' => 'All', 'url' => array('controller' => 'ledgers', 'action' => 'all')),
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* override: sideMenuLinks
|
* override: addGridViewSideMenuLinks
|
||||||
* - Generates controller specific links for the side menu
|
* - Adds grid view navigation side menu links
|
||||||
*/
|
*/
|
||||||
function sideMenuLinks() {
|
|
||||||
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
function addGridViewSideMenuLinks() {
|
||||||
|
parent::addGridViewSideMenuLinks();
|
||||||
|
|
||||||
|
$this->addSideMenuLink('Current',
|
||||||
|
array('controller' => 'ledgers', 'action' => 'current'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('Closed',
|
||||||
|
array('controller' => 'ledgers', 'action' => 'closed'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('All',
|
||||||
|
array('controller' => 'ledgers', 'action' => 'all'), null,
|
||||||
|
'CONTROLLER');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -50,24 +54,21 @@ class LedgersController extends AppController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function gridDataCountTables(&$params, &$model) {
|
function gridDataCountTables(&$params, &$model) {
|
||||||
// Our count should NOT include anything extra,
|
|
||||||
// so we need the virtual function to prevent
|
|
||||||
// the base class from just calling our
|
|
||||||
// gridDataTables function.
|
|
||||||
return parent::gridDataTables($params, $model);
|
|
||||||
}
|
|
||||||
|
|
||||||
function gridDataTables(&$params, &$model) {
|
|
||||||
return array
|
return array
|
||||||
('link' =>
|
('link' =>
|
||||||
array(// Models
|
array(// Models
|
||||||
'Account',
|
'Account',
|
||||||
'LedgerEntry',
|
|
||||||
'CloseTransaction',
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function gridDataTables(&$params, &$model) {
|
||||||
|
$tables = $this->gridDataCountTables($params, $model);
|
||||||
|
$tables['link'][] = 'LedgerEntry';
|
||||||
|
$tables['link'][] = 'CloseTransaction';
|
||||||
|
return $tables;
|
||||||
|
}
|
||||||
|
|
||||||
function gridDataFields(&$params, &$model) {
|
function gridDataFields(&$params, &$model) {
|
||||||
$fields = parent::gridDataFields($params, $model);
|
$fields = parent::gridDataFields($params, $model);
|
||||||
$fields[] = 'CONCAT(Account.id, "-", Ledger.sequence) AS id_sequence';
|
$fields[] = 'CONCAT(Account.id, "-", Ledger.sequence) AS id_sequence';
|
||||||
@@ -85,28 +86,32 @@ class LedgersController extends AppController {
|
|||||||
$conditions[] = array('Ledger.close_transaction_id !=' => null);
|
$conditions[] = array('Ledger.close_transaction_id !=' => null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$conditions[] = array('Account.level >=' =>
|
||||||
|
$this->Permission->level('controller.accounts'));
|
||||||
|
|
||||||
return $conditions;
|
return $conditions;
|
||||||
}
|
}
|
||||||
|
|
||||||
function gridDataOrder(&$params, &$model, $index, $direction) {
|
function gridDataOrder(&$params, &$model, $index, $direction) {
|
||||||
$id_sequence = false;
|
|
||||||
if ($index === 'id_sequence') {
|
|
||||||
$id_sequence = true;
|
|
||||||
$index = 'Ledger.account_id';
|
|
||||||
}
|
|
||||||
|
|
||||||
$order = parent::gridDataOrder($params, $model, $index, $direction);
|
$order = parent::gridDataOrder($params, $model, $index, $direction);
|
||||||
|
|
||||||
if ($id_sequence) {
|
// After sorting by whatever the user wants, add these
|
||||||
$order[] = 'Ledger.sequence ' . $direction;
|
// defaults into the sort mechanism. If we're already
|
||||||
}
|
// sorting by one of them, it will only be redundant,
|
||||||
|
// and should cause no harm (possible a longer query?)
|
||||||
|
$order[] = 'Account.name ' . $direction;
|
||||||
|
$order[] = 'Ledger.sequence ' . $direction;
|
||||||
|
|
||||||
return $order;
|
return $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
$links['Ledger'] = array('id_sequence');
|
// REVISIT <AP>: 20090827
|
||||||
$links['Account'] = array('name');
|
// Need to take 'level' into account
|
||||||
|
if ($this->Permission->allow('controller.accounts')) {
|
||||||
|
$links['Ledger'] = array('sequence');
|
||||||
|
$links['Account'] = array('name');
|
||||||
|
}
|
||||||
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,22 +124,24 @@ class LedgersController extends AppController {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function view($id = null) {
|
function view($id = null) {
|
||||||
if (!$id) {
|
|
||||||
$this->Session->setFlash(__('Invalid Item.', true));
|
|
||||||
$this->redirect(array('action'=>'index'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get details about the ledger itself (no entries yet)
|
|
||||||
$ledger = $this->Ledger->find
|
$ledger = $this->Ledger->find
|
||||||
('first',
|
('first',
|
||||||
array('contain' =>
|
array('contain' =>
|
||||||
array(// Models
|
array(// Models
|
||||||
'Account',
|
'Account',
|
||||||
),
|
),
|
||||||
'conditions' => array(array('Ledger.id' => $id)),
|
'conditions' => array(array('Ledger.id' => $id),
|
||||||
|
array('Account.level >=' =>
|
||||||
|
$this->Permission->level('controller.accounts')),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (empty($ledger)) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
// Get ledger stats for our summary box
|
// Get ledger stats for our summary box
|
||||||
$stats = $this->Ledger->stats($id);
|
$stats = $this->Ledger->stats($id);
|
||||||
|
|
||||||
|
|||||||
216
site/controllers/locks_controller.php
Normal file
216
site/controllers/locks_controller.php
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class LocksController extends AppController {
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* override: addGridViewSideMenuLinks
|
||||||
|
* - Adds grid view navigation side menu links
|
||||||
|
*/
|
||||||
|
|
||||||
|
function addGridViewSideMenuLinks() {
|
||||||
|
parent::addGridViewSideMenuLinks();
|
||||||
|
|
||||||
|
$this->addSideMenuLink('List',
|
||||||
|
array('controller' => 'locks', 'action' => 'all'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('Add',
|
||||||
|
array('controller' => 'locks', 'action' => 'add'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: index / all
|
||||||
|
* - Generate a listing of locks
|
||||||
|
*/
|
||||||
|
|
||||||
|
function index() { $this->all(); }
|
||||||
|
function all() { $this->gridView('Locks', 'all'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtuals: gridData
|
||||||
|
* - With the application controller handling the gridData action,
|
||||||
|
* these virtual functions ensure that the correct data is passed
|
||||||
|
* to jqGrid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* function gridDataCountTables(&$params, &$model) { */
|
||||||
|
/* return array('link' => array('Unit')); */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
function gridDataTables(&$params, &$model) {
|
||||||
|
$tables = parent::gridDataTables($params, $model);
|
||||||
|
$tables['link']['LocksUnit'] = array();
|
||||||
|
return $tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFields(&$params, &$model) {
|
||||||
|
$fields = parent::gridDataFields($params, $model);
|
||||||
|
$fields[] = 'COUNT(LocksUnit.id) AS inuse';
|
||||||
|
$fields[] = 'IF(Lock.qty > COUNT(LocksUnit.id), Lock.qty - COUNT(LocksUnit.id), 0) AS avail';
|
||||||
|
return $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
|
$links['Lock'] = array('name');
|
||||||
|
return parent::gridDataPostProcessLinks($params, $model, $records, $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' => 'locks', 'action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the lock and related fields
|
||||||
|
$this->Lock->id = $id;
|
||||||
|
$lock = $this->Lock->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array(),
|
||||||
|
));
|
||||||
|
//$lock['Lock'] = $lock[0] + $lock['lock'];
|
||||||
|
//unset($lock[0]);
|
||||||
|
|
||||||
|
$this->addSideMenuLink('Edit',
|
||||||
|
array('action' => 'edit', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
|
||||||
|
$this->addSideMenuLink('Delete',
|
||||||
|
array('action' => 'delete', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
|
||||||
|
$this->set(compact('lock'));
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = "Lock : {$lock['Lock']['name']}";
|
||||||
|
$this->set(compact('title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: edit
|
||||||
|
* - Edit customer information
|
||||||
|
*/
|
||||||
|
|
||||||
|
function edit($id = null) {
|
||||||
|
if (isset($this->data)) {
|
||||||
|
// Check to see if the operation was cancelled.
|
||||||
|
if (isset($this->params['form']['cancel'])) {
|
||||||
|
if (isset($this->data['Lock']['id']))
|
||||||
|
$this->redirect(array('action'=>'view', $this->data['Lock']['id']));
|
||||||
|
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the lock and all associated data
|
||||||
|
if (!$this->Lock->saveLock($this->data)) {
|
||||||
|
$this->Session->setFlash("LOCK SAVE FAILED", true);
|
||||||
|
pr("LOCK SAVE FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
// View the lock by redirect
|
||||||
|
$this->redirect(array('action'=>'view', $this->Lock->id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($id) {
|
||||||
|
// Get details on this customer, its contacts and leases
|
||||||
|
$lock = $this->Lock->find
|
||||||
|
('first', array
|
||||||
|
('conditions' => array('Lock.id' => $id),
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->data = $lock;
|
||||||
|
$title = 'Lock: ' . $this->data['Lock']['name'] . " : Edit";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$title = "Enter New Lock Information";
|
||||||
|
$this->data = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
//pr($this->data);
|
||||||
|
$this->set(compact('title'));
|
||||||
|
$this->render('edit');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: add
|
||||||
|
* - Add a new lock
|
||||||
|
*/
|
||||||
|
|
||||||
|
function add() {
|
||||||
|
$this->edit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: delete
|
||||||
|
* - Deletes an old lock
|
||||||
|
*/
|
||||||
|
function delete($id) {
|
||||||
|
if (isset($this->data)) {
|
||||||
|
// Check to see if the operation was cancelled.
|
||||||
|
if (isset($this->params['form']['cancel'])) {
|
||||||
|
if (isset($this->data['Lock']['id']))
|
||||||
|
$this->redirect(array('action'=>'view', $this->data['Lock']['id']));
|
||||||
|
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the lock and all associated data
|
||||||
|
if (!$this->Lock->destroy($this->data['Lock']['id'])) {
|
||||||
|
$this->Session->setFlash(__('Failed to delete lock.', true));
|
||||||
|
$this->redirect(array('action'=>'view', $this->data['Lock']['id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's gone. Go back to the list of locks
|
||||||
|
$this->redirect(array('controller' => 'locks', 'action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// User must specify an ID.
|
||||||
|
if (!$id) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('controller' => 'locks', 'action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the lock and related fields
|
||||||
|
$this->Lock->id = $id;
|
||||||
|
$lock = $this->Lock->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array('Unit'),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Make sure the lock isn't in use.
|
||||||
|
if (isset($lock['Unit']) && count($lock['Unit']) > 0) {
|
||||||
|
$this->Session->setFlash(__('Lock currently on units. Cannot be deleted!', true));
|
||||||
|
$this->redirect(array('action'=>'view', $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$this->data = $lock;
|
||||||
|
$title = "Delete Lock : {$lock['Lock']['name']}";
|
||||||
|
$this->set(compact('title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -52,6 +52,7 @@ class MapsController extends AppController {
|
|||||||
$this->Session->setFlash(__('Invalid Item.', true));
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
$this->redirect(array('action'=>'index'));
|
$this->redirect(array('action'=>'index'));
|
||||||
}
|
}
|
||||||
|
$this->sideMenuEnable('SITE', $this->op_area);
|
||||||
$this->set('info', $this->mapInfo($id, $requested_width));
|
$this->set('info', $this->mapInfo($id, $requested_width));
|
||||||
$this->set('title', "Site Map");
|
$this->set('title', "Site Map");
|
||||||
}
|
}
|
||||||
@@ -85,11 +86,35 @@ class MapsController extends AppController {
|
|||||||
'units' => array());
|
'units' => array());
|
||||||
|
|
||||||
// Find all of the map/unit information from this SiteArea
|
// Find all of the map/unit information from this SiteArea
|
||||||
$this->Map->recursive = 2;
|
$map = $this->Map->find('first', array('contain' => false,
|
||||||
$this->Map->SiteArea->unbindModel(array('hasOne' => array('Map')));
|
'conditions' => array('id' => $id)));
|
||||||
$map = $this->Map->read(null, $id);
|
|
||||||
//pr($map);
|
$units = $this->Map->Unit->find
|
||||||
|
('all',
|
||||||
|
array('link' =>
|
||||||
|
array('Map' =>
|
||||||
|
array('fields' => array()),
|
||||||
|
|
||||||
|
'CurrentLease' =>
|
||||||
|
array('fields' => array('id', 'paid_through_date',
|
||||||
|
$this->Map->Unit->CurrentLease->
|
||||||
|
delinquentField('CurrentLease')),
|
||||||
|
'Customer'),
|
||||||
|
|
||||||
|
'UnitSize' =>
|
||||||
|
array('fields' => array('id', 'depth', 'width',
|
||||||
|
'MapsUnit.pt_top',
|
||||||
|
'MapsUnit.pt_left',
|
||||||
|
'MapsUnit.transpose')),
|
||||||
|
),
|
||||||
|
'fields' => array('id', 'name', 'status'),
|
||||||
|
'conditions' => array('Map.id' => $id),
|
||||||
|
));
|
||||||
|
|
||||||
|
/* pr(compact('map', 'units')); */
|
||||||
|
/* $this->render('/empty'); */
|
||||||
|
/* return; */
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
* The preference would be to leave all things "screen" related
|
* The preference would be to leave all things "screen" related
|
||||||
* to reside in the view. However, two separate views need this
|
* to reside in the view. However, two separate views need this
|
||||||
@@ -113,7 +138,7 @@ class MapsController extends AppController {
|
|||||||
$info['depth'] = $bottom * $screen_adjustment_factor;
|
$info['depth'] = $bottom * $screen_adjustment_factor;
|
||||||
|
|
||||||
// Go through each unit in the map, calculating the map location
|
// Go through each unit in the map, calculating the map location
|
||||||
foreach ($map['Unit'] AS $unit) {
|
foreach ($units AS $unit) {
|
||||||
$lft = $unit['MapsUnit']['pt_left'] + $boundary_adjustment;
|
$lft = $unit['MapsUnit']['pt_left'] + $boundary_adjustment;
|
||||||
$top = $unit['MapsUnit']['pt_top'] + $boundary_adjustment;
|
$top = $unit['MapsUnit']['pt_top'] + $boundary_adjustment;
|
||||||
|
|
||||||
@@ -132,10 +157,9 @@ class MapsController extends AppController {
|
|||||||
$width *= $screen_adjustment_factor;
|
$width *= $screen_adjustment_factor;
|
||||||
$depth *= $screen_adjustment_factor;
|
$depth *= $screen_adjustment_factor;
|
||||||
|
|
||||||
//$info['units'][$unit['id']] =
|
|
||||||
$info['units'][] =
|
$info['units'][] =
|
||||||
array( 'id' => $unit['id'],
|
array( 'id' => $unit['Unit']['id'],
|
||||||
'name' => $unit['name'],
|
'name' => $unit['Unit']['name'],
|
||||||
'left' => $lft,
|
'left' => $lft,
|
||||||
'right' => $lft + $width,
|
'right' => $lft + $width,
|
||||||
'top' => $top,
|
'top' => $top,
|
||||||
@@ -143,11 +167,15 @@ class MapsController extends AppController {
|
|||||||
'width' => $width,
|
'width' => $width,
|
||||||
'depth' => $depth,
|
'depth' => $depth,
|
||||||
'n-s' => $unit['MapsUnit']['transpose'] ? 0 : 1,
|
'n-s' => $unit['MapsUnit']['transpose'] ? 0 : 1,
|
||||||
'status' => $unit['status']
|
'status' => (($unit['Unit']['status'] === 'OCCUPIED' &&
|
||||||
|
!empty($unit[0]['delinquent']))
|
||||||
|
? 'LATE' : $unit['Unit']['status']),
|
||||||
|
'data' => $unit,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//pr($info);
|
/* pr($info); */
|
||||||
|
/* $this->render('/empty'); exit(); */
|
||||||
return $info;
|
return $info;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,8 +188,10 @@ class MapsController extends AppController {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function legend($id = null, $requested_width = 400) {
|
function legend($id = null, $requested_width = 400) {
|
||||||
$status = $this->Map->Unit->activeStatusEnums();
|
$status = array_keys($this->Map->Unit->activeStatusEnums());
|
||||||
//pr($status);
|
$occupied_key = array_search('OCCUPIED', $status);
|
||||||
|
array_splice($status, $occupied_key+1, 0, array('LATE'));
|
||||||
|
|
||||||
$rows = 2;
|
$rows = 2;
|
||||||
$cols = (int)((count($status) + $rows - 1) / $rows);
|
$cols = (int)((count($status) + $rows - 1) / $rows);
|
||||||
|
|
||||||
@@ -191,7 +221,7 @@ class MapsController extends AppController {
|
|||||||
$item_width *= $screen_adjustment_factor;
|
$item_width *= $screen_adjustment_factor;
|
||||||
$item_depth *= $screen_adjustment_factor;
|
$item_depth *= $screen_adjustment_factor;
|
||||||
|
|
||||||
foreach ($status AS $code => $value) {
|
foreach ($status AS $code) {
|
||||||
$info['units'][] = array('name' => $code,
|
$info['units'][] = array('name' => $code,
|
||||||
'status' => $code,
|
'status' => $code,
|
||||||
'width' => $item_width,
|
'width' => $item_width,
|
||||||
@@ -241,9 +271,9 @@ class MapsController extends AppController {
|
|||||||
$info['palate']['unit']['DIRTY']['bg'] = array('red' => 128, 'green' => 192, 'blue' => 192);
|
$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']['VACANT']['bg'] = array('red' => 0, 'green' => 255, 'blue' => 128);
|
||||||
$info['palate']['unit']['OCCUPIED']['bg'] = array('red' => 0, 'green' => 128, 'blue' => 255);
|
$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']['LATE']['bg'] = array('red' => 255, 'green' => 192, 'blue' => 192);
|
||||||
$info['palate']['unit']['LOCKED']['bg'] = array('red' => 255, 'green' => 128, 'blue' => 128);
|
$info['palate']['unit']['LOCKED']['bg'] = array('red' => 255, 'green' => 64, 'blue' => 64);
|
||||||
$info['palate']['unit']['LIENED']['bg'] = array('red' => 255, 'green' => 192, 'blue' => 192);
|
$info['palate']['unit']['LIENED']['bg'] = array('red' => 255, 'green' => 0, 'blue' => 128);
|
||||||
|
|
||||||
// Determine text color to go with each background
|
// Determine text color to go with each background
|
||||||
foreach ($info['palate']['unit'] AS &$code) {
|
foreach ($info['palate']['unit'] AS &$code) {
|
||||||
|
|||||||
@@ -2,20 +2,18 @@
|
|||||||
|
|
||||||
class StatementEntriesController extends AppController {
|
class StatementEntriesController extends AppController {
|
||||||
|
|
||||||
var $sidemenu_links = array();
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* override: sideMenuLinks
|
* action: index / current / past / all
|
||||||
* - Generates controller specific links for the side menu
|
* - Creates a list of statement entries
|
||||||
*/
|
*/
|
||||||
function sideMenuLinks() {
|
|
||||||
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
function index() { $this->gridView('All Statement Entries'); }
|
||||||
|
function unpaid() { $this->gridView('Unpaid Charges', 'unreconciled'); }
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -25,7 +23,7 @@ class StatementEntriesController extends AppController {
|
|||||||
* to jqGrid.
|
* to jqGrid.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function gridDataTables(&$params, &$model) {
|
function gridDataCountTables(&$params, &$model) {
|
||||||
$link =
|
$link =
|
||||||
array(// Models
|
array(// Models
|
||||||
'Transaction' =>
|
'Transaction' =>
|
||||||
@@ -48,44 +46,55 @@ class StatementEntriesController extends AppController {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isset($params['post']['custom']['statement_entry_id'])) {
|
if (!empty($params['post']['custom']['statement_entry_id'])) {
|
||||||
$link['PaymentEntry'] = array();
|
$link['ChargeEntry'] = array();
|
||||||
$link['ChargeEntry'] = array();
|
// This query actually represents a union...
|
||||||
|
// Unpaid Charge/Surplus: ChargeID - NULL; DisbursementID - NULL
|
||||||
|
// Paid Charge/Refund: ChargeID - NULL; DisbursementID - !NULL
|
||||||
|
// Disbursement/Reversal: ChargeID - !NULL; DisbursementID - NULL
|
||||||
|
// <EMPTY SET>: ChargeID - !NULL; DisbursementID - !NULL
|
||||||
|
//
|
||||||
|
// The query is really slow unless we add the `id` condition to the join.
|
||||||
|
// A cleaner query would be nice, but we must work within the Cake framework.
|
||||||
|
$link['DisbursementEntry'] = array('conditions' =>
|
||||||
|
'`DisbursementEntry`.`id` = '
|
||||||
|
. $params['post']['custom']['statement_entry_id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if ($params['action'] === 'collected') { */
|
|
||||||
/* $link['PaymentEntry'] = 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['ChargeEntry'] = array(); */
|
|
||||||
/* } */
|
|
||||||
/* elseif (isset($params['post']['custom']['customer_id']) || isset($params['post']['custom']['lease_id'])) { */
|
|
||||||
/* $link['PaymentEntry'] = array(); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
return array('link' => $link);
|
return array('link' => $link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function gridDataTables(&$params, &$model) {
|
||||||
|
$tables = $this->gridDataCountTables($params, $model);
|
||||||
|
|
||||||
|
if (in_array('applied', $params['post']['fields'])) {
|
||||||
|
$tables['link'] +=
|
||||||
|
array('ChargeEntry' => array(),
|
||||||
|
'DisbursementEntry' => array());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tables;
|
||||||
|
}
|
||||||
|
|
||||||
function gridDataFields(&$params, &$model) {
|
function gridDataFields(&$params, &$model) {
|
||||||
$fields = parent::gridDataFields($params, $model);
|
$fields = parent::gridDataFields($params, $model);
|
||||||
|
|
||||||
if (in_array('applied', $params['post']['fields'])) {
|
if (in_array('applied', $params['post']['fields'])) {
|
||||||
$fields[] = ("IF(StatementEntry.type = 'CHARGE'," .
|
$fields[] = ("IF(StatementEntry.type = 'CHARGE'," .
|
||||||
" SUM(COALESCE(PaymentEntry.amount,0))," .
|
" SUM(COALESCE(DisbursementEntry.amount,0))," .
|
||||||
" SUM(COALESCE(ChargeEntry.amount,0)))" .
|
" SUM(COALESCE(ChargeEntry.amount,0)))" .
|
||||||
" AS 'applied'");
|
" AS 'applied'");
|
||||||
|
}
|
||||||
|
if (in_array('unapplied', $params['post']['fields'])) {
|
||||||
$fields[] = ("StatementEntry.amount - (" .
|
$fields[] = ("StatementEntry.amount - (" .
|
||||||
"IF(StatementEntry.type = 'CHARGE'," .
|
"IF(StatementEntry.type = 'CHARGE'," .
|
||||||
" SUM(COALESCE(PaymentEntry.amount,0))," .
|
" SUM(COALESCE(DisbursementEntry.amount,0))," .
|
||||||
" SUM(COALESCE(ChargeEntry.amount,0)))" .
|
" SUM(COALESCE(ChargeEntry.amount,0)))" .
|
||||||
") AS 'balance'");
|
") AS 'unapplied'");
|
||||||
}
|
}
|
||||||
|
|
||||||
$fields = array_merge($fields,
|
$fields = array_merge($fields,
|
||||||
$this->StatementEntry->chargePaymentFields());
|
$this->StatementEntry->chargeDisbursementFields());
|
||||||
|
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
@@ -107,11 +116,13 @@ class StatementEntriesController extends AppController {
|
|||||||
if (isset($account_id))
|
if (isset($account_id))
|
||||||
$conditions[] = array('StatementEntry.account_id' => $account_id);
|
$conditions[] = array('StatementEntry.account_id' => $account_id);
|
||||||
|
|
||||||
if (isset($statement_entry_id)) {
|
if (isset($customer_id))
|
||||||
|
$conditions[] = array('StatementEntry.customer_id' => $customer_id);
|
||||||
|
|
||||||
|
if (isset($statement_entry_id))
|
||||||
$conditions[] = array('OR' =>
|
$conditions[] = array('OR' =>
|
||||||
array(array('ChargeEntry.id' => $statement_entry_id),
|
array(array('ChargeEntry.id' => $statement_entry_id),
|
||||||
array('PaymentEntry.id' => $statement_entry_id)));
|
array('DisbursementEntry.id' => $statement_entry_id)));
|
||||||
}
|
|
||||||
|
|
||||||
return $conditions;
|
return $conditions;
|
||||||
}
|
}
|
||||||
@@ -119,7 +130,10 @@ class StatementEntriesController extends AppController {
|
|||||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
$links['StatementEntry'] = array('id');
|
$links['StatementEntry'] = array('id');
|
||||||
$links['Transaction'] = array('id');
|
$links['Transaction'] = array('id');
|
||||||
$links['Account'] = array('name');
|
// REVISIT <AP>: 20090827
|
||||||
|
// Need to take 'level' into account
|
||||||
|
if ($this->Permission->allow('controller.accounts'))
|
||||||
|
$links['Account'] = array('name');
|
||||||
$links['Customer'] = array('name');
|
$links['Customer'] = array('name');
|
||||||
$links['Lease'] = array('number');
|
$links['Lease'] = array('number');
|
||||||
$links['Unit'] = array('name');
|
$links['Unit'] = array('name');
|
||||||
@@ -133,34 +147,49 @@ class StatementEntriesController extends AppController {
|
|||||||
// defaults into the sort mechanism. If we're already
|
// defaults into the sort mechanism. If we're already
|
||||||
// sorting by one of them, it will only be redundant,
|
// sorting by one of them, it will only be redundant,
|
||||||
// and should cause no harm (possible a longer query?)
|
// and should cause no harm (possible a longer query?)
|
||||||
$order[] = 'Transaction.stamp ' . $direction;
|
if ($index != 'Transaction.stamp' &&
|
||||||
$order[] = 'StatementEntry.effective_date ' . $direction;
|
$index != 'StatementEntry.effective_date') {
|
||||||
|
$order[] = 'Transaction.stamp ' . $direction;
|
||||||
|
$order[] = 'StatementEntry.effective_date ' . $direction;
|
||||||
|
}
|
||||||
$order[] = 'StatementEntry.id ' . $direction;
|
$order[] = 'StatementEntry.id ' . $direction;
|
||||||
|
|
||||||
return $order;
|
return $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
function gridDataRecordsExecute(&$params, &$model, $query) {
|
function gridDataCountExecute(&$params, &$model, $query) {
|
||||||
if (in_array('applied', $params['post']['fields'])) {
|
if ($params['action'] === 'unreconciled') {
|
||||||
$tquery = array_diff_key($query, array('fields'=>1,'group'=>1,'limit'=>1,'order'=>1));
|
// REVISIT <AP> 20100413:
|
||||||
$tquery['fields'] = array("IF(StatementEntry.type = 'CHARGE'," .
|
// This is a lame solution, as it runs the same queries twice
|
||||||
" SUM(COALESCE(PaymentEntry.amount,0))," .
|
// (and causes code duplication). However, I'm not in the mood
|
||||||
" SUM(COALESCE(ChargeEntry.amount,0)))" .
|
// to flush out an actual "count" solution at the moment, and I
|
||||||
" AS 'applied'",
|
// also don't want to cache the results in $params (although
|
||||||
|
// that is probably the most sensible solution). So, I'll just
|
||||||
"StatementEntry.amount - (" .
|
// calculate the reconciled set both times and live with the
|
||||||
"IF(StatementEntry.type = 'CHARGE'," .
|
// performance and maintenance penalty
|
||||||
" SUM(COALESCE(PaymentEntry.amount,0))," .
|
$lquery = array('conditions' => $query['conditions']);
|
||||||
" SUM(COALESCE(ChargeEntry.amount,0)))" .
|
$set = $this->StatementEntry->reconciledSet('CHARGE', $lquery, true);
|
||||||
") AS 'balance'",
|
return count($set['entries']);
|
||||||
);
|
|
||||||
|
|
||||||
//pr(compact('tquery'));
|
|
||||||
$total = $model->find('first', $tquery);
|
|
||||||
$params['userdata']['total'] = $total[0]['applied'];
|
|
||||||
$params['userdata']['balance'] = $total[0]['balance'];
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
|
return parent::gridDataCountExecute($params, $model, $query);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataRecordsExecute(&$params, &$model, $query) {
|
||||||
|
|
||||||
|
if ($params['action'] === 'unreconciled') {
|
||||||
|
$lquery = array('conditions' => $query['conditions']);
|
||||||
|
$set = $this->StatementEntry->reconciledSet('CHARGE', $lquery, true);
|
||||||
|
|
||||||
|
$entries = array();
|
||||||
|
foreach ($set['entries'] AS $entry)
|
||||||
|
$entries[] = $entry['StatementEntry']['id'];
|
||||||
|
|
||||||
|
$query['conditions'] = array('StatementEntry.id' => $entries);
|
||||||
|
$params['userdata']['balance'] = $set['summary']['balance'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($params['action'] === 'collected') {
|
||||||
$tquery = array_diff_key($query, array('fields'=>1,'group'=>1,'limit'=>1,'order'=>1));
|
$tquery = array_diff_key($query, array('fields'=>1,'group'=>1,'limit'=>1,'order'=>1));
|
||||||
$tquery['fields'] = array("SUM(COALESCE(StatementEntry.amount,0)) AS 'total'");
|
$tquery['fields'] = array("SUM(COALESCE(StatementEntry.amount,0)) AS 'total'");
|
||||||
$total = $model->find('first', $tquery);
|
$total = $model->find('first', $tquery);
|
||||||
@@ -177,12 +206,149 @@ class StatementEntriesController extends AppController {
|
|||||||
* action: reverse the ledger entry
|
* action: reverse the ledger entry
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function reverse($id) {
|
function reverse($id = null) {
|
||||||
$this->StatementEntry->reverse($id);
|
if ($this->data) {
|
||||||
|
//pr($this->data); die();
|
||||||
|
|
||||||
|
$this->StatementEntry->reverse
|
||||||
|
($this->data['StatementEntry']['id'],
|
||||||
|
$this->data['Transaction']['stamp'],
|
||||||
|
$this->data['Transaction']['comment']);
|
||||||
|
|
||||||
|
$this->redirect(array('action'=>'view',
|
||||||
|
$this->data['StatementEntry']['id']));
|
||||||
|
$this->INTERNAL_ERROR('SHOULD HAVE REDIRECTED');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->StatementEntry->id = $id;
|
||||||
|
$entry = $this->StatementEntry->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array('Customer', 'Transaction', 'Account'),
|
||||||
|
));
|
||||||
|
|
||||||
|
if (empty($entry)) {
|
||||||
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
|
$this->redirect(array('controller' => 'customers',
|
||||||
|
'action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->StatementEntry->reversable($id)) {
|
||||||
|
$this->Session->setFlash(__('Item not reversable.', true));
|
||||||
|
$this->redirect(array('action'=>'view', $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = ("Charge #{$entry['StatementEntry']['id']}" .
|
||||||
|
" : {$entry['StatementEntry']['amount']}" .
|
||||||
|
" : Reverse");
|
||||||
|
$this->set(compact('entry', 'title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: waive the ledger entry
|
||||||
|
*/
|
||||||
|
|
||||||
|
function waive($id) {
|
||||||
|
$this->StatementEntry->waive($id);
|
||||||
$this->redirect(array('action'=>'view', $id));
|
$this->redirect(array('action'=>'view', $id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: incexpbymonth
|
||||||
|
* - Displays income and/or expenses by month
|
||||||
|
*/
|
||||||
|
|
||||||
|
function incexpbymonth($accts, $security_deposits, $months) {
|
||||||
|
$datefrom = 'DATE(NOW() - INTERVAL '.($months-1).' MONTH - INTERVAL DAY(NOW())-1 DAY)';
|
||||||
|
$dateto = 'NOW()';
|
||||||
|
/* $datefrom = '"2009-01-01"'; */
|
||||||
|
/* $dateto = '"2012-12-31"'; */
|
||||||
|
|
||||||
|
$result = $this->StatementEntry->find
|
||||||
|
('all',
|
||||||
|
array('link' => array('Account' => array('fields' => 'name')),
|
||||||
|
'fields' => array_merge(array('MONTHNAME(effective_date) AS month',
|
||||||
|
'YEAR(effective_date) AS year'),
|
||||||
|
$this->StatementEntry->chargeDisbursementFields(true)),
|
||||||
|
'conditions' => array('Account.type' => $accts,
|
||||||
|
"effective_date >= $datefrom",
|
||||||
|
"effective_date <= $dateto",
|
||||||
|
),
|
||||||
|
'group' => array('YEAR(effective_date)', 'MONTH(effective_date)', 'Account.id'),
|
||||||
|
'order' => array('YEAR(effective_date) DESC', 'MONTH(effective_date) DESC', 'Account.type',
|
||||||
|
'IF(Account.id = '.$this->StatementEntry->Account->rentAccountID().', "---", Account.name)'),
|
||||||
|
));
|
||||||
|
|
||||||
|
if ($security_deposits) {
|
||||||
|
$sdresult = $this->StatementEntry->Transaction->LedgerEntry->find
|
||||||
|
('all',
|
||||||
|
array('link' => array('Transaction' => array('StatementEntry' => array('fields' => 'effective_date'),
|
||||||
|
'fields' => array()),
|
||||||
|
'Account' => array('fields' => 'name')),
|
||||||
|
'fields' => array_merge(array('MONTHNAME(effective_date) AS month',
|
||||||
|
'YEAR(effective_date) AS year'),
|
||||||
|
$this->StatementEntry->Transaction->LedgerEntry->debitCreditFields(true)),
|
||||||
|
'conditions' => array('LedgerEntry.account_id' => $this->StatementEntry->Account->securityDepositAccountID(),
|
||||||
|
"effective_date >= $datefrom",
|
||||||
|
"effective_date <= $dateto",
|
||||||
|
'StatementEntry.id = (SELECT MIN(id) FROM statement_entries WHERE transaction_id = `Transaction`.id)'
|
||||||
|
),
|
||||||
|
'group' => array('YEAR(effective_date)', 'MONTH(effective_date)', 'Account.id'),
|
||||||
|
'order' => array('YEAR(effective_date) DESC', 'MONTH(effective_date) DESC', 'Account.type', 'Account.name'),
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
$sdresult = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$overview = array('months' => array(), 'amount' => 0);
|
||||||
|
foreach (array_merge($result, $sdresult) AS $row) {
|
||||||
|
$mname = $row[0]['month'] .', '. $row[0]['year'];
|
||||||
|
if (empty($overview['months'][$mname]))
|
||||||
|
$overview['months'][$mname] = array('name' => $mname,
|
||||||
|
'subs' => array(),
|
||||||
|
'amount' => 0);
|
||||||
|
$month = &$overview['months'][$mname];
|
||||||
|
$month['subs'][] = array('name' => $row['Account']['name'],
|
||||||
|
'amount' => $row[0]['balance']);
|
||||||
|
|
||||||
|
$month['amount'] += $row[0]['balance'];
|
||||||
|
$overview['amount'] += $row[0]['balance'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable the Reports menu section
|
||||||
|
$this->sideMenuAreaActivate('REPORT');
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$this->set('months', $months);
|
||||||
|
$this->set(compact('overview'));
|
||||||
|
$this->render('chargesbymonth');
|
||||||
|
}
|
||||||
|
|
||||||
|
function incomebymonth($months = 12, $invoice = false) {
|
||||||
|
$this->set('title', 'Monthly Gross Income');
|
||||||
|
$this->set('reptype', 'Gross Income');
|
||||||
|
$this->incexpbymonth(array('INCOME'), $invoice, $months);
|
||||||
|
}
|
||||||
|
|
||||||
|
function expensebymonth($months = 12) {
|
||||||
|
$this->set('title', 'Gross Monthly Expenses');
|
||||||
|
$this->set('reptype', 'Gross Expenses');
|
||||||
|
$this->incexpbymonth(array('EXPENSE'), false, $months);
|
||||||
|
}
|
||||||
|
|
||||||
|
function netbymonth($months = 12) {
|
||||||
|
$this->set('title', 'Net Monthly Income');
|
||||||
|
$this->set('reptype', 'Net Income');
|
||||||
|
$this->incexpbymonth(array('INCOME', 'EXPENSE'), true, $months);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -191,74 +357,53 @@ class StatementEntriesController extends AppController {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function view($id = null) {
|
function view($id = null) {
|
||||||
if (!$id) {
|
$entry = $this->StatementEntry->find
|
||||||
|
('first',
|
||||||
|
array('contain' => array
|
||||||
|
('Transaction' => array('fields' => array('id', 'type', 'stamp')),
|
||||||
|
'Account' => array('id', 'name', 'type', 'level'),
|
||||||
|
'Customer' => array('fields' => array('id', 'name')),
|
||||||
|
'Lease' => array('fields' => array('id', 'number')),
|
||||||
|
),
|
||||||
|
|
||||||
|
'conditions' => array(array('StatementEntry.id' => $id),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
if (empty($entry)) {
|
||||||
$this->Session->setFlash(__('Invalid Item.', true));
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
$this->redirect(array('controller' => 'accounts', 'action'=>'index'));
|
$this->redirect(array('controller' => 'accounts', 'action'=>'index'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the StatementEntry and related fields
|
$entry['Account']['link'] =
|
||||||
$entry = $this->StatementEntry->find
|
$entry['Account']['level'] >=
|
||||||
('first',
|
$this->Permission->level('controller.accounts');
|
||||||
array('contain' => array
|
|
||||||
('Transaction' => array('fields' => array('id', 'stamp')),
|
|
||||||
'Account' => array('id', 'name', 'type'),
|
|
||||||
'Customer' => array('fields' => array('id', 'name')),
|
|
||||||
'Lease' => array('fields' => array('id')),
|
|
||||||
),
|
|
||||||
|
|
||||||
'conditions' => array('StatementEntry.id' => $id),
|
|
||||||
));
|
|
||||||
|
|
||||||
$reconciled = $this->StatementEntry->reconciledEntries($id);
|
|
||||||
|
|
||||||
|
|
||||||
/* // REVISIT <AP>: 20090711 */
|
|
||||||
/* // It's not clear whether we should be able to reverse charges that have */
|
|
||||||
/* // already been paid/cleared/reconciled. Certainly, that will be the */
|
|
||||||
/* // case when someone has pre-paid and then moves out early. However, this */
|
|
||||||
/* // will work well for items accidentally charged but not yet paid for. */
|
|
||||||
/* if ((!$entry['DebitLedger']['Account']['trackable'] || */
|
|
||||||
/* $stats['debit']['amount_reconciled'] == 0) && */
|
|
||||||
/* (!$entry['CreditLedger']['Account']['trackable'] || */
|
|
||||||
/* $stats['credit']['amount_reconciled'] == 0) */
|
|
||||||
|
|
||||||
/* && 0 */
|
|
||||||
|
|
||||||
/* ) */
|
|
||||||
/* { */
|
|
||||||
/* // Set up dynamic menu items */
|
|
||||||
/* $this->sidemenu_links[] = */
|
|
||||||
/* array('name' => 'Operations', 'header' => true); */
|
|
||||||
|
|
||||||
/* $this->sidemenu_links[] = */
|
|
||||||
/* array('name' => 'Undo', */
|
|
||||||
/* 'url' => array('action' => 'reverse', */
|
|
||||||
/* $id)); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
/* if ($this->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);
|
$stats = $this->StatementEntry->stats($id);
|
||||||
|
|
||||||
if (strtoupper($entry['StatementEntry']['type']) === 'CHARGE')
|
if (in_array(strtoupper($entry['StatementEntry']['type']), $this->StatementEntry->debitTypes()))
|
||||||
$stats = $stats['Charge'];
|
$stats = $stats['Charge'];
|
||||||
else
|
else
|
||||||
$stats = $stats['Payment'];
|
$stats = $stats['Disbursement'];
|
||||||
|
|
||||||
|
|
||||||
|
if (strtoupper($entry['StatementEntry']['type']) === 'CHARGE') {
|
||||||
|
|
||||||
|
// Set up dynamic menu items
|
||||||
|
if ($this->StatementEntry->reversable($id))
|
||||||
|
$this->addSideMenuLink('Reverse',
|
||||||
|
array('action' => 'reverse', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
|
||||||
|
if ($stats['balance'] > 0)
|
||||||
|
$this->addSideMenuLink('Waive Balance',
|
||||||
|
array('action' => 'waive', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare to render.
|
// Prepare to render.
|
||||||
$title = "Statement Entry #{$entry['StatementEntry']['id']}";
|
$title = "Statement Entry #{$entry['StatementEntry']['id']}";
|
||||||
$this->set(compact('entry', 'title', 'reconciled', 'stats'));
|
$this->set(compact('entry', 'title', 'stats'));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,20 +2,7 @@
|
|||||||
|
|
||||||
class TendersController extends AppController {
|
class TendersController extends AppController {
|
||||||
|
|
||||||
var $sidemenu_links = array();
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* override: sideMenuLinks
|
|
||||||
* - Generates controller specific links for the side menu
|
|
||||||
*/
|
|
||||||
function sideMenuLinks() {
|
|
||||||
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -75,7 +62,7 @@ class TendersController extends AppController {
|
|||||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
$links['Tender'] = array('name', 'id');
|
$links['Tender'] = array('name', 'id');
|
||||||
$links['Customer'] = array('name');
|
$links['Customer'] = array('name');
|
||||||
$links['TenderType'] = array('name');
|
//$links['TenderType'] = array('name');
|
||||||
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,15 +102,33 @@ class TendersController extends AppController {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function nsf($id = null) {
|
function nsf($id = null) {
|
||||||
|
if ($this->data) {
|
||||||
|
$result = $this->Tender->nsf
|
||||||
|
($this->data['Tender']['id'],
|
||||||
|
$this->data['Transaction']['stamp'],
|
||||||
|
$this->data['Transaction']['comment']);
|
||||||
|
$this->redirect(array('controller' => 'tenders',
|
||||||
|
'action' => 'view',
|
||||||
|
$this->data['Tender']['id']));
|
||||||
|
}
|
||||||
|
|
||||||
if (!$id) {
|
if (!$id) {
|
||||||
$this->Session->setFlash(__('Invalid Item.', true));
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
$this->redirect(array('action'=>'index'));
|
$this->redirect(array('action'=>'index'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->Tender->nsf($id);
|
$this->Tender->id = $id;
|
||||||
$this->redirect(array('action'=>'view', $id));
|
$tender = $this->Tender->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array('Customer', 'LedgerEntry' => array('Transaction')),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = "Tender #{$tender['Tender']['id']} : {$tender['Tender']['name']} : NSF";
|
||||||
|
$this->set(compact('tender', 'title'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -138,6 +143,7 @@ class TendersController extends AppController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the Tender and related fields
|
// Get the Tender and related fields
|
||||||
|
$this->Tender->id = $id;
|
||||||
$tender = $this->Tender->find
|
$tender = $this->Tender->find
|
||||||
('first', array
|
('first', array
|
||||||
('contain' => array('TenderType', 'Customer', 'LedgerEntry' => array('Transaction')),
|
('contain' => array('TenderType', 'Customer', 'LedgerEntry' => array('Transaction')),
|
||||||
@@ -148,20 +154,87 @@ class TendersController extends AppController {
|
|||||||
&& empty($tender['Tender']['nsf_transaction_id'])
|
&& empty($tender['Tender']['nsf_transaction_id'])
|
||||||
// Hard to tell what types of items can come back as NSF.
|
// Hard to tell what types of items can come back as NSF.
|
||||||
// For now, assume iff it is a named item, it can be NSF.
|
// For now, assume iff it is a named item, it can be NSF.
|
||||||
&& !empty($tender['TenderType']['data1_name'])
|
// (or if we're in development mode)
|
||||||
|
&& (!empty($tender['TenderType']['data1_name']) || !empty($this->params['dev']))
|
||||||
) {
|
) {
|
||||||
// Set up dynamic menu items
|
$this->addSideMenuLink('NSF',
|
||||||
$this->sidemenu_links[] =
|
array('action' => 'nsf', $id), null,
|
||||||
array('name' => 'Operations', 'header' => true);
|
'ACTION');
|
||||||
|
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'NSF',
|
|
||||||
'url' => array('action' => 'nsf',
|
|
||||||
$id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Watch out for the special "Closing" entries, which have
|
||||||
|
// tender_type_id set to NULL. Otherwise, allow editing.
|
||||||
|
if (!empty($tender['TenderType']['id']))
|
||||||
|
$this->addSideMenuLink('Edit',
|
||||||
|
array('action' => 'edit', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
|
||||||
// Prepare to render.
|
// Prepare to render.
|
||||||
$title = "Tender #{$tender['Tender']['id']}";
|
$title = "Tender #{$tender['Tender']['id']} : {$tender['Tender']['name']}";
|
||||||
$this->set(compact('tender', 'title'));
|
$this->set(compact('tender', 'title'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: edit
|
||||||
|
* - Edit tender information
|
||||||
|
*/
|
||||||
|
|
||||||
|
function edit($id = null) {
|
||||||
|
if (isset($this->data)) {
|
||||||
|
// Check to see if the operation was cancelled.
|
||||||
|
if (isset($this->params['form']['cancel'])) {
|
||||||
|
if (empty($this->data['Tender']['id']))
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
|
||||||
|
$this->redirect(array('action'=>'view', $this->data['Tender']['id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we have tender data
|
||||||
|
if (empty($this->data['Tender']) || empty($this->data['Tender']['id']))
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
|
||||||
|
// Figure out which tender type was chosen
|
||||||
|
// REVISIT <AP>: 20090810; Not ready to change tender type
|
||||||
|
// $tender_type_id = $this->data['Tender']['tender_type_id'];
|
||||||
|
$tender_type_id = $this->Tender->field('tender_type_id');
|
||||||
|
if (empty($tender_type_id))
|
||||||
|
$this->redirect(array('action'=>'view', $this->data['Tender']['id']));
|
||||||
|
|
||||||
|
// Get data fields from the selected tender type
|
||||||
|
$this->data['Tender'] += $this->data['type'][$tender_type_id];
|
||||||
|
unset($this->data['type']);
|
||||||
|
|
||||||
|
// Save the tender and all associated data
|
||||||
|
$this->Tender->create();
|
||||||
|
$this->Tender->id = $this->data['Tender']['id'];
|
||||||
|
if (!$this->Tender->save($this->data, false)) {
|
||||||
|
$this->Session->setFlash("TENDER SAVE FAILED", true);
|
||||||
|
pr("TENDER SAVE FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->redirect(array('action'=>'view', $this->Tender->id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($id) {
|
||||||
|
$this->data = $this->Tender->findById($id);
|
||||||
|
} else {
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$tender_types = $this->Tender->TenderType->find
|
||||||
|
('list', array('order' => array('name')));
|
||||||
|
$this->set(compact('tender_types'));
|
||||||
|
|
||||||
|
$types = $this->Tender->TenderType->find('all', array('contain' => false));
|
||||||
|
$this->set(compact('types'));
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = ('Tender #' . $this->data['Tender']['id'] .
|
||||||
|
' : ' . $this->data['Tender']['name'] .
|
||||||
|
" : Edit");
|
||||||
|
$this->set(compact('title'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,26 +4,38 @@ class TransactionsController extends AppController {
|
|||||||
|
|
||||||
var $components = array('RequestHandler');
|
var $components = array('RequestHandler');
|
||||||
|
|
||||||
var $sidemenu_links =
|
|
||||||
array(array('name' => 'Transactions', 'header' => true),
|
|
||||||
array('name' => 'All', 'url' => array('controller' => 'transactions', 'action' => 'all')),
|
|
||||||
array('name' => 'Invoices', 'url' => array('controller' => 'transactions', 'action' => 'invoice')),
|
|
||||||
array('name' => 'Receipts', 'url' => array('controller' => 'transactions', 'action' => 'receipt')),
|
|
||||||
array('name' => 'Deposits', 'url' => array('controller' => 'transactions', 'action' => 'deposit')),
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* override: sideMenuLinks
|
* override: addGridViewSideMenuLinks
|
||||||
* - Generates controller specific links for the side menu
|
* - Adds grid view navigation side menu links
|
||||||
*/
|
*/
|
||||||
function sideMenuLinks() {
|
|
||||||
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
function addGridViewSideMenuLinks() {
|
||||||
|
parent::addGridViewSideMenuLinks();
|
||||||
|
|
||||||
|
$this->addSideMenuLink('Invoices',
|
||||||
|
array('controller' => 'transactions', 'action' => 'invoice'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('Receipts',
|
||||||
|
array('controller' => 'transactions', 'action' => 'receipt'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('Deposits',
|
||||||
|
array('controller' => 'transactions', 'action' => 'deposit'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('All',
|
||||||
|
array('controller' => 'transactions', 'action' => 'all'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090824
|
||||||
|
// Right now, we wish to keep things simple. Don't make these
|
||||||
|
// links available to non-admin users.
|
||||||
|
if (empty($this->params['admin']))
|
||||||
|
$this->sideMenuEnable('CONTROLLER', $this->std_area, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -35,7 +47,18 @@ class TransactionsController extends AppController {
|
|||||||
function all() { $this->gridView('All Transactions', 'all'); }
|
function all() { $this->gridView('All Transactions', 'all'); }
|
||||||
function invoice() { $this->gridView('Invoices'); }
|
function invoice() { $this->gridView('Invoices'); }
|
||||||
function receipt() { $this->gridView('Receipts'); }
|
function receipt() { $this->gridView('Receipts'); }
|
||||||
function deposit() { $this->gridView('Deposits'); }
|
function deposit() {
|
||||||
|
/* $this->addSideMenuLink('New Deposit', */
|
||||||
|
/* array('controller' => 'tenders', 'action' => 'deposit'), null, */
|
||||||
|
/* 'CONTROLLER', $this->new_area); */
|
||||||
|
$this->gridView('Deposits');
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridView($title, $action = null, $element = null) {
|
||||||
|
if ($title != 'Deposits')
|
||||||
|
$this->set('include', array('Customer'));
|
||||||
|
parent::gridView($title, $action, $element);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
@@ -48,13 +71,19 @@ class TransactionsController extends AppController {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function gridDataCountTables(&$params, &$model) {
|
function gridDataCountTables(&$params, &$model) {
|
||||||
return parent::gridDataTables($params, $model);
|
return array
|
||||||
|
('link' =>
|
||||||
|
array(// Models
|
||||||
|
'Account' => array('fields' => array()),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function gridDataTables(&$params, &$model) {
|
function gridDataTables(&$params, &$model) {
|
||||||
$link = $this->gridDataCountTables($params, $model);
|
$link = $this->gridDataCountTables($params, $model);
|
||||||
$link['link']['StatementEntry'] = array('fields' => array());
|
$link['link']['StatementEntry'] = array('fields' => array());
|
||||||
$link['link']['DepositTender'] = array('fields' => array());
|
$link['link']['DepositTender'] = array('fields' => array());
|
||||||
|
$link['link']['Customer'] = array('fields' => array('id', 'name'));
|
||||||
return $link;
|
return $link;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +93,8 @@ class TransactionsController extends AppController {
|
|||||||
$fields[] = ("IF(Transaction.type = 'DEPOSIT'," .
|
$fields[] = ("IF(Transaction.type = 'DEPOSIT'," .
|
||||||
" COUNT(DepositTender.id)," .
|
" COUNT(DepositTender.id)," .
|
||||||
" COUNT(StatementEntry.id)) AS entries");
|
" COUNT(StatementEntry.id)) AS entries");
|
||||||
return $fields;
|
return array_merge($fields,
|
||||||
|
$this->Transaction->LedgerEntry->debitCreditFields(false, true, 'Transaction'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function gridDataConditions(&$params, &$model) {
|
function gridDataConditions(&$params, &$model) {
|
||||||
@@ -77,7 +107,9 @@ class TransactionsController extends AppController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
$links['Transaction'] = array('id');
|
$links['Transaction'] = array('id', 'action' => ($params['action'] == 'deposit'
|
||||||
|
? 'deposit_slip' : 'view'));
|
||||||
|
$links['Customer'] = array('name');
|
||||||
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
return parent::gridDataPostProcessLinks($params, $model, $records, $links);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +121,7 @@ class TransactionsController extends AppController {
|
|||||||
* - handles the creation of a charge invoice
|
* - handles the creation of a charge invoice
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function postInvoice() {
|
function postInvoice($redirect = true) {
|
||||||
if (!$this->RequestHandler->isPost()) {
|
if (!$this->RequestHandler->isPost()) {
|
||||||
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
||||||
return;
|
return;
|
||||||
@@ -104,6 +136,17 @@ class TransactionsController extends AppController {
|
|||||||
die("<H1>INVOICE FAILED</H1>");
|
die("<H1>INVOICE FAILED</H1>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($redirect) {
|
||||||
|
if (!empty($this->data['Customer']['id']))
|
||||||
|
$this->redirect(array('controller' => 'customers',
|
||||||
|
'action' => 'receipt',
|
||||||
|
$this->data['Customer']['id']));
|
||||||
|
else
|
||||||
|
$this->redirect(array('controller' => 'leases',
|
||||||
|
'action' => 'view',
|
||||||
|
$this->data['Lease']['id']));
|
||||||
|
}
|
||||||
|
|
||||||
$this->layout = null;
|
$this->layout = null;
|
||||||
$this->autoLayout = false;
|
$this->autoLayout = false;
|
||||||
$this->autoRender = false;
|
$this->autoRender = false;
|
||||||
@@ -114,10 +157,10 @@ class TransactionsController extends AppController {
|
|||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* action: postReceipt
|
* action: postReceipt
|
||||||
* - handles the creation of a payment receipt
|
* - handles the creation of a receipt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function postReceipt() {
|
function postReceipt($redirect = true) {
|
||||||
if (!$this->RequestHandler->isPost()) {
|
if (!$this->RequestHandler->isPost()) {
|
||||||
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
||||||
return;
|
return;
|
||||||
@@ -141,6 +184,11 @@ class TransactionsController extends AppController {
|
|||||||
die("<H1>RECEIPT FAILED</H1>");
|
die("<H1>RECEIPT FAILED</H1>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($redirect)
|
||||||
|
$this->redirect(array('controller' => 'customers',
|
||||||
|
'action' => 'view',
|
||||||
|
$this->data['Customer']['id']));
|
||||||
|
|
||||||
$this->layout = null;
|
$this->layout = null;
|
||||||
$this->autoLayout = false;
|
$this->autoLayout = false;
|
||||||
$this->autoRender = false;
|
$this->autoRender = false;
|
||||||
@@ -253,7 +301,7 @@ class TransactionsController extends AppController {
|
|||||||
$this->Session->setFlash(__('Unable to Create Deposit', true));
|
$this->Session->setFlash(__('Unable to Create Deposit', true));
|
||||||
$this->redirect(array('controller' => 'tenders', 'action'=>'deposit'));
|
$this->redirect(array('controller' => 'tenders', 'action'=>'deposit'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present the deposit slip to the user
|
// Present the deposit slip to the user
|
||||||
$this->redirect(array('controller' => 'transactions',
|
$this->redirect(array('controller' => 'transactions',
|
||||||
'action' => 'deposit_slip',
|
'action' => 'deposit_slip',
|
||||||
@@ -261,6 +309,107 @@ class TransactionsController extends AppController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: postWriteOff
|
||||||
|
* - handles the write off of bad debt
|
||||||
|
*/
|
||||||
|
|
||||||
|
function postWriteOff() {
|
||||||
|
if (!$this->RequestHandler->isPost()) {
|
||||||
|
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $this->data;
|
||||||
|
if (empty($data['Customer']['id']))
|
||||||
|
$data['Customer']['id'] = null;
|
||||||
|
if (empty($data['Lease']['id']))
|
||||||
|
$data['Lease']['id'] = null;
|
||||||
|
|
||||||
|
pr(compact('data'));
|
||||||
|
|
||||||
|
if (!$this->Transaction->addWriteOff($data,
|
||||||
|
$data['Customer']['id'],
|
||||||
|
$data['Lease']['id'])) {
|
||||||
|
$this->Session->setFlash("WRITE OFF FAILED", true);
|
||||||
|
// REVISIT <AP> 20090706:
|
||||||
|
// Until we can work out the session problems,
|
||||||
|
// just die.
|
||||||
|
die("<H1>WRITE-OFF FAILED</H1>");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return to viewing the lease/customer
|
||||||
|
if (empty($data['Lease']['id']))
|
||||||
|
$this->redirect(array('controller' => 'customers',
|
||||||
|
'action' => 'view',
|
||||||
|
$data['Customer']['id']));
|
||||||
|
else
|
||||||
|
$this->redirect(array('controller' => 'leases',
|
||||||
|
'action' => 'view',
|
||||||
|
$data['Lease']['id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: postRefund
|
||||||
|
* - handles issuing a customer refund
|
||||||
|
*/
|
||||||
|
|
||||||
|
function postRefund() {
|
||||||
|
if (!$this->RequestHandler->isPost()) {
|
||||||
|
echo('<H2>THIS IS NOT A POST FOR SOME REASON</H2>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = $this->data;
|
||||||
|
if (empty($data['Customer']['id']))
|
||||||
|
$data['Customer']['id'] = null;
|
||||||
|
if (empty($data['Lease']['id']))
|
||||||
|
$data['Lease']['id'] = null;
|
||||||
|
|
||||||
|
if (!$this->Transaction->addRefund($data,
|
||||||
|
$data['Customer']['id'],
|
||||||
|
$data['Lease']['id'])) {
|
||||||
|
$this->Session->setFlash("REFUND FAILED", true);
|
||||||
|
// REVISIT <AP> 20090706:
|
||||||
|
// Until we can work out the session problems,
|
||||||
|
// just die.
|
||||||
|
die("<H1>REFUND FAILED</H1>");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return to viewing the lease/customer
|
||||||
|
if (empty($data['Lease']['id']))
|
||||||
|
$this->redirect(array('controller' => 'customers',
|
||||||
|
'action' => 'view',
|
||||||
|
$data['Customer']['id']));
|
||||||
|
else
|
||||||
|
$this->redirect(array('controller' => 'leases',
|
||||||
|
'action' => 'view',
|
||||||
|
$data['Lease']['id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: destroy
|
||||||
|
* - Deletes a transaction and associated entries
|
||||||
|
* - !!WARNING!! This should be used with EXTREME caution, as it
|
||||||
|
* irreversibly destroys the data. It is not for normal use.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function destroy($id) {
|
||||||
|
$this->Transaction->id = $id;
|
||||||
|
$customer_id = $this->Transaction->field('customer_id');
|
||||||
|
$this->Transaction->destroy($id);
|
||||||
|
$this->redirect(array('controller' => 'customers', 'action' => 'view', $customer_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -269,35 +418,40 @@ class TransactionsController extends AppController {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function view($id = null) {
|
function view($id = null) {
|
||||||
if (!$id) {
|
|
||||||
$this->Session->setFlash(__('Invalid Item.', true));
|
|
||||||
$this->redirect(array('action'=>'index'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$transaction = $this->Transaction->find
|
$transaction = $this->Transaction->find
|
||||||
('first',
|
('first',
|
||||||
array('contain' =>
|
array('contain' =>
|
||||||
array(// Models
|
array(// Models
|
||||||
'Account' =>
|
'Account(id,name,level)',
|
||||||
array('fields' => array('Account.id',
|
'Ledger(id,sequence)',
|
||||||
'Account.name'),
|
'NsfTender(id,name)',
|
||||||
),
|
|
||||||
|
|
||||||
'Ledger' =>
|
|
||||||
array('fields' => array('Ledger.id',
|
|
||||||
'Ledger.name'),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
'conditions' => array('Transaction.id' => $id),
|
'conditions' => array(array('Transaction.id' => $id),
|
||||||
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
if ($transaction['Transaction']['type'] === 'DEPOSIT') {
|
if (empty($transaction)) {
|
||||||
$this->sidemenu_links[] =
|
$this->Session->setFlash(__('Invalid Item.', true));
|
||||||
array('name' => 'Operations', 'header' => true);
|
$this->redirect(array('action'=>'index'));
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'View Slip', 'url' => array('action' => 'deposit_slip', $id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$transaction['Account']['link'] =
|
||||||
|
$transaction['Account']['level'] >=
|
||||||
|
$this->Permission->level('controller.accounts');
|
||||||
|
|
||||||
|
if ($transaction['Transaction']['type'] === 'DEPOSIT')
|
||||||
|
$this->addSideMenuLink('View Slip',
|
||||||
|
array('action' => 'deposit_slip', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
|
||||||
|
$this->addSideMenuLink('Destroy',
|
||||||
|
array('action' => 'destroy', $id),
|
||||||
|
array('confirmMessage' =>
|
||||||
|
"This may leave the database in an unstable state." .
|
||||||
|
" Do NOT do this unless you know what you're doing." .
|
||||||
|
" Proceed anyway?"),
|
||||||
|
'ACTION', $this->admin_area);
|
||||||
|
|
||||||
// OK, prepare to render.
|
// OK, prepare to render.
|
||||||
$title = 'Transaction #' . $transaction['Transaction']['id'];
|
$title = 'Transaction #' . $transaction['Transaction']['id'];
|
||||||
$this->set(compact('transaction', 'title'));
|
$this->set(compact('transaction', 'title'));
|
||||||
@@ -313,15 +467,12 @@ class TransactionsController extends AppController {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function deposit_slip($id) {
|
function deposit_slip($id) {
|
||||||
// Build a container for the deposit slip data
|
// Find the deposit transaction
|
||||||
$deposit = array('types' => array());
|
$this->Transaction->id = $id;
|
||||||
|
$deposit = $this->Transaction->find('first', array('contain' => array('Account')));
|
||||||
$this->id = $id;
|
|
||||||
$deposit +=
|
|
||||||
$this->Transaction->find('first', array('contain' => false));
|
|
||||||
|
|
||||||
// Get a summary of all forms of tender in the deposit
|
// Get a summary of all forms of tender in the deposit
|
||||||
$result = $this->Transaction->find
|
$tenders = $this->Transaction->find
|
||||||
('all',
|
('all',
|
||||||
array('link' => array('DepositTender' =>
|
array('link' => array('DepositTender' =>
|
||||||
array('fields' => array(),
|
array('fields' => array(),
|
||||||
@@ -336,32 +487,29 @@ class TransactionsController extends AppController {
|
|||||||
'group' => 'TenderType.id',
|
'group' => 'TenderType.id',
|
||||||
));
|
));
|
||||||
|
|
||||||
if (empty($result)) {
|
// Verify the deposit exists, and that something was actually deposited
|
||||||
die();
|
if (empty($deposit) || empty($tenders)) {
|
||||||
$this->Session->setFlash(__('Invalid Deposit.', true));
|
$this->Session->setFlash(__('Invalid Deposit.', true));
|
||||||
$this->redirect(array('action'=>'deposit'));
|
$this->redirect(array('action'=>'deposit'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the summary to our deposit slip data container
|
// Add the summary to our deposit slip data container
|
||||||
foreach ($result AS $type) {
|
$deposit['types'] = array();
|
||||||
$deposit['types'][$type['TenderType']['id']] =
|
foreach ($tenders AS $tender) {
|
||||||
$type['TenderType'] + $type[0];
|
$deposit['types'][$tender['TenderType']['id']] =
|
||||||
|
$tender['TenderType'] + $tender[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// For each form of tender in the deposit, get the deposit items
|
$deposit_total = 0;
|
||||||
/* foreach ($deposit['types'] AS $type_id => &$type) { */
|
foreach ($deposit['types'] AS $type)
|
||||||
/* $type['entries'] = $this->Transaction->DepositTender->find */
|
$deposit_total += $type['total'];
|
||||||
/* ('all', */
|
|
||||||
/* array('contain' => array('Customer', 'LedgerEntry'), */
|
|
||||||
/* 'conditions' => array(array('DepositTender.deposit_transaction_id' => $id), */
|
|
||||||
/* array('DepositTender.tender_type_id' => $type_id)), */
|
|
||||||
/* )); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
$this->sidemenu_links[] =
|
if (abs($deposit['Transaction']['amount'] - $deposit_total) >= .001)
|
||||||
array('name' => 'Operations', 'header' => true);
|
$this->INTERNAL_ERROR("Deposit items ($deposit_total) do not add up to deposit slip total (".$deposit['Transaction']['amount'].")");
|
||||||
$this->sidemenu_links[] =
|
|
||||||
array('name' => 'View Transaction', 'url' => array('action' => 'view', $id));
|
$this->addSideMenuLink('View',
|
||||||
|
array('action' => 'view', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
|
||||||
$title = 'Deposit Slip';
|
$title = 'Deposit Slip';
|
||||||
$this->set(compact('title', 'deposit'));
|
$this->set(compact('title', 'deposit'));
|
||||||
|
|||||||
255
site/controllers/unit_sizes_controller.php
Normal file
255
site/controllers/unit_sizes_controller.php
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class UnitSizesController extends AppController {
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* override: addGridViewSideMenuLinks
|
||||||
|
* - Adds grid view navigation side menu links
|
||||||
|
*/
|
||||||
|
|
||||||
|
function addGridViewSideMenuLinks() {
|
||||||
|
parent::addGridViewSideMenuLinks();
|
||||||
|
|
||||||
|
$this->addSideMenuLink('1 Bedroom',
|
||||||
|
array('controller' => 'unit_sizes', 'action' => 'bd1'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('2 Bedroom',
|
||||||
|
array('controller' => 'unit_sizes', 'action' => 'bd2'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('3 Bedroom',
|
||||||
|
array('controller' => 'unit_sizes', 'action' => 'bd3'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('4+ Bedroom',
|
||||||
|
array('controller' => 'unit_sizes', 'action' => 'bd4'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('Auto',
|
||||||
|
array('controller' => 'unit_sizes', 'action' => 'auto'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('Boat',
|
||||||
|
array('controller' => 'unit_sizes', 'action' => 'boat'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('RV',
|
||||||
|
array('controller' => 'unit_sizes', 'action' => 'rv'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('All',
|
||||||
|
array('controller' => 'unit_sizes', 'action' => 'all'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: index / unavailable / vacant / occupied / all
|
||||||
|
* - Generate a listing of units
|
||||||
|
*/
|
||||||
|
|
||||||
|
function index() { $this->all(); }
|
||||||
|
function bd1() { $this->gridView('Sizes for 1 Bedroom'); }
|
||||||
|
function bd2() { $this->gridView('Sizes for 2 Bedrooms'); }
|
||||||
|
function bd3() { $this->gridView('Sizes for 3 Bedroom'); }
|
||||||
|
function bd4() { $this->gridView('Sizes for 4+ Bedroom'); }
|
||||||
|
function auto() { $this->gridView('Sizes for an Automobile'); }
|
||||||
|
function boat() { $this->gridView('Sizes for a Boat'); }
|
||||||
|
function rv() { $this->gridView('Sizes for an RV'); }
|
||||||
|
function all() { $this->gridView('All Unit Sizes', 'all'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* virtuals: gridData
|
||||||
|
* - With the application controller handling the gridData action,
|
||||||
|
* these virtual functions ensure that the correct data is passed
|
||||||
|
* to jqGrid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function gridDataCountTables(&$params, &$model) {
|
||||||
|
return array('link' => array('UnitType'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataTables(&$params, &$model) {
|
||||||
|
$tables = $this->gridDataCountTables($params, $model);
|
||||||
|
$tables['link']['Unit'] = array();
|
||||||
|
return $tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataFields(&$params, &$model) {
|
||||||
|
$fields = parent::gridDataFields($params, $model);
|
||||||
|
$fields[] = 'ROUND(UnitSize.width/12, 1) AS width';
|
||||||
|
$fields[] = 'ROUND(UnitSize.depth/12, 1) AS depth';
|
||||||
|
$fields[] = 'ROUND(UnitSize.height/12, 1) AS height';
|
||||||
|
$fields[] = 'ROUND(UnitSize.width/12 * UnitSize.depth/12, 0) AS sqft';
|
||||||
|
$fields[] = 'ROUND(UnitSize.width/12 * UnitSize.depth/12 * UnitSize.height/12, 0) AS cuft';
|
||||||
|
$fields[] = 'ROUND(UnitSize.rent / (UnitSize.width/12 * UnitSize.depth/12), 2) AS sqcost';
|
||||||
|
$fields[] = 'ROUND(UnitSize.rent / (UnitSize.width/12 * UnitSize.depth/12 * UnitSize.height/12), 2) AS cucost';
|
||||||
|
|
||||||
|
$fields[] = 'COUNT(Unit.id) AS units';
|
||||||
|
$fields[] = 'SUM(IF(' . $this->UnitSize->Unit->conditionUnavailable() . ', 1, 0)) AS unavailable';
|
||||||
|
$fields[] = 'SUM(IF(' . $this->UnitSize->Unit->conditionAvailable() . ', 1, 0)) AS available';
|
||||||
|
$fields[] = 'SUM(IF(' . $this->UnitSize->Unit->conditionOccupied() . ', 1, 0)) AS occupied';
|
||||||
|
$fields[] = 'SUM(IF(' . $this->UnitSize->Unit->conditionOccupied() . ', 0, 1)) / COUNT(Unit.id) AS vacancy';
|
||||||
|
$fields[] = 'SUM(IF(' . $this->UnitSize->Unit->conditionOccupied() . ', 1, 0)) / COUNT(Unit.id) AS occupancy';
|
||||||
|
|
||||||
|
return $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataConditions(&$params, &$model) {
|
||||||
|
$conditions = parent::gridDataConditions($params, $model);
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090825
|
||||||
|
// Sizes should come from the database.
|
||||||
|
// For now, I took an assumed average need, then bracketed
|
||||||
|
// with +/- 50 sqft. This gives a 100sqft range for each.
|
||||||
|
if ($params['action'] === 'bd1') { // 75 sqft
|
||||||
|
$conditions[] = array('UnitType.id' => array_keys($this->UnitSize->UnitType->enclosedTypes()));
|
||||||
|
$conditions[] = '(UnitSize.width/12 * UnitSize.depth/12) <= 125';
|
||||||
|
}
|
||||||
|
elseif ($params['action'] === 'bd2') { // 125 sqft
|
||||||
|
$conditions[] = array('UnitType.id' => array_keys($this->UnitSize->UnitType->enclosedTypes()));
|
||||||
|
$conditions[] = '(UnitSize.width/12 * UnitSize.depth/12) >= 75';
|
||||||
|
$conditions[] = '(UnitSize.width/12 * UnitSize.depth/12) <= 175';
|
||||||
|
}
|
||||||
|
elseif ($params['action'] === 'bd3') { // 175 sqft
|
||||||
|
$conditions[] = array('UnitType.id' => array_keys($this->UnitSize->UnitType->enclosedTypes()));
|
||||||
|
$conditions[] = '(UnitSize.width/12 * UnitSize.depth/12) >= 125';
|
||||||
|
$conditions[] = '(UnitSize.width/12 * UnitSize.depth/12) <= 225';
|
||||||
|
}
|
||||||
|
elseif ($params['action'] === 'bd4') { // 225 sqft
|
||||||
|
$conditions[] = array('UnitType.id' => array_keys($this->UnitSize->UnitType->enclosedTypes()));
|
||||||
|
$conditions[] = '(UnitSize.width/12 * UnitSize.depth/12) >= 175';
|
||||||
|
}
|
||||||
|
elseif (in_array($params['action'], array('auto', 'boat', 'rv'))) {
|
||||||
|
$conditions[] = array('UnitType.id' =>
|
||||||
|
array_merge(array_keys($this->UnitSize->UnitType->enclosedTypes()),
|
||||||
|
array_keys($this->UnitSize->UnitType->outdoorTypes())));
|
||||||
|
list($width, $depth, $height) = array(8, 15, null);
|
||||||
|
if ($params['action'] === 'auto')
|
||||||
|
$depth = 15;
|
||||||
|
elseif ($params['action'] === 'boat')
|
||||||
|
$depth = 15;
|
||||||
|
elseif ($params['action'] === 'rv')
|
||||||
|
list($width, $depth, $height) = array(10, 25, 12);
|
||||||
|
|
||||||
|
$conditions[] = "(UnitSize.width/12) >= $width";
|
||||||
|
$conditions[] = "(UnitSize.depth/12) >= $depth";
|
||||||
|
if (isset($height))
|
||||||
|
$conditions[] = array('OR' =>
|
||||||
|
array("(UnitSize.height/12) >= $height",
|
||||||
|
//"UnitSize.height IS NULL",
|
||||||
|
array('UnitType.id' =>
|
||||||
|
array_keys($this->UnitSize->UnitType->outdoorTypes())),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataOrder(&$params, &$model, $index, $direction) {
|
||||||
|
if ($index == 'UnitType.name')
|
||||||
|
$index = 'UnitType.code';
|
||||||
|
|
||||||
|
$order = parent::gridDataOrder($params, $model, $index, $direction);
|
||||||
|
|
||||||
|
// After sorting by whatever the user wants, add these
|
||||||
|
// defaults into the sort mechanism. If we're already
|
||||||
|
// sorting by one of them, it will only be redundant,
|
||||||
|
// and should cause no harm (possible a longer query?)
|
||||||
|
$order[] = 'UnitType.code ' . $direction;
|
||||||
|
$order[] = 'sqft ' . $direction;
|
||||||
|
$order[] = 'UnitSize.rent ' . $direction;
|
||||||
|
|
||||||
|
return $order;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gridDataPostProcessLinks(&$params, &$model, &$records, $links) {
|
||||||
|
$links['UnitSize'] = array('name');
|
||||||
|
return parent::gridDataPostProcessLinks($params, $model, $records, $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 UnitSize and related fields
|
||||||
|
$this->UnitSize->id = $id;
|
||||||
|
$size = $this->UnitSize->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array('UnitType'),
|
||||||
|
'fields' => array('UnitSize.*', 'UnitType.*',
|
||||||
|
'ROUND(UnitSize.width/12, 1) AS width',
|
||||||
|
'ROUND(UnitSize.depth/12, 1) AS depth',
|
||||||
|
'ROUND(UnitSize.height/12, 1) AS height',
|
||||||
|
'ROUND(UnitSize.width/12 * UnitSize.depth/12, 0) AS sqft',
|
||||||
|
'ROUND(UnitSize.width/12 * UnitSize.depth/12 * UnitSize.height/12, 0) AS cuft'),
|
||||||
|
));
|
||||||
|
$size['UnitSize'] = $size[0] + $size['UnitSize'];
|
||||||
|
unset($size[0]);
|
||||||
|
|
||||||
|
$this->set(compact('size'));
|
||||||
|
$this->set('stats', $this->UnitSize->stats($id));
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = "Unit Size : {$size['UnitSize']['name']}";
|
||||||
|
$this->set(compact('title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: edit
|
||||||
|
* - Edit unit_size information
|
||||||
|
*/
|
||||||
|
|
||||||
|
function edit($id = null) {
|
||||||
|
$this->INTERNAL_ERROR('NOT READY');
|
||||||
|
if (isset($this->data)) {
|
||||||
|
// Check to see if the operation was cancelled.
|
||||||
|
if (isset($this->params['form']['cancel'])) {
|
||||||
|
if (empty($this->data['UnitSize']['id']))
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
|
||||||
|
$this->redirect(array('action'=>'view', $this->data['UnitSize']['id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we have unit_size data
|
||||||
|
if (empty($this->data['UnitSize']) || empty($this->data['UnitSize']['id']))
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
|
||||||
|
// Save the unit_size and all associated data
|
||||||
|
$this->UnitSize->create();
|
||||||
|
$this->UnitSize->id = $this->data['UnitSize']['id'];
|
||||||
|
if (!$this->UnitSize->save($this->data, false)) {
|
||||||
|
$this->Session->setFlash("UNIT_SIZE SAVE FAILED", true);
|
||||||
|
pr("UNIT_SIZE SAVE FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->redirect(array('action'=>'view', $this->UnitSize->id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($id) {
|
||||||
|
$this->data = $this->UnitSize->findById($id);
|
||||||
|
} else {
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$title = ('UnitSize ' . $this->data['UnitSize']['name'] .
|
||||||
|
" : Edit");
|
||||||
|
$this->set(compact('title'));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,26 +2,38 @@
|
|||||||
|
|
||||||
class UnitsController extends AppController {
|
class UnitsController extends AppController {
|
||||||
|
|
||||||
var $sidemenu_links =
|
|
||||||
array(array('name' => 'Units', 'header' => true),
|
|
||||||
array('name' => 'Occupied', 'url' => array('controller' => 'units', 'action' => 'occupied')),
|
|
||||||
array('name' => 'Vacant', 'url' => array('controller' => 'units', 'action' => 'vacant')),
|
|
||||||
array('name' => 'Unavailable', 'url' => array('controller' => 'units', 'action' => 'unavailable')),
|
|
||||||
array('name' => 'All', 'url' => array('controller' => 'units', 'action' => 'all')),
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* override: sideMenuLinks
|
* override: addGridViewSideMenuLinks
|
||||||
* - Generates controller specific links for the side menu
|
* - Adds grid view navigation side menu links
|
||||||
*/
|
*/
|
||||||
function sideMenuLinks() {
|
|
||||||
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
|
function addGridViewSideMenuLinks() {
|
||||||
|
parent::addGridViewSideMenuLinks();
|
||||||
|
|
||||||
|
$this->addSideMenuLink('Unavailable',
|
||||||
|
array('controller' => 'units', 'action' => 'unavailable'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('Vacant',
|
||||||
|
array('controller' => 'units', 'action' => 'vacant'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('Occupied',
|
||||||
|
array('controller' => 'units', 'action' => 'occupied'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('Overlocked',
|
||||||
|
array('controller' => 'units', 'action' => 'locked'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('Liened',
|
||||||
|
array('controller' => 'units', 'action' => 'liened'), null,
|
||||||
|
'CONTROLLER');
|
||||||
|
$this->addSideMenuLink('All',
|
||||||
|
array('controller' => 'units', 'action' => 'all'), null,
|
||||||
|
'CONTROLLER');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -33,6 +45,8 @@ class UnitsController extends AppController {
|
|||||||
function unavailable() { $this->gridView('Unavailable Units'); }
|
function unavailable() { $this->gridView('Unavailable Units'); }
|
||||||
function vacant() { $this->gridView('Vacant Units'); }
|
function vacant() { $this->gridView('Vacant Units'); }
|
||||||
function occupied() { $this->gridView('Occupied Units'); }
|
function occupied() { $this->gridView('Occupied Units'); }
|
||||||
|
function locked() { $this->gridView('Overlocked Units'); }
|
||||||
|
function liened() { $this->gridView('Liened Units'); }
|
||||||
function all() { $this->gridView('All Units', 'all'); }
|
function all() { $this->gridView('All Units', 'all'); }
|
||||||
|
|
||||||
|
|
||||||
@@ -69,6 +83,7 @@ class UnitsController extends AppController {
|
|||||||
function gridDataTables(&$params, &$model) {
|
function gridDataTables(&$params, &$model) {
|
||||||
$link = $this->gridDataCountTables($params, $model);
|
$link = $this->gridDataCountTables($params, $model);
|
||||||
$link['link']['CurrentLease']['StatementEntry'] = array('fields' => array());
|
$link['link']['CurrentLease']['StatementEntry'] = array('fields' => array());
|
||||||
|
$link['link']['Lock'];
|
||||||
return $link;
|
return $link;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,8 +96,9 @@ class UnitsController extends AppController {
|
|||||||
function gridDataFields(&$params, &$model) {
|
function gridDataFields(&$params, &$model) {
|
||||||
$fields = parent::gridDataFields($params, $model);
|
$fields = parent::gridDataFields($params, $model);
|
||||||
|
|
||||||
|
$fields[] = 'ROUND(UnitSize.width/12 * UnitSize.depth/12, 0) AS sqft';
|
||||||
return array_merge($fields,
|
return array_merge($fields,
|
||||||
$this->Unit->Lease->StatementEntry->chargePaymentFields(true));
|
$this->Unit->Lease->StatementEntry->chargeDisbursementFields(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
function gridDataConditions(&$params, &$model) {
|
function gridDataConditions(&$params, &$model) {
|
||||||
@@ -100,6 +116,12 @@ class UnitsController extends AppController {
|
|||||||
elseif ($params['action'] === 'unoccupied') {
|
elseif ($params['action'] === 'unoccupied') {
|
||||||
$conditions[] = array('NOT' => array($this->Unit->conditionOccupied()));
|
$conditions[] = array('NOT' => array($this->Unit->conditionOccupied()));
|
||||||
}
|
}
|
||||||
|
elseif ($params['action'] === 'locked') {
|
||||||
|
$conditions[] = $this->Unit->conditionLocked();
|
||||||
|
}
|
||||||
|
elseif ($params['action'] === 'liened') {
|
||||||
|
$conditions[] = $this->Unit->conditionLiened();
|
||||||
|
}
|
||||||
|
|
||||||
return $conditions;
|
return $conditions;
|
||||||
}
|
}
|
||||||
@@ -139,7 +161,7 @@ class UnitsController extends AppController {
|
|||||||
$customer = array();
|
$customer = array();
|
||||||
$unit = array();
|
$unit = array();
|
||||||
|
|
||||||
if (isset($id)) {
|
if (!empty($id)) {
|
||||||
$this->Unit->recursive = -1;
|
$this->Unit->recursive = -1;
|
||||||
$unit = current($this->Unit->read(null, $id));
|
$unit = current($this->Unit->read(null, $id));
|
||||||
}
|
}
|
||||||
@@ -189,6 +211,149 @@ class UnitsController extends AppController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: lock/unlock/lien
|
||||||
|
* - Transitions the unit into / out of the LOCKED state
|
||||||
|
*/
|
||||||
|
|
||||||
|
function status($id, $status) {
|
||||||
|
$this->Unit->updateStatus($id, $status, true);
|
||||||
|
$this->redirect(array('action' => 'view', $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
function lock($id) {
|
||||||
|
if (isset($this->data)) {
|
||||||
|
$id = $this->id = $this->data['Unit']['id'];
|
||||||
|
|
||||||
|
// Check to see if the operation was cancelled.
|
||||||
|
if (isset($this->params['form']['cancel'])) {
|
||||||
|
if (isset($id))
|
||||||
|
$this->redirect(array('action'=>'view', $id));
|
||||||
|
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Figure out which locks the user put on
|
||||||
|
$locks = array();
|
||||||
|
if (isset($this->data['Lock']) && is_array($this->data['Lock'])) {
|
||||||
|
foreach ($this->data['Lock'] AS $lock) {
|
||||||
|
$locks[] = $lock['id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the lock and all associated data
|
||||||
|
if (!$this->Unit->lockUnit($id, $locks)) {
|
||||||
|
$this->Session->setFlash("UNIT LOCK FAILED", true);
|
||||||
|
pr("UNIT LOCK FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it's no longer locked, change status to OCCUPIED
|
||||||
|
// Could still be liened... but that would be odd.
|
||||||
|
if (count($locks) == 0)
|
||||||
|
$this->status($id, 'OCCUPIED');
|
||||||
|
|
||||||
|
// If we're not liened, we must now just be locked
|
||||||
|
if (!$this->Unit->liened(intval($id)))
|
||||||
|
$this->status($id, 'LOCKED');
|
||||||
|
|
||||||
|
// Otherwise, don't change anything.
|
||||||
|
$this->redirect(array('action' => 'view', $id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$id)
|
||||||
|
$this->INTERNAL_ERROR("$id cannot be NULL");
|
||||||
|
|
||||||
|
// Get all locks on this unit
|
||||||
|
$this->data = $this->Unit->find
|
||||||
|
('first',
|
||||||
|
array('contain' => array('Lock' => array('id')),
|
||||||
|
'fields' => array('id', 'name'),
|
||||||
|
'conditions' => array('Unit.id' => $id)
|
||||||
|
));
|
||||||
|
|
||||||
|
$locks = $this->Unit->Lock->lockList();
|
||||||
|
/* $locksold = $locks; */
|
||||||
|
/* foreach ($locksold AS $name) { */
|
||||||
|
/* $locks[$name] = $name; */
|
||||||
|
/* } */
|
||||||
|
$this->set(compact('locks'));
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
//pr($this->data);
|
||||||
|
$this->set(compact('title'));
|
||||||
|
// $this->render('lock');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function unlock($id) { $this->lock($id); }
|
||||||
|
function lien($id) { $this->status($id, 'LIENED'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: overview
|
||||||
|
* - Displays overview information for all units
|
||||||
|
*/
|
||||||
|
function overview() {
|
||||||
|
$result = $this->Unit->find
|
||||||
|
('all',
|
||||||
|
array('link' => array('UnitSize' => array('fields' => array(), 'UnitType' => array('fields' => array('name')))),
|
||||||
|
'fields' => array('status', 'COUNT(Unit.id) AS cnt', 'SUM(Unit.rent) AS rents'),
|
||||||
|
//'conditions' => array('
|
||||||
|
'group' => array('UnitType.id', 'Unit.status'),
|
||||||
|
'order' => array('UnitType.name', 'Unit.status')
|
||||||
|
));
|
||||||
|
|
||||||
|
$overview = array('types' => array(), 'count' => 0, 'rents' => 0);
|
||||||
|
foreach ($result AS $row) {
|
||||||
|
$utname = $row['UnitType']['name'];
|
||||||
|
if (empty($overview['types'][$utname]))
|
||||||
|
$overview['types'][$utname] = array('name' => $utname,
|
||||||
|
'subs' => array(),
|
||||||
|
'count' => 0,
|
||||||
|
'rents' => 0,
|
||||||
|
'phys_pct' => 0,
|
||||||
|
'econ_pct' => 0);
|
||||||
|
$type = &$overview['types'][$utname];
|
||||||
|
$type['subs'][] = array('name' => $row['Unit']['status'],
|
||||||
|
'count' => $row[0]['cnt'],
|
||||||
|
'rents' => $row[0]['rents'],
|
||||||
|
'phys_subpct' => 0,
|
||||||
|
'phys_totpct' => 0,
|
||||||
|
'econ_subpct' => 0,
|
||||||
|
'econ_totpct' => 0);
|
||||||
|
|
||||||
|
|
||||||
|
$type['count'] += $row[0]['cnt'];
|
||||||
|
$type['rents'] += $row[0]['rents'];
|
||||||
|
|
||||||
|
$overview['count'] += $row[0]['cnt'];
|
||||||
|
$overview['rents'] += $row[0]['rents'];
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($overview['types'] AS &$type) {
|
||||||
|
foreach ($type['subs'] AS &$sub) {
|
||||||
|
$sub['phys_subpct'] = $sub['count'] / $type['count'];
|
||||||
|
$sub['econ_subpct'] = $sub['rents'] / $type['rents'];
|
||||||
|
$sub['phys_totpct'] = $sub['count'] / $overview['count'];
|
||||||
|
$sub['econ_totpct'] = $sub['rents'] / $overview['rents'];
|
||||||
|
}
|
||||||
|
$type['phys_pct'] = $type['count'] / $overview['count'];
|
||||||
|
$type['econ_pct'] = $type['rents'] / $overview['rents'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable the Reports menu section
|
||||||
|
$this->sideMenuAreaActivate('REPORT');
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$this->set('title', 'Unit Overview');
|
||||||
|
$this->set(compact('overview'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -207,6 +372,7 @@ class UnitsController extends AppController {
|
|||||||
array('contain' =>
|
array('contain' =>
|
||||||
array(// Models
|
array(// Models
|
||||||
'UnitSize',
|
'UnitSize',
|
||||||
|
'Lock',
|
||||||
'Lease' => array('Customer'),
|
'Lease' => array('Customer'),
|
||||||
'CurrentLease' => array('Customer')
|
'CurrentLease' => array('Customer')
|
||||||
),
|
),
|
||||||
@@ -232,33 +398,124 @@ class UnitsController extends AppController {
|
|||||||
$outstanding_deposit = $this->Unit->Lease->securityDepositBalance($unit['CurrentLease']['id']);
|
$outstanding_deposit = $this->Unit->Lease->securityDepositBalance($unit['CurrentLease']['id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up dynamic menu items
|
// Add a mechanism to lock ANY unit, regardless of status
|
||||||
$this->sidemenu_links[] =
|
$this->addSideMenuLink($this->Unit->lockCount($id) == 0 ? 'Lock' : 'Relock/Unlock',
|
||||||
array('name' => 'Operations', 'header' => true);
|
array('action' => 'lock', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
|
||||||
if (isset($unit['CurrentLease']['id']) &&
|
// If the unit is locked, but not liened, give option to lien.
|
||||||
!isset($unit['CurrentLease']['moveout_date'])) {
|
if ($this->Unit->locked($unit['Unit']['status']) &&
|
||||||
$this->sidemenu_links[] =
|
!$this->Unit->liened($unit['Unit']['status']))
|
||||||
array('name' => 'Move-Out', 'url' => array('action' => 'move_out',
|
$this->addSideMenuLink('Lien',
|
||||||
$id));
|
array('action' => 'lien', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
|
||||||
|
// If there is a current lease on this unit, then provide
|
||||||
|
// a link to move the tenant out. Current lease for a unit
|
||||||
|
// has a bit different definition than a current lease for
|
||||||
|
// a customer, since a lease stays with a customer until it
|
||||||
|
// is finally closed. A lease, however, only stays with a
|
||||||
|
// unit while occupied (since a unit is not responsible for
|
||||||
|
// any lingering financial obligations, like a customer is).
|
||||||
|
// Of course, if there is no current lease, provide a link
|
||||||
|
// to move a new tenant in (if the unit is available).
|
||||||
|
if (isset($unit['CurrentLease']['id'])) {
|
||||||
|
$this->addSideMenuLink('Move-Out',
|
||||||
|
array('action' => 'move_out', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
} elseif ($this->Unit->available($unit['Unit']['status'])) {
|
||||||
|
$this->addSideMenuLink('Move-In',
|
||||||
|
array('action' => 'move_in', $id), null,
|
||||||
|
'ACTION');
|
||||||
} else {
|
} else {
|
||||||
$this->sidemenu_links[] =
|
// Unit is unavailable (dirty, damaged, reserved, business-use, etc)
|
||||||
array('name' => 'Move-In', 'url' => array('action' => 'move_in',
|
|
||||||
$id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($unit['CurrentLease']['id']) &&
|
// If there is a current lease, allow new charges to
|
||||||
!isset($unit['CurrentLease']['close_date'])) {
|
// be added, and payments to be made.
|
||||||
$this->sidemenu_links[] =
|
if (isset($unit['CurrentLease']['id'])) {
|
||||||
array('name' => 'Payment', 'url' => array('controller' => 'customers',
|
$this->addSideMenuLink('New Invoice',
|
||||||
'action' => 'receipt',
|
array('controller' => 'leases',
|
||||||
$unit['CurrentLease']['customer_id']));
|
'action' => 'invoice',
|
||||||
|
$unit['CurrentLease']['id']), null,
|
||||||
|
'ACTION');
|
||||||
|
$this->addSideMenuLink('New Receipt',
|
||||||
|
array('controller' => 'customers',
|
||||||
|
'action' => 'receipt',
|
||||||
|
$unit['CurrentLease']['customer_id']), null,
|
||||||
|
'ACTION');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always allow the unit to be edited.
|
||||||
|
$this->addSideMenuLink('Edit',
|
||||||
|
array('action' => 'edit', $id), null,
|
||||||
|
'ACTION');
|
||||||
|
|
||||||
// Prepare to render.
|
// Prepare to render.
|
||||||
$title = 'Unit ' . $unit['Unit']['name'];
|
$title = 'Unit ' . $unit['Unit']['name'];
|
||||||
$this->set(compact('unit', 'title',
|
$this->set(compact('unit', 'title',
|
||||||
'outstanding_balance',
|
'outstanding_balance',
|
||||||
'outstanding_deposit'));
|
'outstanding_deposit'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* action: edit
|
||||||
|
* - Edit unit information
|
||||||
|
*/
|
||||||
|
|
||||||
|
function edit($id = null) {
|
||||||
|
if (isset($this->data)) {
|
||||||
|
// Check to see if the operation was cancelled.
|
||||||
|
if (isset($this->params['form']['cancel'])) {
|
||||||
|
if (empty($this->data['Unit']['id']))
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
|
||||||
|
$this->redirect(array('action'=>'view', $this->data['Unit']['id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we have unit data
|
||||||
|
if (empty($this->data['Unit']))
|
||||||
|
$this->redirect(array('action'=>'index'));
|
||||||
|
|
||||||
|
// Make sure we have a rental rate
|
||||||
|
if (empty($this->data['Unit']['rent']))
|
||||||
|
$this->redirect(array('action'=>'view', $this->data['Unit']['id']));
|
||||||
|
|
||||||
|
// Save the unit and all associated data
|
||||||
|
$this->Unit->create();
|
||||||
|
$this->Unit->id = $this->data['Unit']['id'];
|
||||||
|
if (!$this->Unit->save($this->data, false)) {
|
||||||
|
$this->Session->setFlash("UNIT SAVE FAILED", true);
|
||||||
|
pr("UNIT SAVE FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->redirect(array('action'=>'view', $this->Unit->id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($id) {
|
||||||
|
$this->data = $this->Unit->findById($id);
|
||||||
|
$title = 'Unit ' . $this->data['Unit']['name'] . " : Edit";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$title = "Enter New Unit";
|
||||||
|
$this->data = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$statusEnums = $this->Unit->allowedStatusSet($id);
|
||||||
|
$statusEnums = array_combine(array_keys($statusEnums),
|
||||||
|
array_keys($statusEnums));
|
||||||
|
$this->set(compact('statusEnums'));
|
||||||
|
|
||||||
|
$unit_sizes = $this->Unit->UnitSize->find
|
||||||
|
('list', array('order' => array('unit_type_id', 'width', 'depth', 'id')));
|
||||||
|
$this->set(compact('unit_sizes'));
|
||||||
|
|
||||||
|
// Prepare to render.
|
||||||
|
$this->set(compact('title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
50
site/controllers/util_controller.php
Normal file
50
site/controllers/util_controller.php
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class UtilController extends AppController {
|
||||||
|
|
||||||
|
var $uses = array();
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: rebuild_box
|
||||||
|
*/
|
||||||
|
|
||||||
|
function rebuild_box($type) {
|
||||||
|
$this->layout = null;
|
||||||
|
$this->autoLayout = false;
|
||||||
|
$this->autoRender = false;
|
||||||
|
Configure::write('debug', '0');
|
||||||
|
|
||||||
|
$usrpass = '--user=perki2_pmgruser --password=pmgrauth';
|
||||||
|
$boxdb = 'perki2_pmgr_' . $type;
|
||||||
|
|
||||||
|
$handle = popen("mysqldump $usrpass --opt perki2_pmgr" .
|
||||||
|
" | mysql $usrpass --database=$boxdb", 'r');
|
||||||
|
while (($read = fread($handle, 2096))) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
pclose($handle);
|
||||||
|
|
||||||
|
$url = $_SERVER['HTTP_REFERER'];
|
||||||
|
if (empty($url) || $url == 'undefined')
|
||||||
|
$url = "/$type";
|
||||||
|
|
||||||
|
$this->redirect($url);
|
||||||
|
}
|
||||||
|
|
||||||
|
function rebuild_sandbox() { $this->rebuild_box('sand'); }
|
||||||
|
function rebuild_devbox() { $this->rebuild_box('dev'); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: logmsg
|
||||||
|
* - action to allow posting log message data
|
||||||
|
*/
|
||||||
|
|
||||||
|
function logmsg() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -121,22 +121,42 @@ class Account extends AppModel {
|
|||||||
* - Returns the ID of the desired account
|
* - Returns the ID of the desired account
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function securityDepositAccountID() { return $this->nameToID('Security Deposit'); }
|
function lookup($name, $check = true) {
|
||||||
function rentAccountID() { return $this->nameToID('Rent'); }
|
$id = $this->nameToID($name);
|
||||||
function lateChargeAccountID() { return $this->nameToID('Late Charge'); }
|
if (empty($id) && $check)
|
||||||
function nsfAccountID() { return $this->nameToID('NSF'); }
|
$this->INTERNAL_ERROR("Missing Account '$name'");
|
||||||
function nsfChargeAccountID() { return $this->nameToID('NSF Charge'); }
|
return $id;
|
||||||
function taxAccountID() { return $this->nameToID('Tax'); }
|
}
|
||||||
function accountReceivableAccountID() { return $this->nameToID('A/R'); }
|
|
||||||
function cashAccountID() { return $this->nameToID('Cash'); }
|
|
||||||
function checkAccountID() { return $this->nameToID('Check'); }
|
|
||||||
function moneyOrderAccountID() { return $this->nameToID('Money Order'); }
|
|
||||||
function concessionAccountID() { return $this->nameToID('Concession'); }
|
|
||||||
function pettyCashAccountID() { return $this->nameToID('Petty Cash'); }
|
|
||||||
function invoiceAccountID() { return $this->nameToID('Invoice'); }
|
|
||||||
function receiptAccountID() { return $this->nameToID('Receipt'); }
|
|
||||||
function badDebtAccountID() { return $this->nameToID('Bad Debt'); }
|
|
||||||
|
|
||||||
|
function securityDepositAccountID() { return $this->lookup('Security Deposit'); }
|
||||||
|
function rentAccountID() { return $this->lookup('Rent'); }
|
||||||
|
function lateChargeAccountID() { return $this->lookup('Late Charge'); }
|
||||||
|
function nsfAccountID() { return $this->lookup('NSF'); }
|
||||||
|
function nsfChargeAccountID() { return $this->lookup('NSF Charge'); }
|
||||||
|
function taxAccountID() { return $this->lookup('Tax'); }
|
||||||
|
function accountReceivableAccountID() { return $this->lookup('A/R'); }
|
||||||
|
function accountPayableAccountID() { return $this->lookup('A/P'); }
|
||||||
|
function cashAccountID() { return $this->lookup('Cash'); }
|
||||||
|
function checkAccountID() { return $this->lookup('Check'); }
|
||||||
|
function moneyOrderAccountID() { return $this->lookup('Money Order'); }
|
||||||
|
function achAccountID() { return $this->lookup('ACH'); }
|
||||||
|
function concessionAccountID() { return $this->lookup('Concession'); }
|
||||||
|
function waiverAccountID() { return $this->lookup('Waiver'); }
|
||||||
|
function pettyCashAccountID() { return $this->lookup('Petty Cash'); }
|
||||||
|
function invoiceAccountID() { return $this->lookup('Invoice'); }
|
||||||
|
function receiptAccountID() { return $this->lookup('Receipt'); }
|
||||||
|
function badDebtAccountID() { return $this->lookup('Bad Debt'); }
|
||||||
|
function customerCreditAccountID() { return $this->lookup(
|
||||||
|
// REVISIT <AP>: 20090816
|
||||||
|
// Use of A/R works, and saves an excess of accounts.
|
||||||
|
// However, a dedicated account is nice, since it can
|
||||||
|
// quickly be spotted how much is _really_ due, vs
|
||||||
|
// how much has been pre-paid. Customer credits in
|
||||||
|
// A/R is not as clear, although a report is an
|
||||||
|
// obvious solution.
|
||||||
|
//'A/R'
|
||||||
|
'Credit'
|
||||||
|
); }
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -168,8 +188,7 @@ class Account extends AppModel {
|
|||||||
function relatedAccounts($attribute, $extra = null) {
|
function relatedAccounts($attribute, $extra = null) {
|
||||||
$this->cacheQueries = true;
|
$this->cacheQueries = true;
|
||||||
$accounts = $this->find('all', array
|
$accounts = $this->find('all', array
|
||||||
('contain' => array('CurrentLedger'),
|
('fields' => array('Account.id', 'Account.name'),
|
||||||
'fields' => array('Account.id', 'Account.type', 'Account.name', 'CurrentLedger.id'),
|
|
||||||
'conditions' => array('Account.'.$attribute => true),
|
'conditions' => array('Account.'.$attribute => true),
|
||||||
'order' => array('Account.name'),
|
'order' => array('Account.name'),
|
||||||
) + (isset($extra) ? $extra : array())
|
) + (isset($extra) ? $extra : array())
|
||||||
@@ -193,17 +212,10 @@ class Account extends AppModel {
|
|||||||
* - Returns an array of accounts suitable for activity xxx
|
* - Returns an array of accounts suitable for activity xxx
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function chargeAccounts() {
|
function invoiceAccounts() { return $this->relatedAccounts('invoices'); }
|
||||||
return $this->relatedAccounts('charges', array('order' => 'name'));
|
function receiptAccounts() { return $this->relatedAccounts('receipts'); }
|
||||||
}
|
function depositAccounts() { return $this->relatedAccounts('deposits'); }
|
||||||
|
function refundAccounts() { return $this->relatedAccounts('refunds'); }
|
||||||
function paymentAccounts() {
|
|
||||||
return $this->relatedAccounts('payments', array('order' => 'name'));
|
|
||||||
}
|
|
||||||
|
|
||||||
function depositAccounts() {
|
|
||||||
return $this->relatedAccounts('deposits', array('order' => 'name'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
@@ -214,14 +226,30 @@ class Account extends AppModel {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function collectableAccounts() {
|
function collectableAccounts() {
|
||||||
$accounts = $this->paymentAccounts();
|
$accounts = $this->receiptAccounts();
|
||||||
|
|
||||||
foreach(array($this->nsfAccountID(),
|
foreach(array($this->customerCreditAccountID(),
|
||||||
$this->securityDepositAccountID())
|
$this->securityDepositAccountID(),
|
||||||
|
$this->nsfAccountID(),
|
||||||
|
$this->waiverAccountID(),
|
||||||
|
$this->badDebtAccountID(),
|
||||||
|
//$this->lookup('Closing'),
|
||||||
|
//$this->lookup('Equity'),
|
||||||
|
)
|
||||||
AS $account_id) {
|
AS $account_id) {
|
||||||
$accounts[$account_id] = $this->name($account_id);
|
$accounts[$account_id] = $this->name($account_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$accounts['all'] = $accounts['default'] = $accounts;
|
||||||
|
|
||||||
|
foreach(array($this->concessionAccountID(),
|
||||||
|
$this->waiverAccountID(),
|
||||||
|
$this->badDebtAccountID(),
|
||||||
|
)
|
||||||
|
AS $account_id) {
|
||||||
|
unset($accounts['default'][$account_id]);
|
||||||
|
}
|
||||||
|
|
||||||
return $accounts;
|
return $accounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,6 +365,7 @@ class Account extends AppModel {
|
|||||||
$this->queryInit($query);
|
$this->queryInit($query);
|
||||||
$query['link'] = array('Account' => $query['link']);
|
$query['link'] = array('Account' => $query['link']);
|
||||||
|
|
||||||
|
$stats = array();
|
||||||
foreach ($this->ledgers($id, $all) AS $ledger)
|
foreach ($this->ledgers($id, $all) AS $ledger)
|
||||||
$this->statsMerge($stats['Ledger'],
|
$this->statsMerge($stats['Ledger'],
|
||||||
$this->Ledger->stats($ledger, $query));
|
$this->Ledger->stats($ledger, $query));
|
||||||
|
|||||||
@@ -41,14 +41,15 @@ class Contact extends AppModel {
|
|||||||
function saveContact($id, $data) {
|
function saveContact($id, $data) {
|
||||||
|
|
||||||
// Establish a display name if not already given
|
// Establish a display name if not already given
|
||||||
if (!$data['Contact']['display_name'])
|
if (!$data['Contact']['display_name'] &&
|
||||||
|
$data['Contact']['first_name'] && $data['Contact']['last_name'])
|
||||||
$data['Contact']['display_name'] =
|
$data['Contact']['display_name'] =
|
||||||
(($data['Contact']['first_name'] &&
|
$data['Contact']['last_name'] . ', ' . $data['Contact']['first_name'];
|
||||||
$data['Contact']['last_name'])
|
|
||||||
? $data['Contact']['last_name'] . ', ' . $data['Contact']['first_name']
|
foreach (array('last_name', 'first_name', 'company_name') AS $fld) {
|
||||||
: ($data['Contact']['first_name']
|
if (!$data['Contact']['display_name'] && $data['Contact'][$fld])
|
||||||
? $data['Contact']['first_name']
|
$data['Contact']['display_name'] = $data['Contact'][$fld];
|
||||||
: $data['Contact']['last_name']));
|
}
|
||||||
|
|
||||||
// Save the contact data
|
// Save the contact data
|
||||||
$this->create();
|
$this->create();
|
||||||
@@ -90,7 +91,7 @@ class Contact extends AppModel {
|
|||||||
|
|
||||||
// If the user has entered all new data, we need to
|
// If the user has entered all new data, we need to
|
||||||
// save that as a brand new entry.
|
// save that as a brand new entry.
|
||||||
if (!isset($item['id'])) {
|
if (!isset($item['id']) || $item['source'] == 'new') {
|
||||||
$I = new $class();
|
$I = new $class();
|
||||||
$I->create();
|
$I->create();
|
||||||
if (!$I->save($item, false)) {
|
if (!$I->save($item, false)) {
|
||||||
|
|||||||
@@ -20,15 +20,25 @@ class Customer extends AppModel {
|
|||||||
),
|
),
|
||||||
'Lease',
|
'Lease',
|
||||||
'StatementEntry',
|
'StatementEntry',
|
||||||
'ContactsCustomer',
|
'ContactsCustomer' => array(
|
||||||
|
// It would be nice to claim a dependency here, which would
|
||||||
|
// simplify deletion of a customer. However, for this to work
|
||||||
|
// Cake must have a primaryKey as a single field. This table
|
||||||
|
// makes use of a complex key, so we're out of luck.
|
||||||
|
/* 'dependent' => true, */
|
||||||
|
),
|
||||||
|
|
||||||
'Transaction',
|
'Transaction',
|
||||||
|
'Tender',
|
||||||
);
|
);
|
||||||
|
|
||||||
var $hasAndBelongsToMany = array(
|
var $hasAndBelongsToMany = array(
|
||||||
'Contact',
|
'Contact' => array(
|
||||||
|
'unique' => true,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//var $default_log_level = 20;
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -54,17 +64,19 @@ class Customer extends AppModel {
|
|||||||
* function: leaseIds
|
* function: leaseIds
|
||||||
* - Returns the lease IDs for the given customer
|
* - Returns the lease IDs for the given customer
|
||||||
*/
|
*/
|
||||||
function leaseIds($id) {
|
function leaseIds($id, $current = false) {
|
||||||
|
$Lease = $current ? 'CurrentLease' : 'Lease';
|
||||||
|
|
||||||
$this->cacheQueries = true;
|
$this->cacheQueries = true;
|
||||||
$customer = $this->find('first',
|
$customer = $this->find('first',
|
||||||
array('contain' =>
|
array('contain' =>
|
||||||
array('Lease' => array('fields' => array('id'))),
|
array($Lease => array('fields' => array('id'))),
|
||||||
'fields' => array(),
|
'fields' => array(),
|
||||||
'conditions' => array(array('Customer.id' => $id))));
|
'conditions' => array(array('Customer.id' => $id))));
|
||||||
$this->cacheQueries = false;
|
$this->cacheQueries = false;
|
||||||
|
|
||||||
$ids = array();
|
$ids = array();
|
||||||
foreach ($customer['Lease'] AS $lease)
|
foreach ($customer[$Lease] AS $lease)
|
||||||
$ids[] = $lease['id'];
|
$ids[] = $lease['id'];
|
||||||
|
|
||||||
return $ids;
|
return $ids;
|
||||||
@@ -81,12 +93,7 @@ class Customer extends AppModel {
|
|||||||
$this->prEnter(compact('id', 'query'));
|
$this->prEnter(compact('id', 'query'));
|
||||||
$this->queryInit($query);
|
$this->queryInit($query);
|
||||||
|
|
||||||
if (!isset($query['link']['Customer']))
|
$query['conditions'][] = array('StatementEntry.customer_id' => $id);
|
||||||
$query['link']['Customer'] = array();
|
|
||||||
if (!isset($query['link']['Customer']['fields']))
|
|
||||||
$query['link']['Customer']['fields'] = array();
|
|
||||||
|
|
||||||
$query['conditions'][] = array('Customer.id' => $id);
|
|
||||||
$query['conditions'][] = array('StatementEntry.account_id' =>
|
$query['conditions'][] = array('StatementEntry.account_id' =>
|
||||||
$this->StatementEntry->Account->securityDepositAccountID());
|
$this->StatementEntry->Account->securityDepositAccountID());
|
||||||
|
|
||||||
@@ -106,18 +113,35 @@ class Customer extends AppModel {
|
|||||||
$this->prEnter(compact('id', 'query'));
|
$this->prEnter(compact('id', 'query'));
|
||||||
$this->queryInit($query);
|
$this->queryInit($query);
|
||||||
|
|
||||||
if (!isset($query['link']['Lease']))
|
$sd_account_id =
|
||||||
$query['link']['Lease'] = array();
|
$this->StatementEntry->Account->securityDepositAccountID();
|
||||||
if (!isset($query['link']['Lease']['fields']))
|
|
||||||
$query['link']['Lease']['fields'] = array();
|
|
||||||
|
|
||||||
$query['conditions'][] = array('Lease.id' => $id);
|
$squery = $query;
|
||||||
$query['conditions'][] = array('StatementEntry.account_id' =>
|
$squery['conditions'][] = array('StatementEntry.customer_id' => $id);
|
||||||
$this->StatementEntry->Account->securityDepositAccountID());
|
$squery['conditions'][] = array('StatementEntry.account_id' => $sd_account_id);
|
||||||
|
$stats = $this->StatementEntry->stats(null, $squery);
|
||||||
|
$this->pr(26, compact('squery', 'stats'));
|
||||||
|
|
||||||
$stats = $this->StatementEntry->stats(null, $query);
|
// OK, we know now how much we charged for a security
|
||||||
$balance = $stats['Charge']['reconciled'] - $stats['Payment']['reconciled'];
|
// deposit, as well as how much we received to pay for it.
|
||||||
return $this->prReturn($balance);
|
// Now we need to know if any has been released.
|
||||||
|
// Yes... this sucks.
|
||||||
|
$lquery = $query;
|
||||||
|
$lquery['link'] = array('Transaction' =>
|
||||||
|
array('fields' => array(),
|
||||||
|
'Customer' =>
|
||||||
|
(empty($query['link'])
|
||||||
|
? array('fields' => array())
|
||||||
|
: $query['link'])));
|
||||||
|
$lquery['conditions'][] = array('Transaction.customer_id' => $id);
|
||||||
|
$lquery['conditions'][] = array('LedgerEntry.account_id' => $sd_account_id);
|
||||||
|
$lquery['conditions'][] = array('LedgerEntry.crdr' => 'DEBIT');
|
||||||
|
$lquery['fields'][] = 'SUM(LedgerEntry.amount) AS total';
|
||||||
|
$released = $this->StatementEntry->Transaction->LedgerEntry->find
|
||||||
|
('first', $lquery);
|
||||||
|
$this->pr(26, compact('lquery', 'released'));
|
||||||
|
|
||||||
|
return $this->prReturn($stats['Charge']['disbursement'] - $released[0]['total']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -132,92 +156,12 @@ class Customer extends AppModel {
|
|||||||
$this->prEnter(compact('id', 'query'));
|
$this->prEnter(compact('id', 'query'));
|
||||||
$this->queryInit($query);
|
$this->queryInit($query);
|
||||||
|
|
||||||
if (!isset($query['link']['Customer']))
|
$query['conditions'][] = array('StatementEntry.customer_id' => $id);
|
||||||
$query['link']['Customer'] = array();
|
|
||||||
if (!isset($query['link']['Customer']['fields']))
|
|
||||||
$query['link']['Customer']['fields'] = array();
|
|
||||||
/* if (!isset($query['link']['StatementEntry'])) */
|
|
||||||
/* $query['link']['StatementEntry'] = array(); */
|
|
||||||
/* if (!isset($query['link']['StatementEntry']['Customer'])) */
|
|
||||||
/* $query['link']['StatementEntry']['Customer'] = array(); */
|
|
||||||
/* if (!isset($query['link']['StatementEntry']['Customer']['fields'])) */
|
|
||||||
/* $query['link']['StatementEntry']['Customer']['fields'] = array(); */
|
|
||||||
|
|
||||||
$query['conditions'][] = array('Customer.id' => $id);
|
|
||||||
|
|
||||||
$set = $this->StatementEntry->reconciledSet('CHARGE', $query, true);
|
$set = $this->StatementEntry->reconciledSet('CHARGE', $query, true);
|
||||||
return $this->prReturn($set);
|
return $this->prReturn($set);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* function: excessPayments
|
|
||||||
* - Returns payments which have not yet been fully utilized
|
|
||||||
*/
|
|
||||||
|
|
||||||
function excessPayments($id, $query = null) {
|
|
||||||
$this->prEnter(compact('id', 'query'));
|
|
||||||
$this->queryInit($query);
|
|
||||||
|
|
||||||
if (!isset($query['link']['StatementEntry']))
|
|
||||||
$query['link']['StatementEntry'] = array();
|
|
||||||
/* if (!isset($query['link']['StatementEntry']['Customer'])) */
|
|
||||||
/* $query['link']['StatementEntry']['Customer'] = array(); */
|
|
||||||
/* if (!isset($query['link']['StatementEntry']['Customer']['fields'])) */
|
|
||||||
/* $query['link']['StatementEntry']['Customer']['fields'] = array(); */
|
|
||||||
|
|
||||||
$query['conditions'][] = array('Customer.id' => $id);
|
|
||||||
|
|
||||||
$set = $this->StatementEntry->reconciledSet('PAYMENT', $query, true);
|
|
||||||
return $this->prReturn($set);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
**************************************************************************
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -233,10 +177,8 @@ class Customer extends AppModel {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
$I = new Contact();
|
$I = new Contact();
|
||||||
$I->create();
|
if (!$I->saveContact(null, array('Contact' => $contact)))
|
||||||
if (!$I->save($contact, false)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
$contact['id'] = $I->id;
|
$contact['id'] = $I->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,6 +202,13 @@ class Customer extends AppModel {
|
|||||||
}
|
}
|
||||||
$id = $this->id;
|
$id = $this->id;
|
||||||
|
|
||||||
|
// Appears that $this->save() "helpfully" choses to add in
|
||||||
|
// any missing data fields, populated with default values.
|
||||||
|
// So, after saving is complete, the fields 'lease_count',
|
||||||
|
// 'past_lease_count', and 'current_lease_count' have all
|
||||||
|
// been reset to zero. Gee, thanks Cake...
|
||||||
|
$this->update($id);
|
||||||
|
|
||||||
// Remove all associated Customer Contacts, as it ensures
|
// Remove all associated Customer Contacts, as it ensures
|
||||||
// any entries deleted by the user actually get deleted
|
// any entries deleted by the user actually get deleted
|
||||||
// in the system. We'll recreate the needed ones anyway.
|
// in the system. We'll recreate the needed ones anyway.
|
||||||
@@ -294,6 +243,200 @@ class Customer extends AppModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: update
|
||||||
|
* - Update any cached or calculated fields
|
||||||
|
*/
|
||||||
|
function update($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
|
||||||
|
if (empty($id)) {
|
||||||
|
$customers = $this->find('all', array('contain' => false, 'fields' => array('id')));
|
||||||
|
foreach ($customers AS $customer) {
|
||||||
|
// This SHOULDN'T happen, but check to be sure
|
||||||
|
// or we'll get infinite recursion.
|
||||||
|
if (empty($customer['Customer']['id']))
|
||||||
|
continue;
|
||||||
|
$this->update($customer['Customer']['id']);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// updateLeaseCount is typically handled directly when needed.
|
||||||
|
// However, this function is used to _ensure_ customer info is
|
||||||
|
// current, so we're obligated to call it anyway.
|
||||||
|
$this->updateLeaseCount($id);
|
||||||
|
|
||||||
|
$current_leases =
|
||||||
|
$this->find('all',
|
||||||
|
// REVISIT <AP>: 20090816
|
||||||
|
// Do we need to update leases other than the current ones?
|
||||||
|
// It may be necessary. For example, a non-current lease
|
||||||
|
// can still be hit with an NSF item. In that case, it
|
||||||
|
// could have stale data if we look only to current leases.
|
||||||
|
//array('link' => array('CurrentLease' => array('type' => 'INNER')),
|
||||||
|
array('link' => array('Lease' => array('type' => 'INNER')),
|
||||||
|
'conditions' => array('Customer.id' => $id)));
|
||||||
|
|
||||||
|
foreach ($current_leases AS $lease) {
|
||||||
|
if (!empty($lease['CurrentLease']['id']))
|
||||||
|
$this->Lease->update($lease['CurrentLease']['id']);
|
||||||
|
if (!empty($lease['Lease']['id']))
|
||||||
|
$this->Lease->update($lease['Lease']['id']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: merge
|
||||||
|
* - Merges two customers into one
|
||||||
|
*/
|
||||||
|
|
||||||
|
function merge($dst_id, $src_id, $contacts) {
|
||||||
|
$this->prEnter(compact('dst_id', 'src_id', 'contacts'));
|
||||||
|
|
||||||
|
// Get the entire list of destination customer contacts
|
||||||
|
$dst_contacts = array();
|
||||||
|
$result = $this->find('all',
|
||||||
|
array('link' => array('ContactsCustomer'),
|
||||||
|
'fields' => array('ContactsCustomer.contact_id', 'ContactsCustomer.type'),
|
||||||
|
'conditions' => array(array('id' => $dst_id,
|
||||||
|
'ContactsCustomer.active' => true))));
|
||||||
|
foreach ($result AS $contact) {
|
||||||
|
$dst_contacts[$contact['ContactsCustomer']['contact_id']] = $contact['ContactsCustomer'];
|
||||||
|
}
|
||||||
|
$this->pr(17, compact('dst_contacts'));
|
||||||
|
|
||||||
|
// Get the entire list of source customer contacts
|
||||||
|
$src_contacts = array();
|
||||||
|
$result = $this->find('all',
|
||||||
|
array('link' => array('ContactsCustomer'),
|
||||||
|
'fields' => array('ContactsCustomer.contact_id', 'ContactsCustomer.type'),
|
||||||
|
'conditions' => array(array('id' => $src_id,
|
||||||
|
'ContactsCustomer.active' => true))));
|
||||||
|
foreach ($result AS $contact) {
|
||||||
|
$src_contacts[$contact['ContactsCustomer']['contact_id']] = $contact['ContactsCustomer'];
|
||||||
|
}
|
||||||
|
$this->pr(17, compact('src_contacts'));
|
||||||
|
|
||||||
|
// Verify the contacts list are all valid source customer contacts
|
||||||
|
foreach ($contacts AS $contact_id) {
|
||||||
|
if (!array_key_exists($contact_id, $src_contacts))
|
||||||
|
return $this->prReturn(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any contacts which are already destination customer contacts
|
||||||
|
$new_contacts = array_diff($contacts, array_keys($dst_contacts));
|
||||||
|
$all_contacts = array_merge($new_contacts, array_keys($dst_contacts));
|
||||||
|
$this->pr(17, compact('new_contacts', 'all_contacts'));
|
||||||
|
|
||||||
|
// For now, we'll assume the operation will succeed.
|
||||||
|
$ret = true;
|
||||||
|
|
||||||
|
// Add each desired source customer contact to the destination customer
|
||||||
|
foreach ($new_contacts AS $contact_id) {
|
||||||
|
$CM = new ContactsCustomer();
|
||||||
|
if (!$CM->save(array('customer_id' => $dst_id)
|
||||||
|
+ $src_contacts[$contact_id], false)) {
|
||||||
|
$ret = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->Lease->updateAll
|
||||||
|
(array('Lease.customer_id' => $dst_id),
|
||||||
|
array('Lease.customer_id' => $src_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->Tender->updateAll
|
||||||
|
(array('Tender.customer_id' => $dst_id),
|
||||||
|
array('Tender.customer_id' => $src_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->StatementEntry->updateAll
|
||||||
|
(array('StatementEntry.customer_id' => $dst_id),
|
||||||
|
array('StatementEntry.customer_id' => $src_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->Transaction->updateAll
|
||||||
|
(array('Transaction.customer_id' => $dst_id),
|
||||||
|
array('Transaction.customer_id' => $src_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Make sure our lease counts, etc are correct
|
||||||
|
$this->update($dst_id);
|
||||||
|
|
||||||
|
// Delete the old customer
|
||||||
|
$this->pr(12, compact('src_id'), "Delete Customer");
|
||||||
|
$this->delete($src_id);
|
||||||
|
|
||||||
|
// Delete all the orphaned customers
|
||||||
|
foreach (array_diff(array_keys($src_contacts), $all_contacts) AS $contact_id) {
|
||||||
|
// Delete un-used or duplicate contacts
|
||||||
|
// REVISIT <AP> 20100702:
|
||||||
|
// Not sure if we really want to do this.
|
||||||
|
// On the one hand, they're probably really redundant,
|
||||||
|
// and only clutter up the list of all contacts. On the
|
||||||
|
// other hand, it destroys data, not only losing the
|
||||||
|
// history, but making it difficult to recover if the
|
||||||
|
// merge is a mistake. Additionally, we need to do
|
||||||
|
// extra checking to ensure that the contact is not
|
||||||
|
// in use by some other customer.
|
||||||
|
// We need some sort of Contact.deleted field...
|
||||||
|
$this->pr(12, compact('contact_id'), "Delete Contact");
|
||||||
|
$this->Contact->delete($contact_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, delete all customer contact relationships
|
||||||
|
$this->ContactsCustomer->deleteAll
|
||||||
|
(array('customer_id' => $src_id), false);
|
||||||
|
|
||||||
|
// Return the result
|
||||||
|
return $this->prReturn($ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: updateLeaseCount
|
||||||
|
* - Updates the internal lease count
|
||||||
|
*/
|
||||||
|
|
||||||
|
function updateLeaseCount($id) {
|
||||||
|
$this->id = $id;
|
||||||
|
|
||||||
|
$lease_count =
|
||||||
|
$this->find('count',
|
||||||
|
array('link' => array('Lease' => array('type' => 'INNER')),
|
||||||
|
'conditions' => array('Customer.id' => $id)));
|
||||||
|
$current_count =
|
||||||
|
$this->find('count',
|
||||||
|
array('link' => array('CurrentLease' => array('type' => 'INNER')),
|
||||||
|
'conditions' => array('Customer.id' => $id)));
|
||||||
|
|
||||||
|
$this->saveField('lease_count', $lease_count);
|
||||||
|
$this->saveField('current_lease_count', $current_count);
|
||||||
|
$this->saveField('past_lease_count', $lease_count - $current_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: balance
|
||||||
|
* - Returns the balance of money owed on the lease
|
||||||
|
*/
|
||||||
|
|
||||||
|
function balance($id) {
|
||||||
|
$stats = $this->stats($id);
|
||||||
|
return $stats['balance'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -320,14 +463,14 @@ class Customer extends AppModel {
|
|||||||
/* $stats = $this->StatementEntry->find */
|
/* $stats = $this->StatementEntry->find */
|
||||||
/* ('first', array */
|
/* ('first', array */
|
||||||
/* ('contain' => false, */
|
/* ('contain' => false, */
|
||||||
/* 'fields' => $this->StatementEntry->chargePaymentFields(true), */
|
/* 'fields' => $this->StatementEntry->chargeDisbursementFields(true), */
|
||||||
/* 'conditions' => array('StatementEntry.customer_id' => $id), */
|
/* 'conditions' => array('StatementEntry.customer_id' => $id), */
|
||||||
/* )); */
|
/* )); */
|
||||||
|
|
||||||
$find_stats = $this->StatementEntry->find
|
$find_stats = $this->StatementEntry->find
|
||||||
('first', array
|
('first', array
|
||||||
('contain' => false,
|
('contain' => false,
|
||||||
'fields' => $this->StatementEntry->chargePaymentFields(true),
|
'fields' => $this->StatementEntry->chargeDisbursementFields(true),
|
||||||
'conditions' => array('StatementEntry.customer_id' => $id),
|
'conditions' => array('StatementEntry.customer_id' => $id),
|
||||||
));
|
));
|
||||||
$find_stats = $find_stats[0];
|
$find_stats = $find_stats[0];
|
||||||
|
|||||||
21
site/models/default_option.php
Normal file
21
site/models/default_option.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
class DefaultOption extends AppModel {
|
||||||
|
|
||||||
|
var $belongsTo =
|
||||||
|
array('OptionValue',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
function values($name = null) {
|
||||||
|
$this->prEnter(compact('name'));
|
||||||
|
|
||||||
|
$query = array();
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
$query['link']['DefaultOption'] = array();
|
||||||
|
$query['link']['DefaultOption']['type'] = 'INNER';
|
||||||
|
$query['link']['DefaultOption']['fields'] = array();
|
||||||
|
return $this->prReturn($this->OptionValue->values($name, $query));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
21
site/models/default_permission.php
Normal file
21
site/models/default_permission.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
class DefaultPermission extends AppModel {
|
||||||
|
|
||||||
|
var $belongsTo =
|
||||||
|
array('PermissionValue',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
function values($name = null) {
|
||||||
|
$this->prEnter(compact('name'));
|
||||||
|
|
||||||
|
$query = array();
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
$query['link']['DefaultPermission'] = array();
|
||||||
|
$query['link']['DefaultPermission']['type'] = 'INNER';
|
||||||
|
$query['link']['DefaultPermission']['fields'] = array();
|
||||||
|
return $this->prReturn($this->PermissionValue->values($name, $query));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -53,12 +53,27 @@ class DoubleEntry extends AppModel {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function addDoubleEntry($entry1, $entry2, $entry1_tender = null) {
|
function addDoubleEntry($entry1, $entry2, $entry1_tender = null) {
|
||||||
/* pr(array('DoubleEntry::addDoubleEntry' => */
|
//$this->prFunctionLevel(16);
|
||||||
/* compact('entry1', 'entry2', 'entry1_tender'))); */
|
$this->prEnter(compact('entry1', 'entry2', 'entry1_tender'));
|
||||||
|
|
||||||
$ret = array();
|
$ret = array();
|
||||||
if (!$this->verifyDoubleEntry($entry1, $entry2, $entry1_tender))
|
if (!$this->verifyDoubleEntry($entry1, $entry2, $entry1_tender))
|
||||||
return array('error' => true) + $ret;
|
return $this->prReturn(array('error' => true) + $ret);
|
||||||
|
|
||||||
|
// Handle the case where a double entry involves the same
|
||||||
|
// exact ledger. This would not serve any useful purpose.
|
||||||
|
// It is not, however, an error. It is semantically correct
|
||||||
|
// just not really logically correct. To make this easier,
|
||||||
|
// just ensure ledger_id is set for each entry, even though
|
||||||
|
// it would be handled later by the LedgerEntry model.
|
||||||
|
//array($entry1, $entry2) AS &$entry) {
|
||||||
|
for ($i=1; $i <= 2; ++$i) {
|
||||||
|
if (empty(${'entry'.$i}['ledger_id']))
|
||||||
|
${'entry'.$i}['ledger_id'] =
|
||||||
|
$this->DebitEntry->Account->currentLedgerID(${'entry'.$i}['account_id']);
|
||||||
|
}
|
||||||
|
if ($entry1['ledger_id'] == $entry2['ledger_id'])
|
||||||
|
return $this->prReturn(array('error' => false));
|
||||||
|
|
||||||
// Since this model only relates to DebitEntry and CreditEntry...
|
// Since this model only relates to DebitEntry and CreditEntry...
|
||||||
$LE = new LedgerEntry();
|
$LE = new LedgerEntry();
|
||||||
@@ -67,13 +82,13 @@ class DoubleEntry extends AppModel {
|
|||||||
$result = $LE->addLedgerEntry($entry1, $entry1_tender);
|
$result = $LE->addLedgerEntry($entry1, $entry1_tender);
|
||||||
$ret['Entry1'] = $result;
|
$ret['Entry1'] = $result;
|
||||||
if ($result['error'])
|
if ($result['error'])
|
||||||
return array('error' => true) + $ret;
|
return $this->prReturn(array('error' => true) + $ret);
|
||||||
|
|
||||||
// Add the second ledger entry to the database
|
// Add the second ledger entry to the database
|
||||||
$result = $LE->addLedgerEntry($entry2);
|
$result = $LE->addLedgerEntry($entry2);
|
||||||
$ret['Entry2'] = $result;
|
$ret['Entry2'] = $result;
|
||||||
if ($result['error'])
|
if ($result['error'])
|
||||||
return array('error' => true) + $ret;
|
return $this->prReturn(array('error' => true) + $ret);
|
||||||
|
|
||||||
// Now link them as a double entry
|
// Now link them as a double entry
|
||||||
$double_entry = array();
|
$double_entry = array();
|
||||||
@@ -82,15 +97,13 @@ class DoubleEntry extends AppModel {
|
|||||||
$double_entry['credit_entry_id'] =
|
$double_entry['credit_entry_id'] =
|
||||||
($entry1['crdr'] === 'CREDIT') ? $ret['Entry1']['ledger_entry_id'] : $ret['Entry2']['ledger_entry_id'];
|
($entry1['crdr'] === 'CREDIT') ? $ret['Entry1']['ledger_entry_id'] : $ret['Entry2']['ledger_entry_id'];
|
||||||
|
|
||||||
/* pr(array('DoubleEntry::addDoubleEntry' => */
|
$ret['data'] = $double_entry;
|
||||||
/* array('checkpoint' => 'Pre-Save') */
|
|
||||||
/* + compact('double_entry'))); */
|
|
||||||
|
|
||||||
$this->create();
|
$this->create();
|
||||||
if (!$this->save($double_entry))
|
if (!$this->save($double_entry))
|
||||||
return array('error' => true) + $ret;
|
return $this->prReturn(array('error' => true) + $ret);
|
||||||
|
|
||||||
$ret['double_entry_id'] = $this->id;
|
$ret['double_entry_id'] = $this->id;
|
||||||
return $ret + array('error' => false);
|
return $this->prReturn($ret + array('error' => false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
38
site/models/group.php
Normal file
38
site/models/group.php
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
class Group extends AppModel {
|
||||||
|
|
||||||
|
var $hasMany =
|
||||||
|
array('GroupOption',
|
||||||
|
'Membership',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $knows =
|
||||||
|
array('User',
|
||||||
|
'Site',
|
||||||
|
);
|
||||||
|
|
||||||
|
static $current_group_ids;
|
||||||
|
function currentGroupIds() {
|
||||||
|
if (empty(self::$current_group_ids))
|
||||||
|
self::$current_group_ids = $this->groupIds();
|
||||||
|
|
||||||
|
if (empty(self::$current_group_ids))
|
||||||
|
// We must force a stop here, since this is typically
|
||||||
|
// called very early on, and so will cause a recursive
|
||||||
|
// crash as we try to render the internal error and
|
||||||
|
// again stumble on this problem.
|
||||||
|
$this->INTERNAL_ERROR('INVALID MEMBERSHIP', 0, true);
|
||||||
|
|
||||||
|
return self::$current_group_ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
function groupIds($user_id = null, $site_id = null) {
|
||||||
|
if (empty($user_id))
|
||||||
|
$user_id = $this->User->currentUserId();
|
||||||
|
if (empty($site_id))
|
||||||
|
$site_id = $this->Site->currentSiteId();
|
||||||
|
|
||||||
|
return $this->Membership->memberGroups($user_id, $site_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
25
site/models/group_option.php
Normal file
25
site/models/group_option.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
class GroupOption extends AppModel {
|
||||||
|
|
||||||
|
var $belongsTo =
|
||||||
|
array('Group',
|
||||||
|
'OptionValue',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
function values($ids, $name = null) {
|
||||||
|
$this->prEnter(compact('id', 'name'));
|
||||||
|
|
||||||
|
$query = array();
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
$query['link']['GroupOption'] = array();
|
||||||
|
$query['link']['GroupOption']['fields'] = array();
|
||||||
|
$query['link']['GroupOption']['Group'] = array();
|
||||||
|
$query['link']['GroupOption']['Group']['fields'] = array();
|
||||||
|
$query['conditions'][] = array('Group.id' => $ids);
|
||||||
|
$query['order'][] = 'Group.rank';
|
||||||
|
return $this->prReturn($this->OptionValue->values($name, $query));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
25
site/models/group_permission.php
Normal file
25
site/models/group_permission.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
class GroupPermission extends AppModel {
|
||||||
|
|
||||||
|
var $belongsTo =
|
||||||
|
array('Group',
|
||||||
|
'PermissionValue',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
function values($ids, $name = null) {
|
||||||
|
$this->prEnter(compact('id', 'name'));
|
||||||
|
|
||||||
|
$query = array();
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
$query['link']['GroupPermission'] = array();
|
||||||
|
$query['link']['GroupPermission']['fields'] = array();
|
||||||
|
$query['link']['GroupPermission']['Group'] = array();
|
||||||
|
$query['link']['GroupPermission']['Group']['fields'] = array();
|
||||||
|
$query['conditions'][] = array('Group.id' => $ids);
|
||||||
|
$query['order'][] = 'Group.rank';
|
||||||
|
return $this->prReturn($this->PermissionValue->values($name, $query));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ class Lease extends AppModel {
|
|||||||
'StatementEntry',
|
'StatementEntry',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//var $default_log_level = array('log' => 30, 'show' => 30);
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -23,21 +24,11 @@ class Lease extends AppModel {
|
|||||||
$this->prEnter(compact('id', 'query'));
|
$this->prEnter(compact('id', 'query'));
|
||||||
$this->queryInit($query);
|
$this->queryInit($query);
|
||||||
|
|
||||||
if (!isset($query['link']['Lease']))
|
$query['conditions'][] = array('StatementEntry.lease_id' => $id);
|
||||||
$query['link']['Lease'] = array();
|
|
||||||
if (!isset($query['link']['Lease']['fields']))
|
|
||||||
$query['link']['Lease']['fields'] = array();
|
|
||||||
|
|
||||||
$query['conditions'][] = array('Lease.id' => $id);
|
|
||||||
$query['conditions'][] = array('StatementEntry.account_id' =>
|
$query['conditions'][] = array('StatementEntry.account_id' =>
|
||||||
$this->StatementEntry->Account->securityDepositAccountID());
|
$this->StatementEntry->Account->securityDepositAccountID());
|
||||||
|
|
||||||
$set = $this->StatementEntry->reconciledSet('CHARGE', $query, false, true);
|
$set = $this->StatementEntry->reconciledSet('CHARGE', $query, false, true);
|
||||||
|
|
||||||
/* $set['summary'] = array('total' => $set['summary']['Charge']['total'], */
|
|
||||||
/* 'balance' => $set['summary']['Charge']['reconciled'], */
|
|
||||||
/* ); */
|
|
||||||
|
|
||||||
return $this->prReturn($set);
|
return $this->prReturn($set);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,18 +44,26 @@ class Lease extends AppModel {
|
|||||||
$this->prEnter(compact('id', 'query'));
|
$this->prEnter(compact('id', 'query'));
|
||||||
$this->queryInit($query);
|
$this->queryInit($query);
|
||||||
|
|
||||||
if (!isset($query['link']['Lease']))
|
// REVISIT <AP>: 20090807
|
||||||
$query['link']['Lease'] = array();
|
// Let's try simplifying the security deposit issue.
|
||||||
if (!isset($query['link']['Lease']['fields']))
|
// Presume that security deposits are NOT used at all,
|
||||||
$query['link']['Lease']['fields'] = array();
|
// until the customer moves out of the unit. At that
|
||||||
|
// time, the ENTIRE deposit is converted to customer
|
||||||
|
// credit. Piece of cake.
|
||||||
|
// For more information, see file revision history,
|
||||||
|
// including the revision just before this, r503.
|
||||||
|
|
||||||
$query['conditions'][] = array('Lease.id' => $id);
|
$this->id = $id;
|
||||||
|
$moveout_date = $this->field('moveout_date');
|
||||||
|
if (!empty($moveout_date))
|
||||||
|
return $this->prReturn(0);
|
||||||
|
|
||||||
|
$query['conditions'][] = array('StatementEntry.lease_id' => $id);
|
||||||
$query['conditions'][] = array('StatementEntry.account_id' =>
|
$query['conditions'][] = array('StatementEntry.account_id' =>
|
||||||
$this->StatementEntry->Account->securityDepositAccountID());
|
$this->StatementEntry->Account->securityDepositAccountID());
|
||||||
|
|
||||||
$stats = $this->StatementEntry->stats(null, $query);
|
$stats = $this->StatementEntry->stats(null, $query);
|
||||||
$balance = $stats['Charge']['reconciled'] - $stats['Payment']['reconciled'];
|
return $this->prReturn($stats['Charge']['disbursement']);
|
||||||
return $this->prReturn($balance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -73,21 +72,18 @@ class Lease extends AppModel {
|
|||||||
**************************************************************************
|
**************************************************************************
|
||||||
* function: releaseSecurityDeposits
|
* function: releaseSecurityDeposits
|
||||||
* - Releases all security deposits associated with this lease.
|
* - 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
|
* to pay outstanding customer charges, or simply to become
|
||||||
* a customer surplus (customer credit).
|
* a customer surplus (customer credit).
|
||||||
*/
|
*/
|
||||||
function releaseSecurityDeposits($id, $query = null) {
|
function releaseSecurityDeposits($id, $stamp = null, $query = null) {
|
||||||
$this->prFunctionLevel(30);
|
//$this->prFunctionLevel(30);
|
||||||
$this->prEnter(compact('id', 'query'));
|
$this->prEnter(compact('id', 'stamp', 'query'));
|
||||||
|
|
||||||
$secdeps = $this->securityDeposits($id, $query);
|
$secdeps = $this->securityDeposits($id, $query);
|
||||||
$secdeps = $secdeps['entries'];
|
$secdeps = $secdeps['entries'];
|
||||||
$this->pr(20, compact('secdeps'));
|
$this->pr(20, compact('secdeps'));
|
||||||
|
|
||||||
$this->securityDepositBalance($id, $query);
|
|
||||||
die();
|
|
||||||
|
|
||||||
// If there are no paid security deposits, then
|
// If there are no paid security deposits, then
|
||||||
// we can consider all security deposits released.
|
// we can consider all security deposits released.
|
||||||
if (count($secdeps) == 0)
|
if (count($secdeps) == 0)
|
||||||
@@ -95,23 +91,17 @@ class Lease extends AppModel {
|
|||||||
|
|
||||||
// Build a transaction
|
// Build a transaction
|
||||||
$release = array('Transaction' => array(), 'Entry' => array());
|
$release = array('Transaction' => array(), 'Entry' => array());
|
||||||
|
$release['Transaction']['stamp'] = $stamp;
|
||||||
$release['Transaction']['comment'] = "Security Deposit Release";
|
$release['Transaction']['comment'] = "Security Deposit Release";
|
||||||
foreach ($secdeps AS $charge) {
|
foreach ($secdeps AS $charge) {
|
||||||
if ($charge['StatementEntry']['type'] !== 'CHARGE')
|
if ($charge['StatementEntry']['type'] !== 'CHARGE')
|
||||||
die("INTERNAL ERROR: SECURITY DEPOSIT IS NOT CHARGE");
|
die("INTERNAL ERROR: SECURITY DEPOSIT IS NOT CHARGE");
|
||||||
|
|
||||||
// Since security deposits are being released, this also means
|
// Since security deposits are being released, this also means
|
||||||
// we're reducing any oustanding amount on a security deposit
|
// any unpaid (or only partially paid) security deposit should
|
||||||
// since we no longer expect it to be owed.
|
// have the remaining balance reversed.
|
||||||
// REVISIT <AP>: 20090730
|
if ($charge['StatementEntry']['balance'] > 0)
|
||||||
// This is kludgy, and I really don't like it. However, this
|
$this->StatementEntry->reverse($charge['StatementEntry']['id'], true, $stamp);
|
||||||
// is not presently something that even happens at the moment,
|
|
||||||
// so this solution will have to work until we come up with
|
|
||||||
// something more robust, like flagging those charges as defunct.
|
|
||||||
if ($charge['StatementEntry']['balance'] > 0) {
|
|
||||||
$this->StatementEntry->id = $charge['StatementEntry']['id'];
|
|
||||||
$this->StatementEntry->saveField('amount', $charge['StatementEntry']['reconciled']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$release['Entry'][] =
|
$release['Entry'][] =
|
||||||
array('amount' => $charge['StatementEntry']['reconciled'],
|
array('amount' => $charge['StatementEntry']['reconciled'],
|
||||||
@@ -121,10 +111,14 @@ class Lease extends AppModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$customer_id = $secdeps[0]['StatementEntry']['customer_id'];
|
$customer_id = $secdeps[0]['StatementEntry']['customer_id'];
|
||||||
$lease_id = $secdeps[0]['StatementEntry']['lease_id'];
|
$lease_id = $secdeps[0]['StatementEntry']['lease_id'];
|
||||||
|
|
||||||
|
// Add receipt of the security deposit funds. Do NOT
|
||||||
|
// flag them as part of the lease, as all received funds
|
||||||
|
// are only associated with the customer, for future
|
||||||
|
// (or present) disbursement on any lease.
|
||||||
$result = $this->StatementEntry->Transaction->addReceipt
|
$result = $this->StatementEntry->Transaction->addReceipt
|
||||||
($release, $customer_id, $lease_id);
|
($release, $customer_id, null);
|
||||||
|
|
||||||
return $this->prReturn($result);
|
return $this->prReturn($result);
|
||||||
}
|
}
|
||||||
@@ -154,8 +148,11 @@ class Lease extends AppModel {
|
|||||||
array('class' => 'StatementEntry',
|
array('class' => 'StatementEntry',
|
||||||
'fields' => array(),
|
'fields' => array(),
|
||||||
'conditions' => array
|
'conditions' => array
|
||||||
('SEx.effective_date = DATE_ADD(StatementEntry.through_date, INTERVAL 1 day)',
|
('SEx.lease_id = StatementEntry.lease_id',
|
||||||
'SEx.lease_id = StatementEntry.lease_id',
|
'SEx.type' => 'CHARGE',
|
||||||
|
'SEx.account_id' => $rent_account_id,
|
||||||
|
'SEx.reverse_transaction_id IS NULL',
|
||||||
|
'SEx.effective_date = DATE_ADD(StatementEntry.through_date, INTERVAL 1 day)',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -165,6 +162,7 @@ class Lease extends AppModel {
|
|||||||
'conditions' => array(array('Lease.id' => $id),
|
'conditions' => array(array('Lease.id' => $id),
|
||||||
array('StatementEntry.type' => 'CHARGE'),
|
array('StatementEntry.type' => 'CHARGE'),
|
||||||
array('StatementEntry.account_id' => $rent_account_id),
|
array('StatementEntry.account_id' => $rent_account_id),
|
||||||
|
array('StatementEntry.reverse_transaction_id IS NULL'),
|
||||||
array('SEx.id' => null),
|
array('SEx.id' => null),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -174,6 +172,35 @@ class Lease extends AppModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: lateCharges
|
||||||
|
* - Returns a list of late charges from this lease
|
||||||
|
*/
|
||||||
|
|
||||||
|
function lateCharges($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
$late_account_id = $this->StatementEntry->Account->lateChargeAccountID();
|
||||||
|
$entries = $this->StatementEntry->find
|
||||||
|
('all',
|
||||||
|
array('link' =>
|
||||||
|
array(// Models
|
||||||
|
'Lease',
|
||||||
|
),
|
||||||
|
|
||||||
|
//'fields' => array('id', 'amount', 'effective_date', 'through_date'),
|
||||||
|
'conditions' => array(array('Lease.id' => $id),
|
||||||
|
array('StatementEntry.type' => 'CHARGE'),
|
||||||
|
array('StatementEntry.account_id' => $late_account_id),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->prReturn($entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -236,7 +263,9 @@ class Lease extends AppModel {
|
|||||||
|
|
||||||
'conditions' =>
|
'conditions' =>
|
||||||
array(array('StatementEntry.lease_id' => $id),
|
array(array('StatementEntry.lease_id' => $id),
|
||||||
array('StatementEntry.account_id' => $rent_account_id)),
|
array('StatementEntry.account_id' => $rent_account_id),
|
||||||
|
array('StatementEntry.reverse_transaction_id IS NULL'),
|
||||||
|
),
|
||||||
|
|
||||||
'order' => array('StatementEntry.effective_date'),
|
'order' => array('StatementEntry.effective_date'),
|
||||||
),
|
),
|
||||||
@@ -255,7 +284,9 @@ class Lease extends AppModel {
|
|||||||
('CHARGE',
|
('CHARGE',
|
||||||
array('conditions' =>
|
array('conditions' =>
|
||||||
array(array('StatementEntry.lease_id' => $id),
|
array(array('StatementEntry.lease_id' => $id),
|
||||||
array('StatementEntry.account_id' => $rent_account_id)),
|
array('StatementEntry.account_id' => $rent_account_id),
|
||||||
|
array('StatementEntry.reverse_transaction_id IS NULL'),
|
||||||
|
),
|
||||||
|
|
||||||
'order' => array('StatementEntry.through_date DESC'),
|
'order' => array('StatementEntry.through_date DESC'),
|
||||||
),
|
),
|
||||||
@@ -273,6 +304,263 @@ class Lease extends AppModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: assessMonthlyRent
|
||||||
|
* - Charges rent for the month, if not already charged.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function assessMonthlyRent($id, $date = null) {
|
||||||
|
$this->prEnter(compact('id', 'date'));
|
||||||
|
$this->id = $id;
|
||||||
|
|
||||||
|
if (empty($date))
|
||||||
|
$date = time();
|
||||||
|
|
||||||
|
if (is_string($date))
|
||||||
|
$date = strtotime($date);
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090808
|
||||||
|
// Anniversary Billing not supported
|
||||||
|
$anniversary = 0 && $this->field('anniversary_billing');
|
||||||
|
if (empty($anniversary)) {
|
||||||
|
$date_parts = getdate($date);
|
||||||
|
$date = mktime(0, 0, 0, $date_parts['mon'], 1, $date_parts['year']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we're not trying to assess rent on a closed lease
|
||||||
|
$close_date = $this->field('close_date');
|
||||||
|
$this->pr(17, compact('close_date'));
|
||||||
|
if (!empty($close_date))
|
||||||
|
return $this->prReturn(null);
|
||||||
|
|
||||||
|
// Don't assess rent after customer has moved out
|
||||||
|
$moveout_date = $this->field('moveout_date');
|
||||||
|
$this->pr(17, compact('moveout_date'));
|
||||||
|
if (!empty($moveout_date) && strtotime($moveout_date) < $date)
|
||||||
|
return $this->prReturn(null);
|
||||||
|
|
||||||
|
// Determine when the customer has already been charged through
|
||||||
|
// and, of course, don't charge them if they've already been.
|
||||||
|
$charge_through_date = strtotime($this->rentChargeThrough($id));
|
||||||
|
$this->pr(17, compact('date', 'charge_through_date')
|
||||||
|
+ array('date_str' => date('Y-m-d', $date),
|
||||||
|
'charge_through_date_str' => date('Y-m-d', $charge_through_date)));
|
||||||
|
if (!$charge_through_date)
|
||||||
|
return $this->prReturn(null);
|
||||||
|
if ($charge_through_date >= $date)
|
||||||
|
return $this->prReturn(null);
|
||||||
|
|
||||||
|
// OK, it seems we're going to go ahead and charge the customer
|
||||||
|
// on this lease. Calculate the new charge through date, which
|
||||||
|
// is 1 day shy of 1 month from $date. For example, if we're
|
||||||
|
// charging for 8/1/09, charge through will be 8/31/09, and
|
||||||
|
// charging for 8/15/09, charge through will be 9/14/09.
|
||||||
|
$date_parts = getdate($date);
|
||||||
|
$charge_through_date = mktime(0, 0, 0,
|
||||||
|
$date_parts['mon']+1,
|
||||||
|
$date_parts['mday']-1,
|
||||||
|
$date_parts['year']);
|
||||||
|
|
||||||
|
// Build the invoice transaction
|
||||||
|
$invoice = array('Transaction' => array(), 'Entry' => array());
|
||||||
|
// REVISIT <AP>: 20090808
|
||||||
|
// Keeping Transaction.stamp until the existing facility
|
||||||
|
// is up to date. Then we want the stamp to be now()
|
||||||
|
// (and so can just delete the next line).
|
||||||
|
$invoice['Transaction']['stamp'] = date('Y-m-d', $date);
|
||||||
|
$invoice['Entry'][] =
|
||||||
|
array('effective_date' => date('Y-m-d', $date),
|
||||||
|
'through_date' => date('Y-m-d', $charge_through_date),
|
||||||
|
'amount' => $this->field('rent'),
|
||||||
|
'account_id' => $this->StatementEntry->Account->rentAccountId(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Record the invoice and return the result
|
||||||
|
$this->pr(21, compact('invoice'));
|
||||||
|
$result = $this->StatementEntry->Transaction->addInvoice
|
||||||
|
($invoice, null, $id);
|
||||||
|
return $this->prReturn($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: assessMonthlyRentAll
|
||||||
|
* - Ensures rent has been charged on all open leases
|
||||||
|
*/
|
||||||
|
|
||||||
|
function assessMonthlyRentAll($date = null) {
|
||||||
|
$this->prEnter(compact('date'));
|
||||||
|
$leases = $this->find
|
||||||
|
('all', array('contain' => false,
|
||||||
|
'conditions' => array('Lease.close_date' => null),
|
||||||
|
));
|
||||||
|
|
||||||
|
$ret = array('Lease' => array());
|
||||||
|
foreach ($leases AS $lease) {
|
||||||
|
$result = $this->assessMonthlyRent($lease['Lease']['id'], $date);
|
||||||
|
$ret['Lease'][$lease['Lease']['id']] = $result;
|
||||||
|
if ($result['error'])
|
||||||
|
$ret['error'] = true;
|
||||||
|
}
|
||||||
|
return $this->prReturn($ret + array('error' => false));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: assessMonthlyLate
|
||||||
|
* - Assess late charges for the month, if not already charged.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function assessMonthlyLate($id, $date = null) {
|
||||||
|
$this->prEnter(compact('id', 'date'));
|
||||||
|
$this->id = $id;
|
||||||
|
|
||||||
|
if (empty($date))
|
||||||
|
$date = time();
|
||||||
|
|
||||||
|
if (is_string($date))
|
||||||
|
$date = strtotime($date);
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090808
|
||||||
|
// Anniversary Billing not supported
|
||||||
|
$anniversary = 0 && $this->field('anniversary_billing');
|
||||||
|
if (empty($anniversary)) {
|
||||||
|
$date_parts = getdate($date);
|
||||||
|
$date = mktime(0, 0, 0, $date_parts['mon'], 11, $date_parts['year']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't assess a late charge if the late charge date hasn't
|
||||||
|
// even come yet. This is questionable whether we really
|
||||||
|
// should restrict, since the user could know what they're
|
||||||
|
// doing, and/or the server clock could be off (although that
|
||||||
|
// would certainly have much larger ramifications). But, the
|
||||||
|
// fact is that this check likely handles the vast majority
|
||||||
|
// of the expected behavior, and presents an issue for very
|
||||||
|
// few users, if any at all.
|
||||||
|
if ($date > time())
|
||||||
|
return $this->prReturn(null);
|
||||||
|
|
||||||
|
// Make sure we're not trying to assess late charges on a closed lease
|
||||||
|
$close_date = $this->field('close_date');
|
||||||
|
$this->pr(17, compact('close_date'));
|
||||||
|
if (!empty($close_date))
|
||||||
|
return $this->prReturn(null);
|
||||||
|
|
||||||
|
// Don't assess late charges after customer has moved out
|
||||||
|
$moveout_date = $this->field('moveout_date');
|
||||||
|
$this->pr(17, compact('moveout_date'));
|
||||||
|
if (!empty($moveout_date) && strtotime($moveout_date) < $date)
|
||||||
|
return $this->prReturn(null);
|
||||||
|
|
||||||
|
// Determine when the customer has been charged through for rent
|
||||||
|
// and don't mark them as late if they haven't even been charged rent
|
||||||
|
$charge_through_date = strtotime($this->rentChargeThrough($id));
|
||||||
|
$this->pr(17, compact('date', 'charge_through_date')
|
||||||
|
+ array('date_str' => date('Y-m-d', $date),
|
||||||
|
'charge_through_date_str' => date('Y-m-d', $charge_through_date)));
|
||||||
|
if ($charge_through_date <= $date)
|
||||||
|
return $this->prReturn(null);
|
||||||
|
|
||||||
|
// Determine if the customer is actually late. This is based on
|
||||||
|
// when they've paid through, plus 10 days before they're late.
|
||||||
|
// REVISIT <AP>: 20090813
|
||||||
|
// Of course, 10 days is a terrible hardcode. This should be
|
||||||
|
// driven from the late schedule, saved as part of the lease
|
||||||
|
// (when finally implemented).
|
||||||
|
$paid_through_date = strtotime($this->rentPaidThrough($id));
|
||||||
|
$this->pr(17, compact('date', 'paid_through_date')
|
||||||
|
+ array('date_str' => date('Y-m-d', $date),
|
||||||
|
'paid_through_date_str' => date('Y-m-d', $paid_through_date)));
|
||||||
|
$date_parts = getdate($paid_through_date);
|
||||||
|
$paid_through_date = mktime(0, 0, 0, $date_parts['mon'], $date_parts['mday']+10, $date_parts['year']);
|
||||||
|
if ($paid_through_date >= $date)
|
||||||
|
return $this->prReturn(null);
|
||||||
|
|
||||||
|
// Determine if the customer has already been charged a late fee
|
||||||
|
// and, of course, don't charge them if they've already been.
|
||||||
|
$late_charges = $this->lateCharges($id);
|
||||||
|
foreach ($late_charges AS $late) {
|
||||||
|
if (strtotime($late['StatementEntry']['effective_date']) == $date)
|
||||||
|
return $this->prReturn(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the invoice transaction
|
||||||
|
$invoice = array('Transaction' => array(), 'Entry' => array());
|
||||||
|
// REVISIT <AP>: 20090808
|
||||||
|
// Keeping Transaction.stamp until the existing facility
|
||||||
|
// is up to date. Then we want the stamp to be now()
|
||||||
|
// (and so can just delete the next line).
|
||||||
|
$invoice['Transaction']['stamp'] = date('Y-m-d', $date);
|
||||||
|
$invoice['Entry'][] =
|
||||||
|
array('effective_date' => date('Y-m-d', $date),
|
||||||
|
'amount' => 10,
|
||||||
|
'account_id' => $this->StatementEntry->Account->lateChargeAccountId(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Record the invoice and return the result
|
||||||
|
$this->pr(21, compact('invoice'));
|
||||||
|
$result = $this->StatementEntry->Transaction->addInvoice
|
||||||
|
($invoice, null, $id);
|
||||||
|
return $this->prReturn($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: assessMonthlyLateAll
|
||||||
|
* - Ensures rent has been charged on all open leases
|
||||||
|
*/
|
||||||
|
|
||||||
|
function assessMonthlyLateAll($date = null) {
|
||||||
|
$this->prEnter(compact('date'));
|
||||||
|
$leases = $this->find
|
||||||
|
('all', array('contain' => false,
|
||||||
|
'conditions' => array('Lease.close_date' => null),
|
||||||
|
));
|
||||||
|
|
||||||
|
$ret = array('Lease' => array());
|
||||||
|
foreach ($leases AS $lease) {
|
||||||
|
$result = $this->assessMonthlyLate($lease['Lease']['id'], $date);
|
||||||
|
$ret['Lease'][$lease['Lease']['id']] = $result;
|
||||||
|
if ($result['error'])
|
||||||
|
$ret['error'] = true;
|
||||||
|
}
|
||||||
|
return $this->prReturn($ret + array('error' => false));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* functions: delinquency
|
||||||
|
* - SQL fragments to determine whether a lease is delinquent
|
||||||
|
*/
|
||||||
|
|
||||||
|
function conditionDelinquent($table_name = 'Lease') {
|
||||||
|
if (empty($table_name)) $t = ''; else $t = $table_name . '.';
|
||||||
|
return ("({$t}close_date IS NULL AND" .
|
||||||
|
" NOW() > DATE_ADD({$t}paid_through_date, INTERVAL 1 DAY))");
|
||||||
|
}
|
||||||
|
|
||||||
|
function delinquentDaysSQL($table_name = 'Lease') {
|
||||||
|
if (empty($table_name)) $t = ''; else $t = $table_name . '.';
|
||||||
|
return ("IF(" . $this->conditionDelinquent($table_name) . "," .
|
||||||
|
" DATEDIFF(NOW(), {$t}paid_through_date)-1," .
|
||||||
|
" NULL)");
|
||||||
|
}
|
||||||
|
|
||||||
|
function delinquentField($table_name = 'Lease') {
|
||||||
|
return ($this->delinquentDaysSQL($table_name) . " AS 'delinquent'");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -345,7 +633,10 @@ class Lease extends AppModel {
|
|||||||
// Set the lease number to be the same as the lease ID
|
// Set the lease number to be the same as the lease ID
|
||||||
$this->id;
|
$this->id;
|
||||||
$this->saveField('number', $this->id);
|
$this->saveField('number', $this->id);
|
||||||
|
|
||||||
|
// Update the current lease count for the customer
|
||||||
|
$this->Customer->updateLeaseCount($customer_id);
|
||||||
|
|
||||||
// Update the unit status
|
// Update the unit status
|
||||||
$this->Unit->updateStatus($unit_id, 'OCCUPIED');
|
$this->Unit->updateStatus($unit_id, 'OCCUPIED');
|
||||||
|
|
||||||
@@ -368,7 +659,7 @@ class Lease extends AppModel {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function moveOut($id, $status = 'VACANT',
|
function moveOut($id, $status = 'VACANT',
|
||||||
$stamp = null, $close = false)
|
$stamp = null, $close = true)
|
||||||
{
|
{
|
||||||
$this->prEnter(compact('id', 'status', 'stamp', 'close'));
|
$this->prEnter(compact('id', 'status', 'stamp', 'close'));
|
||||||
|
|
||||||
@@ -386,10 +677,16 @@ class Lease extends AppModel {
|
|||||||
// Save it!
|
// Save it!
|
||||||
$this->save($this->data, false);
|
$this->save($this->data, false);
|
||||||
|
|
||||||
|
// Release the security deposit(s)
|
||||||
|
$this->releaseSecurityDeposits($id, $stamp);
|
||||||
|
|
||||||
// Close the lease, if so requested
|
// Close the lease, if so requested
|
||||||
if ($close)
|
if ($close)
|
||||||
$this->close($id, $stamp);
|
$this->close($id, $stamp);
|
||||||
|
|
||||||
|
// Update the current lease count for the customer
|
||||||
|
$this->Customer->updateLeaseCount($this->field('customer_id'));
|
||||||
|
|
||||||
// Finally, update the unit status
|
// Finally, update the unit status
|
||||||
$this->recursive = -1;
|
$this->recursive = -1;
|
||||||
$this->read();
|
$this->read();
|
||||||
@@ -423,10 +720,61 @@ class Lease extends AppModel {
|
|||||||
|
|
||||||
// Save it!
|
// Save it!
|
||||||
$this->save($this->data, false);
|
$this->save($this->data, false);
|
||||||
|
|
||||||
|
// Update the current lease count for the customer
|
||||||
|
$this->Customer->updateLeaseCount($this->field('customer_id'));
|
||||||
|
|
||||||
return $this->prReturn(true);
|
return $this->prReturn(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: reopen
|
||||||
|
* - Re-Opens the lease for further action
|
||||||
|
*/
|
||||||
|
|
||||||
|
function reopen($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
|
||||||
|
if (!$this->isClosed($id))
|
||||||
|
return $this->prReturn(false);
|
||||||
|
|
||||||
|
// Reset the data
|
||||||
|
$this->create();
|
||||||
|
$this->id = $id;
|
||||||
|
|
||||||
|
// Set the close date
|
||||||
|
$this->data['Lease']['close_date'] = null;
|
||||||
|
|
||||||
|
// Save it!
|
||||||
|
$this->save($this->data, false);
|
||||||
|
|
||||||
|
// Update the current lease count for the customer
|
||||||
|
$this->Customer->updateLeaseCount($this->field('customer_id'));
|
||||||
|
|
||||||
|
return $this->prReturn(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: isClosed
|
||||||
|
* - Checks to see if the lease is closed
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isClosed($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
|
||||||
|
$this->recursive = -1;
|
||||||
|
$this->read(null, $id);
|
||||||
|
|
||||||
|
return $this->prReturn(!empty($this->data['Lease']['close_date']));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -448,12 +796,13 @@ class Lease extends AppModel {
|
|||||||
if (isset($this->data['Lease']['close_date']))
|
if (isset($this->data['Lease']['close_date']))
|
||||||
return $this->prReturn(false);
|
return $this->prReturn(false);
|
||||||
|
|
||||||
$deposit_balance = $this->securityDepositBalance($id);
|
|
||||||
$stats = $this->stats($id);
|
|
||||||
|
|
||||||
// A lease can only be closed if there are no outstanding
|
// A lease can only be closed if there are no outstanding
|
||||||
// security deposits, and if the account balance is zero.
|
// security deposits ...
|
||||||
if ($deposit_balance != 0)
|
if ($this->securityDepositBalance($id) != 0)
|
||||||
|
return $this->prReturn(false);
|
||||||
|
|
||||||
|
// ... and if the account balance is zero.
|
||||||
|
if ($this->balance($id) != 0)
|
||||||
return $this->prReturn(false);
|
return $this->prReturn(false);
|
||||||
|
|
||||||
// Apparently this lease meets all the criteria!
|
// Apparently this lease meets all the criteria!
|
||||||
@@ -464,12 +813,64 @@ class Lease extends AppModel {
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* function: addCharge
|
* function: refund
|
||||||
* - Adds an additional charge to the lease
|
* - Marks any lease balance as payable to the customer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function addCharge($id, $charge) {
|
function refund($id, $stamp = null) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
$balance = $this->balance($id);
|
||||||
|
|
||||||
|
if ($balance >= 0)
|
||||||
|
return $this->prReturn(array('error' => true));
|
||||||
|
|
||||||
|
$balance *= -1;
|
||||||
|
|
||||||
|
// Build a transaction
|
||||||
|
$refund = array('Transaction' => array(), 'Entry' => array());
|
||||||
|
$refund['Transaction']['stamp'] = $stamp;
|
||||||
|
$refund['Transaction']['comment'] = "Lease Refund";
|
||||||
|
|
||||||
|
$refund['Entry'][] =
|
||||||
|
array('amount' => $balance);
|
||||||
|
|
||||||
|
$result = $this->StatementEntry->Transaction->addRefund
|
||||||
|
($refund, null, $id);
|
||||||
|
|
||||||
|
return $this->prReturn($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: update
|
||||||
|
* - Update any cached or calculated fields
|
||||||
|
*/
|
||||||
|
function update($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
|
||||||
|
$this->id = $id;
|
||||||
|
$this->saveField('charge_through_date', $this->rentChargeThrough($id));
|
||||||
|
$this->saveField('paid_through_date', $this->rentPaidThrough($id));
|
||||||
|
|
||||||
|
$moveout = $this->field('moveout_date');
|
||||||
|
if (empty($moveout))
|
||||||
|
$this->Unit->update($this->field('unit_id'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: balance
|
||||||
|
* - Returns the balance of money owed on the lease
|
||||||
|
*/
|
||||||
|
|
||||||
|
function balance($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
$stats = $this->stats($id);
|
||||||
|
return $this->prReturn($stats['balance']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -485,42 +886,14 @@ class Lease extends AppModel {
|
|||||||
if (!$id)
|
if (!$id)
|
||||||
return $this->prReturn(null);
|
return $this->prReturn(null);
|
||||||
|
|
||||||
$this->queryInit($query);
|
$find_stats = $this->StatementEntry->find
|
||||||
|
('first', array
|
||||||
//$query['link'] = array('Lease' => $query['link']);
|
('contain' => false,
|
||||||
/* if (!isset($query['link']['StatementEntry'])) */
|
'fields' => $this->StatementEntry->chargeDisbursementFields(true),
|
||||||
/* $query['link']['StatementEntry'] = array(); */
|
'conditions' => array('StatementEntry.lease_id' => $id),
|
||||||
/* if (!isset($query['link']['StatementEntry']['ChargeEntry'])) */
|
));
|
||||||
/* $query['link']['StatementEntry']['ChargeEntry'] = array(); */
|
$find_stats = $find_stats[0];
|
||||||
|
return $this->prReturn($find_stats);
|
||||||
/* $query['link']['StatementEntry']['fields'] = array(); */
|
|
||||||
/* $query['link']['ChargeEntry']['fields'] = array(); */
|
|
||||||
/* $query['link']['ChargeEntry']['Account']['fields'] = array(); */
|
|
||||||
/* $query['link']['ChargeEntry']['StatementEntry']['fields'] = array(); */
|
|
||||||
/* $query['link']['ChargeEntry']['StatementEntry']['Invoice']['fields'] = array(); */
|
|
||||||
|
|
||||||
if (!isset($query['fields']))
|
|
||||||
$query['fields'] = array();
|
|
||||||
|
|
||||||
$query['fields'] = array_merge($query['fields'],
|
|
||||||
$this->StatementEntry->chargePaymentFields(true));
|
|
||||||
|
|
||||||
$query['conditions'][] = array('StatementEntry.lease_id' => $id);
|
|
||||||
|
|
||||||
$query['group'] = null;
|
|
||||||
|
|
||||||
$stats = $this->StatementEntry->find('first', $query);
|
|
||||||
//$this->pr(20, compact('query', 'stats'));
|
|
||||||
|
|
||||||
// The fields are all tucked into the [0] index,
|
|
||||||
// and the rest of the array is useless (empty).
|
|
||||||
$stats = $stats[0];
|
|
||||||
|
|
||||||
// Make sure we have a non-null balance
|
|
||||||
if (!isset($stats['balance']))
|
|
||||||
$stats['balance'] = 0;
|
|
||||||
|
|
||||||
return $this->prReturn($stats);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,22 @@ class LedgerEntry extends AppModel {
|
|||||||
);
|
);
|
||||||
|
|
||||||
var $hasOne = array(
|
var $hasOne = array(
|
||||||
'Tender',
|
'Tender' => array(
|
||||||
'DoubleEntry',
|
'dependent' => true,
|
||||||
|
),
|
||||||
|
'DebitDoubleEntry' => array(
|
||||||
|
'className' => 'DoubleEntry',
|
||||||
|
'foreignKey' => 'debit_entry_id',
|
||||||
|
'dependent' => true,
|
||||||
|
),
|
||||||
|
'CreditDoubleEntry' => array(
|
||||||
|
'className' => 'DoubleEntry',
|
||||||
|
'foreignKey' => 'credit_entry_id',
|
||||||
|
'dependent' => true,
|
||||||
|
),
|
||||||
|
'DoubleEntry' => array(
|
||||||
|
'foreignKey' => false,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
var $hasMany = array(
|
var $hasMany = array(
|
||||||
@@ -113,24 +127,20 @@ class LedgerEntry extends AppModel {
|
|||||||
* - Inserts new Ledger Entry into the database
|
* - Inserts new Ledger Entry into the database
|
||||||
*/
|
*/
|
||||||
function addLedgerEntry($entry, $tender = null) {
|
function addLedgerEntry($entry, $tender = null) {
|
||||||
/* pr(array('LedgerEntry::addLedgerEntry' => */
|
//$this->prFunctionLevel(16);
|
||||||
/* compact('entry', 'tender'))); */
|
$this->prEnter(compact('entry', 'tender'));
|
||||||
|
|
||||||
$ret = array();
|
$ret = array('data' => $entry);
|
||||||
if (!$this->verifyLedgerEntry($entry, $tender))
|
if (!$this->verifyLedgerEntry($entry, $tender))
|
||||||
return array('error' => true) + $ret;
|
return $this->prReturn(array('error' => true) + $ret);
|
||||||
|
|
||||||
if (empty($entry['ledger_id']))
|
if (empty($entry['ledger_id']))
|
||||||
$entry['ledger_id'] =
|
$entry['ledger_id'] =
|
||||||
$this->Account->currentLedgerID($entry['account_id']);
|
$this->Account->currentLedgerID($entry['account_id']);
|
||||||
|
|
||||||
/* pr(array('LedgerEntry::addLedgerEntry' => */
|
|
||||||
/* array('checkpoint' => 'Pre-Save') */
|
|
||||||
/* + compact('entry'))); */
|
|
||||||
|
|
||||||
$this->create();
|
$this->create();
|
||||||
if (!$this->save($entry))
|
if (!$this->save($entry))
|
||||||
return array('error' => true) + $ret;
|
return $this->prReturn(array('error' => true) + $ret);
|
||||||
|
|
||||||
$ret['ledger_entry_id'] = $this->id;
|
$ret['ledger_entry_id'] = $this->id;
|
||||||
|
|
||||||
@@ -140,10 +150,10 @@ class LedgerEntry extends AppModel {
|
|||||||
$result = $this->Tender->addTender($tender);
|
$result = $this->Tender->addTender($tender);
|
||||||
$ret['Tender'] = $result;
|
$ret['Tender'] = $result;
|
||||||
if ($result['error'])
|
if ($result['error'])
|
||||||
return array('error' => true) + $ret;
|
return $this->prReturn(array('error' => true) + $ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $ret + array('error' => false);
|
return $this->prReturn($ret + array('error' => false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -155,55 +165,13 @@ class LedgerEntry extends AppModel {
|
|||||||
*/
|
*/
|
||||||
function stats($id = null, $query = null, $set = null) {
|
function stats($id = null, $query = null, $set = null) {
|
||||||
$this->queryInit($query);
|
$this->queryInit($query);
|
||||||
unset($query['group']);
|
|
||||||
|
|
||||||
if (!isset($query['link']['DoubleEntry']))
|
// REVISIT <AP>: 20090816
|
||||||
$query['link']['DoubleEntry'] = array();
|
// This function appeared to be dramatically broken,
|
||||||
/* if (!isset($query['link']['DoubleEntry']['fields'])) */
|
// a throwback to an earlier time. I deleted its
|
||||||
/* $query['link']['DoubleEntry']['fields'] = array(); */
|
// contents and added this error to ensure it does
|
||||||
|
// not get used.
|
||||||
if (isset($id))
|
$this->INTERNAL_ERROR('This function should not be used');
|
||||||
$query['conditions'][] = array('Entry.id' => $id);
|
|
||||||
|
|
||||||
if (isset($set))
|
|
||||||
$set = strtoupper($set);
|
|
||||||
|
|
||||||
//pr(array('stats()', compact('id', 'query', 'set')));
|
|
||||||
|
|
||||||
$rtypes = array('charge', 'payment',
|
|
||||||
// 'debit', 'credit',
|
|
||||||
);
|
|
||||||
|
|
||||||
$stats = array();
|
|
||||||
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')) */
|
|
||||||
) {
|
|
||||||
|
|
||||||
$rquery = $query;
|
|
||||||
$rquery['link'][$Rtype] =
|
|
||||||
array('fields' => array("SUM(COALESCE(Applied{$Rtype}.amount,0)) AS reconciled"));
|
|
||||||
|
|
||||||
$rquery['fields'] = array();
|
|
||||||
//$rquery['fields'][] = "SUM(DoubleEntry.amount) AS total";
|
|
||||||
$rquery['fields'][] = "SUM(DoubleEntry.amount) - SUM(COALESCE(Applied{$Rtype}.amount,0)) AS balance";
|
|
||||||
$rquery['conditions'][] = array("Applied{$Rtype}.id !=" => null);
|
|
||||||
|
|
||||||
$result = $this->find('first', $rquery);
|
|
||||||
//pr(compact('Rtype', 'rquery', 'result'));
|
|
||||||
|
|
||||||
$sumfld = $Rtype;
|
|
||||||
$stats[$sumfld] = $result[0];
|
|
||||||
/* if (!isset($stats[$sumfld]['applied'])) */
|
|
||||||
/* $stats[$sumfld]['applied'] = 0; */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $stats;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
110
site/models/lock.php
Normal file
110
site/models/lock.php
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
<?php
|
||||||
|
class Lock extends AppModel {
|
||||||
|
|
||||||
|
var $name = 'Lock';
|
||||||
|
var $validate = array(
|
||||||
|
'id' => array('numeric'),
|
||||||
|
'name' => array('notempty'),
|
||||||
|
'key' => array('notempty')
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany = array(
|
||||||
|
'LocksUnits'
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasAndBelongsToMany = array(
|
||||||
|
'Unit'
|
||||||
|
);
|
||||||
|
|
||||||
|
var $default_log_level = array('log' => 30, 'show' => 15);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: saveLock
|
||||||
|
* - save data about a new or existing lock
|
||||||
|
*/
|
||||||
|
|
||||||
|
function saveLock($data) {
|
||||||
|
$this->prEnter(compact('data'));
|
||||||
|
$id = $data['Lock']['id'];
|
||||||
|
|
||||||
|
if ($id) {
|
||||||
|
$this->id = $id;
|
||||||
|
|
||||||
|
// Save the old key
|
||||||
|
$oldkey = $this->field('key');
|
||||||
|
$this->pr(5, compact('oldkey'));
|
||||||
|
|
||||||
|
if ($this->field('key') != $data['Lock']['key']) {
|
||||||
|
$data['Lock']['key_last'] = $this->field('key');
|
||||||
|
$data['Lock']['key_ts'] = date('Y-m-d G:i:s');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* // Find the number of outstanding locks in use */
|
||||||
|
/* $locks = $this->find('first', */
|
||||||
|
/* array('link' => array('Unit' => array('fields' => array('Unit.id'))), */
|
||||||
|
/* 'fields' => 'SUM(Unit.id) AS inuse', */
|
||||||
|
/* 'conditions' => array('Lock.id' => $id), */
|
||||||
|
/* )); */
|
||||||
|
/* $this->pr(5, compact('locks')); */
|
||||||
|
|
||||||
|
/* // Can't reduce the locks if there are all in use */
|
||||||
|
/* if ($locks[0]['inuse'] > $data['Lock']['qty']) */
|
||||||
|
/* return $this->prReturn(false); */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Brand new lock
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$data['Lock']['qty'])
|
||||||
|
$data['Lock']['qty'] = 1;
|
||||||
|
|
||||||
|
// Everything looks good... save it!
|
||||||
|
return $this->prReturn($this->save($data, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: destroy
|
||||||
|
* - destroys a lock
|
||||||
|
*/
|
||||||
|
|
||||||
|
function destroy($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
|
||||||
|
// Can't delete a lock that's in use... check.
|
||||||
|
$this->id = $id;
|
||||||
|
$lock = $this->find
|
||||||
|
('first', array
|
||||||
|
('contain' => array('Unit'),
|
||||||
|
));
|
||||||
|
|
||||||
|
// If it's in use, bail with error
|
||||||
|
$this->pr(1, $lock);
|
||||||
|
if (isset($lock['Unit']) && count($lock['Unit']) > 0)
|
||||||
|
return $this->prReturn(false);
|
||||||
|
|
||||||
|
// Otherwise, attempt to delete the lock from the database
|
||||||
|
return $this->prReturn($this->delete());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: lockList
|
||||||
|
* - list of all locks in the system
|
||||||
|
*/
|
||||||
|
|
||||||
|
function lockList() {
|
||||||
|
return $this->find('list',
|
||||||
|
array('order' =>
|
||||||
|
array('name'),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
11
site/models/locks_unit.php
Normal file
11
site/models/locks_unit.php
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
class LocksUnit extends AppModel {
|
||||||
|
var $primaryKey = false;
|
||||||
|
|
||||||
|
var $belongsTo = array(
|
||||||
|
'Lock',
|
||||||
|
'Unit',
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<?php
|
|
||||||
class MapsUnit extends AppModel {
|
|
||||||
|
|
||||||
var $name = 'MapsUnit';
|
|
||||||
var $validate = array(
|
|
||||||
'id' => array('numeric'),
|
|
||||||
'map_id' => array('numeric'),
|
|
||||||
'unit_id' => array('numeric'),
|
|
||||||
'pt_top' => array('numeric'),
|
|
||||||
'pt_left' => array('numeric'),
|
|
||||||
'transpose' => array('boolean')
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
37
site/models/membership.php
Normal file
37
site/models/membership.php
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
class Membership extends AppModel {
|
||||||
|
|
||||||
|
var $belongsTo =
|
||||||
|
array('User',
|
||||||
|
'Site',
|
||||||
|
'Group'
|
||||||
|
);
|
||||||
|
|
||||||
|
function memberGroups($user_id, $site_id) {
|
||||||
|
$this->prEnter(compact('user_id', 'site_id'));
|
||||||
|
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$groups = $this->find('all', array
|
||||||
|
('recursive' => -1,
|
||||||
|
'fields' => array('group_id'),
|
||||||
|
'conditions' => array(array('user_id' => $user_id),
|
||||||
|
array('site_id' => $site_id)),
|
||||||
|
));
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
|
||||||
|
if (empty($groups))
|
||||||
|
return $this->prReturn(null);
|
||||||
|
|
||||||
|
$group_ids = array();
|
||||||
|
foreach ($groups AS $group)
|
||||||
|
$group_ids[] = $group['Membership']['group_id'];
|
||||||
|
|
||||||
|
return $this->prReturn($group_ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
function memberOf($user_id, $site_id) {
|
||||||
|
$groups = $this->memberGroups($user_id, $site_id);
|
||||||
|
return (!empty($groups));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
76
site/models/option.php
Normal file
76
site/models/option.php
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
class Option extends AppModel {
|
||||||
|
|
||||||
|
var $hasMany =
|
||||||
|
array('OptionValue',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $knows =
|
||||||
|
array('User', 'Site', 'Group');
|
||||||
|
|
||||||
|
|
||||||
|
static $option_set = array();
|
||||||
|
|
||||||
|
function getAll($name, $force = false) {
|
||||||
|
/* $this->prClassLevel(30); */
|
||||||
|
/* //$this->OptionValue->prClassLevel(30); */
|
||||||
|
/* $this->Group->Membership->prClassLevel(30); */
|
||||||
|
/* $this->OptionValue->SiteOption->prClassLevel(30); */
|
||||||
|
/* $this->OptionValue->UserOption->prClassLevel(30); */
|
||||||
|
/* $this->OptionValue->GroupOption->prClassLevel(30); */
|
||||||
|
/* $this->OptionValue->DefaultOption->prClassLevel(30); */
|
||||||
|
$this->prEnter(compact('name'));
|
||||||
|
|
||||||
|
if (!empty(self::$option_set[$name]) && !$force)
|
||||||
|
return $this->prReturn(self::$option_set[$name]);
|
||||||
|
|
||||||
|
self::$option_set[$name] = array();
|
||||||
|
|
||||||
|
$site_id = $this->Site->currentSiteId();
|
||||||
|
$user_id = $this->User->currentUserId();
|
||||||
|
$group_ids = $this->Group->currentGroupIds();
|
||||||
|
|
||||||
|
/* $site_id = 2; */
|
||||||
|
/* $user_id = 4; */
|
||||||
|
/* $group_ids = $this->Group->groupIds($user_id, $site_id); */
|
||||||
|
|
||||||
|
if (!empty($site_id))
|
||||||
|
self::$option_set[$name] =
|
||||||
|
array_merge(self::$option_set[$name],
|
||||||
|
$this->OptionValue->SiteOption->values($site_id, $name));
|
||||||
|
|
||||||
|
if (!empty($user_id))
|
||||||
|
self::$option_set[$name] =
|
||||||
|
array_merge(self::$option_set[$name],
|
||||||
|
$this->OptionValue->UserOption->values($user_id, $name));
|
||||||
|
|
||||||
|
if (!empty($group_ids))
|
||||||
|
self::$option_set[$name] =
|
||||||
|
array_merge(self::$option_set[$name],
|
||||||
|
$this->OptionValue->GroupOption->values($group_ids, $name));
|
||||||
|
|
||||||
|
self::$option_set[$name] =
|
||||||
|
array_merge(self::$option_set[$name],
|
||||||
|
$this->OptionValue->DefaultOption->values($name));
|
||||||
|
|
||||||
|
return $this->prReturn(self::$option_set[$name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function get($name) {
|
||||||
|
$this->prEnter(compact('name'));
|
||||||
|
$values = $this->getAll($name);
|
||||||
|
if (empty($values))
|
||||||
|
return null;
|
||||||
|
return $this->prReturn($values[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function enabled($name) {
|
||||||
|
$val = $this->get($name);
|
||||||
|
return (!empty($val));
|
||||||
|
}
|
||||||
|
|
||||||
|
function disabled($name) {
|
||||||
|
return (!$this->enabled($name));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
35
site/models/option_value.php
Normal file
35
site/models/option_value.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
class OptionValue extends AppModel {
|
||||||
|
|
||||||
|
var $belongsTo =
|
||||||
|
array('Option',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany =
|
||||||
|
array('UserOption',
|
||||||
|
'SiteOption',
|
||||||
|
'GroupOption',
|
||||||
|
'DefaultOption',
|
||||||
|
);
|
||||||
|
|
||||||
|
function values($name = null, $query = null) {
|
||||||
|
$this->prEnter(compact('name', 'query'));
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
$query['link']['Option'] = array();
|
||||||
|
|
||||||
|
if (!empty($name)) {
|
||||||
|
$query['conditions'][] = array('Option.name' => $name);
|
||||||
|
$query['link']['Option']['fields'] = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$values = array();
|
||||||
|
foreach ($this->find('all', $query) AS $result)
|
||||||
|
$values[] = $result['OptionValue']['value'];
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
|
||||||
|
return $this->prReturn($values);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
105
site/models/permission.php
Normal file
105
site/models/permission.php
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
<?php
|
||||||
|
class Permission extends AppModel {
|
||||||
|
|
||||||
|
var $hasMany =
|
||||||
|
array('PermissionValue',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $knows =
|
||||||
|
array('User', 'Site', 'Group');
|
||||||
|
|
||||||
|
static $permission_set = array();
|
||||||
|
|
||||||
|
function getAll($name, $force = false) {
|
||||||
|
/* $this->prClassLevel(30); */
|
||||||
|
/* $this->PermissionValue->prClassLevel(30); */
|
||||||
|
/* $this->Group->Membership->prClassLevel(30); */
|
||||||
|
/* $this->PermissionValue->SitePermission->prClassLevel(30); */
|
||||||
|
/* $this->PermissionValue->UserPermission->prClassLevel(30); */
|
||||||
|
/* $this->PermissionValue->GroupPermission->prClassLevel(30); */
|
||||||
|
/* $this->PermissionValue->DefaultPermission->prClassLevel(30); */
|
||||||
|
$this->prEnter(compact('name'));
|
||||||
|
|
||||||
|
if (!empty(self::$permission_set[$name]) && !$force)
|
||||||
|
return $this->prReturn(self::$permission_set[$name]);
|
||||||
|
|
||||||
|
self::$permission_set[$name] = array();
|
||||||
|
|
||||||
|
$site_id = $this->Site->currentSiteId();
|
||||||
|
$user_id = $this->User->currentUserId();
|
||||||
|
$group_ids = $this->Group->currentGroupIds();
|
||||||
|
|
||||||
|
/* $site_id = 1; */
|
||||||
|
/* $user_id = 2; */
|
||||||
|
/* $group_ids = $this->Group->groupIds($user_id, $site_id); */
|
||||||
|
|
||||||
|
if (empty($group_ids)) {
|
||||||
|
self::$permission_set[$name][$name][] = array('access' => 'DENY', 'level' => null);
|
||||||
|
$site_id = null;
|
||||||
|
$user_id = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($site_id))
|
||||||
|
self::$permission_set[$name] =
|
||||||
|
array_merge(self::$permission_set[$name],
|
||||||
|
$this->PermissionValue->SitePermission->values($site_id, $name));
|
||||||
|
|
||||||
|
if (!empty($user_id))
|
||||||
|
self::$permission_set[$name] =
|
||||||
|
array_merge(self::$permission_set[$name],
|
||||||
|
$this->PermissionValue->UserPermission->values($user_id, $name));
|
||||||
|
|
||||||
|
if (!empty($group_ids)) {
|
||||||
|
self::$permission_set[$name] =
|
||||||
|
array_merge(self::$permission_set[$name],
|
||||||
|
$this->PermissionValue->GroupPermission->values($group_ids, $name));
|
||||||
|
|
||||||
|
self::$permission_set[$name] =
|
||||||
|
array_merge(self::$permission_set[$name],
|
||||||
|
$this->PermissionValue->DefaultPermission->values($name));
|
||||||
|
|
||||||
|
self::$permission_set[$name][] = array('access' => 'ALLOW', 'level' => null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->prReturn(self::$permission_set[$name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function get($name) {
|
||||||
|
$this->prEnter(compact('name'));
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090827
|
||||||
|
// This is a pretty crappy algorithm. How do we decide whether DENY really
|
||||||
|
// means DENY, or whether an ALLOW has priority.
|
||||||
|
// Oh well, it works for now...
|
||||||
|
|
||||||
|
$values = $this->getAll($name);
|
||||||
|
$result = array_shift($values);
|
||||||
|
|
||||||
|
foreach ($values AS $value)
|
||||||
|
if (empty($result['level']) || (!empty($value['level']) && $value['level'] < $result['level']))
|
||||||
|
$result['level'] = $value['level'];
|
||||||
|
|
||||||
|
if ($result['access'] !== 'ALLOW')
|
||||||
|
$result['level'] = 9999999;
|
||||||
|
|
||||||
|
return $this->prReturn($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
function allow($name) {
|
||||||
|
$this->prEnter(compact('name'));
|
||||||
|
$result = $this->get($name);
|
||||||
|
return $this->prReturn($result['access'] === 'ALLOW');
|
||||||
|
}
|
||||||
|
|
||||||
|
function deny($name) {
|
||||||
|
$this->prEnter(compact('name'));
|
||||||
|
return $this->prReturn(!$this->allow($name));
|
||||||
|
}
|
||||||
|
|
||||||
|
function level($name) {
|
||||||
|
$this->prEnter(compact('name'));
|
||||||
|
$result = $this->get($name);
|
||||||
|
return $this->prReturn($result['level']);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
36
site/models/permission_value.php
Normal file
36
site/models/permission_value.php
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
class PermissionValue extends AppModel {
|
||||||
|
|
||||||
|
var $belongsTo =
|
||||||
|
array('Permission',
|
||||||
|
);
|
||||||
|
|
||||||
|
var $hasMany =
|
||||||
|
array('UserPermission',
|
||||||
|
'SitePermission',
|
||||||
|
'GroupPermission',
|
||||||
|
'DefaultPermission',
|
||||||
|
);
|
||||||
|
|
||||||
|
function values($name = null, $query = null) {
|
||||||
|
$this->prEnter(compact('name', 'query'));
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
$query['link']['Permission'] = array();
|
||||||
|
|
||||||
|
if (!empty($name)) {
|
||||||
|
$query['conditions'][] = array('Permission.name' => $name);
|
||||||
|
$query['link']['Permission']['fields'] = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$values = array();
|
||||||
|
foreach ($this->find('all', $query) AS $result)
|
||||||
|
$values[] = array('access' => $result['PermissionValue']['access'],
|
||||||
|
'level' => $result['PermissionValue']['level']);
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
|
||||||
|
return $this->prReturn($values);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,16 +1,37 @@
|
|||||||
<?php
|
<?php
|
||||||
class Site extends AppModel {
|
class Site extends AppModel {
|
||||||
|
|
||||||
var $name = 'Site';
|
var $hasMany =
|
||||||
var $validate = array(
|
array('SiteArea',
|
||||||
'id' => array('numeric'),
|
'SiteOption',
|
||||||
'name' => array('notempty')
|
'Membership',
|
||||||
);
|
);
|
||||||
|
|
||||||
var $hasMany = array(
|
static $current_site_id;
|
||||||
'SiteArea',
|
|
||||||
'SiteOption',
|
|
||||||
);
|
|
||||||
|
|
||||||
|
function currentSiteId() {
|
||||||
|
if (!empty(self::$current_site_id))
|
||||||
|
return self::$current_site_id;
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090827
|
||||||
|
// Must get the actual site
|
||||||
|
$code = 'VSS';
|
||||||
|
|
||||||
|
$site = $this->find
|
||||||
|
('first',
|
||||||
|
array('recursive' => -1,
|
||||||
|
'conditions' => compact('code')));
|
||||||
|
|
||||||
|
if (!empty($site['Site']['id']))
|
||||||
|
self::$current_site_id = $site['Site']['id'];
|
||||||
|
else
|
||||||
|
// We must force a stop here, since this is typically
|
||||||
|
// called very early on, and so will cause a recursive
|
||||||
|
// crash as we try to render the internal error and
|
||||||
|
// again stumble on this problem.
|
||||||
|
$this->INTERNAL_ERROR('UNKNOWN SITE', 0, true);
|
||||||
|
|
||||||
|
return self::$current_site_id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
24
site/models/site_option.php
Normal file
24
site/models/site_option.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
class SiteOption extends AppModel {
|
||||||
|
|
||||||
|
var $belongsTo =
|
||||||
|
array('Site',
|
||||||
|
'OptionValue',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
function values($id, $name = null) {
|
||||||
|
$this->prEnter(compact('id', 'name'));
|
||||||
|
|
||||||
|
$query = array();
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
$query['link']['SiteOption'] = array();
|
||||||
|
$query['link']['SiteOption']['fields'] = array();
|
||||||
|
$query['link']['SiteOption']['Site'] = array();
|
||||||
|
$query['link']['SiteOption']['Site']['fields'] = array();
|
||||||
|
$query['conditions'][] = array('Site.id' => $id);
|
||||||
|
return $this->prReturn($this->OptionValue->values($name, $query));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
24
site/models/site_permission.php
Normal file
24
site/models/site_permission.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
class SitePermission extends AppModel {
|
||||||
|
|
||||||
|
var $belongsTo =
|
||||||
|
array('Site',
|
||||||
|
'PermissionValue',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
function values($id, $name = null) {
|
||||||
|
$this->prEnter(compact('id', 'name'));
|
||||||
|
|
||||||
|
$query = array();
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
$query['link']['SitePermission'] = array();
|
||||||
|
$query['link']['SitePermission']['fields'] = array();
|
||||||
|
$query['link']['SitePermission']['Site'] = array();
|
||||||
|
$query['link']['SitePermission']['Site']['fields'] = array();
|
||||||
|
$query['conditions'][] = array('Site.id' => $id);
|
||||||
|
return $this->prReturn($this->PermissionValue->values($name, $query));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,46 +7,81 @@ class StatementEntry extends AppModel {
|
|||||||
'Lease',
|
'Lease',
|
||||||
'Account',
|
'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(
|
'ChargeEntry' => array(
|
||||||
'className' => 'StatementEntry',
|
'className' => 'StatementEntry',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
var $hasMany = array(
|
var $hasMany = array(
|
||||||
// The payments that apply to this charge (if it is one)
|
// The disbursements that apply to this charge (if it is one)
|
||||||
'PaymentEntry' => array(
|
'DisbursementEntry' => array(
|
||||||
'className' => 'StatementEntry',
|
'className' => 'StatementEntry',
|
||||||
'foreignKey' => 'charge_entry_id',
|
'foreignKey' => 'charge_entry_id',
|
||||||
|
'dependent' => true,
|
||||||
),
|
),
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
//var $default_log_level = 30;
|
//var $default_log_level = array('log' => 30, 'show' => 15);
|
||||||
|
var $max_log_level = 19;
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* function: chargePaymentFields
|
* function: debit/creditTypes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
function debitTypes() {
|
||||||
|
return array('CHARGE', 'PAYMENT', 'REFUND');
|
||||||
|
}
|
||||||
|
|
||||||
|
function creditTypes() {
|
||||||
|
return array('DISBURSEMENT', 'WAIVER', 'REVERSAL', 'WRITEOFF', 'SURPLUS');
|
||||||
|
}
|
||||||
|
|
||||||
|
function voidTypes() {
|
||||||
|
return array('VOID');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: chargeDisbursementFields
|
||||||
|
*/
|
||||||
|
|
||||||
|
function chargeDisbursementFields($sum = false, $entry_name = 'StatementEntry') {
|
||||||
|
$debits = $this->debitTypes();
|
||||||
|
$credits = $this->creditTypes();
|
||||||
|
$voids = $this->voidTypes();
|
||||||
|
|
||||||
|
foreach ($debits AS &$enum)
|
||||||
|
$enum = "'" . $enum . "'";
|
||||||
|
foreach ($credits AS &$enum)
|
||||||
|
$enum = "'" . $enum . "'";
|
||||||
|
foreach ($voids AS &$enum)
|
||||||
|
$enum = "'" . $enum . "'";
|
||||||
|
|
||||||
|
$debit_set = implode(", ", $debits);
|
||||||
|
$credit_set = implode(", ", $credits);
|
||||||
|
$void_set = implode(", ", $voids);
|
||||||
|
|
||||||
function chargePaymentFields($sum = false, $entry_name = 'StatementEntry') {
|
|
||||||
$fields = array
|
$fields = array
|
||||||
(
|
(
|
||||||
($sum ? 'SUM(' : '') .
|
($sum ? 'SUM(' : '') .
|
||||||
"IF({$entry_name}.type = 'CHARGE'," .
|
"IF({$entry_name}.type IN ({$debit_set})," .
|
||||||
" {$entry_name}.amount, NULL)" .
|
" {$entry_name}.amount, NULL)" .
|
||||||
($sum ? ')' : '') . ' AS charge' . ($sum ? 's' : ''),
|
($sum ? ')' : '') . ' AS charge' . ($sum ? 's' : ''),
|
||||||
|
|
||||||
($sum ? 'SUM(' : '') .
|
($sum ? 'SUM(' : '') .
|
||||||
"IF({$entry_name}.type = 'PAYMENT' OR {$entry_name}.type = 'SURPLUS'," .
|
"IF({$entry_name}.type IN({$credit_set})," .
|
||||||
" {$entry_name}.amount, NULL)" .
|
" {$entry_name}.amount, NULL)" .
|
||||||
($sum ? ')' : '') . ' AS payment' . ($sum ? 's' : ''),
|
($sum ? ')' : '') . ' AS disbursement' . ($sum ? 's' : ''),
|
||||||
|
|
||||||
($sum ? 'SUM(' : '') .
|
($sum ? 'SUM(' : '') .
|
||||||
"IF({$entry_name}.type = 'CHARGE', 1," .
|
"IF({$entry_name}.type IN ({$debit_set}), 1," .
|
||||||
" IF({$entry_name}.type = 'PAYMENT' OR {$entry_name}.type = 'SURPLUS', -1, 0))" .
|
" IF({$entry_name}.type IN ({$credit_set}), -1, 0))" .
|
||||||
" * IF({$entry_name}.amount, {$entry_name}.amount, 0)" .
|
" * IF({$entry_name}.amount, {$entry_name}.amount, 0)" .
|
||||||
($sum ? ')' : '') . ' AS balance',
|
($sum ? ')' : '') . ' AS balance',
|
||||||
);
|
);
|
||||||
@@ -90,16 +125,13 @@ class StatementEntry extends AppModel {
|
|||||||
function addStatementEntry($entry) {
|
function addStatementEntry($entry) {
|
||||||
$this->prEnter(compact('entry'));
|
$this->prEnter(compact('entry'));
|
||||||
|
|
||||||
$ret = array();
|
$ret = array('data' => $entry);
|
||||||
if (!$this->verifyStatementEntry($entry))
|
if (!$this->verifyStatementEntry($entry))
|
||||||
return array('error' => true, 'verify_data' => $entry) + $ret;
|
return $this->prReturn(array('error' => true, 'verify_data' => $entry) + $ret);
|
||||||
|
|
||||||
$this->pr(20, array('checkpoint' => 'Pre-Save')
|
|
||||||
+ compact('entry'));
|
|
||||||
|
|
||||||
$this->create();
|
$this->create();
|
||||||
if (!$this->save($entry))
|
if (!$this->save($entry))
|
||||||
return array('error' => true, 'save_data' => $entry) + $ret;
|
return $this->prReturn(array('error' => true, 'save_data' => $entry) + $ret);
|
||||||
|
|
||||||
$ret['statement_entry_id'] = $this->id;
|
$ret['statement_entry_id'] = $this->id;
|
||||||
return $this->prReturn($ret + array('error' => false));
|
return $this->prReturn($ret + array('error' => false));
|
||||||
@@ -109,115 +141,101 @@ class StatementEntry extends AppModel {
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* function: reverse
|
* function: waive
|
||||||
* - Reverses the charges
|
* - Waives the charge balance
|
||||||
*
|
|
||||||
* SAMPLE MOVE IN w/ PRE PAYMENT
|
|
||||||
* 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) {
|
function waive($id, $stamp = null) {
|
||||||
$this->prEnter(compact('ledger_entries', 'stamp'));
|
$this->prEnter(compact('id', 'stamp'));
|
||||||
|
|
||||||
// If the user only wants to reverse one ID, we'll allow it
|
// Get the basic information about the entry to be waived.
|
||||||
if (!is_array($ledger_entries))
|
$this->recursive = -1;
|
||||||
$ledger_entries = $this->find
|
$charge = $this->read(null, $id);
|
||||||
('all', array
|
$charge = $charge['StatementEntry'];
|
||||||
('contain' => false,
|
|
||||||
'conditions' => array('Entry.id' => $ledger_entries)));
|
|
||||||
|
|
||||||
$A = new Account();
|
if ($charge['type'] !== 'CHARGE')
|
||||||
|
$this->INTERNAL_ERROR("Waiver item is not CHARGE.");
|
||||||
|
|
||||||
$ar_account_id = $A->accountReceivableAccountID();
|
// Query the stats to get the remaining balance
|
||||||
$receipt_account_id = $A->receiptAccountID();
|
$stats = $this->stats($id);
|
||||||
|
|
||||||
$transaction_id = null;
|
// Build a transaction
|
||||||
foreach ($ledger_entries AS $entry) {
|
$waiver = array('Transaction' => array(), 'Entry' => array());
|
||||||
$entry = $entry['Entry'];
|
$waiver['Transaction']['stamp'] = $stamp;
|
||||||
$amount = -1*$entry['amount'];
|
$waiver['Transaction']['comment'] = "Charge Waiver";
|
||||||
|
|
||||||
if (isset($entry['credit_account_id']))
|
// Add the charge waiver
|
||||||
$refund_account_id = $entry['credit_account_id'];
|
$waiver['Entry'][] =
|
||||||
elseif (isset($entry['CreditLedger']['Account']['id']))
|
array('amount' => $stats['Charge']['balance'],
|
||||||
$refund_account_id = $entry['CreditLedger']['Account']['id'];
|
'comment' => null,
|
||||||
elseif (isset($entry['credit_ledger_id']))
|
);
|
||||||
$refund_account_id = $this->Ledger->accountID($entry['credit_ledger_id']);
|
|
||||||
else
|
|
||||||
return $this->prReturn(null);
|
|
||||||
|
|
||||||
// post new refund in the income account
|
// Record the waiver transaction
|
||||||
$ids = $A->postEntry
|
return $this->prReturn($this->Transaction->addWaiver
|
||||||
(array('transaction_id' => $transaction_id),
|
($waiver, $id, $charge['customer_id'], $charge['lease_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');
|
**************************************************************************
|
||||||
}
|
**************************************************************************
|
||||||
|
* function: reversable
|
||||||
|
* - Returns true if the charge can be reversed; false otherwise
|
||||||
|
*/
|
||||||
|
function reversable($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
|
||||||
|
if (empty($id))
|
||||||
|
return $this->prReturn(false);
|
||||||
|
|
||||||
|
// Verify the item is an actual charge
|
||||||
|
$this->id = $id;
|
||||||
|
$charge_type = $this->field('type');
|
||||||
|
if ($charge_type !== 'CHARGE')
|
||||||
|
return $this->prReturn(false);
|
||||||
|
|
||||||
|
// Determine anything reconciled against the charge
|
||||||
|
$reverse_transaction_id = $this->field('reverse_transaction_id');
|
||||||
|
if (!empty($reverse_transaction_id))
|
||||||
|
return $this->prReturn(false);
|
||||||
|
|
||||||
return $this->prReturn(true);
|
return $this->prReturn(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: reverse
|
||||||
|
* - Reverses the charges
|
||||||
|
*/
|
||||||
|
function reverse($id, $stamp = null, $comment) {
|
||||||
|
$this->prEnter(compact('id', 'stamp'));
|
||||||
|
|
||||||
|
// Verify the item can be reversed
|
||||||
|
if (!$this->reversable($id))
|
||||||
|
$this->INTERNAL_ERROR("Item is not reversable.");
|
||||||
|
|
||||||
|
// Get the basic information about this charge
|
||||||
|
$charge = $this->find('first', array('contain' => true));
|
||||||
|
//$charge = $charge['StatementEntry'];
|
||||||
|
|
||||||
|
// Query the stats to get the remaining balance
|
||||||
|
$stats = $this->stats($id);
|
||||||
|
$charge['paid'] = $stats['Charge']['disbursement'];
|
||||||
|
|
||||||
|
// Record the reversal transaction
|
||||||
|
$result = $this->Transaction->addReversal
|
||||||
|
($charge, $stamp, $comment ? $comment : 'Charge Reversal');
|
||||||
|
|
||||||
|
if (empty($result['error'])) {
|
||||||
|
// Mark the charge as reversed
|
||||||
|
$this->id = $id;
|
||||||
|
$this->saveField('reverse_transaction_id', $result['transaction_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->prReturn($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -229,28 +247,21 @@ OPTION 2
|
|||||||
function reconciledSetQuery($set, $query) {
|
function reconciledSetQuery($set, $query) {
|
||||||
$this->queryInit($query);
|
$this->queryInit($query);
|
||||||
|
|
||||||
if ($set == 'CHARGE' || $set == 'PAYMENT')
|
if (in_array($set, $this->debitTypes()))
|
||||||
$query['conditions'][] = array('StatementEntry.type' => $set);
|
$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
|
else
|
||||||
die("INVALID RECONCILE SET");
|
die("INVALID RECONCILE SET");
|
||||||
|
|
||||||
if ($set == 'CHARGE')
|
$query['conditions'][] = array('StatementEntry.type' => $set);
|
||||||
$query['link']['PaymentEntry'] = array('fields' => array("SUM(PaymentEntry.amount) AS reconciled"));
|
|
||||||
if ($set == 'PAYMENT')
|
|
||||||
$query['link']['ChargeEntry'] = array('fields' => array("SUM(ChargeEntry.amount) AS reconciled"));
|
|
||||||
|
|
||||||
$query['group'] = 'StatementEntry.id';
|
$query['group'] = 'StatementEntry.id';
|
||||||
|
|
||||||
// REVISIT: TESTING
|
|
||||||
//$query['link']['PaymentEntry'] = array('fields' => array("(`PaymentEntry.amount`+0) AS reconciled"));
|
|
||||||
//$query['group'] = null;
|
|
||||||
// END REVISIT
|
|
||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
function reconciledSet($set, $query = null, $unrec = false, $if_rec_include_partial = false) {
|
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'));
|
$this->prEnter(compact('set', 'query', 'unrec', 'if_rec_include_partial'));
|
||||||
$lquery = $this->reconciledSetQuery($set, $query);
|
$lquery = $this->reconciledSetQuery($set, $query);
|
||||||
$result = $this->find('all', $lquery);
|
$result = $this->find('all', $lquery);
|
||||||
@@ -274,7 +285,7 @@ OPTION 2
|
|||||||
$reconciled = true;
|
$reconciled = true;
|
||||||
elseif ($entry['StatementEntry']['reconciled'] == 0)
|
elseif ($entry['StatementEntry']['reconciled'] == 0)
|
||||||
$reconciled = false;
|
$reconciled = false;
|
||||||
else // Partial payment; depends on unrec
|
else // Partial disbursement; depends on unrec
|
||||||
$reconciled = (!$unrec && $if_rec_include_partial);
|
$reconciled = (!$unrec && $if_rec_include_partial);
|
||||||
|
|
||||||
// Add to the set, if it's been requested
|
// Add to the set, if it's been requested
|
||||||
@@ -283,7 +294,7 @@ OPTION 2
|
|||||||
}
|
}
|
||||||
|
|
||||||
return $this->prReturn(array('entries' => $resultset,
|
return $this->prReturn(array('entries' => $resultset,
|
||||||
'summary' => $this->stats(null, $query)));
|
'summary' => $this->stats(null, $query)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -292,7 +303,7 @@ OPTION 2
|
|||||||
**************************************************************************
|
**************************************************************************
|
||||||
* function: reconciledEntries
|
* function: reconciledEntries
|
||||||
* - Returns a list of entries that reconcile against the given entry.
|
* - 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) {
|
function reconciledEntriesQuery($id, $query = null) {
|
||||||
$this->queryInit($query, false);
|
$this->queryInit($query, false);
|
||||||
@@ -303,10 +314,14 @@ OPTION 2
|
|||||||
|
|
||||||
$query['conditions'][] = array('StatementEntry.id' => $id);
|
$query['conditions'][] = array('StatementEntry.id' => $id);
|
||||||
|
|
||||||
if ($this->data['StatementEntry']['type'] == 'CHARGE')
|
if (in_array($this->data['StatementEntry']['type'], $this->debitTypes())) {
|
||||||
$query['link']['PaymentEntry'] = array();
|
$query['link']['DisbursementEntry'] = array();
|
||||||
if ($this->data['StatementEntry']['type'] == 'PAYMENT')
|
$query['conditions'][] = array('DisbursementEntry.id !=' => null);
|
||||||
|
}
|
||||||
|
if (in_array($this->data['StatementEntry']['type'], $this->creditTypes())) {
|
||||||
$query['link']['ChargeEntry'] = array();
|
$query['link']['ChargeEntry'] = array();
|
||||||
|
$query['conditions'][] = array('ChargeEntry.id !=' => null);
|
||||||
|
}
|
||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
@@ -323,6 +338,72 @@ OPTION 2
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: outstandingDebits
|
||||||
|
* - Determines all debit types that have not yet been resolved.
|
||||||
|
* The name is a bit dumb, but it means any statement entry type
|
||||||
|
* that a positive customer balance could be used to offset. In
|
||||||
|
* other words, entries that are still in need of matching
|
||||||
|
* disbursements. Most notably, this means charges but could
|
||||||
|
* also mean things like refunds as well.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function outstandingDebits($query = null, $customer_id = null,
|
||||||
|
$lease_id = null, $debit_types = null)
|
||||||
|
{
|
||||||
|
$this->prEnter(compact('query', 'lease_id',
|
||||||
|
'customer_id', 'charge_ids',
|
||||||
|
'debit_types'));
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
if (empty($debit_types))
|
||||||
|
$debit_types = $this->debitTypes();
|
||||||
|
|
||||||
|
if (!empty($customer_id))
|
||||||
|
$query['conditions'][] = array('StatementEntry.customer_id' => $customer_id);
|
||||||
|
|
||||||
|
if (!empty($lease_id))
|
||||||
|
$query['conditions'][] = array('StatementEntry.lease_id' => $lease_id);
|
||||||
|
|
||||||
|
/* if (isset($charge_ids)) { */
|
||||||
|
/* // REVISIT <AP> 20100330: */
|
||||||
|
/* // Not using $query here, as this code was extracted from its */
|
||||||
|
/* // original location in assignCredits, and so I'm keeping the */
|
||||||
|
/* // logic consistent. It does seem, however, that we shouldn't */
|
||||||
|
/* // be ignoring $query if passed in. I'm sure this won't be */
|
||||||
|
/* // looked at until someone _does_ pass $query in (and it break), */
|
||||||
|
/* // so hopefully at that time, we can understand what needs to */
|
||||||
|
/* // happen in that case (requirements are not clear at present). */
|
||||||
|
/* $lquery = array('contain' => false, */
|
||||||
|
/* 'conditions' => array('StatementEntry.id' => $charge_ids)); */
|
||||||
|
/* } else { */
|
||||||
|
/* $lquery = $query; */
|
||||||
|
/* // If we're working with a specific lease, then limit charges to it */
|
||||||
|
/* if (!empty($lease_id)) */
|
||||||
|
/* $lquery['conditions'][] = array('StatementEntry.lease_id' => $lease_id); */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
if (empty($query['order']))
|
||||||
|
$query['order'] = 'StatementEntry.effective_date ASC';
|
||||||
|
|
||||||
|
$debits = array();
|
||||||
|
foreach ($debit_types AS $dtype) {
|
||||||
|
$rset = $this->reconciledSet($dtype, $query, true);
|
||||||
|
$entries = $rset['entries'];
|
||||||
|
$debits = array_merge($debits, $entries);
|
||||||
|
$this->pr(18, compact('dtype', 'entries'), "Outstanding Debit Entries");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->prReturn($debits);
|
||||||
|
}
|
||||||
|
|
||||||
|
function outstandingCharges($query = null, $customer_id = null, $lease_id = null) {
|
||||||
|
return $this->outstandingDebits($query, $customer_id, $lease_id, array('CHARGE'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -331,198 +412,288 @@ OPTION 2
|
|||||||
*
|
*
|
||||||
* REVISIT <AP>: 20090726
|
* REVISIT <AP>: 20090726
|
||||||
* This algorithm shouldn't be hardcoded. We need to allow
|
* 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) {
|
function assignCredits($query = null, $receipt_id = null,
|
||||||
|
$charge_ids = null, $disbursement_type = null,
|
||||||
|
$customer_id = null, $lease_id = null)
|
||||||
|
{
|
||||||
//$this->prFunctionLevel(25);
|
//$this->prFunctionLevel(25);
|
||||||
$this->prEnter( compact('query', 'receipt_id'));
|
$this->prEnter(compact('query', 'receipt_id',
|
||||||
|
'charge_ids', 'disbursement_type',
|
||||||
|
'customer_id', 'lease_id'));
|
||||||
$this->queryInit($query);
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
if (empty($disbursement_type))
|
||||||
|
$disbursement_type = 'DISBURSEMENT';
|
||||||
|
|
||||||
$ret = array();
|
$ret = array();
|
||||||
|
|
||||||
// First, find all known credits
|
// First, find all known credits, unless this call is to make
|
||||||
$lquery = $query;
|
// credit adjustments to a specific charge
|
||||||
$lquery['conditions'][] = array('StatementEntry.type' => 'SURPLUS');
|
if (empty($receipt_id)) {
|
||||||
$lquery['order'][] = 'StatementEntry.effective_date ASC';
|
|
||||||
$credits = $this->find('all', $lquery);
|
if (!empty($charge_ids))
|
||||||
$this->pr(18, compact('credits'),
|
$this->INTERNAL_ERROR("Charge IDs, yet no corresponding receipt");
|
||||||
"Credits Established");
|
|
||||||
|
|
||||||
// Next, establish credit from the newly added receipt
|
|
||||||
$receipt_credit = null;
|
|
||||||
if (!empty($receipt_id)) {
|
|
||||||
$lquery = $query;
|
$lquery = $query;
|
||||||
$lquery['link'] += array('LedgerEntry' =>
|
if (!empty($customer_id))
|
||||||
array('conditions' =>
|
$lquery['conditions'][] = array('StatementEntry.customer_id' => $customer_id);
|
||||||
//array(LedgerEntry.'crdr'=>'DEBIT'),
|
|
||||||
array('LedgerEntry.account_id !=' => $this->Account->accountReceivableAccountID()),
|
$lquery['conditions'][] = array('StatementEntry.type' => 'SURPLUS');
|
||||||
));
|
// REVISIT <AP>: 20090804
|
||||||
$lquery['fields'] = array('Transaction.id', 'Transaction.stamp', 'Transaction.amount',
|
// We need to ensure that we're using surplus credits ONLY from either
|
||||||
'LedgerEntry.account_id');
|
// the given lease, or those that do not apply to any specific lease.
|
||||||
// Very specific case here... no extra conditions
|
// However, by doing this, it forces any lease surplus amounts to
|
||||||
unset($lquery['conditions']);
|
// remain frozen with that lease until either there is a lease charge,
|
||||||
$this->Transaction->id = $receipt_id;
|
// we refund the money, or we "promote" that surplus to the customer
|
||||||
|
// level and out of the leases direct control.
|
||||||
|
// That seems like a pain. Perhaps we should allow any customer
|
||||||
|
// surplus to be used on any customer charge.
|
||||||
|
$lquery['conditions'][] =
|
||||||
|
array('OR' =>
|
||||||
|
array(array('StatementEntry.lease_id' => null),
|
||||||
|
(!empty($lease_id)
|
||||||
|
? array('StatementEntry.lease_id' => $lease_id)
|
||||||
|
: array()),
|
||||||
|
));
|
||||||
|
$lquery['order'][] = 'StatementEntry.effective_date ASC';
|
||||||
|
$credits = $this->find('all', $lquery);
|
||||||
|
$this->pr(18, compact('credits'),
|
||||||
|
"Credits Established");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Establish credit from the (newly added) receipt
|
||||||
|
$lquery =
|
||||||
|
array('link' =>
|
||||||
|
array('StatementEntry',
|
||||||
|
'LedgerEntry' =>
|
||||||
|
array('conditions' =>
|
||||||
|
array('LedgerEntry.account_id <> Transaction.account_id')
|
||||||
|
),
|
||||||
|
),
|
||||||
|
'conditions' => array('Transaction.id' => $receipt_id),
|
||||||
|
'fields' => array('Transaction.id', 'Transaction.stamp', 'Transaction.amount'),
|
||||||
|
);
|
||||||
$receipt_credit = $this->Transaction->find('first', $lquery);
|
$receipt_credit = $this->Transaction->find('first', $lquery);
|
||||||
if (!$receipt_credit)
|
if (!$receipt_credit)
|
||||||
die("INTERNAL ERROR: UNABLE TO LOCATE RECEIPT");
|
$this->INTERNAL_ERROR("Unable to locate receipt.");
|
||||||
|
|
||||||
$receipt_credit['balance'] = $receipt_credit['Transaction']['amount'];
|
$stats = $this->Transaction->stats($receipt_id);
|
||||||
|
$receipt_credit['balance'] = $stats['undisbursed'];
|
||||||
|
|
||||||
$this->pr(18, compact('receipt_credit'),
|
$receipt_credit['receipt'] = true;
|
||||||
|
$credits = array($receipt_credit);
|
||||||
|
$this->pr(18, compact('credits'),
|
||||||
"Receipt Credit Added");
|
"Receipt Credit Added");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now find all unpaid charges
|
// Now find all unpaid charges, using either the specific set
|
||||||
$lquery = $query;
|
// of charges given, or all outstanding charges based on the
|
||||||
$lquery['order'] = 'StatementEntry.effective_date ASC';
|
// query, customer and/or lease
|
||||||
$charges = $this->reconciledSet('CHARGE', $lquery, true);
|
if (!empty($charge_ids)) {
|
||||||
$this->pr(18, compact('charges'),
|
$this->INTERNAL_ERROR("PERHAPS IMPLEMENTED - THOUGH NEVER TESTED");
|
||||||
"Outstanding Charges Determined");
|
$lquery = $query;
|
||||||
|
$lquery['conditions'][] = array('StatementEntry.id' => $charge_ids);
|
||||||
// Initialize our list of used credits
|
$charges = $this->reconciledSet('CHARGE', $query, true);
|
||||||
$used_credits = array();
|
} else {
|
||||||
|
$charges = $this->outstandingDebits($query, $customer_id, $lease_id);
|
||||||
// Work through all unpaid charges, applying payments as we go
|
}
|
||||||
foreach ($charges['entries'] AS $charge) {
|
|
||||||
|
|
||||||
|
// Work through all unpaid charges, applying disbursements as we go
|
||||||
|
foreach ($charges AS $charge) {
|
||||||
$this->pr(20, compact('charge'),
|
$this->pr(20, compact('charge'),
|
||||||
'Process Charge');
|
'Process Charge');
|
||||||
|
|
||||||
// Check that we have available credits.
|
|
||||||
// Technically, this isn't necessary, since the loop
|
|
||||||
// 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'])) {
|
|
||||||
$this->pr(15, 'No more available credits');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$charge['balance'] = $charge['StatementEntry']['balance'];
|
$charge['balance'] = $charge['StatementEntry']['balance'];
|
||||||
while ($charge['balance'] > 0 &&
|
|
||||||
(count($credits) || !empty($receipt_credit['balance']))) {
|
// Use explicit credits before using the new receipt credit
|
||||||
|
foreach ($credits AS &$credit) {
|
||||||
|
if (empty($charge['balance']))
|
||||||
|
break;
|
||||||
|
if ($charge['balance'] < 0)
|
||||||
|
$this->INTERNAL_ERROR("Negative Charge Balance");
|
||||||
|
|
||||||
|
if (!isset($credit['balance']))
|
||||||
|
$credit['balance'] = $credit['StatementEntry']['amount'];
|
||||||
|
|
||||||
|
if (empty($credit['balance']))
|
||||||
|
continue;
|
||||||
|
if ($credit['balance'] < 0)
|
||||||
|
$this->INTERNAL_ERROR("Negative Credit Balance");
|
||||||
|
|
||||||
$this->pr(20, compact('charge'),
|
$this->pr(20, compact('charge'),
|
||||||
'Attempt Charge Reconciliation');
|
'Attempt Charge Reconciliation');
|
||||||
|
|
||||||
// Use explicit credits before using implicit credits
|
if (empty($credit['receipt']))
|
||||||
// (Not sure it matters though).
|
$disbursement_account_id = $credit['StatementEntry']['account_id'];
|
||||||
if (count($credits)) {
|
else
|
||||||
// Peel off the first credit available
|
$disbursement_account_id = $credit['LedgerEntry']['account_id'];
|
||||||
$credit =& $credits[0];
|
|
||||||
$payment_date = $credit['StatementEntry']['effective_date'];
|
|
||||||
$payment_transaction_id = $credit['StatementEntry']['transaction_id'];
|
|
||||||
$payment_account_id = $credit['StatementEntry']['account_id'];
|
|
||||||
|
|
||||||
if (!isset($credit['balance']))
|
// REVISIT <AP>: 20090811
|
||||||
$credit['balance'] = $credit['StatementEntry']['amount'];
|
// Need to come up with a better strategy for handling
|
||||||
}
|
// concessions. For now, just restricting concessions
|
||||||
elseif (!empty($receipt_credit['balance'])) {
|
// to apply only towards rent will resolve the most
|
||||||
// Use our only receipt credit
|
// predominant (or only) needed usage case.
|
||||||
$credit =& $receipt_credit;
|
if ($disbursement_account_id == $this->Account->concessionAccountID() &&
|
||||||
$payment_date = $credit['Transaction']['stamp'];
|
$charge['StatementEntry']['account_id'] != $this->Account->rentAccountID())
|
||||||
$payment_transaction_id = $credit['Transaction']['id'];
|
continue;
|
||||||
$payment_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
|
// possible without exceeding the charge or credit balance
|
||||||
$payment_amount = min($charge['balance'], $credit['balance']);
|
$disbursement_amount = round(min($charge['balance'], $credit['balance']), 2);
|
||||||
if (!isset($credit['applied']))
|
if (!isset($credit['applied']))
|
||||||
$credit['applied'] = 0;
|
$credit['applied'] = 0;
|
||||||
|
|
||||||
$credit['applied'] += $payment_amount;
|
$credit['applied'] = round($credit['applied'] + $disbursement_amount, 2);
|
||||||
$credit['balance'] -= $payment_amount;
|
$credit['balance'] = round($credit['balance'] - $disbursement_amount, 2);
|
||||||
|
|
||||||
$this->pr(20, compact('credit'),
|
$this->pr(20, compact('credit', 'disbursement_amount'),
|
||||||
($credit['balance'] > 0 ? 'Utilized' : 'Exhausted') .
|
($credit['balance'] > 0 ? 'Utilized' : 'Exhausted') .
|
||||||
(count($credits) ? ' Credit' : ' Receipt'));
|
(empty($credit['receipt']) ? ' Credit' : ' Receipt'));
|
||||||
|
|
||||||
if ($credit['balance'] < 0)
|
if (strtotime($charge['StatementEntry']['effective_date']) >
|
||||||
die("HOW DID WE END UP WITH NEGATIVE SURPLUS BALANCE?");
|
strtotime($credit['StatementEntry']['effective_date']))
|
||||||
|
$disbursement_edate = $charge['StatementEntry']['effective_date'];
|
||||||
|
else
|
||||||
|
$disbursement_edate = $credit['StatementEntry']['effective_date'];
|
||||||
|
|
||||||
// If we've exhausted the credit, get it out of the
|
if (empty($credit['receipt'])) {
|
||||||
// available credit pool (but keep track of it for later).
|
// Explicit Credit
|
||||||
if ($credit['balance'] <= 0 && count($credits))
|
$result = $this->Transaction->addTransactionEntries
|
||||||
$used_credits[] = array_shift($credits);
|
(array('include_ledger_entry' => true,
|
||||||
|
'include_statement_entry' => true),
|
||||||
|
array('type' => 'INVOICE',
|
||||||
|
'id' => $credit['StatementEntry']['transaction_id'],
|
||||||
|
'account_id' => $this->Account->accountReceivableAccountID(),
|
||||||
|
'crdr' => 'CREDIT',
|
||||||
|
'customer_id' => $charge['StatementEntry']['customer_id'],
|
||||||
|
'lease_id' => $charge['StatementEntry']['lease_id'],
|
||||||
|
),
|
||||||
|
array
|
||||||
|
(array('type' => $disbursement_type,
|
||||||
|
'effective_date' => $disbursement_edate,
|
||||||
|
'account_id' => $credit['StatementEntry']['account_id'],
|
||||||
|
'amount' => $disbursement_amount,
|
||||||
|
'charge_entry_id' => $charge['StatementEntry']['id'],
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
// Add a payment that uses the available credit to pay the charge
|
$ret['Disbursement'][] = $result;
|
||||||
$payment = array('type' => 'PAYMENT',
|
if ($result['error'])
|
||||||
'account_id' => $payment_account_id,
|
$ret['error'] = true;
|
||||||
'amount' => $payment_amount,
|
}
|
||||||
'effective_date' => $payment_date,
|
else {
|
||||||
'transaction_id' => $payment_transaction_id,
|
// Receipt Credit
|
||||||
'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'),
|
if (strtotime($charge['StatementEntry']['effective_date']) >
|
||||||
'New Payment Entry');
|
strtotime($credit['Transaction']['stamp']))
|
||||||
|
$disbursement_edate = $charge['StatementEntry']['effective_date'];
|
||||||
|
else
|
||||||
|
$disbursement_edate = $credit['Transaction']['stamp'];
|
||||||
|
|
||||||
$result = $this->addStatementEntry($payment);
|
// Add a disbursement that uses the available credit to pay the charge
|
||||||
$ret['Payment'][] = $result;
|
$disbursement =
|
||||||
if ($result['error'])
|
array('type' => $disbursement_type,
|
||||||
$ret['error'] = true;
|
'effective_date' => $disbursement_edate,
|
||||||
|
'amount' => $disbursement_amount,
|
||||||
|
'account_id' => $credit['LedgerEntry']['account_id'],
|
||||||
|
'transaction_id' => $credit['Transaction']['id'],
|
||||||
|
'customer_id' => $charge['StatementEntry']['customer_id'],
|
||||||
|
'lease_id' => $charge['StatementEntry']['lease_id'],
|
||||||
|
'charge_entry_id' => $charge['StatementEntry']['id'],
|
||||||
|
'comment' => null,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->pr(20, compact('disbursement'), 'New Disbursement Entry');
|
||||||
|
$result = $this->addStatementEntry($disbursement);
|
||||||
|
$ret['Disbursement'][] = $result;
|
||||||
|
if ($result['error'])
|
||||||
|
$ret['error'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust the charge balance to reflect the new disbursement
|
||||||
|
$charge['balance'] = round($charge['balance'] - $disbursement_amount, 2);
|
||||||
|
$this->pr(20, compact('charge', 'disbursement_amount'),
|
||||||
|
($charge['balance'] > 0 ? 'Unfinished' : 'Fully Paid') . ' Charge');
|
||||||
|
|
||||||
// Adjust the charge balance to reflect the new payment
|
|
||||||
$charge['balance'] -= $payment_amount;
|
|
||||||
if ($charge['balance'] < 0)
|
if ($charge['balance'] < 0)
|
||||||
die("HOW DID WE GET A NEGATIVE CHARGE AMOUNT?");
|
die("HOW DID WE GET A NEGATIVE CHARGE AMOUNT?");
|
||||||
|
|
||||||
if ($charge['balance'] <= 0)
|
|
||||||
$this->pr(20, 'Fully Paid Charge');
|
|
||||||
}
|
}
|
||||||
|
// Break the $credit reference to avoid future problems
|
||||||
|
unset($credit);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Partially used credits must be added to the used list
|
$this->pr(18, compact('credits'),
|
||||||
if (isset($credits[0]['applied']))
|
'Disbursements complete');
|
||||||
$used_credits[] = array_shift($credits);
|
|
||||||
|
|
||||||
$this->pr(18, compact('credits', 'used_credits', 'receipt_credit'),
|
|
||||||
'Payments added');
|
|
||||||
|
|
||||||
// Clean up any explicit credits that have been used
|
// Clean up any explicit credits that have been used
|
||||||
foreach ($used_credits AS $credit) {
|
foreach ($credits AS $credit) {
|
||||||
|
if (!empty($credit['receipt']))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (empty($credit['applied']))
|
||||||
|
continue;
|
||||||
|
|
||||||
if ($credit['balance'] > 0) {
|
if ($credit['balance'] > 0) {
|
||||||
$this->pr(20, compact('credit'),
|
$this->pr(20, compact('credit'),
|
||||||
'Update Credit Entry');
|
'Update Credit Entry');
|
||||||
|
|
||||||
$this->id = $credit['StatementEntry']['id'];
|
$this->id = $credit['StatementEntry']['id'];
|
||||||
$this->saveField('amount', $credit['balance']);
|
$this->saveField('amount', $credit['balance']);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$this->pr(20, compact('credit'),
|
$this->pr(20, compact('credit'),
|
||||||
'Delete Exhausted Credit Entry');
|
'Delete Exhausted Credit Entry');
|
||||||
|
|
||||||
$this->del($credit['StatementEntry']['id'], false);
|
$this->delete($credit['StatementEntry']['id'], false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert non-exhausted receipt credit to an explicit one
|
// Check for any implicit receipt credits, converting
|
||||||
if (!empty($receipt_credit['balance'])) {
|
// into explicit credits if there is a remaining balance.
|
||||||
$credit =& $receipt_credit;
|
foreach ($credits AS $credit) {
|
||||||
|
if (empty($credit['receipt']))
|
||||||
|
continue;
|
||||||
|
|
||||||
$this->pr(18, compact('credit'),
|
if (empty($credit['balance']))
|
||||||
'Create Explicit Credit');
|
continue;
|
||||||
|
|
||||||
$result = $this->addStatementEntry
|
// See if there is an existing explicit credit
|
||||||
(array('type' => 'SURPLUS',
|
// for this transaction.
|
||||||
'account_id' => $credit['LedgerEntry']['account_id'],
|
$explicit_credit = $this->find
|
||||||
'amount' => $credit['balance'],
|
('first', array('contain' => false,
|
||||||
'effective_date' => $credit['Transaction']['stamp'],
|
'conditions' =>
|
||||||
'transaction_id' => $credit['Transaction']['id'],
|
array(array('transaction_id' => $credit['Transaction']['id']),
|
||||||
'customer_id' => $credit['Customer']['id'],
|
array('type' => 'SURPLUS')),
|
||||||
));
|
));
|
||||||
$ret['Credit'] = $result;
|
|
||||||
if ($result['error'])
|
if (!empty($explicit_credit)) {
|
||||||
$ret['error'] = true;
|
// REVISIT <AP>: 20090815
|
||||||
|
// Testing whether or not this case occurs
|
||||||
|
$this->INTERNAL_ERROR('Existing explicit credit unexpected');
|
||||||
|
|
||||||
|
// Since there IS an existing explicit credit, we must update
|
||||||
|
// its balance instead of creating a new one, since it has
|
||||||
|
// already been incorporated in the overall credit balance.
|
||||||
|
// If we were to create a new one, we would erroneously create
|
||||||
|
// an excess of credit available.
|
||||||
|
$this->pr(18, compact('explicit_credit', 'credit'),
|
||||||
|
'Update existing explicit credit');
|
||||||
|
$EC = new StatementEntry();
|
||||||
|
$EC->id = $explicit_credit['StatementEntry']['id'];
|
||||||
|
$EC->saveField('amount', $credit['balance']);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($ret['receipt_balance']))
|
||||||
|
$this->INTERNAL_ERROR('Only one receipt expected in assignCredits');
|
||||||
|
|
||||||
|
// Give caller the information necessary to create an explicit
|
||||||
|
// credit from the passed receipt, which we've not exhausted.
|
||||||
|
$this->pr(18, compact('credit'), 'Convert to explicit credit');
|
||||||
|
$ret['receipt_balance'] = $credit['balance'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->prReturn($ret + array('error' => false));
|
return $this->prReturn($ret + array('error' => false));
|
||||||
@@ -536,6 +707,7 @@ OPTION 2
|
|||||||
* - Returns summary data from the requested statement entry
|
* - Returns summary data from the requested statement entry
|
||||||
*/
|
*/
|
||||||
function stats($id = null, $query = null) {
|
function stats($id = null, $query = null) {
|
||||||
|
//$this->prFunctionLevel(array('log' => 16, 'show' => 10));
|
||||||
$this->prEnter(compact('id', 'query'));
|
$this->prEnter(compact('id', 'query'));
|
||||||
|
|
||||||
$this->queryInit($query);
|
$this->queryInit($query);
|
||||||
@@ -545,48 +717,68 @@ OPTION 2
|
|||||||
if (isset($id))
|
if (isset($id))
|
||||||
$query['conditions'][] = array('StatementEntry.id' => $id);
|
$query['conditions'][] = array('StatementEntry.id' => $id);
|
||||||
|
|
||||||
$rquery = $query;
|
$types = array('Charge', 'Disbursement');
|
||||||
unset($rquery['link']['ChargeEntry']);
|
foreach ($types AS $type_index => $this_name) {
|
||||||
$rquery['link']['PaymentEntry'] = array('fields' => array());
|
$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();
|
||||||
|
}
|
||||||
|
|
||||||
$rquery['fields'] = array();
|
$this_query = $query;
|
||||||
$rquery['fields'][] = "StatementEntry.amount";
|
$this_query['fields'] = array();
|
||||||
$rquery['fields'][] = "SUM(PaymentEntry.amount) AS reconciled";
|
$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];
|
||||||
|
|
||||||
$rquery['conditions'][] = array('StatementEntry.type' => 'CHARGE');
|
$this->pr(17, compact('this_query', 'result'), $this_name.'s');
|
||||||
$rquery['group'] = 'StatementEntry.id';
|
|
||||||
|
|
||||||
$result = $this->find('all', $rquery);
|
// Tally the different types that result in credits towards the charges
|
||||||
$stats['Charge'] = array('total' => 0, 'reconciled' => 0);
|
$stats[$this_name]['reconciled'] = 0;
|
||||||
foreach($result AS $charge) {
|
foreach ($that_types AS $that_type) {
|
||||||
$stats['Charge']['total'] += $charge['StatementEntry']['amount'];
|
$lc_that_type = strtolower($that_type);
|
||||||
$stats['Charge']['reconciled'] += $charge[0]['reconciled'];
|
$that_query = $this_query;
|
||||||
|
$that_query['link']["{$that_name}Entry"] = array('fields' => array());
|
||||||
|
$that_query['fields'] = array();
|
||||||
|
if ($this_name == 'Charge')
|
||||||
|
$that_query['fields'][] = "COALESCE(SUM(${that_name}Entry.amount),0) AS $lc_that_type";
|
||||||
|
else
|
||||||
|
$that_query['fields'][] = "COALESCE(SUM(StatementEntry.amount), 0) AS $lc_that_type";
|
||||||
|
$that_query['conditions'][] = array("{$that_name}Entry.type" => $that_type);
|
||||||
|
$result = $this->find('first', $that_query);
|
||||||
|
$stats[$this_name] += $result[0];
|
||||||
|
|
||||||
|
$this->pr(17, compact('that_query', 'result'), "{$this_name}s: $that_type");
|
||||||
|
$stats[$this_name]['reconciled'] += $stats[$this_name][$lc_that_type];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute balance information for charges
|
||||||
|
$stats[$this_name]['balance'] =
|
||||||
|
$stats[$this_name]['total'] - $stats[$this_name]['reconciled'];
|
||||||
|
if (!isset($stats[$this_name]['balance']))
|
||||||
|
$stats[$this_name]['balance'] = 0;
|
||||||
}
|
}
|
||||||
$stats['Charge']['balance'] =
|
|
||||||
$stats['Charge']['total'] - $stats['Charge']['reconciled'];
|
|
||||||
|
|
||||||
$this->pr(17, compact('query', 'result'),
|
|
||||||
'Charges');
|
|
||||||
|
|
||||||
$rquery = $query;
|
// 'balance' is simply the difference between
|
||||||
unset($rquery['link']['PaymentEntry']);
|
// the balances of charges and disbursements
|
||||||
$rquery['link']['ChargeEntry'] = array('fields' => array());
|
$stats['balance'] = $stats['Charge']['balance'] - $stats['Disbursement']['balance'];
|
||||||
|
if (!isset($stats['balance']))
|
||||||
|
$stats['balance'] = 0;
|
||||||
|
|
||||||
$rquery['fields'] = array();
|
// 'account_balance' is really only relevant to
|
||||||
$rquery['fields'][] = "SUM(StatementEntry.amount) AS total";
|
// callers that have requested charge and disbursement
|
||||||
$rquery['fields'][] = "SUM(IF(ChargeEntry.id IS NULL, 0, StatementEntry.amount)) AS reconciled";
|
// stats with respect to a particular account.
|
||||||
$rquery['fields'][] = "SUM(IF(ChargeEntry.id IS NULL, StatementEntry.amount, 0)) AS balance";
|
// It represents the difference between inflow
|
||||||
|
// and outflow from that account.
|
||||||
$rquery['conditions'][] = array('StatementEntry.type' => 'PAYMENT');
|
$stats['account_balance'] = $stats['Charge']['reconciled'] - $stats['Disbursement']['total'];
|
||||||
$result = $this->find('first', $rquery);
|
if (!isset($stats['account_balance']))
|
||||||
if (!isset($result[0]['balance']))
|
$stats['account_balance'] = 0;
|
||||||
$result[0]['balance'] = 0;
|
|
||||||
$stats['Payment'] = $result[0];
|
|
||||||
|
|
||||||
$this->pr(17, compact('rquery', 'result'),
|
|
||||||
'Payments');
|
|
||||||
|
|
||||||
return $this->prReturn($stats);
|
return $this->prReturn($stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -8,12 +8,73 @@ class Tender extends AppModel {
|
|||||||
'DepositTransaction' => array(
|
'DepositTransaction' => array(
|
||||||
'className' => 'Transaction',
|
'className' => 'Transaction',
|
||||||
),
|
),
|
||||||
|
'DepositLedgerEntry' => array(
|
||||||
|
'className' => 'LedgerEntry',
|
||||||
|
),
|
||||||
'NsfTransaction' => array(
|
'NsfTransaction' => array(
|
||||||
'className' => 'Transaction',
|
'className' => 'Transaction',
|
||||||
|
'dependent' => true,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: afterSave
|
||||||
|
* - Performs any work needed after the save occurs
|
||||||
|
*/
|
||||||
|
|
||||||
|
function afterSave($created) {
|
||||||
|
// Come up with a (not necessarily unique) name for the tender.
|
||||||
|
// For checks & money orders, this will be based on the check
|
||||||
|
// number. For other types of tender, we'll just use the
|
||||||
|
// generic name of the tender type, and the tender ID
|
||||||
|
|
||||||
|
// Determine our tender type, and set the ID of that model
|
||||||
|
$this->TenderType->id = $this->field('tender_type_id');
|
||||||
|
|
||||||
|
// REVISIT <AP>: 20090810
|
||||||
|
// The only tender expected to have no tender type
|
||||||
|
// is our special "Closing" tender.
|
||||||
|
if (empty($this->TenderType->id))
|
||||||
|
$newname = 'Closing';
|
||||||
|
else {
|
||||||
|
$newname = $this->TenderType->field('name');
|
||||||
|
$naming_field = $this->TenderType->field('naming_field');
|
||||||
|
if (!empty($naming_field))
|
||||||
|
$newname .= ' #' . $this->field($naming_field);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($newname !== $this->field('name'))
|
||||||
|
$this->saveField('name', $newname);
|
||||||
|
|
||||||
|
return parent::afterSave($created);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: beforeDelete
|
||||||
|
* - Performs any work needed before the delete occurs
|
||||||
|
*/
|
||||||
|
|
||||||
|
function beforeDelete($cascade = true) {
|
||||||
|
// REVISIT <AP>: 20090814
|
||||||
|
// Experimental, and incomplete mechanism to protect
|
||||||
|
// against trying to delete data that shouldn't be deleted.
|
||||||
|
|
||||||
|
$deposit_id = $this->field('deposit_transaction_id');
|
||||||
|
pr(compact('deposit_id'));
|
||||||
|
// If this tender has already been deposited, it would
|
||||||
|
// be a rats nest to figure out how to delete this tender.
|
||||||
|
if (!empty($deposit_id))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return parent::beforeDelete($cascade);
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -43,29 +104,10 @@ class Tender extends AppModel {
|
|||||||
function addTender($tender) {
|
function addTender($tender) {
|
||||||
$this->prEnter(compact('tender'));
|
$this->prEnter(compact('tender'));
|
||||||
|
|
||||||
$ret = array();
|
$ret = array('data' => $tender);
|
||||||
if (!$this->verifyTender($tender))
|
if (!$this->verifyTender($tender))
|
||||||
return $this->prReturn(array('error' => true) + $ret);
|
return $this->prReturn(array('error' => true) + $ret);
|
||||||
|
|
||||||
// Come up with a (not necessarily unique) name for the tender.
|
|
||||||
// For checks & money orders, this will be based on the check
|
|
||||||
// number. For other types of tender, we'll just use the
|
|
||||||
// generic name of the monetary account.
|
|
||||||
// REVISIT <AP>: 20090723
|
|
||||||
// I would like to have cash named "Cash #1234", where
|
|
||||||
// the number would correspond to either the Tender ID
|
|
||||||
// or the LedgerEntry ID.
|
|
||||||
if (empty($tender['name']) && !empty($tender['account_id'])) {
|
|
||||||
$tender['name'] = $this->LedgerEntry->Account->name($tender['account_id']);
|
|
||||||
if ($tender['account_id'] == $this->LedgerEntry->Account->checkAccountID() ||
|
|
||||||
$tender['account_id'] == $this->LedgerEntry->Account->moneyOrderAccountID()) {
|
|
||||||
$tender['name'] .= ' #' . $tender['data1'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->pr(20, array('Tender' => $tender),
|
|
||||||
'Pre-Save');
|
|
||||||
|
|
||||||
$this->create();
|
$this->create();
|
||||||
if (!$this->save($tender))
|
if (!$this->save($tender))
|
||||||
return $this->prReturn(array('error' => true) + $ret);
|
return $this->prReturn(array('error' => true) + $ret);
|
||||||
@@ -80,31 +122,10 @@ class Tender extends AppModel {
|
|||||||
**************************************************************************
|
**************************************************************************
|
||||||
* function: nsf
|
* function: nsf
|
||||||
* - Flags the ledger entry as having insufficient funds
|
* - Flags the ledger entry as having insufficient funds
|
||||||
*
|
|
||||||
* Steps:
|
|
||||||
* - Get information from Check (C1); for amount $A
|
|
||||||
* - Find Bank Deposit matching to Tender
|
|
||||||
* - New Transaction (T1)
|
|
||||||
* - New Bank Deposit (D1)
|
|
||||||
* - New Tender (N1); NSF; D1,
|
|
||||||
* - Add new LedgerEntry (L1a); T1; debit:bank; -$A
|
|
||||||
* - Add new LedgerEntry (L1b); T1; credit:NSF; -$A
|
|
||||||
* - 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
|
|
||||||
* - New Transaction (T2) (?????)
|
|
||||||
* - Add new StatementEntry (S2); T2; CHARGE; NSF; $35
|
|
||||||
* - Add new LedgerEntry (L3a); T2; credit:NSF-Fee; $35
|
|
||||||
* - Add new LedgerEntry (L3b); T2; debit:A/R; $35
|
|
||||||
* - Set C1.nsf_tx = T1
|
|
||||||
* - Re-Reconcile (customer may have running credit)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function nsf($id, $stamp = null) {
|
function nsf($id, $stamp = null, $comment = null) {
|
||||||
$this->prFunctionLevel(30);
|
$this->prEnter(compact('id', 'stamp', 'comment'));
|
||||||
$this->prEnter(compact('id'));
|
|
||||||
|
|
||||||
// Get information about this NSF item.
|
// Get information about this NSF item.
|
||||||
$this->id = $id;
|
$this->id = $id;
|
||||||
@@ -113,6 +134,7 @@ class Tender extends AppModel {
|
|||||||
('contain' =>
|
('contain' =>
|
||||||
array('LedgerEntry',
|
array('LedgerEntry',
|
||||||
'DepositTransaction',
|
'DepositTransaction',
|
||||||
|
'DepositLedgerEntry',
|
||||||
'NsfTransaction'),
|
'NsfTransaction'),
|
||||||
));
|
));
|
||||||
$this->pr(20, compact('tender'));
|
$this->pr(20, compact('tender'));
|
||||||
@@ -128,16 +150,15 @@ class Tender extends AppModel {
|
|||||||
unset($tender['NsfTransaction']);
|
unset($tender['NsfTransaction']);
|
||||||
|
|
||||||
$T = new Transaction();
|
$T = new Transaction();
|
||||||
$result = $T->addNsf($tender, $stamp);
|
$result = $T->addNsf($tender, $stamp, $comment);
|
||||||
if ($result['error'])
|
if (empty($result['error'])) {
|
||||||
return $this->prReturn(false);
|
// Flag the tender as NSF, using the items created from addNsf
|
||||||
|
$this->id = $id;
|
||||||
|
$this->saveField('nsf_transaction_id', $result['nsf_transaction_id']);
|
||||||
|
$this->saveField('nsf_ledger_entry_id', $result['nsf_ledger_entry_id']);
|
||||||
|
}
|
||||||
|
|
||||||
// Flag the tender as NSF, using the items created from addNsf
|
return $this->prReturn($result);
|
||||||
$this->id = $id;
|
|
||||||
$this->saveField('nsf_transaction_id', $result['nsf_transaction_id']);
|
|
||||||
$this->saveField('nsf_ledger_entry_id', $result['nsf_ledger_entry_id']);
|
|
||||||
|
|
||||||
return $this->prReturn(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -112,4 +112,4 @@ class TenderType extends AppModel {
|
|||||||
return $stats[0];
|
return $stats[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -25,8 +25,15 @@ class Unit extends AppModel {
|
|||||||
|
|
||||||
var $hasMany = array(
|
var $hasMany = array(
|
||||||
'Lease',
|
'Lease',
|
||||||
|
'LocksUnit'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
var $hasAndBelongsToMany = array(
|
||||||
|
'Lock'
|
||||||
|
);
|
||||||
|
|
||||||
|
//var $default_log_level = array('log' => 30, 'show' => 15);
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
@@ -50,13 +57,70 @@ class Unit extends AppModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function occupiedEnumValue() {
|
function occupiedEnumValue() {
|
||||||
return statusValue('OCCUPIED');
|
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 locked($enum) {
|
||||||
|
return $this->statusCheck($enum, 'LOCKED', false, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function conditionLocked() {
|
||||||
|
//return array('Unit.status' => 'LOCKED');
|
||||||
|
return ('Unit.status >= ' . $this->statusValue('LOCKED'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function liened($enum) {
|
||||||
|
return $this->statusCheck($enum, 'LIENED', false, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function conditionLiened() {
|
||||||
|
return ('Unit.status >= ' . $this->statusValue('LIENED'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function occupied($enum) {
|
||||||
|
return $this->statusCheck($enum, 'OCCUPIED', false, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function conditionOccupied() {
|
function conditionOccupied() {
|
||||||
return ('Unit.status >= ' . $this->statusValue('OCCUPIED'));
|
return ('Unit.status >= ' . $this->statusValue('OCCUPIED'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function vacant($enum) {
|
||||||
|
return $this->statusCheck($enum, 'UNAVAILABLE', true, 'OCCUPIED', true);
|
||||||
|
}
|
||||||
|
|
||||||
function conditionVacant() {
|
function conditionVacant() {
|
||||||
return ('Unit.status BETWEEN ' .
|
return ('Unit.status BETWEEN ' .
|
||||||
($this->statusValue('UNAVAILABLE')+1) .
|
($this->statusValue('UNAVAILABLE')+1) .
|
||||||
@@ -64,22 +128,143 @@ class Unit extends AppModel {
|
|||||||
($this->statusValue('OCCUPIED')-1));
|
($this->statusValue('OCCUPIED')-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function unavailable($enum) {
|
||||||
|
return $this->statusCheck($enum, null, false, 'UNAVAILABLE', false);
|
||||||
|
}
|
||||||
|
|
||||||
function conditionUnavailable() {
|
function conditionUnavailable() {
|
||||||
return ('Unit.status <= ' . $this->statusValue('UNAVAILABLE'));
|
return ('Unit.status <= ' . $this->statusValue('UNAVAILABLE'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function available($enum) { return $this->vacant($enum); }
|
||||||
|
function conditionAvailable() { return $this->conditionVacant($enum); }
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: allowedStatusSet
|
||||||
|
* - Returns the status set allowed for the given unit
|
||||||
|
*/
|
||||||
|
function allowedStatusSet($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
$this->id = $id;
|
||||||
|
$old_status = $this->field('status');
|
||||||
|
$old_val = $this->statusValue($old_status);
|
||||||
|
$this->pr(17, compact('old_status', 'old_val'));
|
||||||
|
|
||||||
|
$enums = $this->activeStatusEnums();
|
||||||
|
$this->pr(21, compact('enums'));
|
||||||
|
|
||||||
|
foreach ($enums AS $enum => $val) {
|
||||||
|
if (($old_val < $this->occupiedEnumValue()) !=
|
||||||
|
($val < $this->occupiedEnumValue())) {
|
||||||
|
unset($enums[$enum]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->prReturn($enums);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* function: updateStatus
|
* function: updateStatus
|
||||||
* - Update the given unit to the given status
|
* - 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;
|
$this->id = $id;
|
||||||
//pr(compact('id', 'status'));
|
|
||||||
$this->saveField('status', $status);
|
$this->saveField('status', $status);
|
||||||
|
return $this->prReturn(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: update
|
||||||
|
* - Update any cached or calculated fields
|
||||||
|
*/
|
||||||
|
function update($id) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: lockUnit
|
||||||
|
* - Put lock on unit
|
||||||
|
*/
|
||||||
|
function lockUnit($id, $lock_ids) {
|
||||||
|
$this->prEnter(compact('id', 'lock_ids'));
|
||||||
|
$this->id = $id;
|
||||||
|
|
||||||
|
// Remove any exising locks for this unit
|
||||||
|
$this->LocksUnit->deleteAll
|
||||||
|
(array('unit_id' => $id), false);
|
||||||
|
|
||||||
|
// 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 lock, and put them on the unit
|
||||||
|
foreach ($lock_ids AS $lock_id) {
|
||||||
|
$pair['unit_id'] = $id;
|
||||||
|
$pair['lock_id'] = $lock_id;
|
||||||
|
|
||||||
|
// Save the relationship between lock and unit
|
||||||
|
$LU = new LocksUnit();
|
||||||
|
if (!$LU->save($pair, false))
|
||||||
|
$ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->prReturn($ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: lockCount
|
||||||
|
* - Number of locks on a unit
|
||||||
|
*/
|
||||||
|
function lockCount($id) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
return $this->prReturn($this->find
|
||||||
|
('count', array
|
||||||
|
('fields' => array("COUNT(Lock.id) AS count"),
|
||||||
|
'link' => array('Lock'),
|
||||||
|
'conditions' => array('Unit.id' => $id),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
|
|||||||
@@ -1,25 +1,64 @@
|
|||||||
<?php
|
<?php
|
||||||
class UnitSize extends AppModel {
|
class UnitSize extends AppModel {
|
||||||
|
|
||||||
var $name = 'UnitSize';
|
var $belongsTo =
|
||||||
var $validate = array(
|
array(
|
||||||
'id' => array('numeric'),
|
'UnitType',
|
||||||
'unit_type_id' => array('numeric'),
|
);
|
||||||
'code' => array('notempty'),
|
|
||||||
'name' => array('notempty'),
|
|
||||||
'width' => array('numeric'),
|
|
||||||
'depth' => array('numeric'),
|
|
||||||
'deposit' => array('money'),
|
|
||||||
'amount' => array('money')
|
|
||||||
);
|
|
||||||
|
|
||||||
var $belongsTo = array(
|
var $hasMany =
|
||||||
'UnitType',
|
array(
|
||||||
);
|
'Unit',
|
||||||
|
);
|
||||||
|
|
||||||
var $hasMany = array(
|
|
||||||
'Unit',
|
/**************************************************************************
|
||||||
);
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: stats
|
||||||
|
* - Returns summary data from the requested unit size.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function stats($id = null) {
|
||||||
|
$this->prEnter(compact('id'));
|
||||||
|
|
||||||
|
// Right now, we only work with id not null
|
||||||
|
if (!$id)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
$stats = array();
|
||||||
|
|
||||||
|
// Get the total number of units this size
|
||||||
|
$stats['all'] =
|
||||||
|
$this->find('count',
|
||||||
|
array('link' => array('Unit'),
|
||||||
|
'conditions' => array(array('UnitSize.id' => $id)),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Get numbers for units in the various states
|
||||||
|
foreach (array('unavailable', 'vacant', 'occupied', 'locked', 'liened') AS $status) {
|
||||||
|
$statusfunc = 'condition' . ucfirst($status);
|
||||||
|
$stats[$status] =
|
||||||
|
$this->find('count',
|
||||||
|
array('link' => array('Unit'),
|
||||||
|
'conditions' => array(array('UnitSize.id' => $id),
|
||||||
|
$this->Unit->{$statusfunc}()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count up each unit by physical status
|
||||||
|
foreach
|
||||||
|
($this->find('all',
|
||||||
|
array('link' => array('Unit' => array('fields' => array())),
|
||||||
|
'fields' => array('Unit.status', 'COUNT(Unit.id) AS total'),
|
||||||
|
'conditions' => array(array('UnitSize.id' => $id)),
|
||||||
|
'group' => 'Unit.status',
|
||||||
|
)) AS $status) {
|
||||||
|
$stats['status'][$status['Unit']['status']] = $status[0]['total'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the collection
|
||||||
|
return $this->prReturn($stats);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
?>
|
|
||||||
@@ -1,16 +1,50 @@
|
|||||||
<?php
|
<?php
|
||||||
class UnitType extends AppModel {
|
class UnitType extends AppModel {
|
||||||
|
|
||||||
var $name = 'UnitType';
|
var $hasMany =
|
||||||
var $validate = array(
|
array(
|
||||||
'id' => array('numeric'),
|
'UnitSize',
|
||||||
'code' => array('notempty'),
|
);
|
||||||
'name' => array('notempty')
|
|
||||||
);
|
|
||||||
|
|
||||||
var $hasMany = array(
|
|
||||||
'UnitSize',
|
/**************************************************************************
|
||||||
);
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: relatedTypes
|
||||||
|
* - Returns an array of types related by similar attributes
|
||||||
|
*/
|
||||||
|
|
||||||
|
function relatedTypes($attribute, $extra = null) {
|
||||||
|
$this->cacheQueries = true;
|
||||||
|
$types = $this->find('all', array
|
||||||
|
('fields' => array('UnitType.id', 'UnitType.name'),
|
||||||
|
'conditions' => array('UnitType.'.$attribute => true),
|
||||||
|
'order' => array('UnitType.name'),
|
||||||
|
) + (isset($extra) ? $extra : array())
|
||||||
|
);
|
||||||
|
$this->cacheQueries = false;
|
||||||
|
|
||||||
|
// Rearrange to be of the form (id => name)
|
||||||
|
$rel_types = array();
|
||||||
|
foreach ($types AS $type) {
|
||||||
|
$rel_types[$type['UnitType']['id']] = $type['UnitType']['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rel_types;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
**************************************************************************
|
||||||
|
* function: xxxTypes
|
||||||
|
* - Returns an array of types suitable for activity xxx
|
||||||
|
*/
|
||||||
|
|
||||||
|
function residentialTypes() { return $this->relatedTypes('residential'); }
|
||||||
|
function enclosedTypes() { return $this->relatedTypes('enclosed'); }
|
||||||
|
function climateTypes() { return $this->relatedTypes('climate'); }
|
||||||
|
function outdoorTypes() { return $this->relatedTypes('outdoor'); }
|
||||||
|
function coveredTypes() { return $this->relatedTypes('covered'); }
|
||||||
|
|
||||||
}
|
}
|
||||||
?>
|
|
||||||
39
site/models/user.php
Normal file
39
site/models/user.php
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
class User extends AppModel {
|
||||||
|
|
||||||
|
var $hasMany =
|
||||||
|
array('UserOption',
|
||||||
|
'Membership',
|
||||||
|
);
|
||||||
|
|
||||||
|
static $current_user_id;
|
||||||
|
|
||||||
|
function currentUser() {
|
||||||
|
if (!empty($_SERVER['REMOTE_USER']))
|
||||||
|
return $_SERVER['REMOTE_USER'];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function currentUserId() {
|
||||||
|
if (!empty(self::$current_user_id))
|
||||||
|
return self::$current_user_id;
|
||||||
|
|
||||||
|
$user = $this->find
|
||||||
|
('first',
|
||||||
|
array('recursive' => -1,
|
||||||
|
'conditions' => array('login' => $this->currentUser())));
|
||||||
|
|
||||||
|
if (!empty($user['User']['id']))
|
||||||
|
self::$current_user_id = $user['User']['id'];
|
||||||
|
else
|
||||||
|
// We must force a stop here, since this is typically
|
||||||
|
// called very early on, and so will cause a recursive
|
||||||
|
// crash as we try to render the internal error and
|
||||||
|
// again stumble on this problem.
|
||||||
|
$this->INTERNAL_ERROR('UNKNOWN USER', 0, true);
|
||||||
|
|
||||||
|
return self::$current_user_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
24
site/models/user_option.php
Normal file
24
site/models/user_option.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
class UserOption extends AppModel {
|
||||||
|
|
||||||
|
var $belongsTo =
|
||||||
|
array('User',
|
||||||
|
'OptionValue',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
function values($id, $name = null) {
|
||||||
|
$this->prEnter(compact('id', 'name'));
|
||||||
|
|
||||||
|
$query = array();
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
$query['link']['UserOption'] = array();
|
||||||
|
$query['link']['UserOption']['fields'] = array();
|
||||||
|
$query['link']['UserOption']['User'] = array();
|
||||||
|
$query['link']['UserOption']['User']['fields'] = array();
|
||||||
|
$query['conditions'][] = array('User.id' => $id);
|
||||||
|
return $this->prReturn($this->OptionValue->values($name, $query));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
24
site/models/user_permission.php
Normal file
24
site/models/user_permission.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
class UserPermission extends AppModel {
|
||||||
|
|
||||||
|
var $belongsTo =
|
||||||
|
array('User',
|
||||||
|
'PermissionValue',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
function values($id, $name = null) {
|
||||||
|
$this->prEnter(compact('id', 'name'));
|
||||||
|
|
||||||
|
$query = array();
|
||||||
|
$this->queryInit($query);
|
||||||
|
|
||||||
|
$query['link']['UserPermission'] = array();
|
||||||
|
$query['link']['UserPermission']['fields'] = array();
|
||||||
|
$query['link']['UserPermission']['User'] = array();
|
||||||
|
$query['link']['UserPermission']['User']['fields'] = array();
|
||||||
|
$query['conditions'][] = array('User.id' => $id);
|
||||||
|
return $this->prReturn($this->PermissionValue->values($name, $query));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -163,7 +163,7 @@ class ToolbarComponent extends Object {
|
|||||||
trigger_error(sprintf(__('Could not load DebugToolbar panel %s', true), $panel), E_USER_WARNING);
|
trigger_error(sprintf(__('Could not load DebugToolbar panel %s', true), $panel), E_USER_WARNING);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$panelObj =& new $className();
|
$panelObj = new $className();
|
||||||
if (is_subclass_of($panelObj, 'DebugPanel') || is_subclass_of($panelObj, 'debugpanel')) {
|
if (is_subclass_of($panelObj, 'DebugPanel') || is_subclass_of($panelObj, 'debugpanel')) {
|
||||||
$this->panels[$panel] =& $panelObj;
|
$this->panels[$panel] =& $panelObj;
|
||||||
}
|
}
|
||||||
@@ -456,7 +456,7 @@ class LogPanel extends DebugPanel {
|
|||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
function _parseFile($filename) {
|
function _parseFile($filename) {
|
||||||
$file =& new File($filename);
|
$file = new File($filename);
|
||||||
$contents = $file->read();
|
$contents = $file->read();
|
||||||
$timePattern = '/(\d{4}-\d{2}\-\d{2}\s\d{1,2}\:\d{1,2}\:\d{1,2})/';
|
$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);
|
$chunks = preg_split($timePattern, $contents, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
|
||||||
|
|||||||
@@ -30,14 +30,14 @@ $timers = DebugKitDebugger::getTimers();
|
|||||||
?>
|
?>
|
||||||
<h2><?php __('Timers'); ?></h2>
|
<h2><?php __('Timers'); ?></h2>
|
||||||
<p class="request-time">
|
<p class="request-time">
|
||||||
<?php $totalTime = sprintf(__('%s (seconds)', true), $number->precision(DebugKitDebugger::requestTime(), 6)); ?>
|
<?php $totalTime = sprintf(__('%.6s (seconds)', true), DebugKitDebugger::requestTime()); ?>
|
||||||
<?php echo $toolbar->message(__('Total Request Time:', true), $totalTime)?>
|
<?php echo $toolbar->message(__('Total Request Time:', true), $totalTime)?>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<?php foreach ($timers as $timerName => $timeInfo):
|
<?php foreach ($timers as $timerName => $timeInfo):
|
||||||
$rows[] = array(
|
$rows[] = array(
|
||||||
$timeInfo['message'],
|
$timeInfo['message'],
|
||||||
$number->precision($timeInfo['time'], 6)
|
sprintf(__('%.6s', true), $timeInfo['time'])
|
||||||
);
|
);
|
||||||
$headers = array(__('Message', true), __('time in seconds', true));
|
$headers = array(__('Message', true), __('time in seconds', true));
|
||||||
endforeach;
|
endforeach;
|
||||||
|
|||||||
9
site/valley_storage.pmgr.htpasswd
Normal file
9
site/valley_storage.pmgr.htpasswd
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
abijah:Property Manager:a2369e3cc9e231ea6f02ce799a8b9970
|
||||||
|
anja:Property Manager:4539d5a6e58dd5895f2f3891d29705b0
|
||||||
|
kevin:Property Manager:f01accc9f5e5cdfc028dcf0cca837cf1
|
||||||
|
adam:Property Manager:ae6835569bb2fc0a0a4a773580ac8cda
|
||||||
|
shirley:Property Manager:e7e9d674c700796c99cdbf3cf105e739
|
||||||
|
admin:Property Manager:bab2226685d9b4b66220db8df80f1822
|
||||||
|
dev:Property Manager:e5c27b3c025e47239a45daceea2c0a00
|
||||||
|
vasst:Property Manager:523abc6c2b8458b463d5a9baa4f58f2e
|
||||||
|
answerfirst:Property Manager:6ac128447fab8be985c74ba7539c39b3
|
||||||
@@ -15,7 +15,8 @@ echo '<div class="account collected">' . "\n";
|
|||||||
|
|
||||||
// Reset the form
|
// Reset the form
|
||||||
function resetForm() {
|
function resetForm() {
|
||||||
/* updateEntriesGrid(); */
|
// Kick off the grid
|
||||||
|
updateEntriesGrid();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onGridLoadComplete() {
|
function onGridLoadComplete() {
|
||||||
@@ -39,12 +40,15 @@ function updateEntriesGrid() {
|
|||||||
|
|
||||||
$('#collected-total').html('Calculating...');
|
$('#collected-total').html('Calculating...');
|
||||||
$('#collected-entries-jqGrid').clearGridData();
|
$('#collected-entries-jqGrid').clearGridData();
|
||||||
$('#collected-entries-jqGrid').setPostDataItem('dynamic_post', serialize(dynamic_post));
|
$('#collected-entries-jqGrid').setPostDataItem('dynamic_post_replace', serialize(dynamic_post));
|
||||||
$('#collected-entries-jqGrid')
|
$('#collected-entries-jqGrid')
|
||||||
.setGridParam({ page: 1 })
|
.setGridParam({ page: 1 })
|
||||||
.trigger("reloadGrid");
|
.trigger("reloadGrid");
|
||||||
|
|
||||||
//$('#collected-entries .HeaderButton').click();
|
//$('#debug').html("<PRE>\n"+htmlEncode(dump($('#collected-entries-jqGrid').getGridParam()))+"\n</PRE>")
|
||||||
|
var gridstate = $('#collected-entries-jqGrid').getGridParam('gridstate');
|
||||||
|
if (gridstate == 'hidden')
|
||||||
|
$('#collected-entries .HeaderButton').click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -161,12 +165,12 @@ echo $this->element('statement_entries', array
|
|||||||
'grid_div_id' => 'collected-entries',
|
'grid_div_id' => 'collected-entries',
|
||||||
'grid_div_class' => 'text-below',
|
'grid_div_class' => 'text-below',
|
||||||
'grid_events' => array('loadComplete' => 'onGridLoadComplete()'),
|
'grid_events' => array('loadComplete' => 'onGridLoadComplete()'),
|
||||||
//'grid_setup' => array('hiddengrid' => true),
|
'grid_setup' => array('hiddengrid' => true),
|
||||||
//'caption' => '<SPAN id="receipt-charges-caption"></SPAN>',
|
|
||||||
'caption' => 'Collected ' . Inflector::pluralize($account['name']),
|
'caption' => 'Collected ' . Inflector::pluralize($account['name']),
|
||||||
'filter' => array('StatementEntry.type' => 'PAYMENT',
|
'action' => 'collected',
|
||||||
'ChargeEntry.account_id' => $account['id']),
|
'filter' => array('ChargeEntry.account_id' => $account['id']),
|
||||||
'exclude' => array('Account', 'Charge'),
|
'include' => array('Amount'),
|
||||||
|
'exclude' => array(/*'Type',*/ 'Debit', 'Credit'),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -174,20 +178,8 @@ echo $this->element('statement_entries', array
|
|||||||
|
|
||||||
<script type="text/javascript"><!--
|
<script type="text/javascript"><!--
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
$("#TxFromDate")
|
datepicker('TxFromDate');
|
||||||
.attr('autocomplete', 'off')
|
datepicker('TxThroughDate');
|
||||||
.datepicker({ constrainInput: true,
|
|
||||||
numberOfMonths: [1, 1],
|
|
||||||
showCurrentAtPos: 0,
|
|
||||||
dateFormat: 'mm/dd/yy' });
|
|
||||||
|
|
||||||
$("#TxThroughDate")
|
|
||||||
.attr('autocomplete', 'off')
|
|
||||||
.datepicker({ constrainInput: true,
|
|
||||||
numberOfMonths: [1, 1],
|
|
||||||
showCurrentAtPos: 0,
|
|
||||||
dateFormat: 'mm/dd/yy' });
|
|
||||||
|
|
||||||
resetForm();
|
resetForm();
|
||||||
});
|
});
|
||||||
--></script>
|
--></script>
|
||||||
@@ -201,5 +193,3 @@ echo '</div>' . "\n";
|
|||||||
echo '</div>' . "\n";
|
echo '</div>' . "\n";
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<a href="#" onClick="$('#debug').html(''); return false;">Clear Debug Output</a>
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ if (isset($account['Account']))
|
|||||||
$account = $account['Account'];
|
$account = $account['Account'];
|
||||||
|
|
||||||
$rows = array();
|
$rows = array();
|
||||||
$rows[] = array('ID', $account['id']);
|
|
||||||
$rows[] = array('Name', $account['name']);
|
$rows[] = array('Name', $account['name']);
|
||||||
$rows[] = array('Type', $account['type']);
|
$rows[] = array('Type', $account['type']);
|
||||||
$rows[] = array('External Name', $account['external_name']);
|
$rows[] = array('External Name', $account['external_name']);
|
||||||
@@ -78,12 +77,12 @@ echo $this->element('ledger_entries', array
|
|||||||
(// Grid configuration
|
(// Grid configuration
|
||||||
'config' => array
|
'config' => array
|
||||||
('grid_div_id' => 'ledger-ledger-entry-list',
|
('grid_div_id' => 'ledger-ledger-entry-list',
|
||||||
'caption' => ("Current Ledger: " .
|
'caption' => "Current Ledger: #{$current_ledger['sequence']}",
|
||||||
"(". $current_ledger['name'] .")"),
|
'filter' => array('Ledger.id' => $current_ledger['id']),
|
||||||
'filter' => array('Ledger.id' => $current_ledger['id']),
|
|
||||||
'exclude' => array('Account', 'Amount', 'Cr/Dr', 'Balance',
|
'exclude' => array('Account', 'Amount', 'Cr/Dr', 'Balance',
|
||||||
empty($account['payments']) ? 'Tender' : null),
|
empty($account['receipts']) ? 'Tender' : null),
|
||||||
'include' => array('Debit', 'Credit', 'Sub-Total'),
|
'include' => array('Debit', 'Credit', 'Sub-Total'),
|
||||||
|
'limit' => 50,
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
|
||||||
@@ -100,8 +99,9 @@ echo $this->element('ledger_entries', array
|
|||||||
'caption' => "Entire Ledger",
|
'caption' => "Entire Ledger",
|
||||||
'filter' => array('Account.id' => $account['id']),
|
'filter' => array('Account.id' => $account['id']),
|
||||||
'exclude' => array('Account', 'Amount', 'Cr/Dr', 'Balance',
|
'exclude' => array('Account', 'Amount', 'Cr/Dr', 'Balance',
|
||||||
empty($account['payments']) ? 'Tender' : null),
|
empty($account['receipts']) ? 'Tender' : null),
|
||||||
'include' => array('Debit', 'Credit', 'Sub-Total'),
|
'include' => array('Transaction', 'Debit', 'Credit', 'Sub-Total'),
|
||||||
|
'limit' => 50,
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ function contactMethodDiv($obj, $type, $legend, $values = null) {
|
|||||||
' CLASS="'.$type.'-method-%{id}-source" ' . "\n" .
|
' CLASS="'.$type.'-method-%{id}-source" ' . "\n" .
|
||||||
' ID="'.$type.'-method-%{id}-source-'.$stype.'"' . "\n" .
|
' ID="'.$type.'-method-%{id}-source-'.$stype.'"' . "\n" .
|
||||||
' VALUE="'.$stype.'"' . "\n" .
|
' VALUE="'.$stype.'"' . "\n" .
|
||||||
|
($stype == 'new' ? ' CHECKED' . "\n" : '') .
|
||||||
' />' . "\n" .
|
' />' . "\n" .
|
||||||
' <LABEL FOR="'.$type.'-method-%{id}-source-'.$stype.'">'.$sname.'</LABEL>' . "\n" .
|
' <LABEL FOR="'.$type.'-method-%{id}-source-'.$stype.'">'.$sname.'</LABEL>' . "\n" .
|
||||||
' ';
|
' ';
|
||||||
@@ -67,7 +68,7 @@ function contactMethodDiv($obj, $type, $legend, $values = null) {
|
|||||||
'</DIV>' . "\n" .
|
'</DIV>' . "\n" .
|
||||||
|
|
||||||
// BEGIN method-div
|
// BEGIN method-div
|
||||||
'<div id="'.$type.'-%{id}-method-div"' . "\n" .
|
'<div id="'.$type.'-%{id}-method-div"' . '>' . "\n" .
|
||||||
|
|
||||||
$obj->element
|
$obj->element
|
||||||
('form_table',
|
('form_table',
|
||||||
@@ -76,21 +77,30 @@ function contactMethodDiv($obj, $type, $legend, $values = null) {
|
|||||||
'fields' => array
|
'fields' => array
|
||||||
(
|
(
|
||||||
'preference' => array
|
'preference' => array
|
||||||
('opts' => array
|
('label_attributes' => array('class' => 'required'),
|
||||||
|
'opts' => array
|
||||||
('options' => $obj->varstore['methodPreferences'],
|
('options' => $obj->varstore['methodPreferences'],
|
||||||
'selected' => (isset($values) ? $values['ContactsMethod']['preference'] : null),
|
'selected' => (isset($values) ? $values['ContactsMethod']['preference'] : null),
|
||||||
)),
|
),
|
||||||
|
'after' => "Intended purpose for this method of communication.",
|
||||||
|
),
|
||||||
|
|
||||||
'type' => array
|
'type' => array
|
||||||
('opts' => array
|
('label_attributes' => array('class' => 'required'),
|
||||||
|
'opts' => array
|
||||||
('options' => $obj->varstore['methodTypes'],
|
('options' => $obj->varstore['methodTypes'],
|
||||||
'selected' => (isset($values) ? $values['ContactsMethod']['type'] : null),
|
'selected' => (isset($values) ? $values['ContactsMethod']['type'] : null),
|
||||||
)),
|
),
|
||||||
|
'after' => "How / Where this communication reaches the contact.",
|
||||||
|
),
|
||||||
|
|
||||||
'comment' => array
|
'comment' => array
|
||||||
('opts' => array
|
('label_attributes' => array('class' => 'optional empty'),
|
||||||
|
'opts' => array
|
||||||
('value' => (isset($values) ? $values['ContactsMethod']['comment'] : null),
|
('value' => (isset($values) ? $values['ContactsMethod']['comment'] : null),
|
||||||
)),
|
),
|
||||||
|
'after' => "Optional: Comments on how this form of communication relates to the contact.",
|
||||||
|
),
|
||||||
|
|
||||||
))) . "\n" .
|
))) . "\n" .
|
||||||
|
|
||||||
@@ -113,16 +123,27 @@ function contactMethodTypeDiv($obj, $type, $stype, $values = null) {
|
|||||||
if ($type === 'phone') {
|
if ($type === 'phone') {
|
||||||
if ($stype === 'existing') {
|
if ($stype === 'existing') {
|
||||||
$fields = array
|
$fields = array
|
||||||
('id' => array('name' => 'Phone/Ext',
|
('id' => array('label_attributes' => array('class' => 'required empty'),
|
||||||
|
'name' => 'Phone/Ext',
|
||||||
'opts' => array('options' => $obj->varstore['contactPhones'])),
|
'opts' => array('options' => $obj->varstore['contactPhones'])),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
elseif ($stype === 'new') {
|
elseif ($stype === 'new') {
|
||||||
$fields = array
|
$fields = array
|
||||||
('type' => array('opts' => array('options' => $obj->varstore['phoneTypes'])),
|
('type' => array('label_attributes' => array('class' => 'required'),
|
||||||
'phone' => true,
|
'opts' => array('autocomplete' => 'off',
|
||||||
'ext' => array('name' => "Extension"),
|
'options' => $obj->varstore['phoneTypes']),
|
||||||
'comment' => true,
|
'after' => "Physical type of the phone."),
|
||||||
|
'phone' => array('label_attributes' => array('class' => 'required empty'),
|
||||||
|
'opts' => array('autocomplete' => 'off'),
|
||||||
|
'after' => "Required: Phone number."),
|
||||||
|
'ext' => array('name' => "Extension",
|
||||||
|
'label_attributes' => array('class' => 'optional empty'),
|
||||||
|
'opts' => array('autocomplete' => 'off'),
|
||||||
|
'after' => "Optional: Extension number."),
|
||||||
|
'comment' => array('label_attributes' => array('class' => 'optional empty'),
|
||||||
|
'opts' => array('autocomplete' => 'off'),
|
||||||
|
'after' => "Optional: Comments about this phone number."),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
elseif ($stype === 'show') {
|
elseif ($stype === 'show') {
|
||||||
@@ -149,12 +170,25 @@ function contactMethodTypeDiv($obj, $type, $stype, $values = null) {
|
|||||||
}
|
}
|
||||||
elseif ($stype === 'new') {
|
elseif ($stype === 'new') {
|
||||||
$fields = array
|
$fields = array
|
||||||
('address' => true,
|
('address' => array('label_attributes' => array('class' => 'required empty'),
|
||||||
'city' => true,
|
'opts' => array('autocomplete' => 'off'),
|
||||||
'state' => true,
|
'after' => "Required: First line of mailing address."),
|
||||||
'postcode' => array('name' => 'Zip Code'),
|
'city' => array('label_attributes' => array('class' => 'required empty'),
|
||||||
'country' => true,
|
'opts' => array('autocomplete' => 'off'),
|
||||||
'comment' => true,
|
'after' => "Required."),
|
||||||
|
'state' => array('label_attributes' => array('class' => 'required empty'),
|
||||||
|
'opts' => array('autocomplete' => 'off'),
|
||||||
|
'after' => "Required."),
|
||||||
|
'postcode' => array('name' => 'Zip Code',
|
||||||
|
'label_attributes' => array('class' => 'required empty'),
|
||||||
|
'opts' => array('autocomplete' => 'off'),
|
||||||
|
'after' => "Required."),
|
||||||
|
'country' => array('label_attributes' => array('class' => 'optional empty'),
|
||||||
|
'opts' => array('autocomplete' => 'off'),
|
||||||
|
'after' => "Optional: USA is presumed."),
|
||||||
|
'comment' => array('label_attributes' => array('class' => 'optional empty'),
|
||||||
|
'opts' => array('autocomplete' => 'off'),
|
||||||
|
'after' => "Optional: Comments about this mailing address."),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
elseif ($stype === 'show') {
|
elseif ($stype === 'show') {
|
||||||
@@ -177,13 +211,18 @@ function contactMethodTypeDiv($obj, $type, $stype, $values = null) {
|
|||||||
if ($stype === 'existing') {
|
if ($stype === 'existing') {
|
||||||
$fields = array
|
$fields = array
|
||||||
('id' => array('name' => 'Email',
|
('id' => array('name' => 'Email',
|
||||||
|
'label_attributes' => array('class' => 'required'),
|
||||||
'opts' => array('options' => $obj->varstore['contactEmails'])),
|
'opts' => array('options' => $obj->varstore['contactEmails'])),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
elseif ($stype === 'new') {
|
elseif ($stype === 'new') {
|
||||||
$fields = array
|
$fields = array
|
||||||
('email' => true,
|
('email' => array('label_attributes' => array('class' => 'required empty'),
|
||||||
'comment' => true,
|
'opts' => array('autocomplete' => 'off'),
|
||||||
|
'after' => "Required: E-mail address."),
|
||||||
|
'comment' => array('label_attributes' => array('class' => 'optional empty'),
|
||||||
|
'opts' => array('autocomplete' => 'off'),
|
||||||
|
'after' => "Optional: Comments about this email address."),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
elseif ($stype === 'show') {
|
elseif ($stype === 'show') {
|
||||||
@@ -204,7 +243,7 @@ function contactMethodTypeDiv($obj, $type, $stype, $values = null) {
|
|||||||
'<div ' . "\n" .
|
'<div ' . "\n" .
|
||||||
' class="'.$type.'-%{id}-div"' . "\n" .
|
' class="'.$type.'-%{id}-div"' . "\n" .
|
||||||
' id="'.$type.'-%{id}-'.$stype.'-div"' . "\n" .
|
' id="'.$type.'-%{id}-'.$stype.'-div"' . "\n" .
|
||||||
(isset($values) ? '' : ' STYLE="display:none;"' . "\n") .
|
((isset($values) || $stype == 'new') ? '' : ' STYLE="display:none;"' . "\n") .
|
||||||
'>' . "\n" .
|
'>' . "\n" .
|
||||||
|
|
||||||
$obj->element
|
$obj->element
|
||||||
@@ -319,8 +358,27 @@ function contactMethodTypeDiv($obj, $type, $stype, $values = null) {
|
|||||||
.slideDown();
|
.slideDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setEmpty(input_elem) {
|
||||||
|
selector = "label[for=" + $(input_elem).attr("id") + "]";
|
||||||
|
if ($(input_elem).val() == '')
|
||||||
|
$(selector).addClass('empty');
|
||||||
|
else
|
||||||
|
$(selector).removeClass('empty');
|
||||||
|
}
|
||||||
|
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
resetForm();
|
resetForm();
|
||||||
|
|
||||||
|
// In case refresh is hit with populated fields
|
||||||
|
$(":input").each(function(i,elem){ setEmpty(elem); });
|
||||||
|
|
||||||
|
// keyup doesn't catch cut from menu
|
||||||
|
$(":input").live('keyup', function(){
|
||||||
|
setEmpty(this);
|
||||||
|
});
|
||||||
|
$(":input").live('mouseup', function(){
|
||||||
|
setEmpty(this);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
--></script>
|
--></script>
|
||||||
@@ -345,17 +403,30 @@ echo($this->element
|
|||||||
array('class' => 'item contact detail',
|
array('class' => 'item contact detail',
|
||||||
'caption' => isset($this->data['Contact']) ? 'Edit Contact' : 'New Contact',
|
'caption' => isset($this->data['Contact']) ? 'Edit Contact' : 'New Contact',
|
||||||
'fields' => array
|
'fields' => array
|
||||||
('first_name' => true,
|
('last_name' => array('label_attributes' => array('class' => 'recommended empty'),
|
||||||
'last_name' => true,
|
'after' => "Recommended."),
|
||||||
'middle_name' => true,
|
'first_name' => array('label_attributes' => array('class' => 'recommended empty'),
|
||||||
'display_name' => true,
|
'after' => "Recommended."),
|
||||||
'company_name' => array('name' => 'Company'),
|
'middle_name' => array('label_attributes' => array('class' => 'optional empty'),
|
||||||
'id_federal' => array('name' => 'SSN'),
|
'after' => "Optional."),
|
||||||
'id_local' => array('name' => 'ID #'),
|
'company_name' => array('name' => 'Company',
|
||||||
'id_local_state' => array('name' => 'ID State'),
|
'label_attributes' => array('class' => 'optional empty'),
|
||||||
|
'after' => "Optional: Company name, if corporate contact."),
|
||||||
|
'display_name' => array('label_attributes' => array('class' => 'optional empty'),
|
||||||
|
'after' => "Optional with first/last name; Required otherwise."),
|
||||||
|
'id_federal' => array('name' => 'SSN',
|
||||||
|
'label_attributes' => array('class' => 'optional empty'),
|
||||||
|
'after' => "Optional: Social Security Number."),
|
||||||
|
'id_local' => array('name' => 'ID #',
|
||||||
|
'label_attributes' => array('class' => 'recommended empty'),
|
||||||
|
'after' => "Recommended: Driver's license, for example."),
|
||||||
|
'id_local_state' => array('name' => 'ID State',
|
||||||
|
'label_attributes' => array('class' => 'recommended empty'),
|
||||||
|
'after' => "Recommended: State which issued the ID."),
|
||||||
/* 'id_local_exp' => array('name' => 'ID Expiration', */
|
/* 'id_local_exp' => array('name' => 'ID Expiration', */
|
||||||
/* 'opts' => array('empty' => true)), */
|
/* 'opts' => array('empty' => true)), */
|
||||||
'comment' => true,
|
'comment' => array('label_attributes' => array('class' => 'optional empty'),
|
||||||
|
'after' => "Optional: Comments about this contact."),
|
||||||
))) . "\n");
|
))) . "\n");
|
||||||
|
|
||||||
echo $form->submit('Update') . "\n";
|
echo $form->submit('Update') . "\n";
|
||||||
|
|||||||
@@ -17,16 +17,17 @@ if (isset($contact['Contact']))
|
|||||||
$contact = $contact['Contact'];
|
$contact = $contact['Contact'];
|
||||||
|
|
||||||
$rows = array();
|
$rows = array();
|
||||||
$rows[] = array('First Name', $contact['first_name']);
|
$rows[] = array('Display Name', $contact['display_name']);
|
||||||
$rows[] = array('Middle Name', $contact['middle_name']);
|
$rows[] = array('First Name', $contact['first_name']);
|
||||||
$rows[] = array('Last Name', $contact['last_name']);
|
$rows[] = array('Middle Name', $contact['middle_name']);
|
||||||
$rows[] = array('Company', $contact['company_name']);
|
$rows[] = array('Last Name', $contact['last_name']);
|
||||||
$rows[] = array('SSN', $contact['id_federal']);
|
$rows[] = array('Company', $contact['company_name']);
|
||||||
$rows[] = array('ID', ($contact['id_local']
|
$rows[] = array('SSN', $contact['id_federal']);
|
||||||
. ($contact['id_local']
|
$rows[] = array('ID', ($contact['id_local']
|
||||||
? " - ".$contact['id_local_state']
|
. ($contact['id_local']
|
||||||
: "")));
|
? " - ".$contact['id_local_state']
|
||||||
$rows[] = array('Comment', $contact['comment']);
|
: "")));
|
||||||
|
$rows[] = array('Comment', $contact['comment']);
|
||||||
|
|
||||||
echo $this->element('table',
|
echo $this->element('table',
|
||||||
array('class' => 'item contact detail',
|
array('class' => 'item contact detail',
|
||||||
@@ -135,6 +136,7 @@ echo $this->element('customers', array
|
|||||||
'config' => array
|
'config' => array
|
||||||
('caption' => 'Related Customers',
|
('caption' => 'Related Customers',
|
||||||
'filter' => array('Contact.id' => $contact['id']),
|
'filter' => array('Contact.id' => $contact['id']),
|
||||||
|
'include' => array('Relationship'),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -42,11 +42,12 @@ function customerContactDiv($obj, $values = null, $primary = false) {
|
|||||||
' CLASS="contact-%{id}-source" ' . "\n" .
|
' CLASS="contact-%{id}-source" ' . "\n" .
|
||||||
' ID="contact-%{id}-source-'.$stype.'"' . "\n" .
|
' ID="contact-%{id}-source-'.$stype.'"' . "\n" .
|
||||||
' VALUE="'.$stype.'"' . "\n" .
|
' VALUE="'.$stype.'"' . "\n" .
|
||||||
//' CHECKED' . "\n" .
|
($stype == 'new' ? ' CHECKED' . "\n" : '') .
|
||||||
' />' . "\n" .
|
' />' . "\n" .
|
||||||
' <LABEL FOR="contact-%{id}-source-'.$stype.'">'.$sname.'</LABEL>' . "\n" .
|
' <LABEL FOR="contact-%{id}-source-'.$stype.'">'.$sname.'</LABEL>' . "\n" .
|
||||||
' ';
|
' ';
|
||||||
}
|
}
|
||||||
|
$div .= "<P>(Phone numbers / Addresses can be added later)";
|
||||||
}
|
}
|
||||||
$div .= "\n";
|
$div .= "\n";
|
||||||
|
|
||||||
@@ -65,7 +66,7 @@ function customerContactDiv($obj, $values = null, $primary = false) {
|
|||||||
'</DIV>' . "\n" .
|
'</DIV>' . "\n" .
|
||||||
|
|
||||||
// BEGIN contact-div
|
// BEGIN contact-div
|
||||||
'<div id="contact-%{id}-contact-div"' . "\n" .
|
'<div id="contact-%{id}-contact-div">' . "\n" .
|
||||||
|
|
||||||
$obj->element
|
$obj->element
|
||||||
('form_table',
|
('form_table',
|
||||||
@@ -75,23 +76,35 @@ function customerContactDiv($obj, $values = null, $primary = false) {
|
|||||||
(
|
(
|
||||||
'Customer.primary_contact_entry' => array
|
'Customer.primary_contact_entry' => array
|
||||||
('name' => 'Primary Contact',
|
('name' => 'Primary Contact',
|
||||||
|
'label_attributes' => array('class' => null),
|
||||||
'no_prefix' => true,
|
'no_prefix' => true,
|
||||||
'opts' => array
|
'opts' => array
|
||||||
('type' => 'radio',
|
('type' => 'radio',
|
||||||
'options' => array('%{id}' => false),
|
'options' => array('%{id}' => false),
|
||||||
'value' => ($primary ? '%{id}' : 'bogus-value-to-suppress-hidden-input'),
|
'value' => ($primary ? '%{id}' : 'bogus-value-to-suppress-hidden-input'),
|
||||||
)),
|
),
|
||||||
|
'after' => ("Check this button if this contact will be the primary" .
|
||||||
|
" contact for this customer (there can be only one primary" .
|
||||||
|
" contact"),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
'type' => array
|
'type' => array
|
||||||
('opts' => array
|
('label_attributes' => array('class' => 'required'),
|
||||||
|
'opts' => array
|
||||||
('options' => $obj->varstore['contactTypes'],
|
('options' => $obj->varstore['contactTypes'],
|
||||||
'selected' => (isset($values) ? $values['ContactsCustomer']['type'] : null),
|
'selected' => (isset($values) ? $values['ContactsCustomer']['type'] : null),
|
||||||
)),
|
),
|
||||||
|
'after' => "An actual tenant, or just an alternate contact?"
|
||||||
|
),
|
||||||
|
|
||||||
'comment' => array
|
'comment' => array
|
||||||
('opts' => array
|
('label_attributes' => array('class' => 'optional empty'),
|
||||||
|
'opts' => array
|
||||||
('value' => (isset($values) ? $values['ContactsCustomer']['comment'] : null),
|
('value' => (isset($values) ? $values['ContactsCustomer']['comment'] : null),
|
||||||
)),
|
),
|
||||||
|
'after' => "Optional: Comments on the relationship between this customer and this contact."
|
||||||
|
),
|
||||||
|
|
||||||
))) . "\n" .
|
))) . "\n" .
|
||||||
|
|
||||||
@@ -115,22 +128,37 @@ function customerContactTypeDiv($obj, $stype, $values = null) {
|
|||||||
if ($stype === 'existing') {
|
if ($stype === 'existing') {
|
||||||
$fields = array
|
$fields = array
|
||||||
('id' => array('name' => 'Contact',
|
('id' => array('name' => 'Contact',
|
||||||
'opts' => array('options' => $obj->varstore['contacts'])),
|
'label_attributes' => array('class' => 'required empty'),
|
||||||
|
'opts' => array('options' => $obj->varstore['contacts']),
|
||||||
|
'after' => "Select the existing contact."),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
elseif ($stype === 'new') {
|
elseif ($stype === 'new') {
|
||||||
$fields = array
|
$fields = array
|
||||||
('first_name' => true,
|
('last_name' => array('label_attributes' => array('class' => 'recommended empty'),
|
||||||
'last_name' => true,
|
'after' => "Recommended."),
|
||||||
'middle_name' => true,
|
'first_name' => array('label_attributes' => array('class' => 'recommended empty'),
|
||||||
'display_name' => true,
|
'after' => "Recommended."),
|
||||||
'company_name' => array('name' => 'Company'),
|
'middle_name' => array('label_attributes' => array('class' => 'optional empty'),
|
||||||
'id_federal' => array('name' => 'SSN'),
|
'after' => "Optional."),
|
||||||
'id_local' => array('name' => 'ID #'),
|
'company_name' => array('name' => 'Company',
|
||||||
'id_local_state' => array('name' => 'ID State'),
|
'label_attributes' => array('class' => 'optional empty'),
|
||||||
|
'after' => "Optional: Company name, if corporate contact."),
|
||||||
|
'display_name' => array('label_attributes' => array('class' => 'optional empty'),
|
||||||
|
'after' => "Optional with first/last name; Required otherwise."),
|
||||||
|
'id_federal' => array('name' => 'SSN',
|
||||||
|
'label_attributes' => array('class' => 'optional empty'),
|
||||||
|
'after' => "Optional: Social Security Number."),
|
||||||
|
'id_local' => array('name' => 'ID #',
|
||||||
|
'label_attributes' => array('class' => 'recommended empty'),
|
||||||
|
'after' => "Recommended: Driver's license, for example."),
|
||||||
|
'id_local_state' => array('name' => 'ID State',
|
||||||
|
'label_attributes' => array('class' => 'recommended empty'),
|
||||||
|
'after' => "Recommended: State which issued the ID."),
|
||||||
/* 'id_local_exp' => array('name' => 'ID Expiration', */
|
/* 'id_local_exp' => array('name' => 'ID Expiration', */
|
||||||
/* 'opts' => array('empty' => true)), */
|
/* 'opts' => array('empty' => true)), */
|
||||||
'comment' => true,
|
'comment' => array('label_attributes' => array('class' => 'optional empty'),
|
||||||
|
'after' => "Optional: Comments about this contact."),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
elseif ($stype === 'show') {
|
elseif ($stype === 'show') {
|
||||||
@@ -151,14 +179,14 @@ function customerContactTypeDiv($obj, $stype, $values = null) {
|
|||||||
'<div ' . "\n" .
|
'<div ' . "\n" .
|
||||||
' class="contact-%{id}-div"' . "\n" .
|
' class="contact-%{id}-div"' . "\n" .
|
||||||
' id="contact-%{id}-'.$stype.'-div"' . "\n" .
|
' id="contact-%{id}-'.$stype.'-div"' . "\n" .
|
||||||
(isset($values) ? '' : ' STYLE="display:none;"' . "\n") .
|
((isset($values) || $stype == 'new') ? '' : ' STYLE="display:none;"' . "\n") .
|
||||||
'>' . "\n" .
|
'>' . "\n" .
|
||||||
|
|
||||||
$obj->element
|
$obj->element
|
||||||
($element,
|
($element,
|
||||||
array('class' => "item contact {$class}",
|
array('class' => "item contact {$class}",
|
||||||
'field_prefix' => 'Contact.%{id}')
|
'field_prefix' => 'Contact.%{id}')
|
||||||
+ compact('rows', 'fields', 'column_class')) .
|
+ compact('rows', 'fields', 'row_class', 'column_class')) .
|
||||||
|
|
||||||
($stype === 'show'
|
($stype === 'show'
|
||||||
? '<input type="hidden" name="data[Contact][%{id}][id]" value="'.$values['id'].'"/>' . "\n"
|
? '<input type="hidden" name="data[Contact][%{id}][id]" value="'.$values['id'].'"/>' . "\n"
|
||||||
@@ -221,8 +249,28 @@ function customerContactTypeDiv($obj, $stype, $values = null) {
|
|||||||
.slideDown();
|
.slideDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setEmpty(input_elem) {
|
||||||
|
selector = "label[for=" + $(input_elem).attr("id") + "]";
|
||||||
|
//$("#debug").append($(input_elem).attr("id") + ": " + $(input_elem).val() + "<BR>");
|
||||||
|
if ($(input_elem).val() == '')
|
||||||
|
$(selector).addClass('empty');
|
||||||
|
else
|
||||||
|
$(selector).removeClass('empty');
|
||||||
|
}
|
||||||
|
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
resetForm();
|
resetForm();
|
||||||
|
|
||||||
|
// In case refresh is hit with populated fields
|
||||||
|
$(":input").each(function(i,elem){ setEmpty(elem); });
|
||||||
|
|
||||||
|
// keyup doesn't catch cut from menu
|
||||||
|
$(":input").live('keyup', function(){
|
||||||
|
setEmpty(this);
|
||||||
|
});
|
||||||
|
$(":input").live('mouseup', function(){
|
||||||
|
setEmpty(this);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
--></script>
|
--></script>
|
||||||
@@ -247,11 +295,15 @@ echo($this->element
|
|||||||
array('class' => 'item customer detail',
|
array('class' => 'item customer detail',
|
||||||
'caption' => isset($this->data['Customer']) ? 'Edit Customer' : 'New Customer',
|
'caption' => isset($this->data['Customer']) ? 'Edit Customer' : 'New Customer',
|
||||||
'fields' => array
|
'fields' => array
|
||||||
('name' => true,
|
('name' => array('label_attributes' => array('class' => 'optional empty'),
|
||||||
'comment' => true,
|
'after' => ("Optional: If this field is left blank, the" .
|
||||||
|
" customer name will be set to the name of" .
|
||||||
|
" the primary contact, below.")),
|
||||||
|
'comment' => array('label_attributes' => array('class' => 'optional empty'),
|
||||||
|
'after' => 'Optional: Comments about this customer.'),
|
||||||
))) . "\n");
|
))) . "\n");
|
||||||
|
|
||||||
echo $form->submit('Update') . "\n";
|
echo $form->submit(isset($this->data['Customer']) ? 'Update' : 'Add New Customer') . "\n";
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div CLASS="dynamic-set">
|
<div CLASS="dynamic-set">
|
||||||
@@ -268,7 +320,12 @@ echo $form->submit('Update') . "\n";
|
|||||||
<?php
|
<?php
|
||||||
; // Alignment
|
; // Alignment
|
||||||
|
|
||||||
echo $form->submit('Update') . "\n";
|
if (!empty($movein['Unit']['id']))
|
||||||
|
echo $form->input("movein.Unit.id",
|
||||||
|
array('type' => 'hidden',
|
||||||
|
'value' => $movein['Unit']['id'])) . "\n";
|
||||||
|
|
||||||
|
echo $form->submit(isset($this->data['Customer']) ? 'Update' : 'Add New Customer') . "\n";
|
||||||
echo $form->submit('Cancel', array('name' => 'cancel')) . "\n";
|
echo $form->submit('Cancel', array('name' => 'cancel')) . "\n";
|
||||||
echo $form->end() . "\n";
|
echo $form->end() . "\n";
|
||||||
echo '</div>' . "\n";
|
echo '</div>' . "\n";
|
||||||
|
|||||||
176
site/views/customers/merge.ctp
Normal file
176
site/views/customers/merge.ctp
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
<?php /* -*- mode:PHP -*- */ ?>
|
||||||
|
|
||||||
|
<div class="customer merge">
|
||||||
|
<?php
|
||||||
|
; // Editor alignment
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
* Javascript
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Warnings _really_ screw up javascript
|
||||||
|
$saved_debug_state = Configure::read('debug');
|
||||||
|
Configure::write('debug', '0');
|
||||||
|
?>
|
||||||
|
|
||||||
|
<script type="text/javascript"><!--
|
||||||
|
|
||||||
|
// pre-submit callback
|
||||||
|
function verifyRequest() {
|
||||||
|
if (!$("#src-customer-id").val()) {
|
||||||
|
alert("Must select source customer");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
rows = $('#<?php echo "contacts-jqGrid"; ?>').getGridParam('selarrrow');
|
||||||
|
$('#<?php echo "contact-ids"; ?>').val(serialize(rows));
|
||||||
|
|
||||||
|
// return false to prevent the form from being submitted;
|
||||||
|
// anything other than false will allow submission.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateContacts() {
|
||||||
|
$('#contacts-jqGrid').clearGridData();
|
||||||
|
|
||||||
|
var filter = new Array();
|
||||||
|
filter['ContactsCustomer.customer_id'] = $("#src-customer-id").val();
|
||||||
|
|
||||||
|
var dynamic_post = new Array();
|
||||||
|
dynamic_post['filter'] = filter;
|
||||||
|
|
||||||
|
$('#contacts-jqGrid').setPostDataItem('dynamic_post_replace', serialize(dynamic_post));
|
||||||
|
$('#contacts-jqGrid')
|
||||||
|
.setGridParam({ page: 1 })
|
||||||
|
.trigger("reloadGrid");
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRowSelect(grid_id, customer_id) {
|
||||||
|
//$('#output-debug').append("select: "+grid_id+"; "+customer_id+"<BR>\n");
|
||||||
|
|
||||||
|
// Set the item id that will be returned with the form
|
||||||
|
$("#src-customer-id").val(customer_id);
|
||||||
|
|
||||||
|
// Get the item name from the grid
|
||||||
|
$("#src-customer-name").html($(grid_id).getCell(customer_id, "Customer-name"));
|
||||||
|
|
||||||
|
updateContacts();
|
||||||
|
|
||||||
|
$("#customers-list .HeaderButton").click();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onGridState(grid_id, state) {
|
||||||
|
//$('#output-debug').append("state: "+grid_id+"; "+state+"<BR>\n");
|
||||||
|
|
||||||
|
if (state == 'visible') {
|
||||||
|
$(".customer-selection-invalid").hide();
|
||||||
|
$(".customer-selection-valid").hide();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($("#src-customer-id").val() > 0) {
|
||||||
|
$(".customer-selection-invalid").hide();
|
||||||
|
$(".customer-selection-valid").show();
|
||||||
|
} else {
|
||||||
|
$(".customer-selection-invalid").show();
|
||||||
|
$(".customer-selection-valid").hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--></script>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
; // align
|
||||||
|
// Re-Enable warnings
|
||||||
|
Configure::write('debug', $saved_debug_state);
|
||||||
|
|
||||||
|
echo $form->create(null, array('id' => 'customer-merge-form',
|
||||||
|
'onsubmit' => 'return verifyRequest();',
|
||||||
|
'url' => array('controller' => 'customers',
|
||||||
|
'action' => 'mergeFinal')))."\n";
|
||||||
|
|
||||||
|
|
||||||
|
echo '<input type="hidden" id="src-customer-id" name="src-id" value="0" />'."\n";
|
||||||
|
echo '<input type="hidden" id="dst-customer-id" name="dst-id" value="'.$dst_id.'" />'."\n";
|
||||||
|
|
||||||
|
echo $this->element('customers', array
|
||||||
|
('config' => array
|
||||||
|
('grid_div_id' => 'customers-list',
|
||||||
|
'grid_div_class' => 'text-below',
|
||||||
|
'caption' => ('<A HREF="#" ONCLICK="$(\'#customers-list .HeaderButton\').click();'.
|
||||||
|
' return false;">Select Customer</A>'),
|
||||||
|
'grid_events' => array('onSelectRow' =>
|
||||||
|
array('ids' =>
|
||||||
|
'if (ids != null){onRowSelect("#"+$(this).attr("id"), ids);}'),
|
||||||
|
'onHeaderClick' =>
|
||||||
|
array('gridstate' =>
|
||||||
|
'onGridState("#"+$(this).attr("id"), gridstate)'),
|
||||||
|
),
|
||||||
|
'filter' => array('Customer.id !=' => $dst_id),
|
||||||
|
//'nolinks' => true,
|
||||||
|
'limit' => 10,
|
||||||
|
)));
|
||||||
|
|
||||||
|
echo ('<DIV CLASS="customer-merge grid-selection-text">' .
|
||||||
|
|
||||||
|
'<DIV CLASS="customer-selection-valid" style="display:none">' .
|
||||||
|
'Destination Customer: <SPAN id="src-customer-name"></SPAN>' .
|
||||||
|
'</DIV>' .
|
||||||
|
|
||||||
|
'<DIV CLASS="customer-selection-invalid" style="display:none">' .
|
||||||
|
'Please select customer to merge into' .
|
||||||
|
'</DIV>' .
|
||||||
|
|
||||||
|
'</DIV>' . "\n");
|
||||||
|
|
||||||
|
echo $this->element('contacts', array
|
||||||
|
(// Grid configuration
|
||||||
|
'config' => array
|
||||||
|
(
|
||||||
|
'grid_div_id' => 'contacts',
|
||||||
|
'grid_setup' => array('multiselect' => true),
|
||||||
|
'caption' => 'Source contacts to keep',
|
||||||
|
'filter' => array('ContactsCustomer.customer_id' => 0),
|
||||||
|
'include' => array('Relationship', 'License', 'Comment'),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
// Add a hidden item to hold the jqGrid selection,
|
||||||
|
// which we'll populate prior to form submission.
|
||||||
|
echo "\n";
|
||||||
|
echo '<input type="hidden" id="contact-ids" name="contact-ids" value="" />'."\n";
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<H3>WARNING!</H3>
|
||||||
|
The above selected customer is about to be deleted, and all related data (leases, transactions, etc) will be merged into customer #<?php echo $dst_id ?>: <?php echo $dst_name ?>. This process is NOT reversible, so please ensure the selections are correct before proceeding.<BR>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
echo $form->end('Merge Customers') . "\n";
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div id="output-debug" style="display:none"></div>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// Warnings _really_ screw up javascript
|
||||||
|
Configure::write('debug', '0');
|
||||||
|
?>
|
||||||
|
|
||||||
|
<script type="text/javascript"><!--
|
||||||
|
$(document).ready(function(){
|
||||||
|
|
||||||
|
$("#src-customer-id").val(0);
|
||||||
|
$("#src-customer-name").html("INTERNAL ERROR");
|
||||||
|
//onGridState(null, 'visible');
|
||||||
|
|
||||||
|
<?php if ($this->params['dev']): ?>
|
||||||
|
$('#output-debug').show();
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
});
|
||||||
|
--></script>
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -11,6 +11,9 @@
|
|||||||
* Javascript
|
* Javascript
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Warnings _really_ screw up javascript
|
||||||
|
$saved_debug_state = Configure::read('debug');
|
||||||
|
Configure::write('debug', '0');
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<script type="text/javascript"><!--
|
<script type="text/javascript"><!--
|
||||||
@@ -23,60 +26,94 @@
|
|||||||
success: showResponse, // post-submit callback
|
success: showResponse, // post-submit callback
|
||||||
|
|
||||||
// other available options:
|
// 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
|
//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:
|
url: "<?php echo $html->url(array('controller' => 'transactions',
|
||||||
//timeout: 3000,
|
'action' => 'postReceipt', 0)); ?>"
|
||||||
};
|
};
|
||||||
|
|
||||||
// bind form using 'ajaxForm'
|
// bind form using 'ajaxForm'
|
||||||
$('#receipt-form').ajaxForm(options);
|
if ($('#receipt-form').ajaxForm != null)
|
||||||
|
$('#receipt-form').ajaxForm(options);
|
||||||
|
else
|
||||||
|
$('#repeat, label[for=repeat]').remove();
|
||||||
});
|
});
|
||||||
|
|
||||||
// pre-submit callback
|
// pre-submit callback
|
||||||
function verifyRequest(formData, jqForm, options) {
|
function verifyRequest(formData, jqForm, options) {
|
||||||
// formData is an array; here we use $.param to convert it to a string to display it
|
//$("#debug").html('');
|
||||||
// but the form plugin does this for you automatically when it submits the data
|
for (var i = 0; i < formData.length; ++i) {
|
||||||
//var_dump(formData);
|
//$("#debug").append(i + ') ' + dump(formData[i]) + '<BR>');
|
||||||
//$('#request-debug').html('<PRE>'+dump(formData)+'</PRE>');
|
if (formData[i]['name'] == "data[Customer][id]" &&
|
||||||
$('#request-debug').html('Ommitted');
|
!(formData[i]['value'] > 0)) {
|
||||||
|
//$("#debug").append('<P>Missing Customer ID');
|
||||||
|
alert("Please select a customer first.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formData[i]['name'] == "data[Transaction][stamp]" &&
|
||||||
|
formData[i]['value'] == '') {
|
||||||
|
//$("#debug").append('<P>Bad Stamp');
|
||||||
|
if (formData[i]['value'] != '')
|
||||||
|
alert(formData[i]['value'] + " is not valid date stamp. Please correct it.");
|
||||||
|
else
|
||||||
|
alert("Please enter a valid date stamp first.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Terrible way to accomplish this...
|
||||||
|
for (var j = 0; j < 20; ++j) {
|
||||||
|
if (formData[i]['name'] == "data[Entry]["+j+"][amount]") {
|
||||||
|
var val = formData[i]['value'].replace(/\$/,'');
|
||||||
|
//$("#debug").append('<P>Bad Amount');
|
||||||
|
if (!(val > 0)) {
|
||||||
|
if (formData[i]['value'] == '')
|
||||||
|
alert("Please enter an amount first.");
|
||||||
|
else
|
||||||
|
alert('"'+formData[i]['value']+'"' + " is not valid amount. Please correct it.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//$("#debug").append('OK');
|
||||||
//return false;
|
//return false;
|
||||||
|
|
||||||
$('#response-debug').html('Loading <BLINK>...</BLINK>');
|
$('#results').html('Working <BLINK>...</BLINK>');
|
||||||
$('#output-debug').html('Loading <BLINK>...</BLINK>');
|
|
||||||
|
|
||||||
// here we could return false to prevent the form from being submitted;
|
|
||||||
// returning anything other than false will allow the form submit to continue
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// post-submit callback
|
// post-submit callback
|
||||||
function showResponse(responseText, statusText) {
|
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') {
|
if (statusText == 'success') {
|
||||||
|
var amount = 0;
|
||||||
|
$("input.payment.amount").each(function(i) {
|
||||||
|
amount += $(this).val();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#results').html('<H3>Receipt Saved<BR>' +
|
||||||
|
$("#receipt-customer-name").html() +
|
||||||
|
' : ' + fmtCurrency(amount) +
|
||||||
|
'</H3>');
|
||||||
|
|
||||||
|
if (!$("#repeat").attr("checked")) {
|
||||||
|
window.location.href =
|
||||||
|
"<?php echo $html->url(array('controller' => 'customers',
|
||||||
|
'action' => 'view')); ?>"
|
||||||
|
+ "/" + $("#customer-id").val();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// get a clean slate
|
// get a clean slate
|
||||||
//resetForm();
|
resetForm();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
alert('not successful??');
|
$('#results').html('<H2>Failed to save receipt!</H2>');
|
||||||
|
alert('Failed to save receipt.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$('#response-debug').html('<PRE>'+dump(statusText)+'</PRE>');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the form
|
// Reset the form
|
||||||
@@ -84,33 +121,46 @@ function resetForm() {
|
|||||||
$('#payment-entry-id').val(1);
|
$('#payment-entry-id').val(1);
|
||||||
$('#payments').html('');
|
$('#payments').html('');
|
||||||
|
|
||||||
$("#receipt-customer-id").html("INTERNAL ERROR");
|
|
||||||
$("#receipt-customer-name").html("INTERNAL ERROR");
|
|
||||||
$("#receipt-balance").html("INTERNAL ERROR");
|
|
||||||
$("#receipt-charges-caption").html("Outstanding Charges");
|
|
||||||
|
|
||||||
addPaymentSource(false);
|
addPaymentSource(false);
|
||||||
datepickerNow('TransactionStamp');
|
updateCharges($("#customer-id").val());
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCharges(id) {
|
||||||
|
$('#charge-entries-jqGrid').clearGridData();
|
||||||
|
$("#receipt-balance").html("Calculating...");
|
||||||
|
$("#receipt-charges-caption").html("Please Wait...");
|
||||||
|
|
||||||
|
var filter = new Array();
|
||||||
|
filter['StatementEntry.customer_id'] = id;
|
||||||
|
|
||||||
|
var dynamic_post = new Array();
|
||||||
|
dynamic_post['filter'] = filter;
|
||||||
|
|
||||||
|
$('#charge-entries-jqGrid').setPostDataItem('dynamic_post_replace', serialize(dynamic_post));
|
||||||
|
$('#charge-entries-jqGrid')
|
||||||
|
.setGridParam({ page: 1 })
|
||||||
|
.trigger("reloadGrid");
|
||||||
|
|
||||||
|
var gridstate = $('#charge-entries-jqGrid').getGridParam('gridstate');
|
||||||
|
if (gridstate == 'hidden')
|
||||||
|
$('#charge-entries .HeaderButton').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onGridLoadComplete() {
|
||||||
|
var userdata = $('#charge-entries-jqGrid').getGridParam('userData');
|
||||||
|
$('#receipt-balance').html(fmtCurrency(userdata['balance']));
|
||||||
|
$("#receipt-charges-caption").html("Outstanding Charges");
|
||||||
}
|
}
|
||||||
|
|
||||||
function onRowSelect(grid_id, customer_id) {
|
function onRowSelect(grid_id, customer_id) {
|
||||||
// Set the customer id that will be returned with the form
|
// Set the customer id that will be returned with the form
|
||||||
$("#customer-id").val(customer_id);
|
$("#customer-id").val(customer_id);
|
||||||
|
|
||||||
// Get the item names from the grid
|
// Set the customer name, so the user knows who the receipt is for
|
||||||
//$("#receipt-customer-id").html($(grid_id).getCell(customer_id, 'Customer-id'));
|
$("#receipt-customer-name")
|
||||||
// REVISIT <AP>: 20090708
|
.html('<A HREF="view/' + customer_id + '">'
|
||||||
// This is not intended as a long term solution,
|
+ $(grid_id).getCell(customer_id, 'Customer-name')
|
||||||
// but I need a way to enter data and then view
|
+ '</A>');
|
||||||
// the results. This link will help.
|
|
||||||
$("#receipt-customer-id").html('<A HREF="/pmgr/site/customers/view/' +
|
|
||||||
$(grid_id).getCell(customer_id, 'Customer-id').replace(/^#/,'') +
|
|
||||||
'">' +
|
|
||||||
$(grid_id).getCell(customer_id, 'Customer-id') +
|
|
||||||
'</A>');
|
|
||||||
$("#receipt-customer-name").html($(grid_id).getCell(customer_id, 'Customer-name'));
|
|
||||||
$("#receipt-balance").html("Calculating...");
|
|
||||||
$("#receipt-charges-caption").html("Please Wait...");
|
|
||||||
|
|
||||||
// Hide the "no customer" message and show the current customer
|
// Hide the "no customer" message and show the current customer
|
||||||
$(".customer-selection-invalid").hide();
|
$(".customer-selection-invalid").hide();
|
||||||
@@ -143,7 +193,8 @@ function addPaymentSource(flash) {
|
|||||||
addDiv('payment-entry-id', 'payment', 'payments', flash,
|
addDiv('payment-entry-id', 'payment', 'payments', flash,
|
||||||
// HTML section
|
// HTML section
|
||||||
'<FIELDSET CLASS="payment subset">' +
|
'<FIELDSET CLASS="payment subset">' +
|
||||||
'<LEGEND>Payment #%{id} (%{remove})</LEGEND>' +
|
<?php /* '<LEGEND>Payment #%{id} (%{remove})</LEGEND>' + */ ?>
|
||||||
|
'<LEGEND>Payment</LEGEND>' +
|
||||||
|
|
||||||
'<DIV ID="payment-div-%{id}">' +
|
'<DIV ID="payment-div-%{id}">' +
|
||||||
<?php
|
<?php
|
||||||
@@ -173,7 +224,7 @@ function addPaymentSource(flash) {
|
|||||||
'<DIV ID="payment-amount-div-%{id}" CLASS="input text required">' +
|
'<DIV ID="payment-amount-div-%{id}" CLASS="input text required">' +
|
||||||
' <INPUT TYPE="text" SIZE="20"' +
|
' <INPUT TYPE="text" SIZE="20"' +
|
||||||
' NAME="data[Entry][%{id}][amount]"' +
|
' NAME="data[Entry][%{id}][amount]"' +
|
||||||
' CLASS="payment"' +
|
' CLASS="payment amount"' +
|
||||||
' ID="payment-amount-%{id}" />' +
|
' ID="payment-amount-%{id}" />' +
|
||||||
' <LABEL CLASS="payment" FOR="payment-amount-%{id}">Amount</LABEL>' +
|
' <LABEL CLASS="payment" FOR="payment-amount-%{id}">Amount</LABEL>' +
|
||||||
'</DIV>' +
|
'</DIV>' +
|
||||||
@@ -219,48 +270,20 @@ function addPaymentSource(flash) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function switchPaymentType(paymentid_base, paymentid, radioid) {
|
function switchPaymentType(paymentid_base, paymentid, radioid) {
|
||||||
$("."+paymentid_base+"-"+paymentid).slideUp();
|
|
||||||
var type_id = $("#"+radioid).val();
|
var type_id = $("#"+radioid).val();
|
||||||
|
$("."+paymentid_base+"-"+paymentid+
|
||||||
|
":not(" +
|
||||||
|
"#"+paymentid_base+"-"+paymentid+"-"+type_id +
|
||||||
|
")").slideUp();
|
||||||
$("#"+paymentid_base+"-"+paymentid+"-"+type_id).slideDown();
|
$("#"+paymentid_base+"-"+paymentid+"-"+type_id).slideDown();
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function updateChargesGrid(idlist) {
|
|
||||||
$('#charge-entries-jqGrid').setPostDataItem('idlist', serialize(idlist));
|
|
||||||
$('#charge-entries-jqGrid')
|
|
||||||
.setGridParam({ page: 1 })
|
|
||||||
.trigger("reloadGrid");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateCharges(id) {
|
--></script>
|
||||||
var url = '<?php echo ($html->url(array("controller" => $this->params["controller"],
|
|
||||||
"action" => "unreconciled"))); ?>';
|
|
||||||
url += '/'+id;
|
|
||||||
|
|
||||||
$('#charge-entries-jqGrid').clearGridData();
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
type: "GET",
|
|
||||||
url: url,
|
|
||||||
dataType: "xml",
|
|
||||||
success: function(xml) {
|
|
||||||
var ids = new Array();
|
|
||||||
$('entry',xml).each(function(i){
|
|
||||||
ids.push($(this).attr('id'));
|
|
||||||
});
|
|
||||||
$('#receipt-balance').html(fmtCurrency($('entries',xml).attr('balance')));
|
|
||||||
$("#receipt-charges-caption").html("Outstanding Charges");
|
|
||||||
updateChargesGrid(ids);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
--></script>
|
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
; // align
|
; // align
|
||||||
//echo '<DIV ID="dialog">' . "\n";
|
// Re-Enable warnings
|
||||||
|
Configure::write('debug', $saved_debug_state);
|
||||||
|
|
||||||
echo $this->element('customers', array
|
echo $this->element('customers', array
|
||||||
('config' => array
|
('config' => array
|
||||||
@@ -276,15 +299,15 @@ echo $this->element('customers', array
|
|||||||
array('gridstate' =>
|
array('gridstate' =>
|
||||||
'onGridState("#"+$(this).attr("id"), gridstate)'),
|
'onGridState("#"+$(this).attr("id"), gridstate)'),
|
||||||
),
|
),
|
||||||
|
'action' => 'current',
|
||||||
'nolinks' => true,
|
'nolinks' => true,
|
||||||
'limit' => 10,
|
'limit' => 20,
|
||||||
)));
|
)));
|
||||||
|
|
||||||
echo ('<DIV CLASS="receipt grid-selection-text">' .
|
echo ('<DIV CLASS="receipt grid-selection-text">' .
|
||||||
|
|
||||||
'<DIV CLASS="customer-selection-valid" style="display:none">' .
|
'<DIV CLASS="customer-selection-valid" style="display:none">' .
|
||||||
'Customer <SPAN id="receipt-customer-id"></SPAN>' .
|
'Customer: <SPAN id="receipt-customer-name"></SPAN>' .
|
||||||
': <SPAN id="receipt-customer-name"></SPAN>' .
|
|
||||||
|
|
||||||
/* '<DIV CLASS="supporting">' . */
|
/* '<DIV CLASS="supporting">' . */
|
||||||
/* '<TABLE>' . */
|
/* '<TABLE>' . */
|
||||||
@@ -302,17 +325,19 @@ echo ('<DIV CLASS="receipt grid-selection-text">' .
|
|||||||
|
|
||||||
|
|
||||||
echo $this->element('statement_entries', array
|
echo $this->element('statement_entries', array
|
||||||
(// Element configuration
|
(// Grid configuration
|
||||||
'account_ftype' => 'credit',
|
|
||||||
'limit' => 8,
|
|
||||||
|
|
||||||
// Grid configuration
|
|
||||||
'config' => array
|
'config' => array
|
||||||
(
|
(
|
||||||
'grid_div_id' => 'charge-entries',
|
'grid_div_id' => 'charge-entries',
|
||||||
'grid_div_class' => 'text-below',
|
'grid_div_class' => 'text-below',
|
||||||
|
'grid_events' => array('loadComplete' => 'onGridLoadComplete()'),
|
||||||
|
'grid_setup' => array('hiddengrid' => true),
|
||||||
'caption' => '<SPAN id="receipt-charges-caption"></SPAN>',
|
'caption' => '<SPAN id="receipt-charges-caption"></SPAN>',
|
||||||
'rows' => $charges,
|
'action' => 'unreconciled',
|
||||||
|
'exclude' => array('Customer', 'Type', 'Debit', 'Credit'),
|
||||||
|
'include' => array('Applied', 'Balance'),
|
||||||
|
'remap' => array('Received' => 'Paid'),
|
||||||
|
'limit' => 8,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -351,45 +376,49 @@ echo $this->element('form_table',
|
|||||||
),
|
),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
echo "<BR>\n";
|
||||||
|
echo $form->input('repeat', array('type' => 'checkbox',
|
||||||
|
'id' => 'repeat',
|
||||||
|
'label' => 'Enter Multiple Receipts')) . "\n";
|
||||||
echo $form->submit('Generate Receipt') . "\n";
|
echo $form->submit('Generate Receipt') . "\n";
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
<?php /*
|
||||||
<fieldset CLASS="payment superset">
|
<fieldset CLASS="payment superset">
|
||||||
<legend>Payments</legend>
|
<legend>Payments</legend>
|
||||||
|
*/ ?>
|
||||||
<input type="hidden" id="payment-entry-id" value="0">
|
<input type="hidden" id="payment-entry-id" value="0">
|
||||||
<div id="payments"></div>
|
<div id="payments"></div>
|
||||||
|
<?php /*
|
||||||
<fieldset> <legend>
|
<fieldset> <legend>
|
||||||
<a href="#" onClick="addPaymentSource(true); return false;">Add Another Payment</a>
|
<a href="#" onClick="addPaymentSource(true); return false;">Add Another Payment</a>
|
||||||
</legend> </fieldset>
|
</legend> </fieldset>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
*/ ?>
|
||||||
|
|
||||||
<?php echo $form->end('Generate Receipt'); ?>
|
<?php echo $form->end('Generate Receipt'); ?>
|
||||||
|
|
||||||
<?php /* echo '</DIV>' . "\n"; // End of the dialog DIV */ ?>
|
<?php /* echo '</DIV>' . "\n"; // End of the dialog DIV */ ?>
|
||||||
|
|
||||||
<div><H4>Request</H4><div id="request-debug"></div></div>
|
<div id="results"></div>
|
||||||
<div><H4>Response</H4><div id="response-debug"></div></div>
|
<div id="output-debug" style="display:none"></div>
|
||||||
<div><H4>Output</H4><div id="output-debug"></div></div>
|
|
||||||
|
<?php
|
||||||
|
// Warnings _really_ screw up javascript
|
||||||
|
Configure::write('debug', '0');
|
||||||
|
?>
|
||||||
|
|
||||||
<script type="text/javascript"><!--
|
<script type="text/javascript"><!--
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
$("#TransactionStamp")
|
datepicker('TransactionStamp');
|
||||||
.attr('autocomplete', 'off')
|
|
||||||
.datepicker({ constrainInput: true,
|
|
||||||
numberOfMonths: [1, 1],
|
|
||||||
showCurrentAtPos: 0,
|
|
||||||
dateFormat: 'mm/dd/yy' });
|
|
||||||
|
|
||||||
resetForm();
|
$("#customer-id").val(0);
|
||||||
|
$("#receipt-customer-name").html("INTERNAL ERROR");
|
||||||
|
$("#receipt-balance").html("INTERNAL ERROR");
|
||||||
|
$("#receipt-charges-caption").html("Outstanding Charges");
|
||||||
|
|
||||||
<?php if (isset($customer['id'])): ?>
|
<?php if (isset($customer['id'])): ?>
|
||||||
$("#customer-id").val(<?php echo $customer['id']; ?>);
|
$("#customer-id").val(<?php echo $customer['id']; ?>);
|
||||||
//$("#receipt-customer-id").html("<?php echo '#'.$customer['id']; ?>");
|
|
||||||
$("#receipt-customer-id").html('<A HREF="/pmgr/site/customers/view/' +
|
|
||||||
"<?php echo $customer['id']; ?>" +
|
|
||||||
'">#' +
|
|
||||||
"<?php echo $customer['id']; ?>" +
|
|
||||||
'</A>');
|
|
||||||
$("#receipt-customer-name").html("<?php echo $customer['name']; ?>");
|
$("#receipt-customer-name").html("<?php echo $customer['name']; ?>");
|
||||||
$("#receipt-balance").html(fmtCurrency("<?php echo $stats['balance']; ?>"));
|
$("#receipt-balance").html(fmtCurrency("<?php echo $stats['balance']; ?>"));
|
||||||
onGridState(null, 'hidden');
|
onGridState(null, 'hidden');
|
||||||
@@ -397,37 +426,15 @@ echo $form->submit('Generate Receipt') . "\n";
|
|||||||
onGridState(null, 'visible');
|
onGridState(null, 'visible');
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
resetForm();
|
||||||
|
datepickerNow('TransactionStamp');
|
||||||
|
|
||||||
|
<?php if ($this->params['dev']): ?>
|
||||||
/* $("#dialog").dialog({ */
|
$('#output-debug').html('Post Output');
|
||||||
/* bgiframe: true, */
|
$('#output-debug').show();
|
||||||
/* autoOpen: false, */
|
<?php endif; ?>
|
||||||
/* height: 500, */
|
|
||||||
/* width: 600, */
|
|
||||||
/* modal: true, */
|
|
||||||
/* buttons: { */
|
|
||||||
/* 'Post a Payment': function() { */
|
|
||||||
/* var bValid = true; */
|
|
||||||
/* if (bValid) { */
|
|
||||||
/* $('#debug').append('<H2>POSTED!</H2>'); */
|
|
||||||
/* $(this).dialog('close'); */
|
|
||||||
/* } */
|
|
||||||
/* }, */
|
|
||||||
/* Cancel: function() { */
|
|
||||||
/* $(this).dialog('close'); */
|
|
||||||
/* } */
|
|
||||||
/* }, */
|
|
||||||
/* close: function() { */
|
|
||||||
/* } */
|
|
||||||
/* }); */
|
|
||||||
|
|
||||||
/* $('#post-payment').click(function() { */
|
|
||||||
/* $('#dialog').dialog('open'); */
|
|
||||||
/* }); */
|
|
||||||
|
|
||||||
});
|
});
|
||||||
--></script>
|
--></script>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a href="#" onClick="$('#debug').html(''); return false;">Clear Debug Output</a>
|
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ echo '<div class="customer view">' . "\n";
|
|||||||
|
|
||||||
$rows = array();
|
$rows = array();
|
||||||
$rows[] = array('Name', $customer['Customer']['name']);
|
$rows[] = array('Name', $customer['Customer']['name']);
|
||||||
|
$rows[] = array('Since', FormatHelper::date($since, true));
|
||||||
|
if (!empty($until))
|
||||||
|
$rows[] = array('Until', FormatHelper::date($until, true));
|
||||||
$rows[] = array('Comment', $customer['Customer']['comment']);
|
$rows[] = array('Comment', $customer['Customer']['comment']);
|
||||||
|
|
||||||
echo $this->element('table',
|
echo $this->element('table',
|
||||||
@@ -27,7 +30,9 @@ echo $this->element('table',
|
|||||||
echo '<div class="infobox">' . "\n";
|
echo '<div class="infobox">' . "\n";
|
||||||
$rows = array();
|
$rows = array();
|
||||||
$rows[] = array('Security Deposit:', FormatHelper::currency($outstandingDeposit));
|
$rows[] = array('Security Deposit:', FormatHelper::currency($outstandingDeposit));
|
||||||
$rows[] = array('Balance:', FormatHelper::currency($outstandingBalance));
|
//$rows[] = array('Charges:', FormatHelper::currency($stats['charges']));
|
||||||
|
//$rows[] = array('Payments:', FormatHelper::currency($stats['disbursements']));
|
||||||
|
$rows[] = array('Balance Owed:', FormatHelper::currency($outstandingBalance));
|
||||||
echo $this->element('table',
|
echo $this->element('table',
|
||||||
array('class' => 'summary',
|
array('class' => 'summary',
|
||||||
'rows' => $rows,
|
'rows' => $rows,
|
||||||
@@ -48,18 +53,79 @@ echo '<div CLASS="detail supporting">' . "\n";
|
|||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* Contacts
|
* Unpaid Charges
|
||||||
*/
|
*/
|
||||||
|
|
||||||
echo $this->element('contacts', array
|
echo $this->element('statement_entries', array
|
||||||
(// Grid configuration
|
(// Grid configuration
|
||||||
'config' => array
|
'config' => array
|
||||||
('caption' => 'Customer Contacts',
|
('caption' => 'Outstanding Charges',
|
||||||
'filter' => array('Customer.id' => $customer['Customer']['id']),
|
'limit' => 10,
|
||||||
'include' => array('Type', 'Active'),
|
'action' => 'unreconciled',
|
||||||
|
'filter' => array('StatementEntry.customer_id' => $customer['Customer']['id']),
|
||||||
|
'exclude' => array('Customer'),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Customer Credits
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo $this->element('statement_entries', array
|
||||||
|
(// Grid configuration
|
||||||
|
'config' => array
|
||||||
|
('caption' => 'Oustanding Credits',
|
||||||
|
'grid_div_id' => 'surplus',
|
||||||
|
'limit' => 10,
|
||||||
|
'filter' => array('Customer.id' => $customer['Customer']['id'],
|
||||||
|
'StatementEntry.type' => 'SURPLUS'),
|
||||||
|
'exclude' => array('Entry', 'Effective', 'Customer', 'Unit', 'Account', 'Debit', 'Credit'),
|
||||||
|
'include' => array('Transaction', 'Amount'),
|
||||||
|
'remap' => array('Transaction' => 'Receipt'),
|
||||||
|
)));
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Receipt History
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo $this->element('ledger_entries', array
|
||||||
|
(// Grid configuration
|
||||||
|
'config' => array
|
||||||
|
('caption' => 'Receipts',
|
||||||
|
'limit' => 5,
|
||||||
|
'filter' => array('Customer.id' => $customer['Customer']['id'],
|
||||||
|
'Transaction.type' => 'RECEIPT',
|
||||||
|
'Tender.id !=' => null,
|
||||||
|
//'Account.id !=' => '-AR-'
|
||||||
|
),
|
||||||
|
'include' => array('Transaction'),
|
||||||
|
'exclude' => array('Entry', 'Account', 'Cr/Dr'),
|
||||||
|
'remap' => array('Transaction' => 'Receipt'),
|
||||||
|
)));
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Invoice History
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* NOT COMPLETED
|
||||||
|
echo $this->element('transactions', array
|
||||||
|
(// Grid configuration
|
||||||
|
'config' => array
|
||||||
|
('caption' => 'Invoices',
|
||||||
|
'limit' => 5,
|
||||||
|
'filter' => array('Customer.id' => $customer['Customer']['id'],
|
||||||
|
'Transaction.type' => 'INVOICE',
|
||||||
|
),
|
||||||
|
//'include' => array(),
|
||||||
|
'exclude' => array('Type'),
|
||||||
|
'remap' => array('ID' => 'Invoice',
|
||||||
|
//'Timestamp' => 'Date',
|
||||||
|
'Entries' => 'Charges'),
|
||||||
|
)));
|
||||||
|
NOT COMPLETED */
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* Lease History
|
* Lease History
|
||||||
*/
|
*/
|
||||||
@@ -68,50 +134,66 @@ echo $this->element('leases', array
|
|||||||
(// Grid configuration
|
(// Grid configuration
|
||||||
'config' => array
|
'config' => array
|
||||||
('caption' => 'Lease History',
|
('caption' => 'Lease History',
|
||||||
'filter' => array('Customer.id' => $customer['Customer']['id']),
|
'limit' => 5,
|
||||||
|
'filter' => array('Customer.id' => $customer['Customer']['id']),
|
||||||
'exclude' => array('Customer'),
|
'exclude' => array('Customer'),
|
||||||
|
'sort_column' => 'Move-In',
|
||||||
|
'sort_order' => 'DESC',
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* Customer Account History
|
* Contacts
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo $this->element('contacts', array
|
||||||
|
(// Grid configuration
|
||||||
|
'config' => array
|
||||||
|
('caption' => 'Customer Contacts',
|
||||||
|
'limit' => 5,
|
||||||
|
'filter' => array('Customer.id' => $customer['Customer']['id']),
|
||||||
|
'include' => array('Relationship'),
|
||||||
|
)));
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Customer Statement History
|
||||||
*/
|
*/
|
||||||
|
|
||||||
echo $this->element('statement_entries', array
|
echo $this->element('statement_entries', array
|
||||||
(// Grid configuration
|
(// Grid configuration
|
||||||
'config' => array
|
'config' => array
|
||||||
('caption' => 'Account',
|
('caption' => 'Customer Statement',
|
||||||
|
'grid_setup' => array('hiddengrid' => true),
|
||||||
'filter' => array('Customer.id' => $customer['Customer']['id'],
|
'filter' => array('Customer.id' => $customer['Customer']['id'],
|
||||||
'type !=' => 'VOID'),
|
'type !=' => 'VOID'),
|
||||||
|
//'include' => array('Sub-Total'),
|
||||||
'exclude' => array('Customer'),
|
'exclude' => array('Customer'),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* Customer Ledger History
|
* Customer Transaction History
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
echo $this->element('transactions', array
|
||||||
* REVISIT <AP>: 20090724
|
|
||||||
* It's not my intention to really include this, as I believe it
|
|
||||||
* just will confuse folks. However, I've added it at the moment
|
|
||||||
* to help me see the picture of what's happening. It may prove
|
|
||||||
* useful with respect to identifying pre-payments, so after using
|
|
||||||
* it for a while, maybe we can get a feeling for that. I suspect
|
|
||||||
* it will be MUCH more useful just to add the pre-pay amount to
|
|
||||||
* the info box, or provide a list of ledger entries that are JUST
|
|
||||||
* pre-payments. We'll see...
|
|
||||||
*/
|
|
||||||
echo $this->element('ledger_entries', array
|
|
||||||
(// Grid configuration
|
(// Grid configuration
|
||||||
'config' => array
|
'config' => array
|
||||||
('caption' => 'Ledger Entries',
|
('caption' => 'Balance History',
|
||||||
'filter' => array('Customer.id' => $customer['Customer']['id'],
|
'limit' => 10000,
|
||||||
'Account.id !=' => '-AR-'),
|
'limitOptions' => array('10000'),
|
||||||
'exclude' => array('Customer'),
|
'sort_column' => 'Timestamp',
|
||||||
|
'sort_order' => 'ASC',
|
||||||
|
'grid_setup' => array('hiddengrid' => true),
|
||||||
|
'filter' => array('Customer.id' => $customer['Customer']['id']),
|
||||||
|
'include' => array('Comment', 'PosNeg', 'Balance'),
|
||||||
|
'exclude' => array('Amount', 'Entries'),
|
||||||
|
'remap' => array(//'ID' => 'Invoice',
|
||||||
|
'PosNeg' => 'Amount',
|
||||||
|
//'Entries' => 'Charges',
|
||||||
|
),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
|
||||||
/* End "detail supporting" div */
|
/* End "detail supporting" div */
|
||||||
echo '</div>' . "\n";
|
echo '</div>' . "\n";
|
||||||
|
|
||||||
|
|||||||
@@ -1,50 +1,17 @@
|
|||||||
<?php /* -*- mode:PHP -*- */
|
<?php /* -*- mode:PHP -*- */
|
||||||
|
|
||||||
echo '<div class="ledger-entry view">' . "\n";
|
echo '<div class="double-entry view">' . "\n";
|
||||||
|
|
||||||
// The two entry ids, debit and credit, are actually individual
|
// The two entries, debit and credit, are actually individual
|
||||||
// entries in separate accounts (each make up one of the two
|
// entries in separate accounts (each make up one of the two
|
||||||
// entries required for "double entry"). This, when we provide
|
// entries required for "double entry").
|
||||||
// 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.
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
* LedgerEntry Detail Main Section
|
* DoubleEntry Detail Main Section
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$transaction = $entry['Transaction'];
|
$transaction = $entry['Transaction'];
|
||||||
@@ -52,92 +19,61 @@ $ledgers = array('debit' => $entry['DebitLedger'],
|
|||||||
'credit' => $entry['CreditLedger']);
|
'credit' => $entry['CreditLedger']);
|
||||||
$entries = array('debit' => $entry['DebitEntry'],
|
$entries = array('debit' => $entry['DebitEntry'],
|
||||||
'credit' => $entry['CreditEntry']);
|
'credit' => $entry['CreditEntry']);
|
||||||
$customer = $entry['Customer'];
|
|
||||||
$lease = $entry['Lease'];
|
|
||||||
$entry = $entry['DoubleEntry'];
|
$entry = $entry['DoubleEntry'];
|
||||||
|
|
||||||
$rows = array();
|
$rows = array();
|
||||||
$rows[] = array('ID', $entry['id']);
|
|
||||||
$rows[] = array('Transaction', $html->link('#'.$transaction['id'],
|
$rows[] = array('Transaction', $html->link('#'.$transaction['id'],
|
||||||
array('controller' => 'transactions',
|
array('controller' => 'transactions',
|
||||||
'action' => 'view',
|
'action' => 'view',
|
||||||
$transaction['id'])));
|
$transaction['id'])));
|
||||||
$rows[] = array('Timestamp', FormatHelper::datetime($transaction['stamp']));
|
$rows[] = array('Timestamp', FormatHelper::datetime($transaction['stamp']));
|
||||||
$rows[] = array('Effective', FormatHelper::date($entry['effective_date']));
|
$rows[] = array('Comment', $entry['comment']);
|
||||||
//$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('Comment', $entry['comment']);
|
|
||||||
|
|
||||||
echo $this->element('table',
|
echo $this->element('table',
|
||||||
array('class' => 'item ledger-entry detail',
|
array('class' => 'item double-entry detail',
|
||||||
'caption' => 'Double Ledger Entry Detail',
|
'caption' => 'Double Ledger Entry',
|
||||||
'rows' => $rows,
|
'rows' => $rows,
|
||||||
'column_class' => array('field', 'value')));
|
'column_class' => array('field', 'value')));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* LedgerEntry Info Box
|
* Debit/Credit Entries
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* echo '<div class="infobox">' . "\n"; */
|
|
||||||
/* foreach ($ledgers AS $type => $ledger) { */
|
|
||||||
/* //pr($ledger); */
|
|
||||||
/* if (!$ledger['Account']['trackable']) */
|
|
||||||
/* continue; */
|
|
||||||
|
|
||||||
/* $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 '</div>' . "\n"; */
|
|
||||||
|
|
||||||
echo ('<DIV CLASS="ledger-double-entry">' . "\n");
|
echo ('<DIV CLASS="ledger-double-entry">' . "\n");
|
||||||
foreach ($ledgers AS $type => $ledger) {
|
foreach ($ledgers AS $type => $ledger) {
|
||||||
$rows = array();
|
$rows = array();
|
||||||
|
|
||||||
$rows[] = array('ID', $html->link('#' . $entries[$type]['id'],
|
// REVISIT <AP>: 20090816
|
||||||
array('controller' => 'entries',
|
// Due to low priority, the ledger_entry/double_entry stuff
|
||||||
'action' => 'view',
|
// is a bit piecemeal at the moment (trying to reuse old
|
||||||
$entries[$type]['id'])));
|
// code as much as possible). So, LedgerEntry view is just
|
||||||
$rows[] = array('Account', $html->link($ledger['Account']['name'],
|
// redirecting here. Of course, presenting a link for the
|
||||||
array('controller' => 'accounts',
|
// LedgerEntry then is, well, quite pointless.
|
||||||
'action' => 'view',
|
$rows[] = array('ID', '#' . $entries[$type]['id']);
|
||||||
$ledger['Account']['id'])));
|
/* $rows[] = array('ID', $html->link('#' . $entries[$type]['id'], */
|
||||||
$rows[] = array('Ledger', $html->link('#' . $ledger['Account']['id']
|
/* array('controller' => 'entries', */
|
||||||
. '-' . $ledger['sequence'],
|
/* 'action' => 'view', */
|
||||||
array('controller' => 'ledgers',
|
/* $entries[$type]['id']))); */
|
||||||
'action' => 'view',
|
$rows[] = array('Account', ($ledger['link']
|
||||||
$ledger['id'])));
|
? $html->link($ledger['Account']['name'],
|
||||||
$rows[] = array('Amount', FormatHelper::currency($entry['amount']));
|
array('controller' => 'accounts',
|
||||||
$rows[] = array('Effect', $ledger['Account']['ftype'] == $type ? 'INCREASE' : 'DECREASE');
|
'action' => 'view',
|
||||||
|
$ledger['Account']['id']))
|
||||||
|
: $ledger['Account']['name']));
|
||||||
|
$rows[] = array('Ledger', ($ledger['link']
|
||||||
|
? $html->link('#' . $ledger['sequence'],
|
||||||
|
array('controller' => 'ledgers',
|
||||||
|
'action' => 'view',
|
||||||
|
$ledger['id']))
|
||||||
|
: '#' . $ledger['sequence']));
|
||||||
|
$rows[] = array('Amount', FormatHelper::currency($entries[$type]['amount']));
|
||||||
|
//$rows[] = array('Effect', $ledger['Account']['ftype'] == $type ? 'INCREASE' : 'DECREASE');
|
||||||
|
|
||||||
echo $this->element('table',
|
echo $this->element('table',
|
||||||
array('class' => array('item', $type, 'detail'),
|
array('class' => array('item', $type, 'detail'),
|
||||||
'caption' => ucfirst($type) . ' Ledger Entry',
|
'caption' => ucfirst($type) . ' Entry',
|
||||||
'rows' => $rows,
|
'rows' => $rows,
|
||||||
'column_class' => array('field', 'value')));
|
'column_class' => array('field', 'value')));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
// Define the table columns
|
// Define the table columns
|
||||||
$cols = array();
|
$cols = array();
|
||||||
$cols['ID'] = array('index' => 'Account.id', 'formatter' => 'id');
|
|
||||||
$cols['Name'] = array('index' => 'Account.name', 'formatter' => 'longname');
|
$cols['Name'] = array('index' => 'Account.name', 'formatter' => 'longname');
|
||||||
$cols['Type'] = array('index' => 'Account.type', 'formatter' => 'enum');
|
$cols['Type'] = array('index' => 'Account.type', 'formatter' => 'enum');
|
||||||
$cols['Entries'] = array('index' => 'entries', 'formatter' => 'number');
|
$cols['Entries'] = array('index' => 'entries', 'formatter' => 'number');
|
||||||
@@ -15,7 +14,7 @@ $cols['Comment'] = array('index' => 'Account.comment', 'formatter' => 'comment
|
|||||||
$grid
|
$grid
|
||||||
->columns($cols)
|
->columns($cols)
|
||||||
->sortField('Name')
|
->sortField('Name')
|
||||||
->defaultFields(array('ID', 'Name'))
|
->defaultFields(array('Name'))
|
||||||
->searchFields(array('Name'))
|
->searchFields(array('Name'))
|
||||||
->render($this, isset($config) ? $config : null,
|
->render($this, isset($config) ? $config : null,
|
||||||
array_diff(array_keys($cols), array('Comment')));
|
array_diff(array_keys($cols), array('Comment')));
|
||||||
|
|||||||
@@ -2,19 +2,19 @@
|
|||||||
|
|
||||||
// Define the table columns
|
// Define the table columns
|
||||||
$cols = array();
|
$cols = array();
|
||||||
$cols['ID'] = array('index' => 'Contact.id', 'formatter' => 'id');
|
$cols['Relationship'] = array('index' => 'ContactsCustomer.type', 'formatter' => 'enum');
|
||||||
$cols['Last Name'] = array('index' => 'Contact.last_name', 'formatter' => 'name');
|
$cols['Name'] = array('index' => 'Contact.display_name', 'formatter' => 'longname');
|
||||||
$cols['First Name'] = array('index' => 'Contact.first_name', 'formatter' => 'name');
|
$cols['Last Name'] = array('index' => 'Contact.last_name', 'formatter' => 'name');
|
||||||
$cols['Company'] = array('index' => 'Contact.company_name', 'formatter' => 'longname');
|
$cols['First Name'] = array('index' => 'Contact.first_name', 'formatter' => 'name');
|
||||||
$cols['Type'] = array('index' => 'ContactsCustomer.type', 'formatter' => 'enum');
|
$cols['License'] = array('index' => 'Contact.id_local', 'formatter' => 'name');
|
||||||
$cols['Active'] = array('index' => 'ContactsCustomer.active', 'formatter' => 'enum');
|
$cols['Company'] = array('index' => 'Contact.company_name', 'formatter' => 'longname');
|
||||||
$cols['Comment'] = array('index' => 'Contact.comment', 'formatter' => 'comment');
|
$cols['Comment'] = array('index' => 'Contact.comment', 'formatter' => 'comment');
|
||||||
|
|
||||||
// Render the grid
|
// Render the grid
|
||||||
$grid
|
$grid
|
||||||
->columns($cols)
|
->columns($cols)
|
||||||
->sortField('Last Name')
|
->sortField('Last Name')
|
||||||
->defaultFields(array('ID', 'Last Name', 'First Name'))
|
->defaultFields(array('Last Name', 'First Name'))
|
||||||
->searchFields(array('Last Name', 'First Name', 'Company'))
|
->searchFields(array('Last Name', 'First Name', 'Company'))
|
||||||
->render($this, isset($config) ? $config : null,
|
->render($this, isset($config) ? $config : null,
|
||||||
array_diff(array_keys($cols), array('Type', 'Active', 'Comment')));
|
array_diff(array_keys($cols), array('Relationship', 'License', 'Comment')));
|
||||||
|
|||||||
@@ -2,25 +2,22 @@
|
|||||||
|
|
||||||
// Define the table columns
|
// Define the table columns
|
||||||
$cols = array();
|
$cols = array();
|
||||||
$cols['ID'] = array('index' => 'Customer.id', 'formatter' => 'id');
|
$cols['Customer'] = array('index' => 'Customer.id', 'formatter' => 'id');
|
||||||
$cols['Relationship'] = array('index' => 'ContactsCustomer.type', 'formatter' => 'enum');
|
$cols['Relationship'] = array('index' => 'ContactsCustomer.type', 'formatter' => 'enum');
|
||||||
$cols['Name'] = array('index' => 'Customer.name', 'formatter' => 'longname');
|
$cols['Name'] = array('index' => 'Customer.name', 'formatter' => 'longname');
|
||||||
$cols['Last Name'] = array('index' => 'PrimaryContact.last_name', 'formatter' => 'name');
|
$cols['Last Name'] = array('index' => 'PrimaryContact.last_name', 'formatter' => 'name');
|
||||||
$cols['First Name'] = array('index' => 'PrimaryContact.first_name', 'formatter' => 'name');
|
$cols['First Name'] = array('index' => 'PrimaryContact.first_name', 'formatter' => 'name');
|
||||||
|
$cols['Units'] = array('index' => 'current_lease_count', 'formatter' => 'number');
|
||||||
|
$cols['Past Leases'] = array('index' => 'past_lease_count', 'formatter' => 'number');
|
||||||
$cols['Leases'] = array('index' => 'lease_count', 'formatter' => 'number');
|
$cols['Leases'] = array('index' => 'lease_count', 'formatter' => 'number');
|
||||||
$cols['Balance'] = array('index' => 'balance', 'formatter' => 'currency');
|
$cols['Balance'] = array('index' => 'balance', 'formatter' => 'currency');
|
||||||
$cols['Comment'] = array('index' => 'Customer.comment', 'formatter' => 'comment');
|
$cols['Comment'] = array('index' => 'Customer.comment', 'formatter' => 'comment');
|
||||||
|
|
||||||
|
|
||||||
// Certain fields are only valid with a particular context
|
|
||||||
if (!isset($config['filter']['Contact.id']))
|
|
||||||
$grid->invalidFields('Relationship');
|
|
||||||
|
|
||||||
// Render the grid
|
// Render the grid
|
||||||
$grid
|
$grid
|
||||||
->columns($cols)
|
->columns($cols)
|
||||||
->sortField('Name')
|
->sortField('Name')
|
||||||
->defaultFields(array('ID', 'Name'))
|
->defaultFields(array('Name'))
|
||||||
->searchFields(array('Name', 'Last Name', 'First Name'))
|
->searchFields(array('Name', 'Last Name', 'First Name'))
|
||||||
->render($this, isset($config) ? $config : null,
|
->render($this, isset($config) ? $config : null,
|
||||||
array_diff(array_keys($cols), array('Comment')));
|
array_diff(array_keys($cols), array('Relationship', 'Past Leases', 'Comment')));
|
||||||
|
|||||||
@@ -1,116 +0,0 @@
|
|||||||
<?php /* -*- mode:PHP -*- */
|
|
||||||
|
|
||||||
// Define the table columns
|
|
||||||
$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['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['Debit Account'] = array('index' => 'DebitAccount.name', 'formatter' => 'name');
|
|
||||||
$cols['Credit Account'] = array('index' => 'CreditAccount.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['Amount'] = array('index' => 'LedgerEntry.amount', 'formatter' => 'currency');
|
|
||||||
$cols['Debit'] = array('index' => 'debit', 'formatter' => 'currency');
|
|
||||||
$cols['Credit'] = array('index' => 'credit', 'formatter' => 'currency');
|
|
||||||
|
|
||||||
$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);
|
|
||||||
|
|
||||||
|
|
||||||
if (isset($transaction_id) || isset($reconcile_id))
|
|
||||||
$grid->invalidFields('Transaction');
|
|
||||||
|
|
||||||
if (!isset($collected_account_id))
|
|
||||||
$grid->invalidFields('Last Payment');
|
|
||||||
|
|
||||||
if (isset($account_ftype) || isset($ledger_id) || isset($account_id) || isset($ar_account) || isset($customer_id))
|
|
||||||
$grid->invalidFields(array('Debit Account', 'Credit Account'));
|
|
||||||
else
|
|
||||||
$grid->invalidFields('Account');
|
|
||||||
|
|
||||||
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) || isset($customer_id)) {
|
|
||||||
$grid->invalidFields('Amount');
|
|
||||||
$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.
|
|
||||||
if (isset($lease_id) || isset($customer_id))
|
|
||||||
$grid->invalidFields(array('Customer'));
|
|
||||||
|
|
||||||
if (isset($lease_id) || $group_by_tx)
|
|
||||||
$grid->invalidFields(array('Lease', 'Unit'));
|
|
||||||
|
|
||||||
if (!isset($reconcile_id) && !isset($collected_account_id))
|
|
||||||
$grid->invalidFields('Applied');
|
|
||||||
else
|
|
||||||
$cols['Sub-Total']['index'] = 'subtotal-applied';
|
|
||||||
|
|
||||||
if (isset($account_ftype) || isset($collected_account_id))
|
|
||||||
$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';
|
|
||||||
$grid->limit(50);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($reconcile_id)) {
|
|
||||||
$config['action'] = 'reconcile';
|
|
||||||
$grid->customData(compact('reconcile_id'))->limit(20);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($collected_account_id)) {
|
|
||||||
$config['action'] = 'collected';
|
|
||||||
$account_id = $collected_account_id;
|
|
||||||
$grid->limit(50);
|
|
||||||
$grid->sortField('Last Payment');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($entry_ids))
|
|
||||||
$grid->id_list($entry_ids);
|
|
||||||
|
|
||||||
// Set up search fields if requested by caller
|
|
||||||
if (isset($searchfields))
|
|
||||||
$grid->searchFields(array('Customer', 'Unit'));
|
|
||||||
|
|
||||||
// Include custom data
|
|
||||||
$grid->customData(compact('ledger_id', 'account_id', 'ar_account',
|
|
||||||
'account_type', 'account_ftype', 'monetary_source_id',
|
|
||||||
'customer_id', 'lease_id', 'transaction_id', 'group_by_tx'));
|
|
||||||
|
|
||||||
// Render the grid
|
|
||||||
$grid
|
|
||||||
->render($this, isset($config) ? $config : null,
|
|
||||||
array('Transaction', 'Entry', 'Date', 'Effective', 'Last Payment',
|
|
||||||
'Account', 'Debit Account', 'Credit Account',
|
|
||||||
'Customer', 'Unit',
|
|
||||||
'Comment',
|
|
||||||
'Amount', 'Debit', 'Credit',
|
|
||||||
'Applied', 'Sub-Total')
|
|
||||||
);
|
|
||||||
@@ -32,8 +32,8 @@ foreach ($fields AS $field => $config) {
|
|||||||
$include_after = true;
|
$include_after = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (empty($column_class))
|
||||||
$column_class = array();
|
$column_class = array();
|
||||||
if ($include_before)
|
if ($include_before)
|
||||||
$column_class[] = 'before';
|
$column_class[] = 'before';
|
||||||
$column_class[] = 'field';
|
$column_class[] = 'field';
|
||||||
@@ -79,7 +79,13 @@ foreach ($fields AS $field => $config) {
|
|||||||
$cells[] = null;
|
$cells[] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$name = $config['name'];
|
if (empty($config['opts']['label']))
|
||||||
|
$name = $form->label($field, $config['name'],
|
||||||
|
empty($config['label_attributes'])
|
||||||
|
? null : $config['label_attributes']);
|
||||||
|
else
|
||||||
|
$name = $config['name'];
|
||||||
|
|
||||||
if (isset($config['with_name_before']))
|
if (isset($config['with_name_before']))
|
||||||
$name = $config['with_name_before'] . $name;
|
$name = $config['with_name_before'] . $name;
|
||||||
elseif (isset($with_name_before))
|
elseif (isset($with_name_before))
|
||||||
@@ -107,7 +113,7 @@ foreach ($fields AS $field => $config) {
|
|||||||
if (isset($config['with_value_after']))
|
if (isset($config['with_value_after']))
|
||||||
$value = $value . $config['with_value_after'];
|
$value = $value . $config['with_value_after'];
|
||||||
elseif (isset($with_value_after))
|
elseif (isset($with_value_after))
|
||||||
$value = $valeu . $with_value_after;
|
$value = $value . $with_value_after;
|
||||||
$cells[] = $value;
|
$cells[] = $value;
|
||||||
|
|
||||||
if ($include_after) {
|
if ($include_after) {
|
||||||
@@ -123,7 +129,7 @@ foreach ($fields AS $field => $config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
echo $this->element('table',
|
echo $this->element('table',
|
||||||
compact('class', 'caption', 'headers',
|
compact('id', 'class', 'caption', 'headers',
|
||||||
'rows', 'row_class', 'suppress_alternate_rows',
|
'rows', 'row_class', 'suppress_alternate_rows',
|
||||||
'column_class')
|
'column_class')
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ if (!isset($limitOptions)) {
|
|||||||
}
|
}
|
||||||
sort($limitOptions, SORT_NUMERIC);
|
sort($limitOptions, SORT_NUMERIC);
|
||||||
$limitOptions = array_unique($limitOptions, SORT_NUMERIC);
|
$limitOptions = array_unique($limitOptions, SORT_NUMERIC);
|
||||||
|
//$limitOptions[] = 'ALL'; // Would be nice... jqGrid shows 'NaN of NaN'
|
||||||
|
|
||||||
if (!isset($height))
|
if (!isset($height))
|
||||||
$height = 'auto';
|
$height = 'auto';
|
||||||
@@ -46,12 +47,10 @@ if (!isset($grid_setup))
|
|||||||
$grid_setup = array();
|
$grid_setup = array();
|
||||||
|
|
||||||
// Do some prework to bring in the appropriate libraries
|
// Do some prework to bring in the appropriate libraries
|
||||||
$imgpath = '/pmgr/site/css/jqGrid/basic/images';
|
$html->css('ui.jqgrid', null, null, false);
|
||||||
$html->css('jqGrid/basic/grid', null, null, false);
|
$javascript->link('jqGrid/grid.locale-en', false);
|
||||||
$html->css('jqGrid/jqModal', null, null, false);
|
$javascript->link('jqGrid/jquery.jqGrid.min', false);
|
||||||
$javascript->link('jqGrid/jquery.jqGrid.js', false);
|
$javascript->link('jqGrid/grid.postext', false);
|
||||||
$javascript->link('jqGrid/js/jqModal', false);
|
|
||||||
$javascript->link('jqGrid/js/jqDnR', false);
|
|
||||||
$javascript->link('pmgr_jqGrid', false);
|
$javascript->link('pmgr_jqGrid', false);
|
||||||
|
|
||||||
|
|
||||||
@@ -63,7 +62,6 @@ $javascript->link('pmgr_jqGrid', false);
|
|||||||
// as part of the data fetch.
|
// as part of the data fetch.
|
||||||
$url = $html->url(array('controller' => $controller,
|
$url = $html->url(array('controller' => $controller,
|
||||||
'action' => 'gridData',
|
'action' => 'gridData',
|
||||||
'debug' => 0,
|
|
||||||
));
|
));
|
||||||
|
|
||||||
// Create extra parameters that jqGrid will pass to our
|
// Create extra parameters that jqGrid will pass to our
|
||||||
@@ -124,15 +122,20 @@ foreach ($jqGridColumns AS $header => &$col) {
|
|||||||
// No special formatting for number
|
// No special formatting for number
|
||||||
unset($col['formatter']);
|
unset($col['formatter']);
|
||||||
}
|
}
|
||||||
|
elseif ($col['formatter'] === 'percentage') {
|
||||||
|
$col['formatter'] = array('--special' => 'percentageFormatter');
|
||||||
|
$default['width'] = 60;
|
||||||
|
$default['align'] = 'right';
|
||||||
|
}
|
||||||
elseif ($col['formatter'] === 'currency') {
|
elseif ($col['formatter'] === 'currency') {
|
||||||
// Use our custom formatting for currency
|
// Use our custom formatting for currency
|
||||||
$col['formatter'] = array('--special' => 'currencyFormatter');
|
$col['formatter'] = array('--special' => 'currencyFormatter');
|
||||||
$default['width'] = 85;
|
$default['width'] = 65;
|
||||||
$default['align'] = 'right';
|
$default['align'] = 'right';
|
||||||
}
|
}
|
||||||
elseif ($col['formatter'] === 'date') {
|
elseif ($col['formatter'] === 'date') {
|
||||||
$default['formatoptions'] = array('newformat' => 'm/d/Y');
|
$default['formatoptions'] = array('newformat' => 'm/d/Y');
|
||||||
$default['width'] = 95;
|
$default['width'] = 90;
|
||||||
$default['align'] = 'center';
|
$default['align'] = 'center';
|
||||||
}
|
}
|
||||||
elseif (preg_match("/^(long|short)?name$/",
|
elseif (preg_match("/^(long|short)?name$/",
|
||||||
@@ -146,8 +149,14 @@ foreach ($jqGridColumns AS $header => &$col) {
|
|||||||
// No special formatting for name
|
// No special formatting for name
|
||||||
unset($col['formatter']);
|
unset($col['formatter']);
|
||||||
}
|
}
|
||||||
elseif ($col['formatter'] === 'enum') {
|
elseif (preg_match("/^(long|short)?enum$/",
|
||||||
|
$col['formatter'], $matches)) {
|
||||||
$default['width'] = 60;
|
$default['width'] = 60;
|
||||||
|
if (!empty($matches[1]) && $matches[1] === 'long')
|
||||||
|
$default['width'] *= 1.5;
|
||||||
|
if (!empty($matches[1]) && $matches[1] === 'short')
|
||||||
|
$default['width'] *= 0.7;
|
||||||
|
|
||||||
//$default['align'] = 'right';
|
//$default['align'] = 'right';
|
||||||
|
|
||||||
// No special formatting for enum
|
// No special formatting for enum
|
||||||
@@ -164,7 +173,8 @@ foreach ($jqGridColumns AS $header => &$col) {
|
|||||||
|
|
||||||
// Just a rough approximation to ensure columns
|
// Just a rough approximation to ensure columns
|
||||||
// are wide enough to fully display their header.
|
// are wide enough to fully display their header.
|
||||||
$min_width = strlen($header) * 10;
|
$min_width = strlen($header) * 7;
|
||||||
|
$min_width = 0; // REVISIT <AP>: 20090829; if/while jqGrid is fixed width
|
||||||
if ((!isset($default['width']) || $default['width'] < $min_width) && !$default['force'])
|
if ((!isset($default['width']) || $default['width'] < $min_width) && !$default['force'])
|
||||||
$default['width'] = $min_width;
|
$default['width'] = $min_width;
|
||||||
}
|
}
|
||||||
@@ -188,9 +198,12 @@ if (isset($sort_order)) {
|
|||||||
$sortorder = 'ASC';
|
$sortorder = 'ASC';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (1) { // debug
|
$debug = !empty($this->params['dev']);
|
||||||
|
if ($debug)
|
||||||
$caption .= '<span class="debug grid-query"> :: <span id="'.$grid_id.'-query"></span></span>';
|
$caption .= '<span class="debug grid-query"> :: <span id="'.$grid_id.'-query"></span></span>';
|
||||||
}
|
|
||||||
|
$caption .= ('<span class="grid-error" id="'.$grid_id.'-error"' .
|
||||||
|
' style="display:none"> :: Error (Please Reload)</span>');
|
||||||
|
|
||||||
foreach (array_merge(array('loadComplete' => '', 'loadError' => ''),
|
foreach (array_merge(array('loadComplete' => '', 'loadError' => ''),
|
||||||
$grid_events) AS $event => $statement) {
|
$grid_events) AS $event => $statement) {
|
||||||
@@ -200,13 +213,21 @@ foreach (array_merge(array('loadComplete' => '', 'loadError' => ''),
|
|||||||
$statement = current($statement);
|
$statement = current($statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($event == 'loadComplete') {
|
if ($event == 'loadComplete' && $debug) {
|
||||||
$grid_events[$event] =
|
$grid_events[$event] =
|
||||||
array('--special' => "function($params) {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('<A HREF=\"'+url+'\">Grid Query</A><BR>'); $statement;}");
|
array('--special' => "function($params) {url=jQuery('#{$grid_id}').getGridParam('url');url=url+'/debug:1?'; pd=jQuery('#{$grid_id}').getPostData();$.each(pd,function(i){ url+=i+'='+escape(pd[i])+'&'; }); jQuery('#{$grid_id}-query').html('<A HREF=\"'+url+'\">Grid Query</A><BR>'); $statement;}");
|
||||||
}
|
}
|
||||||
elseif ($event == 'loadError') {
|
elseif ($event == 'loadError' && $debug) {
|
||||||
$grid_events[$event] =
|
$grid_events[$event] =
|
||||||
array('--special' => "function($params) {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('<A HREF=\"'+url+'\">Grid Error Query</A><BR>'); $statement;}");
|
array('--special' => "function($params) {url=jQuery('#{$grid_id}').getGridParam('url');url=url+'/debug:1?'; pd=jQuery('#{$grid_id}').getPostData();$.each(pd,function(i){ url+=i+'='+escape(pd[i])+'&'; }); jQuery('#{$grid_id}-query').html('<A HREF=\"'+url+'\">Grid Error Query</A><BR>'); $statement;}");
|
||||||
|
}
|
||||||
|
elseif ($event == 'loadComplete' && !$debug) {
|
||||||
|
$grid_events[$event] =
|
||||||
|
array('--special' => "function($params) {jQuery('#{$grid_id}-error').hide(); $statement;}");
|
||||||
|
}
|
||||||
|
elseif ($event == 'loadError' && !$debug) {
|
||||||
|
$grid_events[$event] =
|
||||||
|
array('--special' => "function($params) {jQuery('#{$grid_id}-error').show(); $statement;}");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$grid_events[$event] =
|
$grid_events[$event] =
|
||||||
@@ -226,13 +247,14 @@ $jqGrid_setup = array_merge
|
|||||||
'colNames' => array_keys($jqGridColumns),
|
'colNames' => array_keys($jqGridColumns),
|
||||||
'colModel' => array('--special' => $jqGridColumns),
|
'colModel' => array('--special' => $jqGridColumns),
|
||||||
'height' => $height,
|
'height' => $height,
|
||||||
|
'width' => 700,
|
||||||
'rowNum' => $limit,
|
'rowNum' => $limit,
|
||||||
'rowList' => $limitOptions,
|
'rowList' => $limitOptions,
|
||||||
'sortname' => $sortname,
|
'sortname' => $sortname,
|
||||||
'sortorder' => $sortorder,
|
'sortorder' => $sortorder,
|
||||||
'caption' => $caption,
|
'caption' => $caption,
|
||||||
'imgpath' => $imgpath,
|
|
||||||
'viewrecords' => true,
|
'viewrecords' => true,
|
||||||
|
'gridview' => true,
|
||||||
'pager' => $grid_id.'-pager',
|
'pager' => $grid_id.'-pager',
|
||||||
),
|
),
|
||||||
$grid_events,
|
$grid_events,
|
||||||
@@ -245,67 +267,46 @@ $jqGrid_setup = array_merge
|
|||||||
// to kick this thing off.
|
// to kick this thing off.
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
<?php if ($first_grid): ?>
|
||||||
|
<script type="text/javascript"><!--
|
||||||
|
var currencyFormatter = function(cellval, opts, rowObject) {
|
||||||
|
if (!cellval)
|
||||||
|
return "";
|
||||||
|
return fmtCurrency(cellval);
|
||||||
|
}
|
||||||
|
|
||||||
|
var percentageFormatter = function(cellval, opts, rowObject) {
|
||||||
|
var precision;
|
||||||
|
if (typeof(opts.colModel) != 'undefined' &&
|
||||||
|
typeof(opts.colModel.formatoptions) != 'undefined' &&
|
||||||
|
typeof(opts.colModel.formatoptions.precision) != 'undefined')
|
||||||
|
precision = opts.colModel.formatoptions.precision;
|
||||||
|
else
|
||||||
|
precision = 0;
|
||||||
|
amount = cellval.toString().replace(/\%/g,'');
|
||||||
|
amount = (amount*100).toFixed(precision);
|
||||||
|
return amount+'%';
|
||||||
|
}
|
||||||
|
|
||||||
|
var idFormatter = function(cellval, opts, rowObject) {
|
||||||
|
if (!cellval)
|
||||||
|
return cellval;
|
||||||
|
return '#'+cellval;
|
||||||
|
}
|
||||||
|
--></script>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
|
||||||
<DIV ID="<?php echo $grid_div_id; ?>" CLASS="<?php echo $grid_div_class; ?>">
|
<DIV ID="<?php echo $grid_div_id; ?>" CLASS="<?php echo $grid_div_class; ?>">
|
||||||
<table id="<?php echo $grid_id; ?>" class="scroll"></table>
|
<table id="<?php echo $grid_id; ?>" class="scroll"></table>
|
||||||
<div id="<?php echo $grid_id; ?>-pager" class="scroll" style="text-align:right"></div>
|
<div id="<?php echo $grid_id; ?>-pager" class="scroll" style="text-align:right"></div>
|
||||||
<script type="text/javascript"><!--
|
<script type="text/javascript"><!--
|
||||||
|
|
||||||
jQuery(document).ready(function(){
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
jQuery('#<?php echo $grid_id; ?>').jqGrid(
|
jQuery('#<?php echo $grid_id; ?>').jqGrid(
|
||||||
<?php echo FormatHelper::phpVarToJavascript($jqGrid_setup); ?>
|
<?php echo FormatHelper::phpVarToJavascript($jqGrid_setup) . "\n"; ?>
|
||||||
).navGrid('#<?php echo $grid_id; ?>-pager',
|
).navGrid('#<?php echo $grid_id; ?>-pager', { view:false,edit:false,add:false,del:false,search:true,refresh:true});
|
||||||
{ view:false,
|
|
||||||
edit:false,
|
|
||||||
add:false,
|
|
||||||
del:false,
|
|
||||||
search:true,
|
|
||||||
refresh:true});
|
|
||||||
|
|
||||||
<?php
|
|
||||||
/* jQuery('#t_<?php echo $grid_id; ?>').height(25).hide() */
|
|
||||||
/* .filterGrid('#<?php echo $grid_id; ?>', { */
|
|
||||||
/* gridModel:true, */
|
|
||||||
/* gridToolbar:true, */
|
|
||||||
/* autosearch:true, */
|
|
||||||
/* }); */
|
|
||||||
|
|
||||||
/* jQuery('#<?php echo $grid_id; ?>').navGrid('#<?php echo $grid_id; ?>-pager', */
|
|
||||||
/* { view:false, */
|
|
||||||
/* edit:false, */
|
|
||||||
/* add:false, */
|
|
||||||
/* del:false, */
|
|
||||||
/* search:false, */
|
|
||||||
/* refresh:false}) */
|
|
||||||
/* .navButtonAdd('#<?php echo $grid_id; ?>-pager',{ */
|
|
||||||
/* caption:"Search", */
|
|
||||||
/* title:"Toggle Search", */
|
|
||||||
/* buttonimg:'<?php echo $imgpath; ?>' + '/find.gif', */
|
|
||||||
/* onClickButton:function(){ */
|
|
||||||
/* if(jQuery('#t_<?php echo $grid_id; ?>').css("display")=="none") { */
|
|
||||||
/* jQuery('#t_<?php echo $grid_id; ?>').css("display",""); */
|
|
||||||
/* } else { */
|
|
||||||
/* jQuery('#t_<?php echo $grid_id; ?>').css("display","none"); */
|
|
||||||
/* } */
|
|
||||||
/* } */
|
|
||||||
/* }); */
|
|
||||||
?>
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
--></script>
|
--></script>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
if (count($search_fields) > 0) {
|
if (count($search_fields) > 0) {
|
||||||
echo('<div>Search By:<BR>' . "\n");
|
echo('<div>Search By:<BR>' . "\n");
|
||||||
|
|||||||
@@ -2,23 +2,36 @@
|
|||||||
|
|
||||||
// Define the table columns
|
// Define the table columns
|
||||||
$cols = array();
|
$cols = array();
|
||||||
$cols['LeaseID'] = array('index' => 'Lease.id', 'hidden' => true);
|
|
||||||
$cols['Lease'] = array('index' => 'Lease.number', 'formatter' => 'id');
|
$cols['Lease'] = array('index' => 'Lease.number', 'formatter' => 'id');
|
||||||
$cols['Unit'] = array('index' => 'Unit.name', 'width' => '50', 'align' => 'center');
|
$cols['Unit'] = array('index' => 'Unit.name', 'formatter' => 'shortname', 'align' => 'center');
|
||||||
|
$cols['Customer id'] = array('index' => 'Customer.id', 'hidden' => true);
|
||||||
$cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'longname');
|
$cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'longname');
|
||||||
$cols['Rent'] = array('index' => 'Lease.rent', 'formatter' => 'currency', 'hiddenz' => true);
|
$cols['Rent'] = array('index' => 'Lease.rent', 'formatter' => 'currency');
|
||||||
$cols['Deposit'] = array('index' => 'Lease.deposit', 'formatter' => 'currency', 'hiddenz' => true);
|
$cols['Deposit'] = array('index' => 'Lease.deposit', 'formatter' => 'currency');
|
||||||
$cols['Signed'] = array('index' => 'Lease.lease_date', 'formatter' => 'date');
|
$cols['Signed'] = array('index' => 'Lease.lease_date', 'formatter' => 'date');
|
||||||
$cols['Move-In'] = array('index' => 'Lease.movein_date', 'formatter' => 'date');
|
$cols['Move-In'] = array('index' => 'Lease.movein_date', 'formatter' => 'date');
|
||||||
$cols['Move-Out'] = array('index' => 'Lease.moveout_date', 'formatter' => 'date');
|
$cols['Move-Out'] = array('index' => 'Lease.moveout_date', 'formatter' => 'date');
|
||||||
|
$cols['Closed'] = array('index' => 'Lease.close_date', 'formatter' => 'date');
|
||||||
|
$cols['Charge-Thru'] = array('index' => 'Lease.charge_through_date', 'formatter' => 'date');
|
||||||
|
$cols['Paid-Thru'] = array('index' => 'Lease.paid_through_date', 'formatter' => 'date');
|
||||||
|
$cols['Status'] = array('index' => 'status', 'formatter' => 'longenum');
|
||||||
$cols['Balance'] = array('index' => 'balance', 'formatter' => 'currency');
|
$cols['Balance'] = array('index' => 'balance', 'formatter' => 'currency');
|
||||||
$cols['Comment'] = array('index' => 'Lease.comment', 'formatter' => 'comment');
|
$cols['Comment'] = array('index' => 'Lease.comment', 'formatter' => 'comment');
|
||||||
|
|
||||||
|
if (!empty($this->params['action'])) {
|
||||||
|
if ($this->params['action'] === 'closed')
|
||||||
|
$grid->invalidFields(array('Charge-Thru', 'Paid-Thru', 'Status'));
|
||||||
|
elseif ($this->params['action'] === 'active')
|
||||||
|
$grid->invalidFields(array('Closed'));
|
||||||
|
elseif ($this->params['action'] === 'delinquent')
|
||||||
|
$grid->invalidFields(array('Closed'));
|
||||||
|
}
|
||||||
|
|
||||||
// Render the grid
|
// Render the grid
|
||||||
$grid
|
$grid
|
||||||
->columns($cols)
|
->columns($cols)
|
||||||
->sortField('LeaseID')
|
->sortField('Lease')
|
||||||
->defaultFields(array('LeaseID', 'Lease'))
|
->defaultFields(array('Lease'))
|
||||||
->searchFields(array('Customer', 'Unit'))
|
->searchFields(array('Customer', 'Unit'))
|
||||||
->render($this, isset($config) ? $config : null,
|
->render($this, isset($config) ? $config : null,
|
||||||
array_diff(array_keys($cols), array('Comment')));
|
array_diff(array_keys($cols), array('Signed', 'Charge-Thru', 'Status', 'Comment')));
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ $cols['Sub-Total'] = array('index' => 'subtotal-balance', 'formatter' =>
|
|||||||
|
|
||||||
// Render the grid
|
// Render the grid
|
||||||
$grid
|
$grid
|
||||||
->limit(50)
|
|
||||||
->columns($cols)
|
->columns($cols)
|
||||||
->sortField('Date')
|
->sortField('Date', 'DESC')
|
||||||
->defaultFields(array('Entry', 'Date', 'Amount'))
|
->defaultFields(array('Entry', 'Date', 'Amount'))
|
||||||
->searchFields(array('Customer', 'Unit'))
|
->searchFields(array('Customer', 'Unit'))
|
||||||
->render($this, isset($config) ? $config : null,
|
->render($this, isset($config) ? $config : null,
|
||||||
array_diff(array_keys($cols), array('Debit', 'Credit', 'Balance', 'Sub-Total', 'Comment')));
|
array_diff(array_keys($cols), array('Transaction', 'Debit', 'Credit',
|
||||||
|
'Balance', 'Sub-Total', 'Comment')));
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,8 @@
|
|||||||
|
|
||||||
// Define the table columns
|
// Define the table columns
|
||||||
$cols = array();
|
$cols = array();
|
||||||
$cols['ID'] = array('index' => 'id_sequence', 'formatter' => 'id');
|
|
||||||
$cols['Name'] = array('index' => 'Ledger.name', 'formatter' => 'name');
|
|
||||||
$cols['Account'] = array('index' => 'Account.name', 'formatter' => 'longname');
|
$cols['Account'] = array('index' => 'Account.name', 'formatter' => 'longname');
|
||||||
|
$cols['Sequence'] = array('index' => 'Ledger.sequence', 'formatter' => 'id');
|
||||||
$cols['Open Date'] = array('index' => 'PriorCloseTransaction.stamp', 'formatter' => 'date');
|
$cols['Open Date'] = array('index' => 'PriorCloseTransaction.stamp', 'formatter' => 'date');
|
||||||
$cols['Close Date'] = array('index' => 'CloseTransaction.stamp', 'formatter' => 'date');
|
$cols['Close Date'] = array('index' => 'CloseTransaction.stamp', 'formatter' => 'date');
|
||||||
$cols['Comment'] = array('index' => 'Ledger.comment', 'formatter' => 'comment');
|
$cols['Comment'] = array('index' => 'Ledger.comment', 'formatter' => 'comment');
|
||||||
@@ -16,8 +15,8 @@ $cols['Balance'] = array('index' => 'balance', 'formatter' => 'c
|
|||||||
// Render the grid
|
// Render the grid
|
||||||
$grid
|
$grid
|
||||||
->columns($cols)
|
->columns($cols)
|
||||||
->sortField('ID', 'ASC')
|
->sortField('Sequence')
|
||||||
->defaultFields(array('ID', 'Name', 'Account'))
|
->defaultFields(array('Sequence'))
|
||||||
->searchFields(array('Account', 'Comment'))
|
->searchFields(array('Comment'))
|
||||||
->render($this, isset($config) ? $config : null,
|
->render($this, isset($config) ? $config : null,
|
||||||
array_diff(array_keys($cols), array('Open Date', 'Comment')));
|
array_diff(array_keys($cols), array('Account', 'Open Date', 'Comment')));
|
||||||
|
|||||||
20
site/views/elements/locks.ctp
Normal file
20
site/views/elements/locks.ctp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php /* -*- mode:PHP -*- */
|
||||||
|
|
||||||
|
// Define the table columns
|
||||||
|
$cols = array();
|
||||||
|
$cols['Name'] = array('index' => 'name', 'formatter' => 'name');
|
||||||
|
$cols['Comment'] = array('index' => 'comment', 'formatter' => 'comment');
|
||||||
|
$cols['Key/Combo'] = array('index' => 'key', 'formatter' => 'number');
|
||||||
|
$cols['Previous Key'] = array('index' => 'key_last', 'formatter' => 'number');
|
||||||
|
$cols['Quantity'] = array('index' => 'qty', 'formatter' => 'number');
|
||||||
|
$cols['In Use'] = array('index' => 'inuse', 'formatter' => 'number');
|
||||||
|
$cols['Available'] = array('index' => 'avail', 'formatter' => 'number');
|
||||||
|
|
||||||
|
// Render the grid
|
||||||
|
$grid
|
||||||
|
->columns($cols)
|
||||||
|
->sortField('Name')
|
||||||
|
->defaultFields(array('Name'))
|
||||||
|
->searchFields(array('Name'))
|
||||||
|
->render($this, isset($config) ? $config : null,
|
||||||
|
array_diff(array_keys($cols), array('Previous Key')));
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
// Define the table columns
|
// Define the table columns
|
||||||
$cols = array();
|
$cols = array();
|
||||||
$cols['ID'] = array('index' => 'Map.id', 'formatter' => 'id');
|
|
||||||
$cols['Name'] = array('index' => 'Map.name', 'formatter' => 'longname');
|
$cols['Name'] = array('index' => 'Map.name', 'formatter' => 'longname');
|
||||||
$cols['Site Area'] = array('index' => 'SiteArea.name', 'formatter' => 'longname');
|
$cols['Site Area'] = array('index' => 'SiteArea.name', 'formatter' => 'longname');
|
||||||
$cols['Width'] = array('index' => 'Map.width', 'formatter' => 'number');
|
$cols['Width'] = array('index' => 'Map.width', 'formatter' => 'number');
|
||||||
@@ -13,7 +12,7 @@ $cols['Comment'] = array('index' => 'Map.comment', 'formatter' => 'comment
|
|||||||
$grid
|
$grid
|
||||||
->columns($cols)
|
->columns($cols)
|
||||||
->sortField('Name')
|
->sortField('Name')
|
||||||
->defaultFields(array('ID', 'Name'))
|
->defaultFields(array('Name'))
|
||||||
->searchFields(array('Name'))
|
->searchFields(array('Name'))
|
||||||
->render($this, isset($config) ? $config : null,
|
->render($this, isset($config) ? $config : null,
|
||||||
array_diff(array_keys($cols), array()));
|
array_diff(array_keys($cols), array()));
|
||||||
|
|||||||
@@ -8,17 +8,78 @@
|
|||||||
* @package pmgr
|
* @package pmgr
|
||||||
*/
|
*/
|
||||||
|
|
||||||
foreach ($menu AS $item) {
|
// REVISIT <AP>: 20090823
|
||||||
if (isset($item['header']))
|
// Add way to slide the entire menu off the page
|
||||||
echo('<DIV CLASS="header">' . $item['name'] . '</DIV>' . "\n");
|
|
||||||
elseif (isset($item['hr']))
|
|
||||||
echo('<HR>' . "\n");
|
|
||||||
elseif (isset($item['url']))
|
|
||||||
echo('<DIV CLASS="item">'
|
|
||||||
. $html->link($item['name'], $item['url'],
|
|
||||||
isset($item['htmlAttributes']) ? $item['htmlAttributes'] : null,
|
|
||||||
isset($item['confirmMessage']) ? $item['confirmMessage'] : null,
|
|
||||||
isset($item['escapeTitle']) ? $item['escapeTitle'] : null)
|
|
||||||
|
|
||||||
. '</DIV>' . "\n");
|
// The sidemenu-container is necessary to define the
|
||||||
|
// bounds as the parent of the sidemenu div, which will
|
||||||
|
// be heavily manipulated by the accordion module. If
|
||||||
|
// we don't have good control over the parent, the
|
||||||
|
// accordion will get confused and behave poorly.
|
||||||
|
echo('<DIV ID="sidemenu-container">' . "\n");
|
||||||
|
echo('<DIV ID="sidemenu">' . "\n");
|
||||||
|
|
||||||
|
$section = 0;
|
||||||
|
$active_section = null;
|
||||||
|
foreach ($menu['areas'] AS $area_name => $area) {
|
||||||
|
if (empty($area['subareas']))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
foreach ($area['subareas'] AS $subarea_name => $subarea) {
|
||||||
|
if (empty($subarea['priorities']))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!isset($active_section) &&
|
||||||
|
!empty($menu['active']['area']) && $area_name == $menu['active']['area'] &&
|
||||||
|
(empty($menu['active']['subarea']) || $subarea_name == $menu['active']['subarea']))
|
||||||
|
$active_section = $section;
|
||||||
|
|
||||||
|
++$section;
|
||||||
|
|
||||||
|
echo('<H3' .
|
||||||
|
//' id="sidemenu-section-'.$area_name.'-'.$subarea_name.'"' .
|
||||||
|
' class="sidemenu-header">' .
|
||||||
|
$subarea['name'] .
|
||||||
|
"</H3>\n");
|
||||||
|
|
||||||
|
echo('<DIV class="sidemenu-content">' . "\n");
|
||||||
|
foreach ($subarea['priorities'] AS $priority) {
|
||||||
|
foreach ($priority AS $item) {
|
||||||
|
if (isset($item['url'])) {
|
||||||
|
echo('<DIV CLASS="sidemenu-item">'
|
||||||
|
. $html->link($item['name'], $item['url'],
|
||||||
|
isset($item['htmlAttributes']) ? $item['htmlAttributes'] : null,
|
||||||
|
isset($item['confirmMessage']) ? $item['confirmMessage'] : null,
|
||||||
|
isset($item['escapeTitle']) ? $item['escapeTitle'] : null)
|
||||||
|
. '</DIV>' . "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo('</DIV>' . "\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
echo('</DIV>' . "\n"); // End #sidemenu
|
||||||
|
echo('</DIV>' . "\n"); // End #sidemenu-container
|
||||||
|
|
||||||
|
// Uses both hoverintent, which is a more user friendly mechanism
|
||||||
|
// than mouseover, as well as click. This provides 1) a workable
|
||||||
|
// solution for those browsers that don't use pointers, such as
|
||||||
|
// a touchscreen, and 2) a means to open the menu if the animation
|
||||||
|
// was running while the user moved the pointer to a new menu area.
|
||||||
|
$javascript->codeBlock(
|
||||||
|
<<<JSCB
|
||||||
|
jQuery(document).ready(function(){
|
||||||
|
if (jQuery("#sidemenu").accordion != null) {
|
||||||
|
jQuery("#sidemenu").accordion
|
||||||
|
({ fillSpace : true,
|
||||||
|
event : "click hoverintent",
|
||||||
|
animated : "bounceslide"
|
||||||
|
JSCB
|
||||||
|
. (isset($active_section) ? ",\n\t active : $active_section\n" : '') .
|
||||||
|
<<<JSCB
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
JSCB
|
||||||
|
, array('inline' => false));
|
||||||
|
|||||||
@@ -9,18 +9,22 @@ $cols['Date'] = array('index' => 'Transaction.stamp', 'formatter' =>
|
|||||||
$cols['Effective'] = array('index' => 'StatementEntry.effective_date', 'formatter' => 'date');
|
$cols['Effective'] = array('index' => 'StatementEntry.effective_date', 'formatter' => 'date');
|
||||||
$cols['Through'] = array('index' => 'StatementEntry.through_date', 'formatter' => 'date');
|
$cols['Through'] = array('index' => 'StatementEntry.through_date', 'formatter' => 'date');
|
||||||
|
|
||||||
$cols['Account'] = array('index' => 'Account.name', 'formatter' => 'name');
|
|
||||||
|
|
||||||
$cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'longname');
|
$cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'longname');
|
||||||
$cols['Lease'] = array('index' => 'Lease.number', 'formatter' => 'id');
|
$cols['Lease'] = array('index' => 'Lease.number', 'formatter' => 'id');
|
||||||
$cols['Unit'] = array('index' => 'Unit.name', 'formatter' => 'shortname');
|
$cols['Unit'] = array('index' => 'Unit.name', 'formatter' => 'shortname');
|
||||||
|
|
||||||
$cols['Comment'] = array('index' => 'StatementEntry.comment', 'formatter' => 'comment', 'width'=>150);
|
$cols['Comment'] = array('index' => 'StatementEntry.comment', 'formatter' => 'comment', 'width'=>150);
|
||||||
|
|
||||||
$cols['Charge'] = array('index' => 'charge', 'formatter' => 'currency');
|
$cols['Type'] = array('index' => 'StatementEntry.type', 'formatter' => 'longenum');
|
||||||
$cols['Payment'] = array('index' => 'payment', 'formatter' => 'currency');
|
$cols['Account'] = array('index' => 'Account.name', 'formatter' => 'name');
|
||||||
|
$cols['Debit'] = array('index' => 'charge', 'formatter' => 'currency');
|
||||||
|
$cols['Credit'] = array('index' => 'disbursement', 'formatter' => 'currency');
|
||||||
|
|
||||||
$cols['Applied'] = array('index' => "applied", 'formatter' => 'currency');
|
$cols['Amount'] = array('index' => "StatementEntry.amount", 'formatter' => 'currency');
|
||||||
|
$cols['Received'] = array('index' => "applied", 'formatter' => 'currency');
|
||||||
|
// 'balance' is already in use as part of charge/disbursement/balance.
|
||||||
|
// 'unapplied' isn't quite the right term, but it's not customer visible.
|
||||||
|
$cols['Balance'] = array('index' => "unapplied", 'formatter' => 'currency');
|
||||||
$cols['Sub-Total'] = array('index' => 'subtotal-balance', 'formatter' => 'currency', 'sortable' => false);
|
$cols['Sub-Total'] = array('index' => 'subtotal-balance', 'formatter' => 'currency', 'sortable' => false);
|
||||||
|
|
||||||
|
|
||||||
@@ -28,17 +32,30 @@ if (isset($subtotal_column))
|
|||||||
$cols['Sub-Total']['index'] =
|
$cols['Sub-Total']['index'] =
|
||||||
'subtotal-' . $cols[$subtotal_column]['index'];
|
'subtotal-' . $cols[$subtotal_column]['index'];
|
||||||
|
|
||||||
|
if ((isset($action) && $action == 'unreconciled') ||
|
||||||
|
(isset($config) && isset($config['action']) && $config['action'] == 'unreconciled')) {
|
||||||
|
if (isset($config) && !isset($config['grid_div_id']))
|
||||||
|
$config['grid_div_id'] = 'unpaid';
|
||||||
|
$include_columns = array('Entry', 'Date',
|
||||||
|
'Effective', 'Customer', 'Unit',
|
||||||
|
'Account', 'Amount', 'Received', 'Balance');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$include_columns =
|
||||||
|
array_diff(array_keys($cols),
|
||||||
|
array('Transaction', 'Through', 'Lease',
|
||||||
|
'Amount', 'Received', 'Balance', 'Sub-Total',
|
||||||
|
'Comment'));
|
||||||
|
}
|
||||||
|
|
||||||
// Include custom data
|
// Include custom data
|
||||||
$grid->customData(compact('statement_entry_id'));
|
$grid->customData(compact('statement_entry_id'));
|
||||||
|
|
||||||
// Render the grid
|
// Render the grid
|
||||||
$grid
|
$grid
|
||||||
->columns($cols)
|
->columns($cols)
|
||||||
->sortField('Date')
|
->sortField('Date', 'DESC')
|
||||||
->defaultFields(array('Entry', 'Date', 'Charge', 'Payment'))
|
->defaultFields(array('Entry', 'Date', 'Charge', 'Payment'))
|
||||||
->searchFields(array('Customer', 'Unit'))
|
->searchFields(array('Customer', 'Unit'))
|
||||||
->render($this, isset($config) ? $config : null,
|
->render($this, isset($config) ? $config : null, $include_columns);
|
||||||
array_diff(array_keys($cols), array('Through', 'Lease',
|
|
||||||
'Applied', 'Sub-Total',
|
|
||||||
'Comment')));
|
|
||||||
|
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ if (isset($rows) && is_array($rows) && count($rows)) {
|
|||||||
|
|
||||||
foreach ($rows AS $r => &$row) {
|
foreach ($rows AS $r => &$row) {
|
||||||
foreach ($row AS $c => $col) {
|
foreach ($row AS $c => $col) {
|
||||||
$cell_class = implode(" ", array_merge(isset( $row_class[$r]) ? $row_class[$r] : array(),
|
$cell_class = implode(" ", array_merge(empty( $row_class[$r]) ? array() : $row_class[$r],
|
||||||
isset($column_class[$c]) ? $column_class[$c] : array()));
|
empty($column_class[$c]) ? array() : $column_class[$c]));
|
||||||
if ($cell_class)
|
if ($cell_class)
|
||||||
$row[$c] = array($col, array('class' => $cell_class));
|
$row[$c] = array($col, array('class' => $cell_class));
|
||||||
}
|
}
|
||||||
@@ -64,9 +64,12 @@ if (isset($rows) && is_array($rows) && count($rows)) {
|
|||||||
$class = implode(' ', $class);
|
$class = implode(' ', $class);
|
||||||
|
|
||||||
// OK, output the table HTML
|
// OK, output the table HTML
|
||||||
echo('<TABLE' . (isset($class) ? ' CLASS="'.$class.'"' : '') . '>' . "\n");
|
echo('<TABLE' .
|
||||||
|
(empty($id) ? '' : ' ID="'.$id.'"') .
|
||||||
|
(empty($class) ? '' : ' CLASS="'.$class.'"') .
|
||||||
|
'>' . "\n");
|
||||||
|
|
||||||
if (isset($caption))
|
if (!empty($caption))
|
||||||
echo(' <CAPTION>' . $caption . '</CAPTION>' . "\n");
|
echo(' <CAPTION>' . $caption . '</CAPTION>' . "\n");
|
||||||
|
|
||||||
if (isset($headers) && is_array($headers)) {
|
if (isset($headers) && is_array($headers)) {
|
||||||
|
|||||||
@@ -2,11 +2,10 @@
|
|||||||
|
|
||||||
// Define the table columns
|
// Define the table columns
|
||||||
$cols = array();
|
$cols = array();
|
||||||
//$cols['ID'] = array('index' => 'Tender.id', 'formatter' => 'id');
|
|
||||||
$cols['Date'] = array('index' => 'Transaction.stamp', 'formatter' => 'date');
|
$cols['Date'] = array('index' => 'Transaction.stamp', 'formatter' => 'date');
|
||||||
$cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'longname');
|
$cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'longname');
|
||||||
$cols['Item'] = array('index' => 'Tender.name', 'formatter' => 'longname');
|
$cols['Item'] = array('index' => 'Tender.name', 'formatter' => 'longname');
|
||||||
$cols['Type'] = array('index' => 'TenderType.name', 'formatter' => 'name');
|
$cols['Type'] = array('index' => 'TenderType.name', 'formatter' => 'shortname');
|
||||||
$cols['Comment'] = array('index' => 'Tender.comment', 'formatter' => 'comment');
|
$cols['Comment'] = array('index' => 'Tender.comment', 'formatter' => 'comment');
|
||||||
$cols['Amount'] = array('index' => 'LedgerEntry.amount', 'formatter' => 'currency');
|
$cols['Amount'] = array('index' => 'LedgerEntry.amount', 'formatter' => 'currency');
|
||||||
$cols['Sub-Total'] = array('index' => 'subtotal-LedgerEntry.amount', 'formatter' => 'currency');
|
$cols['Sub-Total'] = array('index' => 'subtotal-LedgerEntry.amount', 'formatter' => 'currency');
|
||||||
@@ -18,4 +17,4 @@ $grid
|
|||||||
->defaultFields(array('Date', 'Name', 'Amount'))
|
->defaultFields(array('Date', 'Name', 'Amount'))
|
||||||
->searchFields(array('Name', 'Type'))
|
->searchFields(array('Name', 'Type'))
|
||||||
->render($this, isset($config) ? $config : null,
|
->render($this, isset($config) ? $config : null,
|
||||||
array_diff(array_keys($cols), array('Sub-Total')));
|
array_diff(array_keys($cols), array('Comment', 'Sub-Total')));
|
||||||
|
|||||||
@@ -1,20 +1,27 @@
|
|||||||
<?php /* -*- mode:PHP -*- */
|
<?php /* -*- mode:PHP -*- */
|
||||||
|
|
||||||
|
if (isset($include))
|
||||||
|
$include = is_array($include) ? $include : array($include);
|
||||||
|
else
|
||||||
|
$include = array();
|
||||||
|
|
||||||
// Define the table columns
|
// Define the table columns
|
||||||
$cols = array();
|
$cols = array();
|
||||||
$cols['ID'] = array('index' => 'Transaction.id', 'formatter' => 'id');
|
$cols['ID'] = array('index' => 'Transaction.id', 'formatter' => 'id');
|
||||||
$cols['Type'] = array('index' => 'Transaction.type', 'formatter' => 'enum');
|
$cols['Type'] = array('index' => 'Transaction.type', 'formatter' => 'enum');
|
||||||
//$cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'longname');
|
$cols['Customer'] = array('index' => 'Customer.name', 'formatter' => 'longname');
|
||||||
$cols['Timestamp'] = array('index' => 'Transaction.stamp', 'formatter' => 'date');
|
$cols['Timestamp'] = array('index' => 'Transaction.stamp', 'formatter' => 'date');
|
||||||
|
$cols['Comment'] = array('index' => 'Transaction.comment', 'formatter' => 'comment', 'sortable' => false);
|
||||||
|
$cols['Entries'] = array('index' => 'entries', 'formatter' => 'number');
|
||||||
$cols['Amount'] = array('index' => 'Transaction.amount', 'formatter' => 'currency');
|
$cols['Amount'] = array('index' => 'Transaction.amount', 'formatter' => 'currency');
|
||||||
$cols['entries'] = array('index' => 'entries', 'formatter' => 'number');
|
$cols['PosNeg'] = array('index' => 'balance', 'formatter' => 'currency');
|
||||||
$cols['Comment'] = array('index' => 'Transaction.comment', 'formatter' => 'comment');
|
$cols['Balance'] = array('index' => 'subtotal-balance', 'formatter' => 'currency', 'sortable' => false);
|
||||||
|
|
||||||
// Render the grid
|
// Render the grid
|
||||||
$grid
|
$grid
|
||||||
->columns($cols)
|
->columns($cols)
|
||||||
->sortField('Timestamp')
|
->sortField('Timestamp', 'DESC')
|
||||||
->defaultFields(array('ID', 'Timestamp'))
|
->defaultFields(array('ID', 'Timestamp'))
|
||||||
->searchFields(array('Type', 'Comment'))
|
->searchFields(array('Type', 'Comment'))
|
||||||
->render($this, isset($config) ? $config : null,
|
->render($this, isset($config) ? $config : null,
|
||||||
array_diff(array_keys($cols), array('Comment')));
|
array_merge($include, array_diff(array_keys($cols), array('Customer', 'PosNeg', 'Balance', 'Comment'))));
|
||||||
|
|||||||
40
site/views/elements/unit_sizes.ctp
Normal file
40
site/views/elements/unit_sizes.ctp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?php /* -*- mode:PHP -*- */
|
||||||
|
|
||||||
|
// Define the table columns
|
||||||
|
$cols = array();
|
||||||
|
$cols['Size'] = array('index' => 'UnitSize.name', 'formatter' => 'shortname');
|
||||||
|
$cols['Type'] = array('index' => 'UnitType.name', 'formatter' => 'shortname');
|
||||||
|
$cols['Width'] = array('index' => 'UnitSize.width', 'formatter' => 'number');
|
||||||
|
$cols['Depth'] = array('index' => 'UnitSize.depth', 'formatter' => 'number');
|
||||||
|
$cols['Height'] = array('index' => 'UnitSize.height', 'formatter' => 'number');
|
||||||
|
$cols['Area'] = array('index' => 'sqft', 'formatter' => 'number');
|
||||||
|
$cols['Volume'] = array('index' => 'cuft', 'formatter' => 'number');
|
||||||
|
$cols['Deposit'] = array('index' => 'UnitSize.deposit', 'formatter' => 'currency');
|
||||||
|
$cols['Rent'] = array('index' => 'UnitSize.rent', 'formatter' => 'currency');
|
||||||
|
$cols['Per Foot'] = array('index' => 'sqcost', 'formatter' => 'currency');
|
||||||
|
$cols['Per Cubic Ft'] = array('index' => 'cucost', 'formatter' => 'currency');
|
||||||
|
$cols['Unavailable'] = array('index' => 'unavailable', 'formatter' => 'number');
|
||||||
|
$cols['Occupied'] = array('index' => 'occupied', 'formatter' => 'number');
|
||||||
|
$cols['Available'] = array('index' => 'available', 'formatter' => 'number');
|
||||||
|
$cols['Total'] = array('index' => 'units', 'formatter' => 'number');
|
||||||
|
$cols['Occupancy'] = array('index' => 'occupancy', 'formatter' => 'percentage', 'formatoptions' => array('precision' => 0));
|
||||||
|
$cols['Vacancy'] = array('index' => 'vacancy', 'formatter' => 'percentage', 'formatoptions' => array('precision' => 0));
|
||||||
|
$cols['Comment'] = array('index' => 'Unit.comment', 'formatter' => 'comment');
|
||||||
|
|
||||||
|
// Render the grid
|
||||||
|
$grid
|
||||||
|
->columns($cols)
|
||||||
|
->sortField('Area')
|
||||||
|
->defaultFields(array('Size', 'Area'))
|
||||||
|
->searchFields(array('Size', 'Width', 'Depth', 'Area', 'Deposit', 'Rent'))
|
||||||
|
->render($this, isset($config) ? $config : null,
|
||||||
|
array_diff(array_keys($cols), array('Width', 'Depth',
|
||||||
|
'Deposit',
|
||||||
|
'Height', 'Volume',
|
||||||
|
//'Per Foot',
|
||||||
|
'Per Cubic Ft',
|
||||||
|
'Occupied',
|
||||||
|
//'Total',
|
||||||
|
'Occupancy',
|
||||||
|
//'Vacancy',
|
||||||
|
'Comment')));
|
||||||
@@ -4,19 +4,23 @@
|
|||||||
$cols = array();
|
$cols = array();
|
||||||
$cols['Sort'] = array('index' => 'Unit.sort_order', 'hidden' => true);
|
$cols['Sort'] = array('index' => 'Unit.sort_order', 'hidden' => true);
|
||||||
$cols['Walk'] = array('index' => 'Unit.walk_order', 'formatter' => 'number');
|
$cols['Walk'] = array('index' => 'Unit.walk_order', 'formatter' => 'number');
|
||||||
$cols['ID'] = array('index' => 'Unit.id', 'formatter' => 'id');
|
|
||||||
$cols['Unit'] = array('index' => 'Unit.name', 'formatter' => 'shortname');
|
$cols['Unit'] = array('index' => 'Unit.name', 'formatter' => 'shortname');
|
||||||
$cols['Size'] = array('index' => 'UnitSize.name', 'formatter' => 'shortname');
|
$cols['Size'] = array('index' => 'UnitSize.name', 'formatter' => 'shortname');
|
||||||
|
$cols['Area'] = array('index' => 'sqft', 'formatter' => 'number');
|
||||||
$cols['Rent'] = array('index' => 'Unit.rent', 'formatter' => 'currency');
|
$cols['Rent'] = array('index' => 'Unit.rent', 'formatter' => 'currency');
|
||||||
$cols['Status'] = array('index' => 'Unit.status', 'formatter' => 'name'); // We have enough real estate
|
$cols['Deposit'] = array('index' => 'Unit.deposit', 'formatter' => 'currency');
|
||||||
|
$cols['Status'] = array('index' => 'Unit.status', 'formatter' => 'enum');
|
||||||
$cols['Balance'] = array('index' => 'balance', 'formatter' => 'currency');
|
$cols['Balance'] = array('index' => 'balance', 'formatter' => 'currency');
|
||||||
$cols['Comment'] = array('index' => 'Unit.comment', 'formatter' => 'comment');
|
$cols['Comment'] = array('index' => 'Unit.comment', 'formatter' => 'comment');
|
||||||
|
|
||||||
|
if (in_array($this->params['action'], array('vacant', 'unavailable')))
|
||||||
|
$grid->invalidFields('Balance');
|
||||||
|
|
||||||
// Render the grid
|
// Render the grid
|
||||||
$grid
|
$grid
|
||||||
->columns($cols)
|
->columns($cols)
|
||||||
->sortField('Sort')
|
->sortField('Sort')
|
||||||
->defaultFields(array('Sort', 'ID', 'Unit'))
|
->defaultFields(array('Sort', 'Unit'))
|
||||||
->searchFields(array('Unit', 'Size', 'Status'))
|
->searchFields(array('Unit', 'Size', 'Status'))
|
||||||
->render($this, isset($config) ? $config : null,
|
->render($this, isset($config) ? $config : null,
|
||||||
array_diff(array_keys($cols), array('Walk', 'Comment')));
|
array_diff(array_keys($cols), array('Walk', 'Deposit', 'Comment')));
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<?php /* -*- mode:PHP -*- */
|
||||||
|
if (!empty($message))
|
||||||
|
echo $message;
|
||||||
|
|||||||
@@ -19,14 +19,26 @@ class FormatHelper extends AppHelper {
|
|||||||
true));
|
true));
|
||||||
}
|
}
|
||||||
|
|
||||||
function currency($amount, $spans = false) {
|
function currency($amount, $spans = false, $dollar_sign = null) {
|
||||||
if (!isset($amount))
|
if (!isset($amount))
|
||||||
return '-';
|
return '-';
|
||||||
//return null;
|
//return null;
|
||||||
|
|
||||||
$currency = self::$number->currency($amount,
|
// Use of the $number->currency() function results in the clever,
|
||||||
'USD',
|
// but problematic, use of cents for amounts less than $1. For
|
||||||
$spans ? array('before'=>'', 'after'=>'') : array());
|
// example, 50 cents is shown as '50c', not '$0.50'. We want to
|
||||||
|
// keep everything in terms of dollars, especially for the cases
|
||||||
|
// where this result is placed into a form for input. 50 cents
|
||||||
|
// will end up as 50 dollars upon submission :-(
|
||||||
|
$currency = self::$number->format
|
||||||
|
(abs($amount),
|
||||||
|
array('places' => 2,
|
||||||
|
'before' => $spans ? '' : (isset($dollar_sign) ? $dollar_sign : '$'),
|
||||||
|
'after' => $spans ? '' : null,
|
||||||
|
));
|
||||||
|
|
||||||
|
if ($amount < 0)
|
||||||
|
$currency = '(' . $currency . ')';
|
||||||
|
|
||||||
if ($spans)
|
if ($spans)
|
||||||
return ('<SPAN CLASS="dollar-sign">$</SPAN>' .
|
return ('<SPAN CLASS="dollar-sign">$</SPAN>' .
|
||||||
@@ -35,22 +47,36 @@ class FormatHelper extends AppHelper {
|
|||||||
return $currency;
|
return $currency;
|
||||||
}
|
}
|
||||||
|
|
||||||
function date($date, $age = false) {
|
function percent($amount, $precision = 2) {
|
||||||
if (!$date) return null;
|
if (!isset($amount))
|
||||||
|
return '-';
|
||||||
|
|
||||||
$date_fmt = 'm/d/Y';
|
return self::$number->toPercentage($amount*100, $precision);
|
||||||
return (self::$time->format($date_fmt, $date) .
|
|
||||||
($age
|
|
||||||
? ' (' . self::age($date, 60*60*24) . ')'
|
|
||||||
: ''));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function datetime($datetime, $age = false) {
|
function date($date, $age = false, $class = null, $time = false) {
|
||||||
if (!$datetime) return null;
|
if (!$date) return null;
|
||||||
return (self::$time->nice($datetime) .
|
|
||||||
($age
|
if (empty($class))
|
||||||
? ' (' . self::age($datetime) . ')'
|
$class = '';
|
||||||
: ''));
|
|
||||||
|
if ($time)
|
||||||
|
$date_html = self::$time->nice($date);
|
||||||
|
else
|
||||||
|
$date_html = self::$time->format('m/d/Y', $date);
|
||||||
|
|
||||||
|
$date_html = '<span class="fmt-date '.$class.'">'.$date_html.'</span>';
|
||||||
|
|
||||||
|
if ($age) {
|
||||||
|
$date_html .= ' (' . self::age($date, $class, true, $time ? 0 : 60*60*24) . ')';
|
||||||
|
$date_html = '<span class="fmt-dateage '.$class.'">'.$date_html.'</span>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $date_html;
|
||||||
|
}
|
||||||
|
|
||||||
|
function datetime($datetime, $age = false, $class = null) {
|
||||||
|
return self::date($datetime, $age, $class, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function phone($phone, $ext = null) {
|
function phone($phone, $ext = null) {
|
||||||
@@ -81,10 +107,13 @@ class FormatHelper extends AppHelper {
|
|||||||
return $comment;
|
return $comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
function age($datetime, $min_span = 0) {
|
function age($datetime, $class, $suffix = false, $min_span = 0) {
|
||||||
if (!isset($datetime))
|
if (!isset($datetime))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
if (empty($class))
|
||||||
|
$class = '';
|
||||||
|
|
||||||
$now = time();
|
$now = time();
|
||||||
$seconds = self::$time->fromString($datetime);
|
$seconds = self::$time->fromString($datetime);
|
||||||
$backwards = ($seconds > $now);
|
$backwards = ($seconds > $now);
|
||||||
@@ -95,9 +124,11 @@ class FormatHelper extends AppHelper {
|
|||||||
|
|
||||||
//pr(compact('now', 'seconds', 'backwards', 'timefrom', 'timeto', 'span', 'min_span'));
|
//pr(compact('now', 'seconds', 'backwards', 'timefrom', 'timeto', 'span', 'min_span'));
|
||||||
|
|
||||||
// If now, just return so
|
// If now, just use 'now'
|
||||||
if ($span === 0)
|
if ($span === 0) {
|
||||||
return __('now', true);
|
$approx = 0;
|
||||||
|
$unit = 'now';
|
||||||
|
}
|
||||||
|
|
||||||
// Display seconds if under 45 seconds
|
// Display seconds if under 45 seconds
|
||||||
if ($span < 45 && $span >= $min_span) {
|
if ($span < 45 && $span >= $min_span) {
|
||||||
@@ -164,20 +195,36 @@ class FormatHelper extends AppHelper {
|
|||||||
//pr(compact('span', 'min_span', 'approx', 'unit'));
|
//pr(compact('span', 'min_span', 'approx', 'unit'));
|
||||||
|
|
||||||
if ($approx == 0) {
|
if ($approx == 0) {
|
||||||
if ($unit == 'day')
|
if ($unit == 'now')
|
||||||
return __('today', true);
|
$age = 'now';
|
||||||
|
elseif ($unit == 'day')
|
||||||
return __('this ' . $unit, true);
|
$age = 'today';
|
||||||
|
else
|
||||||
|
$age = 'this ' . $unit;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if (isset($relative))
|
||||||
|
$age = $relative;
|
||||||
|
elseif ($approx > $span)
|
||||||
|
$age = 'almost';
|
||||||
|
elseif ($approx < $span)
|
||||||
|
$age = 'over';
|
||||||
|
else
|
||||||
|
$age = '';
|
||||||
|
|
||||||
return (__(isset($relative)
|
$age .= ' ' . self::_n($approx, $unit);
|
||||||
? $relative
|
|
||||||
: ($approx == $span
|
if ($suffix) {
|
||||||
? ''
|
if ($backwards)
|
||||||
: ($approx > $span ? 'almost' : 'over')), true)
|
$age .= ' from now';
|
||||||
. ' '
|
else
|
||||||
. self::_n($approx, $unit)
|
$age .= ' ago';
|
||||||
. ($backwards ? '' : __(' ago', true)));
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$age = '<span class="fmt-age '.$class.'">'.__($age, true).'</span>';
|
||||||
|
|
||||||
|
return $age;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************
|
/*****************************
|
||||||
@@ -228,14 +275,21 @@ class FormatHelper extends AppHelper {
|
|||||||
|
|
||||||
|
|
||||||
// Helper function to convert PHP vars to javascript
|
// Helper function to convert PHP vars to javascript
|
||||||
function phpVarToJavascript($var, $name = '', $depth='', $special = false) {
|
function phpVarToJavascript($var, $name = '', $depth='', $special = false, $pretty = false) {
|
||||||
|
|
||||||
// Establish a prefix to use before printing $var
|
// Establish a prefix to use before printing $var
|
||||||
$prefix = $depth;
|
if ($pretty) {
|
||||||
|
$prefix = $depth;
|
||||||
|
$pretty_sp = " ";
|
||||||
|
$pretty_nl = "\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$prefix = $pretty_sp = $pretty_nl = '';
|
||||||
|
}
|
||||||
|
|
||||||
// If given a name, set it up JS style
|
// If given a name, set it up JS style
|
||||||
if ($name)
|
if ($name)
|
||||||
$prefix .= $name . ": ";
|
$prefix .= $name . ":" . $pretty_sp;
|
||||||
|
|
||||||
if (!isset($var))
|
if (!isset($var))
|
||||||
return $prefix . 'null';
|
return $prefix . 'null';
|
||||||
@@ -288,22 +342,22 @@ class FormatHelper extends AppHelper {
|
|||||||
// PHP array indices can be a mix of integer and string based.
|
// PHP array indices can be a mix of integer and string based.
|
||||||
// Just guess here, unless flagged as a special case.
|
// Just guess here, unless flagged as a special case.
|
||||||
if (isset($var[0]) || $special)
|
if (isset($var[0]) || $special)
|
||||||
return ($prefix . "[\n"
|
return ($prefix . "[" . $pretty_nl
|
||||||
. implode(",\n",
|
. implode("," . $pretty_nl,
|
||||||
array_map(array('FormatHelper', 'phpVarToJavascript'),
|
array_map(array('FormatHelper', 'phpVarToJavascript'),
|
||||||
array_values($var),
|
array_values($var),
|
||||||
array(),
|
array(),
|
||||||
array_fill(0, count($var), $depth.' ')
|
array_fill(0, count($var), $depth.' ')
|
||||||
))
|
))
|
||||||
. "\n$depth]");
|
. ($pretty ? "\n$depth" : '') . "]");
|
||||||
|
|
||||||
return ($prefix . "{\n"
|
return ($prefix . "{" . $pretty_nl
|
||||||
. implode(",\n",
|
. implode("," . $pretty_nl,
|
||||||
array_map(array('FormatHelper', 'phpVarToJavascript'),
|
array_map(array('FormatHelper', 'phpVarToJavascript'),
|
||||||
array_values($var), array_keys($var),
|
array_values($var), array_keys($var),
|
||||||
array_fill(0, count($var), $depth.' ')
|
array_fill(0, count($var), $depth.' ')
|
||||||
))
|
))
|
||||||
. "\n$depth}");
|
. ($pretty ? "\n$depth" : '') . "}");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ class GridHelper extends AppHelper {
|
|||||||
var $included, $invalid;
|
var $included, $invalid;
|
||||||
var $columns;
|
var $columns;
|
||||||
var $controller;
|
var $controller;
|
||||||
|
static $first_grid = true;
|
||||||
|
|
||||||
function __construct() {
|
function __construct() {
|
||||||
$this->reset();
|
$this->reset();
|
||||||
@@ -166,9 +167,14 @@ class GridHelper extends AppHelper {
|
|||||||
$included = array_diff(array_merge($this->included, $included),
|
$included = array_diff(array_merge($this->included, $included),
|
||||||
array_merge($this->invalid, $excluded));
|
array_merge($this->invalid, $excluded));
|
||||||
|
|
||||||
// Extract the columns that correspond to the inclusion set
|
// Defined the columns, based on the inclusion set,
|
||||||
$this->jqGrid_options['jqGridColumns']
|
// remapping column names as necessary.
|
||||||
= array_intersect_key($this->columns, array_flip($included));
|
$this->jqGrid_options['jqGridColumns'] = array();
|
||||||
|
foreach (array_intersect_key($this->columns, array_flip($included)) AS $name => $col) {
|
||||||
|
if (!empty($config['remap'][$name]))
|
||||||
|
$name = $config['remap'][$name];
|
||||||
|
$this->jqGrid_options['jqGridColumns'][$name] = $col;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure search fields are all part of the inclusion set
|
// Make sure search fields are all part of the inclusion set
|
||||||
$this->jqGrid_options['search_fields']
|
$this->jqGrid_options['search_fields']
|
||||||
@@ -209,11 +215,22 @@ class GridHelper extends AppHelper {
|
|||||||
}
|
}
|
||||||
$this->jqGrid_options['controller'] = $controller;
|
$this->jqGrid_options['controller'] = $controller;
|
||||||
|
|
||||||
|
// Add in any custom variables requested
|
||||||
|
if (isset($config['custom'])) {
|
||||||
|
$this->customData($config['custom']);
|
||||||
|
unset($config['custom']);
|
||||||
|
}
|
||||||
|
|
||||||
// Incorporate all other user options
|
// Incorporate all other user options
|
||||||
if (isset($config))
|
if (isset($config))
|
||||||
$this->jqGrid_options = array_merge_recursive($this->jqGrid_options, $config);
|
$this->jqGrid_options = array_merge($this->jqGrid_options, $config);
|
||||||
|
|
||||||
|
// Set flag whether or not this is the first grid
|
||||||
|
$this->jqGrid_options['first_grid'] = self::$first_grid;
|
||||||
|
|
||||||
|
//pr(compact('config') + array('jqGrid_options' => $this->jqGrid_options));
|
||||||
echo $view->element('jqGrid', $this->jqGrid_options);
|
echo $view->element('jqGrid', $this->jqGrid_options);
|
||||||
|
self::$first_grid = false;
|
||||||
|
|
||||||
// Since we only have one instance of this class
|
// Since we only have one instance of this class
|
||||||
// as a helper, we must assume it could be used
|
// as a helper, we must assume it could be used
|
||||||
@@ -223,4 +240,4 @@ class GridHelper extends AppHelper {
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -24,27 +24,80 @@
|
|||||||
?>
|
?>
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<?php
|
||||||
|
/* print("<!--\n"); */
|
||||||
|
/* print("SERVER = "); print_r($_SERVER); print("\n"); */
|
||||||
|
/* print("REQUEST = "); print_r($_REQUEST); print("\n"); */
|
||||||
|
/* print("COOKIE = "); print_r($_COOKIE); print("\n"); */
|
||||||
|
/* print("-->\n"); */
|
||||||
|
?>
|
||||||
<head>
|
<head>
|
||||||
<?php echo $html->charset(); ?>
|
<?php echo $html->charset(); ?>
|
||||||
<title>
|
<title>
|
||||||
|
<?php if (devbox()) echo "*DEVBOX* "; ?>
|
||||||
|
<?php if (sandbox()) echo "*SANDBOX* "; ?>
|
||||||
Property Manager: <?php echo $title_for_layout; ?>
|
Property Manager: <?php echo $title_for_layout; ?>
|
||||||
|
<?php if (sandbox()) echo " *SANDBOX*"; ?>
|
||||||
|
<?php if (devbox()) echo " *DEVBOX*"; ?>
|
||||||
</title>
|
</title>
|
||||||
<?php
|
<?php
|
||||||
|
// Reset the __scripts variable, which has already been dumped to
|
||||||
|
// $scripts_for_layout. Elements/Helpers used in the layout may
|
||||||
|
// also have some scripts to add. They cannot be put into the head
|
||||||
|
// but we can at least put them into a relatively benign place, so
|
||||||
|
// scripts don't have to be dumped inline in possibly awkward spots.
|
||||||
|
// Oh, and yes... I know we're not supposed to be using this variable
|
||||||
|
// directly, and will possibly get burned someday. Oh well, Cake
|
||||||
|
// hasn't left us a lot of choice, besides writing our own scripts
|
||||||
|
// mechanism _additional_ to what Cake has provided :-/
|
||||||
|
$this->__scripts = array();
|
||||||
|
|
||||||
|
if (!empty($_SERVER['HTTPS']))
|
||||||
|
$protocol = 'https://';
|
||||||
|
else
|
||||||
|
$protocol = 'http://';
|
||||||
|
|
||||||
echo $html->meta('icon') . "\n";
|
echo $html->meta('icon') . "\n";
|
||||||
|
|
||||||
|
$theme = 'smoothness';
|
||||||
|
$theme = 'base';
|
||||||
|
$theme = 'dotluv';
|
||||||
|
$theme = 'dark-hive';
|
||||||
|
$theme = 'start';
|
||||||
|
if (devbox())
|
||||||
|
$theme = 'dotluv';
|
||||||
|
if (sandbox())
|
||||||
|
$theme = 'darkness';
|
||||||
|
|
||||||
echo $html->css('cake.generic') . "\n";
|
echo $html->css('cake.generic') . "\n";
|
||||||
|
echo $html->css('themes/'.$theme.'/ui.all') . "\n";
|
||||||
echo $html->css('layout') . "\n";
|
echo $html->css('layout') . "\n";
|
||||||
echo $html->css('print', null, array('media' => 'print')) . "\n";
|
echo $html->css('print', null, array('media' => 'print')) . "\n";
|
||||||
echo $html->css('sidemenu') . "\n";
|
echo $html->css('sidemenu') . "\n";
|
||||||
//echo $html->css('jquery/base/ui.all') . "\n";
|
|
||||||
//echo $html->css('jquery/smoothness/ui.all') . "\n";
|
echo $javascript->link('jquery-1.7.2.min') . "\n";
|
||||||
//echo $html->css('jquery/dotluv/ui.all') . "\n";
|
echo $javascript->link('jquery-ui-1.7.2.custom.min') . "\n";
|
||||||
echo $html->css('jquery/start/ui.all') . "\n";
|
//echo $javascript->link($protocol . 'ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js') . "\n";
|
||||||
echo $javascript->link('jquery/jquery') . "\n";
|
//echo $javascript->link($protocol . 'ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.js') . "\n";
|
||||||
echo $javascript->link('jquery/jquery-ui') . "\n";
|
//echo $javascript->link($protocol . 'ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js') . "\n";
|
||||||
|
//echo $javascript->link($protocol . 'ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js') . "\n";
|
||||||
echo $javascript->link('jquery.form') . "\n";
|
echo $javascript->link('jquery.form') . "\n";
|
||||||
|
echo $javascript->link('jquery.hoverIntent') . "\n";
|
||||||
echo $javascript->link('pmgr') . "\n";
|
echo $javascript->link('pmgr') . "\n";
|
||||||
echo $scripts_for_layout . "\n";
|
echo $scripts_for_layout . "\n";
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
<?php if ($this->params['action'] !== 'INTERNAL_ERROR'): ?>
|
||||||
|
<script type="text/javascript"><!--
|
||||||
|
if (typeof(jQuery) == 'undefined') {
|
||||||
|
window.location.href =
|
||||||
|
"<?php echo $html->url(array('controller' => 'util',
|
||||||
|
'action' => 'INTERNAL_ERROR',
|
||||||
|
'jQuery NOT LOADED!')); ?>";
|
||||||
|
}
|
||||||
|
--></script>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
@@ -89,5 +142,7 @@
|
|||||||
<?php echo $cakeDebug; ?>
|
<?php echo $cakeDebug; ?>
|
||||||
<?php /* pr($this); */ ?>
|
<?php /* pr($this); */ ?>
|
||||||
|
|
||||||
|
<?php echo implode("\n", $this->__scripts) . "\n"; ?>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,88 +0,0 @@
|
|||||||
<?php /* -*- mode:PHP -*- */
|
|
||||||
|
|
||||||
echo '<div class="apply-deposit input">' . "\n";
|
|
||||||
|
|
||||||
echo ('<DIV CLASS="apply-deposit grid-selection-text">' .
|
|
||||||
|
|
||||||
'Lease #' . $lease['number'] .
|
|
||||||
' / Customer #' . $customer['id'] .
|
|
||||||
': ' . $customer['name'] .
|
|
||||||
' / Unit ' . $unit['name'] .
|
|
||||||
|
|
||||||
'<DIV CLASS="supporting">' .
|
|
||||||
'<TABLE>' .
|
|
||||||
|
|
||||||
/* '<TR><TD CLASS="field">Balance:</TD><TD CLASS="value">' . */
|
|
||||||
/* FormatHelper::currency($lease['stats']['balance']) . */
|
|
||||||
/* '</TD></TR>' . */
|
|
||||||
|
|
||||||
'<TR><TD CLASS="field">Deposit:</TD><TD CLASS="value">' .
|
|
||||||
FormatHelper::currency($depositBalance) .
|
|
||||||
'</TD></TR>' .
|
|
||||||
|
|
||||||
'</TABLE>' .
|
|
||||||
'</DIV>' .
|
|
||||||
|
|
||||||
'</DIV>' . "\n");
|
|
||||||
|
|
||||||
|
|
||||||
echo $form->create(null, array('id' => 'apply-deposit-form',
|
|
||||||
'url' => array('controller' => 'leases',
|
|
||||||
'action' => 'apply_deposit')
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
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.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' => '<A HREF="#" ONCLICK="datepickerNow(\'TransactionStamp\'); return false;">Now</A>',
|
|
||||||
),
|
|
||||||
"amount" => array('prefix' => 'LedgerEntry',
|
|
||||||
'opts' => array('value' => $depositBalance),
|
|
||||||
),
|
|
||||||
"comment" => array('opts' => array('size' => 50),
|
|
||||||
),
|
|
||||||
)));
|
|
||||||
|
|
||||||
echo $form->end('Utilize Deposit');
|
|
||||||
?>
|
|
||||||
|
|
||||||
<script type="text/javascript"><!--
|
|
||||||
|
|
||||||
// Reset the form
|
|
||||||
function resetForm() {
|
|
||||||
datepickerNow('TransactionStamp');
|
|
||||||
}
|
|
||||||
|
|
||||||
$(document).ready(function(){
|
|
||||||
$("#TransactionStamp")
|
|
||||||
.attr('autocomplete', 'off')
|
|
||||||
.datepicker({ constrainInput: true,
|
|
||||||
numberOfMonths: [1, 1],
|
|
||||||
showCurrentAtPos: 0,
|
|
||||||
dateFormat: 'mm/dd/yy' });
|
|
||||||
|
|
||||||
resetForm();
|
|
||||||
});
|
|
||||||
--></script>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
<?php /* -*- mode:PHP -*- */
|
|
||||||
|
|
||||||
echo '<div class="bad-debt input">' . "\n";
|
|
||||||
|
|
||||||
echo ('<DIV CLASS="bad-debt grid-selection-text">' .
|
|
||||||
|
|
||||||
'Lease #' . $lease['number'] .
|
|
||||||
' / Customer #' . $customer['id'] .
|
|
||||||
': ' . $customer['name'] .
|
|
||||||
' / Unit ' . $unit['name'] .
|
|
||||||
|
|
||||||
'<DIV CLASS="supporting">' .
|
|
||||||
'<TABLE>' .
|
|
||||||
'<TR><TD CLASS="field">Balance:</TD><TD CLASS="value">'.$lease['stats']['balance'].'</TD></TR>' .
|
|
||||||
'</TABLE>' .
|
|
||||||
'</DIV>' .
|
|
||||||
|
|
||||||
'</DIV>' . "\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' => '<A HREF="#" ONCLICK="datepickerNow(\'TransactionStamp\'); return false;">Now</A>',
|
|
||||||
),
|
|
||||||
"comment" => array('opts' => array('size' => 50),
|
|
||||||
),
|
|
||||||
)));
|
|
||||||
|
|
||||||
echo $form->end('Write Off Remaining Balance');
|
|
||||||
?>
|
|
||||||
|
|
||||||
<script type="text/javascript"><!--
|
|
||||||
|
|
||||||
// Reset the form
|
|
||||||
function resetForm() {
|
|
||||||
datepickerNow('TransactionStamp');
|
|
||||||
}
|
|
||||||
|
|
||||||
$(document).ready(function(){
|
|
||||||
$("#TransactionStamp")
|
|
||||||
.attr('autocomplete', 'off')
|
|
||||||
.datepicker({ constrainInput: true,
|
|
||||||
numberOfMonths: [1, 1],
|
|
||||||
showCurrentAtPos: 0,
|
|
||||||
dateFormat: 'mm/dd/yy' });
|
|
||||||
|
|
||||||
resetForm();
|
|
||||||
});
|
|
||||||
--></script>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
@@ -4,6 +4,14 @@
|
|||||||
<?php
|
<?php
|
||||||
; // Editor alignment
|
; // Editor alignment
|
||||||
|
|
||||||
|
$unit = $lease['Unit'];
|
||||||
|
$customer = $lease['Customer'];
|
||||||
|
|
||||||
|
if (isset($lease['Lease']))
|
||||||
|
$lease = $lease['Lease'];
|
||||||
|
|
||||||
|
//pr(compact('unit', 'customer', 'lease', 'movein'));
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
@@ -11,105 +19,134 @@
|
|||||||
* Javascript
|
* Javascript
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Warnings _really_ screw up javascript
|
||||||
|
$saved_debug_state = Configure::read('debug');
|
||||||
|
Configure::write('debug', '0');
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<script type="text/javascript"><!--
|
<script type="text/javascript"><!--
|
||||||
|
|
||||||
|
var lease_charge_through;
|
||||||
|
|
||||||
// prepare the form when the DOM is ready
|
// prepare the form when the DOM is ready
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
var options = {
|
var options = {
|
||||||
target: '#output-debug', // target element(s) to be updated with server response
|
target: '#output-debug', // target element(s) to be updated with server response
|
||||||
beforeSubmit: verifyRequest, // pre-submit callback
|
beforeSubmit: verifyRequest, // pre-submit callback
|
||||||
success: showResponse, // post-submit callback
|
success: showResponse, // post-submit callback
|
||||||
|
|
||||||
// other available options:
|
// 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
|
//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:
|
url: "<?php echo $html->url(array('controller' => 'transactions',
|
||||||
//timeout: 3000,
|
'action' => 'postInvoice', 0)); ?>"
|
||||||
};
|
};
|
||||||
|
|
||||||
// bind form using 'ajaxForm'
|
// bind form using 'ajaxForm'
|
||||||
|
if ($('#invoice-form').ajaxForm != null)
|
||||||
$('#invoice-form').ajaxForm(options);
|
$('#invoice-form').ajaxForm(options);
|
||||||
});
|
else
|
||||||
|
$('#repeat, label[for=repeat]').remove();
|
||||||
|
});
|
||||||
|
|
||||||
// pre-submit callback
|
// pre-submit callback
|
||||||
function verifyRequest(formData, jqForm, options) {
|
function verifyRequest(formData, jqForm, options) {
|
||||||
// formData is an array; here we use $.param to convert it to a string to display it
|
//$("#debug").html('');
|
||||||
// but the form plugin does this for you automatically when it submits the data
|
for (var i = 0; i < formData.length; ++i) {
|
||||||
//var_dump(formData);
|
//$("#debug").append(i + ') ' + dump(formData[i]) + '<BR>');
|
||||||
//$('#request-debug').html('<PRE>'+dump(formData)+'</PRE>');
|
if (formData[i]['name'] == "data[Lease][id]" &&
|
||||||
$('#request-debug').html('Ommitted');
|
!(formData[i]['value'] > 0)) {
|
||||||
|
//$("#debug").append('<P>Missing Lease ID');
|
||||||
|
alert("Must select a lease first");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formData[i]['name'] == "data[Transaction][stamp]" &&
|
||||||
|
formData[i]['value'] == '') {
|
||||||
|
//$("#debug").append('<P>Bad Stamp');
|
||||||
|
if (formData[i]['value'] != '')
|
||||||
|
alert(formData[i]['value'] + " is not valid date stamp. Please correct it.");
|
||||||
|
else
|
||||||
|
alert("Please enter a valid date stamp first.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Terrible way to accomplish this...
|
||||||
|
for (var j = 0; j < 20; ++j) {
|
||||||
|
if (formData[i]['name'] == "data[Entry]["+j+"][amount]") {
|
||||||
|
var val = formData[i]['value'].replace(/\$/,'');
|
||||||
|
//$("#debug").append('<P>Bad Amount');
|
||||||
|
if (!(val > 0)) {
|
||||||
|
if (formData[i]['value'] == '')
|
||||||
|
alert("Please enter an amount for Charge #"+j+", or remove the Charge completely.");
|
||||||
|
else
|
||||||
|
alert('"'+formData[i]['value']+'"' + " is not a valid amount for Charge #"+j+". Please correct it.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//$("#debug").append('OK');
|
||||||
//return false;
|
//return false;
|
||||||
|
|
||||||
$('#response-debug').html('Loading <BLINK>...</BLINK>');
|
$('#results').html('Working <BLINK>...</BLINK>');
|
||||||
$('#output-debug').html('Loading <BLINK>...</BLINK>');
|
|
||||||
|
|
||||||
// here we could return false to prevent the form from being submitted;
|
|
||||||
// returning anything other than false will allow the form submit to continue
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// post-submit callback
|
// post-submit callback
|
||||||
function showResponse(responseText, statusText) {
|
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') {
|
if (statusText == 'success') {
|
||||||
|
var amount = 0;
|
||||||
|
$("input.invoice.amount").each(function(i) {
|
||||||
|
amount += (+ $(this).val().replace(/\$/,''));
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#results').html('<H3>Invoice Saved<BR>' +
|
||||||
|
$("#invoice-customer").html() +
|
||||||
|
' : ' + fmtCurrency(amount) +
|
||||||
|
'</H3>');
|
||||||
|
|
||||||
|
if (!$("#repeat").attr("checked")) {
|
||||||
|
window.location.href =
|
||||||
|
<?php if (empty($movein)): ?>
|
||||||
|
"<?php echo $html->url(array('controller' => 'customers',
|
||||||
|
'action' => 'view')); ?>"
|
||||||
|
+ "/" + $("#customer-id").val();
|
||||||
|
<?php else: ?>
|
||||||
|
"<?php echo $html->url(array('controller' => 'customers',
|
||||||
|
'action' => 'receipt')); ?>"
|
||||||
|
+ "/" + $("#customer-id").val();
|
||||||
|
<?php endif; ?>
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// get a clean slate
|
// get a clean slate
|
||||||
//resetForm();
|
resetForm();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
alert('not successful??');
|
$('#results').html('<H2>Failed to save invoice!</H2>');
|
||||||
|
alert('Failed to save invoice.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$('#response-debug').html('<PRE>'+dump(statusText)+'</PRE>');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the form
|
// Reset the form
|
||||||
function resetForm() {
|
function resetForm(nocharge) {
|
||||||
$("#charge-entry-id").val(1);
|
$('#charge-entry-id').val(1);
|
||||||
|
$('#charges').html('');
|
||||||
|
|
||||||
$("#invoice-lease").html("INTERNAL ERROR");
|
if (!nocharge)
|
||||||
$("#invoice-unit").html("INTERNAL ERROR");
|
addChargeSource(false);
|
||||||
$("#invoice-customer").html("INTERNAL ERROR");
|
|
||||||
$("#invoice-rent").html("INTERNAL ERROR");
|
|
||||||
$("#invoice-late").html("INTERNAL ERROR");
|
|
||||||
$("#invoice-deposit").html("INTERNAL ERROR");
|
|
||||||
|
|
||||||
addChargeSource(false);
|
|
||||||
datepickerNow('TransactionStamp');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function onRowSelect(grid_id, lease_id) {
|
function onRowSelect(grid_id, lease_id) {
|
||||||
// Set the item id that will be returned with the form
|
// Set the item id that will be returned with the form
|
||||||
$("#lease-id").val(lease_id);
|
$("#lease-id").val(lease_id);
|
||||||
|
$("#customer-id").val($(grid_id).getCell(lease_id, 'Customer-id'));
|
||||||
|
|
||||||
// Get the item names from the grid
|
$("#invoice-lease").html($(grid_id).getCell(lease_id, 'Lease-number'));
|
||||||
//$("#invoice-lease").html($(grid_id).getCell(lease_id, 'Lease-number'));
|
|
||||||
// REVISIT <AP>: 20090708
|
|
||||||
// This is not intended as a long term solution,
|
|
||||||
// but I need a way to enter data and then view
|
|
||||||
// the results. This link will help.
|
|
||||||
$("#invoice-lease").html('<A HREF="/pmgr/site/leases/view/' +
|
|
||||||
$(grid_id).getCell(lease_id, 'Lease-id').replace(/^#/,'') +
|
|
||||||
'">' +
|
|
||||||
$(grid_id).getCell(lease_id, 'Lease-number') +
|
|
||||||
'</A>');
|
|
||||||
$("#invoice-unit").html($(grid_id).getCell(lease_id, 'Unit-name'));
|
$("#invoice-unit").html($(grid_id).getCell(lease_id, 'Unit-name'));
|
||||||
$("#invoice-customer").html($(grid_id).getCell(lease_id, 'Customer-name'));
|
$("#invoice-customer").html($(grid_id).getCell(lease_id, 'Customer-name'));
|
||||||
$("#invoice-rent").html($(grid_id).getCell(lease_id, 'Lease-rent'));
|
$("#invoice-rent").html($(grid_id).getCell(lease_id, 'Lease-rent'));
|
||||||
@@ -117,6 +154,7 @@ function onRowSelect(grid_id, lease_id) {
|
|||||||
$("#invoice-deposit").html($(grid_id).getCell(lease_id, 'Lease-deposit')
|
$("#invoice-deposit").html($(grid_id).getCell(lease_id, 'Lease-deposit')
|
||||||
? $(grid_id).getCell(lease_id, 'Lease-deposit')
|
? $(grid_id).getCell(lease_id, 'Lease-deposit')
|
||||||
: '-');
|
: '-');
|
||||||
|
lease_charge_through = $(grid_id).getCell(lease_id, 'Lease-charge_through_date')
|
||||||
|
|
||||||
// Hide the "no lease" message and show the current lease
|
// Hide the "no lease" message and show the current lease
|
||||||
$(".lease-selection-invalid").hide();
|
$(".lease-selection-invalid").hide();
|
||||||
@@ -142,6 +180,78 @@ function onGridState(grid_id, state) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setNextRent(id) {
|
||||||
|
var chg_thru;
|
||||||
|
$('.ChargeForm').each( function(i) {
|
||||||
|
if ($('.ChargeFormThroughDate', this).attr('id') == 'Entry'+id+'ThroughDate')
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ($('.ChargeFormAccount option:selected', this).val() == <?php echo $rentAccount ?>
|
||||||
|
&& $('.ChargeFormThroughDate', this).val()) {
|
||||||
|
var dt = new Date($('.ChargeFormThroughDate', this).val());
|
||||||
|
//$('#debug').append('Rent in ' + i + '; date ' + dt + '<BR>');
|
||||||
|
if (chg_thru == null || dt > chg_thru)
|
||||||
|
chg_thru = dt;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!chg_thru)
|
||||||
|
chg_thru = new Date(lease_charge_through);
|
||||||
|
|
||||||
|
if (chg_thru < dateEOM(chg_thru)) {
|
||||||
|
// Add a charge to finish out the month
|
||||||
|
datepickerSet('Entry'+id+'EffectiveDate', dateTomorrow(chg_thru));
|
||||||
|
datepickerSet('Entry'+id+'ThroughDate', dateEOM(chg_thru));
|
||||||
|
} else {
|
||||||
|
// Add a whole month's charge for next month
|
||||||
|
datepickerSet('Entry'+id+'EffectiveDate', dateNextBOM(chg_thru));
|
||||||
|
datepickerSet('Entry'+id+'ThroughDate', dateNextEOM(chg_thru));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now add in the amount owed based on the calculated
|
||||||
|
// effective and through dates.
|
||||||
|
prorate(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function prorate(id) {
|
||||||
|
var edt = datepickerGet('Entry'+id+'EffectiveDate');
|
||||||
|
var tdt = datepickerGet('Entry'+id+'ThroughDate');
|
||||||
|
var rent = $('#invoice-rent').html().replace(/\$/,'');
|
||||||
|
|
||||||
|
// Reset the comment. It might wipe out a user comment,
|
||||||
|
// but it's probably low risk/concern
|
||||||
|
$('#Entry'+id+'Comment').val('');
|
||||||
|
|
||||||
|
if (edt == null || tdt == null) {
|
||||||
|
alert('Can only prorate with both effective and through dates');
|
||||||
|
rent = 0;
|
||||||
|
}
|
||||||
|
else if (edt > tdt) {
|
||||||
|
alert('Effective date is later than the Through date');
|
||||||
|
rent = 0;
|
||||||
|
}
|
||||||
|
else if (tdt.getMonth() == edt.getMonth() + 1 &&
|
||||||
|
edt.getDate() == tdt.getDate() + 1) {
|
||||||
|
// appears to be anniversary billing, one full cycle
|
||||||
|
}
|
||||||
|
else if (edt.getTime() == dateBOM(edt).getTime() &&
|
||||||
|
tdt.getTime() == dateEOM(edt).getTime()) {
|
||||||
|
// appears to be one full month
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var one_day=1000*60*60*24;
|
||||||
|
var days = Math.ceil((tdt.getTime()-edt.getTime()+1)/(one_day));
|
||||||
|
var dim =
|
||||||
|
((edt.getMonth() == tdt.getMonth())
|
||||||
|
? dateEOM(edt).getDate() // prorated within the month.
|
||||||
|
: 30); // prorated across months.
|
||||||
|
rent *= days / dim;
|
||||||
|
$('#Entry'+id+'Comment').val('Rent proration: '+days+'/'+dim+' days');
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#Entry'+id+'Amount').val(fmtCurrency(rent));
|
||||||
|
}
|
||||||
|
|
||||||
function addChargeSource(flash) {
|
function addChargeSource(flash) {
|
||||||
var id = $("#charge-entry-id").val();
|
var id = $("#charge-entry-id").val();
|
||||||
addDiv('charge-entry-id', 'charge', 'charges', flash,
|
addDiv('charge-entry-id', 'charge', 'charges', flash,
|
||||||
@@ -152,26 +262,33 @@ function addChargeSource(flash) {
|
|||||||
<?php
|
<?php
|
||||||
echo FormatHelper::phpVarToJavascript
|
echo FormatHelper::phpVarToJavascript
|
||||||
($this->element('form_table',
|
($this->element('form_table',
|
||||||
array('class' => "item invoice ledger-entry entry",
|
array('id' => 'Entry%{id}Form',
|
||||||
|
'class' => "ChargeForm item invoice ledger-entry entry",
|
||||||
//'with_name_after' => ':',
|
//'with_name_after' => ':',
|
||||||
'field_prefix' => 'Entry.%{id}',
|
'field_prefix' => 'Entry.%{id}',
|
||||||
'fields' => array
|
'fields' => array
|
||||||
("account_id" => array('name' => 'Account',
|
("account_id" => array('name' => 'Account',
|
||||||
'opts' =>
|
'opts' =>
|
||||||
array('options' => $chargeAccounts,
|
array('class' => 'ChargeFormAccount',
|
||||||
|
'options' => $chargeAccounts,
|
||||||
'value' => $defaultAccount,
|
'value' => $defaultAccount,
|
||||||
),
|
),
|
||||||
|
'between' => '<A HREF="#" ONCLICK="setNextRent(\'%{id}\'); return false;">Rent</A>',
|
||||||
),
|
),
|
||||||
"effective_date" => array('opts' =>
|
"effective_date" => array('opts' =>
|
||||||
array('type' => 'text'),
|
array('class' => 'ChargeFormEffectiveDate',
|
||||||
|
'type' => 'text'),
|
||||||
'between' => '<A HREF="#" ONCLICK="datepickerBOM(\'TransactionStamp\',\'Entry%{id}EffectiveDate\'); return false;">BOM</A>',
|
'between' => '<A HREF="#" ONCLICK="datepickerBOM(\'TransactionStamp\',\'Entry%{id}EffectiveDate\'); return false;">BOM</A>',
|
||||||
),
|
),
|
||||||
"through_date" => array('opts' =>
|
"through_date" => array('opts' =>
|
||||||
array('type' => 'text'),
|
array('class' => 'ChargeFormThroughDate',
|
||||||
|
'type' => 'text'),
|
||||||
'between' => '<A HREF="#" ONCLICK="datepickerEOM(\'Entry%{id}EffectiveDate\',\'Entry%{id}ThroughDate\'); return false;">EOM</A>',
|
'between' => '<A HREF="#" ONCLICK="datepickerEOM(\'Entry%{id}EffectiveDate\',\'Entry%{id}ThroughDate\'); return false;">EOM</A>',
|
||||||
),
|
),
|
||||||
"amount" => true,
|
"amount" => array('opts' => array('class' => 'ChargeFormAmount invoice amount'),
|
||||||
"comment" => array('opts' => array('size' => 50)),
|
'between' => '<A HREF="#" ONCLICK="prorate(\'%{id}\'); return false;">Prorate</A>',
|
||||||
|
),
|
||||||
|
"comment" => array('opts' => array('class' => 'ChargeFormComment', 'size' => 50)),
|
||||||
),
|
),
|
||||||
))) . "+\n";
|
))) . "+\n";
|
||||||
?>
|
?>
|
||||||
@@ -179,43 +296,40 @@ function addChargeSource(flash) {
|
|||||||
'</FIELDSET>'
|
'</FIELDSET>'
|
||||||
);
|
);
|
||||||
|
|
||||||
$("#Entry"+id+"EffectiveDate")
|
datepicker("Entry"+id+"EffectiveDate");
|
||||||
.attr('autocomplete', 'off')
|
datepicker("Entry"+id+"ThroughDate");
|
||||||
.datepicker({ constrainInput: true,
|
|
||||||
numberOfMonths: [1, 1],
|
|
||||||
showCurrentAtPos: 0,
|
|
||||||
dateFormat: 'mm/dd/yy' });
|
|
||||||
|
|
||||||
$("#Entry"+id+"ThroughDate")
|
return id;
|
||||||
.attr('autocomplete', 'off')
|
|
||||||
.datepicker({ constrainInput: true,
|
|
||||||
numberOfMonths: [1, 1],
|
|
||||||
showCurrentAtPos: 0,
|
|
||||||
dateFormat: 'mm/dd/yy' });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--></script>
|
--></script>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
; // align
|
; // align
|
||||||
|
// Re-Enable warnings
|
||||||
|
Configure::write('debug', $saved_debug_state);
|
||||||
|
|
||||||
echo $this->element('leases', array
|
if (empty($movein))
|
||||||
('config' => array
|
echo $this->element('leases', array
|
||||||
('grid_div_id' => 'leases-list',
|
('config' => array
|
||||||
'grid_div_class' => 'text-below',
|
('grid_div_id' => 'leases-list',
|
||||||
'caption' => ('<A HREF="#" ONCLICK="$(\'#leases-list .HeaderButton\').click();'.
|
'grid_div_class' => 'text-below',
|
||||||
' return false;">Select Lease</A>'),
|
'caption' => ('<A HREF="#" ONCLICK="$(\'#leases-list .HeaderButton\').click();'.
|
||||||
'grid_setup' => array('hiddengrid' => isset($lease['Lease']['id'])),
|
' return false;">Select Lease</A>'),
|
||||||
'grid_events' => array('onSelectRow' =>
|
'grid_setup' => array('hiddengrid' => isset($lease['id'])),
|
||||||
array('ids' =>
|
'grid_events' => array('onSelectRow' =>
|
||||||
'if (ids != null){onRowSelect("#"+$(this).attr("id"), ids);}'),
|
array('ids' =>
|
||||||
'onHeaderClick' =>
|
'if (ids != null){onRowSelect("#"+$(this).attr("id"), ids);}'),
|
||||||
array('gridstate' =>
|
'onHeaderClick' =>
|
||||||
'onGridState("#"+$(this).attr("id"), gridstate)'),
|
array('gridstate' =>
|
||||||
),
|
'onGridState("#"+$(this).attr("id"), gridstate)'),
|
||||||
'nolinks' => true,
|
),
|
||||||
'limit' => 10,
|
'include' => array('Charge-Thru'),
|
||||||
)));
|
'exclude' => array('Closed', 'Paid-Thru'),
|
||||||
|
'action' => 'active',
|
||||||
|
'nolinks' => true,
|
||||||
|
'limit' => 10,
|
||||||
|
)));
|
||||||
|
|
||||||
echo ('<DIV CLASS="invoice grid-selection-text">' .
|
echo ('<DIV CLASS="invoice grid-selection-text">' .
|
||||||
|
|
||||||
@@ -249,6 +363,11 @@ echo $form->input("Lease.id",
|
|||||||
'type' => 'hidden',
|
'type' => 'hidden',
|
||||||
'value' => 0));
|
'value' => 0));
|
||||||
|
|
||||||
|
echo $form->input("Customer.id",
|
||||||
|
array('id' => 'customer-id',
|
||||||
|
'type' => 'hidden',
|
||||||
|
'value' => 0));
|
||||||
|
|
||||||
/* echo '<fieldset CLASS="invoice">' . "\n"; */
|
/* echo '<fieldset CLASS="invoice">' . "\n"; */
|
||||||
/* echo ' <legend>Invoice</legend>' . "\n"; */
|
/* echo ' <legend>Invoice</legend>' . "\n"; */
|
||||||
|
|
||||||
@@ -267,6 +386,13 @@ echo $this->element('form_table',
|
|||||||
|
|
||||||
/* echo '</fieldset>' . "\n"; */
|
/* echo '</fieldset>' . "\n"; */
|
||||||
|
|
||||||
|
if (empty($movein)) {
|
||||||
|
echo "<BR>\n";
|
||||||
|
echo $form->input('repeat', array('type' => 'checkbox',
|
||||||
|
'id' => 'repeat',
|
||||||
|
'label' => 'Enter Multiple Invoices')) . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
echo $form->submit('Generate Invoice') . "\n";
|
echo $form->submit('Generate Invoice') . "\n";
|
||||||
?>
|
?>
|
||||||
|
|
||||||
@@ -281,41 +407,117 @@ echo $form->submit('Generate Invoice') . "\n";
|
|||||||
|
|
||||||
<?php echo $form->end('Generate Invoice'); ?>
|
<?php echo $form->end('Generate Invoice'); ?>
|
||||||
|
|
||||||
<div><H4>Request</H4><div id="request-debug"></div></div>
|
<div id="results"></div>
|
||||||
<div><H4>Response</H4><div id="response-debug"></div></div>
|
<div id="output-debug" style="display:none"></div>
|
||||||
<div><H4>Output</H4><div id="output-debug"></div></div>
|
|
||||||
|
<?php
|
||||||
|
// Warnings _really_ screw up javascript
|
||||||
|
Configure::write('debug', '0');
|
||||||
|
?>
|
||||||
|
|
||||||
<script type="text/javascript"><!--
|
<script type="text/javascript"><!--
|
||||||
|
$.fn.removeCol = function(col){
|
||||||
|
if(!col){ col = 1; }
|
||||||
|
$('tr td:nth-child('+col+'), tr th:nth-child('+col+')', this).remove();
|
||||||
|
};
|
||||||
|
|
||||||
|
function addHidden(id, fld, name) {
|
||||||
|
$('#Entry'+id+fld).after
|
||||||
|
('<input type="hidden"' +
|
||||||
|
' name="data[Entry]['+id+']['+name+']"' +
|
||||||
|
' value="' + $('#Entry'+id+fld).val() + '">');
|
||||||
|
}
|
||||||
|
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
$("#TransactionStamp")
|
datepicker('TransactionStamp');
|
||||||
.attr('autocomplete', 'off')
|
|
||||||
.datepicker({ constrainInput: true,
|
<?php if (isset($lease['id'])): ?>
|
||||||
numberOfMonths: [1, 1],
|
$("#lease-id").val(<?php echo $lease['id']; ?>);
|
||||||
showCurrentAtPos: 0,
|
$("#customer-id").val(<?php echo $customer['id']; ?>);
|
||||||
dateFormat: 'mm/dd/yy' });
|
|
||||||
|
$("#invoice-lease").html("<?php echo '#'.$lease['number']; ?>");
|
||||||
|
$("#invoice-unit").html("<?php echo $unit['name']; ?>");
|
||||||
|
$("#invoice-customer").html("<?php echo $customer['name']; ?>");
|
||||||
|
$("#invoice-rent").html("<?php echo FormatHelper::currency($lease['rent']); ?>");
|
||||||
|
$("#invoice-late").html("<?php echo FormatHelper::currency($defaultLate); ?>");
|
||||||
|
$("#invoice-deposit").html("<?php echo FormatHelper::currency($lease['deposit']); ?>");
|
||||||
|
lease_charge_through = <?php
|
||||||
|
if ($lease['charge_through_date'])
|
||||||
|
echo 'new Date("'.date('m/d/Y', strtotime($lease['charge_through_date'])).'")';
|
||||||
|
elseif ($lease['paid_through_date'])
|
||||||
|
echo 'new Date("'.date('m/d/Y', strtotime($lease['paid_through_date'])).'")';
|
||||||
|
else
|
||||||
|
echo 'dateYesterday("'.date('m/d/Y', strtotime($lease['movein_date'])).'")';
|
||||||
|
?>;
|
||||||
|
|
||||||
|
<?php else: ?>
|
||||||
|
$("#lease-id").val(0);
|
||||||
|
$("#customer-id").val(<?php echo empty($movein) ? 0 : $customer['id']; ?>);
|
||||||
|
$("#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");
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
|
||||||
|
<?php if (empty($movein)): ?>
|
||||||
|
|
||||||
resetForm();
|
resetForm();
|
||||||
|
datepickerNow('TransactionStamp');
|
||||||
|
|
||||||
<?php if (isset($lease['Lease']['id'])): ?>
|
<?php else: ?>
|
||||||
$("#lease-id").val(<?php echo $lease['Lease']['id']; ?>);
|
|
||||||
//$("#invoice-lease").html("<?php echo '#'.$lease['Lease']['number']; ?>");
|
var id;
|
||||||
$("#invoice-lease").html('<A HREF="/pmgr/site/leases/view/' +
|
resetForm(true);
|
||||||
"<?php echo $lease['Lease']['id']; ?>" +
|
|
||||||
'">#' +
|
$("#TransactionStamp").attr('disabled', true);
|
||||||
"<?php echo $lease['Lease']['number']; ?>" +
|
$("#TransactionStamp").val("<?php echo date('m/d/Y', $movein['time']); ?>");
|
||||||
'</A>');
|
$('#TransactionStamp').after
|
||||||
$("#invoice-unit").html("<?php echo $lease['Unit']['name']; ?>");
|
('<input type="hidden"' +
|
||||||
$("#invoice-customer").html("<?php echo $lease['Customer']['name']; ?>");
|
' name="data[Transaction][stamp]"' +
|
||||||
$("#invoice-rent").html("<?php echo FormatHelper::currency($lease['Lease']['rent']); ?>");
|
' value="' + $("#TransactionStamp").val() + '">');
|
||||||
$("#invoice-late").html('$10.00');
|
$("#TransactionComment").val('Move-In Charges');
|
||||||
$("#invoice-deposit").html("<?php echo FormatHelper::currency($lease['Lease']['deposit']); ?>");
|
|
||||||
|
<?php if ($movein['deposit'] != 0): ?>
|
||||||
|
id = addChargeSource(false);
|
||||||
|
$('#Entry'+id+'Form').removeCol(2);
|
||||||
|
$('#Entry'+id+'Form input, #Entry'+id+'Form select').attr('disabled', true);
|
||||||
|
$('#Entry'+id+'EffectiveDate').val("<?php echo date('m/d/Y', $movein['effective_time']); ?>");
|
||||||
|
addHidden(id, 'EffectiveDate', 'effective_date');
|
||||||
|
$('#Entry'+id+'AccountId').val(<?php echo $securityDepositAccount; ?>);
|
||||||
|
addHidden(id, 'AccountId', 'account_id');
|
||||||
|
$('#Entry'+id+'Amount').val("<?php echo FormatHelper::currency($movein['deposit']); ?>");
|
||||||
|
addHidden(id, 'Amount', 'amount');
|
||||||
|
$('#Entry'+id+'Comment').removeAttr('disabled');
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
id = addChargeSource(false);
|
||||||
|
$('#Entry'+id+'Form').removeCol(2);
|
||||||
|
$('#Entry'+id+'Form input, #Entry'+id+'Form select').attr('disabled', true);
|
||||||
|
setNextRent(id);
|
||||||
|
addHidden(id, 'EffectiveDate', 'effective_date');
|
||||||
|
addHidden(id, 'ThroughDate', 'through_date');
|
||||||
|
addHidden(id, 'AccountId', 'account_id');
|
||||||
|
addHidden(id, 'Amount', 'amount');
|
||||||
|
$('#Entry'+id+'Comment').removeAttr('disabled');
|
||||||
|
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
|
||||||
|
<?php if (isset($lease['id'])): ?>
|
||||||
onGridState(null, 'hidden');
|
onGridState(null, 'hidden');
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
onGridState(null, 'visible');
|
onGridState(null, 'visible');
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ($this->params['dev']): ?>
|
||||||
|
$('#output-debug').html('Post Output');
|
||||||
|
$('#output-debug').show();
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
});
|
});
|
||||||
--></script>
|
--></script>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a href="#" onClick="$('#debug').html(''); return false;">Clear Debug Output</a>
|
|
||||||
|
|||||||
@@ -26,14 +26,53 @@ $move_type = preg_replace("/.*_/", "", $this->action);
|
|||||||
// Reset the form
|
// Reset the form
|
||||||
function resetForm() {
|
function resetForm() {
|
||||||
$("#customer-id").val(0);
|
$("#customer-id").val(0);
|
||||||
$("#move-customer").html("INTERNAL ERROR");
|
|
||||||
$("#unit-id").val(0);
|
$("#unit-id").val(0);
|
||||||
|
$("#lease-id").val(0);
|
||||||
|
$("#move-customer").html("INTERNAL ERROR");
|
||||||
$("#move-unit").html("INTERNAL ERROR");
|
$("#move-unit").html("INTERNAL ERROR");
|
||||||
|
$("#move-lease").html("INTERNAL ERROR");
|
||||||
datepickerNow('LeaseMoveDate', false);
|
datepickerNow('LeaseMoveDate', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pre-submit callback
|
||||||
|
function verifyRequest() {
|
||||||
|
//$("#debug").html('');
|
||||||
|
<?php if ($move_type === 'out'): ?>
|
||||||
|
|
||||||
|
if (!($("#lease-id").val() > 0)) {
|
||||||
|
//$("#debug").append('<P>Missing Lease ID');
|
||||||
|
alert("Please select the lease");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
<?php else: ?>
|
||||||
|
|
||||||
|
if (!($("#customer-id").val() > 0)) {
|
||||||
|
//$("#debug").append('<P>Missing Customer ID');
|
||||||
|
alert("Please select the customer");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!($("#unit-id").val() > 0)) {
|
||||||
|
//$("#debug").append('<P>Missing Unit ID');
|
||||||
|
alert("Please select the unit");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
//$("#debug").append('OK');
|
||||||
|
//return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
function onRowSelect(grid_id, item_type, item_id) {
|
function onRowSelect(grid_id, item_type, item_id) {
|
||||||
cell_name = item_type.charAt(0).toUpperCase() + item_type.substr(1) + "-name";
|
cell_name = item_type.charAt(0).toUpperCase() + item_type.substr(1);
|
||||||
|
if (item_type == 'lease')
|
||||||
|
cell_name += "-number";
|
||||||
|
else
|
||||||
|
cell_name += "-name";
|
||||||
|
|
||||||
// Set the item id that will be returned with the form
|
// Set the item id that will be returned with the form
|
||||||
$("#"+item_type+"-id").val(item_id);
|
$("#"+item_type+"-id").val(item_id);
|
||||||
@@ -41,6 +80,28 @@ function onRowSelect(grid_id, item_type, item_id) {
|
|||||||
// Get the item name from the grid
|
// Get the item name from the grid
|
||||||
$("#move-"+item_type).html($(grid_id).getCell(item_id, cell_name));
|
$("#move-"+item_type).html($(grid_id).getCell(item_id, cell_name));
|
||||||
|
|
||||||
|
// If a unit was selected, update the rent and deposit
|
||||||
|
if (item_type == 'unit') {
|
||||||
|
$("#LeaseRent").val($(grid_id).getCell(item_id, 'Unit-rent'));
|
||||||
|
$("#LeaseDeposit").val($(grid_id).getCell(item_id, 'Unit-deposit'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a unit was selected, update the "Create new customer" link
|
||||||
|
if (item_type == 'unit') {
|
||||||
|
$("#customer-selection-new-url").attr
|
||||||
|
('href',
|
||||||
|
"<?php echo
|
||||||
|
$html->url(array('controller' => 'customers',
|
||||||
|
'action' => 'add')); ?>"
|
||||||
|
+ '/' + $("#unit-id").val());
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a lease was selected, update the customer and unit
|
||||||
|
if (item_type == 'lease') {
|
||||||
|
$("#move-unit").html($(grid_id).getCell(item_id, 'Unit-name'));
|
||||||
|
$("#move-customer").html($(grid_id).getCell(item_id, 'Customer-name'));
|
||||||
|
}
|
||||||
|
|
||||||
// Hide the "no customer" message and show the current customer
|
// Hide the "no customer" message and show the current customer
|
||||||
$("."+item_type+"-selection-invalid").hide();
|
$("."+item_type+"-selection-invalid").hide();
|
||||||
$("."+item_type+"-selection-valid").show();
|
$("."+item_type+"-selection-valid").show();
|
||||||
@@ -50,12 +111,12 @@ function onRowSelect(grid_id, item_type, item_id) {
|
|||||||
|
|
||||||
function onGridState(grid_id, item_type, state) {
|
function onGridState(grid_id, item_type, state) {
|
||||||
if (state == 'visible') {
|
if (state == 'visible') {
|
||||||
|
$("."+item_type+"-selection-new").show();
|
||||||
$("."+item_type+"-selection-invalid").hide();
|
$("."+item_type+"-selection-invalid").hide();
|
||||||
$("."+item_type+"-selection-valid").hide();
|
$("."+item_type+"-selection-valid").hide();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//if ($(grid_id).getGridParam("selrow"))
|
$("."+item_type+"-selection-new").hide();
|
||||||
//alert("id:" + $("#"+item_type+"-id").val());
|
|
||||||
if ($("#"+item_type+"-id").val() > 0) {
|
if ($("#"+item_type+"-id").val() > 0) {
|
||||||
$("."+item_type+"-selection-invalid").hide();
|
$("."+item_type+"-selection-invalid").hide();
|
||||||
$("."+item_type+"-selection-valid").show();
|
$("."+item_type+"-selection-valid").show();
|
||||||
@@ -72,7 +133,42 @@ function onGridState(grid_id, item_type, state) {
|
|||||||
<?php
|
<?php
|
||||||
; // align
|
; // align
|
||||||
|
|
||||||
if ($move_type !== 'out') {
|
if ($move_type === 'out') {
|
||||||
|
echo $this->element('leases', array
|
||||||
|
('config' => array
|
||||||
|
('grid_div_id' => 'leases-list',
|
||||||
|
'grid_div_class' => 'text-below',
|
||||||
|
'caption' => ('<A HREF="#" ONCLICK="$(\'#leases-list .HeaderButton\').click();'.
|
||||||
|
' return false;">Select Lease</A>'),
|
||||||
|
'grid_setup' => array('hiddengrid' => isset($lease['id'])),
|
||||||
|
'grid_events' => array('onSelectRow' =>
|
||||||
|
array('ids' =>
|
||||||
|
'if (ids != null){onRowSelect("#"+$(this).attr("id"), "lease", ids);}'),
|
||||||
|
'onHeaderClick' =>
|
||||||
|
array('gridstate' =>
|
||||||
|
'onGridState("#"+$(this).attr("id"), "lease", gridstate)'),
|
||||||
|
),
|
||||||
|
'exclude' => array('Closed'),
|
||||||
|
'action' => 'active',
|
||||||
|
'nolinks' => true,
|
||||||
|
'limit' => 10,
|
||||||
|
)));
|
||||||
|
|
||||||
|
echo ('<DIV CLASS="move-inout grid-selection-text">' .
|
||||||
|
|
||||||
|
'<DIV CLASS="lease-selection-valid" style="display:none">' .
|
||||||
|
'Lease <SPAN id="move-lease"></SPAN>' . ' / ' .
|
||||||
|
'Unit: <SPAN id="move-unit"></SPAN>' . ' / ' .
|
||||||
|
'Customer: <SPAN id="move-customer"></SPAN>' .
|
||||||
|
'</DIV>' .
|
||||||
|
|
||||||
|
'<DIV CLASS="lease-selection-invalid" style="display:none">' .
|
||||||
|
'Please select lease' .
|
||||||
|
'</DIV>' .
|
||||||
|
|
||||||
|
'</DIV>' . "\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
echo $this->element('customers', array
|
echo $this->element('customers', array
|
||||||
('config' => array
|
('config' => array
|
||||||
('grid_div_id' => 'customers-list',
|
('grid_div_id' => 'customers-list',
|
||||||
@@ -90,22 +186,27 @@ if ($move_type !== 'out') {
|
|||||||
'nolinks' => true,
|
'nolinks' => true,
|
||||||
'limit' => 10,
|
'limit' => 10,
|
||||||
)));
|
)));
|
||||||
}
|
|
||||||
|
|
||||||
echo ('<DIV CLASS="move-inout grid-selection-text">' .
|
echo ('<DIV CLASS="move-inout grid-selection-text">' .
|
||||||
|
|
||||||
'<DIV CLASS="customer-selection-valid" style="display:none">' .
|
'<DIV CLASS="customer-selection-new" style="display:none">' .
|
||||||
'Customer: <SPAN id="move-customer"></SPAN>' .
|
$html->link('Create a new Customer',
|
||||||
'</DIV>' .
|
array('controller' => 'customers',
|
||||||
|
'action' => 'add',
|
||||||
|
(empty($unit['id']) ? null : $unit['id'])),
|
||||||
|
array('id' => 'customer-selection-new-url')) .
|
||||||
|
'</DIV>' .
|
||||||
|
|
||||||
'<DIV CLASS="customer-selection-invalid" style="display:none">' .
|
'<DIV CLASS="customer-selection-valid" style="display:none">' .
|
||||||
'Please select customer' .
|
'Customer: <SPAN id="move-customer"></SPAN>' .
|
||||||
'</DIV>' .
|
'</DIV>' .
|
||||||
|
|
||||||
'</DIV>' . "\n");
|
'<DIV CLASS="customer-selection-invalid" style="display:none">' .
|
||||||
|
'Please select customer' .
|
||||||
|
'</DIV>' .
|
||||||
|
|
||||||
|
'</DIV>' . "\n");
|
||||||
|
|
||||||
if ($move_type !== 'out') {
|
|
||||||
echo $this->element('units', array
|
echo $this->element('units', array
|
||||||
('config' => array
|
('config' => array
|
||||||
('grid_div_id' => 'units-list',
|
('grid_div_id' => 'units-list',
|
||||||
@@ -120,43 +221,47 @@ if ($move_type !== 'out') {
|
|||||||
array('gridstate' =>
|
array('gridstate' =>
|
||||||
'onGridState("#"+$(this).attr("id"), "unit", gridstate)'),
|
'onGridState("#"+$(this).attr("id"), "unit", gridstate)'),
|
||||||
),
|
),
|
||||||
'action' => 'unoccupied',
|
'include' => array('Deposit'),
|
||||||
|
'exclude' => array('Balance'),
|
||||||
|
'action' => 'vacant',
|
||||||
'nolinks' => true,
|
'nolinks' => true,
|
||||||
'limit' => 10,
|
'limit' => 10,
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
echo ('<DIV CLASS="move-inout grid-selection-text">' .
|
||||||
|
|
||||||
|
'<DIV CLASS="unit-selection-valid" style="display:none">' .
|
||||||
|
'Unit: <SPAN id="move-unit"></SPAN>' .
|
||||||
|
'</DIV>' .
|
||||||
|
|
||||||
|
'<DIV CLASS="unit-selection-invalid" style="display:none">' .
|
||||||
|
'Please select unit' .
|
||||||
|
'</DIV>' .
|
||||||
|
|
||||||
|
'</DIV>' . "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
echo ('<DIV CLASS="move-inout grid-selection-text">' .
|
|
||||||
|
|
||||||
'<DIV CLASS="unit-selection-valid" style="display:none">' .
|
|
||||||
'Unit: <SPAN id="move-unit"></SPAN>' .
|
|
||||||
'</DIV>' .
|
|
||||||
|
|
||||||
'<DIV CLASS="unit-selection-invalid" style="display:none">' .
|
|
||||||
'Please select unit' .
|
|
||||||
'</DIV>' .
|
|
||||||
|
|
||||||
'</DIV>' . "\n");
|
|
||||||
|
|
||||||
echo $form->create(null, array('id' => 'move-inout-form',
|
echo $form->create(null, array('id' => 'move-inout-form',
|
||||||
|
'onsubmit' => 'return verifyRequest();',
|
||||||
'url' => array('controller' => 'leases',
|
'url' => array('controller' => 'leases',
|
||||||
'action' => $move_action)));
|
'action' => $move_action)));
|
||||||
|
|
||||||
echo $form->input("Lease.customer_id",
|
|
||||||
array('id' => 'customer-id',
|
|
||||||
'type' => 'hidden',
|
|
||||||
'value' => 0));
|
|
||||||
|
|
||||||
echo $form->input("Lease.unit_id",
|
|
||||||
array('id' => 'unit-id',
|
|
||||||
'type' => 'hidden',
|
|
||||||
'value' => 0));
|
|
||||||
|
|
||||||
if ($move_type === 'out') {
|
if ($move_type === 'out') {
|
||||||
echo $form->input('Lease.id',
|
echo $form->input('Lease.id',
|
||||||
array('type' => 'hidden',
|
array('id' => 'lease-id',
|
||||||
'value' => $lease['id'],
|
'type' => 'hidden',
|
||||||
));
|
'value' => 0));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo $form->input("Lease.customer_id",
|
||||||
|
array('id' => 'customer-id',
|
||||||
|
'type' => 'hidden',
|
||||||
|
'value' => 0));
|
||||||
|
|
||||||
|
echo $form->input("Lease.unit_id",
|
||||||
|
array('id' => 'unit-id',
|
||||||
|
'type' => 'hidden',
|
||||||
|
'value' => 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
echo $this->element('form_table',
|
echo $this->element('form_table',
|
||||||
@@ -169,7 +274,20 @@ echo $this->element('form_table',
|
|||||||
'id' => "LeaseMoveDate"),
|
'id' => "LeaseMoveDate"),
|
||||||
'between' => '<A HREF="#" ONCLICK="datepickerNow(\'LeaseMoveDate\', false); return false;">Now</A>',
|
'between' => '<A HREF="#" ONCLICK="datepickerNow(\'LeaseMoveDate\', false); return false;">Now</A>',
|
||||||
),
|
),
|
||||||
"comment" =>
|
) +
|
||||||
|
($move_type === 'in' ? array
|
||||||
|
("deposit" =>
|
||||||
|
array('opts' => array
|
||||||
|
('value' => (!empty($unit)
|
||||||
|
? FormatHelper::currency($unit['deposit'])
|
||||||
|
: null))),
|
||||||
|
"rent" =>
|
||||||
|
array('opts' => array
|
||||||
|
('value' => (!empty($unit)
|
||||||
|
? FormatHelper::currency($unit['rent'])
|
||||||
|
: null))),
|
||||||
|
) : array()) + array
|
||||||
|
("comment" =>
|
||||||
($move_type !== 'out'
|
($move_type !== 'out'
|
||||||
? array('opts' => array('size' => 50))
|
? array('opts' => array('size' => 50))
|
||||||
: null),
|
: null),
|
||||||
@@ -198,15 +316,23 @@ echo $form->end('Perform Move ' . ucfirst($move_type));
|
|||||||
|
|
||||||
<script type="text/javascript"><!--
|
<script type="text/javascript"><!--
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
$("#LeaseMoveDate")
|
datepicker('LeaseMoveDate');
|
||||||
.attr('autocomplete', 'off')
|
|
||||||
.datepicker({ constrainInput: true,
|
|
||||||
numberOfMonths: [1, 1],
|
|
||||||
showCurrentAtPos: 0,
|
|
||||||
dateFormat: 'mm/dd/yy' });
|
|
||||||
|
|
||||||
resetForm();
|
resetForm();
|
||||||
|
|
||||||
|
<?php if ($move_type === 'out') { ?>
|
||||||
|
|
||||||
|
<?php if (isset($lease['id'])): ?>
|
||||||
|
$("#lease-id").val(<?php echo $lease['id']; ?>);
|
||||||
|
$("#move-lease").html("#<?php echo $lease['number']; ?>");
|
||||||
|
$("#move-customer").html("<?php echo $customer['name']; ?>");
|
||||||
|
$("#move-unit").html("<?php echo $unit['name']; ?>");
|
||||||
|
onGridState(null, 'lease', 'hidden');
|
||||||
|
<?php else: ?>
|
||||||
|
onGridState(null, 'lease', 'visible');
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php } else { /* end (move_type === 'out') */ ?>
|
||||||
|
|
||||||
<?php if (isset($customer['id'])): ?>
|
<?php if (isset($customer['id'])): ?>
|
||||||
$("#customer-id").val(<?php echo $customer['id']; ?>);
|
$("#customer-id").val(<?php echo $customer['id']; ?>);
|
||||||
$("#move-customer").html("<?php echo $customer['name']; ?>");
|
$("#move-customer").html("<?php echo $customer['name']; ?>");
|
||||||
@@ -222,6 +348,10 @@ echo $form->end('Perform Move ' . ucfirst($move_type));
|
|||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
onGridState(null, 'unit', 'visible');
|
onGridState(null, 'unit', 'visible');
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php } /* end (move_type === 'out') */ ?>
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
--></script>
|
--></script>
|
||||||
|
|
||||||
|
|||||||
74
site/views/leases/overview.ctp
Normal file
74
site/views/leases/overview.ctp
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<?php /* -*- mode:PHP -*- */
|
||||||
|
|
||||||
|
echo '<div class="lease overview">' . "\n";
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
* Overview Main Section
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
$rows = array();
|
||||||
|
$rows[] = array('', FormatHelper::currency($overview['']));
|
||||||
|
|
||||||
|
echo $this->element('table',
|
||||||
|
array('class' => 'item lease detail',
|
||||||
|
'caption' => '',
|
||||||
|
'rows' => $rows,
|
||||||
|
'column_class' => array('field', 'value')));
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
**********************************************************************
|
||||||
|
* Supporting Elements Section
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo '<div CLASS="detail supporting">' . "\n";
|
||||||
|
|
||||||
|
$headers = array('', 'Count');
|
||||||
|
$row_class = array();
|
||||||
|
$rows = array();
|
||||||
|
foreach ($overview['months'] AS $month) {
|
||||||
|
$row_class[] = 'subheader';
|
||||||
|
$rows[] = array($month['name']);
|
||||||
|
|
||||||
|
$odd = 1;
|
||||||
|
$row_class[] = array('subitem', $odd ? 'oddrow' : 'evenrow');
|
||||||
|
$rows[] = array('Beginning of Month', $month['start']); $odd = !$odd;
|
||||||
|
$row_class[] = array('subitem', $odd ? 'oddrow' : 'evenrow');
|
||||||
|
$rows[] = array('+ Move-Ins', $month['movein']); $odd = !$odd;
|
||||||
|
$row_class[] = array('subitem', $odd ? 'oddrow' : 'evenrow');
|
||||||
|
$rows[] = array('- Move-Outs', $month['moveout']); $odd = !$odd;
|
||||||
|
|
||||||
|
$row_class[] = 'grand';
|
||||||
|
$rows[] = array('End of ' . $month['name'], $month['finish']);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo $this->element('table',
|
||||||
|
array('class' => 'item lease-overview overview list',
|
||||||
|
'caption' => 'Leased Units By Month',
|
||||||
|
'headers' => $headers,
|
||||||
|
'rows' => $rows,
|
||||||
|
'row_class' => $row_class,
|
||||||
|
'suppress_alternate_rows' => true
|
||||||
|
));
|
||||||
|
|
||||||
|
?>
|
||||||
|
<script type="text/javascript"><!--
|
||||||
|
jQuery(document).ready(function(){
|
||||||
|
jQuery('table.overview td.subheader').attr('colSpan', 2);
|
||||||
|
});
|
||||||
|
--></script>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
/* End "detail supporting" div */
|
||||||
|
echo '</div>' . "\n";
|
||||||
|
|
||||||
|
/* End page div */
|
||||||
|
echo '</div>' . "\n";
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
<?php /* -*- mode:PHP -*- */
|
|
||||||
|
|
||||||
echo '<div class="account deposit">' . "\n";
|
|
||||||
echo '<H2>Perform Bank Deposit</H2>' . "\n";
|
|
||||||
echo '<P>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 '<P><BR>' . "\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' => ('<A HREF="#" ONCLICK="$(\'#'.$grid_div_id.' .HeaderButton\').click();'.
|
|
||||||
' return false;">Items in '.$acct['Account']['name'].' Ledger</A>'),
|
|
||||||
'grid_setup' => array('hiddengrid' => true),
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
$options = array();
|
|
||||||
foreach ($depositableAccount AS $acct) {
|
|
||||||
$options[$acct['Account']['id']] = $acct['Account']['name'];
|
|
||||||
}
|
|
||||||
|
|
||||||
echo $form->input('Deposit.Account.id', array('label' => 'Deposit Account ',
|
|
||||||
'options' => $options));
|
|
||||||
echo $form->end('Perform Deposit');
|
|
||||||
|
|
||||||
/* End page div */
|
|
||||||
echo '</div>' . "\n";
|
|
||||||
@@ -18,7 +18,6 @@ if (isset($lease['Lease']))
|
|||||||
|
|
||||||
$rows = array();
|
$rows = array();
|
||||||
|
|
||||||
$rows[] = array('ID', $lease['id']);
|
|
||||||
$rows[] = array('Number', $lease['number']);
|
$rows[] = array('Number', $lease['number']);
|
||||||
$rows[] = array('Lease Type', $lease_type['name']);
|
$rows[] = array('Lease Type', $lease_type['name']);
|
||||||
$rows[] = array('Unit', $html->link($unit['name'],
|
$rows[] = array('Unit', $html->link($unit['name'],
|
||||||
@@ -39,7 +38,6 @@ $rows[] = array('Notice Received', FormatHelper::date($lease['notice_received_d
|
|||||||
$rows[] = array('Closed', FormatHelper::date($lease['close_date'], true));
|
$rows[] = array('Closed', FormatHelper::date($lease['close_date'], true));
|
||||||
$rows[] = array('Deposit', FormatHelper::currency($lease['deposit']));
|
$rows[] = array('Deposit', FormatHelper::currency($lease['deposit']));
|
||||||
$rows[] = array('Rent', FormatHelper::currency($lease['rent']));
|
$rows[] = array('Rent', FormatHelper::currency($lease['rent']));
|
||||||
$rows[] = array('Paid Through', FormatHelper::date($lease['paid_through'], true));
|
|
||||||
$rows[] = array('Comment', $lease['comment']);
|
$rows[] = array('Comment', $lease['comment']);
|
||||||
|
|
||||||
|
|
||||||
@@ -57,7 +55,10 @@ echo $this->element('table',
|
|||||||
echo '<div class="infobox">' . "\n";
|
echo '<div class="infobox">' . "\n";
|
||||||
$rows = array();
|
$rows = array();
|
||||||
$rows[] = array('Security Deposit:', FormatHelper::currency($outstandingDeposit));
|
$rows[] = array('Security Deposit:', FormatHelper::currency($outstandingDeposit));
|
||||||
$rows[] = array('Balance:', FormatHelper::currency($outstandingBalance));
|
$rows[] = array('Balance Owed:', FormatHelper::currency($outstandingBalance));
|
||||||
|
$rows[] = array('Paid Through:', FormatHelper::date($lease['paid_through_date'], false));
|
||||||
|
if ($lease['delinquent'])
|
||||||
|
$rows[] = array('Delinquent:', FormatHelper::age($lease['paid_through_date'], 'delinquent'));
|
||||||
echo $this->element('table',
|
echo $this->element('table',
|
||||||
array('class' => 'summary',
|
array('class' => 'summary',
|
||||||
'rows' => $rows,
|
'rows' => $rows,
|
||||||
@@ -77,6 +78,21 @@ echo '</div>' . "\n";
|
|||||||
echo '<div CLASS="detail supporting">' . "\n";
|
echo '<div CLASS="detail supporting">' . "\n";
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* Unpaid Charges
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo $this->element('statement_entries', array
|
||||||
|
(// Grid configuration
|
||||||
|
'config' => array
|
||||||
|
('caption' => 'Outstanding Charges',
|
||||||
|
'limit' => 10,
|
||||||
|
'action' => 'unreconciled',
|
||||||
|
'filter' => array('StatementEntry.lease_id' => $lease['id']),
|
||||||
|
'exclude' => array('Customer', 'Unit'),
|
||||||
|
)));
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* Lease Account History
|
* Lease Account History
|
||||||
*/
|
*/
|
||||||
@@ -84,8 +100,8 @@ echo '<div CLASS="detail supporting">' . "\n";
|
|||||||
echo $this->element('statement_entries', array
|
echo $this->element('statement_entries', array
|
||||||
(// Grid configuration
|
(// Grid configuration
|
||||||
'config' => array
|
'config' => array
|
||||||
('caption' => 'Account',
|
('caption' => 'Lease Statement',
|
||||||
'filter' => array('Lease.id' => $lease['id']),
|
'filter' => array('Lease.id' => $lease['id']),
|
||||||
'include' => array('Through'),
|
'include' => array('Through'),
|
||||||
'exclude' => array('Customer', 'Lease', 'Unit'),
|
'exclude' => array('Customer', 'Lease', 'Unit'),
|
||||||
)));
|
)));
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user