From 0b69e065aedcba5b6d4c2c2fb3bf5efe41829032 Mon Sep 17 00:00:00 2001 From: abijah Date: Tue, 30 Jun 2009 17:52:43 +0000 Subject: [PATCH] Major change to invoice/receipt algorithms. The end result shouldn't be visible, but there were significant problems understanding how to reconcile entries and this cleaned things up significantly. There may be some bugs left, but quick tests show it to be working git-svn-id: file:///svn-source/pmgr/branches/charge_credit_20090629@190 97e9348a-65ac-dc4b-aefc-98561f571b83 --- scripts/sitelink2pmgr.pl | 495 +++++++++++++++++++++++---------------- 1 file changed, 291 insertions(+), 204 deletions(-) diff --git a/scripts/sitelink2pmgr.pl b/scripts/sitelink2pmgr.pl index 427efbf..a37d282 100644 --- a/scripts/sitelink2pmgr.pl +++ b/scripts/sitelink2pmgr.pl @@ -696,10 +696,6 @@ foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'} = $newdb{'tables'}{'contacts'}{'autoid'}; - $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account_id'} = - $newdb{'lookup'}{'account'}{'A/R'}{'account_id'}; - $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'ledger_id'} = - $newdb{'lookup'}{'account'}{'A/R'}{'ledger_id'}; addRow('customers', { 'name' => "$row->{'LastName'}, $row->{'FirstName'}", @@ -818,19 +814,15 @@ foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'ledger'} = {}; -$query = "SELECT L.*, A.TenantID FROM TenantLedger L LEFT JOIN `Access` A ON A.LedgerID = L.LedgerID WHERE L.UnitID <> 'POS\$' ORDER BY L.LedgerID"; +$query = "SELECT L.*, A.TenantID FROM TenantLedger L LEFT JOIN `Access` A ON A.LedgerID = L.LedgerID WHERE L.UnitID <> 'POS\$' ORDER BY L.DateIn"; foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}} = { 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'} }; - $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'account_id'} - = $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'account_id'}; - $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger_id'} - = $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'ledger_id'}; - addRow('leases', - { 'number' => $row->{'LedgerID'}, + { #'number' => $newdb{'tables'}{'leases'}{'autoid'}+1, + 'number' => $row->{'LedgerID'}, 'lease_type_id' => $newdb{'tables'}{'lease_types'}{'autoid'}, 'unit_id' => $newdb{'lookup'}{'unit'}{$row->{'UnitID'}}{'id'}, 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'}, @@ -857,49 +849,78 @@ foreach $row (@{query($sdbh, $query)}) { ## ###################################################################### -## Charges +## Invoices $newdb{'lookup'}{'charge'} = {}; -$query = "SELECT * FROM Charges ORDER BY ChargeID"; +$query = "SELECT *, ChargeAmount+TaxAmount AS InvoiceAmount FROM Charges ORDER BY ChargeID"; foreach $row (@{query($sdbh, $query)}) { - my $credit_ledger_id; - my $ledger_entry_id; addRow('transactions', { 'stamp' => datefmt($row->{'ChargeDate'}), 'through_date' => datefmt($row->{'EndDate'}) }); $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}} - = { 'tx' => $newdb{'tables'}{'transactions'}{'autoid'}, - 'ledger_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger_id'}, - #'ledger_id' => $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}, - 'amount' => $row->{'ChargeAmount'}, - 'tax_amount' => $row->{'TaxAmount'}, - 'customer_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'customer_id'}, - 'lease_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease_id'}, - }; + = { 'invoice' => + { 'tx' => $newdb{'tables'}{'transactions'}{'autoid'}, + 'lease_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease_id'}, + 'customer_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'customer_id'}, + 'amount' => $row->{'InvoiceAmount'}, + } }; - $credit_ledger_id = $newdb{'lookup'}{'charge_type'}{$row->{'ChargeDescription'}}{'ledger_id'}; - if ($use_ir) { - addRow('ledger_entries', - { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, - 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}, - 'credit_ledger_id' => $credit_ledger_id, - 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, - 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, - 'amount' => $row->{'ChargeAmount'}, - 'comment' => "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}" }); - $ledger_entry_id = $newdb{'tables'}{'ledger_entries'}{'autoid'}; - $credit_ledger_id = $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}; - } + # Invoice must debit the A/R ledger... + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'debit_ledger_id'} + = $newdb{'lookup'}{'account'}{'A/R'}{'ledger_id'}; + # ...and credit the Invoice ledger. + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'credit_ledger_id'} + = $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}; + + # Create the invoice entry + # debit: A/R credit: Invoice + addRow('ledger_entries', + { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'tx'}, + 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'debit_ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'credit_ledger_id'}, + 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'customer_id'}, + 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'lease_id'}, + 'amount' => $row->{'InvoiceAmount'}, + 'comment' => "Invoice: Charge: $row->{'ChargeID'}" }); + + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'} + = $newdb{'tables'}{'ledger_entries'}{'autoid'}; +} + + +###################################################################### +## Charges + +$query = "SELECT * FROM Charges ORDER BY ChargeID"; +foreach $row (@{query($sdbh, $query)}) { + + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'} + = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'tx'}; + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'} + = $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'customer_id'}; + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'} + = $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease_id'}; + + # Charge must credit the invoice ledger... + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'credit_ledger_id'} + = $newdb{'lookup'}{'charge_type'}{$row->{'ChargeDescription'}}{'ledger_id'}; + + # ...and debit the A/R ledger. + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'debit_ledger_id'} + = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'credit_ledger_id'}; + + # Add the charge entry + # debit: Invoice credit: Rent/LateCharge/Etc addRow('ledger_entries', { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_id'}, - 'credit_ledger_id' => $credit_ledger_id, + 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'debit_ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'credit_ledger_id'}, 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, 'amount' => $row->{'ChargeAmount'}, @@ -908,57 +929,46 @@ foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'} = $newdb{'tables'}{'ledger_entries'}{'autoid'}; - if ($use_ir) { - # Reconcile the invoice account. Since this is from the perspective - # of the invoice, the entry crediting the charge is the debit, and - # the entry debiting A/R is the credit. - addRow('reconciliations', - { 'debit_ledger_entry_id' => $ledger_entry_id, - 'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'}, - 'amount' => $row->{'ChargeAmount'}, - }); - } + # Reconcile the Invoice account. Our two entries look like: + # debit: Invoice credit: Rent/LateCharge/Etc + # debit: A/R credit: Invoice + # Since this is from the perspective of the Invoice account, + # the credit entry is the Invoice<->A/R, and the debit + # entry is the actual charge ledger entry. + addRow('reconciliations', + { 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'}, + 'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'}, + 'amount' => $row->{'ChargeAmount'}, + }); next unless $row->{'TaxAmount'}; - $credit_ledger_id = $newdb{'lookup'}{'charge_type'}{'Tax'}{'ledger_id'}; - if ($use_ir) { - addRow('ledger_entries', - { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, - 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}, - 'credit_ledger_id' => $credit_ledger_id, - 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, - 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, - 'amount' => $row->{'TaxAmount'}, - 'comment' => undef }); - $ledger_entry_id = $newdb{'tables'}{'ledger_entries'}{'autoid'}; - $credit_ledger_id = $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'}; - } - + # Add the tax charge entry + # debit: Invoice credit: Tax addRow('ledger_entries', { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, 'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_id'}, - 'credit_ledger_id' => $credit_ledger_id, + 'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'debit_ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Tax'}{'ledger_id'}, 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, 'amount' => $row->{'TaxAmount'}, - 'comment' => undef }); + 'comment' => "Tax for ChargeID:$row->{'ChargeID'}" }); - $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tax_entry'} + $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tax_ledger_entry_id'} = $newdb{'tables'}{'ledger_entries'}{'autoid'}; - if ($use_ir) { - # Reconcile the invoice account. Since this is from the perspective - # of the invoice, the entry crediting the charge is the debit, and - # the entry debiting A/R is the credit. - addRow('reconciliations', - { 'debit_ledger_entry_id' => $ledger_entry_id, - 'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tax_entry'}, - 'amount' => $row->{'TaxAmount'}, - }); - } + # Reconcile the Invoice account. Our two entries look like: + # debit: Invoice credit: Tax + # debit: A/R credit: Invoice + # Since this is from the perspective of the Invoice account, + # the credit entry is the Invoice<->A/R, and the debit + # entry is the actual tax ledger entry. + addRow('reconciliations', + { 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tax_ledger_entry_id'}, + 'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'}, + 'amount' => $row->{'TaxAmount'}, + }); } @@ -967,42 +977,168 @@ foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'receipt'} = {}; -$query = - "SELECT R.ReceiptNum, C.LedgerID, R.ReceiptDate" . - " FROM Receipts R, Payments P, Charges C" . - " WHERE P.ReceiptNum = R.ReceiptNum" . - " AND C.ChargeID = P.ChargeID" . - " GROUP BY R.ReceiptNum, C.LedgerID, R.ReceiptDate" . - " ORDER BY R.ReceiptNum"; -foreach $row (@{query($sdbh, $query)}) { +############################################################ +############################################################ +############################################################ +# REVISIT 20090630 +# Handling of receipts is all backwards. The way things +# _should_ look if someone provides Cash and Check to pay +# rent & tax for two units (50 on UnitA and 40 UnitB): +# +# RENT TAX INVOICE A/R RECEIPT CASH CHECK +# ------- ------- ------- ------- ------- ------- ------- +# |50 | 50| | | | | +# | | 5 5| | | | | +# | | |55 55| | | | +# |40 | 40| | | | | +# | | 4 4| | | | | +# | | |44 44| | | | +# | | | | |79 | 79| +# | | | | |20 20| | +# | | | |99 99| | | +# | | | | | | | +# +# HOWEVER, +# Our current implementation MUST match LedgerEntry to +# LedgerEntry for reconcile purposes. Thus, although there +# is a way to reconcile that $50 was received, there is no +# way to flag the payment as being for UnitA, unless we +# either rely on the charge to determine the fact (a +# solution that has proven very messy), or we add it to +# the reconciliations table. The hope, for simplicity's +# sake, was to ensure there was a single ledger entry in +# A/R for each payment that could correspond to a lease/unit, +# so that no A/R ledger entry ever represented payment for +# more than one lease. However, to do so, our ledgers +# appear like this instead: +# +# RENT TAX INVOICE A/R RECEIPT CASH CHECK +# ------- ------- ------- ------- ------- ------- ------- +# |50 | 50| | | | | +# | | 5 5| | | | | +# | | |55 55| | | | +# |40 | 40| | | | | +# | | 4 4| | | | | +# | | |44 44| | | | +# | | | | |79 | 79| +# | | | | |20 20| | +# | | | |50 50| | | +# | | | | 5 5| | | +# | | | |40 40| | | +# | | | | 4 4| | | +# | | | | | | | +# +# There is another possible solution, although it is +# very probably ledger overkill (even invoice/receipt +# already fall into the overkill category). +# +# RENT TAX INVOICE A/R MERGE RECEIPT CASH CHECK +# ------- ------- ------- ------- ------- ------- ------- ------- +# |50 | 50| | | | | | +# | | 5 5| | | | | | +# | | |55 55| | | | | +# |40 | 40| | | | | | +# | | 4 4| | | | | | +# | | |44 44| | | | | +# | | | | | |79 | 79| +# | | | | | |20 20| | +# | | | | |50 50| | | +# | | | | | 5 5| | | +# | | | | |40 40| | | +# | | | | | 4 4| | | +# | | | |99 99| | | | +# | | | | | | | | +# +# I might opt for this last option, but ultimately, none +# of these are really correct. We need a better solution. +# Until then, I'll go with the easiest. - if ($newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}) { - die unless ($newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'customer_id'} - == $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'customer_id'}); - push(@{$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'ledgers'}}, - $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger_id'}); - #print Dumper $receipt_map{$row->{'ReceiptNum'}}; - next; +############################################################ +############################################################ +############################################################ + +# Sitelink splits one physical payment into multiple "payments" to match each charge. +# The solution here is kludgy, but for our cases at least, it brings those pseudo-payments +# back into a single one. This presumes there is only one PaymentType per receipt. +$query = + "SELECT R.ReceiptNum, R.ReceiptDate, P.PaymentType, P.CheckNum, SUM(P.PaymentAmount) AS ReceiptAmount" . + " FROM Receipts R, Payments P" . + " WHERE P.ReceiptNum = R.ReceiptNum" . + " GROUP BY R.ReceiptNum, R.ReceiptDate, P.PaymentType, P.CheckNum" . + " ORDER BY R.ReceiptNum, P.PaymentType"; +foreach $row (@{query($sdbh, $query)}) { + +# if ($newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}) { +# next; +# } + + if (!$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}) { + addRow('transactions', + { 'stamp' => datefmt($row->{'ReceiptDate'}), + 'through_date' => undef }); + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}} + = {'tx' => $newdb{'tables'}{'transactions'}{'autoid'} }; + } + + if ($row->{'ReceiptDate'} =~ m%3/25/2009%) { + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'} + = $newdb{'ids'}{'monetary_source'}{'Closing'}; + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'account_name'} + = 'Bank'; + } + else { + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'} + = $newdb{'ids'}{'monetary_source'}{ + $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'} + }; + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'account_name'} + = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'account_name'}; } - addRow('transactions', - { 'stamp' => datefmt($row->{'ReceiptDate'}), - 'through_date' => undef }); + # Set up a monetary source for the receipt, + if (!$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}) { + my $name = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'}; + if ($name eq 'Check') { + $name = 'Check #' . $row->{'CheckNum'}; + } + addRow('monetary_sources', + { 'monetary_type_id' => $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'monetary_type'}{'id'}, + 'name' => $name, + 'comment' => "Receipt:$row->{'ReceiptNum'}; Payment:$row->{'PaymentType'}; Check:$row->{'CheckNum'}" }); - $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}} - = {'tx' => $newdb{'tables'}{'transactions'}{'autoid'}, - # NOTE: Use of 'lease_id' would be invalid, since the - # receipt could be for multiple leases. 'customer_id' - # could be OK, but better to avoid this issue all - # together by excluding them both from this lookup. - 'ledgers' => [ $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'ledger_id'} ] }; + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'} + = $newdb{'tables'}{'monetary_sources'}{'autoid'}; + } + + # Receipt must debit the "money" asset (bank, cash, check, etc)... + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'debit_ledger_id'} + = $newdb{'lookup'}{'account'}{ + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'account_name'} + }{'ledger_id'}; + + # ...and credit the Receipt ledger + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'credit_ledger_id'} + = $newdb{'lookup'}{'account'}{'Receipt'}{'ledger_id'}; + + # NOTE THE ABOVE LARGE COMMENT BLOCK + # The choice of credit/debit ledgers does not mirror the + # choices for invoice. This _should_ be A/R to Receipt, + # but it is Money to Receipt instead. + # debit: Cash/Check/Etc credit: Receipt + addRow('ledger_entries', + { 'monetary_source_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}, + 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, + 'debit_ledger_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'debit_ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'credit_ledger_id'}, + 'amount' => $row->{'ReceiptAmount'}, + 'comment' => "Receipt: $row->{'ReceiptNum'}; " }); + + $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'} + = $newdb{'tables'}{'ledger_entries'}{'autoid'}; } -# sub idkeys { [ sort( {$a <=> $b} keys(%{$_[0]})) ] } -# $Data::Dumper::Sortkeys = \&idkeys; - ###################################################################### ## Payments @@ -1014,117 +1150,68 @@ foreach $row (@{query($sdbh, $query)}) { $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}} = {}; - if ($row->{'PaymentDate'} =~ m%3/25/2009%) { - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'} - = $newdb{'ids'}{'monetary_source'}{'Closing'}; - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'account_name'} - = 'Bank'; - } - else { - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'} - = $newdb{'ids'}{'monetary_source'}{ - $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'} - }; - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'account_name'} - = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'account_name'}; - } + # NOTE THE ABOVE LARGE COMMENT BLOCK + # The choice of credit/debit ledgers does not mirror the + # choices for charges. This _should_ be Money to Receipt, + # but it is A/R to Receipt instead. - if (!$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}) { - if (!defined $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'}) { - my $name; - $name = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'}; - if ($name eq 'Check') { - $name = 'Check #' . $row->{'CheckNum'}; - } - addRow('monetary_sources', - { 'monetary_type_id' => $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'monetary_type'}{'id'}, - 'name' => $name, - 'comment' => "Payment: $row->{'PaymentID'}; Type: $row->{'PaymentType'}; Check: $row->{'CheckNum'}; $row->{'Memo'}" }); - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'} - = $newdb{'tables'}{'monetary_sources'}{'autoid'}; - } - - $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'} - = $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'monetary_source_id'}; - } - - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'} - = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_id'}; - - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'} - = $newdb{'lookup'}{'account'}{ - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'account_name'} - }{'ledger_id'}; - - if ($use_ir) { - addRow('ledger_entries', - { #'monetary_source_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}, - 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Receipt'}{'ledger_id'}, - 'credit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'}, - 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, - 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, - 'amount' => $row->{'PaymentAmount'}, - 'comment' => "Receipt: $row->{'ReceiptNum'}; " }); + # Ensure Receipt has the right customer + $newdb{'tables'}{'ledger_entries'}{'rows'}[ $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'} - = $newdb{'tables'}{'ledger_entries'}{'autoid'}; - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'} - = $newdb{'lookup'}{'account'}{'Receipt'}{'ledger_id'}; - } + ]{'customer_id'} = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}; - # Sitelink splits one physical payment into multiple "payments" to match each charge - # This is kludgy, but for our cases at least, brings those pseudo-payments back into - # a single one. It presumes that there is only one PaymentType per receipt. - if (!$newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'}) { - addRow('ledger_entries', - { 'monetary_source_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}, - 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, - 'debit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'}, - 'credit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'}, - 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, - #'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, - 'amount' => 0, - 'comment' => "Receipt: $row->{'ReceiptNum'}; Charge: $row->{'ChargeID'}; Payment: $row->{'PaymentID'}" }); + # Payment must debit the associated receipt ledger (which should be Receipt)... + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'} + = $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'credit_ledger_id'}; - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} - = $newdb{'tables'}{'ledger_entries'}{'autoid'}; - } + # ...and credit the A/R ledger. + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'} + = $newdb{'lookup'}{'account'}{'A/R'}{'ledger_id'}; - $newdb{'tables'}{'ledger_entries'}{'rows'}[ - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} - ]{'amount'} += $row->{'PaymentAmount'}; + # Add the payment entry + # debit: Receipt credit: A/R + addRow('ledger_entries', + { 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'}, + 'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'}, + 'debit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'}, + 'credit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'}, + 'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}, + 'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}, + 'amount' => $row->{'PaymentAmount'}, + 'comment' => "Receipt: $row->{'ReceiptNum'}; Charge: $row->{'ChargeID'}; Payment: $row->{'PaymentID'}" }); - $newdb{'tables'}{'ledger_entries'}{'rows'}[ - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} - ]{'comment'} .= 'P:'.$row->{'PaymentID'} . '->C:' . $row->{'ChargeID'} . '; '; + $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} + = $newdb{'tables'}{'ledger_entries'}{'autoid'}; - if ($use_ir) { - # Reconcile the invoice account. Since this is from the perspective - # of the invoice, the entry crediting the charge is the debit, and - # the entry debiting A/R is the credit. - addRow('reconciliations', - { 'debit_ledger_entry_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}, - 'credit_ledger_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'}, - 'amount' => $row->{'PaymentAmount'}, - }); - } + # Reconcile the Receipt account. Our two entries look like: + # debit: Cash/Check/Etc credit: Receipt + # debit: Receipt credit: A/R + # Since this is from the perspective of the Receipt account, + # the debit entry is the Receipt<->A/R, and the credit + # entry is the actual receipt ledger entry. + addRow('reconciliations', + { 'debit_ledger_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'}, + 'credit_ledger_entry_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}, + 'amount' => $row->{'PaymentAmount'}, + }); - # OK, now that the receipt is reconciled, update - # payment to reference the true ledger_entry_id - $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'} - = $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}; # Figure out how much of the charge can be reconciled - my $reconcile_amount = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'amount'}; + my $reconcile_amount = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'amount'}; + #print STDERR Dumper($newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}); exit; $reconcile_amount = $row->{'PaymentAmount'} if $row->{'PaymentAmount'} <= $reconcile_amount; - # Reconcile the A/R account. Since this is from the perspective - # of the A/R, charge is the debit, and payment is the credit + # Reconcile the A/R account. Our two entries look like: + # debit: Receipt credit: A/R + # debit: A/R credit: Invoice + # Since this is from the perspective of the A/R account, + # the debit entry is the Invoice<->A/R, and the credit + # entry is the Receipt<->A/R. addRow('reconciliations', - { 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'}, - 'credit_ledger_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'}, - 'amount' => $reconcile_amount, - }); + { 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'}, + 'credit_ledger_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'}, + 'amount' => $reconcile_amount, + }); # Update the transaction to use the memo from this payment if ($row->{'Memo'}) {