ddb55681e038a515dbe36a0353b840c2da6bc678
[fa-stable.git] / purchasing / includes / supp_trans_class.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 /* Definition of the Supplier Transactions class to hold all the information for an accounts payable invoice or credit note
13 */
14
15 include_once($path_to_root . "/taxes/tax_calc.inc");
16
17 class supp_trans 
18 {
19         //db interface
20         var $trans_no;
21         var $trans_type;        // invoice or credit
22         var $supplier_id;
23         var $reference;
24         var $supp_reference;
25         var $tran_date;
26         var $due_date;
27         var $ov_amount;
28         var $ov_discount;
29         var $ov_gst;
30         var $ex_rate;
31
32         var $tax_included;
33
34         var $grn_items; /*array of objects of class grn_item using the id as the pointer */
35         var $gl_codes; /*array of objects of class gl_codes using a counter as the pointer */
36         var $Comments;
37         //---
38
39         var $supplier_name;
40         var $terms;
41         
42         var $tax_description;
43         var $tax_group_id;
44
45         var $src_docs = array();                // source invoice for this credit note (if any)
46
47         var $credit = 0;
48         var $currency;
49         var $tax_overrides = array();           // array of taxes manually inserted during sales invoice entry
50
51         var $dimension,
52                 $dimension2;
53
54         function __construct($trans_type, $trans_no=0)
55         {
56                 $this->trans_type = $trans_type;
57                 /*Constructor function initialises a new Supplier Transaction object */
58                 $this->read($trans_type, $trans_no);
59         }
60
61         function read($trans_type, $trans_no)
62         {
63                 $this->trans_type = $trans_type;
64                 $this->trans_no = $trans_no;
65                 $this->grn_items = array();
66                 $this->gl_codes = array();
67                 if ($trans_no) {
68                         read_supp_invoice($trans_no, $trans_type, $this);
69
70                         if ($trans_type == ST_SUPPCREDIT)
71                                 $this->src_docs = find_src_invoices($trans_no);
72
73                         read_supplier_details_to_trans($this, $this->supplier_id);
74                 }
75         }
76
77         function add_grn_to_trans($grn_item_id, $po_detail_item, $item_code, $item_description, 
78                 $qty_recd, $prev_quantity_inv, $this_quantity_inv, $order_price, $chg_price, 
79                 $std_cost_unit=null, $gl_code='')
80         {
81                 $line = new grn_item($grn_item_id, $po_detail_item, 
82                         $item_code, $item_description, $qty_recd, $prev_quantity_inv, $this_quantity_inv, 
83                         $order_price, $chg_price, $std_cost_unit, $gl_code, $this->tax_included);
84
85                 $line->cart = $this;
86                 $this->grn_items[$grn_item_id] = $line;
87                 $this->src_docs = find_src_invoices($this);
88
89                 unset($this->tax_overrides); // cancel tax overrides after cart change
90                 return 1;
91         }
92
93         function add_gl_codes_to_trans($gl_code, $gl_act_name, $gl_dim, $gl_dim2, $amount, $memo_)
94         {
95                 $this->gl_codes[] = new gl_codes($gl_code, $gl_act_name, $gl_dim, $gl_dim2, $amount, $memo_);
96                 unset($this->tax_overrides); // cancel tax overrides after cart change
97                 return 1;
98         }
99
100         function remove_grn_from_trans($grn_item_id)
101         {
102                 unset($this->tax_overrides); // cancel tax overrides after cart change
103             unset($this->grn_items[$grn_item_id]);
104         }
105         function remove_gl_codes_from_trans($gl_code_counter)
106         {
107                 unset($this->tax_overrides); // cancel tax overrides after cart change
108                 unset($this->gl_codes[$gl_code_counter]);
109         }
110
111         function is_valid_trans_to_post()
112         {
113                 return (count($this->grn_items) > 0 || count($this->gl_codes) > 0 || 
114                         ($this->ov_amount != 0) || ($this->ov_discount > 0));
115         }
116
117         function clear_items()
118         {
119                 unset($this->grn_items);
120                 unset($this->gl_codes);
121                 $this->ov_amount = $this->ov_discount = $this->supplier_id = 0;
122
123                 $this->grn_items = array();
124                 $this->gl_codes = array();
125         }
126
127     function get_taxes($gl_codes=true)
128     {
129         $items = array();
130         $prices = array();
131
132         foreach ($this->grn_items as $ln_itm) 
133         {
134                 $items[] = $ln_itm->item_code;
135                 $prices[] = round( $ln_itm->this_quantity_inv * $ln_itm->chg_price, user_price_dec());
136         }
137
138         $taxes = get_tax_for_items($this->trans_type, $items, $prices, 0, $this->tax_group_id, 
139                 $this->tax_included);
140
141                 if (isset($this->tax_overrides))
142                         foreach($this->tax_overrides as $id => $value) // add values entered manually
143                         {
144                                 $taxes[$id]['Override'] = $value;
145                         }
146
147                 // Taxes included in gl_codes table have exact value, but count to overrides as well.
148                 // Therefore when we want to know taxes only for items (gl_codes==false),
149                 // we have to subtract gl_taxes from override values.
150                 foreach ($this->gl_codes as $gl_code)
151                 {
152                         $index = is_tax_account($gl_code->gl_code);
153                         if ($index !== false)
154                         {
155                                 if ($gl_codes)
156                                         $taxes[$index]['Value'] += $gl_code->amount;
157                                 elseif (isset($this->tax_overrides))
158                                         $taxes[$index]['Override'] -= $gl_code->amount;
159                         }
160                 }
161         return $taxes;
162     }
163         //
164         //      Returns total invoice amount without taxes.
165         //
166     function get_total_taxfree()
167     {
168         $total = 0;
169
170                 foreach ($this->grn_items as $ln_itm)
171                 $total += round(($ln_itm->this_quantity_inv * $ln_itm->taxfree_charge_price()),
172                          user_price_dec());
173
174                 foreach ($this->gl_codes as $gl_line)
175                 {
176                         if (!is_tax_account($gl_line->gl_code))
177                                 $total += $gl_line->amount;
178                 }
179                 return $total;
180     }
181
182         //
183         //      Returns transaction total 
184         //
185         function get_items_total()
186         {
187                 $total = 0;
188
189                 foreach ($this->grn_items as $ln_itm)
190                         $total += round($ln_itm->this_quantity_inv * $ln_itm->chg_price, user_price_dec());
191
192                 foreach ($this->gl_codes as $gl_line)
193                 {
194                         if (!is_tax_account($gl_line->gl_code) || $this->tax_included)
195                                 $total += $gl_line->amount;
196                 }
197                 return $total;
198         }
199
200         /*
201                 Split line value to cost and taxes.
202                 Stores calculated amounts in $line->gl_amounts array.
203         */
204         function split_line_values()
205         {
206                 // split nominal line values
207                 foreach($this->grn_items as $line)
208                         $line->split_item_value();
209
210                 // Exact tax values are currently entered as tax totals, so we need to move the differences back on line level.
211                 // currently first item with given tax type will be fixed with the calculated difference
212                 // FIXME: change UI moving tax edit to line level in line edit mode, then this workaround will be obsolete.
213                 foreach($this->get_taxes() as $tax_id => $tax)
214                 {
215                         if ($tax['Value'] != 0 && isset($tax['Override']) && ($tax['Value'] != $tax['Override']))
216                         {
217                                 foreach($this->grn_items as $id => $line)
218                                         if ($line->gl_amounts[0]['tax_type_id'] == $tax_id) // assumed single tax rate on item, so always gl_amounts[0] is valid
219                                         {
220                                                 $diff = $tax['Override'] - $tax['Value'];
221                                                 $this->grn_items[$id]->gl_amounts[0]['Value'] += $diff;
222                                                 if ($line->vat_category != VC_NONDEDUCT)
223                                                         $this->grn_items[$id]->gl_amounts[0]['Deductible'] += $diff;
224                                                 else
225                                                         $this->grn_items[$id]->gl_amounts['Cost'] += $diff;
226                                                  // when supplier uses net prices the price is exact, so don't fix net, still record exact VAT.
227                                                 if ($this->tax_included) {
228                                                         $this->grn_items[$id]->gl_amounts['Net'] -= $diff;
229                                                         $this->grn_items[$id]->gl_amounts['Cost'] -= $diff;
230                                                 }
231                                                 break;
232                                         }
233                         }
234                 }
235         }
236 } /* end of class defintion */
237
238 class grn_item 
239 {
240
241 /* Contains relavent information from the purch_order_details as well to provide in cached form,
242 all the info to do the necessary entries without looking up ie additional queries of the database again */
243
244         var $id;
245
246         var $gl_code;
247
248         var $po_detail_item;
249         var $item_code;
250         var $item_description;
251         var $this_quantity_inv;
252         var $chg_price;
253
254         var $qty_recd;
255         var $prev_quantity_inv;
256         var $order_price;
257         var $std_cost_unit;
258         var $tax_included;
259         var $gl_amounts;        // splited line value (after call to split_line_value method
260         var $vat_category;
261
262         var $cart; // line context
263
264         function __construct($id, $po_detail_item, $item_code, $item_description, $qty_recd, 
265                 $prev_quantity_inv, $this_quantity_inv, $order_price, $chg_price,
266                 $std_cost_unit, $gl_code, $tax_included)
267         {
268
269                 $this->id = $id;
270                 $this->po_detail_item = $po_detail_item;
271                 $this->item_code = $item_code;
272                 $this->item_description = $item_description;
273                 $this->qty_recd = $qty_recd;
274                 $this->prev_quantity_inv = $prev_quantity_inv;
275                 $this->this_quantity_inv = $this_quantity_inv;
276                 $this->order_price = $order_price;              // price on order
277                 $this->chg_price = $chg_price;
278                 $this->std_cost_unit = $std_cost_unit;  // provisional cost for clearing
279                 $this->gl_code = $gl_code;
280                 $this->tax_included = $tax_included;
281
282                 $opts = get_item($item_code);
283                 $this->vat_category = $opts['vat_category'];
284         }
285
286 //      function full_charge_price($tax_group_id, $trans_type=ST_PURCHORDER)
287 //      {
288 //              return get_full_price_for_item($trans_type, $this->item_code, 
289 //                $this->chg_price, $tax_group_id, $this->tax_included);
290 //      }
291
292         function taxfree_charge_price()
293         {
294                 $this->split_item_value();
295                 return $this->gl_amounts['Net'];
296         }
297
298         /*
299                 Splits item value to parts posted to GL.
300         */
301         function split_item_value()
302         {
303
304         $vat_factor = 1;
305
306                 return $this->gl_amounts = split_item_price($this->item_code, $this->chg_price*$this->this_quantity_inv, $this->cart->tax_group_id, $this->cart->tax_included, 
307                         $this->cart->trans_type, $vat_factor);
308         }
309 }
310
311
312 class gl_codes 
313 {
314
315         var $gl_code;
316         var $gl_act_name;
317         var $gl_dim;
318         var $gl_dim2;
319         var $amount;
320         var $memo_;
321
322         function __construct($gl_code, $gl_act_name, $gl_dim, $gl_dim2, $amount, $memo_)
323         {
324                 $this->gl_code = $gl_code;
325                 $this->gl_act_name = $gl_act_name;
326                 $this->gl_dim = $gl_dim;
327                 $this->gl_dim2 = $gl_dim2;
328                 $this->amount = $amount;
329                 $this->memo_= $memo_;
330         }
331 }
332