Files
pmgr/models/monetary_source.php

262 lines
8.7 KiB
PHP

<?php
class MonetarySource extends AppModel {
var $name = 'MonetarySource';
var $validate = array(
'id' => array('numeric'),
'name' => array('notempty'),
'tillable' => array('boolean')
);
var $belongsTo = array(
);
var $hasMany = array(
'LedgerEntry',
);
/**************************************************************************
**************************************************************************
**************************************************************************
* function: nsf
* - Flags the ledger entry as having insufficient funds
* - NOTE: nsf only works if given the monetary source id
* to transaction e3, below
*
* FEE RENT A/R RECEIPT CHECK NSF BANK
* ------- ------- ------- ------- ------- ------- -------
* | |30 30| | | | | t1 e1a : R e2/e6a :
* | |20 20| | | | | t1 e1b : R e2/e6b :
* | | | | | | |
* | | |50 50| | | | t2 e2 : R e3 : R e1a/e1b
* | | | |50 50| | | t2 e3 : R e4 : R e2
* | | | | | | |
* | | | | |50 | 50| t3 e4 : R e5 : R e3
* | | | | | | |
* | | | | | 50| |50 t4 e5 : R e4 : R e6a/e6b
* | | 30| | | |30 | t5 e6a : : R e5
* | | 20| | | |20 | t5 e6b : : R e5
* |35 | 35| | | | | t5 e7
* - NOTE
* The above example is great, except it leave no way to resolve
* that the rent has not actually been collected. So, instead
* perhaps we need to run a negative credit to A/R, which we can
* use to reconcile against the Rent<->A/R double entry:
*
* | | | | | 50| |50 t4 e5 : R e4 : R e6a/e6b (?)
* | | |-30 | | -30| | t5 e6a : R e1a : R e5 (?)
* | | |-20 | | -20| | t5 e6b : R e1b : R e5 (?)
* |35 | 35| | | | | t5 e7
* OR perhaps even a negative entry all the way through to the
* bank, making the NSF appear not as a withdrawal, but as a
* negative deposit (i.e, and adjustment, just like it really is):
*
* | | | | | |-50 -50| t4 e5 : R e4 (?) : R e6a/e6b
* | | |-30 | | -30| | t5 e6a : R e1a : R e5
* | | |-20 | | -20| | t5 e6b : R e1b : R e5
* |35 | 35| | | | | t5 e7
*
*/
function nsf($id, $stamp = null) {
pr(array('MonetarySource::nsf',
compact('id')));
$A = new Account();
// Get the LedgerEntries that use this monetary source
$source = $this->find
('first',
array('contain' =>
array(/* e3 */
'LedgerEntry' =>
array('Transaction.id',
'MonetarySource.id',
'Customer.id',
'Lease.id',
/* e3 debit */
'DebitLedger' => /* e.g. CHECK Ledger */
array('fields' => array(),
'Account' => /* e.g. CHECK Account */
array('fields' => array('id', 'name'),
'conditions' =>
/* array(array('Account.payable' => 1), */
/* array('Account.type' => 'ASSET')), */
array('Account.payable' => 1,
'Account.type' => 'ASSET'),
),
),
/* e3 credit */
'CreditLedger' => /* i.e. RECEIPT Ledger */
array('fields' => array('id'),
'Account' => /* i.e. RECEIPT Account */
array('fields' => array('id', 'name'),
'conditions' =>
array('Account.id' => $A->receiptAccountID()),
),
),
/* e2 */
'DebitReconciliationLedgerEntry' =>
array(/* e2 credit */
'CreditLedger' => /* i.e. A/R Ledger */
array('fields' => array(),
'Account' => /* i.e. A/R Account */
array('fields' => array(),
'conditions' =>
array('Account.id' => $A->accountReceivableAccountID()),
),
),
/* e1 */
// STUPID CakePHP bug screws up CLASS contains CLASS.
// Use the same class, but with different name.
'DebitReconciliationLedgerEntry2',
),
/* e4 */
'CreditReconciliationLedgerEntry' =>
array(/* e4 debit */
'DebitLedger' => /* e.g. BANK Ledger */
array('fields' => array('id'),
'Account' => /* e.g. BANK Account */
array('fields' => array('id', 'name'),
'conditions' =>
array('Account.depositable' => 1),
),
),
),
),
),
/* 'fields' => array('LedgerEntry.*'), */
'conditions' => array(array('MonetarySource.id' => $id),
),
));
pr($source);
$nsf_account_id = $A->nsfAccountID();
$nsf_fee_account_id = $A->nsfChargeAccountID();
$ar_account_id = $A->accountReceivableAccountID();
$total = 0;
$e6_debit_rec_ids = array();
$e6_credit_rec_ids = array();
$e5_transaction_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'];
$amount *= -1;
// e4 account
$bank_account_id = $e4['DebitLedger']['account_id'];
// post new e5
$e5_ids = $A->postLedgerEntry
(array('transaction_id' => $e5_transaction_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 of Monetary Source #{$id}",
/* ), */
/* array('credit' => array */
/* (array('LedgerEntry' => array */
/* ('id' => $e4['id'], */
/* 'amount' => $amount, */
/* ))), */
));
if ($e5_ids['error'])
return null;
pr(array('checkpoint' => 'Posted Ledger Entry e5',
compact('e5_ids')));
$e6_debit_rec_ids[]
= array('LedgerEntry' => array('id' => $e5_ids['id'], 'amount' => $amount));
foreach ($e3['DebitReconciliationLedgerEntry'] AS $e2) {
foreach ($e2['DebitReconciliationLedgerEntry2'] AS $e1) {
$e6_credit_rec_ids[]
= array('LedgerEntry' => array('id' => $e1['id'], 'amount' => -1*$e1['Reconciliation']['amount']));
}
}
$total += $amount;
}
// Cheat for now
$lease_id = $source['LedgerEntry'][0]['lease_id'];
$customer_id = $source['LedgerEntry'][0]['customer_id'];
// post new e6
$e6_ids = $A->postLedgerEntry
(null,
null,
array('debit_ledger_id' => $A->currentLedgerID($nsf_account_id),
'credit_ledger_id' => $A->currentLedgerID($ar_account_id),
'effective_date' => $stamp,
'amount' => $total,
'lease_id' => $lease_id,
'customer_id' => $customer_id,
'comment' => "NSF back to A/R from Monetary Source #{$id}",
),
array('debit' => $e6_debit_rec_ids,
'credit' => $e6_credit_rec_ids)
);
if ($e6_ids['error'])
return null;
pr(array('checkpoint' => 'Posted Ledger Entry e6',
compact('e6_ids', 'e6_debit_rec_ids', 'e6_credit_rec_ids')));
// post new e7
$e7_ids = $A->postLedgerEntry
(array('transaction_id' => $e6_ids['transaction_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 for Monetary Source #{$id}",
)
);
if ($e7_ids['error'])
return null;
pr(array('checkpoint' => 'Posted Ledger Entry e7',
compact('e7_ids')));
return true;
}
}
?>