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,
41 $current_allocated, $ref)
45 $this->allocs[count($this->allocs)] = new allocation_item($type, $type_no,
46 $date_, $due_date, $amount, $amount_allocated, $current_allocated, $ref);
55 function update_item($index, $type, $type_no, $date_, $due_date,
56 $amount, $amount_allocated, $current_allocated, $ref)
60 $this->allocs[$index] = new allocation_item($type, $type_no,
61 $date_, $due_date, $amount, $amount_allocated, $current_allocated, $ref);
70 function add_or_update_item($type, $type_no, $date_, $due_date,
71 $amount, $amount_allocated, $current_allocated, $ref)
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, $ref);
82 return $this->add_item($type, $type_no, $date_, $due_date,
83 $amount, $amount_allocated, $current_allocated, $ref);
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
135 $myrow["reference"]); // this allocation
137 if ($trans_no == 0) return; // this is new payment
139 /* Now get trans that might have previously been allocated to by this trans
140 NB existing entries where still some of the trans outstanding entered from
141 above logic will be overwritten with the prev alloc detail below */
143 if ($this->person_type)
144 $trans_items = get_allocatable_to_supp_transactions($this->person_id,
147 $trans_items = get_allocatable_to_cust_transactions($this->person_id,
150 while ($myrow = db_fetch($trans_items))
152 $this->add_or_update_item ($myrow["type"], $myrow["trans_no"],
153 sql2date($myrow["tran_date"]),
154 sql2date($myrow["due_date"]),
156 $myrow["alloc"] - $myrow["amt"], $myrow["amt"], $myrow["reference"]);
160 // Update allocations in database.
166 if ($this->person_type)
167 clear_supp_alloctions($this->type, $this->trans_no, $this->date_);
169 clear_cust_alloctions($this->type, $this->trans_no, $this->date_);
171 // now add the new allocations
172 $total_allocated = 0;
173 foreach ($this->allocs as $alloc_item)
175 if ($alloc_item->current_allocated > 0)
177 if ($this->person_type) {
178 add_supp_allocation($alloc_item->current_allocated,
179 $this->type, $this->trans_no,
180 $alloc_item->type, $alloc_item->type_no, $this->date_);
182 update_supp_trans_allocation($alloc_item->type,
183 $alloc_item->type_no, $alloc_item->current_allocated);
185 add_cust_allocation($alloc_item->current_allocated,
186 $this->type, $this->trans_no,
187 $alloc_item->type, $alloc_item->type_no, $this->date_);
189 update_debtor_trans_allocation($alloc_item->type,
190 $alloc_item->type_no, $alloc_item->current_allocated);
192 // Exchange Variations Joe Hunt 2008-09-20 ////////////////////
193 exchange_variation($this->type, $this->trans_no,
194 $alloc_item->type, $alloc_item->type_no, $this->date_,
195 $alloc_item->current_allocated,
196 $this->person_type ? PT_SUPPLIER : PT_CUSTOMER);
199 //////////////////////////////////////////////////////////////
200 $total_allocated += $alloc_item->current_allocated;
203 } /*end of the loop through the array of allocations made */
204 if ($this->person_type)
205 update_supp_trans_allocation($this->type, $this->trans_no,
208 update_debtor_trans_allocation($this->type, $this->trans_no,
211 commit_transaction();
217 //-----------------------------------------------------------------------------------
219 class allocation_item
228 var $amount_allocated;
232 var $current_allocated;
234 function allocation_item ($type, $type_no, $date_, $due_date, $amount,
235 $amount_allocated, $current_allocated, $ref)
239 $this->type_no = $type_no;
243 $this->date_ = $date_;
244 $this->due_date = $due_date;
246 $this->amount = $amount;
247 $this->amount_allocated = $amount_allocated;
248 $this->current_allocated = $current_allocated;
252 //--------------------------------------------------------------------------------
254 function show_allocatable($show_totals) {
256 global $systypes_array;
258 $k = $counter = $total_allocated = 0;
260 if (count($_SESSION['alloc']->allocs))
262 start_table(TABLESTYLE, "width=60%");
263 $th = array(_("Transaction Type"), _("#"), _("Ref"), _("Date"), _("Due Date"), _("Amount"),
264 _("Other Allocations"), _("This Allocation"), _("Left to Allocate"),'','');
267 foreach ($_SESSION['alloc']->allocs as $alloc_item)
269 alt_table_row_color($k);
270 label_cell($systypes_array[$alloc_item->type]);
271 label_cell(get_trans_view_str($alloc_item->type, $alloc_item->type_no));
272 label_cell($alloc_item->ref);
273 label_cell($alloc_item->date_, "align=right");
274 label_cell($alloc_item->due_date, "align=right");
275 amount_cell($alloc_item->amount);
276 amount_cell($alloc_item->amount_allocated);
278 $_POST['amount' . $counter] = price_format($alloc_item->current_allocated);
279 amount_cells(null, "amount" . $counter, price_format('amount' . $counter));
281 $un_allocated = round($alloc_item->amount - $alloc_item->amount_allocated, 6);
282 amount_cell($un_allocated, false,'', 'maxval'.$counter);
283 label_cell("<a href='#' name=Alloc$counter onclick='allocate_all(this.name.substr(5));return true;'>"
284 . _("All") . "</a>");
285 label_cell("<a href='#' name=DeAll$counter onclick='allocate_none(this.name.substr(5));return true;'>"
286 . _("None") . "</a>".hidden("un_allocated" . $counter,
287 price_format($un_allocated), false));
290 $total_allocated += input_num('amount' . $counter);
294 label_row(_("Total Allocated"), price_format($total_allocated),
295 "colspan=6 align=right", "align=right id='total_allocated'", 3);
296 $amount = $_SESSION['alloc']->amount;
298 if ($_SESSION['alloc']->type == ST_SUPPCREDIT
299 || $_SESSION['alloc']->type == ST_SUPPAYMENT
300 || $_SESSION['alloc']->type == ST_BANKPAYMENT)
303 if ($amount - $total_allocated < 0)
305 $font1 = "<font color=red>";
309 $font1 = $font2 = "";
310 $left_to_allocate = price_format($amount - $total_allocated);
311 label_row(_("Left to Allocate"), $font1 . $left_to_allocate . $font2,
312 "colspan=6 align=right", "nowrap align=right id='left_to_allocate'",
317 hidden('TotalNumberOfAllocs', $counter);
319 //--------------------------------------------------------------------------------
321 function check_allocations()
325 $total_allocated = 0;
327 for ($counter = 0; $counter < $_POST["TotalNumberOfAllocs"]; $counter++)
329 if (!check_num('amount' . $counter, 0))
331 display_error(_("The entry for one or more amounts is invalid or negative."));
332 set_focus('amount'.$counter);
336 /*Now check to see that the AllocAmt is no greater than the
337 amount left to be allocated against the transaction under review */
338 if (input_num('amount' . $counter) > input_num('un_allocated' . $counter))
340 display_error(_("At least one transaction is overallocated."));
341 set_focus('amount'.$counter);
345 $_SESSION['alloc']->allocs[$counter]->current_allocated = input_num('amount' . $counter);
347 $total_allocated += input_num('amount' . $counter);
350 $amount = $_SESSION['alloc']->amount;
353 if (in_array($_SESSION['alloc']->type, array(ST_BANKPAYMENT, ST_SUPPCREDIT, ST_SUPPAYMENT)))
356 if ($total_allocated - ($amount + input_num('discount')) > $SysPrefs->allocation_settled_allowance())
358 display_error(_("These allocations cannot be processed because the amount allocated is more than the total amount left to allocate."));