Definitely not perfect, but the database changes seem to be OK, along with the sitelink script. Certainly workable if not yet complete.

git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716@358 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
abijah
2009-07-21 04:16:54 +00:00
parent ae5d4763f9
commit 59e6379977
2 changed files with 261 additions and 526 deletions

View File

@@ -922,13 +922,6 @@ UNLOCK TABLES;
-- ----------------------------------------------------------------------
-- ----------------------------------------------------------------------
-- TABLE pmgr_ledgers
--
-- REVISIT <AP>: 20090605
-- We may not really need a ledgers table.
-- It's not clear to me though, as we very
-- possibly need to close out certain
-- ledgers every so often, and just carry
-- the balance forward (year end, etc).
DROP TABLE IF EXISTS `pmgr_ledgers`;
CREATE TABLE `pmgr_ledgers` (
@@ -969,123 +962,144 @@ CREATE TABLE `pmgr_transactions` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`type` ENUM('INVOICE',
'CREDIT',
'RECEIPT',
'REFUND',
'DEPOSIT',
-- 'CREDIT',
-- 'REFUND',
'TRANSFER')
NOT NULL,
`stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- The account/ledger of the transaction set
-- (e.g. A/R, Bank, etc)
`account_id` INT(10) UNSIGNED NOT NULL,
`ledger_id` INT(10) UNSIGNED NOT NULL,
-- For convenience. Actually, INVOICE will always set crdr
-- to DEBIT, RECEIPT will use CREDIT, and DEPOSIT will use
-- DEBIT
`crdr` ENUM('DEBIT',
'CREDIT')
NOT NULL,
-- amount is for convenience. It can always be calculated from
-- the associated double entries (and therefore will need to be
-- updated if they should change in any way).
`amount` FLOAT(12,2) DEFAULT NULL,
-- `customer_id` INT(10) UNSIGNED DEFAULT NULL,
-- `lease_id` INT(10) UNSIGNED DEFAULT NULL,
`comment` VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- -- -- ----------------------------------------------------------------------
-- -- -- ----------------------------------------------------------------------
-- -- -- TABLE pmgr_charge_details
-- DROP TABLE IF EXISTS `pmgr_charge_details`;
-- CREATE TABLE `pmgr_charge_details` (
-- `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
-- -- Through date is used if/when a charge covers a certain time period,
-- -- like rent. A security deposit, for example, would not use the
-- -- through date.
-- `through_date` DATE DEFAULT NULL, -- last day
-- `due_date` DATE DEFAULT NULL,
-- PRIMARY KEY (`id`)
-- ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- -- -- ----------------------------------------------------------------------
-- -- -- ----------------------------------------------------------------------
-- -- -- TABLE pmgr_payment_details
-- DROP TABLE IF EXISTS `pmgr_payment_details`;
-- CREATE TABLE `pmgr_payment_details` (
-- `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
-- -- name may (or may not) be used to clarify in reports
-- -- for example, 'Check #1234' as the payment name.
-- `name` VARCHAR(80) DEFAULT NULL,
-- -- REVISIT <AP>: 20090716
-- -- Type may needs to be another table, so that the user
-- -- can add new types. If so, they will also have to
-- -- specify the required data1/2/3/4 fields.
-- -- For now, this will work.
-- `monetary_type` ENUM('CASH',
-- 'CHECK',
-- 'MONEYORDER',
-- 'ACH',
-- 'DEBITCARD',
-- 'CREDITCARD')
-- DEFAULT NULL,
-- -- REVISIT <AP>: 20090605
-- -- Check Number;
-- -- Routing Number, Account Number;
-- -- Card Number, Expiration Date; CVV2 Code
-- -- etc.
-- -- REVISIT <AP> 20090630
-- -- I _think_ that CVV2 is NEVER supposed to
-- -- be stored ANYWHERE. Merchants agree to
-- -- use it only to verify the transaction and
-- -- then leave no record of it, so that even
-- -- if their security is compromised, no one
-- -- will know the CVV2 code unless they are
-- -- in physical possession of the card.
-- `data1` VARCHAR(80) DEFAULT NULL,
-- `data2` VARCHAR(80) DEFAULT NULL,
-- `data3` VARCHAR(80) DEFAULT NULL,
-- `data4` VARCHAR(80) DEFAULT NULL,
-- PRIMARY KEY (`id`)
-- ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- -- ----------------------------------------------------------------------
-- -- ----------------------------------------------------------------------
-- -- TABLE pmgr_entries
-- -- TABLE pmgr_ledger_entries
DROP TABLE IF EXISTS `pmgr_entries`;
CREATE TABLE `pmgr_entries` (
DROP TABLE IF EXISTS `pmgr_ledger_entries`;
CREATE TABLE `pmgr_ledger_entries` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`type` ENUM('CHARGE',
'PAYMENT',
'DEPOSIT',
'TRANSFER')
NOT NULL,
`transaction_id` INT(10) UNSIGNED NOT NULL,
-- The account/ledger of the entry
`account_id` INT(10) UNSIGNED NOT NULL,
`ledger_id` INT(10) UNSIGNED NOT NULL,
-- For convenience. Actually, CHARGE will always set crdr
-- to CREDIT and PAYMENT will use DEBIT.
`crdr` ENUM('DEBIT',
'CREDIT')
NOT NULL,
-- The actual ledgers where this entry is recorded
`double_entry_id` INT(10) UNSIGNED DEFAULT NULL,
`amount` FLOAT(12,2) NOT NULL,
`comment` VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- -- ----------------------------------------------------------------------
-- -- ----------------------------------------------------------------------
-- -- TABLE pmgr_double_entries
DROP TABLE IF EXISTS `pmgr_double_entries`;
CREATE TABLE `pmgr_double_entries` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
-- The two entries that make up a "double entry"
`debit_entry_id` INT(10) UNSIGNED NOT NULL,
`credit_entry_id` INT(10) UNSIGNED NOT NULL,
-- REVISIT <AP>: 20090720
-- The amount from ledger_entries should be moved here to
-- eliminate duplication, and crdr should just be deleted.
-- However, it can always be changed later, and I thinks
-- those fields will come in handy when generating a
-- a ledger report. So, duplication for now.
`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,
`transaction_id` INT(10) UNSIGNED NOT NULL,
-- Effective date is when the charge/payment/transfer actually
-- takes effect (since it may not be at the time of the transaction).
-- Through date is used if/when a charge covers a certain time period,
-- like rent. A security deposit, for example, would not use the
-- through date.
`effective_date` DATE DEFAULT NULL, -- first day
`through_date` DATE DEFAULT NULL, -- last day
`due_date` DATE DEFAULT NULL,
`customer_id` INT(10) UNSIGNED NOT NULL,
`lease_id` INT(10) UNSIGNED NOT NULL,
`amount` FLOAT(12,2) NOT NULL,
-- The account of the entry
-- REVISIT <AP>: 20090720
-- We don't want to confuse statement entries with ledger entries,
-- yet we're including account here. It doesn't feel right, but at
-- the same time, it will allow us to show _what_ was charged for
-- in the statement. Keeping it for now...
`account_id` INT(10) UNSIGNED DEFAULT NULL,
-- Allow the payment to reconcile against the charge
`charge_entry_id` INT(10) UNSIGNED DEFAULT NULL,
`comment` VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------------------------------------------------
-- ----------------------------------------------------------------------
-- TABLE pmgr_payments
DROP TABLE IF EXISTS `pmgr_payments`;
CREATE TABLE `pmgr_payments` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
-- name may (or may not) be used to clarify in reports
-- for example, 'Check #1234' as the payment name.
`name` VARCHAR(80) DEFAULT NULL,
@@ -1095,7 +1109,7 @@ CREATE TABLE `pmgr_entries` (
-- can add new types. If so, they will also have to
-- specify the required data1/2/3/4 fields.
-- For now, this will work.
`monetary_type` ENUM('CASH',
`type` ENUM('CASH',
'CHECK',
'MONEYORDER',
'ACH',
@@ -1121,48 +1135,13 @@ CREATE TABLE `pmgr_entries` (
`data3` VARCHAR(80) DEFAULT NULL,
`data4` VARCHAR(80) DEFAULT NULL,
`comment` VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------------------------------------------------
-- ----------------------------------------------------------------------
-- TABLE pmgr_reconciliations
DROP TABLE IF EXISTS `pmgr_reconciliations`;
CREATE TABLE `pmgr_reconciliations` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`debit_entry_id` INT(10) UNSIGNED NOT NULL,
`credit_entry_id` INT(10) UNSIGNED NOT NULL,
`amount` FLOAT(12,2) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ----------------------------------------------------------------------
-- ----------------------------------------------------------------------
-- TABLE pmgr_double_entries
DROP TABLE IF EXISTS `pmgr_double_entries`;
CREATE TABLE `pmgr_double_entries` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`transaction_id` INT(10) UNSIGNED DEFAULT NULL,
-- Effective date is when the charge/payment/transfer actually
-- takes effect (since it may not be at the time of the transaction).
`effective_date` DATE DEFAULT NULL, -- first day
`customer_id` INT(10) UNSIGNED DEFAULT NULL,
`lease_id` INT(10) UNSIGNED DEFAULT NULL,
`debit_ledger_id` INT(10) UNSIGNED NOT NULL,
`credit_ledger_id` INT(10) UNSIGNED NOT NULL,
`amount` FLOAT(12,2) NOT NULL,
-- The ledger entry this physical payment applies to
`ledger_entry_id` INT(10) UNSIGNED NOT NULL,
-- The deposit that included these monies
`deposit_entry_id` INT(10) UNSIGNED DEFAULT NULL,
-- The NSF entry, should this come back from the bank.
`nsf_ledger_entry_id` INT(10) UNSIGNED DEFAULT NULL,
`comment` VARCHAR(255) DEFAULT NULL,
@@ -1172,193 +1151,33 @@ CREATE TABLE `pmgr_double_entries` (
-- ----------------------------------------------------------------------
-- ----------------------------------------------------------------------
-- TABLE pmgr_charges_payments
-- TABLE pmgr_deposits
DROP TABLE IF EXISTS `pmgr_charges_payments`;
CREATE TABLE `pmgr_charges_payments` (
DROP TABLE IF EXISTS `pmgr_deposits`;
CREATE TABLE `pmgr_deposits` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
-- Mark which charge the payment reconciles, and how much was applied
`charge_entry_id` INT(10) UNSIGNED NOT NULL,
`payment_entry_id` INT(10) UNSIGNED NOT NULL,
`transaction_id` INT(10) UNSIGNED NOT NULL,
-- The account/ledger of the entry
`account_id` INT(10) UNSIGNED NOT NULL,
`ledger_id` INT(10) UNSIGNED NOT NULL,
-- For convenience. Should always be DEBIT (unless we
-- decide to credit NSF instead of a negative debit).
`crdr` ENUM('DEBIT')
NOT NULL DEFAULT 'DEBIT',
`amount` FLOAT(12,2) NOT NULL,
`comment` VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- -- ----------------------------------------------------------------------
-- -- ----------------------------------------------------------------------
-- -- TABLE pmgr_folders
-- --
-- -- It's a dumb name, but at the moment, it's how I'm thinking about
-- -- this all. In the generic, a purchase begins with a purchase order
-- -- from the customer. When you receive it, you grab a new manilla
-- -- folder, drop the purchase order in, and start making the widgets.
-- -- when their ready, you ship them with invoice, and drop a copy of
-- -- the invoice in the folder. When they pay, you generate a receipt,
-- -- and drop a copy in the folder. If the check bounces, you note
-- -- that in the folder, and generate a new NSF fee invoice (which gets
-- -- put into its OWN new folder). When they pay again, you generate
-- -- another receipt and put it into the folder, and this process could
-- -- repeat until the invoice finally gets paid, or you write it off as
-- -- a bad debt, which would be noted, of course, in the folder.
-- DROP TABLE IF EXISTS `pmgr_folders`;
-- CREATE TABLE `pmgr_folders` (
-- `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
-- `stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- `comment` VARCHAR(255) DEFAULT NULL,
-- `customer_id` INT(10) UNSIGNED DEFAULT NULL,
-- `lease_id` INT(10) UNSIGNED DEFAULT NULL,
-- PRIMARY KEY (`id`)
-- ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- -- ----------------------------------------------------------------------
-- -- ----------------------------------------------------------------------
-- -- TABLE pmgr_invoices
-- DROP TABLE IF EXISTS `pmgr_invoices`;
-- CREATE TABLE `pmgr_invoices` (
-- `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
-- `stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- -- amount is for convenience. It can always be calculated from
-- -- the attached ledger entries (and therefore will need to be
-- -- updated if they should change in any way).
-- `amount` FLOAT(12,2) DEFAULT NULL,
-- -- `customer_id` INT(10) UNSIGNED DEFAULT NULL,
-- -- `lease_id` INT(10) UNSIGNED DEFAULT NULL,
-- -- `folder_id` INT(10) UNSIGNED NOT NULL,
-- `comment` VARCHAR(255) DEFAULT NULL,
-- PRIMARY KEY (`id`)
-- ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- -- ----------------------------------------------------------------------
-- -- ----------------------------------------------------------------------
-- -- TABLE pmgr_charges
-- DROP TABLE IF EXISTS `pmgr_charges`;
-- CREATE TABLE `pmgr_charges` (
-- `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
-- -- Effective date is when the charge actually takes effect
-- -- (since it may not be at the time of the invoice). Through
-- -- date is used if/when a charge covers a certain time period,
-- -- like rent. A security deposit, for example, would not use
-- -- the through date.
-- `effective_date` DATE DEFAULT NULL, -- first day
-- `through_date` DATE DEFAULT NULL, -- last day
-- `due_date` DATE DEFAULT NULL,
-- `customer_id` INT(10) UNSIGNED DEFAULT NULL,
-- `lease_id` INT(10) UNSIGNED DEFAULT NULL,
-- `amount` FLOAT(12,2) DEFAULT NULL,
-- `comment` VARCHAR(255) DEFAULT NULL,
-- PRIMARY KEY (`id`)
-- ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- -- ----------------------------------------------------------------------
-- -- ----------------------------------------------------------------------
-- -- TABLE pmgr_payments
-- DROP TABLE IF EXISTS `pmgr_payments`;
-- CREATE TABLE `pmgr_payments` (
-- `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
-- `stamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- -- Customer ID ensures that they payment doesn't get lost
-- -- in the system if either a) it's a pre-payment, or
-- -- b) the associated invoice is deleted.
-- `customer_id` INT(10) UNSIGNED DEFAULT NULL,
-- `amount` FLOAT(12,2) DEFAULT NULL,
-- -- name may (or may not) be used to clarify in reports
-- -- for example, 'Check #1234' as the payment name.
-- `name` VARCHAR(80) DEFAULT NULL,
-- -- REVISIT <AP>: 20090716
-- -- Type may needs to be another table, so that the user
-- -- can add new types. If so, they will also have to
-- -- specify the required data1/2/3/4 fields.
-- -- For now, this will work.
-- `type` ENUM('CASH',
-- 'CHECK',
-- 'MONEYORDER',
-- 'ACH',
-- 'DEBITCARD',
-- 'CREDITCARD')
-- DEFAULT NULL,
-- -- REVISIT <AP>: 20090605
-- -- Check Number;
-- -- Routing Number, Account Number;
-- -- Card Number, Expiration Date; CVV2 Code
-- -- etc.
-- -- REVISIT <AP> 20090630
-- -- I _think_ that CVV2 is NEVER supposed to
-- -- be stored ANYWHERE. Merchants agree to
-- -- use it only to verify the transaction and
-- -- then leave no record of it, so that even
-- -- if their security is compromised, no one
-- -- will know the CVV2 code unless they are
-- -- in physical possession of the card.
-- `data1` VARCHAR(80) DEFAULT NULL,
-- `data2` VARCHAR(80) DEFAULT NULL,
-- `data3` VARCHAR(80) DEFAULT NULL,
-- `data4` VARCHAR(80) DEFAULT NULL,
-- `comment` VARCHAR(255) DEFAULT NULL,
-- PRIMARY KEY (`id`)
-- ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- -- ----------------------------------------------------------------------
-- -- ----------------------------------------------------------------------
-- -- TABLE pmgr_transfers
-- DROP TABLE IF EXISTS `pmgr_transfers`;
-- CREATE TABLE `pmgr_transfers` (
-- `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
-- -- Effective date is when the charge actually takes effect
-- -- (since it may not be at the time of the invoice). Through
-- -- date is used if/when a charge covers a certain time period,
-- -- like rent. A security deposit, for example, would not use
-- -- the through date.
-- `effective_date` DATE DEFAULT NULL, -- first day
-- `through_date` DATE DEFAULT NULL, -- last day
-- `due_date` DATE DEFAULT NULL,
-- `customer_id` INT(10) UNSIGNED DEFAULT NULL,
-- `lease_id` INT(10) UNSIGNED DEFAULT NULL,
-- `amount` FLOAT(12,2) DEFAULT NULL,
-- `comment` VARCHAR(255) DEFAULT NULL,
-- PRIMARY KEY (`id`)
-- ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- ######################################################################
-- ######################################################################
-- ######################################################################

View File

@@ -914,6 +914,9 @@ foreach $row (@{query($sdbh, $query)}) {
addRow('transactions', {
'type' => 'INVOICE',
'stamp' => $stamp,
'account_id' => $newdb{'lookup'}{'account'}{'A/R'}{'account_id'},
'ledger_id' => $newdb{'lookup'}{'account'}{'A/R'}{'ledger_id'},
'crdr' => 'DEBIT',
#'amount' => $row->{'InvoiceAmount'},
#'comment' => "Invoice Transaction",
});
@@ -965,49 +968,47 @@ foreach $row (@{query($sdbh, $query)}) {
= $newdb{'lookup'}{'account'}{'A/R'}{'ledger_id'};
# debit: A/R credit: Rent/LateCharge/Etc
foreach ('debit', 'credit') {
my $CRDR = $_;
$CRDR =~ tr/a-z/A-Z/;
addRow('ledger_entries', {
'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'id'},
'account_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{$_.'_account_id'},
'ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{$_.'_ledger_id'},
'crdr' => $CRDR,
'amount' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'amount'},
'comment' => "$_ Ledger Entry: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}",
});
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{$_.'_entry_id'}
= $newdb{'tables'}{'ledger_entries'}{'autoid'};
}
addRow('double_entries', {
'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'id'},
'effective_date' => $effective_date,
'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'},
'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'},
'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'debit_ledger_id'},
'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'credit_ledger_id'},
'amount' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'amount'},
#'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'id'},
'debit_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'debit_entry_id'},
'credit_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'credit_entry_id'},
'comment' => "Double Entry: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}",
});
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'double_entry_id'}
= $newdb{'tables'}{'double_entries'}{'autoid'};
# Add the Charge Entry
addRow('entries', {
# Add the Charge Statement Entry
addRow('statement_entries', {
'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'id'},
'type' => 'CHARGE',
'effective_date' => $effective_date,
'through_date' => $through_date,
'double_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'double_entry_id'},
'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'},
'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'},
'account_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'credit_account_id'},
'ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'credit_ledger_id'},
'crdr' => 'CREDIT',
'amount' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'amount'},
'comment' => "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}",
});
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'entry_id'}
= $newdb{'tables'}{'entries'}{'autoid'};
# Add the A/R entry
addRow('entries', {
'type' => 'TRANSFER',
'double_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'double_entry_id'},
'account_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'debit_account_id'},
'ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'debit_ledger_id'},
'crdr' => 'DEBIT',
'comment' => "Charge A/R: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}",
});
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ar_entry_id'}
= $newdb{'tables'}{'entries'}{'autoid'};
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'amount'}
= $row->{'ChargeAmount'};
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'statement_entry_id'}
= $newdb{'tables'}{'statement_entries'}{'autoid'};
next unless $row->{'TaxAmount'};
@@ -1043,86 +1044,6 @@ foreach $row (@{query($sdbh, $query)}) {
$newdb{'lookup'}{'receipt'} = {};
############################################################
############################################################
############################################################
# REVISIT <AP> 20090630
# Handling of receipts is all backwards. The way things
# _should_ look if someone provides Cash and Check to pay
# rent & tax for two units (50 on UnitA and 40 UnitB):
#
# RENT TAX INVOICE A/R RECEIPT CASH CHECK
# ------- ------- ------- ------- ------- ------- -------
# |50 | 50| | | | |
# | | 5 5| | | | |
# | | |55 55| | | |
# |40 | 40| | | | |
# | | 4 4| | | | |
# | | |44 44| | | |
# | | | | |79 | 79|
# | | | | |20 20| |
# | | | |99 99| | |
# | | | | | | |
#
# HOWEVER,
# Our current implementation MUST match LedgerEntry to
# LedgerEntry for reconcile purposes. Thus, although there
# is a way to reconcile that $50 was received, there is no
# way to flag the payment as being for UnitA, unless we
# either rely on the charge to determine the fact (a
# solution that has proven very messy), or we add it to
# the reconciliations table. The hope, for simplicity's
# sake, was to ensure there was a single ledger entry in
# A/R for each payment that could correspond to a lease/unit,
# so that no A/R ledger entry ever represented payment for
# more than one lease. However, to do so, our ledgers
# appear like this instead:
#
# RENT TAX INVOICE A/R RECEIPT CASH CHECK
# ------- ------- ------- ------- ------- ------- -------
# |50 | 50| | | | | t1a
# | | 5 5| | | | | t1a
# | | |55 55| | | | t1b
# |40 | 40| | | | | t2a
# | | 4 4| | | | | t2a
# | | |44 44| | | | t2b
# | | | | |79 | 79| t3a
# | | | | |20 20| | t3a
# | | | |50 50| | | t3b
# | | | | 5 5| | | t3b
# | | | |40 40| | | t3b
# | | | | 4 4| | | t3b
# | | | | | | |
#
# There is another possible solution, although it is
# very probably ledger overkill (even invoice/receipt
# already fall into the overkill category).
#
# RENT TAX INVOICE A/R MERGE RECEIPT CASH CHECK
# ------- ------- ------- ------- ------- ------- ------- -------
# |50 | 50| | | | | |
# | | 5 5| | | | | |
# | | |55 55| | | | |
# |40 | 40| | | | | |
# | | 4 4| | | | | |
# | | |44 44| | | | |
# | | | | | |79 | 79|
# | | | | | |20 20| |
# | | | | |50 50| | |
# | | | | | 5 5| | |
# | | | | |40 40| | |
# | | | | | 4 4| | |
# | | | |99 99| | | |
# | | | | | | | |
#
# I might opt for this last option, but ultimately, none
# of these are really correct. We need a better solution.
# Until then, I'll go with the easiest.
############################################################
############################################################
############################################################
# Sitelink splits one physical payment into multiple "payments" to match each charge.
# The solution here is kludgy, but for our cases at least, it brings those pseudo-payments
# back into a single one. This presumes there is only one PaymentType per receipt.
@@ -1153,6 +1074,8 @@ foreach $row (@{query($sdbh, $query)}) {
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}
= { 'date' => $stamp,
'effective_date' => $effective_date,
'through_date' => $through_date,
'amount' => $row->{'ReceiptAmount'},
};
@@ -1185,6 +1108,9 @@ foreach $row (@{query($sdbh, $query)}) {
addRow('transactions', {
'type' => 'RECEIPT',
'stamp' => $stamp,
'account_id' => $newdb{'lookup'}{'account'}{'A/R'}{'account_id'},
'ledger_id' => $newdb{'lookup'}{'account'}{'A/R'}{'ledger_id'},
'crdr' => 'CREDIT',
});
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'receipt_id'}
@@ -1206,48 +1132,45 @@ foreach $row (@{query($sdbh, $query)}) {
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'credit_ledger_id'}
= $newdb{'lookup'}{'account'}{'A/R'}{'ledger_id'};
# debit: Cash/Check/Etc credit: A/R
foreach ('debit', 'credit') {
my $CRDR = $_;
$CRDR =~ tr/a-z/A-Z/;
addRow('ledger_entries', {
'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'receipt_id'},
'account_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{$_.'_account_id'},
'ledger_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{$_.'_ledger_id'},
'crdr' => $CRDR,
'amount' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'amount'},
'comment' => "$_ Entry Receipt: $row->{'ReceiptNum'}; Type: $row->{'PaymentType'}",
});
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{$_.'_entry_id'}
= $newdb{'tables'}{'ledger_entries'}{'autoid'};
}
addRow('double_entries', {
'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'receipt_id'},
'effective_date' => $effective_date,
'customer_id' => undef, # This is set later...
'debit_ledger_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'debit_ledger_id'},
'credit_ledger_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'credit_ledger_id'},
'amount' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'amount'},
'comment' => "Double Entry Receipt: $row->{'ReceiptNum'}; Type: $row->{'PaymentType'}",
#'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'receipt_id'},
'debit_entry_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'debit_entry_id'},
'credit_entry_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'credit_entry_id'},
'comment' => "Double Entry: $row->{'ReceiptNum'}; Type: $row->{'PaymentType'}",
});
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'double_entry_id'}
= $newdb{'tables'}{'double_entries'}{'autoid'};
# Add the Payment Entry
addRow('entries', {
'type' => 'PAYMENT',
'account_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'debit_account_id'},
'ledger_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'debit_ledger_id'},
'crdr' => 'DEBIT',
'double_entry_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'double_entry_id'},
# Add the physical payment
addRow('payments', {
'ledger_entry_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'debit_entry_id'},
'name' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'name'},
'monetary_type' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'type'},
'type' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'type'},
'data1' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'data1'},
'comment' => "Receipt: $row->{'ReceiptNum'}; Type: $row->{'PaymentType'}",
'comment' => "Physical Payment: $row->{'ReceiptNum'}; Type: $row->{'PaymentType'}",
});
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'entry_id'}
= $newdb{'tables'}{'entries'}{'autoid'};
# Add the A/R Entry
addRow('entries', {
'type' => 'TRANSFER',
'account_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'credit_account_id'},
'ledger_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'credit_ledger_id'},
'crdr' => 'CREDIT',
'double_entry_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'double_entry_id'},
'comment' => "Receipt A/R: $row->{'ReceiptNum'}; Type: $row->{'PaymentType'}",
});
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ar_entry_id'}
= $newdb{'tables'}{'entries'}{'autoid'};
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'payment_id'}
= $newdb{'tables'}{'payments'}{'autoid'};
}
@@ -1260,49 +1183,40 @@ $newdb{'lookup'}{'payment'} = {};
$query = "SELECT * FROM Payments ORDER BY PaymentID";
foreach $row (@{query($sdbh, $query)})
{
$newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}
= { 'receipt_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'receipt_id'},
'ar_entry_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ar_entry_id'},
'entry_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'entry_id'},
'amount' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'amount'},
};
# Ensure Payment has the right customer
$newdb{'tables'}{'double_entries'}{'rows'}[
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'double_entry_id'}
]{'customer_id'} = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'};
next
if ($newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'reconciled'});
# Figure out how much of the charge can be reconciled
my $charge_amount = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'amount'};
my $payment_amount = $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'amount'};
my $payment_amount = $row->{'PaymentAmount'};
my $reconcile_amount = ($charge_amount < $payment_amount) ? $charge_amount : $payment_amount;
# Reconcile the A/R Account
addRow('reconciliations', {
'debit_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ar_entry_id'},
'credit_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ar_entry_id'},
'amount' => $reconcile_amount,
$newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}
= { 'receipt_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'receipt_id'},
'effective_date' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'effective_date'},
'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'},
'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'},
'amount' => $reconcile_amount,
'account_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'credit_account_id'},
};
my $comment = $row->{'Memo'} || "Payment: $row->{'ReceiptNum'}; Type: $row->{'PaymentType'}";
# Add the Payment Statement Entry
addRow('statement_entries', {
'transaction_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'receipt_id'},
'type' => 'PAYMENT',
'effective_date' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'effective_date'},
'customer_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'customer_id'},
'lease_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'lease_id'},
'account_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'account_id'},
'amount' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'amount'},
'charge_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'statement_entry_id'},
'comment' => $comment,
});
# Reconcile the payment to the charge
addRow('charges_payments', {
'charge_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'entry_id'},
'payment_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'entry_id'},
'amount' => $reconcile_amount,
});
$newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'reconciled'} = 1;
# Update the transaction to use the memo from this payment
if ($row->{'Memo'}) {
my $id = $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'entry_id'};
$newdb{'tables'}{'entries'}{'rows'}[$id]{'comment'} = $row->{'Memo'};
}
$newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'statement_entry_id'}
= $newdb{'tables'}{'statement_entries'}{'autoid'};
}
@@ -1328,93 +1242,95 @@ print("Set up Petty Cash...\n");
addRow('transactions', {
'type' => 'TRANSFER',
'stamp' => datefmt('03/25/2009 16:00'),
});
addRow('double_entries', {
'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'},
'effective_date' => $effective_date,
'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Equity'}{'ledger_id'},
'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Loan'}{'ledger_id'},
'amount' => 5000,
'account_id' => $newdb{'lookup'}{'account'}{'Equity'}{'account_id'},
'ledger_id' => $newdb{'lookup'}{'account'}{'Equity'}{'ledger_id'},
'crdr' => 'DEBIT',
'comment' => "HTP Loan #1",
});
addRow('entries', {
'type' => 'TRANSFER',
addRow('ledger_entries', {
'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'},
'account_id' => $newdb{'lookup'}{'account'}{'Equity'}{'account_id'},
'ledger_id' => $newdb{'lookup'}{'account'}{'Equity'}{'ledger_id'},
'crdr' => 'DEBIT',
'double_entry_id' => $newdb{'tables'}{'double_entries'}{'autoid'},
'amount' => 5000,
'comment' => "Equity: HTP Loan #1",
});
addRow('entries', {
'type' => 'TRANSFER',
addRow('ledger_entries', {
'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'},
'account_id' => $newdb{'lookup'}{'account'}{'Loan'}{'account_id'},
'ledger_id' => $newdb{'lookup'}{'account'}{'Loan'}{'ledger_id'},
'crdr' => 'CREDIT',
'double_entry_id' => $newdb{'tables'}{'double_entries'}{'autoid'},
'amount' => 5000,
'comment' => "Loan: HTP Loan #1",
});
addRow('double_entries', {
'debit_entry_id' => $newdb{'tables'}{'ledger_entries'}{'autoid'}-1,
'credit_entry_id' => $newdb{'tables'}{'ledger_entries'}{'autoid'},
});
# Add the second loan
# debit: Equity credit: Loan
addRow('transactions', {
'type' => 'TRANSFER',
'stamp' => datefmt('04/01/2009 16:00'),
});
addRow('double_entries', {
'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'},
'effective_date' => $effective_date,
'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Equity'}{'ledger_id'},
'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Loan'}{'ledger_id'},
'amount' => 1000,
'account_id' => $newdb{'lookup'}{'account'}{'Equity'}{'account_id'},
'ledger_id' => $newdb{'lookup'}{'account'}{'Equity'}{'ledger_id'},
'crdr' => 'DEBIT',
'comment' => "HTP Loan #2",
});
addRow('entries', {
'type' => 'TRANSFER',
addRow('ledger_entries', {
'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'},
'account_id' => $newdb{'lookup'}{'account'}{'Equity'}{'account_id'},
'ledger_id' => $newdb{'lookup'}{'account'}{'Equity'}{'ledger_id'},
'crdr' => 'DEBIT',
'double_entry_id' => $newdb{'tables'}{'double_entries'}{'autoid'},
'amount' => 1000,
'comment' => "Equity: HTP Loan #2",
});
addRow('entries', {
'type' => 'TRANSFER',
addRow('ledger_entries', {
'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'},
'account_id' => $newdb{'lookup'}{'account'}{'Loan'}{'account_id'},
'ledger_id' => $newdb{'lookup'}{'account'}{'Loan'}{'ledger_id'},
'crdr' => 'CREDIT',
'double_entry_id' => $newdb{'tables'}{'double_entries'}{'autoid'},
'amount' => 1000,
'comment' => "Loan: HTP Loan #2",
});
addRow('double_entries', {
'debit_entry_id' => $newdb{'tables'}{'ledger_entries'}{'autoid'}-1,
'credit_entry_id' => $newdb{'tables'}{'ledger_entries'}{'autoid'},
});
# Cheat for now, using equity for Petty Cash
# debit: Petty Cash credit: Equity
addRow('transactions', {
'type' => 'TRANSFER',
'stamp' => datefmt('03/25/2009 16:00'),
});
addRow('double_entries', {
'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'},
'effective_date' => $effective_date,
'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Petty Cash'}{'ledger_id'},
'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Equity'}{'ledger_id'},
'amount' => 750,
'comment' => "Petty Cash Funding",
});
addRow('entries', {
'type' => 'TRANSFER',
'account_id' => $newdb{'lookup'}{'account'}{'Petty Cash'}{'account_id'},
'ledger_id' => $newdb{'lookup'}{'account'}{'Petty Cash'}{'ledger_id'},
'crdr' => 'DEBIT',
'double_entry_id' => $newdb{'tables'}{'double_entries'}{'autoid'},
'comment' => "Petty Cash Funding",
});
addRow('ledger_entries', {
'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'},
'account_id' => $newdb{'lookup'}{'account'}{'Petty Cash'}{'account_id'},
'ledger_id' => $newdb{'lookup'}{'account'}{'Petty Cash'}{'ledger_id'},
'crdr' => 'DEBIT',
'amount' => 750,
'comment' => "Petty Cash: Petty Cash Funding",
});
addRow('entries', {
'type' => 'TRANSFER',
addRow('ledger_entries', {
'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'},
'account_id' => $newdb{'lookup'}{'account'}{'Equity'}{'account_id'},
'ledger_id' => $newdb{'lookup'}{'account'}{'Equity'}{'ledger_id'},
'crdr' => 'CREDIT',
'double_entry_id' => $newdb{'tables'}{'double_entries'}{'autoid'},
'amount' => 750,
'comment' => "Equity: Petty Cash Funding",
});
addRow('double_entries', {
'debit_entry_id' => $newdb{'tables'}{'ledger_entries'}{'autoid'}-1,
'credit_entry_id' => $newdb{'tables'}{'ledger_entries'}{'autoid'},
});
######################################################################
## Build the Database
@@ -1481,9 +1397,9 @@ query($db_handle, $query);
print("Set Invoice/Receipt Totals...\n");
$query = "UPDATE pmgr_transactions T, pmgr_double_entries DE
SET T.`amount` = COALESCE(T.`amount`,0) + DE.amount
WHERE DE.transaction_id = T.id";
$query = "UPDATE pmgr_transactions T, pmgr_ledger_entries E
SET T.`amount` = COALESCE(T.`amount`,0) + E.amount
WHERE E.transaction_id = T.id AND E.account_id = T.account_id";
query($db_handle, $query);