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"];
136 $this->date_ = Today();
138 /* Now populate the array of possible (and previous actual) allocations
139 for this customer/supplier. First get the transactions that have
140 outstanding balances ie Total-alloc >0 */
142 $this->allocs = array();
143 if ($this->person_id)
145 if ($this->person_type==PT_SUPPLIER)
146 $trans_items = get_allocatable_to_supp_transactions($this->person_id);
148 $trans_items = get_allocatable_to_cust_transactions($this->person_id);
149 while ($myrow = db_fetch($trans_items))
151 $this->add_item($myrow["type"], $myrow["trans_no"],
152 sql2date($myrow["tran_date"]),
153 sql2date($myrow["due_date"]),
154 $myrow["Total"], // trans total
155 $myrow["alloc"], // trans total allocated
157 $myrow["reference"]); // this allocation
160 if ($this->trans_no == 0) return; // this is new payment
162 /* Now get trans that might have previously been allocated to by this trans
163 NB existing entries where still some of the trans outstanding entered from
164 above logic will be overwritten with the prev alloc detail below */
166 if ($this->person_type==PT_SUPPLIER)
167 $trans_items = get_allocatable_to_supp_transactions($this->person_id,
168 $this->trans_no, $this->type);
170 $trans_items = get_allocatable_to_cust_transactions($this->person_id,
171 $this->trans_no, $this->type);
173 while ($myrow = db_fetch($trans_items))
176 $this->add_or_update_item ($myrow["type"], $myrow["trans_no"],
177 sql2date($myrow["tran_date"]),
178 sql2date($myrow["due_date"]),
180 $myrow["alloc"] - $myrow["amt"], $myrow["amt"], $myrow["reference"]);
184 // Update allocations in database.
190 if ($this->person_type == PT_SUPPLIER)
191 clear_supp_alloctions($this->type, $this->trans_no, $this->date_);
193 clear_cust_alloctions($this->type, $this->trans_no);
195 // now add the new allocations
196 $total_allocated = 0;
197 $dec = user_price_dec();
198 foreach ($this->allocs as $alloc_item)
200 if ($alloc_item->current_allocated > 0)
202 $amount = round($alloc_item->current_allocated, $dec);
204 if ($this->person_type == PT_SUPPLIER) {
205 add_supp_allocation($amount,
206 $this->type, $this->trans_no,
207 $alloc_item->type, $alloc_item->type_no, $this->date_);
209 update_supp_trans_allocation($alloc_item->type, $alloc_item->type_no);
211 add_cust_allocation($amount,
212 $this->type, $this->trans_no,
213 $alloc_item->type, $alloc_item->type_no, $this->date_);
215 update_debtor_trans_allocation($alloc_item->type, $alloc_item->type_no);
217 // Exchange Variations Joe Hunt 2008-09-20 ////////////////////
218 if (!in_array($alloc_item->type, array(ST_SALESQUOTE, ST_SALESORDER, ST_PURCHORDER)))
219 exchange_variation($this->type, $this->trans_no,
220 $alloc_item->type, $alloc_item->type_no, $this->date_,
221 $amount, $this->person_type);
223 //////////////////////////////////////////////////////////////
224 $total_allocated += $alloc_item->current_allocated;
227 } /*end of the loop through the array of allocations made */
228 if ($this->person_type == PT_SUPPLIER)
229 update_supp_trans_allocation($this->type, $this->trans_no);
231 update_debtor_trans_allocation($this->type, $this->trans_no);
233 commit_transaction();
239 //-----------------------------------------------------------------------------------
241 class allocation_item
250 var $amount_allocated;
254 var $current_allocated;
256 function allocation_item ($type, $type_no, $date_, $due_date, $amount,
257 $amount_allocated, $current_allocated, $ref)
261 $this->type_no = $type_no;
265 $this->date_ = $date_;
266 $this->due_date = $due_date;
268 $this->amount = $amount;
269 $this->amount_allocated = $amount_allocated;
270 $this->current_allocated = $current_allocated;
274 //--------------------------------------------------------------------------------
276 function show_allocatable($show_totals) {
278 global $systypes_array;
280 $k = $counter = $total_allocated = 0;
282 $cart = $_SESSION['alloc'];
283 $supp_ref = in_array($cart->type, array(ST_SUPPCREDIT, ST_SUPPAYMENT, ST_BANKPAYMENT));
285 if (count($cart->allocs))
287 if ($cart->currency != $cart->person_curr)
288 display_heading(sprintf(_("Allocated amounts in %s:"), $cart->person_curr));
289 start_table(TABLESTYLE, "width=60%");
290 $th = array(_("Transaction Type"), _("#"), $supp_ref ? _("Supplier Ref"): _("Ref"), _("Date"), _("Due Date"), _("Amount"),
291 _("Other Allocations"), _("Left to Allocate"), _("This Allocation"),'','');
295 foreach ($cart->allocs as $id => $alloc_item)
297 if (floatcmp(abs($alloc_item->amount), $alloc_item->amount_allocated))
299 alt_table_row_color($k);
300 label_cell($systypes_array[$alloc_item->type]);
301 label_cell(get_trans_view_str($alloc_item->type, $alloc_item->type_no));
302 label_cell($alloc_item->ref);
303 label_cell($alloc_item->date_, "align=right");
304 label_cell($alloc_item->due_date, "align=right");
305 amount_cell(abs($alloc_item->amount));
306 amount_cell($alloc_item->amount_allocated);
308 $_POST['amount' . $id] = price_format($alloc_item->current_allocated);
310 $un_allocated = round((abs($alloc_item->amount) - $alloc_item->amount_allocated), 6);
311 amount_cell($un_allocated, false,'', 'maxval'.$id);
312 amount_cells(null, "amount" . $id);//, input_num('amount' . $id));
313 label_cell("<a href='#' name=Alloc$id onclick='allocate_all(this.name.substr(5));return true;'>"
314 . _("All") . "</a>");
315 label_cell("<a href='#' name=DeAll$id onclick='allocate_none(this.name.substr(5));return true;'>"
316 . _("None") . "</a>".hidden("un_allocated" . $id,
317 price_format($un_allocated), false));
320 $total_allocated += input_num('amount' . $id);
324 label_row(_("Total Allocated"), price_format($total_allocated),
325 "colspan=8 align=right", "align=right id='total_allocated'", 3);
327 $amount = $_SESSION['alloc']->amount;
329 if ($_SESSION['alloc']->type == ST_SUPPCREDIT
330 || $_SESSION['alloc']->type == ST_SUPPAYMENT
331 || $_SESSION['alloc']->type == ST_BANKPAYMENT)
334 $amount = abs($cart->amount);
336 if (floatcmp($amount, $total_allocated) < 0)
338 $font1 = "<font color=red>";
342 $font1 = $font2 = "";
343 $left_to_allocate = price_format($amount - $total_allocated);
344 label_row(_("Left to Allocate"), $font1 . $left_to_allocate . $font2,
345 "colspan=8 align=right", "nowrap align=right id='left_to_allocate'",
350 hidden('TotalNumberOfAllocs', count($cart->allocs));
352 //--------------------------------------------------------------------------------
354 function check_allocations()
358 $total_allocated = 0;
360 for ($counter = 0; $counter < get_post("TotalNumberOfAllocs"); $counter++)
362 if (!isset($_POST['amount'.$counter])) continue;
364 if (!check_num('amount' . $counter, 0))
366 display_error(_("The entry for one or more amounts is invalid or negative."));
367 set_focus('amount'.$counter);
371 /* Now check to see that the AllocAmt is no greater than the
372 amount left to be allocated against the transaction under review;
373 skip check if no allocation is set to avoid deadlock on mistakenly overallocated transactions*/
374 $allocated = input_num('amount' . $counter);
375 if ($allocated && ($allocated > input_num('un_allocated' . $counter)))
377 display_error(_("At least one transaction is overallocated."));
378 set_focus('amount'.$counter);
382 $_SESSION['alloc']->allocs[$counter]->current_allocated = input_num('amount' . $counter);
384 $total_allocated += input_num('amount' . $counter);
387 $amount = $_SESSION['alloc']->amount;
389 if (in_array($_SESSION['alloc']->type, array(ST_BANKPAYMENT, ST_SUPPCREDIT, ST_SUPPAYMENT)))
392 $amount = abs($_SESSION['alloc']->amount);
394 if ($total_allocated - ($amount + input_num('discount')) > $SysPrefs->allocation_settled_allowance())
396 display_error(_("These allocations cannot be processed because the amount allocated is more than the total amount left to allocate."));