price.lib.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. <?php
  2. /* Copyright (C) 2002-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2006-2008 Laurent Destailleur <eldy@users.sourceforge.net>
  4. * Copyright (C) 2010-2012 Juanjo Menent <jmenent@2byte.es>
  5. * Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. /**
  21. * \file htdocs/core/lib/price.lib.php
  22. * \brief Library with functions to calculate prices
  23. */
  24. /**
  25. * Calculate totals (net, vat, ...) of a line.
  26. * Value for localtaxX_type are '0' : local tax not applied
  27. * '1' : local tax apply on products and services without vat (vat is not applied for local tax calculation)
  28. * '2' : local tax apply on products and services before vat (vat is calculated on amount + localtax)
  29. * '3' : local tax apply on products without vat (vat is not applied for local tax calculation)
  30. * '4' : local tax apply on products before vat (vat is calculated on amount + localtax)
  31. * '5' : local tax apply on services without vat (vat is not applied for local tax calculation)
  32. * '6' : local tax apply on services before vat (vat is calculated on amount + localtax)
  33. * '7' : local tax is a fix amount applied on global invoice
  34. *
  35. * @param int $qty Quantity
  36. * @param float $pu Unit price (HT or TTC selon price_base_type)
  37. * @param float $remise_percent_ligne Discount for line
  38. * @param float $txtva 0=do not apply standard tax, Vat rate=apply
  39. * @param float $uselocaltax1_rate 0=do not use this localtax, >0=apply, -1=autodetect according to seller
  40. * @param float $uselocaltax2_rate 0=do not use this localtax, >0=apply, -1=autodetect according to seller
  41. * @param float $remise_percent_global 0
  42. * @param string $price_base_type HT=on calcule sur le HT, TTC=on calcule sur le TTC
  43. * @param int $info_bits Miscellanous informations on line
  44. * @param int $type 0/1=Product/service
  45. * @param string $seller Thirdparty seller (we need $seller->country_code property). Provided only if seller is the supplier.
  46. * @return result[ 0=total_ht,
  47. * 1=total_vat,
  48. * 2=total_ttc,
  49. * 3=pu_ht,
  50. * 4=pu_tva,
  51. * 5=pu_ttc,
  52. * 6=total_ht_without_discount,
  53. * 7=total_vat_without_discount,
  54. * 8=total_ttc_without_discount,
  55. * 9=amount tax1 for total_ht,
  56. * 10=amount tax2 for total_ht,
  57. * 11=amount tax1 for pu_ht,
  58. * 12=amount tax2 for pu_ht,
  59. * 13=not used???,
  60. * 14=amount tax1 for total_ht_without_discount,
  61. * 15=amount tax1 for total_ht_without_discount]
  62. */
  63. function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $seller = '')
  64. {
  65. global $conf,$mysoc,$db;
  66. $result=array();
  67. if (empty($seller) || ! is_object($seller))
  68. {
  69. if (! is_object($mysoc)) // mysoc may be not defined (during migration process)
  70. {
  71. $mysoc=new Societe($db);
  72. $mysoc->getMysoc($conf);
  73. }
  74. $seller=$mysoc; // If seller is a customer, $seller is not provided, we use $mysoc
  75. //var_dump($seller->country_id);exit;
  76. }
  77. $countryid=$seller->country_id;
  78. if ($uselocaltax1_rate < 0) $uselocaltax1_rate=$seller->localtax1_assuj;
  79. if ($uselocaltax2_rate < 0) $uselocaltax2_rate=$seller->localtax2_assuj;
  80. // Now we search localtaxes information ourself (rates and types).
  81. $sql = "SELECT taux, localtax1, localtax2, localtax1_type, localtax2_type";
  82. $sql.= " FROM ".MAIN_DB_PREFIX."c_tva as cv";
  83. //$sql.= ", ".MAIN_DB_PREFIX."c_pays as cc";
  84. $sql.= " WHERE cv.taux = ".$txtva;
  85. //$sql.= " AND cv.fk_pays = cc.rowid and cc.code = '".$mysoc->country_code."'";
  86. $sql.= " AND cv.fk_pays = ".$countryid;
  87. dol_syslog("search vat information sql=".$sql);
  88. $resql = $db->query($sql);
  89. if ($resql)
  90. {
  91. $obj = $db->fetch_object($resql);
  92. if ($obj)
  93. {
  94. $localtax1_rate=$obj->localtax1;
  95. $localtax2_rate=$obj->localtax2;
  96. $localtax1_type=$obj->localtax1_type;
  97. $localtax2_type=$obj->localtax2_type;
  98. //var_dump($localtax1_rate.' '.$localtax2_rate.' '.$localtax1_type.' '.$localtax2_type);exit;
  99. }
  100. }
  101. else dol_print_error($db);
  102. // initialize total (may be HT or TTC depending on price_base_type)
  103. $tot_sans_remise = $pu * $qty;
  104. $tot_avec_remise_ligne = $tot_sans_remise * (1 - ($remise_percent_ligne / 100));
  105. $tot_avec_remise = $tot_avec_remise_ligne * (1 - ($remise_percent_global / 100));
  106. // initialize result
  107. for ($i=0; $i <= 15; $i++) $result[$i] = 0;
  108. // if there's some localtax including vat, we calculate localtaxes (we will add later)
  109. $localtaxes = array(0,0,0);
  110. $apply_tax = false;
  111. switch($localtax1_type) {
  112. case '2': // localtax on product or service
  113. $apply_tax = true;
  114. break;
  115. case '4': // localtax on product
  116. if ($type == 0) $apply_tax = true;
  117. break;
  118. case '6': // localtax on service
  119. if ($type == 1) $apply_tax = true;
  120. break;
  121. }
  122. if ($uselocaltax1_rate && $apply_tax) {
  123. $result[14] = price2num(($tot_sans_remise * (1 + ( $localtax1_rate / 100))) - $tot_sans_remise, 'MT');
  124. $localtaxes[0] += $result[14];
  125. $result[9] = price2num(($tot_avec_remise * (1 + ( $localtax1_rate / 100))) - $tot_avec_remise, 'MT');
  126. $localtaxes[1] += $result[9];
  127. $result[11] = price2num(($pu * (1 + ( $localtax1_rate / 100))) - $pu, 'MU');
  128. $localtaxes[2] += $result[11];
  129. }
  130. $apply_tax = false;
  131. switch($localtax2_type) {
  132. case '2': // localtax on product or service
  133. $apply_tax = true;
  134. break;
  135. case '4': // localtax on product
  136. if ($type == 0) $apply_tax = true;
  137. break;
  138. case '6': // localtax on service
  139. if ($type == 1) $apply_tax = true;
  140. break;
  141. }
  142. if ($uselocaltax2_rate && $apply_tax) {
  143. $result[15] = price2num(($tot_sans_remise * (1 + ( $localtax2_rate / 100))) - $tot_sans_remise, 'MT');
  144. $localtaxes[0] += $result[15];
  145. $result[10] = price2num(($tot_avec_remise * (1 + ( $localtax2_rate / 100))) - $tot_avec_remise, 'MT');
  146. $localtaxes[1] += $result[10];
  147. $result[12] = price2num(($pu * (1 + ( $localtax2_rate / 100))) - $pu, 'MU');
  148. $localtaxes[2] += $result[12];
  149. }
  150. //dol_syslog("price.lib::calcul_price_total $qty, $pu, $remise_percent_ligne, $txtva, $price_base_type $info_bits");
  151. if ($price_base_type == 'HT')
  152. {
  153. // We work to define prices using the price without tax
  154. $result[6] = price2num($tot_sans_remise, 'MT');
  155. $result[8] = price2num(($tot_sans_remise + $localtaxes[0]) * (1 + ( (($info_bits & 1)?0:$txtva) / 100)), 'MT'); // Selon TVA NPR ou non
  156. $result8bis= price2num(($tot_sans_remise + $localtaxes[0]) * (1 + ( $txtva / 100)), 'MT'); // Si TVA consideree normale (non NPR)
  157. $result[7] = price2num($result8bis - ($result[6] + $localtaxes[0]), 'MT');
  158. $result[0] = price2num($tot_avec_remise, 'MT');
  159. $result[2] = price2num(($tot_avec_remise + $localtaxes[1]) * (1 + ( (($info_bits & 1)?0:$txtva) / 100)), 'MT'); // Selon TVA NPR ou non
  160. $result2bis= price2num(($tot_avec_remise + $localtaxes[1]) * (1 + ( $txtva / 100)), 'MT'); // Si TVA consideree normale (non NPR)
  161. $result[1] = price2num($result2bis - ($result[0] + $localtaxes[1]), 'MT'); // Total VAT = TTC - (HT + localtax)
  162. $result[3] = price2num($pu, 'MU');
  163. $result[5] = price2num(($pu + $localtaxes[2]) * (1 + ((($info_bits & 1)?0:$txtva) / 100)), 'MU'); // Selon TVA NPR ou non
  164. $result5bis= price2num(($pu + $localtaxes[2]) * (1 + ($txtva / 100)), 'MU'); // Si TVA consideree normale (non NPR)
  165. $result[4] = price2num($result5bis - ($result[3] + $localtaxes[2]), 'MU');
  166. }
  167. else
  168. {
  169. // We work to define prices using the price with tax
  170. $result[8] = price2num($tot_sans_remise + $localtaxes[0], 'MT');
  171. $result[6] = price2num(($tot_sans_remise + $localtaxes[0]) / (1 + ((($info_bits & 1)?0:$txtva) / 100)), 'MT'); // Selon TVA NPR ou non
  172. $result6bis= price2num(($tot_sans_remise + $localtaxes[0]) / (1 + ($txtva / 100)), 'MT'); // Si TVA consideree normale (non NPR)
  173. $result[7] = price2num($result[8] - ($result6bis + $localtaxes[0]), 'MT');
  174. $result[2] = price2num($tot_avec_remise + $localtaxes[1], 'MT');
  175. $result[0] = price2num(($tot_avec_remise + $localtaxes[1]) / (1 + ((($info_bits & 1)?0:$txtva) / 100)), 'MT'); // Selon TVA NPR ou non
  176. $result0bis= price2num(($tot_avec_remise + $localtaxes[1]) / (1 + ($txtva / 100)), 'MT'); // Si TVA consideree normale (non NPR)
  177. $result[1] = price2num($result[2] - ($result0bis + $localtaxes[1]), 'MT'); // Total VAT = TTC - HT
  178. $result[5] = price2num(($pu + $localtaxes[2]), 'MU');
  179. $result[3] = price2num(($pu + $localtaxes[2]) / (1 + ((($info_bits & 1)?0:$txtva) / 100)), 'MU'); // Selon TVA NPR ou non
  180. $result3bis= price2num(($pu + $localtaxes[2]) / (1 + ($txtva / 100)), 'MU'); // Si TVA consideree normale (non NPR)
  181. $result[4] = price2num($result[5] - ($result3bis + $localtaxes[2]), 'MU');
  182. }
  183. // if there's some localtax without vat, we calculate localtaxes (we will add them at end)
  184. //If price is 'TTC' we need to have the totals without VAT for a correct calculation
  185. if ($price_base_type=='TTC')
  186. {
  187. $tot_sans_remise= price2num($tot_sans_remise / (1 + ($txtva / 100)),'MU');
  188. $tot_avec_remise= price2num($tot_avec_remise / (1 + ($txtva / 100)),'MU');
  189. $pu = price2num($pu / (1 + ($txtva / 100)),'MU');
  190. }
  191. $apply_tax = false;
  192. switch($localtax1_type) {
  193. case '1': // localtax on product or service
  194. $apply_tax = true;
  195. break;
  196. case '3': // localtax on product
  197. if ($type == 0) $apply_tax = true;
  198. break;
  199. case '5': // localtax on service
  200. if ($type == 1) $apply_tax = true;
  201. break;
  202. }
  203. if ($uselocaltax1_rate && $apply_tax) {
  204. $result[14] = price2num(($tot_sans_remise * (1 + ( $localtax1_rate / 100))) - $tot_sans_remise, 'MT'); // amount tax1 for total_ht_without_discount
  205. $result[8] += $result[14]; // total_ttc_without_discount + tax1
  206. $result[9] = price2num(($tot_avec_remise * (1 + ( $localtax1_rate / 100))) - $tot_avec_remise, 'MT'); // amount tax1 for total_ht
  207. $result[2] += $result[9]; // total_ttc + tax1
  208. $result[11] = price2num(($pu * (1 + ( $localtax1_rate / 100))) - $pu, 'MU'); // amount tax1 for pu_ht
  209. $result[5] += $result[11]; // pu_ht + tax1
  210. }
  211. $apply_tax = false;
  212. switch($localtax2_type) {
  213. case '1': // localtax on product or service
  214. $apply_tax = true;
  215. break;
  216. case '3': // localtax on product
  217. if ($type == 0) $apply_tax = true;
  218. break;
  219. case '5': // localtax on service
  220. if ($type == 1) $apply_tax = true;
  221. break;
  222. }
  223. if ($uselocaltax2_rate && $apply_tax) {
  224. $result[15] = price2num(($tot_sans_remise * (1 + ( $localtax2_rate / 100))) - $tot_sans_remise, 'MT'); // amount tax2 for total_ht_without_discount
  225. $result[8] += $result[15]; // total_ttc_without_discount + tax2
  226. $result[10] = price2num(($tot_avec_remise * (1 + ( $localtax2_rate / 100))) - $tot_avec_remise, 'MT'); // amount tax2 for total_ht
  227. $result[2] += $result[10]; // total_ttc + tax2
  228. $result[12] = price2num(($pu * (1 + ( $localtax2_rate / 100))) - $pu, 'MU'); // amount tax2 for pu_ht
  229. $result[5] += $result[12]; // pu_ht + tax2
  230. }
  231. // If rounding is not using base 10 (rare)
  232. if (! empty($conf->global->MAIN_ROUNDING_RULE_TOT))
  233. {
  234. if ($price_base_type == 'HT')
  235. {
  236. $result[0]=round($result[0]/$conf->global->MAIN_ROUNDING_RULE_TOT, 0)*$conf->global->MAIN_ROUNDING_RULE_TOT;
  237. $result[1]=round($result[1]/$conf->global->MAIN_ROUNDING_RULE_TOT, 0)*$conf->global->MAIN_ROUNDING_RULE_TOT;
  238. $result[2]=price2num($result[0]+$result[1], 'MT');
  239. $result[9]=round($result[9]/$conf->global->MAIN_ROUNDING_RULE_TOT, 0)*$conf->global->MAIN_ROUNDING_RULE_TOT;
  240. $result[10]=round($result[10]/$conf->global->MAIN_ROUNDING_RULE_TOT, 0)*$conf->global->MAIN_ROUNDING_RULE_TOT;
  241. }
  242. else
  243. {
  244. $result[1]=round($result[1]/$conf->global->MAIN_ROUNDING_RULE_TOT, 0)*$conf->global->MAIN_ROUNDING_RULE_TOT;
  245. $result[2]=round($result[2]/$conf->global->MAIN_ROUNDING_RULE_TOT, 0)*$conf->global->MAIN_ROUNDING_RULE_TOT;
  246. $result[0]=price2num($result[2]-$result[0], 'MT');
  247. $result[9]=round($result[9]/$conf->global->MAIN_ROUNDING_RULE_TOT, 0)*$conf->global->MAIN_ROUNDING_RULE_TOT;
  248. $result[10]=round($result[10]/$conf->global->MAIN_ROUNDING_RULE_TOT, 0)*$conf->global->MAIN_ROUNDING_RULE_TOT;
  249. }
  250. }
  251. //print "Price.lib::calcul_price_total ".$result[0]."-".$result[1]."-".$result[2];
  252. return $result;
  253. }