The NSF functionality is working good from a strictly general ledger point of view. However, as it's implemented, it's leaving us unable to observe that we've actually experienced negative collected rent. This is a big problem, but I've put a couple notes in place on how I might try to proceed on this next, and am checking in this semi-working version.

git-svn-id: file:///svn-source/pmgr/branches/invoice_receipt_20090629/site@329 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
abijah
2009-07-14 20:48:16 +00:00
parent 69b3cf3ed3
commit 01aa2d1697
3 changed files with 114 additions and 64 deletions

View File

@@ -61,7 +61,11 @@ class MonetarySourcesController extends AppController {
$this->redirect(array('action'=>'index')); $this->redirect(array('action'=>'index'));
} }
$this->MonetarySource->nsf($id); // REVISIT <AP>: 20090713
// For testing purposes, must be deleted
$stamp = '2009-07-09';
$this->MonetarySource->nsf($id, $stamp);
} }
/************************************************************************** /**************************************************************************

View File

@@ -114,6 +114,8 @@ class Account extends AppModel {
function securityDepositAccountID() { return $this->nameToID('Security Deposit'); } function securityDepositAccountID() { return $this->nameToID('Security Deposit'); }
function rentAccountID() { return $this->nameToID('Rent'); } function rentAccountID() { return $this->nameToID('Rent'); }
function lateChargeAccountID() { return $this->nameToID('Late Charge'); } function lateChargeAccountID() { return $this->nameToID('Late Charge'); }
function nsfAccountID() { return $this->nameToID('NSF'); }
function nsfChargeAccountID() { return $this->nameToID('NSF Charge'); }
function taxAccountID() { return $this->nameToID('Tax'); } function taxAccountID() { return $this->nameToID('Tax'); }
function accountReceivableAccountID() { return $this->nameToID('A/R'); } function accountReceivableAccountID() { return $this->nameToID('A/R'); }
function cashAccountID() { return $this->nameToID('Cash'); } function cashAccountID() { return $this->nameToID('Cash'); }

View File

@@ -36,18 +36,36 @@ class MonetarySource extends AppModel {
* | | | | | 50| |50 t4a * | | | | | 50| |50 t4a
* | | 50| | | |50 | t4b * | | 50| | | |50 | t4b
* |35 | 35| | | | | t4b * |35 | 35| | | | | t4b
* - NOTE
* The above example is great, except it leave no way to resolve
* that the rent has not actually been collected. So, instead
* perhaps we need to run a negative credit to A/R, which we can
* use to reconcile against the Rent<->A/R double entry:
*
* | | | | | 50| |50 t4a
* | | |-50 | | -50| | t4b
* |35 | 35| | | | | t4b
* OR perhaps even a negative entry all the way through to the
* bank, making the NSF appear not as a withdrawal, but as a
* negative deposit (i.e, and adjustment, just like it really is):
*
* | | | | | |-50 -50| t4a
* | | |-50 | | -50| | t4b
* |35 | 35| | | | | t4b
* *
*/ */
function nsf($id) { function nsf($id, $stamp = null) {
pr(array('MonetarySource::nsf', pr(array('MonetarySource::nsf',
compact('id'))); compact('id')));
$A = new Account(); $A = new Account();
// Get the LedgerEntries that use this monetary source // Get the LedgerEntries that use this monetary source
$entries = $this->find $source = $this->find
('all', ('first',
array('contain' => array('contain' =>
array(/* t2b */ array(/* t2b */
'LedgerEntry' => 'LedgerEntry' =>
@@ -71,7 +89,7 @@ class MonetarySource extends AppModel {
/* e.g. RECEIPT */ /* e.g. RECEIPT */
'CreditLedger' => 'CreditLedger' =>
array('fields' => array(), array('fields' => array('id'),
'Account' => 'Account' =>
array('fields' => array('id', 'name'), array('fields' => array('id', 'name'),
'conditions' => 'conditions' =>
@@ -83,7 +101,7 @@ class MonetarySource extends AppModel {
'CreditReconciliationLedgerEntry' => 'CreditReconciliationLedgerEntry' =>
array(/* e.g. BANK */ array(/* e.g. BANK */
'DebitLedger' => 'DebitLedger' =>
array('fields' => array(), array('fields' => array('id'),
'Account' => 'Account' =>
array('fields' => array('id', 'name'), array('fields' => array('id', 'name'),
'conditions' => 'conditions' =>
@@ -99,78 +117,104 @@ class MonetarySource extends AppModel {
'conditions' => array(array('MonetarySource.id' => $id), 'conditions' => array(array('MonetarySource.id' => $id),
), ),
)); ));
pr($entries); pr($source);
die();
if (!isset($amount)) $nsf_account_id = $A->nsfAccountID();
$amount = $entry['LedgerEntry']['amount']; $nsf_fee_account_id = $A->nsfChargeAccountID();
$ar_account_id = $A->accountReceivableAccountID();
$ids = $this->Ledger->Account->postLedgerEntry $total = 0;
(array('transaction_id' => $transaction_id), $nsf_rec_ids = array();
$transaction_id = null;
foreach ($source['LedgerEntry'] AS $entry) {
if (count($entry['CreditReconciliationLedgerEntry']) < 1)
continue;
if (count($entry['CreditReconciliationLedgerEntry']) > 1)
die('Too many CRLEs');
$amount = $entry['amount'];
$bank_account_id = $entry['CreditReconciliationLedgerEntry'][0]['DebitLedger']['account_id'];
pr(array('checkpoint' => 'outerloop',
compact('id', $amount, 'bank_account_id', $entry)));
$ids = $A->postLedgerEntry
(array('transaction_id' => $transaction_id),
null,
array('debit_ledger_id' => $A->currentLedgerID($nsf_account_id),
'credit_ledger_id' => $A->currentLedgerID($bank_account_id),
'effective_date' => $stamp,
'amount' => $amount,
'lease_id' => $entry['lease_id'],
'customer_id' => $entry['customer_id'],
'comment' => "NSF of Monetary Source #{$id}",
),
array('credit' => array
(array('LedgerEntry' => array
('id' => $entry['CreditReconciliationLedgerEntry'][0]['id'],
'amount' => $amount,
))),
));
if ($ids['error'])
return null;
pr(array('checkpoint' => 'insert 1',
compact('ids')));
$total += $amount;
$nsf_rec_ids[]
= array('LedgerEntry' => array('id' => $ids['id'], 'amount' => $amount));
}
// Cheat for now
$lease_id = $source['LedgerEntry'][0]['lease_id'];
$customer_id = $source['LedgerEntry'][0]['customer_id'];
$ids = $A->postLedgerEntry
(null,
null, null,
array('debit_ledger_id' => $A->currentLedgerID($entry['CreditLedger']['account_id']), array('debit_ledger_id' => $A->currentLedgerID($ar_account_id),
'credit_ledger_id' => $A->currentLedgerID($entry['DebitLedger']['account_id']), 'credit_ledger_id' => $A->currentLedgerID($nsf_account_id),
'effective_date' => $entry['LedgerEntry']['effective_date'], 'effective_date' => $stamp,
//'effective_date' => $entry['LedgerEntry']['effective_date'], 'amount' => $total,
'amount' => $amount, 'lease_id' => $lease_id,
'lease_id' => $entry['Lease']['id'], 'customer_id' => $customer_id,
'customer_id' => $entry['Customer']['id'], 'comment' => "NSF back to A/R from Monetary Source #{$id}",
'comment' => "Reversal of Ledger Entry #{$id}",
), ),
array('debit' => array(array('LedgerEntry' => array('id' => $entry['LedgerEntry']['id'], array('credit' => $nsf_rec_ids)
'amount' => $amount, );
))),
'credit' => array(array('LedgerEntry' => array('id' => $entry['LedgerEntry']['id'],
'amount' => $amount,
))),
));
if ($ids['error']) if ($ids['error'])
return null; return null;
pr(array('checkpoint' => 'insert 2',
compact('ids')));
$tid = $ids['transaction_id']; $tid = $ids['transaction_id'];
/* pr(compact('entry')); */ $ids = $A->postLedgerEntry
(array('transaction_id' => $tid),
foreach (array('Debit', 'Credit') AS $dc_type) { null,
foreach ($entry[$dc_type . 'ReconciliationLedgerEntry'] AS $RLE) { array('debit_ledger_id' => $A->currentLedgerID($ar_account_id),
/* pr(array('checkpoint' => "Reverse $dc_type LE", */ 'credit_ledger_id' => $A->currentLedgerID($nsf_fee_account_id),
/* compact('id', 'RLE'))); */ 'effective_date' => $stamp,
if ($RLE['id'] == $rec_id) 'amount' => 35,
continue; 'lease_id' => $lease_id,
'customer_id' => $customer_id,
if (!$this->reverse($RLE['id'], $RLE['Reconciliation']['amount'], $tid, $id)) 'comment' => "NSF Fee for Monetary Source #{$id}",
$ids['error'] = true; )
);
/* $rids = $this->Ledger->Account->postLedgerEntry */
/* (array('transaction_id' => $tid), */
/* null, */
/* array('debit_ledger_id' => $A->currentLedgerID($RLE['CreditLedger']['account_id']), */
/* 'credit_ledger_id' => $A->currentLedgerID($RLE['DebitLedger']['account_id']), */
/* 'effective_date' => $RLE['effective_date'], */
/* //'effective_date' => $RLE['effective_date'], */
/* 'amount' => $RLE['Reconciliation']['amount'], */
/* 'lease_id' => $entry['Lease']['id'], */
/* 'customer_id' => $entry['Customer']['id'], */
/* 'comment' => "Reversal of Ledger Entry #{$RLE['id']}", */
/* ), */
/* array('debit' => array(array('LedgerEntry' => array('id' => $RLE['id'], */
/* 'amount' => $RLE['Reconciliation']['amount'], */
/* ))), */
/* 'credit' => array(array('LedgerEntry' => array('id' => $RLE['id'], */
/* 'amount' => $RLE['Reconciliation']['amount'], */
/* ))), */
/* )); */
/* if ($rids['error']) */
/* $ids['error'] = true; */
}
}
if ($ids['error']) if ($ids['error'])
return null; return null;
return $ids['id']; pr(array('checkpoint' => 'insert 3',
compact('ids')));
return true;
} }