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; // true - supplier, otherwise customer
27 var $amount = 0; /*Total amount of the transaction in FX */
29 var $allocs; /*array of transactions allocated to */
31 function allocation($type, $trans_no)
33 $this->allocs = array();
35 $this->trans_no = $trans_no;
37 $this->read(); // read payment or credit
40 function add_item($type, $type_no, $date_, $due_date, $amount, $amount_allocated,
45 $this->allocs[count($this->allocs)] = new allocation_item($type, $type_no,
46 $date_, $due_date, $amount, $amount_allocated, $current_allocated);
55 function update_item($index, $type, $type_no, $date_, $due_date,
56 $amount, $amount_allocated, $current_allocated)
60 $this->allocs[$index] = new allocation_item($type, $type_no,
61 $date_, $due_date, $amount, $amount_allocated, $current_allocated);
70 function add_or_update_item($type, $type_no, $date_, $due_date,
71 $amount, $amount_allocated, $current_allocated)
73 for ($i = 0; $i < count($this->allocs); $i++)
75 $item = $this->allocs[$i];
76 if (($item->type == $type) && ($item->type_no == $type_no))
78 return $this->update_item($i, $type, $type_no, $date_, $due_date,
79 $amount, $amount_allocated, $current_allocated);
82 return $this->add_item($type, $type_no, $date_, $due_date,
83 $amount, $amount_allocated, $current_allocated);
87 // Read payment or credit current/available allocations to cart.
89 // FIXME - read all transactions below twice seems to be suboptimal
91 function read($type = null, $trans_no = 0)
93 if ($type == null) { // re-read
95 $trans_no = $this->trans_no;
97 if ($type == ST_BANKPAYMENT || $type == ST_BANKDEPOSIT) {
98 $bank_trans = db_fetch(get_bank_trans($type, $trans_no));
99 $this->person_type = $bank_trans['person_type_id'] == PT_SUPPLIER;
101 $this->person_type = $type == ST_SUPPCREDIT || $type == ST_SUPPAYMENT;
102 $this->allocs = array();
105 $trans = $this->person_type ? get_supp_trans($trans_no, $type)
106 : get_customer_trans($trans_no, $type);
108 $this->person_id = $trans[$this->person_type ? 'supplier_id':'debtor_no'];
109 $this->person_name = $trans[$this->person_type ? "supplier_name":"DebtorName"];
110 $this->amount = $trans["Total"];
111 $this->date_ = sql2date($trans["tran_date"]);
114 $this->person_id = get_post($this->person_type ? 'supplier_id':'customer_id');
115 $this->date_ = get_post($this->person_type ? 'DatePaid':'DateBanked', Today());
118 /* Now populate the array of possible (and previous actual) allocations
119 for this customer/supplier. First get the transactions that have
120 outstanding balances ie Total-alloc >0 */
122 if ($this->person_type)
123 $trans_items = get_allocatable_to_supp_transactions($this->person_id);
125 $trans_items = get_allocatable_to_cust_transactions($this->person_id);
127 while ($myrow = db_fetch($trans_items))
129 $this->add_item($myrow["type"], $myrow["trans_no"],
130 sql2date($myrow["tran_date"]),
131 sql2date($myrow["due_date"]),
132 $myrow["Total"], // trans total
133 $myrow["alloc"], // trans total allocated
134 0); // this allocation
136 if ($trans_no == 0) return; // this is new payment
138 /* Now get trans that might have previously been allocated to by this trans
139 NB existing entries where still some of the trans outstanding entered from
140 above logic will be overwritten with the prev alloc detail below */
142 if ($this->person_type)
143 $trans_items = get_allocatable_to_supp_transactions($this->person_id,
146 $trans_items = get_allocatable_to_cust_transactions($this->person_id,
149 while ($myrow = db_fetch($trans_items))
151 $this->add_or_update_item ($myrow["type"], $myrow["trans_no"],
152 sql2date($myrow["tran_date"]),
153 sql2date($myrow["due_date"]),
155 $myrow["alloc"] - $myrow["amt"], $myrow["amt"]);
159 // Update allocations in database.
165 if ($this->person_type)
166 clear_supp_alloctions($this->type, $this->trans_no, $this->date_);
168 clear_cust_alloctions($this->type, $this->trans_no, $this->date_);
170 // now add the new allocations
171 $total_allocated = 0;
172 foreach ($this->allocs as $alloc_item)
174 if ($alloc_item->current_allocated > 0)
176 if ($this->person_type) {
177 add_supp_allocation($alloc_item->current_allocated,
178 $this->type, $this->trans_no,
179 $alloc_item->type, $alloc_item->type_no, $this->date_);
181 update_supp_trans_allocation($alloc_item->type,
182 $alloc_item->type_no, $alloc_item->current_allocated);
184 add_cust_allocation($alloc_item->current_allocated,
185 $this->type, $this->trans_no,
186 $alloc_item->type, $alloc_item->type_no, $this->date_);
188 update_debtor_trans_allocation($alloc_item->type,
189 $alloc_item->type_no, $alloc_item->current_allocated);
191 // Exchange Variations Joe Hunt 2008-09-20 ////////////////////
192 exchange_variation($this->type, $this->trans_no,
193 $alloc_item->type, $alloc_item->type_no, $this->date_,
194 $alloc_item->current_allocated,
195 $this->person_type ? PT_SUPPLIER : PT_CUSTOMER);
198 //////////////////////////////////////////////////////////////
199 $total_allocated += $alloc_item->current_allocated;
202 } /*end of the loop through the array of allocations made */
203 if ($this->person_type)
204 update_supp_trans_allocation($this->type, $this->trans_no,
207 update_debtor_trans_allocation($this->type, $this->trans_no,
210 commit_transaction();
216 //-----------------------------------------------------------------------------------
218 class allocation_item
227 var $amount_allocated;
230 var $current_allocated;
232 function allocation_item ($type, $type_no, $date_, $due_date, $amount,
233 $amount_allocated, $current_allocated)
237 $this->type_no = $type_no;
239 $this->date_ = $date_;
240 $this->due_date = $due_date;
242 $this->amount = $amount;
243 $this->amount_allocated = $amount_allocated;
244 $this->current_allocated = $current_allocated;
248 //--------------------------------------------------------------------------------
250 function show_allocatable($show_totals) {
252 global $systypes_array;
254 $k = $counter = $total_allocated = 0;
256 if (count($_SESSION['alloc']->allocs))
258 start_table(TABLESTYLE, "width=60%");
259 $th = array(_("Transaction Type"), _("#"), _("Date"), _("Due Date"), _("Amount"),
260 _("Other Allocations"), _("This Allocation"), _("Left to Allocate"),'','');
263 foreach ($_SESSION['alloc']->allocs as $alloc_item)
265 alt_table_row_color($k);
266 label_cell($systypes_array[$alloc_item->type]);
267 label_cell(get_trans_view_str($alloc_item->type, $alloc_item->type_no));
268 label_cell($alloc_item->date_, "align=right");
269 label_cell($alloc_item->due_date, "align=right");
270 amount_cell($alloc_item->amount);
271 amount_cell($alloc_item->amount_allocated);
273 $_POST['amount' . $counter] = price_format($alloc_item->current_allocated);
274 amount_cells(null, "amount" . $counter, price_format('amount' . $counter));
276 $un_allocated = round($alloc_item->amount - $alloc_item->amount_allocated, 6);
277 amount_cell($un_allocated, false,'', 'maxval'.$counter);
278 label_cell("<a href='#' name=Alloc$counter onclick='allocate_all(this.name.substr(5));return true;'>"
279 . _("All") . "</a>");
280 label_cell("<a href='#' name=DeAll$counter onclick='allocate_none(this.name.substr(5));return true;'>"
281 . _("None") . "</a>".hidden("un_allocated" . $counter,
282 price_format($un_allocated), false));
285 $total_allocated += input_num('amount' . $counter);
289 label_row(_("Total Allocated"), price_format($total_allocated),
290 "colspan=6 align=right", "align=right id='total_allocated'", 3);
291 $amount = $_SESSION['alloc']->amount;
293 if ($_SESSION['alloc']->type == ST_SUPPCREDIT
294 || $_SESSION['alloc']->type == ST_SUPPAYMENT
295 || $_SESSION['alloc']->type == ST_BANKPAYMENT)
298 if ($amount - $total_allocated < 0)
300 $font1 = "<font color=red>";
304 $font1 = $font2 = "";
305 $left_to_allocate = price_format($amount - $total_allocated);
306 label_row(_("Left to Allocate"), $font1 . $left_to_allocate . $font2,
307 "colspan=6 align=right", "nowrap align=right id='left_to_allocate'",
312 hidden('TotalNumberOfAllocs', $counter);
314 //--------------------------------------------------------------------------------
316 function check_allocations()
320 $total_allocated = 0;
322 for ($counter = 0; $counter < $_POST["TotalNumberOfAllocs"]; $counter++)
324 if (!check_num('amount' . $counter, 0))
326 display_error(_("The entry for one or more amounts is invalid or negative."));
327 set_focus('amount'.$counter);
331 /*Now check to see that the AllocAmt is no greater than the
332 amount left to be allocated against the transaction under review */
333 if (input_num('amount' . $counter) > input_num('un_allocated' . $counter))
335 display_error(_("At least one transaction is overallocated."));
336 set_focus('amount'.$counter);
340 $_SESSION['alloc']->allocs[$counter]->current_allocated = input_num('amount' . $counter);
342 $total_allocated += input_num('amount' . $counter);
345 $amount = $_SESSION['alloc']->amount;
348 if (in_array($_SESSION['alloc']->type, array(ST_BANKPAYMENT, ST_SUPPCREDIT, ST_SUPPAYMENT)))
351 if ($total_allocated - ($amount + input_num('discount')) > $SysPrefs->allocation_settled_allowance())
353 display_error(_("These allocations cannot be processed because the amount allocated is more than the total amount left to allocate."));