array( 'className' => 'LedgerEntry', ), 'CreditEntry' => array( 'className' => 'LedgerEntry', ), ); /************************************************************************** ************************************************************************** ************************************************************************** * function: verifyDoubleEntry * - Verifies consistenty of new double entry data * (not in a pre-existing double entry) */ function verifyDoubleEntry($entry1, $entry2, $entry1_tender = null) { /* pr(array("DoubleEntry::verifyDoubleEntry()" */ /* => compact('entry1', 'entry2', 'entry1_tender'))); */ $LE = new LedgerEntry(); if (!$LE->verifyLedgerEntry($entry1, $entry1_tender)) { /* pr(array("DoubleEntry::verifyDoubleEntry()" */ /* => "Entry1 verification failed")); */ return false; } if (!$LE->verifyLedgerEntry($entry2)) { /* pr(array("DoubleEntry::verifyDoubleEntry()" */ /* => "Entry2 verification failed")); */ return false; } if (!(($entry1['crdr'] === 'DEBIT' && $entry2['crdr'] === 'CREDIT') || ($entry1['crdr'] === 'CREDIT' && $entry2['crdr'] === 'DEBIT')) || ($entry1['amount'] != $entry2['amount'])) { /* pr(array("DoubleEntry::verifyDoubleEntry()" */ /* => "Double Entry verification failed")); */ return false; } return true; } /************************************************************************** ************************************************************************** ************************************************************************** * function: addDoubleEntry * - Inserts new Double Entry into the database */ function addDoubleEntry($entry1, $entry2, $entry1_tender = null) { //$this->prFunctionLevel(16); $this->prEnter(compact('entry1', 'entry2', 'entry1_tender')); $ret = array(); if (!$this->verifyDoubleEntry($entry1, $entry2, $entry1_tender)) return $this->prReturn(array('error' => true) + $ret); // Handle the case where a double entry involves the same // exact ledger. This would not serve any useful purpose. // It is not, however, an error. It is semantically correct // just not really logically correct. To make this easier, // just ensure ledger_id is set for each entry, even though // it would be handled later by the LedgerEntry model. //array($entry1, $entry2) AS &$entry) { for ($i=1; $i <= 2; ++$i) { if (empty(${'entry'.$i}['ledger_id'])) ${'entry'.$i}['ledger_id'] = $this->DebitEntry->Account->currentLedgerID(${'entry'.$i}['account_id']); } if ($entry1['ledger_id'] == $entry2['ledger_id']) return $this->prReturn(array('error' => false)); // Since this model only relates to DebitEntry and CreditEntry... $LE = new LedgerEntry(); // Add the first ledger entry to the database $result = $LE->addLedgerEntry($entry1, $entry1_tender); $ret['Entry1'] = $result; if ($result['error']) return $this->prReturn(array('error' => true) + $ret); // Add the second ledger entry to the database $result = $LE->addLedgerEntry($entry2); $ret['Entry2'] = $result; if ($result['error']) return $this->prReturn(array('error' => true) + $ret); // Now link them as a double entry $double_entry = array(); $double_entry['debit_entry_id'] = ($entry1['crdr'] === 'DEBIT') ? $ret['Entry1']['ledger_entry_id'] : $ret['Entry2']['ledger_entry_id']; $double_entry['credit_entry_id'] = ($entry1['crdr'] === 'CREDIT') ? $ret['Entry1']['ledger_entry_id'] : $ret['Entry2']['ledger_entry_id']; $ret['data'] = $double_entry; $this->create(); if (!$this->save($double_entry)) return $this->prReturn(array('error' => true) + $ret); $ret['double_entry_id'] = $this->id; return $this->prReturn($ret + array('error' => false)); } }