diff --git a/site/models/statement_entry.php b/site/models/statement_entry.php index c514d00..c3ba3f3 100644 --- a/site/models/statement_entry.php +++ b/site/models/statement_entry.php @@ -562,38 +562,24 @@ class StatementEntry extends AppModel { if (empty($credit['balance'])) continue; + $ret['receipt_balance'] = $credit['balance']; // Convert non-exhausted receipt credit to an explicit one - $explicit_credit = $this->find - ('first', array('contain' => false, - 'conditions' => - array(array('transaction_id' => $credit['Transaction']['id']), - array('type' => 'SURPLUS')), - )); + $this->pr(18, compact('credit'), + 'Create Explicit Credit'); - if (empty($explicit_credit)) { - $this->pr(18, compact('credit'), - 'Create Explicit Credit'); - - $result = $this->addStatementEntry - (array('type' => 'SURPLUS', - 'account_id' => $credit['LedgerEntry']['account_id'], - 'amount' => $credit['balance'], - 'effective_date' => $credit['Transaction']['stamp'], - 'transaction_id' => $credit['Transaction']['id'], - 'customer_id' => $customer_id, - 'lease_id' => $lease_id, - )); - $ret['Credit'] = $result; - if ($result['error']) - $ret['error'] = true; - } - else { - $this->pr(18, compact('explicit_credit', 'credit'), - 'Update Explicit Credit'); - $EC = new StatementEntry(); - $EC->id = $explicit_credit['StatementEntry']['id']; - $EC->saveField('amount', $credit['balance']); - } +/* //$result = $this->Transaction->LedgerEntry->DoubleEntry->addDoubleEntry */ +/* $result = $this->addStatementEntry */ +/* (array('type' => 'SURPLUS', */ +/* 'account_id' => $credit['LedgerEntry']['account_id'], */ +/* 'amount' => $credit['balance'], */ +/* 'effective_date' => $credit['Transaction']['stamp'], */ +/* 'transaction_id' => $credit['Transaction']['id'], */ +/* 'customer_id' => $customer_id, */ +/* 'lease_id' => $lease_id, */ +/* )); */ +/* $ret['Credit'] = $result; */ +/* if ($result['error']) */ +/* $ret['error'] = true; */ } } diff --git a/site/models/transaction.php b/site/models/transaction.php index 44893b9..e69fbad 100644 --- a/site/models/transaction.php +++ b/site/models/transaction.php @@ -453,54 +453,6 @@ class Transaction extends AppModel { * entries, as layed out in the $data['Entry'] array. The array is * overloaded, since it is used to create both ledger _and_ statement * entries. - * - * $data - * - Transaction - * - [MANDATORY] - * - type (INVOICE, RECEIPT) - * - account_id - * - crdr - * - [OPTIONAL] - * - stamp - * (default: NOW) - * - comment - * - [AUTOMATICALLY SET] (if set, these items will be overwritten) - * - id - * - amount - * - customer_id - * - ledger_id - * - * - Entry (array) - * - [MANDATORY] - * - type (CHARGE, DISBURSEMENT) - * - account_id - * - crdr - * - amount - * - [OPTIONAL] - * - effective_date - * - through_date - * - due_date - * - comment (used for statement or ledger entry, based on context) - * - ledger_entry_comment - * - statement_entry_comment - * - Tender - * - [MANDATORY] - * - tender_type_id - * - [OPTIONAL] - * - name - * (default: Entry Account Name & data1) - * - data1, data2, data3, data4 - * - comment - * - [AUTOMATICALLY SET] (if set, these items will be overwritten) - * - id - * - ledger_entry_id - * - deposit_transaction_id - * - nsf_transaction_id - * - [AUTOMATICALLY SET] (if set, these items will be overwritten) - * - id - * - transaction_id - * - ledger_id - * */ function addTransaction($control, $transaction, $entries) { @@ -523,8 +475,174 @@ class Transaction extends AppModel { $transaction['customer_id'] = $L->field('customer_id'); } + $result = $this->_splitEntries($control, $transaction, $entries); + if (!empty($result['error'])) + return $this->prReturn(array('error' => true)); + + // Extract each item from result and make local variables + extract($result); + + // If transaction amount is not already set, use the + // sum of the entry amounts. + $transaction += array('amount' => $transaction_amount); + + $this->pr(20, compact('transaction', 'entries')); + + // Move forward, verifying and saving everything. + $ret = array(); + if (!$this->verifyTransaction($transaction, $entries)) + return $this->prReturn(array('error' => true) + $ret); + + // Save transaction to the database + $this->create(); + if (!$this->save($transaction)) + return $this->prReturn(array('error' => true) + $ret); + $transaction['id'] = $this->id; + + // Add the entries + $ret = $this->addTransactionEntries($control, $transaction, $entries, false); + + if (!empty($control['assign']) && !$ret['error']) { + $result = $this->StatementEntry->assignCredits + (null, + (empty($control['assign_receipt']) ? null + : $ret['transaction_id']), + null, + $assign_disbursement_type, + $transaction['customer_id'], + $transaction['lease_id'] + ); + + $ret['assigned'] = $result; + if ($result['error']) + $ret['error'] = true; + + if ($control['assign_receipt'] && + !empty($result['receipt_balance'])) { + +/* $result = $this->addTransactionEntries */ +/* ($control, */ +/* $transaction, */ +/* array('' */ + + $result = $this->StatementEntry->addStatementEntry + (array('type' => 'SURPLUS', + 'account_id' => $this->Account->accountPayableAccountID(), + 'amount' => $result['receipt_balance'], + 'effective_date' => $transaction['stamp'], + 'transaction_id' => $transaction['id'], + 'customer_id' => $transaction['customer_id'], + 'lease_id' => $transaction['lease_id'], + )); + } + + } + + $this->Customer->update($transaction['customer_id']); + return $this->prReturn($ret); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: addTransactionEntries + * - Largely a helper function to addTransaction, this function is + * responsible for adding ledger/statement entries to an existing + * transaction. If needed, this function can also be called outside + * of addTransaction, although it's not clear where that would be + * appropriate, since transactions are really snapshots of some + * event, and shouldn't be mucked with after creation. + */ + + function addTransactionEntries($control, $transaction, $entries, $split = true) { + $this->prEnter(compact('control', 'transaction', 'entries', 'split')); + + // Verify that we have a transaction and entries + if (empty($transaction['id']) || + ($transaction['type'] !== 'CLOSE' && empty($entries))) + return $this->prReturn(array('error' => true)); + + // If the entries are not already split, do so now. + if ($split) { + $result = $this->_splitEntries($control, $transaction, $entries); + if (!empty($result['error'])) + return $this->prReturn(array('error' => true)); + $entries = $result['entries']; + } + +/* // Verify the entries */ +/* $ret = array(); */ +/* if (!$this->verifyTransaction($transaction, $entries)) */ +/* return $this->prReturn(array('error' => true) + $ret); */ + + $this->id = $transaction['id']; + $transaction['stamp'] = $this->field('stamp'); + $transaction['customer_id'] = $this->field('customer_id'); + + // Set up our return array + $ret = array(); + $ret['transaction_id'] = $this->id; + $ret['entries'] = array(); + $ret['error'] = false; + + // Go through the entries + foreach ($entries AS $e_index => &$entry) { + // Ensure these items are null'ed out so we don't + // accidentally pick up stale data. + $le1 = $le1_tender = $le2 = $se = null; + extract($entry); + + if (!empty($le1) && !empty($le2)) { + $le1['transaction_id'] = $le2['transaction_id'] = $ret['transaction_id']; + if (isset($le1_tender)) + $le1_tender['customer_id'] = $transaction['customer_id']; + $result = $this->LedgerEntry->DoubleEntry->addDoubleEntry($le1, $le2, $le1_tender); + $ret['entries'][$e_index]['DoubleEntry'] = $result; + if ($result['error']) { + $ret['error'] = true; + continue; + } + } + + if (!empty($se)) { + $se['transaction_id'] = $ret['transaction_id']; + if (empty($se['effective_date'])) + $se['effective_date'] = $transaction['stamp']; + $result = $this->StatementEntry->addStatementEntry($se); + $ret['entries'][$e_index]['StatementEntry'] = $result; + if ($result['error']) { + $ret['error'] = true; + continue; + } + } + } + + return $this->prReturn($ret); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * function: _splitEntries + * - An internal helper function capable of splitting an array of + * combined ledger/statement entries into their indivdual entry + * components (2 ledger entries, and a statement entry), based + * on the typical requirements. Any custom split will have to + * be done outside of this function. + */ + + function _splitEntries($control, $transaction, $entries) { + $this->prEnter(compact('control', 'transaction', 'entries')); + + // Verify that we have a transaction and entries + if (empty($transaction) || + ($transaction['type'] !== 'CLOSE' && empty($entries))) + return $this->prReturn(array('error' => true)); + // Some transactions do not have their statement entries - // generated from this function, but they are instead + // generated directly as part of the transaction, but are // created in the final steps during the reconciliation // phase by the assignCredits function. Keep track of // what type the statement entries _would_ have been, so @@ -626,78 +744,9 @@ class Transaction extends AppModel { $entry = compact('le1', 'le1_tender', 'le2', 'se'); } - // If transaction amount is not already set, use the - // sum of the entry amounts. - $transaction += array('amount' => $transaction_amount); - - $this->pr(20, compact('transaction', 'entries')); - - // Move forward, verifying and saving everything. - $ret = array(); - if (!$this->verifyTransaction($transaction, $entries)) - return $this->prReturn(array('error' => true) + $ret); - - // Save transaction to the database - $this->create(); - if (!$this->save($transaction)) - return $this->prReturn(array('error' => true) + $ret); - $transaction_stamp = $this->field('stamp'); - - // Set up our return ids array - $ret['transaction_id'] = $this->id; - $ret['entries'] = array(); - $ret['error'] = false; - - // Go through the entries - foreach ($entries AS $e_index => &$entry) { - // Ensure these items are null'ed out so we don't - // accidentally pick up stale data. - $le1 = $le1_tender = $le2 = $se = null; - extract($entry); - - if (!empty($le1) && !empty($le2)) { - $le1['transaction_id'] = $le2['transaction_id'] = $ret['transaction_id']; - if (isset($le1_tender)) - $le1_tender['customer_id'] = $transaction['customer_id']; - $result = $this->LedgerEntry->DoubleEntry->addDoubleEntry($le1, $le2, $le1_tender); - $ret['entries'][$e_index]['DoubleEntry'] = $result; - if ($result['error']) { - $ret['error'] = true; - continue; - } - } - - if (!empty($se)) { - $se['transaction_id'] = $ret['transaction_id']; - if (empty($se['effective_date'])) - $se['effective_date'] = $transaction_stamp; - $result = $this->StatementEntry->addStatementEntry($se); - $ret['entries'][$e_index]['StatementEntry'] = $result; - if ($result['error']) { - $ret['error'] = true; - continue; - } - } - } - - if (!empty($control['assign']) && !$ret['error']) { - $result = $this->StatementEntry->assignCredits - (null, - (empty($control['assign_receipt']) ? null - : $ret['transaction_id']), - null, - $assign_disbursement_type, - $transaction['customer_id'], - $transaction['lease_id'] - ); - - $ret['assigned'] = $result; - if ($result['error']) - $ret['error'] = true; - } - - $this->Customer->update($transaction['customer_id']); - return $this->prReturn($ret); + return $this->prReturn(compact('transaction_amount', + 'assign_disbursement_type', + 'entries') + array('error' => false)); } @@ -887,6 +936,7 @@ class Transaction extends AppModel { array('control' => array('assign' => true, 'assign_receipt' => true, + //'assign_receipt' => true, 'include_ledger_entry' => false, 'include_statement_entry' => true, ), @@ -894,9 +944,11 @@ class Transaction extends AppModel { 'Transaction' => array('stamp' => $stamp, 'type' => 'CREDIT_NOTE', - 'crdr' => 'DEBIT', + + 'crdr' => 'CREDIT', + 'account_id' => $this->Account->accountReceivableAccountID(), + 'amount' => $charge['StatementEntry']['amount'], - 'account_id' => $charge['StatementEntry']['account_id'], 'customer_id' => $charge['StatementEntry']['customer_id'], 'lease_id' => null, 'comment' => $comment, @@ -922,9 +974,11 @@ class Transaction extends AppModel { array('include_ledger_entry' => true, 'include_statement_entry' => true, 'type' => 'REVERSAL', - 'crdr' => 'CREDIT', + + 'crdr' => 'DEBIT', + 'account_id' => $charge['StatementEntry']['account_id'], + 'amount' => $rollback['Transaction']['amount'], - 'account_id' => $this->Account->accountReceivableAccountID(), 'customer_id' => $charge['StatementEntry']['customer_id'], 'lease_id' => $charge['StatementEntry']['lease_id'], 'charge_entry_id' => $charge['StatementEntry']['id'],