Compare commits

...

6 Commits

Author SHA1 Message Date
abijah
861eabc6b5 Forgot the new files on the last checkin
git-svn-id: file:///svn-source/pmgr/branches/statements_20090623@185 97e9348a-65ac-dc4b-aefc-98561f571b83
2009-06-24 17:18:25 +00:00
abijah
6baa7fa6e6 Nowhere near complete, but must snapshot prior to my Boston trip.
git-svn-id: file:///svn-source/pmgr/branches/statements_20090623@184 97e9348a-65ac-dc4b-aefc-98561f571b83
2009-06-24 17:16:39 +00:00
abijah
8cb45ad1d6 Branch for adding the concepts of statements. I suspect I'll end up killing it.
git-svn-id: file:///svn-source/pmgr/branches/statements_20090623@183 97e9348a-65ac-dc4b-aefc-98561f571b83
2009-06-24 17:14:39 +00:00
abijah
ce4fa4131a More changes. I just can't seem to come up with a solution that works that I like. The problem now, without invoice/receipt, is that one check cannot cleanly pay for two units.
git-svn-id: file:///svn-source/pmgr/branches/single_AR_20090622@182 97e9348a-65ac-dc4b-aefc-98561f571b83
2009-06-24 00:33:39 +00:00
abijah
80f8bd36d5 Nowhere near done yet, but checking in a snapshot of semi-working code. There is some simultaneous support for both with and without use of the Invoice/Receipt account. I want to do away with them completely, but will need to change how sitelink payments are mapped (right now, they split a payment into multiple parts to match the charge).
git-svn-id: file:///svn-source/pmgr/branches/single_AR_20090622@181 97e9348a-65ac-dc4b-aefc-98561f571b83
2009-06-23 19:04:41 +00:00
abijah
7aa1100cac Moving to the standard accounting method of a single Account Receiveable.
git-svn-id: file:///svn-source/pmgr/branches/single_AR_20090622@180 97e9348a-65ac-dc4b-aefc-98561f571b83
2009-06-22 23:46:03 +00:00
24 changed files with 1087 additions and 538 deletions

View File

