array( 'className' => 'Transaction', ), 'NsfTransaction' => array( 'className' => 'Transaction', ), ); /************************************************************************** ************************************************************************** ************************************************************************** * function: verifyTender * - Verifies consistenty of new tender data * (not in a pre-existing tender) */ function verifyTender($tender) { /* pr(array("Tender::verifyTender()" */ /* => compact('tender'))); */ if (empty($tender['tender_type_id'])) { /* pr(array("Tender::verifyTender()" */ /* => "Tender verification failed")); */ return false; } return true; } /************************************************************************** ************************************************************************** ************************************************************************** * function: addTender * - Inserts new Tender into the database */ function addTender($tender) { /* pr(array('Tender::addTender' => */ /* compact('tender'))); */ $ret = array(); if (!$this->verifyTender($tender)) return array('error' => true) + $ret; // Come up with a (not necessarily unique) name for the tender. // For checks & money orders, this will be based on the check // number. For other types of tender, we'll just use the // generic name of the monetary account. // REVISIT : 20090723 // I would like to have cash named "Cash #1234", where // the number would correspond to either the Tender ID // or the LedgerEntry ID. if (empty($tender['name']) && !empty($tender['account_id'])) { $tender['name'] = $this->LedgerEntry->Account->name($tender['account_id']); if ($tender['account_id'] == $this->LedgerEntry->Account->checkAccountID() || $tender['account_id'] == $this->LedgerEntry->Account->moneyOrderAccountID()) { $tender['name'] .= ' #' . $tender['data1']; } } /* pr(array('Tender::addTender' => */ /* array('checkpoint' => 'Pre-Save') */ /* + array('Tender' => $tender))); */ $this->create(); if (!$this->save($tender)) return array('error' => true) + $ret; $ret['tender_id'] = $this->id; return $ret + array('error' => false); } /************************************************************************** ************************************************************************** ************************************************************************** * function: nsf * - Flags the ledger entry as having insufficient funds * * Steps: * - Get information from Check (C1); for amount $A * - Find Bank Deposit matching to Tender * - New Transaction (T1) * - New Bank Deposit (D1) * - New Tender (N1); NSF; D1, * - Add new LedgerEntry (L1a); T1; debit:bank; -$A * - Add new LedgerEntry (L1b); T1; credit:NSF; -$A * - Add new LedgerEntry (L2a); T1; debit:NSF; -$A; N1 * - Add new LedgerEntry (L2b); T1; credit:A/R; -$A * - For Tx associated with LE associated with C1: * - For each Payment SE of Tx: * - Add new StatementEntry (S1n); T1; PAYMENT; -1*S1n.amount * - New Transaction (T2) (?????) * - Add new StatementEntry (S2); T2; CHARGE; NSF; $35 * - Add new LedgerEntry (L3a); T2; credit:NSF-Fee; $35 * - Add new LedgerEntry (L3b); T2; debit:A/R; $35 * - Set C1.nsf_tx = T1 * - Re-Reconcile (customer may have running credit) */ function nsf($id, $stamp = null) { pr(array('Tender::nsf', compact('id'))); // Get information about this NSF item. $this->id = $id; $tender = $this->find ('first', array ('contain' => array('LedgerEntry', 'DepositTransaction', 'NsfTransaction'), )); //'conditions' => array(array('Tender.id' => $id)), pr($tender); if (!empty($tender['NsfTransaction']['id'])) die("Item has already been set as NSF"); if (empty($tender['DepositTransaction']['id'])) die("Item has not been deposited yet"); /* $payments = $this->LedgerEntry->Transaction->StatementEntry->find */ /* ('all', array */ /* ('contain' => array('Transaction' => */ /* array('fields' => array(), */ /* 'LedgerEntry */ /* 'conditions' => array('StatementEntry.transaction_id' => xx, */ /* array('LedgerEntry', */ /* 'DepositTransaction', */ /* 'NsfTransaction'), */ /* )); */ $nsf_ledger_entry = $this->LedgerEntry->find ('first', array ('contain' => array('Transaction' => array(//'fields' => array(), 'StatementEntry' => array(//'fields' => array(), ), ), ), 'conditions' => array('LedgerEntry.id' => $tender['LedgerEntry']['id']), )); pr(compact('nsf_ledger_entry')); $bounce = array('Transaction' => array(), 'Entry' => array()); $bounce['Transaction']['account_id'] = $tender['DepositTransaction']['account_id']; $bounce['Transaction']['customer_id'] = $tender['Tender']['customer_id']; $bounce['Transaction']['amount'] = -1 * $tender['LedgerEntry']['amount']; foreach ($nsf_ledger_entry['Transaction']['StatementEntry'] AS $payment) { $bounce['Entry'][] = array('type' => 'PAYMENT', 'amount' => -1 * $payment['amount'], 'account_id' => $payment['account_id'], 'customer_id' => $payment['customer_id'], 'lease_id' => $payment['lease_id'], 'charge_entry_id' => $payment['charge_entry_id'], //'effective_date' => $tender[ stamp ], ); } pr(compact('bounce')); $result = $this->NsfTransaction->addNsf($bounce); if ($result['error']) die("Unable to save NSF transaction"); $this->id = $id; $this->saveField('nsf_transaction_id', $result['transaction_id']); die(); $nsf_account_id = $A->nsfAccountID(); $nsf_fee_account_id = $A->nsfChargeAccountID(); $ar_account_id = $A->accountReceivableAccountID(); $receipt_account_id = $A->receiptAccountID(); $t4_id = null; $t5_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']; // e4 account $bank_account_id = $e4['DebitLedger']['account_id']; // post new e5 $e5_ids = $A->postLedgerEntry (array('transaction_id' => $t4_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 Bank Reversal; Monetary Source #{$id}", ) ); if ($e5_ids['error']) return null; $t4_id = $e5_ids['transaction_id']; pr(array('checkpoint' => 'Posted Ledger Entry e5', compact('e5_ids', 'amount'))); // post new e6... this will be our crossover point // from typical positive entries to negative entries. // Therefore, no reconciliation on this account. $e6_ids = $A->postLedgerEntry (array('transaction_id' => $t5_id), array('monetary_source_id' => $e3['monetary_source_id']), array('debit_ledger_id' => $A->currentLedgerID($nsf_account_id), 'credit_ledger_id' => $A->currentLedgerID($receipt_account_id), 'effective_date' => $stamp, 'amount' => $amount, 'lease_id' => $e3['lease_id'], 'customer_id' => $e3['customer_id'], 'comment' => "NSF tracker; Monetary Source #{$id}", ), array('debit' => array (array('LedgerEntry' => array('id' => $e5_ids['id'], 'amount' => $amount))), ) ); if ($e6_ids['error']) return null; $t5_id = $e6_ids['transaction_id']; pr(array('checkpoint' => 'Posted Ledger Entry e6', compact('e6_ids', 'amount'))); $t6_id = null; foreach ($e3['DebitReconciliationLedgerEntry'] AS $e2) { foreach ($e2['DebitReconciliationLedgerEntry2'] AS $e1) { $amount = -1*$e1['Reconciliation']['amount']; // post new e7 $e7_ids = $A->postLedgerEntry (array('transaction_id' => $t6_id), null, array('debit_ledger_id' => $A->currentLedgerID($receipt_account_id), 'credit_ledger_id' => $A->currentLedgerID($ar_account_id), 'effective_date' => $stamp, 'amount' => $amount, 'lease_id' => $e1['lease_id'], 'customer_id' => $e1['customer_id'], 'comment' => "NSF Receipt; Monetary Source #{$id}", ), array('debit' => array (array('LedgerEntry' => array('id' => $e6_ids['id'], 'amount' => $amount))), 'credit' => array (array('LedgerEntry' => array('id' => $e1['id'], 'amount' => $amount))), ) ); if ($e7_ids['error']) return null; $t6_id = $e7_ids['transaction_id']; pr(array('checkpoint' => 'Posted Ledger Entry e7', compact('e7_ids', 'amount'))); } } } // Cheat for now $customer_id = $source['LedgerEntry'][0]['customer_id']; $lease_id = null; // post new e8 $e8_ids = $A->postLedgerEntry (array('transaction_id' => $t6_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; Monetary Source #{$id}", ) ); if ($e8_ids['error']) return null; pr(array('checkpoint' => 'Posted Ledger Entry e8', compact('e8_ids'))); return true; } } ?>