377456b15e262e6b6718c91944da2add925eab9a
[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;       // true - supplier, otherwise customer
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         // FIXME - read all transactions below twice seems to be suboptimal
90         //
91         function read($type = null, $trans_no = 0) 
92         {
93                 if ($type == null) {    // re-read
94                         $type = $this->type;
95                         $trans_no = $this->trans_no;
96                 }
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;
100                 } else
101                         $this->person_type = $type == ST_SUPPCREDIT || $type == ST_SUPPAYMENT;
102                 $this->allocs = array();
103
104                 if ($trans_no) {
105                         $trans = $this->person_type ? get_supp_trans($trans_no, $type) 
106                                 : get_customer_trans($trans_no, $type);
107
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"]);
112                 } 
113                 else {
114                         $this->person_id = get_post($this->person_type ? 'supplier_id':'customer_id');
115                         $this->date_ = get_post($this->person_type ? 'DatePaid':'DateBanked', Today());
116                 }
117
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 */
121
122                 if ($this->person_type)
123                         $trans_items = get_allocatable_to_supp_transactions($this->person_id);
124                 else
125                         $trans_items = get_allocatable_to_cust_transactions($this->person_id);
126
127                 while ($myrow = db_fetch($trans_items))
128                 {
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
135                 }
136                 if ($trans_no == 0) return; // this is new payment
137
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 */
141
142                 if ($this->person_type)
143                         $trans_items = get_allocatable_to_supp_transactions($this->person_id, 
144                                 $trans_no, $type);
145                 else
146                         $trans_items = get_allocatable_to_cust_transactions($this->person_id, 
147                                 $trans_no, $type);
148
149                 while ($myrow = db_fetch($trans_items))
150                 {
151                         $this->add_or_update_item ($myrow["type"], $myrow["trans_no"],
152                                 sql2date($myrow["tran_date"]),
153                                 sql2date($myrow["due_date"]),
154                                 $myrow["Total"],
155                                 $myrow["alloc"] - $myrow["amt"], $myrow["amt"]);
156                 }
157         }
158         //
159         //      Update allocations in database.
160         //
161         function write()
162         {
163                 begin_transaction();
164
165                 if ($this->person_type)
166                         clear_supp_alloctions($this->type, $this->trans_no, $this->date_);
167                 else
168                         clear_cust_alloctions($this->type, $this->trans_no, $this->date_);
169
170                 // now add the new allocations
171                 $total_allocated = 0;
172                 foreach ($this->allocs as $alloc_item)
173                 {
174                         if ($alloc_item->current_allocated > 0)
175                         {
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_);
180
181                                         update_supp_trans_allocation($alloc_item->type, 
182                                                 $alloc_item->type_no, $alloc_item->current_allocated);
183                                 } else {
184                                         add_cust_allocation($alloc_item->current_allocated,
185                                                 $this->type, $this->trans_no,
186                                         $alloc_item->type, $alloc_item->type_no, $this->date_);
187                         
188                                         update_debtor_trans_allocation($alloc_item->type, 
189                                                 $alloc_item->type_no, $alloc_item->current_allocated);
190                                 }
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);
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 $systypes_array;
253         
254     $k = $counter = $total_allocated = 0;
255
256         if (count($_SESSION['alloc']->allocs)) 
257         {
258                 start_table(TABLESTYLE, "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, 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));
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) > input_num('un_allocated' . $counter))
334                  {
335                         display_error(_("At least one transaction is overallocated."));
336                         set_focus('amount'.$counter);
337                         return false;
338                  }
339
340                  $_SESSION['alloc']->allocs[$counter]->current_allocated = input_num('amount' . $counter);
341
342                  $total_allocated += input_num('amount' . $counter);
343         }
344
345         $amount = $_SESSION['alloc']->amount;
346         
347
348         if (in_array($_SESSION['alloc']->type, array(ST_BANKPAYMENT, ST_SUPPCREDIT, ST_SUPPAYMENT)))
349                 $amount = -$amount;
350
351         if ($total_allocated - ($amount + input_num('discount'))  > $SysPrefs->allocation_settled_allowance())
352         {
353                 display_error(_("These allocations cannot be processed because the amount allocated is more than the total amount left to allocate."));
354                 return false;
355         }
356
357         return true;
358 }
359
360 ?>