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))
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, $this->date_);
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 exchange_variation($this->type, $this->trans_no,
218 $alloc_item->type, $alloc_item->type_no, $this->date_,
219 $amount, $this->person_type);
221 //////////////////////////////////////////////////////////////
222 $total_allocated += $alloc_item->current_allocated;
225 } /*end of the loop through the array of allocations made */
226 if ($this->person_type == PT_SUPPLIER)
227 update_supp_trans_allocation($this->type, $this->trans_no);
229 update_debtor_trans_allocation($this->type, $this->trans_no);
231 commit_transaction();
237 //-----------------------------------------------------------------------------------
239 class allocation_item
248 var $amount_allocated;
252 var $current_allocated;
254 function allocation_item ($type, $type_no, $date_, $due_date, $amount,
255 $amount_allocated, $current_allocated, $ref)
259 $this->type_no = $type_no;
263 $this->date_ = $date_;
264 $this->due_date = $due_date;
266 $this->amount = $amount;
267 $this->amount_allocated = $amount_allocated;
268 $this->current_allocated = $current_allocated;
272 //--------------------------------------------------------------------------------
274 function show_allocatable($show_totals) {
276 global $systypes_array;
278 $k = $counter = $total_allocated = 0;
280 $cart = $_SESSION['alloc'];
281 $supp_ref = in_array($cart->type, array(ST_SUPPCREDIT, ST_SUPPAYMENT, ST_BANKPAYMENT));
283 if (count($cart->allocs))
285 if ($cart->currency != $cart->person_curr)
286 display_heading(sprintf(_("Allocated amounts in %s:"), $cart->person_curr));
287 start_table(TABLESTYLE, "width='60%'");
288 $th = array(_("Transaction Type"), _("#"), $supp_ref ? _("Supplier Ref"): _("Ref"), _("Date"), _("Due Date"), _("Amount"),
289 _("Other Allocations"), _("Left to Allocate"), _("This Allocation"),'','');
293 foreach ($cart->allocs as $id => $alloc_item)
295 if (floatcmp(abs($alloc_item->amount), $alloc_item->amount_allocated))
297 alt_table_row_color($k);
298 label_cell($systypes_array[$alloc_item->type]);
299 label_cell(get_trans_view_str($alloc_item->type, $alloc_item->type_no));
300 label_cell($alloc_item->ref);
301 label_cell($alloc_item->date_, "align=right");
302 label_cell($alloc_item->due_date, "align=right");
303 amount_cell(abs($alloc_item->amount));
304 amount_cell($alloc_item->amount_allocated);
306 $_POST['amount' . $id] = price_format($alloc_item->current_allocated);
308 $un_allocated = round((abs($alloc_item->amount) - $alloc_item->amount_allocated), 6);
309 amount_cell($un_allocated, false,'', 'maxval'.$id);
310 amount_cells(null, "amount" . $id);//, input_num('amount' . $id));
311 label_cell("<a href='#' name=Alloc$id onclick='allocate_all(this.name.substr(5));return true;'>"
312 . _("All") . "</a>");
313 label_cell("<a href='#' name=DeAll$id onclick='allocate_none(this.name.substr(5));return true;'>"
314 . _("None") . "</a>".hidden("un_allocated" . $id,
315 price_format($un_allocated), false));
318 $total_allocated += input_num('amount' . $id);
322 label_row(_("Total Allocated"), price_format($total_allocated),
323 "colspan=8 align=right", "align=right id='total_allocated'", 3);
325 $amount = $_SESSION['alloc']->amount;
327 if ($_SESSION['alloc']->type == ST_SUPPCREDIT
328 || $_SESSION['alloc']->type == ST_SUPPAYMENT
329 || $_SESSION['alloc']->type == ST_BANKPAYMENT)
332 $amount = abs($cart->amount);
334 if (floatcmp($amount, $total_allocated) < 0)
336 $font1 = "<font color=red>";
340 $font1 = $font2 = "";
341 $left_to_allocate = price_format($amount - $total_allocated);
342 label_row(_("Left to Allocate"), $font1 . $left_to_allocate . $font2,
343 "colspan=8 align=right", "nowrap align=right id='left_to_allocate'",
348 hidden('TotalNumberOfAllocs', count($cart->allocs));
350 //--------------------------------------------------------------------------------
352 function check_allocations()
356 $total_allocated = 0;
358 for ($counter = 0; $counter < get_post("TotalNumberOfAllocs"); $counter++)
360 if (!isset($_POST['amount'.$counter])) continue;
361 if (!check_num('amount' . $counter, 0))
363 display_error(_("The entry for one or more amounts is invalid or negative."));
364 set_focus('amount'.$counter);
368 /* Now check to see that the AllocAmt is no greater than the
369 amount left to be allocated against the transaction under review;
370 skip check if no allocation is set to avoid deadlock on mistakenly overallocated transactions*/
371 $allocated = input_num('amount' . $counter);
372 if ($allocated && ($allocated > input_num('un_allocated' . $counter)))
374 display_error(_("At least one transaction is overallocated."));
375 set_focus('amount'.$counter);
379 $_SESSION['alloc']->allocs[$counter]->current_allocated = input_num('amount' . $counter);
381 $total_allocated += input_num('amount' . $counter);
384 $amount = $_SESSION['alloc']->amount;
386 if (in_array($_SESSION['alloc']->type, array(ST_BANKPAYMENT, ST_SUPPCREDIT, ST_SUPPAYMENT)))
389 $amount = abs($_SESSION['alloc']->amount);
391 if ($total_allocated - ($amount + input_num('discount')) > $SysPrefs->allocation_settled_allowance())
393 display_error(_("These allocations cannot be processed because the amount allocated is more than the total amount left to allocate."));