@@ -633,14 +633,8 @@ CREATE TABLE `pmgr_customers` (
-- If NULL, rely on the contact info exclusively -- If NULL, rely on the contact info exclusively
`name` VARCHAR(80) DEFAULT NULL, `name` VARCHAR(80) DEFAULT NULL,
-- A customer gets their own account, although any -- Statement of charges/payments
-- lease specific charge (rent, late fees, etc) will `statement_id` INT(10) UNSIGNED NOT NULL,
-- be debited against the lease account. This one
-- will be used for non-lease related charges, as
-- well as charges that intentionally span more than
-- one lease (such as one security deposit to cover
-- two or more units).
`account_id` INT(10) UNSIGNED NOT NULL,
-- Primary Contact... every customer must have one -- Primary Contact... every customer must have one
-- (and presumably, most customers will _be_ one). -- (and presumably, most customers will _be_ one).
@@ -703,12 +697,13 @@ CREATE TABLE `pmgr_leases` (
-- Allow user to specify their own lease numbers -- Allow user to specify their own lease numbers
-- If NULL, `id` will be used -- If NULL, `id` will be used
`number` VARCHAR(20) DEFAULT NULL, -- `number` VARCHAR(20) DEFAULT NULL,
`number` INT(10) UNSIGNED DEFAULT NULL,
`lease_type_id` INT(10) UNSIGNED NOT NULL, `lease_type_id` INT(10) UNSIGNED NOT NULL,
`unit_id` INT(10) UNSIGNED NOT NULL, `unit_id` INT(10) UNSIGNED NOT NULL,
`customer_id` INT(10) UNSIGNED NOT NULL, `customer_id` INT(10) UNSIGNED NOT NULL,
`account_id` INT(10) UNSIGNED NOT NULL, `statement_id` INT(10) UNSIGNED NOT NULL,
`late_schedule_id` INT(10) UNSIGNED DEFAULT NULL, `late_schedule_id` INT(10) UNSIGNED DEFAULT NULL,
`lease_date` DATE NOT NULL, `lease_date` DATE NOT NULL,
@@ -866,15 +861,18 @@ LOCK TABLES `pmgr_accounts` WRITE;
INSERT INTO `pmgr_accounts` (`type`, `name`, `trackable`) INSERT INTO `pmgr_accounts` (`type`, `name`, `trackable`)
VALUES VALUES
('ASSET', 'A/R', 1), ('ASSET', 'A/R', 1),
('ASSET', 'Invoice', 1),
('ASSET', 'Receipt', 1),
('LIABILITY', 'A/P', 1), ('LIABILITY', 'A/P', 1),
('LIABILITY', 'Tax', 0), ('LIABILITY', 'Tax', 0),
('LIABILITY', 'Customer Credit', 1), ('LIABILITY', 'Customer Credit', 1),
('ASSET', 'Bank', 0), ('ASSET', 'Bank', 0),
('ASSET', 'Payment', 0), ('ASSET', 'Till', 0),
('LIABILITY', 'Security Deposit', 1), ('LIABILITY', 'Security Deposit', 1),
('INCOME', 'Rent', 0), ('INCOME', 'Rent', 0),
('INCOME', 'Late Charge', 0), ('INCOME', 'Late Charge', 0),
('EXPENSE', 'Concession', 0); ('EXPENSE', 'Concession', 0),
('EXPENSE', 'Bad Debt', 0);
UNLOCK TABLES; UNLOCK TABLES;
@@ -965,6 +963,8 @@ CREATE TABLE `pmgr_ledger_entries` (
`name` VARCHAR(80) DEFAULT NULL, `name` VARCHAR(80) DEFAULT NULL,
`monetary_source_id` INT(10) UNSIGNED DEFAULT NULL, -- NULL if internal transfer `monetary_source_id` INT(10) UNSIGNED DEFAULT NULL, -- NULL if internal transfer
`transaction_id` INT(10) UNSIGNED NOT NULL, `transaction_id` INT(10) UNSIGNED NOT NULL,
`customer_id` INT(10) UNSIGNED DEFAULT NULL,
`lease_id` INT(10) UNSIGNED DEFAULT NULL,
`amount` FLOAT(12,2) NOT NULL, `amount` FLOAT(12,2) NOT NULL,
`debit_ledger_id` INT(10) UNSIGNED NOT NULL, `debit_ledger_id` INT(10) UNSIGNED NOT NULL,
@@ -986,13 +986,27 @@ CREATE TABLE `pmgr_reconciliations` (
`debit_ledger_entry_id` INT(10) UNSIGNED NOT NULL, `debit_ledger_entry_id` INT(10) UNSIGNED NOT NULL,
`credit_ledger_entry_id` INT(10) UNSIGNED NOT NULL, `credit_ledger_entry_id` INT(10) UNSIGNED NOT NULL,
`terminal_ledger_entry_id` INT(10) UNSIGNED DEFAULT NULL, `amount` FLOAT(12,2) NOT NULL,
`amount` FLOAT(12,2) NOT NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8; ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ######################################################################
-- ######################################################################
-- ######################################################################
-- ######################################################################
-- ######################################################################
-- ######################################################################
-- ######################################################################
-- ######################################################################
-- ######################################################################
-- ##
-- ## MONETARY
-- ##
-- ---------------------------------------------------------------------- -- ----------------------------------------------------------------------
-- ---------------------------------------------------------------------- -- ----------------------------------------------------------------------
-- TABLE pmgr_monetary_sources -- TABLE pmgr_monetary_sources
@@ -1047,6 +1061,59 @@ UNLOCK TABLES;
-- ######################################################################
-- ######################################################################
-- ######################################################################
-- ######################################################################
-- ######################################################################
-- ######################################################################
-- ######################################################################
-- ######################################################################
-- ######################################################################
-- ##
-- ## STATEMENTS
-- ##
-- ## Statements are supplementary financial information. They should
-- ## NEVER be used in financial calculations, but rather are secondary
-- ## information, to be created where needed.
-- ----------------------------------------------------------------------
-- ----------------------------------------------------------------------
-- TABLE pmgr_statements
DROP TABLE IF EXISTS `pmgr_statements`;
CREATE TABLE `pmgr_statements` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`comment` VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------------------------------------------------
-- ----------------------------------------------------------------------
-- TABLE pmgr_statement_entries
DROP TABLE IF EXISTS `pmgr_statement_entries`;
CREATE TABLE `pmgr_statement_entries` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`type` ENUM('CHARGE',
'PAYMENT')
NOT NULL,
`statement_id` INT(10) UNSIGNED NOT NULL,
`ledger_entry_id` INT(10) UNSIGNED NOT NULL,
`amount` FLOAT(12,2) NOT NULL,
`comment` VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ###################################################################### -- ######################################################################
-- ###################################################################### -- ######################################################################

View File

@@ -92,6 +92,32 @@ sub addRow {
} }
######################################################################
######################################################################
## updateRow
sub updateRow {
my ($table, $id, $cols) = @_;
die unless $table;
die unless $id;
die unless ref($cols) eq 'HASH';
die "Table `$table` is unknown!"
unless defined $newdb{'tables'}{$table};
die "Table `$table` : ID `$id` does not exist!"
unless $newdb{'tables'}{$table}{'rows'}[$id];
# For debug purposes
my $line = (caller())[2];
$cols->{'--UPDATE-LINE--'} = [] unless $cols->{'--UPDATE-LINE--'};
push(@{$cols->{'--UPDATE-LINE--'}}, "updateRow called from line: $line");
#$newdb{'tables'}{$table}{'rows'}[$id] = $cols;
return $id;
}
###################################################################### ######################################################################
###################################################################### ######################################################################
## query ## query
@@ -145,7 +171,13 @@ sub executeSchema {
sub buildTables { sub buildTables {
foreach my $table (values %{$newdb{'tables'}}) { foreach my $table (values %{$newdb{'tables'}}) {
printf(STDERR "%-30s : %d rows\n", $table->{'name'}, int(@{$table->{'rows'}})); my $count = 0;
foreach (@{$table->{'rows'}}) {
next unless defined $_;
++$count;
}
printf(STDERR "%-30s : %d rows\n", $table->{'name'}, $count);
foreach (@{$table->{'rows'}}) { foreach (@{$table->{'rows'}}) {
next unless defined $_; next unless defined $_;
@@ -437,9 +469,9 @@ foreach $row (@$result) {
'comment' => undef }); 'comment' => undef });
$newdb{'lookup'}{'account'}{$row->{'name'}} $newdb{'lookup'}{'account'}{$row->{'name'}}
= {'account' => $row->{'id'}, = {'account_id' => $row->{'id'},
'tillable' => $row->{'tillable'}, 'tillable' => $row->{'tillable'},
'ledger' => $newdb{'tables'}{'ledgers'}{'autoid'} }; 'ledger_id' => $newdb{'tables'}{'ledgers'}{'autoid'} };
if ((!defined $newdb{'tables'}{'accounts'}{'autoid'}) || if ((!defined $newdb{'tables'}{'accounts'}{'autoid'}) ||
$row->{'id'} > $newdb{'tables'}{'accounts'}{'autoid'}) { $row->{'id'} > $newdb{'tables'}{'accounts'}{'autoid'}) {
@@ -449,7 +481,7 @@ foreach $row (@$result) {
# For compatibility, while deciding on account names # For compatibility, while deciding on account names
$newdb{'lookup'}{'account'}{'Cash'} $newdb{'lookup'}{'account'}{'Cash'}
= $newdb{'lookup'}{'account'}{'Payment'}; = $newdb{'lookup'}{'account'}{'Till'};
$newdb{'lookup'}{'charge_type'} = {}; $newdb{'lookup'}{'charge_type'} = {};
$newdb{'lookup'}{'charge_type'}{'Rent'} = $newdb{'lookup'}{'charge_type'}{'Rent'} =
@@ -474,15 +506,15 @@ foreach $row (@$result) {
$newdb{'lookup'}{'payment_type'} = {}; $newdb{'lookup'}{'payment_type'} = {};
$newdb{'lookup'}{'payment_type'}{1} $newdb{'lookup'}{'payment_type'}{1}
= { 'name' => 'Cash', 'account' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Cash'} }; = { 'name' => 'Cash', 'account_name' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Cash'} };
$newdb{'lookup'}{'payment_type'}{2} $newdb{'lookup'}{'payment_type'}{2}
= { 'name' => 'Check', 'account' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Check'} }; = { 'name' => 'Check', 'account_name' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Check'} };
$newdb{'lookup'}{'payment_type'}{3} $newdb{'lookup'}{'payment_type'}{3}
= { 'name' => 'Money Order', 'account' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Money Order'} }; = { 'name' => 'Money Order', 'account_name' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Money Order'} };
$newdb{'lookup'}{'payment_type'}{4} $newdb{'lookup'}{'payment_type'}{4}
= { 'name' => 'ACH', 'account' => 'Bank', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'ACH'} }; = { 'name' => 'ACH', 'account_name' => 'Bank', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'ACH'} };
$newdb{'lookup'}{'payment_type'}{12} $newdb{'lookup'}{'payment_type'}{12}
= { 'name' => 'Concession', 'account' => 'Concession', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Other Non-Tillable'} }; = { 'name' => 'Concession', 'account_name' => 'Concession', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Other Non-Tillable'} };
$newdb{'ids'}{'monetary_source'} = {}; $newdb{'ids'}{'monetary_source'} = {};
@@ -490,14 +522,14 @@ $newdb{'ids'}{'monetary_source'}{'internal'} = undef;
addRow('monetary_sources', addRow('monetary_sources',
{ 'monetary_type_id' => $newdb{'lookup'}{'monetary_type'}{'Cash'}{'id'}, { 'monetary_type_id' => $newdb{'lookup'}{'monetary_type'}{'Cash'}{'id'},
'name' => 'Cash Source', 'name' => 'Cash',
'comment' => 'Monetary source used for any cash transaction' }); 'comment' => 'Monetary source used for any cash transaction' });
$newdb{'ids'}{'monetary_source'}{'Cash'} = $newdb{'ids'}{'monetary_source'}{'Cash'} =
$newdb{'tables'}{'monetary_sources'}{'autoid'}; $newdb{'tables'}{'monetary_sources'}{'autoid'};
addRow('monetary_sources', addRow('monetary_sources',
{ 'monetary_type_id' => $newdb{'lookup'}{'monetary_type'}{'Other Non-Tillable'}{'id'}, { 'monetary_type_id' => $newdb{'lookup'}{'monetary_type'}{'Other Non-Tillable'}{'id'},
'name' => 'Closing Monies Credited', 'name' => 'Closing',
'comment' => 'Credited at the closing table' }); 'comment' => 'Credited at the closing table' });
$newdb{'ids'}{'monetary_source'}{'Closing'} = $newdb{'ids'}{'monetary_source'}{'Closing'} =
$newdb{'tables'}{'monetary_sources'}{'autoid'}; $newdb{'tables'}{'monetary_sources'}{'autoid'};
@@ -651,6 +683,13 @@ foreach $row (@{query($sdbh, $query)}) {
$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}} $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}
= { 'name' => "$row->{'LastName'}, $row->{'FirstName'}" }; = { 'name' => "$row->{'LastName'}, $row->{'FirstName'}" };
# Each tenants receives a statement
addRow('statements',
{ 'comment' => ("Statement for " .
$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'name'}) });
$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'statement_id'} =
$newdb{'tables'}{'statements'}{'autoid'};
addRow('contacts', addRow('contacts',
{ 'first_name' => $row->{'FirstName'}, { 'first_name' => $row->{'FirstName'},
'middle_name' => $row->{'MiddleName'}, 'middle_name' => $row->{'MiddleName'},
@@ -661,34 +700,16 @@ foreach $row (@{query($sdbh, $query)}) {
$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'} = $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'} =
$newdb{'tables'}{'contacts'}{'autoid'}; $newdb{'tables'}{'contacts'}{'autoid'};
# Every customer gets their own account
addRow('accounts',
{ 'type' => 'ASSET',
'trackable' => 1,
'name' => ('Customer #' . ($newdb{'tables'}{'customers'}{'autoid'}+1) .
' ('.$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'name'} . ')'),
'comment' => undef });
#'comment' => 'For direct customer transaction, NOT lease charges!' });
addRow('ledgers',
{ 'account_id' => $newdb{'tables'}{'accounts'}{'autoid'},
'open_stamp' => '2009-01-01',
'comment' => undef });
$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account'} =
$newdb{'tables'}{'accounts'}{'autoid'};
$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'ledger'} =
$newdb{'tables'}{'ledgers'}{'autoid'};
addRow('customers', addRow('customers',
{ 'name' => "$row->{'LastName'}, $row->{'FirstName'}", { 'name' => "$row->{'LastName'}, $row->{'FirstName'}",
'primary_contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'}, 'statement_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'statement_id'},
'account_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account'} }); 'primary_contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'} });
$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'} = $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'} =
$newdb{'tables'}{'customers'}{'autoid'}; $newdb{'tables'}{'customers'}{'autoid'};
addRow('contacts_customers', addRow('contacts_customers',
{ 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'}, { 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'},
'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'}, 'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'},
'type' => 'TENANT' }, 'type' => 'TENANT' },
1); 1);
@@ -754,7 +775,7 @@ foreach $row (@{query($sdbh, $query)}) {
$newdb{'tables'}{'contacts'}{'autoid'}; $newdb{'tables'}{'contacts'}{'autoid'};
addRow('contacts_customers', addRow('contacts_customers',
{ 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'}, { 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'},
'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'alt'}, 'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'alt'},
'type' => 'ALTERNATE' }, 'type' => 'ALTERNATE' },
1); 1);
@@ -800,53 +821,31 @@ $query = "SELECT L.*, A.TenantID FROM TenantLedger L LEFT JOIN `Access` A ON A.L
foreach $row (@{query($sdbh, $query)}) { foreach $row (@{query($sdbh, $query)}) {
$newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}} $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}
= { 'cust' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'} }; = { 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'},
'customer_statement_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'statement_id'},
};
if (1) { # Each lease receives a statement
# Every lease gets its own account addRow('statements',
addRow('accounts', { 'comment' => ("Statement for Lease #" . $row->{'LedgerID'}) });
{ 'type' => 'ASSET', $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease_statement_id'} =
'trackable' => 1, $newdb{'tables'}{'statements'}{'autoid'};
'name' => ('Lease #' . $row->{'LedgerID'}
. ' ('.$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'name'} . ')'),
'comment' => undef });
#'comment' => 'For lease related transaction, NOT personal charges!' });
addRow('ledgers',
{ 'account_id' => $newdb{'tables'}{'accounts'}{'autoid'},
'open_stamp' => datefmt($row->{'DateIn'}),
'comment' => undef });
$newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'account'}
= $newdb{'tables'}{'accounts'}{'autoid'};
$newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'}
= $newdb{'tables'}{'ledgers'}{'autoid'};
}
else {
$newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'account'}
= $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account'};
$newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'}
= $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'ledger'};
}
$newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust_account'}
= $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account'};
$newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust_ledger'}
= $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'ledger'};
addRow('leases', addRow('leases',
{ 'number' => $row->{'LedgerID'}, { 'number' => $row->{'LedgerID'},
'statement_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease_statement_id'},
'lease_type_id' => $newdb{'tables'}{'lease_types'}{'autoid'}, 'lease_type_id' => $newdb{'tables'}{'lease_types'}{'autoid'},
'unit_id' => $newdb{'lookup'}{'unit'}{$row->{'UnitID'}}{'id'}, 'unit_id' => $newdb{'lookup'}{'unit'}{$row->{'UnitID'}}{'id'},
'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'cust'}, 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'},
'account_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'account'},
'lease_date' => datefmt($row->{'DateIn'}), 'lease_date' => datefmt($row->{'DateIn'}),
'movein_date' => datefmt($row->{'DateIn'}), 'movein_date' => datefmt($row->{'DateIn'}),
'moveout_date' => datefmt($row->{'DateOut'}), 'moveout_date' => datefmt($row->{'DateOut'}),
'close_date' => datefmt($row->{'DateClosed'}), 'close_date' => datefmt($row->{'DateClosed'}),
'amount' => $row->{'Rent'} }); 'amount' => $row->{'Rent'} });
$newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease'} = $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease_id'} =
$newdb{'tables'}{'leases'}{'autoid'}; $newdb{'tables'}{'leases'}{'autoid'};
} }
@@ -868,63 +867,59 @@ $newdb{'lookup'}{'charge'} = {};
$query = "SELECT * FROM Charges ORDER BY ChargeID"; $query = "SELECT * FROM Charges ORDER BY ChargeID";
foreach $row (@{query($sdbh, $query)}) { foreach $row (@{query($sdbh, $query)}) {
addRow('transactions', addRow('transactions',
{ 'stamp' => datefmt($row->{'ChargeDate'}), { 'stamp' => datefmt($row->{'ChargeDate'}),
'through_date' => datefmt($row->{'EndDate'}) }); 'through_date' => datefmt($row->{'EndDate'}) });
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}} $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}
= { 'tx' => $newdb{'tables'}{'transactions'}{'autoid'}, = { 'tx' => $newdb{'tables'}{'transactions'}{'autoid'},
'ledger' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'},
'amount' => $row->{'ChargeAmount'}, 'amount' => $row->{'ChargeAmount'},
'tax_amount' => $row->{'TaxAmount'}, 'tax_amount' => $row->{'TaxAmount'},
'lease_statement_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease_statement_id'},
'customer_statement_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'customer_statement_id'},
}; };
addRow('ledger_entries', addRow('ledger_entries',
{ 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'},
'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'},
'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger'}, 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'A/R'}{'ledger_id'},
'credit_ledger_id' => $newdb{'lookup'}{'charge_type'}{$row->{'ChargeDescription'}}{'ledger'}, 'credit_ledger_id' => $newdb{'lookup'}{'charge_type'}{$row->{'ChargeDescription'}}{'ledger_id'},
'amount' => $row->{'ChargeAmount'}, 'amount' => $row->{'ChargeAmount'},
'comment' => "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}" }); 'comment' => "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}" });
my $debit_entry_id = $newdb{'tables'}{'ledger_entries'}{'autoid'}, foreach ($newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_statement_id'},
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_statement_id'}) {
addRow('ledger_entries', addRow('statement_entries',
{ 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, { 'type' => 'CHARGE',
'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, 'statement_id' => $_,
'debit_ledger_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust_ledger'}, 'ledger_entry_id' => $newdb{'tables'}{'ledger_entries'}{'autoid'},
'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger'}, 'amount' => $row->{'ChargeAmount'} });
'amount' => $row->{'ChargeAmount'}, }
'comment' => "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}" });
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'terminal'}
= $debit_entry_id;
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'entry'}
= $newdb{'tables'}{'ledger_entries'}{'autoid'},
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger'}
= $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust_ledger'};
addRow('reconciliations',
{ 'debit_ledger_entry_id' => $debit_entry_id,
'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'entry'},
'terminal_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'terminal'},
'amount' => $row->{'ChargeAmount'},
});
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'}
= $newdb{'tables'}{'ledger_entries'}{'autoid'};
next unless $row->{'TaxAmount'}; next unless $row->{'TaxAmount'};
addRow('ledger_entries', addRow('ledger_entries',
{ 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'},
'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'},
'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger'}, 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'A/R'}{'ledger_id'},
'credit_ledger_id' => $newdb{'lookup'}{'charge_type'}{'Tax'}{'ledger'}, 'credit_ledger_id' => $newdb{'lookup'}{'charge_type'}{'Tax'}{'ledger_id'},
'amount' => $row->{'TaxAmount'}, 'amount' => $row->{'TaxAmount'},
'comment' => undef }); 'comment' => undef });
foreach ($newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_statement_id'},
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_statement_id'}) {
addRow('statement_entries',
{ 'type' => 'CHARGE',
'statement_id' => $_,
'ledger_entry_id' => $newdb{'tables'}{'ledger_entries'}{'autoid'},
'amount' => $row->{'TaxAmount'} });
}
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tax_entry'} $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tax_entry'}
= $newdb{'tables'}{'ledger_entries'}{'autoid'}, = $newdb{'tables'}{'ledger_entries'}{'autoid'};
} }
@@ -944,10 +939,10 @@ $query =
foreach $row (@{query($sdbh, $query)}) { foreach $row (@{query($sdbh, $query)}) {
if ($newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}) { if ($newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}) {
die unless ($newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'cust'} die unless ($newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'customer_id'}
== $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'cust'}); == $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'customer_id'});
push(@{$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'ledgers'}}, push(@{$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'ledgers'}},
$newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'}); $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger_id'});
#print Dumper $receipt_map{$row->{'ReceiptNum'}}; #print Dumper $receipt_map{$row->{'ReceiptNum'}};
next; next;
} }
@@ -958,8 +953,12 @@ foreach $row (@{query($sdbh, $query)}) {
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}} $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}
= {'tx' => $newdb{'tables'}{'transactions'}{'autoid'}, = {'tx' => $newdb{'tables'}{'transactions'}{'autoid'},
'cust' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'cust'}, # NOTE: Use of 'lease_id' would be invalid, since the
'ledgers' => [ $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger'} ] }; # receipt could be for multiple leases. 'customer_id'
# could be OK, but better to avoid this issue all
# together by excluding them both from this lookup.
'ledgers' => [ $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger_id'} ] };
} }
@@ -975,48 +974,104 @@ $newdb{'lookup'}{'payment'} = {};
$query = "SELECT * FROM Payments ORDER BY PaymentID"; $query = "SELECT * FROM Payments ORDER BY PaymentID";
foreach $row (@{query($sdbh, $query)}) foreach $row (@{query($sdbh, $query)})
{ {
my $monetary_source_id; $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}} = {};
if ($row->{'PaymentDate'} =~ m%3/25/2009%) { if ($row->{'PaymentDate'} =~ m%3/25/2009%) {
$monetary_source_id = $newdb{'ids'}{'monetary_source'}{'closing'}; $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'}
= $newdb{'ids'}{'monetary_source'}{'Closing'};
$newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'account_name'}
= 'Bank';
} }
else { else {
$monetary_source_id = $newdb{'ids'}{'monetary_source'}{ $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'}
$newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'} = $newdb{'ids'}{'monetary_source'}{
$newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'}
}; };
$newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'account_name'}
= $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'account_name'};
} }
if (!defined $monetary_source_id) { if (!$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}) {
addRow('monetary_sources', if (!defined $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'}) {
{ 'monetary_type_id' => $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'monetary_type'}{'id'}, my $name;
'name' => $row->{'RecdFrom'}, $name = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'};
'comment' => "Payment: $row->{'PaymentID'}; Type: $row->{'PaymentType'}; Check: $row->{'CheckNum'}; $row->{'Memo'}" }); if ($name eq 'Check') {
$monetary_source_id = $newdb{'tables'}{'monetary_sources'}{'autoid'}; $name = 'Check #' . $row->{'CheckNum'};
} }
addRow('monetary_sources',
{ 'monetary_type_id' => $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'monetary_type'}{'id'},
'name' => $name,
'comment' => "Payment: $row->{'PaymentID'}; Type: $row->{'PaymentType'}; Check: $row->{'CheckNum'}; $row->{'Memo'}" });
$newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'}
= $newdb{'tables'}{'monetary_sources'}{'autoid'};
}
my $payment_acct = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'account'}; $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}
= $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'};
}
addRow('ledger_entries', $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'}
{ 'monetary_source_id' => $monetary_source_id, = $newdb{'lookup'}{'account'}{$newdb{'lookup'}{'payment'}{
'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, $row->{'PaymentID'}}{'account_name'}
'debit_ledger_id' => $newdb{'lookup'}{'account'}{$payment_acct}{'ledger'}, }{'ledger_id'};
'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger'},
'amount' => $row->{'PaymentAmount'},
'comment' => "Receipt: $row->{'ReceiptNum'}; Payment: $row->{'PaymentID'}; Charge: $row->{'ChargeID'}" });
$newdb{'lookup'}{'payment'}{$row->{'PaymentID'}} # Sitelink splits one physical payment into multiple "payments" to match each charge
= { 'entry' => $newdb{'tables'}{'ledger_entries'}{'autoid'} }; # This is kludgy, but for our cases at least, brings those pseudo-payments back into
# a single one. It presumes that there is only one PaymentType per receipt.
if (!$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}) {
addRow('ledger_entries',
{ 'monetary_source_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'},
'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'},
'debit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'},
'credit_ledger_id' => $newdb{'lookup'}{'account'}{'A/R'}{'ledger_id'},
'amount' => 0,
'comment' => "Receipt: $row->{'ReceiptNum'}; " });
# Reconcile Payment to the Charge. Since tracking is due to $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}
# the A/R account (Lease Account in this case), credit/debit = $newdb{'tables'}{'ledger_entries'}{'autoid'};
# is from the perspective of that account. Namely, the charge
# was the debit to the A/R, and the payment was the credit. addRow('statement_entries',
{ 'type' => 'PAYMENT',
'statement_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_statement_id'},
'ledger_entry_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'},
'amount' => 0 });
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'statement_entry_id'}
= $newdb{'tables'}{'statement_entries'}{'autoid'};
}
$newdb{'tables'}{'ledger_entries'}{'rows'}[
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}
]{'amount'} += $row->{'PaymentAmount'};
$newdb{'tables'}{'ledger_entries'}{'rows'}[
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}
]{'comment'} .= 'P:'.$row->{'PaymentID'} . '->C:' . $row->{'ChargeID'} . '; ';
$newdb{'tables'}{'statement_entries'}{'rows'}[
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'statement_entry_id'}
]{'amount'} += $row->{'PaymentAmount'};
addRow('statement_entries',
{ 'type' => 'PAYMENT',
'statement_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_statement_id'},
'ledger_entry_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'},
'amount' => $row->{'PaymentAmount'} });
# OK, now that the receipt is reconciled, update
# payment to reference the true ledger_entry_id
$newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'}
= $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'};
# Figure out how much of the charge can be reconciled
my $reconcile_amount = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'amount'}; my $reconcile_amount = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'amount'};
$reconcile_amount = $row->{'PaymentAmount'} if $row->{'PaymentAmount'} <= $reconcile_amount; $reconcile_amount = $row->{'PaymentAmount'} if $row->{'PaymentAmount'} <= $reconcile_amount;
# Reconcile the A/R account. Since this is from the perspective
# of the A/R, charge is the debit, and payment is the credit
addRow('reconciliations', addRow('reconciliations',
{ 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'entry'}, { 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'},
'credit_ledger_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'entry'}, 'credit_ledger_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'},
'terminal_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'terminal'},
'amount' => $reconcile_amount, 'amount' => $reconcile_amount,
}); });
@@ -1033,11 +1088,12 @@ foreach $row (@{query($sdbh, $query)})
## Fake Data for Testing ## Fake Data for Testing
my %fake = my %fake =
('custid' => 2, ('customer_id' => 4,
'ledger_id' => 4,
'invoice' => [ { 'id' => 1000, 'invoice' => [ { 'id' => 1000,
'date' => '2009-05-05', 'date' => '2009-05-05',
'entry' => [ { 'id' => 2100, 'entry' => [ { 'id' => 2100,
'account' => 'Security Deposit', 'account_name' => 'Security Deposit',
'amount' => 10, 'amount' => 10,
'tax' => 0 }, 'tax' => 0 },
], ],
@@ -1046,7 +1102,7 @@ my %fake =
'date' => '2009-05-01', 'date' => '2009-05-01',
'thru' => '2009-05-31', 'thru' => '2009-05-31',
'entry' => [ { 'id' => 2110, 'entry' => [ { 'id' => 2110,
'account' => 'Rent', 'account_name' => 'Rent',
'amount' => 100, 'amount' => 100,
'tax' => 5 }, 'tax' => 5 },
], ],
@@ -1054,7 +1110,7 @@ my %fake =
{ 'id' => 1002, { 'id' => 1002,
'date' => '2009-05-11', 'date' => '2009-05-11',
'entry' => [ { 'id' => 2120, 'entry' => [ { 'id' => 2120,
'account' => 'Late Charge', 'account_name' => 'Late Charge',
'amount' => 25, 'amount' => 25,
'tax' => 0 }, 'tax' => 0 },
], ],
@@ -1115,105 +1171,137 @@ my %fake =
); );
sub fakeTesting {
$newdb{'ids'}{'ledger'}{'Cash-Old'} =
$newdb{'lookup'}{'account'}{'Cash'}{'ledger_id'};
$newdb{'ids'}{'ledger'}{'Cash-Old'} = addRow('ledgers',
$newdb{'lookup'}{'account'}{'Cash'}{'ledger'}; { 'account_id' => $newdb{'lookup'}{'account'}{'Cash'}{'account_id'},
'open_stamp' => 'NOW()',
'sequence' => 2,
'comment' => 'Opened new ledger for testing' });
addRow('ledgers', $newdb{'lookup'}{'account'}{'Cash'}{'ledger_id'} =
{ 'account_id' => $newdb{'lookup'}{'account'}{'Cash'}{'account'}, $newdb{'tables'}{'ledgers'}{'autoid'};
'open_stamp' => 'NOW()',
'sequence' => 2,
'comment' => 'Opened new ledger for testing' });
$newdb{'lookup'}{'account'}{'Cash'}{'ledger'} = my $balance = 0;
$newdb{'tables'}{'ledgers'}{'autoid'}; foreach $row (@{$newdb{'tables'}{'ledger_entries'}{'rows'}}) {
next unless defined $row;
$balance += $row->{'amount'}
if $row->{'debit_ledger_id'} == $newdb{'ids'}{'ledger'}{'Cash-Old'};
$balance -= $row->{'amount'}
if $row->{'credit_ledger_id'} == $newdb{'ids'}{'ledger'}{'Cash-Old'};
}
my $balance = 0; addRow('transactions',
foreach $row (@{$newdb{'tables'}{'ledger_entries'}{'rows'}}) { { 'stamp' => '2009-05-10' });
next unless defined $row;
$balance += $row->{'amount'}
if $row->{'debit_ledger_id'} == $newdb{'ids'}{'ledger'}{'Cash-Old'};
$balance -= $row->{'amount'}
if $row->{'credit_ledger_id'} == $newdb{'ids'}{'ledger'}{'Cash-Old'};
}
addRow('transactions', addRow('ledger_entries',
{ 'stamp' => '2009-05-10' }); { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'},
'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'},
addRow('ledger_entries', 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Cash'}{'ledger_id'},
{ 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, 'credit_ledger_id' => $newdb{'ids'}{'ledger'}{'Cash-Old'},
'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'}, 'amount' => $balance,
'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Cash'}{'ledger'}, 'name' => "Close Out ($newdb{'ids'}{'ledger'}{'Cash-Old'} -> $newdb{'tables'}{'transactions'}{'autoid'})",
'credit_ledger_id' => $newdb{'ids'}{'ledger'}{'Cash-Old'}, 'comment' => "Carrying forward old ledger balance onto new ledger" });
'amount' => $balance,
'name' => "Close Out ($newdb{'ids'}{'ledger'}{'Cash-Old'} -> $newdb{'tables'}{'transactions'}{'autoid'})",
'comment' => "Carrying forward old ledger balance onto new ledger" });
# NOTE: no tracking for the Cash account # NOTE: no tracking for the Cash account
$newdb{'tables'}{'ledgers'}{'rows'}[$newdb{'ids'}{'ledger'}{'Cash-Old'}]{'closed'} = 1; $newdb{'tables'}{'ledgers'}{'rows'}[$newdb{'ids'}{'ledger'}{'Cash-Old'}]{'closed'} = 1;
$newdb{'tables'}{'ledgers'}{'rows'}[$newdb{'ids'}{'ledger'}{'Cash-Old'}]{'close_stamp'} = 'NOW()'; $newdb{'tables'}{'ledgers'}{'rows'}[$newdb{'ids'}{'ledger'}{'Cash-Old'}]{'close_stamp'} = 'NOW()';
foreach my $ir ('invoice', 'receipt') { foreach my $ir ('invoice', 'receipt') {
foreach my $tx (@{$fake{$ir}}) { foreach my $tx (@{$fake{$ir}}) {
#print Dumper ${%$tx{'date'}}; #print Dumper ${%$tx{'date'}};
#exit; #exit;
addRow('transactions', addRow('transactions',
{ 'id' => $tx->{'id'}, { 'id' => $tx->{'id'},
'stamp' => $tx->{'date'}, 'stamp' => $tx->{'date'},
'through_date' => $tx->{'thru'}, 'through_date' => $tx->{'thru'},
'comment' => "Fake $ir" }, 'comment' => "Fake $ir" },
1); 1);
foreach my $e (@{$tx->{'entry'}}) { foreach my $e (@{$tx->{'entry'}}) {
my $dr = ($ir eq 'invoice') ? 'A/R' : 'Cash'; my $crdr = ($ir eq 'invoice') ? 'Invoice' : 'Receipt';
my $cr = ($ir eq 'invoice') ? $e->{'account'} : 'A/R'; my $dr = ($ir eq 'invoice') ? 'A/R' : 'Cash';
my $monetary_source_id; $crdr = $dr;
my $cr = ($ir eq 'invoice') ? $e->{'account_name'} : 'A/R';
my $monetary_source_id;
if (defined $e->{'type'}) { if (defined $e->{'type'}) {
addRow('monetary_sources', addRow('monetary_sources',
{ 'monetary_type_id' => $e->{'type'}, { 'monetary_type_id' => $e->{'type'},
'name' => "Money of type " . $e->{'type'}, 'name' => "Money of type " . $e->{'type'},
'comment' => "Fake Money For " . $e->{'id'} }); 'comment' => "Fake Money For " . $e->{'id'} });
$monetary_source_id = $newdb{'tables'}{'monetary_sources'}{'autoid'}; $monetary_source_id = $newdb{'tables'}{'monetary_sources'}{'autoid'};
} }
else { else {
$monetary_source_id = $newdb{'ids'}{'monetary_source'}{'internal'}; $monetary_source_id = $newdb{'ids'}{'monetary_source'}{'internal'};
} }
addRow('ledger_entries', addRow('ledger_entries',
{ 'id' => $e->{'id'}, { 'id' => $e->{'id'},
'monetary_source_id' => $monetary_source_id, 'monetary_source_id' => $monetary_source_id,
'transaction_id' => $tx->{'id'}, 'transaction_id' => $tx->{'id'},
'debit_ledger_id' => $newdb{'lookup'}{'account'}{$dr}{'ledger'}, 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'},
'credit_ledger_id' => $newdb{'lookup'}{'account'}{$cr}{'ledger'}, 'credit_ledger_id' => $newdb{'lookup'}{'account'}{$cr}{'ledger_id'},
'amount' => $e->{'amount'}, 'customer_id' => $fake{'customer_id'},
'comment' => "Fake $ir entry" }, 'lease_id' => $fake{'lease_id'},
1); 'amount' => $e->{'amount'},
'comment' => "Fake $ir entry" },
1);
foreach my $t (@{$e->{'track'}}) { # addRow('ledger_entries',
addRow('reconciliations', # { 'id' => $e->{'id'},
{ 'debit_ledger_entry_id' => $t->{'debit'}, # 'monetary_source_id' => $monetary_source_id,
'credit_ledger_entry_id' => $e->{'id'}, # 'transaction_id' => $tx->{'id'},
'terminal_ledger_entry_id' => $t->{'debit'}, # 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$dr}{'ledger_id'},
'amount' => $t->{'amount'} # 'credit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'},
}); # 'customer_id' => $fake{'customer_id'},
} # 'lease_id' => $fake{'lease_id'},
# 'amount' => $e->{'amount'},
# 'comment' => "Fake $ir entry" },
# 1);
next unless $e->{'tax'}; foreach my $t (@{$e->{'track'}}) {
addRow('reconciliations',
{ 'debit_ledger_entry_id' => $t->{'debit'},
'credit_ledger_entry_id' => $e->{'id'},
'amount' => $t->{'amount'}
});
}
addRow('ledger_entries', next unless $e->{'tax'};
{ 'id' => $e->{'id'}+1,
'monetary_source_id' => $monetary_source_id, addRow('ledger_entries',
'transaction_id' => $tx->{'id'}, { 'id' => $e->{'id'}+1,
'debit_ledger_id' => $newdb{'lookup'}{'account'}{$dr}{'ledger'}, 'monetary_source_id' => $monetary_source_id,
'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Tax'}{'ledger'}, 'transaction_id' => $tx->{'id'},
'amount' => $e->{'tax'}, 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'},
'comment' => "Fake Tax" }, 'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Tax'}{'ledger_id'},
1); 'customer_id' => $fake{'customer_id'},
} 'lease_id' => $fake{'lease_id'},
} 'amount' => $e->{'amount'},
'comment' => "Fake Tax" },
1);
# addRow('ledger_entries',
# { 'id' => $e->{'id'}+1,
# 'monetary_source_id' => $monetary_source_id,
# 'transaction_id' => $tx->{'id'},
# 'debit_ledger_id' => $newdb{'lookup'}{'account'}{$dr}{'ledger_id'},
# 'credit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'},
# 'customer_id' => $fake{'customer_id'},
# 'lease_id' => $fake{'lease_id'},
# 'amount' => $e->{'tax'},
# 'comment' => "Fake Tax" },
# 1);
}
}
}
} }
#fakeTesting();
$Data::Dumper::Sortkeys = 1; $Data::Dumper::Sortkeys = 1;
print Dumper \%newdb; print Dumper \%newdb;
# exit; # exit;

View File

@@ -305,7 +305,13 @@ class AppController extends Controller {
$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) {
if (!isset($record[$table]))
continue;
foreach (array_diff_key($fields, array_flip($special)) AS $field) { foreach (array_diff_key($fields, array_flip($special)) AS $field) {
if (!isset($record[$table][$id]) || !isset($record[$table][$field]))
continue;
// DEBUG PURPOSES ONLY! // DEBUG PURPOSES ONLY!
//$params['linkrecord'][] = compact('table', 'field', 'id', 'controller', 'record'); //$params['linkrecord'][] = compact('table', 'field', 'id', 'controller', 'record');
$record[$table][$field] = $record[$table][$field] =
@@ -338,30 +344,40 @@ class AppController extends Controller {
} }
function jqGridDataOutputRecords(&$params, &$model, &$records) { function jqGridDataOutputRecords(&$params, &$model, &$records) {
$model_alias = $model->alias; $id_field = 'jqGrid_id';
$id = 'jqGrid_id';
foreach ($records AS $record) { foreach ($records AS $record) {
echo " <row id='{$record[$id]}'>\n"; $this->jqGridDataOutputRecord($params, $model, $record,
foreach ($params['fields'] AS $field) { $record[$id_field], $params['fields']);
if (preg_match("/\./", $field)) {
list($tbl, $col) = explode(".", $field);
$data = $record[$tbl][$col];
}
else {
$data = $record[$model_alias][$field];
}
// be sure to put text data in CDATA
if (preg_match("/^\d*$/", $data))
echo " <cell>$data</cell>\n";
else
echo " <cell><![CDATA[$data]]></cell>\n";
}
echo " </row>\n";
} }
} }
function jqGridDataOutputRecord(&$params, &$model, &$record, $id, $fields) {
echo " <row id='$id'>\n";
foreach ($fields AS $field) {
$this->jqGridDataOutputRecordField($params, $model, $record, $field);
}
echo " </row>\n";
}
function jqGridDataOutputRecordField(&$params, &$model, &$record, $field) {
if (preg_match("/\./", $field)) {
list($tbl, $col) = explode(".", $field);
$data = $record[$tbl][$col];
}
else {
$data = $record[$model->alias][$field];
}
$this->jqGridDataOutputRecordCell($params, $model, $record, $field, $data);
}
function jqGridDataOutputRecordCell(&$params, &$model, &$record, $field, $data) {
// be sure to put text data in CDATA
if (preg_match("/^\d*$/", $data))
echo " <cell>$data</cell>\n";
else
echo " <cell><![CDATA[$data]]></cell>\n";
}
function jqGridDataFinalize(&$params) { function jqGridDataFinalize(&$params) {
if ($params['debug']) { if ($params['debug']) {
$xml = ob_get_contents(); $xml = ob_get_contents();

View File

@@ -78,6 +78,24 @@ class AppModel extends Model {
/**************************************************************************
**************************************************************************
**************************************************************************
* function: nameToID
* - Returns the ID of the named item
*/
function nameToID($name) {
$this->cacheQueries = true;
$item = $this->find('first', array
('recursive' => -1,
'conditions' => compact('name'),
));
$this->cacheQueries = false;
$item = current($item);
return $item['id'];
}
/************************************************************************** /**************************************************************************
************************************************************************** **************************************************************************
************************************************************************** **************************************************************************

View File

@@ -71,6 +71,7 @@ class LeasesController extends AppController {
function jqGridRecordLinks(&$params, &$model, &$records, $links) { function jqGridRecordLinks(&$params, &$model, &$records, $links) {
$links['Lease'] = array('number'); $links['Lease'] = array('number');
$links['Unit'] = array('name'); $links['Unit'] = array('name');
$links['Customer'] = array('name');
return parent::jqGridRecordLinks($params, $model, $records, $links); return parent::jqGridRecordLinks($params, $model, $records, $links);
} }
@@ -107,7 +108,6 @@ class LeasesController extends AppController {
array(// Models array(// Models
'LeaseType', 'LeaseType',
'Unit', 'Unit',
'Account' => array('CurrentLedger'),
'Customer', 'Customer',
), ),
'conditions' => array(array('Lease.id' => $id)), 'conditions' => array(array('Lease.id' => $id)),
@@ -115,23 +115,15 @@ class LeasesController extends AppController {
) )
); );
// Summarize each ledger
$this->Lease->statsMerge($lease,
$this->Lease->stats($lease['Lease']['id']));
// Obtain the overall lease balance // Obtain the overall lease balance
$this->Lease->statsMerge($lease['Lease'], $this->Lease->statsMerge($lease['Lease'],
array('stats' => $this->Lease->stats($id))); array('stats' => $this->Lease->stats($id)));
$outstanding_balance = $lease['Lease']['stats']['Account']['Ledger']['balance']; $outstanding_balance = $lease['Lease']['stats']['balance'];
// Determine the lease security deposit // Determine the lease security deposit
$deposits = $this->Lease->findSecurityDeposits($lease['Lease']['id']); $deposits = $this->Lease->findSecurityDeposits($lease['Lease']['id']);
$outstanding_deposit = $deposits['summary']['balance']; $outstanding_deposit = $deposits['summary']['balance'];
// Move the Leder stats into our alias 'CurrentLedger'
$lease['Account']['CurrentLedger'] += $lease['Account']['Ledger'];
unset($lease['Account']['Ledger']);
// Prepare to render // Prepare to render
$title = 'Lease: #' . $lease['Lease']['id']; $title = 'Lease: #' . $lease['Lease']['id'];
$this->set(compact('lease', 'title', $this->set(compact('lease', 'title',

View File

@@ -25,6 +25,14 @@ class LedgerEntriesController extends AppController {
* to jqGrid. * to jqGrid.
*/ */
function jqGridDataSetup(&$params) {
parent::jqGridDataSetup($params);
if (isset($params['custom']['ar_account'])) {
$params['custom']['account_id'] =
$this->LedgerEntry->DebitLedger->Account->accountReceivableAccountID();
}
}
function jqGridDataTables(&$params, &$model) { function jqGridDataTables(&$params, &$model) {
$link = $link =
array(// Models array(// Models
@@ -36,6 +44,16 @@ class LedgerEntriesController extends AppController {
array('fields' => array('id', 'name'), array('fields' => array('id', 'name'),
), ),
'Customer' =>
array('fields' => array('id', 'name'),
),
'Lease' =>
array('fields' => array('id', 'number'),
'Unit' =>
array('fields' => array('id', 'name'),
),
),
); );
if (isset($params['custom']['account_ftype'])) { if (isset($params['custom']['account_ftype'])) {
@@ -77,6 +95,19 @@ class LedgerEntriesController extends AppController {
); );
} }
if (isset($params['custom']['account_id'])) {
$account_id = $params['custom']['account_id'];
$link['Ledger'] =
array('fields' => array('id', 'sequence'),
'conditions' => ("Ledger.id = IF(DebitLedger.account_id = $account_id," .
" LedgerEntry.credit_ledger_id," .
" LedgerEntry.debit_ledger_id)"),
'Account' => array(
'fields' => array('id', 'name'),
),
);
}
if (isset($params['custom']['reconcile_id'])) { if (isset($params['custom']['reconcile_id'])) {
$ftype = $params['custom']['account_ftype']; $ftype = $params['custom']['account_ftype'];
$ftype = $this->LedgerEntry->DebitLedger->Account->fundamentalOpposite($ftype); $ftype = $this->LedgerEntry->DebitLedger->Account->fundamentalOpposite($ftype);
@@ -92,11 +123,14 @@ class LedgerEntriesController extends AppController {
$ledger_id = (isset($params['custom']['ledger_id']) $ledger_id = (isset($params['custom']['ledger_id'])
? $params['custom']['ledger_id'] ? $params['custom']['ledger_id']
: null); : null);
$account_id = (isset($params['custom']['account_id'])
? $params['custom']['account_id']
: null);
$account_type = (isset($params['custom']['account_type']) $account_type = (isset($params['custom']['account_type'])
? $params['custom']['account_type'] ? $params['custom']['account_type']
: null); : null);
return $model->ledgerContextFields2($ledger_id, $account_type); return $model->ledgerContextFields2($ledger_id, $account_id, $account_type);
} }
function jqGridDataConditions(&$params, &$model) { function jqGridDataConditions(&$params, &$model) {
@@ -118,20 +152,41 @@ class LedgerEntriesController extends AppController {
$conditions[] = array('Reconciliation.'.$ftype.'_ledger_entry_id' => $params['custom']['reconcile_id']); $conditions[] = array('Reconciliation.'.$ftype.'_ledger_entry_id' => $params['custom']['reconcile_id']);
} }
if (isset($params['custom']['account_id'])) {
$conditions[] =
array('OR' =>
array(array('CreditAccount.id' => $params['custom']['account_id']),
array('DebitAccount.id' => $params['custom']['account_id'])));
}
if (isset($params['custom']['customer_id'])) {
$conditions[] =
array('Customer.id' => $params['custom']['customer_id']);
}
if (isset($params['custom']['lease_id'])) {
$conditions[] =
array('Lease.id' => $params['custom']['lease_id']);
}
if (isset($params['custom']['transaction_id'])) {
$conditions[] =
array('Transaction.id' => $params['custom']['transaction_id']);
}
return $conditions; return $conditions;
} }
function jqGridRecordLinks(&$params, &$model, &$records, $links) { function jqGridRecordLinks(&$params, &$model, &$records, $links) {
$links['Transaction'] = array('id'); $links['Transaction'] = array('id');
$links['LedgerEntry'] = array('id'); $links['LedgerEntry'] = array('id');
if (isset($params['custom']['account_ftype']) || isset($params['custom']['ledger_id'])) { $links['Account'] = array('controller' => 'accounts', 'name');
$links['Account'] = array('controller' => 'accounts', 'name'); $links['DebitAccount'] = array('controller' => 'accounts', 'name');
} $links['CreditAccount'] = array('controller' => 'accounts', 'name');
else {
$links['DebitAccount'] = array('controller' => 'accounts', 'name');
$links['CreditAccount'] = array('controller' => 'accounts', 'name');
}
$links['MonetarySource'] = array('name'); $links['MonetarySource'] = array('name');
$links['Customer'] = array('name');
$links['Lease'] = array('number');
$links['Unit'] = array('name');
return parent::jqGridRecordLinks($params, $model, $records, $links); return parent::jqGridRecordLinks($params, $model, $records, $links);
} }
@@ -145,8 +200,39 @@ class LedgerEntriesController extends AppController {
function jqGridDataOrder(&$params, &$model, $index, $direction) { function jqGridDataOrder(&$params, &$model, $index, $direction) {
/* if ($index === 'balance') */ /* if ($index === 'balance') */
/* return ($index .' '. $direction); */ /* return ($index .' '. $direction); */
$order = parent::jqGridDataOrder($params, $model, $index, $direction);
return parent::jqGridDataOrder($params, $model, $index, $direction); if ($index === 'Transaction.stamp') {
$order[] = 'LedgerEntry.id ' . $direction;
}
return $order;
}
function jqGridRecordsPostProcess(&$params, &$model, &$records) {
parent::jqGridRecordsPostProcess($params, $model, $records);
$subtotal = 0;
foreach ($records AS &$record) {
$amount = (isset($record['LedgerEntry']['balance'])
? $record['LedgerEntry']['balance']
: $record['LedgerEntry']['amount']);
$record['LedgerEntry']['subtotal'] = ($subtotal += $amount);
continue;
// Experiment to minimize columns by putting the monetary source
// as the Account, when available
if ($record['MonetarySource']['name'])
$record['Account']['name'] = $record['MonetarySource']['name'];
}
}
function jqGridDataOutputRecordCell(&$params, &$model, &$record, $field, $data) {
/* if ($field === 'CreditAccount.name') { */
/* $data .= '-OK'; */
/* } */
parent::jqGridDataOutputRecordCell($params, $model, $record, $field, $data);
} }
@@ -167,6 +253,7 @@ class LedgerEntriesController extends AppController {
$entry = $this->LedgerEntry->find $entry = $this->LedgerEntry->find
('first', ('first',
array('contain' => array('MonetarySource.id', array('contain' => array('MonetarySource.id',
'MonetarySource.name',
'MonetarySource.MonetaryType.id', 'MonetarySource.MonetaryType.id',
'Transaction.id', 'Transaction.id',
'Transaction.stamp', 'Transaction.stamp',
@@ -176,6 +263,9 @@ class LedgerEntriesController extends AppController {
'CreditLedger.id', 'CreditLedger.id',
'CreditLedger.sequence', 'CreditLedger.sequence',
'CreditLedger.account_id', 'CreditLedger.account_id',
'Customer.id',
'Customer.name',
'Lease.id',
), ),
'fields' => array('LedgerEntry.id', 'fields' => array('LedgerEntry.id',
@@ -184,6 +274,7 @@ class LedgerEntriesController extends AppController {
'conditions' => array('LedgerEntry.id' => $id), 'conditions' => array('LedgerEntry.id' => $id),
)); ));
pr($entry);
// Because 'DebitLedger' and 'CreditLedger' both relate to 'Account', // Because 'DebitLedger' and 'CreditLedger' both relate to 'Account',
// CakePHP will not include them in the LedgerEntry->find (or so it // CakePHP will not include them in the LedgerEntry->find (or so it

View File

@@ -0,0 +1,116 @@
<?php
class StatementEntriesController extends AppController {
var $sidemenu_links = array();
/**************************************************************************
**************************************************************************
**************************************************************************
* override: sideMenuLinks
* - Generates controller specific links for the side menu
*/
function sideMenuLinks() {
return array_merge(parent::sideMenuLinks(), $this->sidemenu_links);
}
/**************************************************************************
**************************************************************************
**************************************************************************
* virtuals: jqGridData
* - With the application controller handling the jqGridData action,
* these virtual functions ensure that the correct data is passed
* to jqGrid.
*/
function jqGridDataTables(&$params, &$model) {
$link =
array(// Models
'LedgerEntry' =>
array('fields' => array('id'),
// Models
'Transaction' =>
array('fields' => array('id', 'stamp'),
),
'Ledger' =>
array('fields' => array('id', 'sequence'),
'conditions' => ("Ledger.id = IF(StatementEntry.type = 'CHARGE'," .
" LedgerEntry.credit_ledger_id," .
" LedgerEntry.debit_ledger_id)"),
// Models
'Account' => array('fields' => array('id', 'name'),
),
),
),
);
return array('link' => $link);
}
function jqGridDataFields(&$params, &$model) {
$fields = array('id', 'type', 'comment');
$fields[] = "IF(StatementEntry.type = 'CHARGE', StatementEntry.amount, NULL) AS 'charge'";
$fields[] = "IF(StatementEntry.type = 'PAYMENT', StatementEntry.amount, NULL) AS 'payment'";
$fields[] = "IF(StatementEntry.type = 'CHARGE', 1, -1) * StatementEntry.amount AS 'amount'";
return $fields;
}
function jqGridDataConditions(&$params, &$model) {
$conditions = parent::jqGridDataConditions($params, $model);
if (isset($params['custom']['statement_id'])) {
$conditions[] =
array('StatementEntry.statement_id' => $params['custom']['statement_id']);
}
return $conditions;
}
function jqGridRecordLinks(&$params, &$model, &$records, $links) {
$links['Transaction'] = array('id');
$links['StatementEntry'] = array('id');
$links['Account'] = array('controller' => 'accounts', 'name');
$links['LedgerEntry'] = array('id');
return parent::jqGridRecordLinks($params, $model, $records, $links);
}
function jqGridRecordsPostProcess(&$params, &$model, &$records) {
parent::jqGridRecordsPostProcess($params, $model, $records);
$subtotal = 0;
foreach ($records AS &$record) {
$amount = $record['StatementEntry']['amount'];
$record['StatementEntry']['amount'] = $amount;
$record['StatementEntry']['subtotal'] = ($subtotal += $amount);
}
}
/**************************************************************************
**************************************************************************
**************************************************************************
* 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 StatementEntry and related fields
$entry = $this->StatementEntry->find
('first',
array('contain' => array(),
'conditions' => array('StatementEntry.id' => $id),
));
// Prepare to render.
$title = "Statement Entry #{$entry['StatementEntry']['id']}";
$this->set(compact('entry', 'title'));
}
}

View File

@@ -55,7 +55,7 @@ class UnitsController extends AppController {
$link = array $link = array
('link' => ('link' =>
array(// Models array(// Models
'UnitSize' => array('fields' => array('name')), 'UnitSize' => array('fields' => array('id', 'name')),
), ),
); );
@@ -93,6 +93,11 @@ class UnitsController extends AppController {
return parent::jqGridDataOrder($params, $model, $index, $direction); return parent::jqGridDataOrder($params, $model, $index, $direction);
} }
function jqGridRecordLinks(&$params, &$model, &$records, $links) {
//$links['UnitSize'] = array('name');
$links['Unit'] = array('name', 'id');
return parent::jqGridRecordLinks($params, $model, $records, $links);
}
/************************************************************************** /**************************************************************************
************************************************************************** **************************************************************************
@@ -121,7 +126,7 @@ class UnitsController extends AppController {
// Get the balance on each lease. // Get the balance on each lease.
foreach ($unit['Lease'] AS &$lease) { foreach ($unit['Lease'] AS &$lease) {
$stats = $this->Unit->Lease->stats($lease['id']); $stats = $this->Unit->Lease->stats($lease['id']);
$lease['balance'] = $stats['Account']['Ledger']['balance']; $lease['balance'] = $stats['balance'];
} }
$outstanding_balance = 0; $outstanding_balance = 0;
@@ -130,7 +135,7 @@ class UnitsController extends AppController {
// Figure out the outstanding balance of the current lease. // Figure out the outstanding balance of the current lease.
$stats = $this->Unit->stats($id); $stats = $this->Unit->stats($id);
$outstanding_balance = $outstanding_balance =
$stats['CurrentLease']['Account']['Ledger']['balance']; $stats['CurrentLease']['balance'];
// Figure out the total security deposit for the current lease. // Figure out the total security deposit for the current lease.
$deposits = $this->Unit->Lease->findSecurityDeposits($unit['CurrentLease']['id']); $deposits = $this->Unit->Lease->findSecurityDeposits($unit['CurrentLease']['id']);

View File

@@ -82,37 +82,13 @@ class Account extends AppModel {
/************************************************************************** /**************************************************************************
************************************************************************** **************************************************************************
************************************************************************** **************************************************************************
* function: securityDepositAccountID * function: Account IDs
* - Returns the ID of the Security Deposit Account * - Returns the ID of the desired account
*/ */
function securityDepositAccountID() {
$this->cacheQueries = true;
$account = $this->find('first', array
('recursive' => -1,
'conditions' => array
(array('name' => 'Security Deposit')),
));
$this->cacheQueries = false;
return $account['Account']['id'];
}
function securityDepositAccountID() { return $this->nameToID('Security Deposit'); }
/************************************************************************** function rentAccountID() { return $this->nameToID('Rent'); }
************************************************************************** function accountReceivableAccountID() { return $this->nameToID('A/R'); }
**************************************************************************
* function:rentAccountID
* - Returns the ID of the Rent Account
*/
function rentAccountID() {
$this->cacheQueries = true;
$account = $this->find('first', array
('recursive' => -1,
'conditions' => array
(array('name' => 'Rent')),
));
$this->cacheQueries = false;
return $account['Account']['id'];
}
/************************************************************************** /**************************************************************************
@@ -122,22 +98,19 @@ class Account extends AppModel {
* - Returns an array of ledger ids from the given account * - Returns an array of ledger ids from the given account
*/ */
function ledgers($id, $all = false) { function ledgers($id, $all = false) {
$cachekey = $all ? 'all' : 'current';
if (isset($this->cache[$id]['ledgers'][$cachekey])) {
return $this->cache[$id]['ledgers'][$cachekey];
}
if ($all) { if ($all) {
$contain = array('Ledger' => array('fields' => array('Ledger.id'))); $contain = array('Ledger' => array('fields' => array('Ledger.id')));
} else { } else {
$contain = array('CurrentLedger' => array('fields' => array('CurrentLedger.id'))); $contain = array('CurrentLedger' => array('fields' => array('CurrentLedger.id')));
} }
$this->cacheQueries = true;
$account = $this->find('first', array $account = $this->find('first', array
('contain' => $contain, ('contain' => $contain,
'fields' => array(), 'fields' => array(),
'conditions' => array(array('Account.id' => $id)), 'conditions' => array(array('Account.id' => $id)),
)); ));
$this->cacheQueries = false;
if ($all) { if ($all) {
$ledger_ids = array(); $ledger_ids = array();
@@ -148,14 +121,11 @@ class Account extends AppModel {
$ledger_ids = array($account['CurrentLedger']['id']); $ledger_ids = array($account['CurrentLedger']['id']);
} }
// Save the ledgers in our cache for future reference
$this->cache[$id]['ledgers'][$cachekey] = $ledger_ids;
/* pr(array('function' => 'Account::ledgers', */ /* pr(array('function' => 'Account::ledgers', */
/* 'args' => compact('id', 'all'), */ /* 'args' => compact('id', 'all'), */
/* 'return' => $this->cache[$id]['ledgers'][$cachekey])); */ /* 'return' => $ledger_ids)); */
return $this->cache[$id]['ledgers'][$cachekey]; return $ledger_ids;
} }
@@ -234,7 +204,11 @@ class Account extends AppModel {
* (such as charges not paid). * (such as charges not paid).
*/ */
function findUnreconciledLedgerEntries($id = null, $fundamental_type = null) { function findUnreconciledLedgerEntries($id = null, $fundamental_type = null, $cond = null) {
if (!isset($cond))
$cond = array();
$cond[] = array('Account.id' => $id);
foreach (($fundamental_type foreach (($fundamental_type
? array($fundamental_type) ? array($fundamental_type)
: array('debit', 'credit')) AS $fund) { : array('debit', 'credit')) AS $fund) {
@@ -260,7 +234,7 @@ class Account extends AppModel {
'group' => ("LedgerEntry.id" . 'group' => ("LedgerEntry.id" .
" HAVING LedgerEntry.amount" . " HAVING LedgerEntry.amount" .
" <> COALESCE(SUM(Reconciliation.amount),0)"), " <> COALESCE(SUM(Reconciliation.amount),0)"),
'conditions' => array('Account.id' => $id), 'conditions' => $cond,
'fields' => array(), 'fields' => array(),
)); ));
$balance = 0; $balance = 0;
@@ -290,7 +264,7 @@ class Account extends AppModel {
* whatever algorithm is simplest. * whatever algorithm is simplest.
*/ */
function reconcileNewLedgerEntry($id, $fundamental_type, $amount) { function reconcileNewLedgerEntry($id, $fundamental_type, $amount, $cond = null) {
$ofund = $this->fundamentalOpposite($fundamental_type); $ofund = $this->fundamentalOpposite($fundamental_type);
$unreconciled = array($ofund => array('entry'=>array(), 'balance'=>0)); $unreconciled = array($ofund => array('entry'=>array(), 'balance'=>0));
$applied = 0; $applied = 0;
@@ -298,7 +272,7 @@ class Account extends AppModel {
// if there is no money in the entry, it can reconcile nothing // if there is no money in the entry, it can reconcile nothing
// don't bother wasting time sifting ledger entries. // don't bother wasting time sifting ledger entries.
if ($amount > 0) { if ($amount > 0) {
$unreconciled = $this->findUnreconciledLedgerEntries($id, $ofund); $unreconciled = $this->findUnreconciledLedgerEntries($id, $ofund, $cond);
foreach ($unreconciled[$ofund]['entry'] AS $i => &$entry) { foreach ($unreconciled[$ofund]['entry'] AS $i => &$entry) {
// Determine if amount is sufficient to cover the entry // Determine if amount is sufficient to cover the entry

View File

@@ -8,7 +8,7 @@ class Customer extends AppModel {
); );
var $belongsTo = array( var $belongsTo = array(
'Account', 'Statement',
'PrimaryContact' => array( 'PrimaryContact' => array(
'className' => 'Contact', 'className' => 'Contact',
), ),
@@ -20,11 +20,19 @@ class Customer extends AppModel {
'conditions' => 'CurrentLease.close_date IS NULL', 'conditions' => 'CurrentLease.close_date IS NULL',
), ),
'Lease', 'Lease',
'Transaction', 'LedgerEntry',
// Cheat to get Account set as part of this class
'Account',
); );
var $hasAndBelongsToMany = array( var $hasAndBelongsToMany = array(
'Contact', 'Contact',
'Transaction' => array(
'joinTable' => 'ledger_entries',
'foreignKey' => 'customer_id',
'associationForeignKey' => 'transaction_id',
),
); );
@@ -36,13 +44,26 @@ class Customer extends AppModel {
*/ */
function accountId($id) { function accountId($id) {
$this->cacheQueries = true; $this->cacheQueries = true;
$customer = $this->find('first', $item = $this->find('first',
array('contain' => false, array('contain' => false,
'fields' => array('account_id'), 'fields' => array('account_id'),
'conditions' => array(array('Customer.id' => $id)))); 'conditions' => compact('id')));
$this->cacheQueries = false; $this->cacheQueries = false;
return $customer['Customer']['account_id']; $item = current($item);
return $item['account_id'];
}
function statementID($id) {
$this->cacheQueries = true;
$item = $this->find('first', array
('recursive' => -1,
'conditions' => compact('id'),
));
$this->cacheQueries = false;
$item = current($item);
return $item['statement_id'];
} }
@@ -68,6 +89,7 @@ class Customer extends AppModel {
return $ids; return $ids;
} }
/************************************************************************** /**************************************************************************
************************************************************************** **************************************************************************
************************************************************************** **************************************************************************
@@ -75,29 +97,10 @@ class Customer extends AppModel {
* - Returns an array of security deposit entries * - Returns an array of security deposit entries
*/ */
function findSecurityDeposits($id, $link = null) { function findSecurityDeposits($id, $link = null) {
/* pr(array('function' => 'Customer::findSecurityDeposits', */ return $this->Statement->findEntriesRelatedToAccount
/* 'args' => compact('id', 'link'), */ ($this->statementId($id),
/* )); */
$entries = $this->Account->findLedgerEntriesRelatedToAccount
($this->accountId($id),
$this->Account->securityDepositAccountID(), $this->Account->securityDepositAccountID(),
true, null, $link); null, $link);
foreach ($this->leaseIds($id) AS $lease_id) {
$ledger_entries = $this->Lease->findSecurityDeposits($lease_id, $link);
$this->statsMerge($entries['summary'], $ledger_entries['summary']);
$entries['Entries'] = array_merge($entries['Entries'],
$ledger_entries['Entries']);
}
/* pr(array('function' => 'Customer::findSecurityDeposits', */
/* 'args' => compact('id', 'link'), */
/* 'vars' => compact('customer'), */
/* 'return' => compact('entries'), */
/* )); */
return $entries;
} }
@@ -110,22 +113,10 @@ class Customer extends AppModel {
*/ */
function findUnreconciledLedgerEntries($id = null, $fundamental_type = null) { function findUnreconciledLedgerEntries($id = null, $fundamental_type = null) {
$unreconciled = $this->Account->findUnreconciledLedgerEntries $unreconciled = $this->Account->findUnreconciledLedgerEntries
($this->accountId($id), $fundamental_type); ($this->Account->accountReceivableAccountID(),
$fundamental_type,
foreach ($this->leaseIds($id) AS $lease_id) { array('LedgerEntry.customer_id' => $id));
$unrec = $this->Lease->findUnreconciledLedgerEntries($lease_id,
$fundamental_type);
foreach (array_keys($unreconciled) AS $type) {
$left = &$unreconciled[$type];
$right = &$unrec[$type];
$left['entry'] = array_merge($left['entry'], $right['entry']);
$left['balance'] += $right['balance'];
}
}
return $unreconciled; return $unreconciled;
} }
@@ -146,25 +137,11 @@ class Customer extends AppModel {
*/ */
function reconcileNewLedgerEntry($id, $fundamental_type, $amount) { function reconcileNewLedgerEntry($id, $fundamental_type, $amount) {
$reconciled = $this->Account->reconcileNewLedgerEntry $reconciled = $this->Account->reconcileNewLedgerEntry
($this->accountId($id), $fundamental_type, $amount); ($this->Account->accountReceivableAccountID(),
$fundamental_type,
foreach ($this->leaseIds($id) AS $lease_id) { $amount,
foreach (array_keys($reconciled) AS $type) { array('LedgerEntry.customer_id' => $id));
$rec = $this->Lease->reconcileNewLedgerEntry($lease_id,
$fundamental_type,
$reconciled[$type]['unapplied']);
$left = &$reconciled[$type];
$right = &$rec[$type];
$left['entry'] = array_merge($left['entry'], $right['entry']);
$left['balance'] += $right['balance'];
$left['applied'] += $right['applied'];
$left['unapplied'] = $right['unapplied'];
}
}
return $reconciled; return $reconciled;
} }
@@ -189,7 +166,6 @@ class Customer extends AppModel {
'ContactEmail', 'ContactEmail',
'ContactAddress', 'ContactAddress',
), ),
'Account',
'Lease' => 'Lease' =>
array('Unit' => array('Unit' =>
array('order' => array('sort_order'), array('order' => array('sort_order'),
@@ -201,22 +177,12 @@ class Customer extends AppModel {
'conditions' => array('Customer.id' => $id), 'conditions' => array('Customer.id' => $id),
)); ));
// Add the lease balance to each lease. // Figure out the outstanding balance for this customer
foreach ($customer['Lease'] AS &$lease) {
$stats = $this->Lease->stats($lease['id']);
$lease['balance'] = $stats['Account']['Ledger']['balance'];
}
// Figure out the outstanding balance of the current lease.
$customer['stats'] = $this->stats($id); $customer['stats'] = $this->stats($id);
// Figure out the total security deposit for the current lease. // Figure out the total security deposit for the current lease.
$customer['deposits'] = $this->findSecurityDeposits($id); $customer['deposits'] = $this->findSecurityDeposits($id);
// Add statistics into the customer account.
$customer['Account'] = array_merge($customer['Account'],
$customer['stats']['Account']['Ledger']);
return $customer; return $customer;
} }
@@ -228,34 +194,11 @@ class Customer extends AppModel {
* - Returns summary data from the requested customer. * - Returns summary data from the requested customer.
*/ */
function stats($id = null) { function stats($id = null, $cond = null, $link = null) {
if (!$id) if (!$id)
return null; return null;
// Get the basic information necessary return $this->Statement->stats($this->statementID($id), $cond, $link);
$customer = $this->find('first',
array('contain' =>
array('Account' => array
('fields' => array('Account.id')),
'Lease' => array
('fields' => array('Lease.id'))
),
'conditions' => array
(array('Customer.id' => $id))));
// Get stats from the customer account, and each lease
$stats['Account'] = $this->Account->stats($customer['Account']['id']);
foreach ($customer['Lease'] AS $lease) {
$this->statsMerge($stats['Lease'], $this->Lease->stats($lease['id']));
}
// Merge the stats from both the customer specific account, as
// well as the leases. This will provide current customer standing.
$this->statsMerge($stats, $stats['Account']['Ledger']);
$this->statsMerge($stats, $stats['Lease']['Account']['Ledger']);
return $stats;
} }
} }

View File

@@ -25,27 +25,37 @@ class Lease extends AppModel {
var $belongsTo = array( var $belongsTo = array(
'LeaseType', 'LeaseType',
'Unit', 'Unit',
'Account',
'Customer', 'Customer',
'Statement',
'LateSchedule', 'LateSchedule',
); );
var $hasMany = array(
'LedgerEntry',
// Cheat to get Account set as part of this class
'Account',
);
/************************************************************************** /**************************************************************************
************************************************************************** **************************************************************************
************************************************************************** **************************************************************************
* function: accountId * function: accessors
* - Returns the accountId of the given lease
*/ */
function accountId($id) { function accountId($id) {
$this->cacheQueries = true; return $this->Account->invoiceAccountID();
$lease = $this->find('first', array }
('recursive' => -1,
'fields' => array('account_id'),
'conditions' => array(array('id' => $id)),
));
$this->cacheQueries = false;
return $lease['Lease']['account_id']; function statementID($id) {
$this->cacheQueries = true;
$item = $this->find('first', array
('recursive' => -1,
'conditions' => compact('id'),
));
$this->cacheQueries = false;
$item = current($item);
return $item['statement_id'];
} }
@@ -61,6 +71,10 @@ class Lease extends AppModel {
/* 'args' => compact('id', 'all', 'cond', 'link'), */ /* 'args' => compact('id', 'all', 'cond', 'link'), */
/* )); */ /* )); */
if (!isset($cond))
$cond = array();
$cond[] = array('LedgerEntry.lease_id' => $id);
$entries = $this->Account->findLedgerEntries($this->accountId($id), $entries = $this->Account->findLedgerEntries($this->accountId($id),
$all, $cond, $link); $all, $cond, $link);
@@ -80,21 +94,10 @@ class Lease extends AppModel {
* - Returns an array of security deposit entries * - Returns an array of security deposit entries
*/ */
function findSecurityDeposits($id, $link = null) { function findSecurityDeposits($id, $link = null) {
/* pr(array('function' => 'Lease::findSecurityDeposits', */ return $this->Statement->findEntriesRelatedToAccount
/* 'args' => compact('id', 'link'), */ ($this->statementId($id),
/* )); */
$entries = $this->Account->findLedgerEntriesRelatedToAccount
($this->accountId($id),
$this->Account->securityDepositAccountID(), $this->Account->securityDepositAccountID(),
true, null, $link); null, $link);
/* pr(array('function' => 'Lease::findSecurityDeposits', */
/* 'args' => compact('id', 'link'), */
/* 'vars' => compact('lease'), */
/* 'return' => compact('entries'), */
/* )); */
return $entries;
} }
@@ -108,7 +111,7 @@ class Lease extends AppModel {
function findUnreconciledLedgerEntries($id = null, $fundamental_type = null) { function findUnreconciledLedgerEntries($id = null, $fundamental_type = null) {
return $this->Account->findUnreconciledLedgerEntries return $this->Account->findUnreconciledLedgerEntries
($this->accountId($id), $fundamental_type); ($this->accountId($id), $fundamental_type, array('LedgerEntry.lease_id' => $id));
} }
@@ -128,7 +131,7 @@ class Lease extends AppModel {
function reconcileNewLedgerEntry($id, $fundamental_type, $amount) { function reconcileNewLedgerEntry($id, $fundamental_type, $amount) {
return $this->Account->reconcileNewLedgerEntry return $this->Account->reconcileNewLedgerEntry
($this->accountId($id), $fundamental_type, $amount); ($this->accountId($id), $fundamental_type, $amount, array('LedgerEntry.lease_id' => $id));
} }
@@ -139,23 +142,11 @@ class Lease extends AppModel {
* - Returns summary data from the requested lease. * - Returns summary data from the requested lease.
*/ */
function stats($id = null) { function stats($id = null, $cond = null, $link = null) {
if (!$id) if (!$id)
return null; return null;
// Find the associated account. return $this->Statement->stats($this->statementID($id), $cond, $link);
$lease = $this->find('first',
array('recursive' => -1,
'conditions' => array(array('Lease.id' => $id))));
// Pull the stats from the account.
$stats['Account'] = $this->Account->stats($lease['Lease']['account_id']);
// Place a summary of the stats (one lease account in this case)
// at the top level for easy summarized access.
$this->statsMerge($stats, $stats['Account']['Ledger']);
return $stats;
} }
} }

View File

@@ -115,6 +115,9 @@ class Ledger extends AppModel {
* - Returns summary data from the requested ledger. * - Returns summary data from the requested ledger.
*/ */
function stats($id, $cond = null) { function stats($id, $cond = null) {
if (!isset($cond))
$cond = array();
$cond[] = array('Ledger.id' => $id);
$stats = $this->find $stats = $this->find
('first', array ('first', array
@@ -138,8 +141,7 @@ class Ledger extends AppModel {
) * IF(LedgerEntry.amount, LedgerEntry.amount, 0) ) * IF(LedgerEntry.amount, LedgerEntry.amount, 0)
) AS balance", ) AS balance",
"COUNT(LedgerEntry.id) AS entries"), "COUNT(LedgerEntry.id) AS entries"),
'conditions' => array(isset($cond) ? $cond : array(), 'conditions' => $cond,
array('Ledger.id' => $id)),
'group' => 'Ledger.id', 'group' => 'Ledger.id',
)); ));

View File

@@ -11,6 +11,8 @@ class LedgerEntry extends AppModel {
var $belongsTo = array( var $belongsTo = array(
'MonetarySource', 'MonetarySource',
'Transaction', 'Transaction',
'Customer',
'Lease',
'DebitLedger' => array( 'DebitLedger' => array(
'className' => 'Ledger', 'className' => 'Ledger',
@@ -84,7 +86,7 @@ class LedgerEntry extends AppModel {
return $fields; return $fields;
} }
function ledgerContextFields2($ledger_id = null, $account_type = null) { function ledgerContextFields2($ledger_id = null, $account_id = null, $account_type = null) {
$fields = array('id', 'name', 'comment', 'amount'); $fields = array('id', 'name', 'comment', 'amount');
if (isset($ledger_id)) { if (isset($ledger_id)) {
@@ -93,20 +95,29 @@ class LedgerEntry extends AppModel {
$fields[] = ("IF(LedgerEntry.credit_ledger_id = $ledger_id," . $fields[] = ("IF(LedgerEntry.credit_ledger_id = $ledger_id," .
" SUM(LedgerEntry.amount), NULL) AS credit"); " SUM(LedgerEntry.amount), NULL) AS credit");
if (isset($account_type)) { if (isset($account_id) || isset($account_type)) {
if (in_array($account_type, array('ASSET', 'EXPENSE'))) $Account = new Account();
$ledger_type = 'debit'; $account_ftype = $Account->fundamentalType($account_id ? $account_id : $account_type);
else $fields[] = ("(IF(LedgerEntry.{$account_ftype}_ledger_id = $ledger_id," .
$ledger_type = 'credit';
$fields[] = ("(IF(LedgerEntry.{$ledger_type}_ledger_id = $ledger_id," .
" 1, -1) * SUM(LedgerEntry.amount)) AS balance"); " 1, -1) * SUM(LedgerEntry.amount)) AS balance");
} }
} }
elseif (isset($account_id)) {
$fields[] = ("IF(DebitLedger.account_id = $account_id," .
" SUM(LedgerEntry.amount), NULL) AS debit");
$fields[] = ("IF(CreditLedger.account_id = $account_id," .
" SUM(LedgerEntry.amount), NULL) AS credit");
$Account = new Account();
$account_ftype = ucfirst($Account->fundamentalType($account_id));
$fields[] = ("(IF({$account_ftype}Ledger.account_id = $account_id," .
" 1, -1) * SUM(LedgerEntry.amount)) AS balance");
}
return $fields; return $fields;
} }
function ledgerContextConditions($ledger_id, $account_type) { function ledgerContextConditions($ledger_id, $account_type) {
if (isset($ledger_id)) { if (isset($ledger_id)) {
return array return array

123
site/models/statement.php Normal file
View File

@@ -0,0 +1,123 @@
<?php
class Statement extends AppModel {
var $hasMany = array(
'Lease',
'Customer',
'StatementEntry',
'ChargeStatementEntry' => array(
'className' => 'StatementEntry',
'conditions' => array('type' => 'CHARGE'),
),
'PaymentStatementEntry' => array(
'className' => 'StatementEntry',
'conditions' => array('type' => 'PAYMENT'),
),
);
/**************************************************************************
**************************************************************************
**************************************************************************
* function: findStatementEntries
* - Returns an array of statement entries that belong to a given
* statement. There is extra work done... see the StatementEntry model.
*/
function findStatementEntries($id, $cond = null, $link = null) {
/* pr(array('function' => 'Statement::findStatementEntries', */
/* 'args' => compact('id', 'cond', 'link'), */
/* )); */
if (!isset($cond))
$cond = array();
$cond[] = array('Statement.id' => $id);
$entries = $this->find('all', array('link' => $link, 'conditions' => $cond));
/* pr(array('function' => 'Statement::findStatementEntries', */
/* 'args' => compact('id', 'cond', 'link'), */
/* 'return' => compact('entries'), */
/* )); */
return $entries;
}
/**************************************************************************
**************************************************************************
**************************************************************************
* function: findEntriesRelatedToAccount
* - Returns an array of statement entries that belong to the given
* account, and are related to a specific account.
*/
function findEntriesRelatedToAccount($id, $rel_ids, $cond = null, $link = null) {
/* pr(array('function' => 'Statement::findEntriesRelatedToAccount', */
/* 'args' => compact('id', 'rel_ids', 'cond', 'link'), */
/* )); */
if (!isset($cond))
$cond = array();
if (!isset($link))
$link = array();
if (!is_array($rel_ids))
$rel_ids = array($rel_ids);
$link['StatementEntry'] = array('LedgerEntry' => array('Ledger' => array('Account')));
$cond[] = array('Account.id' => $rel_ids);
$entries = $this->findStatementEntries($id, $cond, $link);
$stats = $this->stats($id, $cond, $link);
$entries = array('Entries' => $entries,
'summary' => $stats);
/* pr(array('function' => 'Statement::findEntriesRelatedToAccount', */
/* 'args' => compact('id', 'relid', 'cond', 'link'), */
/* 'return' => compact('entries'), */
/* )); */
return $entries;
}
/**************************************************************************
**************************************************************************
**************************************************************************
* function: stats
* - Returns summary data from the requested statement.
*/
function stats($id, $cond = null, $link = null) {
if (!isset($cond))
$cond = array();
if (!isset($link))
$link = array();
if (!isset($link['StatementEntry']))
$link['StatementEntry'] = array('fields' => array());
$cond[] = array('Statement.id' => $id);
$stats = $this->find
('first', array
('link' => $link,
'fields' =>
array("SUM(IF(StatementEntry.type = 'CHARGE',
StatementEntry.amount, NULL)) AS charges",
"SUM(IF(StatementEntry.type = 'PAYMENT',
StatementEntry.amount, NULL)) AS payments",
"SUM(IF(StatementEntry.type = 'CHARGE', 1, -1)
* IF(StatementEntry.amount, StatementEntry.amount, 0)
) AS balance",
"COUNT(StatementEntry.id) AS entries"),
'conditions' => $cond,
'group' => 'Statement.id',
));
// The fields are all tucked into the [0] index,
// and the rest of the array is useless (empty).
return $stats[0];
}
}
?>

View File

@@ -0,0 +1,9 @@
<?php
class StatementEntry extends AppModel {
var $belongsTo = array(
'Statement',
'LedgerEntry',
);
}

View File

@@ -63,12 +63,13 @@ echo $this->element('leases',
/********************************************************************** /**********************************************************************
* Account * Customer Statement
*/ */
echo $this->element('accounts', echo $this->element('statement_entries',
array('caption' => 'Account', array('caption' => 'Statement',
'accounts' => array($customer['Account']))); 'statement_id' => $customer['Customer']['statement_id'],
));
/* End "detail supporting" div */ /* End "detail supporting" div */

View File

@@ -143,8 +143,12 @@ foreach ($jqGridColumns AS &$col) {
} }
// Set the default sort column // Set the default sort column
reset($jqGridColumns); if (isset($sort_column)) {
$sortname = current($jqGridColumns); $sortname = $jqGridColumns[$sort_column];
} else {
reset($jqGridColumns);
$sortname = current($jqGridColumns);
}
$sortname = $sortname['index']; $sortname = $sortname['index'];
// Configure the grid setup, giving priority to user defined parameters // Configure the grid setup, giving priority to user defined parameters
@@ -185,10 +189,14 @@ $jqGrid_setup = array_merge
jQuery(document).ready(function(){ jQuery(document).ready(function(){
currencyFormatter = function(el, cellval, opts) { currencyFormatter = function(el, cellval, opts) {
if (!cellval)
return;
$(el).html(fmtCurrency(cellval)); $(el).html(fmtCurrency(cellval));
} }
idFormatter = function(el, cellval, opts) { idFormatter = function(el, cellval, opts) {
if (!cellval)
return;
$(el).html('#'+cellval); $(el).html('#'+cellval);
} }

View File

@@ -1,5 +1,30 @@
<?php /* -*- mode:PHP -*- */ <?php /* -*- mode:PHP -*- */
if (isset($account_ftype) || isset($ledger_id) || isset($account_id) || isset($ar_account)) {
$single_account = true;
} else {
$single_account = false;
}
if (isset($ledger_id) || isset($account_id) || isset($ar_account)) {
$single_amount = false;
} else {
$single_amount = true;
}
if (isset($reconcile_id)) {
$applied_amount = true;
} else {
$applied_amount = false;
}
if (isset($account_ftype)) {
$subtotal_amount = false;
} else {
$subtotal_amount = true;
}
// Define the table columns // Define the table columns
$cols = array(); $cols = array();
if (0) { if (0) {
@@ -8,33 +33,42 @@ if (isset($notxgroup))
else else
$cols['Transaction'] = array('index' => 'Transaction.id', 'formatter' => 'id'); $cols['Transaction'] = array('index' => 'Transaction.id', 'formatter' => 'id');
} else { } else {
$notxgroup = true; $notxgroup = false;
$cols['Transaction'] = array('index' => 'Transaction.id', 'formatter' => 'id'); $cols['Transaction'] = array('index' => 'Transaction.id', 'formatter' => 'id');
$cols['Entry'] = array('index' => 'LedgerEntry.id', 'formatter' => 'id'); $cols['Entry'] = array('index' => 'LedgerEntry.id', 'formatter' => 'id');
} }
$cols['Date'] = array('index' => 'Transaction.stamp', 'formatter' => 'date'); $cols['Date'] = array('index' => 'Transaction.stamp', 'formatter' => 'date');
if (isset($account_ftype) || isset($ledger_id)) {
$cols['Account'] = array('index' => 'Account.name', 'formatter' => 'longname'); if ($single_account) {
$cols['Account'] = array('index' => 'Account.name', 'formatter' => 'name');
} }
else { else {
$cols['Debit Account'] = array('index' => 'DebitAccount.name', 'formatter' => 'longname'); $cols['Debit Account'] = array('index' => 'DebitAccount.name', 'formatter' => 'name');
$cols['Credit Account'] = array('index' => 'CreditAccount.name', 'formatter' => 'longname'); $cols['Credit Account'] = array('index' => 'CreditAccount.name', 'formatter' => 'name');
} }
$cols['Source'] = array('index' => 'MonetarySource.name', 'formatter' => 'name'); $cols['Source'] = array('index' => 'MonetarySource.name', 'formatter' => 'name');
$cols['Comment'] = array('index' => 'LedgerEntry.comment', 'formatter' => 'comment', 'width'=>150); $cols['Comment'] = array('index' => 'LedgerEntry.comment', 'formatter' => 'comment', 'width'=>150);
if (isset($ledger_id)) {
if ($single_amount) {
$cols['Amount'] = array('index' => 'LedgerEntry.amount', 'formatter' => 'currency');
}
else {
$cols['Debit'] = array('index' => 'debit', 'formatter' => 'currency'); $cols['Debit'] = array('index' => 'debit', 'formatter' => 'currency');
$cols['Credit'] = array('index' => 'credit', 'formatter' => 'currency'); $cols['Credit'] = array('index' => 'credit', 'formatter' => 'currency');
} }
else {
$cols['Amount'] = array('index' => 'LedgerEntry.amount', 'formatter' => 'currency'); if ($applied_amount) {
}
if (isset($reconcile_id)) {
$cols['Applied'] = array('index' => "Reconciliation.amount", 'formatter' => 'currency'); $cols['Applied'] = array('index' => "Reconciliation.amount", 'formatter' => 'currency');
} }
$custom_post_data = compact('ledger_id', 'account_type', 'account_ftype', 'notxgroup'); if ($subtotal_amount) {
$cols['Sub-Total'] = array('index' => 'subtotal', 'formatter' => 'currency', 'sortable' => false);
}
$custom_post_data = compact('ledger_id', 'account_id', 'ar_account',
'account_type', 'account_ftype',
'customer_id', 'lease_id', 'transaction_id', 'notxgroup');
$jqGrid_options = array('jqGridColumns' => $cols, $jqGrid_options = array('jqGridColumns' => $cols,
'controller' => 'ledger_entries', 'controller' => 'ledger_entries',
@@ -42,11 +76,6 @@ $jqGrid_options = array('jqGridColumns' => $cols,
$jqGrid_options += compact('grid_div_id', 'grid_id', 'caption', 'grid_setup', 'limit'); $jqGrid_options += compact('grid_div_id', 'grid_id', 'caption', 'grid_setup', 'limit');
if (isset($ledger_id)) {
$jqGrid_options += array('action' => 'ledger',
'limit' => 50);
}
if (isset($ledger_entries)) { if (isset($ledger_entries)) {
$jqGrid_options += array('custom_ids' => $jqGrid_options += array('custom_ids' =>
array_map(create_function('$data', array_map(create_function('$data',
@@ -54,6 +83,10 @@ if (isset($ledger_entries)) {
$ledger_entries), $ledger_entries),
'limit' => 10); 'limit' => 10);
} }
else {
$jqGrid_options += array('action' => 'ledger',
'limit' => 50);
}
if (isset($reconcile_id)) { if (isset($reconcile_id)) {
$custom_post_data += compact('reconcile_id'); $custom_post_data += compact('reconcile_id');
@@ -61,5 +94,6 @@ if (isset($reconcile_id)) {
} }
$jqGrid_options += compact('custom_post_data'); $jqGrid_options += compact('custom_post_data');
$jqGrid_options['sort_column'] = 'Date';
echo $this->element('jqGrid', $jqGrid_options); echo $this->element('jqGrid', $jqGrid_options);

View File

@@ -0,0 +1,50 @@
<?php /* -*- mode:PHP -*- */
if (0) {
$subtotal_amount = false;
} else {
$subtotal_amount = true;
}
// Define the table columns
$cols = array();
$cols['ID'] = array('index' => 'StatementEntry.id', 'formatter' => 'id');
$cols['Entry'] = array('index' => 'LedgerEntry.id', 'formatter' => 'id');
$cols['Date'] = array('index' => 'Transaction.stamp', 'formatter' => 'date');
//$cols['Type'] = array('index' => 'StatementEntry.type', 'formatter' => 'name');
$cols['Account'] = array('index' => 'Account.name', 'formatter' => 'longname');
//$cols['Comment'] = array('index' => 'StatementEntry.comment', 'formatter' => 'comment', 'width'=>150);
//$cols['Amount'] = array('index' => 'StatementEntry.amount', 'formatter' => 'currency');
$cols['Charge'] = array('index' => 'charge', 'formatter' => 'currency');
$cols['Payment'] = array('index' => 'payment', 'formatter' => 'currency');
if ($subtotal_amount) {
$cols['Sub-Total'] = array('index' => 'subtotal', 'formatter' => 'currency', 'sortable' => false);
}
$custom_post_data = compact('statement_id');
$jqGrid_options = array('jqGridColumns' => $cols,
'controller' => 'statement_entries',
);
$jqGrid_options += compact('grid_div_id', 'grid_id', 'caption', 'grid_setup', 'limit');
if (isset($statement_entries)) {
$jqGrid_options += array('custom_ids' =>
array_map(create_function('$data',
'return $data["id"];'),
$statement_entries),
'limit' => 10);
}
else {
$jqGrid_options += array('action' => 'statement',
'limit' => 50);
}
$jqGrid_options += compact('custom_post_data');
$jqGrid_options['sort_column'] = 'Date';
echo $this->element('jqGrid', $jqGrid_options);

View File

@@ -11,7 +11,6 @@ echo '<div class="lease view">' . "\n";
$lease_type = $lease['LeaseType']; $lease_type = $lease['LeaseType'];
$customer = $lease['Customer']; $customer = $lease['Customer'];
$account = $lease['Account'];
$unit = $lease['Unit']; $unit = $lease['Unit'];
if (isset($lease['Lease'])) if (isset($lease['Lease']))
@@ -20,7 +19,7 @@ if (isset($lease['Lease']))
$rows = array(array('ID', $lease['id']), $rows = array(array('ID', $lease['id']),
array('Number', $lease['number']), array('Number', $lease['number']),
array('Lease Type', $lease_type['name']), array('Lease Type', $lease_type['name']),
array('Unit', $html->link($unit['id'], array('Unit', $html->link($unit['name'],
array('controller' => 'units', array('controller' => 'units',
'action' => 'view', 'action' => 'view',
$unit['id']))), $unit['id']))),
@@ -36,10 +35,6 @@ $rows = array(array('ID', $lease['id']),
array('Notice Given', FormatHelper::date($lease['notice_given_date'], true)), array('Notice Given', FormatHelper::date($lease['notice_given_date'], true)),
array('Notice Received', FormatHelper::date($lease['notice_received_date'], true)), array('Notice Received', FormatHelper::date($lease['notice_received_date'], true)),
array('Closed', FormatHelper::date($lease['close_date'], true)), array('Closed', FormatHelper::date($lease['close_date'], true)),
array('Account', $html->link($account['name'],
array('controller' => 'accounts',
'action' => 'view',
$account['id']))),
array('Deposit', FormatHelper::currency($lease['deposit'])), array('Deposit', FormatHelper::currency($lease['deposit'])),
array('Rent', FormatHelper::currency($lease['amount'])), array('Rent', FormatHelper::currency($lease['amount'])),
array('Comment', $lease['comment'])); array('Comment', $lease['comment']));
@@ -53,7 +48,7 @@ echo $this->element('table',
/********************************************************************** /**********************************************************************
* Account Info Box * Lease Info Box
*/ */
echo '<div class="infobox">' . "\n"; echo '<div class="infobox">' . "\n";
@@ -80,15 +75,15 @@ echo '<div CLASS="detail supporting">' . "\n";
/********************************************************************** /**********************************************************************
* Current Ledger * Lease Account History
*/ */
echo $this->element('ledger_entries', echo $this->element('statement_entries',
array('caption' => "Current Ledger: (#{$account['id']}-{$account['CurrentLedger']['sequence']})", array('caption' => 'Statement',
'ledger_id' => $account['CurrentLedger']['id'], 'statement_id' => $lease['statement_id'],
'account_type' => $account['type'],
)); ));
/* End "detail supporting" div */ /* End "detail supporting" div */
echo '</div>' . "\n"; echo '</div>' . "\n";

View File

@@ -13,6 +13,8 @@ $transaction = $entry['Transaction'];
$debit_ledger = $entry['DebitLedger']; $debit_ledger = $entry['DebitLedger'];
$credit_ledger = $entry['CreditLedger']; $credit_ledger = $entry['CreditLedger'];
$source = $entry['MonetarySource']; $source = $entry['MonetarySource'];
$customer = $entry['Customer'];
$lease = $entry['Lease'];
$entry = $entry['LedgerEntry']; $entry = $entry['LedgerEntry'];
$rows = array(array('ID', $entry['id']), $rows = array(array('ID', $entry['id']),
@@ -21,8 +23,20 @@ $rows = array(array('ID', $entry['id']),
'action' => 'view', 'action' => 'view',
$transaction['id']))), $transaction['id']))),
array('Timestamp', FormatHelper::datetime($transaction['stamp'])), array('Timestamp', FormatHelper::datetime($transaction['stamp'])),
array('Monetary Source', (isset($source['id']) array('Customer', (isset($customer['name'])
? $html->link('#'.$source['id'], ? $html->link($customer['name'],
array('controller' => 'customers',
'action' => 'view',
$customer['id']))
: null)),
array('Lease', (isset($lease['id'])
? $html->link('#'.$lease['id'],
array('controller' => 'leases',
'action' => 'view',
$lease['id']))
: null)),
array('Monetary Source', (isset($source['name'])
? $html->link($source['name'],
array('controller' => 'monetary_sources', array('controller' => 'monetary_sources',
'action' => 'view', 'action' => 'view',
$source['id'])) $source['id']))
@@ -67,12 +81,12 @@ echo $this->element('table',
echo '<div class="infobox">' . "\n"; echo '<div class="infobox">' . "\n";
$rows = array(); $rows = array();
if ($debit_ledger['Account']['trackable']) { if ($debit_ledger['Account']['trackable']) {
$rows[] = array('Debit Amount Reconciled:', FormatHelper::currency($stats['debit_amount_reconciled'])); $rows[] = array('Payments Received:', FormatHelper::currency($stats['debit_amount_reconciled']));
$rows[] = array('Debit Amount Remaining:', FormatHelper::currency($stats['debit_amount_remaining'])); $rows[] = array('Amount Owing:', FormatHelper::currency($stats['debit_amount_remaining']));
} }
if ($credit_ledger['Account']['trackable']) { if ($credit_ledger['Account']['trackable']) {
$rows[] = array('Credit Amount Reconciled:', FormatHelper::currency($stats['credit_amount_reconciled'])); $rows[] = array('Charges Reconciled:', FormatHelper::currency($stats['credit_amount_reconciled']));
$rows[] = array('Credit Amount Remaining:', FormatHelper::currency($stats['credit_amount_remaining'])); $rows[] = array('Unapplied Amount:', FormatHelper::currency($stats['credit_amount_remaining']));
} }
echo $this->element('table', echo $this->element('table',
array('class' => 'summary', array('class' => 'summary',
@@ -97,26 +111,25 @@ echo '<div CLASS="detail supporting">' . "\n";
* Reconciliation Ledger Entries * Reconciliation Ledger Entries
*/ */
echo $this->element('ledger_entries', if ($debit_ledger['Account']['trackable']) {
array('caption' => "Debit Applications", echo $this->element('ledger_entries',
'grid_div_id' => 'debit_reconciliation_ledger_entries', array('caption' => "Payments Received",
//'ledger_id' => $debit_ledger['id'], 'grid_div_id' => 'debit_reconciliation_ledger_entries',
//'account_type' => $debit_ledger['Account']['type'], 'account_ftype' => 'debit',
'account_ftype' => 'debit', 'reconcile_id' => $entry['id'],
'reconcile_id' => $entry['id'], //'ledger_entries' => $reconciled['debit']['entry'],
'ledger_entries' => $reconciled['debit']['entry'], ));
)); }
echo $this->element('ledger_entries', if ($credit_ledger['Account']['trackable']) {
array('caption' => "Credit Applications", echo $this->element('ledger_entries',
'grid_div_id' => 'credit_reconciliation_ledger_entries', array('caption' => "Charges Paid",
//'ledger_id' => $credit_ledger['id'], 'grid_div_id' => 'credit_reconciliation_ledger_entries',
//'account_type' => $credit_ledger['Account']['type'], 'account_ftype' => 'credit',
//'account_ftype' => 'debit', // Looking for debits to match this credit 'reconcile_id' => $entry['id'],
'account_ftype' => 'credit', //'ledger_entries' => $reconciled['credit']['entry'],
'reconcile_id' => $entry['id'], ));
'ledger_entries' => $reconciled['credit']['entry'], }
));
/* End "detail supporting" div */ /* End "detail supporting" div */

View File

@@ -54,7 +54,8 @@ echo '<div CLASS="detail supporting">' . "\n";
echo $this->element('ledger_entries', echo $this->element('ledger_entries',
array('caption' => 'Entries in Transaction', array('caption' => 'Entries in Transaction',
'ledger_entries' => $transaction['LedgerEntry'], //'ledger_entries' => $transaction['LedgerEntry'],
'transaction_id' => $transaction['Transaction']['id'],
'notxgroup' => true, 'notxgroup' => true,
)); ));

View File

@@ -57,16 +57,15 @@ echo $this->element('leases',
/********************************************************************** /**********************************************************************
* Ledger History * Current Lease Statement History
*/ */
/* foreach($unit['Lease'] AS $lease) { */
/* pr($lease); */ echo $this->element('statement_entries',
/* $caption = 'Lease #'.$lease['number'].' (Tenant: '.$lease['Customer']['name'].')'; */ array('caption' => ('Current Lease Statement (' .
/* echo $this->element('lease', */ $unit['CurrentLease']['Customer']['name'] .
/* array('caption' => $caption, */ ')'),
/* 'entries' => $lease['Customer']['Transaction'], */ 'statement_id' => $unit['CurrentLease']['statement_id']
/* 'ledger' => array('mix'=>1))); */ ));
/* } */
/* End "detail supporting" div */ /* End "detail supporting" div */

View File

@@ -65,8 +65,10 @@ tr.evnrow { background: #f4f4f4; }
*/ */
table.detail { width : 60%; table.detail { width : 60%;
float: left; } float : left; }
table.detail td.field { width: 10em; } table.detail td.field { width : 10em; }
table.item.detail td.value { white-space : normal; }
div.detail.supporting { clear : both; div.detail.supporting { clear : both;
padding-top: 1.5em; } padding-top: 1.5em; }