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 e3, below * * FEE RENT A/R RECEIPT CHECK NSF BANK * ------- ------- ------- ------- ------- ------- ------- * | |30 30| | | | | t1 e1a : R e2/e6a : * | |20 20| | | | | t1 e1b : R e2/e6b : * | | | | | | | * | | |50 50| | | | t2 e2 : R e3 : R e1a/e1b * | | | |50 50| | | t2 e3 : R e4 : R e2 * | | | | | | | * | | | | |50 | 50| t3 e4 : R e5 : R e3 * | | | | | | | * | | | | | 50| |50 t4 e5 : R e4 : R e6a/e6b * | | 30| | | |30 | t5 e6a : : R e5 * | | 20| | | |20 | t5 e6b : : R e5 * |35 | 35| | | | | t5 e7 * - 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 t4 e5 : R e4 : R e6a/e6b (?) * | | |-30 | | -30| | t5 e6a : R e1a : R e5 (?) * | | |-20 | | -20| | t5 e6b : R e1b : R e5 (?) * |35 | 35| | | | | t5 e7 * 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| t4 e5 : R e4 (?) : R e6a/e6b * | | |-30 | | -30| | t5 e6a : R e1a : R e5 * | | |-20 | | -20| | t5 e6b : R e1b : R e5 * |35 | 35| | | | | t5 e7 * */ 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(/* e3 */ 'LedgerEntry' => array('Transaction.id', 'MonetarySource.id', 'Customer.id', 'Lease.id', /* e3 debit */ 'DebitLedger' => /* e.g. CHECK Ledger */ array('fields' => array(), 'Account' => /* e.g. CHECK Account */ array('fields' => array('id', 'name'), 'conditions' => /* array(array('Account.payable' => 1), */ /* array('Account.type' => 'ASSET')), */ array('Account.payable' => 1, 'Account.type' => 'ASSET'), ), ), /* e3 credit */ 'CreditLedger' => /* i.e. RECEIPT Ledger */ array('fields' => array('id'), 'Account' => /* i.e. RECEIPT Account */ array('fields' => array('id', 'name'), 'conditions' => array('Account.id' => $A->receiptAccountID()), ), ), /* e2 */ 'DebitReconciliationLedgerEntry' => array(/* e2 credit */ 'CreditLedger' => /* i.e. A/R Ledger */ array('fields' => array(), 'Account' => /* i.e. A/R Account */ array('fields' => array(), 'conditions' => array('Account.id' => $A->accountReceivableAccountID()), ), ), /* e1 */ // STUPID CakePHP bug screws up CLASS contains CLASS. // Use the same class, but with different name. 'DebitReconciliationLedgerEntry2', ), /* e4 */ 'CreditReconciliationLedgerEntry' => array(/* e4 debit */ 'DebitLedger' => /* e.g. BANK Ledger */ array('fields' => array('id'), 'Account' => /* e.g. BANK 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; $e6_debit_rec_ids = array(); $e6_credit_rec_ids = array(); $e5_transaction_id = null; foreach ($source['LedgerEntry'] AS $e3) { // We expect only a single e4 entry $e4 = $e3['CreditReconciliationLedgerEntry']; if (count($e4) < 1) continue; if (count($e4) > 1) die('Too many e4 entries'); // Pullup e4 from the single member array $e4 = $e4[0]; // e3 amount $amount = $e3['amount']; $amount *= -1; // e4 account $bank_account_id = $e4['DebitLedger']['account_id']; // post new e5 $e5_ids = $A->postLedgerEntry (array('transaction_id' => $e5_transaction_id), null, array('debit_ledger_id' => $A->currentLedgerID($bank_account_id), 'credit_ledger_id' => $A->currentLedgerID($nsf_account_id), 'effective_date' => $stamp, 'amount' => $amount, 'lease_id' => $e3['lease_id'], 'customer_id' => $e3['customer_id'], 'comment' => "NSF of Monetary Source #{$id}", /* ), */ /* array('credit' => array */ /* (array('LedgerEntry' => array */ /* ('id' => $e4['id'], */ /* 'amount' => $amount, */ /* ))), */ )); if ($e5_ids['error']) return null; pr(array('checkpoint' => 'Posted Ledger Entry e5', 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; } // Cheat for now $lease_id = $source['LedgerEntry'][0]['lease_id']; $customer_id = $source['LedgerEntry'][0]['customer_id']; // post new e6 $e6_ids = $A->postLedgerEntry (null, null, array('debit_ledger_id' => $A->currentLedgerID($nsf_account_id), 'credit_ledger_id' => $A->currentLedgerID($ar_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('debit' => $e6_debit_rec_ids, 'credit' => $e6_credit_rec_ids) ); if ($e6_ids['error']) return null; pr(array('checkpoint' => 'Posted Ledger Entry e6', compact('e6_ids', 'e6_debit_rec_ids', 'e6_credit_rec_ids'))); // post new e7 $e7_ids = $A->postLedgerEntry (array('transaction_id' => $e6_ids['transaction_id']), 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 ($e7_ids['error']) return null; pr(array('checkpoint' => 'Posted Ledger Entry e7', compact('e7_ids'))); return true; } } ?>