New files from unstable branch
[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, $ref)
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, $ref);
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, $ref)
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, $ref);
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, $ref)
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, $ref);
80                         }  
81                 }
82         return $this->add_item($type, $type_no, $date_, $due_date, 
83                 $amount, $amount_allocated, $current_allocated, $ref);
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,
135                                 $myrow["reference"]); // this allocation
136                 }
137                 if ($trans_no == 0) return; // this is new payment
138
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 */
142
143                 if ($this->person_type)
144                         $trans_items = get_allocatable_to_supp_transactions($this->person_id, 
145                                 $trans_no, $type);
146                 else
147                         $trans_items = get_allocatable_to_cust_transactions($this->person_id, 
148                                 $trans_no, $type);
149
150                 while ($myrow = db_fetch($trans_items))
151                 {
152                         $this->add_or_update_item ($myrow["type"], $myrow["trans_no"],
153                                 sql2date($myrow["tran_date"]),
154                                 sql2date($myrow["due_date"]),
155                                 $myrow["Total"],
156                                 $myrow["alloc"] - $myrow["amt"], $myrow["amt"], $myrow["reference"]);
157                 }
158         }
159         //
160         //      Update allocations in database.
161         //
162         function write()
163         {
164                 begin_transaction();
165
166                 if ($this->person_type)
167                         clear_supp_alloctions($this->type, $this->trans_no, $this->date_);
168                 else
169                         clear_cust_alloctions($this->type, $this->trans_no, $this->date_);
170
171                 // now add the new allocations
172                 $total_allocated = 0;
173                 foreach ($this->allocs as $alloc_item)
174                 {
175                         if ($alloc_item->current_allocated > 0)
176                         {
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_);
181
182                                         update_supp_trans_allocation($alloc_item->type, 
183                                                 $alloc_item->type_no, $alloc_item->current_allocated);
184                                 } else {
185                                         add_cust_allocation($alloc_item->current_allocated,
186                                                 $this->type, $this->trans_no,
187                                         $alloc_item->type, $alloc_item->type_no, $this->date_);
188                         
189                                         update_debtor_trans_allocation($alloc_item->type, 
190                                                 $alloc_item->type_no, $alloc_item->current_allocated);
191                                 }
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);
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         var $ref;
231         
232         var $current_allocated;
233         
234         function allocation_item ($type, $type_no, $date_, $due_date, $amount, 
235                 $amount_allocated, $current_allocated, $ref)
236         {
237
238                 $this->type = $type;
239                 $this->type_no = $type_no;
240
241                 $this->ref = $ref;
242
243                 $this->date_ = $date_;
244                 $this->due_date = $due_date;
245                 
246                 $this->amount = $amount;
247                 $this->amount_allocated = $amount_allocated;
248                 $this->current_allocated = $current_allocated;
249         }
250 }
251
252 //--------------------------------------------------------------------------------
253
254 function show_allocatable($show_totals) {
255
256         global $systypes_array;
257         
258     $k = $counter = $total_allocated = 0;
259
260         if (count($_SESSION['alloc']->allocs)) 
261         {
262                 start_table(TABLESTYLE, "width=60%");
263                 $th = array(_("Transaction Type"), _("#"), _("Ref"), _("Date"), _("Due Date"), _("Amount"),
264                         _("Other Allocations"), _("This Allocation"), _("Left to Allocate"),'','');
265                 table_header($th);
266
267                 foreach ($_SESSION['alloc']->allocs as $alloc_item)
268             {
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);
277
278                 $_POST['amount' . $counter] = price_format($alloc_item->current_allocated);
279                 amount_cells(null, "amount" . $counter, price_format('amount' . $counter));
280
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));
288                         end_row();
289
290                 $total_allocated += input_num('amount' . $counter);
291                     $counter++;
292                 }
293                 if ($show_totals) {
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;
297
298                         if ($_SESSION['alloc']->type == ST_SUPPCREDIT
299                                 || $_SESSION['alloc']->type == ST_SUPPAYMENT
300                                 ||  $_SESSION['alloc']->type == ST_BANKPAYMENT)
301                                 $amount = -$amount;
302                         
303                         if ($amount - $total_allocated < 0)
304                 {
305                         $font1 = "<font color=red>";
306                         $font2 = "</font>";
307             }
308                 else
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'",
313                                  3);
314                 }
315                 end_table(1);
316         }
317         hidden('TotalNumberOfAllocs', $counter);
318 }
319 //--------------------------------------------------------------------------------
320
321 function check_allocations()
322 {
323         global $SysPrefs;
324
325         $total_allocated = 0;
326
327         for ($counter = 0; $counter < $_POST["TotalNumberOfAllocs"]; $counter++)
328         {
329                 if (!check_num('amount' . $counter, 0))
330                 {
331                         display_error(_("The entry for one or more amounts is invalid or negative."));
332                         set_focus('amount'.$counter);
333                         return false;
334                  }
335
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))
339                  {
340                         display_error(_("At least one transaction is overallocated."));
341                         set_focus('amount'.$counter);
342                         return false;
343                  }
344
345                  $_SESSION['alloc']->allocs[$counter]->current_allocated = input_num('amount' . $counter);
346
347                  $total_allocated += input_num('amount' . $counter);
348         }
349
350         $amount = $_SESSION['alloc']->amount;
351         
352
353         if (in_array($_SESSION['alloc']->type, array(ST_BANKPAYMENT, ST_SUPPCREDIT, ST_SUPPAYMENT)))
354                 $amount = -$amount;
355
356         if ($total_allocated - ($amount + input_num('discount'))  > $SysPrefs->allocation_settled_allowance())
357         {
358                 display_error(_("These allocations cannot be processed because the amount allocated is more than the total amount left to allocate."));
359                 return false;
360         }
361
362         return true;
363 }
364
365 ?>