2 /**********************************************************************
3 Copyright (C) FrontAccounting, LLC.
4 Released under the terms of the GNU General Public License, GPL,
5 as published by the Free Software Foundation, either version 3
6 of the License, or (at your option) any later version.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
11 ***********************************************************************/
13 Class for supplier/customer payment/credit allocations edition
16 //-----------------------------------------------------------------------------------
24 var $person_name = '';
25 var $person_type; // PT_SUPPLIER/PT_CUSTOMER
28 var $amount = 0; /*Total amount of the transaction in FX */
31 var $allocs; /*array of transactions allocated to */
33 function allocation($type, $trans_no, $person_id = null, $person_type_id=null)
35 $this->allocs = array();
37 $this->trans_no = $trans_no;
40 $this->set_person($person_id, $person_type_id);
42 $this->read($type, $trans_no, $person_id, $person_type_id); // read payment or credit
45 function set_person($person_id, $person_type)
47 $this->person_id = $person_id;
48 $this->person_type = $person_type;
49 $this->person_curr = $person_type == PT_SUPPLIER ?
50 get_supplier_currency($person_id) : get_customer_currency($person_id);
51 return $this->person_curr;
54 function add_item($type, $type_no, $date_, $due_date, $amount, $amount_allocated,
55 $current_allocated, $ref)
57 if (floatcmp($amount, 0))
59 $this->allocs[count($this->allocs)] = new allocation_item($type, $type_no,
60 $date_, $due_date, $amount, $amount_allocated, $current_allocated, $ref);
69 function update_item($index, $type, $type_no, $date_, $due_date,
70 $amount, $amount_allocated, $current_allocated, $ref)
72 if (floatcmp($amount, 0))
74 $this->allocs[$index] = new allocation_item($type, $type_no,
75 $date_, $due_date, $amount, $amount_allocated, $current_allocated, $ref);
84 function add_or_update_item($type, $type_no, $date_, $due_date,
85 $amount, $amount_allocated, $current_allocated, $ref)
87 for ($i = 0; $i < count($this->allocs); $i++)
89 $item = $this->allocs[$i];
90 if (($item->type == $type) && ($item->type_no == $type_no))
92 return $this->update_item($i, $type, $type_no, $date_, $due_date,
93 $amount, $amount_allocated, $current_allocated, $ref);
96 return $this->add_item($type, $type_no, $date_, $due_date,
97 $amount, $amount_allocated, $current_allocated, $ref);
101 // Read payment or credit current/available allocations to cart.
103 // FIXME - read all transactions below twice seems to be suboptimal
105 function read($type = null, $trans_no = 0, $person_id=null, $person_type_id=null)
107 if ($type !== null) { // otherwise re-read
109 $trans_no = $this->trans_no;
111 if (isset($person_type_id))
113 $this->person_type = $person_type_id;
114 $this->person_id = $person_id;
115 } else { // guess person_type_id
116 if (in_array($type, array(ST_BANKPAYMENT, ST_BANKDEPOSIT)))
118 $bank_trans = db_fetch(get_bank_trans($type, $trans_no));
119 $this->person_type = $bank_trans['person_type_id'];
121 $this->person_type = in_array($type, array(ST_SUPPCREDIT, ST_SUPPAYMENT)) ? PT_SUPPLIER : PT_CUSTOMER;
125 $trans = $this->person_type == PT_SUPPLIER ? get_supp_trans($trans_no, $type, $person_id)
126 : get_customer_trans($trans_no, $type, $person_id);
128 $this->person_id = $trans[$this->person_type == PT_SUPPLIER ? 'supplier_id':'debtor_no'];
129 $this->person_name = $trans[$this->person_type == PT_SUPPLIER ? "supplier_name":"DebtorName"];
130 $this->date_ = sql2date($trans["tran_date"]);
131 $this->person_curr = $trans['curr_code'];
132 $this->currency = isset($trans['bank_curr_code']) ? $trans['bank_curr_code'] : $trans['curr_code'];
133 $this->bank_amount = @$trans["bank_amount"];
134 $this->amount = $trans["Total"];
137 /* Now populate the array of possible (and previous actual) allocations
138 for this customer/supplier. First get the transactions that have
139 outstanding balances ie Total-alloc >0 */
141 $this->allocs = array();
142 if ($this->person_id)
144 if ($this->person_type==PT_SUPPLIER)
145 $trans_items = get_allocatable_to_supp_transactions($this->person_id);
147 $trans_items = get_allocatable_to_cust_transactions($this->person_id);
148 while ($myrow = db_fetch($trans_items))
150 $this->add_item($myrow["type"], $myrow["trans_no"],
151 sql2date($myrow["tran_date"]),
152 sql2date($myrow["due_date"]),
153 $myrow["Total"], // trans total
154 $myrow["alloc"], // trans total allocated
156 $myrow["reference"]); // this allocation
159 if ($this->trans_no == 0) return; // this is new payment
161 /* Now get trans that might have previously been allocated to by this trans
162 NB existing entries where still some of the trans outstanding entered from
163 above logic will be overwritten with the prev alloc detail below */
165 if ($this->person_type==PT_SUPPLIER)
166 $trans_items = get_allocatable_to_supp_transactions($this->person_id,
167 $this->trans_no, $this->type);
169 $trans_items = get_allocatable_to_cust_transactions($this->person_id,
170 $this->trans_no, $this->type);
172 while ($myrow = db_fetch($trans_items))
175 $this->add_or_update_item ($myrow["type"], $myrow["trans_no"],
176 sql2date($myrow["tran_date"]),
177 sql2date($myrow["due_date"]),
179 $myrow["alloc"] - $myrow["amt"], $myrow["amt"], $myrow["reference"]);
183 // Update allocations in database.
189 if ($this->person_type == PT_SUPPLIER)
190 clear_supp_alloctions($this->type, $this->trans_no, $this->date_);
192 clear_cust_alloctions($this->type, $this->trans_no);
194 // now add the new allocations
195 $total_allocated = 0;
196 $dec = user_price_dec();
197 foreach ($this->allocs as $alloc_item)
199 if ($alloc_item->current_allocated > 0)
201 $amount = round($alloc_item->current_allocated, $dec);
203 if ($this->person_type == PT_SUPPLIER) {
204 add_supp_allocation($amount,
205 $this->type, $this->trans_no,
206 $alloc_item->type, $alloc_item->type_no, $this->date_);
208 update_supp_trans_allocation($alloc_item->type, $alloc_item->type_no);
210 add_cust_allocation($amount,
211 $this->type, $this->trans_no,
212 $alloc_item->type, $alloc_item->type_no, $this->date_);
214 update_debtor_trans_allocation($alloc_item->type, $alloc_item->type_no);
216 // Exchange Variations Joe Hunt 2008-09-20 ////////////////////
217 if (!in_array($alloc_item->type, array(ST_SALESQUOTE, ST_SALESORDER, ST_PURCHORDER)))
218 exchange_variation($this->type, $this->trans_no,
219 $alloc_item->type, $alloc_item->type_no, $this->date_,
220 $amount, $this->person_type);
222 //////////////////////////////////////////////////////////////
223 $total_allocated += $alloc_item->current_allocated;
226 } /*end of the loop through the array of allocations made */
227 if ($this->person_type == PT_SUPPLIER)
228 update_supp_trans_allocation($this->type, $this->trans_no);
230 update_debtor_trans_allocation($this->type, $this->trans_no);
232 commit_transaction();
238 //-----------------------------------------------------------------------------------
240 class allocation_item
249 var $amount_allocated;
253 var $current_allocated;
255 function allocation_item ($type, $type_no, $date_, $due_date, $amount,
256 $amount_allocated, $current_allocated, $ref)
260 $this->type_no = $type_no;
264 $this->date_ = $date_;
265 $this->due_date = $due_date;
267 $this->amount = $amount;
268 $this->amount_allocated = $amount_allocated;
269 $this->current_allocated = $current_allocated;
273 //--------------------------------------------------------------------------------
275 function show_allocatable($show_totals) {
277 global $systypes_array;
279 $k = $counter = $total_allocated = 0;
281 $cart = $_SESSION['alloc'];
282 $supp_ref = in_array($cart->type, array(ST_SUPPCREDIT, ST_SUPPAYMENT, ST_BANKPAYMENT));
284 if (count($cart->allocs))
286 if ($cart->currency != $cart->person_curr)
287 display_heading(sprintf(_("Allocated amounts in %s:"), $cart->person_curr));
288 start_table(TABLESTYLE, "width=60%");
289 $th = array(_("Transaction Type"), _("#"), $supp_ref ? _("Supplier Ref"): _("Ref"), _("Date"), _("Due Date"), _("Amount"),
290 _("Other Allocations"), _("Left to Allocate"), _("This Allocation"),'','');
294 foreach ($cart->allocs as $id => $alloc_item)
296 if (floatcmp(abs($alloc_item->amount), $alloc_item->amount_allocated))
298 alt_table_row_color($k);
299 label_cell($systypes_array[$alloc_item->type]);
300 label_cell(get_trans_view_str($alloc_item->type, $alloc_item->type_no));
301 label_cell($alloc_item->ref);
302 label_cell($alloc_item->date_, "align=right");
303 label_cell($alloc_item->due_date, "align=right");
304 amount_cell(abs($alloc_item->amount));
305 amount_cell($alloc_item->amount_allocated);
307 $_POST['amount' . $id] = price_format($alloc_item->current_allocated);
309 $un_allocated = round((abs($alloc_item->amount) - $alloc_item->amount_allocated), 6);
310 amount_cell($un_allocated, false,'', 'maxval'.$id);
311 amount_cells(null, "amount" . $id);//, input_num('amount' . $id));
312 label_cell("<a href='#' name=Alloc$id onclick='allocate_all(this.name.substr(5));return true;'>"
313 . _("All") . "</a>");
314 label_cell("<a href='#' name=DeAll$id onclick='allocate_none(this.name.substr(5));return true;'>"
315 . _("None") . "</a>".hidden("un_allocated" . $id,
316 price_format($un_allocated), false));
319 $total_allocated += input_num('amount' . $id);
323 label_row(_("Total Allocated"), price_format($total_allocated),
324 "colspan=8 align=right", "align=right id='total_allocated'", 3);
326 $amount = $_SESSION['alloc']->amount;
328 if ($_SESSION['alloc']->type == ST_SUPPCREDIT
329 || $_SESSION['alloc']->type == ST_SUPPAYMENT
330 || $_SESSION['alloc']->type == ST_BANKPAYMENT)
333 $amount = abs($cart->amount);
335 if (floatcmp($amount, $total_allocated) < 0)
337 $font1 = "<font color=red>";
341 $font1 = $font2 = "";
342 $left_to_allocate = price_format($amount - $total_allocated);
343 label_row(_("Left to Allocate"), $font1 . $left_to_allocate . $font2,
344 "colspan=8 align=right", "nowrap align=right id='left_to_allocate'",
349 hidden('TotalNumberOfAllocs', count($cart->allocs));
351 //--------------------------------------------------------------------------------
353 function check_allocations()
357 $total_allocated = 0;
359 for ($counter = 0; $counter < get_post("TotalNumberOfAllocs"); $counter++)
361 if (!isset($_POST['amount'.$counter])) continue;
363 if (!check_num('amount' . $counter, 0))
365 display_error(_("The entry for one or more amounts is invalid or negative."));
366 set_focus('amount'.$counter);
370 /* Now check to see that the AllocAmt is no greater than the
371 amount left to be allocated against the transaction under review;
372 skip check if no allocation is set to avoid deadlock on mistakenly overallocated transactions*/
373 $allocated = input_num('amount' . $counter);
374 if ($allocated && ($allocated > input_num('un_allocated' . $counter)))
376 display_error(_("At least one transaction is overallocated."));
377 set_focus('amount'.$counter);
381 $_SESSION['alloc']->allocs[$counter]->current_allocated = input_num('amount' . $counter);
383 $total_allocated += input_num('amount' . $counter);
386 $amount = $_SESSION['alloc']->amount;
388 if (in_array($_SESSION['alloc']->type, array(ST_BANKPAYMENT, ST_SUPPCREDIT, ST_SUPPAYMENT)))
391 $amount = abs($_SESSION['alloc']->amount);
393 if ($total_allocated - ($amount + input_num('discount')) > $SysPrefs->allocation_settled_allowance())
395 display_error(_("These allocations cannot be processed because the amount allocated is more than the total amount left to allocate."));