Fixed bug [0000178] - database error when allocation bank payment in supplier allocat...
[fa-stable.git] / includes / ui / allocation_cart.inc
1 <?php
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 ***********************************************************************/
12 /*
13         Class for supplier/customer payment/credit allocations edition
14         and related helpers.
15 */
16 //-----------------------------------------------------------------------------------
17
18 class allocation 
19 {
20
21         var $trans_no; 
22         var $type;
23         var $person_id = '';
24         var $person_name = '';
25         var $person_type;
26         var $date_;
27         var $amount = 0; /*Total amount of the transaction in FX */
28         
29         var $allocs; /*array of transactions allocated to */    
30
31         function allocation($type, $trans_no)
32         {
33                 $this->allocs = array();
34                 
35                 $this->trans_no = $trans_no;
36                 $this->type = $type;
37                 $this->read(); // read payment or credit
38         }
39
40         function add_item($type, $type_no, $date_, $due_date, $amount, $amount_allocated, 
41                 $current_allocated)
42         {
43                 if ($amount > 0)
44                 {
45                         $this->allocs[count($this->allocs)] = new allocation_item($type, $type_no, 
46                                 $date_, $due_date, $amount, $amount_allocated, $current_allocated);
47                         return true;
48                 } 
49                 else 
50                 {
51                         return false;
52                 }
53         }
54         
55         function update_item($index, $type, $type_no, $date_, $due_date, 
56                 $amount, $amount_allocated, $current_allocated)
57         {
58                 if ($amount > 0)
59                 {
60                         $this->allocs[$index] = new allocation_item($type, $type_no, 
61                                 $date_, $due_date, $amount, $amount_allocated, $current_allocated);
62                         return true;
63                 } 
64                 else 
65                 {
66                         return false;
67                 }
68         }       
69         
70         function add_or_update_item($type, $type_no, $date_, $due_date, 
71                 $amount, $amount_allocated, $current_allocated)
72         {
73                 for ($i = 0; $i < count($this->allocs); $i++) 
74                 {
75                         $item = $this->allocs[$i];
76                         if (($item->type == $type) && ($item->type_no == $type_no)) 
77                         {
78                                 return $this->update_item($i, $type, $type_no, $date_, $due_date, 
79                                         $amount, $amount_allocated, $current_allocated);
80                         }  
81                 }
82         return $this->add_item($type, $type_no, $date_, $due_date, 
83                 $amount, $amount_allocated, $current_allocated);
84         }                                               
85
86         //
87         //      Read payment or credit current/available allocations to cart.
88         //
89         function read($type = null, $trans_no = 0) 
90         {
91                 if ($type == null) {    // re-read
92                         $type = $this->type;
93                         $trans_no = $this->trans_no;
94                 }
95                 if ($type == ST_BANKPAYMENT || $type == ST_BANKDEPOSIT) {
96                         $bank_trans = db_fetch(get_bank_trans($type, $trans_no));
97                         $this->person_type = $bank_trans['person_type_id'] == PT_SUPPLIER;
98                 } else
99                         $this->person_type = $type == ST_SUPPCREDIT || $type == ST_SUPPAYMENT;
100                 $this->allocs = array();
101
102                 if ($trans_no) {
103                         $trans = $this->person_type ? get_supp_trans($trans_no, $type) 
104                                 : get_customer_trans($trans_no, $type);
105
106                         $this->person_id = $trans[$this->person_type ? 'supplier_id':'debtor_no'];
107                         $this->person_name = $trans[$this->person_type ? "supplier_name":"DebtorName"];
108                         $this->amount = $trans["Total"];
109                         $this->date_ = sql2date($trans["tran_date"]);
110                 } 
111                 else {
112                         $this->person_id = get_post($this->person_type ? 'supplier_id':'customer_id');
113                         $this->date_ = get_post($this->person_type ? 'DatePaid':'DateBanked', Today());
114                 }
115
116         /* Now populate the array of possible (and previous actual) allocations 
117                 for this customer/supplier. First get the transactions that have 
118                 outstanding balances ie Total-alloc >0 */
119
120                 if ($this->person_type)
121                         $trans_items = get_allocatable_to_supp_transactions($this->person_id);
122                 else
123                         $trans_items = get_allocatable_to_cust_transactions($this->person_id);
124
125                 while ($myrow = db_fetch($trans_items))
126                 {
127                         $this->add_item($myrow["type"], $myrow["trans_no"],
128                                 sql2date($myrow["tran_date"]),
129                                 sql2date($myrow["due_date"]),
130                                 $myrow["Total"], // trans total
131                                 $myrow["alloc"], // trans total allocated
132                                 0); // this allocation
133                 }
134
135                 if ($trans_no == 0) return; // this is new payment
136
137         /* Now get trans that might have previously been allocated to by this trans
138         NB existing entries where still some of the trans outstanding entered from
139         above logic will be overwritten with the prev alloc detail below */
140
141                 if ($this->person_type)
142                         $trans_items = get_allocatable_to_supp_transactions($this->person_id, 
143                                 $trans_no, $type);
144                 else
145                         $trans_items = get_allocatable_to_cust_transactions($this->person_id, 
146                                 $trans_no, $type);
147         
148                 while ($myrow = db_fetch($trans_items))
149                 {
150                         $this->add_or_update_item ($myrow["type"], $myrow["trans_no"],
151                                 sql2date($myrow["tran_date"]),
152                                 sql2date($myrow["due_date"]),
153                                 $myrow["Total"],
154                                 $myrow["alloc"] - $myrow["amt"], $myrow["amt"]);
155                 }
156         }
157         //
158         //      Update allocations in database.
159         //
160         function write()
161         {
162                 begin_transaction();
163
164                 if ($this->person_type)
165                         clear_supp_alloctions($this->type, $this->trans_no, $this->date_);
166                 else
167                         clear_cust_alloctions($this->type, $this->trans_no, $this->date_);
168
169                 // now add the new allocations
170                 $total_allocated = 0;
171                 foreach ($this->allocs as $alloc_item)
172                 {
173                         if ($alloc_item->current_allocated > 0)
174                         {
175                                 if ($this->person_type) {
176                                         add_supp_allocation($alloc_item->current_allocated,
177                                                 $this->type, $this->trans_no,
178                                         $alloc_item->type, $alloc_item->type_no, $this->date_);
179
180                                         update_supp_trans_allocation($alloc_item->type, 
181                                                 $alloc_item->type_no, $alloc_item->current_allocated);
182                                 } else {
183                                         add_cust_allocation($alloc_item->current_allocated,
184                                                 $this->type, $this->trans_no,
185                                         $alloc_item->type, $alloc_item->type_no, $this->date_);
186                         
187                                         update_debtor_trans_allocation($alloc_item->type, 
188                                                 $alloc_item->type_no, $alloc_item->current_allocated);
189                                 }
190                                 // Exchange Variations Joe Hunt 2008-09-20 ////////////////////
191
192                                 exchange_variation($this->type, $this->trans_no,
193                                         $alloc_item->type, $alloc_item->type_no, $this->date_,
194                                         $alloc_item->current_allocated,
195                                         $sup ? PT_SUPPLIER 
196                                                 : PT_CUSTOMER);
197                                 
198
199                                 //////////////////////////////////////////////////////////////
200                                 $total_allocated += $alloc_item->current_allocated;
201                         }
202
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, 
206                                 $total_allocated);
207                 else
208                         update_debtor_trans_allocation($this->type,     $this->trans_no, 
209                                 $total_allocated);
210         
211                 commit_transaction();
212
213         }
214
215
216
217 //-----------------------------------------------------------------------------------
218
219 class allocation_item 
220 {
221
222         var $type;
223         var $type_no;
224         
225         var $date_;
226         var $due_date;
227         
228         var $amount_allocated;
229         var $amount;
230         
231         var $current_allocated;
232         
233         function allocation_item ($type, $type_no, $date_, $due_date, $amount, 
234                 $amount_allocated, $current_allocated)
235         {
236
237                 $this->type = $type;
238                 $this->type_no = $type_no;
239                 
240                 $this->date_ = $date_;
241                 $this->due_date = $due_date;
242                 
243                 $this->amount = $amount;
244                 $this->amount_allocated = $amount_allocated;
245                 $this->current_allocated = $current_allocated;
246         }
247 }
248
249 //--------------------------------------------------------------------------------
250
251 function show_allocatable($show_totals) {
252
253         global $table_style, $systypes_array;
254         
255     $k = $counter = $total_allocated = 0;
256
257         if (count($_SESSION['alloc']->allocs)) 
258         {
259                 start_table("$table_style width=60%");
260                 $th = array(_("Transaction Type"), _("#"), _("Date"), _("Due Date"), _("Amount"),
261                         _("Other Allocations"), _("This Allocation"), _("Left to Allocate"),'','');
262                 table_header($th);
263
264                 foreach ($_SESSION['alloc']->allocs as $alloc_item)
265             {
266                         alt_table_row_color($k);
267                 label_cell($systypes_array[$alloc_item->type]);
268                         label_cell(get_trans_view_str($alloc_item->type, $alloc_item->type_no));
269                 label_cell($alloc_item->date_, "align=right");
270                 label_cell($alloc_item->due_date, "align=right");
271                 amount_cell($alloc_item->amount);
272                         amount_cell($alloc_item->amount_allocated);
273
274                 $_POST['amount' . $counter] = price_format($alloc_item->current_allocated);
275                 amount_cells(null, "amount" . $counter, price_format('amount' . $counter));
276
277                 $un_allocated = round($alloc_item->amount - $alloc_item->amount_allocated, 6);
278                 amount_cell($un_allocated);
279                         label_cell("<a href='#' name=Alloc$counter onclick='allocate_all(this.name.substr(5));return true;'>"
280                                  . _("All") . "</a>");
281                         label_cell("<a href='#' name=DeAll$counter onclick='allocate_none(this.name.substr(5));return true;'>"
282                                  . _("None") . "</a>".hidden("un_allocated" . $counter, 
283                                  price_format($un_allocated), false));
284                         end_row();
285
286                 $total_allocated += input_num('amount' . $counter);
287                     $counter++;
288                 }
289                 if ($show_totals) {
290                 label_row(_("Total Allocated"), price_format($total_allocated),
291                         "colspan=6 align=right", "align=right id='total_allocated'", 3);
292                         $amount = $_SESSION['alloc']->amount;
293
294                         if ($_SESSION['alloc']->type == ST_SUPPCREDIT
295                                 || $_SESSION['alloc']->type == ST_SUPPAYMENT
296                                 ||  $_SESSION['alloc']->type == ST_BANKPAYMENT)
297                                 $amount = -$amount;
298                         
299                         if ($amount - $total_allocated < 0)
300                 {
301                         $font1 = "<font color=red>";
302                         $font2 = "</font>";
303             }
304                 else
305                         $font1 = $font2 = "";
306                         $left_to_allocate = price_format($amount - $total_allocated);
307                 label_row(_("Left to Allocate"), $font1 . $left_to_allocate . $font2, 
308                                 "colspan=6 align=right", "nowrap align=right id='left_to_allocate'",
309                                  3);
310                 }
311                 end_table(1);
312         }
313         hidden('TotalNumberOfAllocs', $counter);
314 }
315 //--------------------------------------------------------------------------------
316
317 function check_allocations()
318 {
319         global $SysPrefs;
320
321         $total_allocated = 0;
322
323         for ($counter = 0; $counter < $_POST["TotalNumberOfAllocs"]; $counter++)
324         {
325                 if (!check_num('amount' . $counter, 0))
326                 {
327                         display_error(_("The entry for one or more amounts is invalid or negative."));
328                         set_focus('amount'.$counter);
329                         return false;
330                  }
331
332                   /*Now check to see that the AllocAmt is no greater than the
333                  amount left to be allocated against the transaction under review */
334                  if (input_num('amount' . $counter) > get_post('un_allocated' . $counter))
335                  {
336                      //$_POST['amount' . $counter] = $_POST['un_allocated' . $counter];
337                  }
338
339                  $_SESSION['alloc']->allocs[$counter]->current_allocated = input_num('amount' . $counter);
340
341                  $total_allocated += input_num('amount' . $counter);
342         }
343
344         $amount = $_SESSION['alloc']->amount;
345         if ($_SESSION['alloc']->type == 21 || $_SESSION['alloc']->type == 22) 
346                 $amount = -$amount;
347
348         if ($total_allocated - ($amount + input_num('discount'))  > $SysPrefs->allocation_settled_allowance())
349         {
350                 display_error(_("These allocations cannot be processed because the amount allocated is more than the total amount left to allocate."));
351                 return false;
352         }
353
354         return true;
355 }
356
357 ?>