PricesTest.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. <?php
  2. /* Copyright (C) 2010 Laurent Destailleur <eldy@users.sourceforge.net>
  3. * Copyright (C) 2015 Juanjo Menent <jmenent@2byte.es>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. * or see http://www.gnu.org/
  18. */
  19. /**
  20. * \file test/phpunit/PricesTest.php
  21. * \ingroup test
  22. * \brief PHPUnit test
  23. * \remarks To run this script as CLI: phpunit filename.php
  24. */
  25. global $conf,$user,$langs,$db;
  26. //define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver
  27. //require_once 'PHPUnit/Autoload.php';
  28. require_once dirname(__FILE__).'/../../htdocs/master.inc.php';
  29. require_once dirname(__FILE__).'/../../htdocs/core/lib/price.lib.php';
  30. require_once dirname(__FILE__).'/../../htdocs/compta/facture/class/facture.class.php';
  31. if (empty($user->id))
  32. {
  33. print "Load permissions for admin user nb 1\n";
  34. $user->fetch(1);
  35. $user->getrights();
  36. }
  37. $conf->global->MAIN_DISABLE_ALL_MAILS=1;
  38. if (! empty($conf->global->MAIN_ROUNDING_RULE_TOT))
  39. {
  40. print "Parameter MAIN_ROUNDING_RULE_TOT must be set to 0 or not set.\n";
  41. exit(1);
  42. }
  43. /**
  44. * Class for PHPUnit tests
  45. *
  46. * @backupGlobals disabled
  47. * @backupStaticAttributes enabled
  48. * @remarks backupGlobals must be disabled to have db,conf,user and lang not erased.
  49. */
  50. class PricesTest extends PHPUnit_Framework_TestCase
  51. {
  52. protected $savconf;
  53. protected $savuser;
  54. protected $savlangs;
  55. protected $savdb;
  56. /**
  57. * Constructor
  58. * We save global variables into local variables
  59. *
  60. * @return CoreTest
  61. */
  62. function __construct()
  63. {
  64. parent::__construct();
  65. //$this->sharedFixture
  66. global $conf,$user,$langs,$db;
  67. $this->savconf=$conf;
  68. $this->savuser=$user;
  69. $this->savlangs=$langs;
  70. $this->savdb=$db;
  71. print __METHOD__." db->type=".$db->type." user->id=".$user->id;
  72. //print " - db ".$db->db;
  73. print "\n";
  74. }
  75. // Static methods
  76. public static function setUpBeforeClass()
  77. {
  78. global $conf,$user,$langs,$db;
  79. //$db->begin(); // This is to have all actions inside a transaction even if test launched without suite.
  80. print __METHOD__."\n";
  81. }
  82. // tear down after class
  83. public static function tearDownAfterClass()
  84. {
  85. global $conf,$user,$langs,$db;
  86. //$db->rollback();
  87. print __METHOD__."\n";
  88. }
  89. /**
  90. * Init phpunit tests
  91. *
  92. * @return void
  93. */
  94. protected function setUp()
  95. {
  96. global $conf,$user,$langs,$db;
  97. $conf=$this->savconf;
  98. $user=$this->savuser;
  99. $langs=$this->savlangs;
  100. $db=$this->savdb;
  101. print __METHOD__."\n";
  102. }
  103. /**
  104. * End phpunit tests
  105. *
  106. * @return void
  107. */
  108. protected function tearDown()
  109. {
  110. print __METHOD__."\n";
  111. }
  112. /**
  113. * Test function calcul_price_total
  114. *
  115. * @return boolean
  116. * @see http://wiki.dolibarr.org/index.php/Draft:VAT_calculation_and_rounding#Standard_usage
  117. */
  118. public function testCalculPriceTotal()
  119. {
  120. global $conf,$user,$langs,$db;
  121. $this->savconf=$conf;
  122. $this->savuser=$user;
  123. $this->savlangs=$langs;
  124. $this->savdb=$db;
  125. global $mysoc;
  126. $mysoc=new Societe($db);
  127. // To force status that say module multicompany is on
  128. //$conf->multicurrency=new stdClass();
  129. //$conf->multicurrency->enabled = 0;
  130. /*
  131. * Country France
  132. */
  133. // qty=1, unit_price=1.24, discount_line=0, vat_rate=10, price_base_type='HT' (method we provide value)
  134. $mysoc->country_code='FR';
  135. $mysoc->country_id=1;
  136. $result1=calcul_price_total(1, 1.24, 0, 10, 0, 0, 0, 'HT', 0, 0);
  137. print __METHOD__." result1=".join(', ',$result1)."\n";
  138. // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount)
  139. $this->assertEquals(array(1.24, 0.12, 1.36, 1.24, 0.124, 1.364, 1.24, 0.12, 1.36, 0, 0, 0, 0, 0, 0, 0, 1.24, 0.12, 1.36, 1.24, 0.124, 1.364, 1.24, 0.12, 1.36, 0, 0),$result1,'Test1 FR');
  140. // qty=1, unit_price=1.24, discount_line=0, vat_rate=10, price_base_type='HT', multicurrency_tx=1.09205 (method we provide value)
  141. $mysoc->country_code='FR';
  142. $mysoc->country_id=1;
  143. $result1=calcul_price_total(2, 8.56, 0, 10, 0, 0, 0, 'HT', 0, 0, '', '', 100, 1.09205);
  144. print __METHOD__." result1=".join(', ',$result1)."\n";
  145. // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount)
  146. $this->assertEquals(array(17.12, 1.71, 18.83, 8.56, 0.856, 9.416, 17.12, 1.71, 18.83, 0, 0, 0, 0, 0, 0, 0, 18.7, 1.87, 20.57, 9.34795, 0.93479, 10.28274, 18.7, 1.87, 20.57, 0, 0),$result1,'Test1b FR');
  147. // qty=2, unit_price=0, discount_line=0, vat_rate=10, price_base_type='HT', multicurrency_tx=1.09205 (method we provide value), pu_ht_devise=100
  148. $mysoc->country_code='FR';
  149. $mysoc->country_id=1;
  150. $result1=calcul_price_total(2, 0, 0, 10, 0, 0, 0, 'HT', 0, 0, '', '', 100, 1.09205, 20);
  151. print __METHOD__." result1=".join(', ',$result1)."\n";
  152. // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount)
  153. $this->assertEquals(array(36.63, 3.66, 40.29, 18.31418, 1.83142, 20.1456, 36.63, 3.66, 40.29, 0, 0, 0, 0, 0, 0, 0, 40, 4, 44, 20, 2, 22, 40, 4, 44, 0, 0),$result1,'Test1c FR');
  154. /*
  155. * Country Spain
  156. */
  157. // 10 * 10 HT - 0% discount with 10% vat, seller not using localtax1, not localtax2 (method we provide value)
  158. $mysoc->country_code='ES';
  159. $mysoc->country_id=4;
  160. $mysoc->localtax1_assuj=0;
  161. $mysoc->localtax2_assuj=0;
  162. $result2=calcul_price_total(10, 10, 0, 10, 0, 0, 0, 'HT', 0, 0); // 10 * 10 HT - 0% discount with 10% vat and 1.4% localtax1, 0% localtax2
  163. print __METHOD__." result2=".join(', ',$result2)."\n";
  164. // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount)
  165. $this->assertEquals(array(100, 10, 110, 10, 1, 11, 100, 10, 110, 0, 0, 0, 0, 0, 0, 0, 100, 10, 110, 10, 1, 11, 100, 10, 110, 0, 0),$result2,'Test1 ES');
  166. // 10 * 10 HT - 0% discount with 10% vat, seller not using localtax1, not localtax2 (other method autodetect)
  167. $mysoc->country_code='ES';
  168. $mysoc->country_id=4;
  169. $mysoc->localtax1_assuj=0;
  170. $mysoc->localtax2_assuj=0;
  171. $result2=calcul_price_total(10, 10, 0, 10, -1, -1, 0, 'HT', 0, 0); // 10 * 10 HT - 0% discount with 10% vat and 1.4% localtax1, 0% localtax2
  172. print __METHOD__." result2=".join(', ',$result2)."\n";
  173. // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount)
  174. $this->assertEquals(array(100, 10, 110, 10, 1, 11, 100, 10, 110, 0, 0, 0, 0, 0, 0, 0, 100, 10, 110, 10, 1, 11, 100, 10, 110, 0, 0),$result2,'Test2 ES');
  175. // --------------------------------------------------------
  176. // 10 * 10 HT - 0% discount with 10% vat and 1.4% localtax1 type 3, 0% localtax2 type 5 (method we provide value)
  177. $mysoc->country_code='ES';
  178. $mysoc->country_id=4;
  179. $mysoc->localtax1_assuj=1;
  180. $mysoc->localtax2_assuj=0;
  181. $result2=calcul_price_total(10, 10, 0, 10, 1.4, 0, 0, 'HT', 0, 0);
  182. print __METHOD__." result2=".join(', ',$result2)."\n";
  183. // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount)
  184. $this->assertEquals(array(100, 10, 111.4, 10, 1, 11.14, 100, 10, 111.4, 1.4, 0, 0.14, 0, 0, 1.4, 0, 100, 10, 111.4, 10, 1, 11.14, 100, 10, 111.4, 1.4, 0),$result2,'Test3 ES');
  185. // 10 * 10 HT - 0% discount with 10% vat and 1.4% localtax1 type 3, 0% localtax2 type 5 (other method autodetect)
  186. $mysoc->country_code='ES';
  187. $mysoc->country_id=4;
  188. $mysoc->localtax1_assuj=1;
  189. $mysoc->localtax2_assuj=0;
  190. $result2=calcul_price_total(10, 10, 0, 10, -1, -1, 0, 'HT', 0, 0);
  191. print __METHOD__." result2=".join(', ',$result2)."\n";
  192. // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount)
  193. $this->assertEquals(array(100, 10, 111.4, 10, 1, 11.14, 100, 10, 111.4, 1.4, 0, 0.14, 0, 0, 1.4, 0, 100, 10, 111.4, 10, 1, 11.14, 100, 10, 111.4, 1.4, 0),$result2,'Test4 ES');
  194. // --------------------------------------------------------
  195. // 10 * 10 HT - 0% discount with 10% vat and 0% localtax1 type 3, 19% localtax2 type 5 (method we provide value), we provide a service and not a product
  196. $mysoc->country_code='ES';
  197. $mysoc->country_id=4;
  198. $mysoc->localtax1_assuj=0;
  199. $mysoc->localtax2_assuj=1;
  200. $result2=calcul_price_total(10, 10, 0, 10, 0, -19, 0, 'HT', 0, 1);
  201. // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount)
  202. $this->assertEquals(array(100, 10, 91, 10, 1, 9.1, 100, 10, 91, 0, -19, 0, -1.90, 0, 0, -19, 100, 10, 91, 10, 1, 9.1, 100, 10, 91, 0, -19),$result2,'Test5 ES for service');
  203. // 10 * 10 HT - 0% discount with 10% vat and 0% localtax1 type 3, 21% localtax2 type 5 (other method autodetect), we provide a service and not a product
  204. $mysoc->country_code='ES';
  205. $mysoc->country_id=4;
  206. $mysoc->localtax1_assuj=0;
  207. $mysoc->localtax2_assuj=1;
  208. $result2=calcul_price_total(10, 10, 0, 10, -1, -1, 0, 'HT', 0, 0);
  209. print __METHOD__." result2=".join(', ',$result2)."\n";
  210. // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount)
  211. $this->assertEquals(array(100, 10, 110, 10, 1, 11, 100, 10, 110, 0, 0, 0, 0, 0, 0, 0, 100, 10, 110, 10, 1, 11, 100, 10, 110, 0, 0),$result2,'Test6 ES for product');
  212. // 10 * 10 HT - 0% discount with 10% vat and 0% localtax1 type 3, 21% localtax2 type 5 (other method autodetect), we provide a product and not a service
  213. $mysoc->country_code='ES';
  214. $mysoc->country_id=4;
  215. $mysoc->localtax1_assuj=0;
  216. $mysoc->localtax2_assuj=1;
  217. $result2=calcul_price_total(10, 10, 0, 10, -1, -1, 0, 'HT', 0, 1);
  218. print __METHOD__." result2=".join(', ',$result2)."\n";
  219. // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount)
  220. $this->assertEquals(array(100, 10, 91, 10, 1, 9.1, 100, 10, 91, 0, -19, 0, -1.90, 0, 0, -19, 100, 10, 91, 10, 1, 9.1, 100, 10, 91, 0, -19),$result2,'Test6 ES for service');
  221. // --------------------------------------------------------
  222. // Credit Note: 10 * -10 HT - 0% discount with 10% vat and 0% localtax1 type 3, 19% localtax2 type 5 (method we provide value), we provide a product and not a service
  223. $mysoc->country_code='ES';
  224. $mysoc->country_id=4;
  225. $mysoc->localtax1_assuj=0;
  226. $mysoc->localtax2_assuj=1;
  227. $result2=calcul_price_total(10, -10, 0, 10, 0, 19, 0, 'HT', 0, 0);
  228. print __METHOD__." result2=".join(', ',$result2)."\n";
  229. // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount)
  230. $this->assertEquals(array(-100, -10, -110, -10, -1, -11, -100, -10, -110, 0, 0, 0, 0, 0, 0, 0, -100, -10, -110, -10, -1, -11, -100, -10, -110, 0, 0),$result2,'Test7 ES for product');
  231. // Credit Note: 10 * -10 HT - 0% discount with 10% vat and 1.4% localtax1 type 3, 0% localtax2 type 5 (other method autodetect), we provide a service and not a product
  232. $mysoc->country_code='ES';
  233. $mysoc->country_id=4;
  234. $mysoc->localtax1_assuj=0;
  235. $mysoc->localtax2_assuj=1;
  236. $result2=calcul_price_total(10, -10, 0, 10, -1, -1, 0, 'HT', 0, 1);
  237. print __METHOD__." result2=".join(', ',$result2)."\n";
  238. $this->assertEquals(array(-100, -10, -91, -10, -1, -9.1, -100, -10, -91, 0, 19, 0, 1.90, 0, 0, 19, -100, -10, -91, -10, -1, -9.1, -100, -10, -91, 0, 19),$result2,'Test8 ES for service');
  239. /*
  240. * Country Côte d'Ivoire
  241. */
  242. // 10 * 10 HT - 0% discount with 18% vat, seller using localtax1 type 2, not localtax2 (method we provide value)
  243. $mysoc->country_code='CI';
  244. $mysoc->country_id=21;
  245. $mysoc->localtax1_assuj=1;
  246. $mysoc->localtax2_assuj=0;
  247. //$localtaxes=getLocalTaxesFromRate(18, 0, null, $mysoc);
  248. //var_dump($locataxes);
  249. $result3=calcul_price_total(10, 10, 0, 18, 7.5, 0, 0, 'HT', 0, 0); // 10 * 10 HT - 0% discount with 18% vat and 7.5% localtax1, 0% localtax2
  250. print __METHOD__." result3=".join(', ',$result3)."\n";
  251. // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount)
  252. $this->assertEquals(array(100, 18, 126.85, 10, 1.8, 12.685, 100, 18, 126.85, 8.85, 0, 0.885, 0, 0, 8.85, 0, 100, 18, 126.85, 10, 1.8, 12.685, 100, 18, 126.85, 8.85, 0),$result3,'Test9 CI');
  253. // 10 * 10 HT - 0% discount with 18% vat, seller using localtax1 type 2, not localtax2 (other method autodetect)
  254. $mysoc->country_code='CI';
  255. $mysoc->country_id=21;
  256. $mysoc->localtax1_assuj=1;
  257. $mysoc->localtax2_assuj=0;
  258. $result3=calcul_price_total(10, 10, 0, 18, -1, -1, 0, 'HT', 0, 0); // 10 * 10 HT - 0% discount with 18% vat and 7.5% localtax1, 0% localtax2
  259. print __METHOD__." result3=".join(', ',$result3)."\n";
  260. // result[0,1,2,3,4,5,6,7,8] (total_ht, total_vat, total_ttc, pu_ht, pu_tva, pu_ttc, total_ht_without_discount, total_vat_without_discount, total_ttc_without_discount)
  261. $this->assertEquals(array(100, 18, 126.85, 10, 1.8, 12.685, 100, 18, 126.85, 8.85, 0, 0.885, 0, 0, 8.85, 0, 100, 18, 126.85, 10, 1.8, 12.685, 100, 18, 126.85, 8.85, 0),$result3,'Test10 CI');
  262. return true;
  263. }
  264. /**
  265. * Test function addline and update_price
  266. *
  267. * @return boolean
  268. * @see http://wiki.dolibarr.org/index.php/Draft:VAT_calculation_and_rounding#Standard_usage
  269. */
  270. public function testUpdatePrice()
  271. {
  272. //$this->sharedFixture
  273. global $conf,$user,$langs,$db;
  274. $this->savconf=$conf;
  275. $this->savuser=$user;
  276. $this->savlangs=$langs;
  277. $this->savdb=$db;
  278. $conf->global->MAIN_ROUNDOFTOTAL_NOT_TOTALOFROUND=0;
  279. // Two lines of 1.24 give 2.48 HT and 2.72 TTC with standard vat rounding mode
  280. $localobject=new Facture($this->savdb);
  281. $localobject->initAsSpecimen('nolines');
  282. $invoiceid=$localobject->create($user);
  283. $localobject->addline('Desc',1.24,1,10,0,0,0,0,'','',0,0,0,'HT');
  284. $localobject->addline('Desc',1.24,1,10,0,0,0,0,'','',0,0,0,'HT');
  285. $newlocalobject=new Facture($this->savdb);
  286. $newlocalobject->fetch($invoiceid);
  287. $this->assertEquals(2.48,$newlocalobject->total_ht, "testUpdatePrice test1");
  288. $this->assertEquals(0.24,$newlocalobject->total_tva, "testUpdatePrice test2");
  289. $this->assertEquals(2.72,$newlocalobject->total_ttc, "testUpdatePrice test3");
  290. // Two lines of 1.24 give 2.48 HT and 2.73 TTC with global vat rounding mode
  291. $localobject=new Facture($this->savdb);
  292. $localobject->initAsSpecimen('nolines');
  293. $invoiceid=$localobject->create($user);
  294. $localobject->addline('Desc',1.24,1,10,0,0,0,0,'','',0,0,0,'HT');
  295. $localobject->addline('Desc',1.24,1,10,0,0,0,0,'','',0,0,0,'HT');
  296. $newlocalobject=new Facture($this->savdb);
  297. $newlocalobject->fetch($invoiceid);
  298. $this->assertEquals(2.48,$newlocalobject->total_ht, "testUpdatePrice test4");
  299. //$this->assertEquals(0.25,$newlocalobject->total_tva);
  300. //$this->assertEquals(2.73,$newlocalobject->total_ttc);
  301. }
  302. }