Fixed bug [0000179] (data error in supplier allocations)
[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                                         $this->person_type ? PT_SUPPLIER : PT_CUSTOMER);
196                                 
197
198                                 //////////////////////////////////////////////////////////////
199                                 $total_allocated += $alloc_item->current_allocated;
200                         }
201
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, 
205                                 $total_allocated);
206                 else
207                         update_debtor_trans_allocation($this->type,     $this->trans_no, 
208                                 $total_allocated);
209         
210                 commit_transaction();
211
212         }
213
214
215
216 //-----------------------------------------------------------------------------------
217
218 class allocation_item 
219 {
220
221         var $type;
222         var $type_no;
223         
224         var $date_;
225         var $due_date;
226         
227         var $amount_allocated;
228         var $amount;
229         
230         var $current_allocated;
231         
232         function allocation_item ($type, $type_no, $date_, $due_date, $amount, 
233                 $amount_allocated, $current_allocated)
234         {
235
236                 $this->type = $type;
237                 $this->type_no = $type_no;
238                 
239                 $this->date_ = $date_;
240                 $this->due_date = $due_date;
241                 
242                 $this->amount = $amount;
243                 $this->amount_allocated = $amount_allocated;
244                 $this->current_allocated = $current_allocated;
245         }
246 }
247
248 //--------------------------------------------------------------------------------
249
250 function show_allocatable($show_totals) {
251
252         global $table_style, $systypes_array;
253         
254     $k = $counter = $total_allocated = 0;
255
256         if (count($_SESSION['alloc']->allocs)) 
257         {
258                 start_table("$table_style width=60%");
259                 $th = array(_("Transaction Type"), _("#"), _("Date"), _("Due Date"), _("Amount"),
260                         _("Other Allocations"), _("This Allocation"), _("Left to Allocate"),'','');
261                 table_header($th);
262
263                 foreach ($_SESSION['alloc']->allocs as $alloc_item)
264             {
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);
272
273                 $_POST['amount' . $counter] = price_format($alloc_item->current_allocated);
274                 amount_cells(null, "amount" . $counter, price_format('amount' . $counter));
275
276                 $un_allocated = round($alloc_item->amount - $alloc_item->amount_allocated, 6);
277                 amount_cell($un_allocated);
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));
283                         end_row();
284
285                 $total_allocated += input_num('amount' . $counter);
286                     $counter++;
287                 }
288                 if ($show_totals) {
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;
292
293                         if ($_SESSION['alloc']->type == ST_SUPPCREDIT
294                                 || $_SESSION['alloc']->type == ST_SUPPAYMENT
295                                 ||  $_SESSION['alloc']->type == ST_BANKPAYMENT)
296                                 $amount = -$amount;
297                         
298                         if ($amount - $total_allocated < 0)
299                 {
300                         $font1 = "<font color=red>";
301                         $font2 = "</font>";
302             }
303                 else
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'",
308                                  3);
309                 }
310                 end_table(1);
311         }
312         hidden('TotalNumberOfAllocs', $counter);
313 }
314 //--------------------------------------------------------------------------------
315
316 function check_allocations()
317 {
318         global $SysPrefs;
319
320         $total_allocated = 0;
321
322         for ($counter = 0; $counter < $_POST["TotalNumberOfAllocs"]; $counter++)
323         {
324                 if (!check_num('amount' . $counter, 0))
325                 {
326                         display_error(_("The entry for one or more amounts is invalid or negative."));
327                         set_focus('amount'.$counter);
328                         return false;
329                  }
330
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) > get_post('un_allocated' . $counter))
334                  {
335                      //$_POST['amount' . $counter] = $_POST['un_allocated' . $counter];
336                  }
337
338                  $_SESSION['alloc']->allocs[$counter]->current_allocated = input_num('amount' . $counter);
339
340                  $total_allocated += input_num('amount' . $counter);
341         }
342
343         $amount = $_SESSION['alloc']->amount;
344         if ($_SESSION['alloc']->type == 21 || $_SESSION['alloc']->type == 22) 
345                 $amount = -$amount;
346
347         if ($total_allocated - ($amount + input_num('discount'))  > $SysPrefs->allocation_settled_allowance())
348         {
349                 display_error(_("These allocations cannot be processed because the amount allocated is more than the total amount left to allocate."));
350                 return false;
351         }
352
353         return true;
354 }
355
356 ?>