Implemented refund, at least for the most part. Minor testing, but looks promising. Because of this change the customer account entries grid appears odd, with a refunds showing up as a 'Charge'. So, I'm toying with the idea of having entries show up as customer 'Debits' and 'Credits'. I don't know if this will cause user confusion, but we'll play with it for a while and see. It actually reminds me a bit (coming full circle) of the earliest implementations, which kept track of a lease on its own account/ledger, in which credit/debit would be the exact correct terms.

git-svn-id: file:///svn-source/pmgr/branches/yafr_20090716/site@493 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
abijah
2009-08-06 05:11:58 +00:00
parent bd85ce9f51
commit a5e7366cac
11 changed files with 236 additions and 133 deletions

View File

@@ -207,6 +207,10 @@ class Account extends AppModel {
return $this->relatedAccounts('deposits', array('order' => 'name'));
}
function refundAccounts() {
return $this->relatedAccounts('refunds', array('order' => 'name'));
}
/**************************************************************************
**************************************************************************

View File

@@ -31,13 +31,17 @@ class StatementEntry extends AppModel {
*/
function debitTypes() {
return array('CHARGE', 'VOUCHER');
return array('CHARGE', 'PAYMENT', 'REFUND');
}
function creditTypes() {
return array('DISBURSEMENT', 'WAIVER', 'SURPLUS');
}
function voidTypes() {
return array('VOID');
}
/**************************************************************************
**************************************************************************
@@ -46,32 +50,36 @@ class StatementEntry extends AppModel {
*/
function chargeDisbursementFields($sum = false, $entry_name = 'StatementEntry') {
$charges = array('CHARGE', 'VOUCHER');
$nulls = array('PAYMENT', 'VOID');
$debits = $this->debitTypes();
$credits = $this->creditTypes();
$voids = $this->voidTypes();
foreach ($charges AS &$enum)
foreach ($debits AS &$enum)
$enum = "'" . $enum . "'";
foreach ($nulls AS &$enum)
foreach ($credits AS &$enum)
$enum = "'" . $enum . "'";
foreach ($voids AS &$enum)
$enum = "'" . $enum . "'";
$charge_set = implode(", ", $charges);
$null_set = implode(", ", $nulls);
$debit_set = implode(", ", $debits);
$credit_set = implode(", ", $credits);
$void_set = implode(", ", $voids);
$fields = array
(
($sum ? 'SUM(' : '') .
"IF({$entry_name}.type IN ({$charge_set})," .
"IF({$entry_name}.type IN ({$debit_set})," .
" {$entry_name}.amount, NULL)" .
($sum ? ')' : '') . ' AS charge' . ($sum ? 's' : ''),
($sum ? 'SUM(' : '') .
"IF({$entry_name}.type NOT IN({$charge_set}, ${null_set})," .
"IF({$entry_name}.type IN({$credit_set})," .
" {$entry_name}.amount, NULL)" .
($sum ? ')' : '') . ' AS disbursement' . ($sum ? 's' : ''),
($sum ? 'SUM(' : '') .
"IF({$entry_name}.type IN ({$null_set}), 0," .
" IF({$entry_name}.type IN ({$charge_set}), 1, -1))" .
"IF({$entry_name}.type IN ({$debit_set}), 1," .
" IF({$entry_name}.type IN ({$credit_set}), -1, 0))" .
" * IF({$entry_name}.amount, {$entry_name}.amount, 0)" .
($sum ? ')' : '') . ' AS balance',
);
@@ -263,23 +271,16 @@ class StatementEntry extends AppModel {
function reconciledSetQuery($set, $query) {
$this->queryInit($query);
if ($set == 'CHARGE' || $set == 'DISBURSEMENT')
$query['conditions'][] = array('StatementEntry.type' => $set);
if (in_array($set, $this->debitTypes()))
$query['link']['DisbursementEntry'] = array('fields' => array("SUM(DisbursementEntry.amount) AS reconciled"));
elseif (in_array($set, $this->creditTypes()))
$query['link']['ChargeEntry'] = array('fields' => array("SUM(ChargeEntry.amount) AS reconciled"));
else
die("INVALID RECONCILE SET");
if ($set == 'CHARGE')
$query['link']['DisbursementEntry'] = array('fields' => array("SUM(DisbursementEntry.amount) AS reconciled"));
if ($set == 'DISBURSEMENT')
$query['link']['ChargeEntry'] = array('fields' => array("SUM(ChargeEntry.amount) AS reconciled"));
$query['conditions'][] = array('StatementEntry.type' => $set);
$query['group'] = 'StatementEntry.id';
// REVISIT: TESTING
//$query['link']['DisbursementEntry'] = array('fields' => array("(`DisbursementEntry.amount`+0) AS reconciled"));
//$query['group'] = null;
// END REVISIT
return $query;
}
@@ -337,9 +338,9 @@ class StatementEntry extends AppModel {
$query['conditions'][] = array('StatementEntry.id' => $id);
if ($this->data['StatementEntry']['type'] == 'CHARGE')
if (in_array($this->data['StatementEntry']['type'], $this->debitTypes()))
$query['link']['DisbursementEntry'] = array();
if ($this->data['StatementEntry']['type'] == 'DISBURSEMENT')
if (in_array($this->data['StatementEntry']['type'], $this->creditTypes()))
$query['link']['ChargeEntry'] = array();
return $query;
@@ -372,7 +373,7 @@ class StatementEntry extends AppModel {
$charge_ids = null, $disbursement_type = null,
$customer_id = null, $lease_id = null)
{
$this->prFunctionLevel(25);
//$this->prFunctionLevel(25);
$this->prEnter(compact('query', 'receipt_id',
'charge_ids', 'disbursement_type',
'customer_id', 'lease_id'));
@@ -450,15 +451,19 @@ class StatementEntry extends AppModel {
$lquery['conditions'][] = array('StatementEntry.lease_id' => $lease_id);
}
$lquery['order'] = 'StatementEntry.effective_date ASC';
$charges = $this->reconciledSet('CHARGE', $lquery, true);
$this->pr(18, compact('charges'),
"Outstanding Charges Determined");
$charges = array();
foreach ($this->debitTypes() AS $dtype) {
$rset = $this->reconciledSet($dtype, $lquery, true);
$entries = $rset['entries'];
$charges = array_merge($charges, $entries);
$this->pr(18, compact('dtype', 'entries'), "Outstanding Debit Entries");
}
// Initialize our list of used credits
$used_credits = array();
// Work through all unpaid charges, applying disbursements as we go
foreach ($charges['entries'] AS $charge) {
foreach ($charges AS $charge) {
$this->pr(20, compact('charge'),
'Process Charge');
@@ -627,7 +632,7 @@ class StatementEntry extends AppModel {
$charge_query['fields'] = array();
$charge_query['fields'][] = "SUM(StatementEntry.amount) AS total";
$charge_query['conditions'][] = array('StatementEntry.type' => array('CHARGE', 'VOUCHER'));
$charge_query['conditions'][] = array('StatementEntry.type' => $this->debitTypes());
$result = $this->find('first', $charge_query);
$stats['Charge'] = $result[0];

View File

@@ -324,28 +324,21 @@ class Transaction extends AppModel {
function addRefund($data, $customer_id, $lease_id = null) {
$this->prEnter(compact('data', 'customer_id', 'lease_id'));
// REVISIT <AP>: 20090804
// NOT IMPLEMENTED AT ALL. Just cut and paste so far
return array('error' => true);
// Establish the transaction as a Refund
// Establish the transaction as a Refund. This is just like a
// Payment, except instead of paying out of the account payable,
// it comes from the customer credit in the account receivable.
// Someday, perhaps we'll just issue a Credit Note or similar,
// but for now, a refund means it's time to actually PAY.
$refund =& $data['Transaction'];
$refund +=
array('type' => 'CREDIT_NOTE',
'crdr' => 'DEBIT',
'account_id' => $this->Account->accountReceivableAccountID(),
'customer_id' => $customer_id,
'lease_id' => $lease_id,
);
array('account_id' => $this->Account->accountReceivableAccountID());
// Go through the statement entries and flag as vouchers
// Also, to make it clear to the user, we flag as a REFUND
// even though that type works and operates just as PAYMENT
foreach ($data['Entry'] AS &$entry)
$entry += array('type' => 'VOUCHER',
'crdr' => 'CREDIT',
'account_id' => $this->Account->accountPayableAccountID(),
);
$entry += array('type' => 'REFUND');
$ids = $this->addTransaction($data['Transaction'], $data['Entry']);
$ids = $this->addPayment($data, $customer_id, $lease_id);
if (isset($ids['transaction_id']))
$ids['refund_id'] = $ids['transaction_id'];
@@ -363,10 +356,6 @@ class Transaction extends AppModel {
function addPayment($data, $customer_id, $lease_id = null) {
$this->prEnter(compact('data', 'customer_id', 'lease_id'));
// REVISIT <AP>: 20090804
// NOT IMPLEMENTED AT ALL. Just cut and paste so far
return array('error' => true);
// Establish the transaction as an payment
$payment =& $data['Transaction'];
$payment +=