getting closer to a workable NSF solution. I don't like it, but it might allow us to move forward in the short term. This solution required a stupid kludge to get CakePHP to work with the necessary query, which sucks but is not too cumbersome. What isn't working at the moment, is for the NSF to show up on the lease account, which is what I'll try to work out next. Also, the monies deposited are not trackable, since I'm not reconciling them (due to the sign flip). Not sure if there is an easily workable solution. Also, to get the collected rent report to show this negative income, it requires the bank account be part of the query, which I accomplish in the short term by setting the 'payable' flag. I may need to fix/kludge this by running the NSF through the receipt account and adding the NSF account to the list on the collected page.

git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629/site@331 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
abijah
2009-07-15 00:21:23 +00:00
parent 34e3251240
commit 68a10e783b
2 changed files with 95 additions and 81 deletions

View File

@@ -58,6 +58,16 @@ class LedgerEntry extends AppModel {
'foreignKey' => 'credit_ledger_entry_id', 'foreignKey' => 'credit_ledger_entry_id',
'associationForeignKey' => 'debit_ledger_entry_id', 'associationForeignKey' => 'debit_ledger_entry_id',
), ),
// STUPID CakePHP bug screws up when using Containable
// and CLASS contains CLASS. This extra HABTM give the
// option of multiple depths on one CLASS, since there
// isn't an alias specification for Containable.
'DebitReconciliationLedgerEntry2' => array(
'className' => 'LedgerEntry',
'joinTable' => 'reconciliations',
'foreignKey' => 'credit_ledger_entry_id',
'associationForeignKey' => 'debit_ledger_entry_id',
),
'CreditReconciliationLedgerEntry' => array( 'CreditReconciliationLedgerEntry' => array(
'className' => 'LedgerEntry', 'className' => 'LedgerEntry',
'joinTable' => 'reconciliations', 'joinTable' => 'reconciliations',

View File

@@ -22,20 +22,22 @@ class MonetarySource extends AppModel {
* function: nsf * function: nsf
* - Flags the ledger entry as having insufficient funds * - Flags the ledger entry as having insufficient funds
* - NOTE: nsf only works if given the monetary source id * - NOTE: nsf only works if given the monetary source id
* to transaction t2b, below * to transaction e3, below
* *
* FEE RENT A/R RECEIPT CHECK NSF BANK * FEE RENT A/R RECEIPT CHECK NSF BANK
* ------- ------- ------- ------- ------- ------- ------- * ------- ------- ------- ------- ------- ------- -------
* | |50 50| | | | | e1 * | |30 30| | | | | t1 e1a : R e2/e6a :
* | |20 20| | | | | t1 e1b : R e2/e6b :
* | | | | | | | * | | | | | | |
* | | |50 50| | | | e2a * | | |50 50| | | | t2 e2 : R e3 : R e1a/e1b
* | | | |50 50| | | e2b * | | | |50 50| | | t2 e3 : R e4 : R e2
* | | | | | | | * | | | | | | |
* | | | | |50 | 50| e3 * | | | | |50 | 50| t3 e4 : R e5 : R e3
* | | | | | | | * | | | | | | |
* | | | | | 50| |50 e4 * | | | | | 50| |50 t4 e5 : R e4 : R e6a/e6b
* | | 50| | | |50 | e5a * | | 30| | | |30 | t5 e6a : : R e5
* |35 | 35| | | | | e5b * | | 20| | | |20 | t5 e6b : : R e5
* |35 | 35| | | | | t5 e7
* - NOTE * - NOTE
* The above example is great, except it leave no way to resolve * The above example is great, except it leave no way to resolve
@@ -43,17 +45,19 @@ class MonetarySource extends AppModel {
* perhaps we need to run a negative credit to A/R, which we can * perhaps we need to run a negative credit to A/R, which we can
* use to reconcile against the Rent<->A/R double entry: * use to reconcile against the Rent<->A/R double entry:
* *
* | | | | | 50| |50 e4 * | | | | | 50| |50 t4 e5 : R e4 : R e6a/e6b (?)
* | | |-50 | | -50| | e5a * | | |-30 | | -30| | t5 e6a : R e1a : R e5 (?)
* |35 | 35| | | | | e5b * | | |-20 | | -20| | t5 e6b : R e1b : R e5 (?)
* |35 | 35| | | | | t5 e7
* OR perhaps even a negative entry all the way through to the * OR perhaps even a negative entry all the way through to the
* bank, making the NSF appear not as a withdrawal, but as a * bank, making the NSF appear not as a withdrawal, but as a
* negative deposit (i.e, and adjustment, just like it really is): * negative deposit (i.e, and adjustment, just like it really is):
* *
* | | | | | |-50 -50| e4 * | | | | | |-50 -50| t4 e5 : R e4 (?) : R e6a/e6b
* | | |-50 | | -50| | e5a * | | |-30 | | -30| | t5 e6a : R e1a : R e5
* |35 | 35| | | | | e5b * | | |-20 | | -20| | t5 e6b : R e1b : R e5
* |35 | 35| | | | | t5 e7
* *
*/ */
@@ -67,14 +71,14 @@ class MonetarySource extends AppModel {
$source = $this->find $source = $this->find
('first', ('first',
array('contain' => array('contain' =>
array(/* e2b */ array(/* e3 */
'LedgerEntry' => 'LedgerEntry' =>
array('Transaction.id', array('Transaction.id',
'MonetarySource.id', 'MonetarySource.id',
'Customer.id', 'Customer.id',
'Lease.id', 'Lease.id',
/* e2b debit */ /* e3 debit */
'DebitLedger' => /* e.g. CHECK Ledger */ 'DebitLedger' => /* e.g. CHECK Ledger */
array('fields' => array(), array('fields' => array(),
@@ -88,7 +92,7 @@ class MonetarySource extends AppModel {
), ),
), ),
/* e2b credit */ /* e3 credit */
'CreditLedger' => /* i.e. RECEIPT Ledger */ 'CreditLedger' => /* i.e. RECEIPT Ledger */
array('fields' => array('id'), array('fields' => array('id'),
'Account' => /* i.e. RECEIPT Account */ 'Account' => /* i.e. RECEIPT Account */
@@ -98,9 +102,9 @@ class MonetarySource extends AppModel {
), ),
), ),
/* e2a */ /* e2 */
'DebitReconciliationLedgerEntry' => 'DebitReconciliationLedgerEntry' =>
array(/* e2a credit */ array(/* e2 credit */
'CreditLedger' => /* i.e. A/R Ledger */ 'CreditLedger' => /* i.e. A/R Ledger */
array('fields' => array(), array('fields' => array(),
@@ -112,23 +116,14 @@ class MonetarySource extends AppModel {
), ),
/* e1 */ /* e1 */
'DebitReconciliationLedgerEntry' => // STUPID CakePHP bug screws up CLASS contains CLASS.
array(/* e1 credit */ // Use the same class, but with different name.
'CreditLedger' => /* e.g. Rent Ledger */ 'DebitReconciliationLedgerEntry2',
array('fields' => array(),
'Account' => /* e.g. Rent Account */
array('fields' => array(),
'conditions' =>
array('Account.id' => $A->accountReceivableAccountID()),
),
),
),
), ),
/* e3 */ /* e4 */
'CreditReconciliationLedgerEntry' => 'CreditReconciliationLedgerEntry' =>
array(/* e3 debit */ array(/* e4 debit */
'DebitLedger' => /* e.g. BANK Ledger */ 'DebitLedger' => /* e.g. BANK Ledger */
array('fields' => array('id'), array('fields' => array('id'),
'Account' => /* e.g. BANK Account */ 'Account' => /* e.g. BANK Account */
@@ -153,86 +148,95 @@ class MonetarySource extends AppModel {
$ar_account_id = $A->accountReceivableAccountID(); $ar_account_id = $A->accountReceivableAccountID();
$total = 0; $total = 0;
$nsf_rec_ids = array(); $e6_debit_rec_ids = array();
$e6_credit_rec_ids = array();
$transaction_id = null; $e5_transaction_id = null;
// FOR EACH e2b foreach ($source['LedgerEntry'] AS $e3) {
foreach ($source['LedgerEntry'] AS $entry) { // We expect only a single e4 entry
// Count number of e3 entries $e4 = $e3['CreditReconciliationLedgerEntry'];
if (count($entry['CreditReconciliationLedgerEntry']) < 1) if (count($e4) < 1)
continue; continue;
if (count($entry['CreditReconciliationLedgerEntry']) > 1) if (count($e4) > 1)
die('Too many CRLEs'); die('Too many e4 entries');
// e2b amount // Pullup e4 from the single member array
$amount = $entry['amount']; $e4 = $e4[0];
// e3 account // e3 amount
$bank_account_id = $entry['CreditReconciliationLedgerEntry'][0]['DebitLedger']['account_id']; $amount = $e3['amount'];
$amount *= -1;
pr(array('checkpoint' => 'outerloop', // e4 account
compact('id', $amount, 'bank_account_id', $entry))); $bank_account_id = $e4['DebitLedger']['account_id'];
// post new e4 // post new e5
$ids = $A->postLedgerEntry $e5_ids = $A->postLedgerEntry
(array('transaction_id' => $transaction_id), (array('transaction_id' => $e5_transaction_id),
null, null,
array('debit_ledger_id' => $A->currentLedgerID($nsf_account_id), array('debit_ledger_id' => $A->currentLedgerID($bank_account_id),
'credit_ledger_id' => $A->currentLedgerID($bank_account_id), 'credit_ledger_id' => $A->currentLedgerID($nsf_account_id),
'effective_date' => $stamp, 'effective_date' => $stamp,
'amount' => $amount, 'amount' => $amount,
'lease_id' => $entry['lease_id'], 'lease_id' => $e3['lease_id'],
'customer_id' => $entry['customer_id'], 'customer_id' => $e3['customer_id'],
'comment' => "NSF of Monetary Source #{$id}", 'comment' => "NSF of Monetary Source #{$id}",
), /* ), */
array('credit' => array /* array('credit' => array */
(array('LedgerEntry' => array /* (array('LedgerEntry' => array */
('id' => $entry['CreditReconciliationLedgerEntry'][0]['id'], /* ('id' => $e4['id'], */
'amount' => $amount, /* 'amount' => $amount, */
))), /* ))), */
)); ));
if ($ids['error']) if ($e5_ids['error'])
return null; return null;
pr(array('checkpoint' => 'insert 1', pr(array('checkpoint' => 'Posted Ledger Entry e5',
compact('ids'))); compact('e5_ids')));
$e6_debit_rec_ids[]
= array('LedgerEntry' => array('id' => $e5_ids['id'], 'amount' => $amount));
foreach ($e3['DebitReconciliationLedgerEntry'] AS $e2) {
foreach ($e2['DebitReconciliationLedgerEntry2'] AS $e1) {
$e6_credit_rec_ids[]
= array('LedgerEntry' => array('id' => $e1['id'], 'amount' => -1*$e1['Reconciliation']['amount']));
}
}
$total += $amount; $total += $amount;
$nsf_rec_ids[]
= array('LedgerEntry' => array('id' => $ids['id'], 'amount' => $amount));
} }
// Cheat for now // Cheat for now
$lease_id = $source['LedgerEntry'][0]['lease_id']; $lease_id = $source['LedgerEntry'][0]['lease_id'];
$customer_id = $source['LedgerEntry'][0]['customer_id']; $customer_id = $source['LedgerEntry'][0]['customer_id'];
// post new e5a // post new e6
$ids = $A->postLedgerEntry $e6_ids = $A->postLedgerEntry
(null, (null,
null, null,
array('debit_ledger_id' => $A->currentLedgerID($ar_account_id), array('debit_ledger_id' => $A->currentLedgerID($nsf_account_id),
'credit_ledger_id' => $A->currentLedgerID($nsf_account_id), 'credit_ledger_id' => $A->currentLedgerID($ar_account_id),
'effective_date' => $stamp, 'effective_date' => $stamp,
'amount' => $total, 'amount' => $total,
'lease_id' => $lease_id, 'lease_id' => $lease_id,
'customer_id' => $customer_id, 'customer_id' => $customer_id,
'comment' => "NSF back to A/R from Monetary Source #{$id}", 'comment' => "NSF back to A/R from Monetary Source #{$id}",
), ),
array('credit' => $nsf_rec_ids) array('debit' => $e6_debit_rec_ids,
'credit' => $e6_credit_rec_ids)
); );
if ($ids['error']) if ($e6_ids['error'])
return null; return null;
pr(array('checkpoint' => 'insert 2', pr(array('checkpoint' => 'Posted Ledger Entry e6',
compact('ids'))); compact('e6_ids', 'e6_debit_rec_ids', 'e6_credit_rec_ids')));
$tid = $ids['transaction_id']; // post new e7
$e7_ids = $A->postLedgerEntry
// post new e5b (array('transaction_id' => $e6_ids['transaction_id']),
$ids = $A->postLedgerEntry
(array('transaction_id' => $tid),
null, null,
array('debit_ledger_id' => $A->currentLedgerID($ar_account_id), array('debit_ledger_id' => $A->currentLedgerID($ar_account_id),
'credit_ledger_id' => $A->currentLedgerID($nsf_fee_account_id), 'credit_ledger_id' => $A->currentLedgerID($nsf_fee_account_id),
@@ -244,11 +248,11 @@ class MonetarySource extends AppModel {
) )
); );
if ($ids['error']) if ($e7_ids['error'])
return null; return null;
pr(array('checkpoint' => 'insert 3', pr(array('checkpoint' => 'Posted Ledger Entry e7',
compact('ids'))); compact('e7_ids')));
return true; return true;
} }