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 include_once($path_to_root . "/taxes/db/tax_groups_db.inc");
13 include_once($path_to_root . "/taxes/db/tax_types_db.inc");
14 include_once($path_to_root . "/taxes/db/item_tax_types_db.inc");
16 //---------------------------------------------------------------------------------
17 // Returns basic fiscal parameters for transaction item which depend on stock type and customer/supplier tax area.
19 // vat_category => stock tax category
20 // tax_area => cust/supp tax area
21 // taxes => all taxes applicable:
22 // tax_type_id1 => (tax_type_id, tax_type_name, sales_gl_code, purchasing_gl_code, rate)
23 // tax_type_id2 => ...
25 function get_base_taxdata($stock_id, $group_id)
27 static $last_group = null, $group_data;
29 if ($last_group != $group_id) { // cache group data for better performance
30 $last_group = $group_id;
31 $group_data = get_tax_group_data($group_id);
34 $taxdata = array('tax_area' => $group_data['tax_area'], 'taxes' => null);
36 $item_tax_type = get_item_tax_type_for_item($stock_id); // get item tax data
37 $taxdata['vat_category'] = $item_tax_type['vat_category'];
39 // if the item is exempt from all taxes thats all
40 if ($item_tax_type["exempt"])
43 $taxdata['taxes'] = array();
45 // get the exemptions for this item tax type
46 $item_tax_type_exemptions_db = get_item_tax_type_exemptions($item_tax_type["id"]);
48 // read them all into an array to minimize db querying
49 $item_tax_type_exemptions = array();
50 while ($item_tax_type_exemp = db_fetch($item_tax_type_exemptions_db))
52 $item_tax_type_exemptions[] = $item_tax_type_exemp["tax_type_id"];
55 $tax_group_items_array = $group_data['taxes'];
56 // if any of the taxes of the tax group are in the exemptions, then skip
57 foreach ($tax_group_items_array as $tax_group_item)
62 // if it's in the exemptions, skip
63 if (is_null($tax_group_item['rate']))
66 foreach ($item_tax_type_exemptions as $exemption)
68 if (($tax_group_item['tax_type_id'] == $exemption))
77 $index = $tax_group_item['tax_type_id'];
78 $taxdata['taxes'][$index] = $tax_group_item;
86 Main tax procedure splitting transaction item value according to item tax rules applicable:
87 $amount - price/value to be splitted
88 $tax_group - entity tax group
89 $tax_included - whether value includes all taxes
90 $vat_factor - 0-1; tax deduction factor (purchases, not used for now; depends on whthere it is related to exempt or taxed sales)
91 $allow_reverse - option for invoice - whether to honour reverse charging (depends on customer tax status)
93 Returned array contains calculated values for GL postings and tax registration:
94 'Net' - value without tax,
96 'Cost' - cost value (can be higher then Net value),
97 'vat_category' - stock tax category
99 and (with numeric keys) detailed info for any applicable tax rate:
100 'tax_type_id' - tax type id
101 'Value' - charged tax value
102 'Deductible' - tax deductible (can be lower than Value for special goods or mixed sales structure)
103 'Payable' - tax payable
104 'Adjust' - additional adjustment to deductible tax due to sales structure factor
106 'sales_gl_code' - sales tax GL account
107 'purchasing_gl_code' - purchase tax GL account
108 'tax_type_name' - name of tax type
110 Price value is splitted as follows:
111 Tax: sum of Value (for applicable taxes)
113 Cost: Net + sum(Payable-Deductible)
114 for every applicable tax rate:
115 Value: tax calculated or 0
116 Deductible: vat_factor*Value or 0
117 Adjust: Value-Deductible or 0
120 function split_item_price($stock_id, $amount, $group_id, $tax_included=false, $trans_type=ST_SUPPINVOICE, $vat_factor = 1,
125 $dec = user_price_dec();
127 $itemdata = get_base_taxdata($stock_id, $group_id);
128 $vat_category = $itemdata['vat_category'];
129 $item_taxes = $itemdata['taxes'];
131 $taxopt = $TS->options($trans_type, $itemdata['tax_area'], $vat_category, $allow_reverse);
133 if (empty($item_taxes))
135 $ret_array['Net'] = $amount;
136 $ret_array['Cost'] = $amount;
137 $ret_array['Tax'] = 0;
138 if (!is_null($item_taxes)) // register empty taxes only for not fully exempt items
139 $ret_array[] = array('Value'=>0, 'rate' => null, 'tax_type_id' => null, 'Deductible'=>0, 'Adjust' => 0, 'Payable' => 0);
143 $ret_array['Net'] = $ret_array['Cost'] = $ret_array['Tax'] = 0;
147 if ($taxopt&TAX_CHARGED) // divide tax for net and tax only if charged on document
148 foreach ($item_taxes as $taxitem)
149 $tax_multiplier += $taxitem['rate'];
151 $partial_vat_percent = get_company_pref('partial_vat_percent');
153 foreach ($item_taxes as $tax_id => $item_tax)
155 if ($item_tax['rate'] !== null)
158 // effective vat for some special purchases is lower than nominal
159 $factor = $vat_category == VC_NONDEDUCT ? 0 : ($vat_category==VC_PARTIAL ? $partial_vat_percent/100.0 : 1);
161 $net_value = $amount;
162 if ($tax_included == true) {
163 $vat_value = round($amount*$item_tax['rate']/(100+$tax_multiplier), 2);
165 if ($taxopt&TAX_CHARGED)
166 $net_value -= $vat_value;
170 $vat_value = round($amount * $item_tax['rate'] / 100, 2);
173 $ret_array['Net'] = round2($net_value, $dec);
174 $ret_array['Cost'] = $ret_array['Net'];
176 $tax = array('Value' => 0, 'Deductible' => 0, 'Adjust' => 0, 'Payable' => 0);
178 $tax['purchasing_gl_code'] = $item_tax['purchasing_gl_code'];
179 $tax['sales_gl_code'] = $item_tax['sales_gl_code'];
180 $tax['rate'] = $item_tax['rate'];
181 $tax['tax_type_id'] = $item_tax['tax_type_id'];
182 $tax['tax_type_name'] = $item_tax['tax_type_name'];
184 if ($taxopt & TAX_CHARGED) // tax is charged on document
185 $tax['Value'] = round2($vat_value, $dec);
187 if ($taxopt & TAX_PAYABLE) // transaction is taxable
188 $tax['Payable'] = round2($vat_value, $dec);
190 if ($taxopt & TAX_DEDUCTIBLE) // tax is deductible
192 $tax['Deductible'] = round2($vat_value*$factor, 2); // avoid rounding issues if $dec > 2 decimal places
193 $tax['Adjust'] = round2(-(1-$vat_factor)*$factor*$vat_value, $dec); // adjustment due to mixed taxed/exmpt sales activity
195 $tax['Deductible'] = 0;
200 $ret_array['Cost'] += ($tax['Payable'] - $tax['Deductible']);
201 elseif ($tax['Deductible'])
202 $ret_array['Cost'] += $tax['Adjust'];
205 $ret_array['Tax'] += $tax['Value'];
209 $ret_array['vat_category'] = $vat_category;
213 //-----------------------------------------------------------------------------------
214 // return an array of (tax_type_id, tax_type_name, sales_gl_code, purchasing_gl_code, rate, included_in_price, Value, Net)
216 // $vat_factors - effective part of vat values included in tax; calculated but not included vat is added to net value
218 function get_tax_for_items($trans_type, $items, $prices, $tax_group, $tax_included=null,
219 $tax_algorithm = null, $vat_factors = null, $allow_reverse = true)
222 // calculate tax sums
223 $ret_tax_array = array();
224 foreach($items as $i => $stock_id)
226 $taxdata = split_item_price($stock_id, $prices[$i], $tax_group, $tax_included, $trans_type,
227 $vat_factors ? $vat_factors[$i] : 1, $allow_reverse);
229 foreach ($taxdata as $key => $data)
231 if (is_numeric($key))
233 $tax_id = isset($data['tax_type_id']) ? $data['tax_type_id'] : 'exempt';
235 if (!isset($ret_tax_array[$tax_id]))
237 $ret_tax_array[$tax_id] = $data;
238 $ret_tax_array[$tax_id]['Net'] = $taxdata['Net'];
239 $ret_tax_array[$tax_id]['vat_category'] = $taxdata['vat_category'];
243 foreach(array('Value', 'Payable', 'Deductible', 'Adjust') as $amt)
244 $ret_tax_array[$tax_id][$amt] += $data[$amt];
245 $ret_tax_array[$tax_id]['Net'] += $taxdata['Net'];
252 $tax_algorithm = get_company_pref('tax_algorithm');
254 if ($tax_algorithm == TCA_TOTALS) { // ?
255 $dec = user_price_dec();
257 foreach($ret_tax_array as $index => $item_tax) {
258 if ($ret_tax_array[$index]['Value'])
259 $ret_tax_array[$index]['Value'] = round2($item_tax['Net'] * $item_tax['rate'] / 100, $dec);
263 return $ret_tax_array;
267 //---------------------------------------------------------------------------------
269 // returns the price of a given item minus any included taxes
270 // for item $stock_id with line price $price and supplier/customer group_id $tax_group
272 function get_tax_free_price_for_item($trans_type, $stock_id, $price, $tax_group, $tax_included, $allow_reverse = true)
274 // if price is zero, then can't be taxed !
278 if ($tax_included==0) return $price;
280 $taxdata = split_item_price($stock_id, $price, $tax_group, $tax_included, $trans_type, 1, $allow_reverse);
282 return $taxdata['Net'];
285 // Full price (incl. VAT) for item $stock_id
286 // calculated for line price $price, and applicable group $tax_group
288 function get_full_price_for_item($trans_type, $stock_id, $price, $tax_group, $tax_included, $allow_reverse = true)
290 // if price is zero, then can't be taxed !
294 if ($tax_included==1) return $price;
296 $taxdata = split_item_price($stock_id, $price, $tax_group, $tax_included, $trans_type, 1, $allow_reverse);
298 return $taxdata['Net'] + $taxdata['Tax'];