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 = isset($trans["bank_amount"]) ? $trans["bank_amount"] : $trans["Total"]; // not set for journal entry
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))
174 $this->add_or_update_item ($myrow["type"], $myrow["trans_no"],
175 sql2date($myrow["tran_date"]),
176 sql2date($myrow["due_date"]),
178 $myrow["alloc"] - $myrow["amt"], $myrow["amt"], $myrow["reference"]);
182 // Update allocations in database.
186 global $no_exchange_variations;
190 if ($this->person_type == PT_SUPPLIER)
191 clear_supp_alloctions($this->type, $this->trans_no, $this->person_id, $this->date_);
193 clear_cust_alloctions($this->type, $this->trans_no, $this->person_id, $this->date_);
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->person_id, $this->date_);
209 update_supp_trans_allocation($alloc_item->type, $alloc_item->type_no, $this->person_id);
211 add_cust_allocation($amount,
212 $this->type, $this->trans_no,
213 $alloc_item->type, $alloc_item->type_no, $this->person_id, $this->date_);
215 update_debtor_trans_allocation($alloc_item->type, $alloc_item->type_no, $this->person_id);
217 // Exchange Variations Joe Hunt 2008-09-20 ////////////////////
218 if ($alloc_item->type != ST_SALESORDER && !@$no_exchange_variations
219 && $alloc_item->type != ST_PURCHORDER && $alloc_item->type != ST_JOURNAL && $this->type != ST_JOURNAL)
220 exchange_variation($this->type, $this->trans_no,
221 $alloc_item->type, $alloc_item->type_no, $this->date_,
222 $amount, $this->person_type);
224 //////////////////////////////////////////////////////////////
225 $total_allocated += $alloc_item->current_allocated;
228 } /*end of the loop through the array of allocations made */
229 if ($this->person_type == PT_SUPPLIER)
230 update_supp_trans_allocation($this->type, $this->trans_no, $this->person_id);
232 update_debtor_trans_allocation($this->type, $this->trans_no, $this->person_id);
234 commit_transaction();
240 //-----------------------------------------------------------------------------------
242 class allocation_item
251 var $amount_allocated;
255 var $current_allocated;
257 function allocation_item ($type, $type_no, $date_, $due_date, $amount,
258 $amount_allocated, $current_allocated, $ref)
262 $this->type_no = $type_no;
266 $this->date_ = $date_;
267 $this->due_date = $due_date;
269 $this->amount = $amount;
270 $this->amount_allocated = $amount_allocated;
271 $this->current_allocated = $current_allocated;
275 //--------------------------------------------------------------------------------
277 function show_allocatable($show_totals) {
279 global $systypes_array;
281 $k = $total_allocated = 0;
283 $cart = $_SESSION['alloc'];
284 $supp_ref = in_array($cart->type, array(ST_SUPPCREDIT, ST_SUPPAYMENT, ST_BANKPAYMENT));
286 if (count($cart->allocs))
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 = abs($cart->amount);
329 if (floatcmp($amount, $total_allocated) < 0)
331 $font1 = "<font color=red>";
335 $font1 = $font2 = "";
336 $left_to_allocate = price_format($amount - $total_allocated);
337 label_row(_("Left to Allocate"), $font1 . $left_to_allocate . $font2,
338 "colspan=8 align=right", "nowrap align=right id='left_to_allocate'",
343 hidden('TotalNumberOfAllocs', count($cart->allocs));
345 //--------------------------------------------------------------------------------
347 function check_allocations()
351 $total_allocated = 0;
353 for ($counter = 0; $counter < get_post("TotalNumberOfAllocs"); $counter++)
355 if (!isset($_POST['amount'.$counter])) continue;
356 if (!check_num('amount' . $counter, 0))
358 display_error(_("The entry for one or more amounts is invalid or negative."));
359 set_focus('amount'.$counter);
363 /* Now check to see that the AllocAmt is no greater than the
364 amount left to be allocated against the transaction under review;
365 skip check if no allocation is set to avoid deadlock on mistakenly overallocated transactions*/
366 $allocated = input_num('amount' . $counter);
367 if ($allocated && ($allocated > input_num('un_allocated' . $counter)))
369 display_error(_("At least one transaction is overallocated."));
370 set_focus('amount'.$counter);
374 $_SESSION['alloc']->allocs[$counter]->current_allocated = input_num('amount' . $counter);
376 $total_allocated += input_num('amount' . $counter);
379 $amount = abs($_SESSION['alloc']->amount);
381 if ($total_allocated - ($amount + input_num('discount')) > $SysPrefs->allocation_settled_allowance())
383 display_error(_("These allocations cannot be processed because the amount allocated is more than the total amount left to allocate."));
390 //----------------------------------------------------------------------------------------
392 // Returns sales or purchase invoice allocations to be reallocated after invoice edition.
394 function get_inv_allocations($trans_no, $trans_type, $person_id)
397 if ($trans_type == ST_SUPPINVOICE || $trans_type == ST_SUPPCREDIT)
398 $result = get_allocatable_from_supp_transactions($person_id, $trans_no, $trans_type);
400 $result = get_allocatable_from_cust_transactions($person_id, $trans_no, $trans_type);
402 while($dat = db_fetch($result))
404 $allocs[] = array('type'=> $dat['type'], 'trans_no'=> $dat['trans_no'], 'amount'=>$dat['alloc']);