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:
@@ -207,6 +207,10 @@ class Account extends AppModel {
|
||||
return $this->relatedAccounts('deposits', array('order' => 'name'));
|
||||
}
|
||||
|
||||
function refundAccounts() {
|
||||
return $this->relatedAccounts('refunds', array('order' => 'name'));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -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 +=
|
||||
|
||||
Reference in New Issue
Block a user