array('numeric'), 'name' => array('notempty'), 'tillable' => array('boolean') ); var $belongsTo = array( ); var $hasMany = array( 'LedgerEntry', ); /************************************************************************** ************************************************************************** ************************************************************************** * function: nsf * - Flags the ledger entry as having insufficient funds * - NOTE: nsf only works if given the monetary source id * to transaction t2b, below * * FEE RENT A/R RECEIPT CHECK NSF BANK * ------- ------- ------- ------- ------- ------- ------- * | |50 50| | | | | t1 * | | | | | | | * | | |50 50| | | | t2a * | | | |50 50| | | t2b * | | | | | | | * | | | | |50 | 50| t3 * | | | | | | | * | | | | | 50| |50 t4a * | | 50| | | |50 | 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, $stamp = null) { pr(array('MonetarySource::nsf', compact('id'))); $A = new Account(); // Get the LedgerEntries that use this monetary source $source = $this->find ('first', array('contain' => array(/* t2b */ 'LedgerEntry' => array('Transaction.id', 'MonetarySource.id', 'Customer.id', 'Lease.id', /* e.g. CHECK */ 'DebitLedger' => array('fields' => array(), 'Account' => array('fields' => array('id', 'name'), 'conditions' => /* array(array('Account.payable' => 1), */ /* array('Account.type' => 'ASSET')), */ array('Account.payable' => 1, 'Account.type' => 'ASSET'), ), ), /* e.g. RECEIPT */ 'CreditLedger' => array('fields' => array('id'), 'Account' => array('fields' => array('id', 'name'), 'conditions' => array('Account.id' => $A->receiptAccountID()), ), ), /* t3 */ 'CreditReconciliationLedgerEntry' => array(/* e.g. BANK */ 'DebitLedger' => array('fields' => array('id'), 'Account' => array('fields' => array('id', 'name'), 'conditions' => array('Account.depositable' => 1), ), ), ), ), ), /* 'fields' => array('LedgerEntry.*'), */ 'conditions' => array(array('MonetarySource.id' => $id), ), )); pr($source); $nsf_account_id = $A->nsfAccountID(); $nsf_fee_account_id = $A->nsfChargeAccountID(); $ar_account_id = $A->accountReceivableAccountID(); $total = 0; $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, array('debit_ledger_id' => $A->currentLedgerID($ar_account_id), 'credit_ledger_id' => $A->currentLedgerID($nsf_account_id), 'effective_date' => $stamp, 'amount' => $total, 'lease_id' => $lease_id, 'customer_id' => $customer_id, 'comment' => "NSF back to A/R from Monetary Source #{$id}", ), array('credit' => $nsf_rec_ids) ); if ($ids['error']) return null; pr(array('checkpoint' => 'insert 2', compact('ids'))); $tid = $ids['transaction_id']; $ids = $A->postLedgerEntry (array('transaction_id' => $tid), null, array('debit_ledger_id' => $A->currentLedgerID($ar_account_id), 'credit_ledger_id' => $A->currentLedgerID($nsf_fee_account_id), 'effective_date' => $stamp, 'amount' => 35, 'lease_id' => $lease_id, 'customer_id' => $customer_id, 'comment' => "NSF Fee for Monetary Source #{$id}", ) ); if ($ids['error']) return null; pr(array('checkpoint' => 'insert 3', compact('ids'))); return true; } } ?>