diff --git a/controllers/customers_controller.php b/controllers/customers_controller.php index d0a1238..d3e8ef7 100644 --- a/controllers/customers_controller.php +++ b/controllers/customers_controller.php @@ -180,15 +180,59 @@ class CustomersController extends AppController { /* $customer = $this->data; */ /* } */ if (isset($id)) { - $customer = $this->Customer->details($id); - unset($customer['deposits']['Entries']); + $this->Customer->recursive = -1; + $customer = $this->Customer->read(null, $id); + $customer = $customer['Customer']; + $unreconciled = $this->Customer->findUnreconciledLedgerEntries($id); + $charges = $unreconciled['debit']; } else { $customer = null; + $charges = array('balance' => 0, 'entry' => array()); } $title = 'Payment Entry'; - $this->set(compact('customer', 'title')); + $this->set(compact('customer', 'charges', 'title')); + } + + + /************************************************************************** + ************************************************************************** + ************************************************************************** + * action: unreconciledEntries + * - returns the list of unreconciled entries + */ + + function unreconciled($id) { + + //$this->layout = 'ajax'; + $this->layout = null; + $this->autoLayout = false; + $this->autoRender = false; + Configure::write('debug', '0'); + header("Content-type: text/xml;charset=utf-8"); + + App::import('Helper', 'Xml'); + $xml = new XmlHelper(); + + // Find the unreconciled entries, then manipulate the structure + // slightly to accomodate the format necessary for XML Helper. + $unreconciled = $this->Customer->findUnreconciledLedgerEntries($id); + $unreconciled = array('entries' => + array_intersect_key($unreconciled['debit'], + array('entry'=>1, 'balance'=>1))); + + // XML Helper will dump an empty tag if the array is empty + if (!count($unreconciled['entries']['entry'])) + unset($unreconciled['entries']['entry']); + + pr($unreconciled); + //$reconciled = $cust->reconcileNewLedgerEntry($cust_id, 'credit', $amount); + + $opts = array(); + //$opts['format'] = 'tags'; + echo $xml->header(); + echo $xml->serialize($unreconciled, $opts); } } diff --git a/models/account.php b/models/account.php index 8945109..e007bc8 100644 --- a/models/account.php +++ b/models/account.php @@ -236,7 +236,7 @@ class Account extends AppModel { ? array($fundamental_type) : array('debit', 'credit')) AS $fund) { $ucfund = ucfirst($fund); - $unreconciled[$fund]['entries'] = $this->find + $unreconciled[$fund]['entry'] = $this->find ('all', array ('link' => array ('Ledger' => array @@ -261,7 +261,7 @@ class Account extends AppModel { 'fields' => array(), )); $balance = 0; - foreach ($unreconciled[$fund]['entries'] AS &$entry) { + foreach ($unreconciled[$fund]['entry'] AS &$entry) { $entry = array_merge(array_diff_key($entry["LedgerEntry"], array(0=>true)), $entry[0]); $balance += $entry['balance']; @@ -289,7 +289,7 @@ class Account extends AppModel { function reconcileNewLedgerEntry($id, $fundamental_type, $amount) { $ofund = $this->fundamentalOpposite($fundamental_type); - $unreconciled = array($ofund => array('entries'=>array(), 'balance'=>0)); + $unreconciled = array($ofund => array('entry'=>array(), 'balance'=>0)); $applied = 0; // if there is no money in the entry, it can reconcile nothing @@ -297,7 +297,7 @@ class Account extends AppModel { if ($amount > 0) { $unreconciled = $this->findUnreconciledLedgerEntries($id, $ofund); - foreach ($unreconciled[$ofund]['entries'] AS $i => &$entry) { + foreach ($unreconciled[$ofund]['entry'] AS $i => &$entry) { // Determine if amount is sufficient to cover the entry if ($amount > $entry['balance']) $apply = $entry['balance']; diff --git a/models/customer.php b/models/customer.php index e6475d5..4064fe0 100644 --- a/models/customer.php +++ b/models/customer.php @@ -122,7 +122,7 @@ class Customer extends AppModel { $left = &$unreconciled[$type]; $right = &$unrec[$type]; - $left['entries'] = array_merge($left['entries'], $right['entries']); + $left['entry'] = array_merge($left['entry'], $right['entry']); $left['balance'] += $right['balance']; } } @@ -159,7 +159,7 @@ class Customer extends AppModel { $left = &$reconciled[$type]; $right = &$rec[$type]; - $left['entries'] = array_merge($left['entries'], $right['entries']); + $left['entry'] = array_merge($left['entry'], $right['entry']); $left['balance'] += $right['balance']; $left['applied'] += $right['applied']; $left['unapplied'] = $right['unapplied']; diff --git a/views/customers/payment.ctp b/views/customers/payment.ctp index 9023240..2ec59e5 100644 --- a/views/customers/payment.ctp +++ b/views/customers/payment.ctp @@ -54,36 +54,14 @@ $grid_setup = array(); -if (isset($customer['Customer']['id'])) +if (isset($customer['id'])) $grid_setup['hiddengrid'] = true; $grid_setup['onSelectRow'] = array ('--special' => - 'function(ids) { if (ids != null)' . - ' {' . - // Set the customer id that will be returned with the form - ' $("#customer-id").val(ids);' . - // Get the customer name from the grid - ' $("#payment_customer").html($("#"+$(this).attr("id"))' . - ' .getCell(ids, "Customer-name"));' . - // Replace that with just the text portion of the hyperlink - ' $("#payment_customer").html("Receipt for "+ $("#payment_customer a").html());' . - ' } }' + 'function(ids) { if (ids != null) { onRowSelect("#"+$(this).attr("id"), ids); } }' ); -/* $grid_setup['loadComplete'] = array */ -/* ('--special' => */ -/* 'function() { ' . */ -/* //' $("#"+$(this).attr("id")).setSelection($("#customer-id").val());' . */ -/* ' $(\'#customers-list-jqGrid\').setSelection($(\'#customer-id\').val());' . */ -/* ' $("#"+$(this).attr("id")).setCaption("Hello");' . */ -/* ' alert("Loaded");' . */ -/* ' }' */ -/* ); */ - - -//pr($customer); -//echo ('Get grid code
'); // Customer // Outstanding balance @@ -95,7 +73,7 @@ $grid_setup['onSelectRow'] = array ?> - ' . "\n"; echo $this->element('customers', - array('caption' => 'Select Customer', + array('grid_div_id' => 'customers-list', + 'caption' => ('Select Customer'), 'limit' => 7, 'grid_setup' => $grid_setup, )); -echo ('

' . - (isset($customer['Customer']['id']) - ? 'Receipt for ' . $customer['Customer']['name'] - : 'Please select customer') . - '

' . "\n"); +echo $this->element('ledger_entries', + array('grid_div_id' => 'charge-entries', + 'caption' => 'Outstanding Charges', +/* (isset($customer['name']) */ +/* ? " for {$customer['name']}: ".FormatHelper::currency($charges['balance']) */ +/* : '')), */ + 'limit' => 8, + 'ledger_id' => 6, + 'account_type' => 'credit', + 'ledger_entries' => $charges['entry'], + )); + +echo ('

' . + '' . + 'Enter new receipt for ' . + '' . (isset($customer['name']) ? $customer['name'] : "") . '' . + '' . + '' . + 'Please select customer' . + '' . + '

' . "\n"); echo $form->create(null, array('id' => 'payment-form', 'url' => array('controller' => 'transactions', @@ -373,7 +427,7 @@ echo $form->create(null, array('id' => 'payment-form', ***************************************************/ ?> - +
Payments @@ -393,12 +447,10 @@ echo $form->end('Post Payment'); //echo '' . "\n"; // End of the dialog DIV ?> -Clear Debug Output Create Payment */ ?> -

Request

Response

Output

@@ -412,6 +464,13 @@ echo $form->end('Post Payment'); $("#datepicker").datepicker() .datepicker('setDate', '+0'); + + $("#customer-id").val(); + updateChargesCaption("", + ); + + + /* $("#dialog").dialog({ */ /* bgiframe: true, */ /* autoOpen: false, */ @@ -439,8 +498,10 @@ echo $form->end('Post Payment'); /* }); */ }); + + - +Clear Debug Output diff --git a/views/elements/customers.ctp b/views/elements/customers.ctp index 4cfa0e3..f7a31fd 100644 --- a/views/elements/customers.ctp +++ b/views/elements/customers.ctp @@ -15,7 +15,7 @@ $jqGrid_options = array('jqGridColumns' => $cols, 'controller' => 'customers'); // User requested options have priority -$jqGrid_options += compact('caption', 'grid_setup', 'limit'); +$jqGrid_options += compact('grid_div_id', 'grid_id', 'caption', 'grid_setup', 'limit'); if (isset($customers)) { $jqGrid_options += array('custom_ids' => diff --git a/views/elements/ledger_entries.ctp b/views/elements/ledger_entries.ctp index 2a54d43..09cbbea 100644 --- a/views/elements/ledger_entries.ctp +++ b/views/elements/ledger_entries.ctp @@ -18,11 +18,11 @@ $custom_post_data = array('ledger_id' => $ledger_id, 'account_type' => $account_type); $jqGrid_options = array('jqGridColumns' => $cols, - 'grid_id' => isset($grid_id) ? $grid_id : null, - 'caption' => isset($caption) ? $caption : null, 'controller' => 'ledger_entries', ); +$jqGrid_options += compact('grid_div_id', 'grid_id', 'caption', 'grid_setup', 'limit'); + if (isset($ledger_entries)) { $jqGrid_options += array('custom_ids' => array_map(create_function('$data', diff --git a/webroot/js/pmgr.js b/webroot/js/pmgr.js index c264ac1..d7e931a 100644 --- a/webroot/js/pmgr.js +++ b/webroot/js/pmgr.js @@ -134,3 +134,105 @@ function fmtCurrency(amount) { } +// REVISIT : 20090617 +// I would rather use XML to pass from JS to PHP, but at the +// moment things were working just fine with serialize, and +// I'm not keen on redesigning it at the moment. So, here +// is a serialize implementation I found on the web. + +function serialize( mixed_value ) { + // http://kevin.vanzonneveld.net + // + original by: Arpad Ray (mailto:arpad@php.net) + // + improved by: Dino + // + bugfixed by: Andrej Pavlovic + // + bugfixed by: Garagoth + // + input by: DtTvB (http://dt.in.th/2008-09-16.string-length-in-bytes.html) + // + bugfixed by: Russell Walker + // % note: We feel the main purpose of this function should be to ease the transport of data between php & js + // % note: Aiming for PHP-compatibility, we have to translate objects to arrays + // * example 1: serialize(['Kevin', 'van', 'Zonneveld']); + // * returns 1: 'a:3:{i:0;s:5:"Kevin";i:1;s:3:"van";i:2;s:9:"Zonneveld";}' + // * example 2: serialize({firstName: 'Kevin', midName: 'van', surName: 'Zonneveld'}); + // * returns 2: 'a:3:{s:9:"firstName";s:5:"Kevin";s:7:"midName";s:3:"van";s:7:"surName";s:9:"Zonneveld";}' + + var _getType = function( inp ) { + var type = typeof inp, match; + var key; + if (type == 'object' && !inp) { + return 'null'; + } + if (type == "object") { + if (!inp.constructor) { + return 'object'; + } + var cons = inp.constructor.toString(); + match = cons.match(/(\w+)\(/); + if (match) { + cons = match[1].toLowerCase(); + } + var types = ["boolean", "number", "string", "array"]; + for (key in types) { + if (cons == types[key]) { + type = types[key]; + break; + } + } + } + return type; + }; + var type = _getType(mixed_value); + var val, ktype = ''; + + switch (type) { + case "function": + val = ""; + break; + case "undefined": + val = "N"; + break; + case "boolean": + val = "b:" + (mixed_value ? "1" : "0"); + break; + case "number": + val = (Math.round(mixed_value) == mixed_value ? "i" : "d") + ":" + mixed_value; + break; + case "string": + val = "s:" + encodeURIComponent(mixed_value).replace(/%../g, 'x').length + ":\"" + mixed_value + "\""; + break; + case "array": + case "object": + val = "a"; + /* + if (type == "object") { + var objname = mixed_value.constructor.toString().match(/(\w+)\(\)/); + if (objname == undefined) { + return; + } + objname[1] = serialize(objname[1]); + val = "O" + objname[1].substring(1, objname[1].length - 1); + } + */ + var count = 0; + var vals = ""; + var okey; + var key; + for (key in mixed_value) { + ktype = _getType(mixed_value[key]); + if (ktype == "function") { + continue; + } + + okey = (key.match(/^[0-9]+$/) ? parseInt(key, 10) : key); + vals += serialize(okey) + + serialize(mixed_value[key]); + count++; + } + val += ":" + count + ":{" + vals + "}"; + break; + } + if (type != "object" && type != "array") { + val += ";"; + } + return val; + +}