calcul_price_total()   F
last analyzed

Complexity

Conditions 70
Paths > 20000

Size

Total Lines 359
Code Lines 245

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 70
eloc 245
nc 23040
nop 16
dl 0
loc 359
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* Copyright (C) 2002-2006 Rodolphe Quiedeville <[email protected]>
4
 * Copyright (C) 2006-2008 Laurent Destailleur  <[email protected]>
5
 * Copyright (C) 2010-2013 Juanjo Menent        <[email protected]>
6
 * Copyright (C) 2012      Christophe Battarel  <[email protected]>
7
 * Copyright (C) 2012      Cédric Salvador      <[email protected]>
8
 * Copyright (C) 2012-2014 Raphaël Doursenaud   <[email protected]>
9
 * Copyright (C) 2024       Frédéric France             <[email protected]>
10
 * Copyright (C) 2024		MDW							<[email protected]>
11
 * Copyright (C) 2024       Rafael San José             <[email protected]>
12
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 3 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
25
 */
26
27
use Dolibarr\Lib\ViewMain;
28
29
/**
30
 *      \file       htdocs/core/lib/price.lib.php
31
 *      \brief      Library with functions to calculate prices
32
 */
33
34
35
/**
36
 *      Calculate totals (net, vat, ...) of a line.
37
 *      Value for localtaxX_type are    '0' : local tax not applied
38
 *                                      '1' : local tax apply on products and services without vat (localtax is calculated on amount without tax)
39
 *                                      '2' : local tax apply on products and services including vat (localtax is calculated on amount + tax)
40
 *                                      '3' : local tax apply on products without vat (localtax is calculated on amount without tax)
41
 *                                      '4' : local tax apply on products including vat (localtax is calculated on amount + tax)
42
 *                                      '5' : local tax apply on services without vat (localtax is calculated on amount without tax)
43
 *                                      '6' : local tax apply on services including vat (localtax is calculated on amount + tax)
44
 *
45
 * @param float $qty Quantity
46
 * @param float $pu Unit price (HT or TTC depending on price_base_type. TODO Add also mode 'INCT' when pu is price HT+VAT+LT1+LT2)
47
 * @param float $remise_percent_ligne Discount for line
48
 * @param float $txtva 0=do not apply VAT tax, VAT rate=apply (this is VAT rate only without text code, we don't need text code because we alreaydy have all tax info into $localtaxes_array)
49
 * @param float $uselocaltax1_rate 0=do not use localtax1, >0=apply and get value from localtaxes_array (or database if empty), -1=autodetect according to seller if we must apply, get value from localtaxes_array (or database if empty). Try to always use -1.
50
 * @param float $uselocaltax2_rate 0=do not use localtax2, >0=apply and get value from localtaxes_array (or database if empty), -1=autodetect according to seller if we must apply, get value from localtaxes_array (or database if empty). Try to always use -1.
51
 * @param float $remise_percent_global 0
52
 * @param string $price_base_type 'HT'=Unit price parameter $pu is HT, 'TTC'=Unit price parameter $pu is TTC (HT+VAT but not Localtax. TODO Add also mode 'INCT' when pu is price HT+VAT+LT1+LT2)
53
 * @param int $info_bits Miscellaneous information on line
54
 * @param int $type 0/1=Product/service
55
 * @param Societe|string $seller Thirdparty seller (we need $seller->country_id property). Provided only if seller is the supplier, otherwise $seller will be $mysoc.
56
 * @param array $localtaxes_array Array with localtaxes info array('0'=>type1,'1'=>rate1,'2'=>type2,'3'=>rate2) (loaded by getLocalTaxesFromRate(vatrate, 0, ...) function).
57
 * @param integer $progress Situation invoices progress (value from 0 to 100, 100 by default)
58
 * @param double $multicurrency_tx Currency rate (1 by default)
59
 * @param double $pu_devise Amount in currency
60
 * @param string $multicurrency_code Value of the foreign currency if multicurrency is used ('EUR', 'USD', ...). It will be used for rounding according to currency.
61
 * @return         array [
62
 *                       0=total_ht,
63
 *                       1=total_vat, (main vat only)
64
 *                       2=total_ttc, (total_ht + main vat + local taxes)
65
 *                       3=pu_ht,
66
 *                       4=pu_vat, (main vat only)
67
 *                       5=pu_ttc,
68
 *                       6=total_ht_without_discount,
69
 *                       7=total_vat_without_discount, (main vat only)
70
 *                       8=total_ttc_without_discount, (total_ht + main vat + local taxes)
71
 *                       9=total_tax1 for total_ht,
72
 *                      10=total_tax2 for total_ht,
73
 *
74
 *                      11=pu_tax1 for pu_ht,                           !! should not be used
75
 *                      12=pu_tax2 for pu_ht,                           !! should not be used
76
 *                      13=??                                           !! should not be used
77
 *                      14=total_tax1 for total_ht_without_discount,    !! should not be used
78
 *                      15=total_tax2 for total_ht_without_discount,    !! should not be used
79
 *
80
 *                      16=multicurrency_total_ht
81
 *                      17=multicurrency_total_tva
82
 *                      18=multicurrency_total_ttc
83
 *                      19=multicurrency_pu_ht
84
 *                      20=multicurrency_pu_vat
85
 *                      21=multicurrency_pu_ttc
86
 *                      22=multicurrency_total_ht_without_discount
87
 *                      23=multicurrency_total_vat_without_discount
88
 *                      24=multicurrency_total_ttc_without_discount
89
 *                      25=multicurrency_total_tax1 for total_ht
90
 *                      26=multicurrency_total_tax2 for total_ht
91
 */
92
function calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $seller = '', $localtaxes_array = [], $progress = 100, $multicurrency_tx = 1, $pu_devise = 0, $multicurrency_code = '')
93
{
94
    global $conf, $mysoc, $db;
95
96
    $result = array();
97
98
    // Clean parameters
99
    if (empty($info_bits)) {
100
        $info_bits = 0;
101
    }
102
    if (empty($txtva)) {
103
        $txtva = 0;
104
    }
105
    if (empty($seller) || !is_object($seller)) {
106
        dol_syslog("Price.lib::calcul_price_total Warning: function is called with parameter seller that is missing", LOG_WARNING);
107
        if (!is_object($mysoc)) {   // mysoc may be not defined (during migration process)
108
            $mysoc = new Societe($db);
109
            $mysoc->setMysoc($conf);
110
        }
111
        $seller = $mysoc; // If sell is done to a customer, $seller is not provided, we use $mysoc
112
        //var_dump($seller->country_id);exit;
113
    }
114
    if (empty($localtaxes_array) || !is_array($localtaxes_array)) {
115
        dol_syslog("Price.lib::calcul_price_total Warning: function is called with parameter localtaxes_array that is missing or empty", LOG_WARNING);
116
    }
117
    if (!is_numeric($txtva)) {
118
        dol_syslog("Price.lib::calcul_price_total Warning: function was called with a parameter vat rate that is not a real numeric value. There is surely a bug.", LOG_ERR);
119
    } elseif ($txtva >= 1000) {
120
        dol_syslog("Price.lib::calcul_price_total Warning: function was called with a bad value for vat rate (should be often < 100, always < 1000). There is surely a bug.", LOG_ERR);
121
    }
122
    // Too verbose. Enable for debug only
123
    // dol_syslog("Price.lib::calcul_price_total qty=".$qty." pu=".$pu." remiserpercent_ligne=".$remise_percent_ligne." txtva=".$txtva." uselocaltax1_rate=".$uselocaltax1_rate." uselocaltax2_rate=".$uselocaltax2_rate.' remise_percent_global='.$remise_percent_global.' price_base_type='.$ice_base_type.' type='.$type.' progress='.$progress);
124
125
    $countryid = $seller->country_id;
126
127
    if (is_numeric($uselocaltax1_rate)) {
128
        $uselocaltax1_rate = (float)$uselocaltax1_rate;
129
    }
130
    if (is_numeric($uselocaltax2_rate)) {
131
        $uselocaltax2_rate = (float)$uselocaltax2_rate;
132
    }
133
134
    if ($uselocaltax1_rate < 0) {
135
        $uselocaltax1_rate = $seller->localtax1_assuj;
136
    }
137
    if ($uselocaltax2_rate < 0) {
138
        $uselocaltax2_rate = $seller->localtax2_assuj;
139
    }
140
141
    //var_dump($uselocaltax1_rate.' - '.$uselocaltax2_rate);
142
    dol_syslog('Price.lib::calcul_price_total qty=' . $qty . ' pu=' . $pu . ' remise_percent_ligne=' . $remise_percent_ligne . ' txtva=' . $txtva . ' uselocaltax1_rate=' . $uselocaltax1_rate . ' uselocaltax2_rate=' . $uselocaltax2_rate . ' remise_percent_global=' . $remise_percent_global . ' price_base_type=' . $price_base_type . ' type=' . $type . ' progress=' . $progress);
143
144
    // Now we search localtaxes information ourself (rates and types).
145
    $localtax1_type = 0;
146
    $localtax2_type = 0;
147
148
    if (is_array($localtaxes_array) && count($localtaxes_array)) {
149
        $localtax1_type = $localtaxes_array[0];
150
        $localtax1_rate = $localtaxes_array[1];
151
        $localtax2_type = $localtaxes_array[2];
152
        $localtax2_rate = $localtaxes_array[3];
153
    } else {
154
        // deprecated method. values and type for localtaxes must be provided by caller and loaded with getLocalTaxesFromRate using the full vat rate (including text code)
155
        // also, with this method, we may get several possible values (for example with localtax2 in spain), so we take the first one.
156
        dol_syslog("Price.lib::calcul_price_total search vat information using old deprecated method", LOG_WARNING);
157
158
        $sql = "SELECT taux, localtax1, localtax2, localtax1_type, localtax2_type";
159
        $sql .= " FROM " . MAIN_DB_PREFIX . "c_tva as cv";
160
        $sql .= " WHERE cv.taux = " . ((float)$txtva);
161
        $sql .= " AND cv.fk_pays = " . ((int)$countryid);
162
        $sql .= " AND cv.entity IN (" . getEntity('c_tva') . ")";
163
        $resql = $db->query($sql);
164
        if ($resql) {
165
            $obj = $db->fetch_object($resql);
166
            if ($obj) {
167
                $localtax1_rate = (float)$obj->localtax1; // Use float to force to get first numeric value when value is x:y:z
168
                $localtax2_rate = (float)$obj->localtax2; // Use float to force to get first numeric value when value is -19:-15:-9
169
                $localtax1_type = $obj->localtax1_type;
170
                $localtax2_type = $obj->localtax2_type;
171
                //var_dump($localtax1_rate.' '.$localtax2_rate.' '.$localtax1_type.' '.$localtax2_type);
172
            }
173
        } else {
174
            dol_print_error($db);
175
        }
176
    }
177
178
    // pu calculation from pu_devise if pu empty
179
    if (empty($pu) && !empty($pu_devise)) {
180
        if (!empty($multicurrency_tx)) {
181
            $pu = $pu_devise / $multicurrency_tx;
182
        } else {
183
            dol_syslog('Price.lib::calcul_price_total function called with bad parameters combination (multicurrency_tx empty when pu_devise not) ', LOG_ERR);
184
            return array();
185
        }
186
    }
187
    if ($pu === '') {
188
        $pu = 0;
189
    }
190
    // pu_devise calculation from pu
191
    if (empty($pu_devise) && !empty($multicurrency_tx)) {
192
        if (is_numeric($pu) && is_numeric($multicurrency_tx)) {
193
            $pu_devise = $pu * $multicurrency_tx;
194
        } else {
195
            dol_syslog('Price.lib::calcul_price_total function called with bad parameters combination (pu or multicurrency_tx are not numeric)', LOG_ERR);
196
            return array();
197
        }
198
    }
199
200
    // initialize total (may be HT or TTC depending on price_base_type)
201
    $tot_sans_remise = $pu * $qty * $progress / 100;
202
    $tot_avec_remise_ligne = $tot_sans_remise * (1 - ((float)$remise_percent_ligne / 100));
203
    $tot_avec_remise = $tot_avec_remise_ligne * (1 - ((float)$remise_percent_global / 100));
204
205
    // initialize result array
206
    for ($i = 0; $i <= 15; $i++) {
207
        $result[$i] = 0;
208
    }
209
210
    // if there's some localtax including vat, we calculate localtaxes (we will add later)
211
212
    // if input unit price is 'HT', we need to have the totals with main VAT for a correct calculation
213
    if ($price_base_type != 'TTC') {
214
        $tot_sans_remise_wt = price2num($tot_sans_remise * (1 + ($txtva / 100)), 'MU');
215
        $tot_avec_remise_wt = price2num($tot_avec_remise * (1 + ($txtva / 100)), 'MU');
216
        $pu_wt = price2num($pu * (1 + ($txtva / 100)), 'MU');
217
    } else {
218
        $tot_sans_remise_wt = $tot_sans_remise;
219
        $tot_avec_remise_wt = $tot_avec_remise;
220
        $pu_wt = $pu;
221
    }
222
223
    //print 'rr'.$price_base_type.'-'.$txtva.'-'.$tot_sans_remise_wt."-".$pu_wt."-".$uselocaltax1_rate."-".$localtax1_rate."-".$localtax1_type."\n";
224
225
    $localtaxes = array(0, 0, 0);
226
    $apply_tax = false;
227
    switch ($localtax1_type) {
228
        case '2':     // localtax on product or service
229
            $apply_tax = true;
230
            break;
231
        case '4':     // localtax on product
232
            if ($type == 0) {
233
                $apply_tax = true;
234
            }
235
            break;
236
        case '6':     // localtax on service
237
            if ($type == 1) {
238
                $apply_tax = true;
239
            }
240
            break;
241
    }
242
243
    if ($uselocaltax1_rate && $apply_tax) {
244
        $result[14] = price2num(($tot_sans_remise_wt * (1 + ($localtax1_rate / 100))) - $tot_sans_remise_wt, 'MT');
245
        $localtaxes[0] += $result[14];
246
247
        $result[9] = price2num(($tot_avec_remise_wt * (1 + ($localtax1_rate / 100))) - $tot_avec_remise_wt, 'MT');
248
        $localtaxes[1] += $result[9];
249
250
        $result[11] = price2num(($pu_wt * (1 + ($localtax1_rate / 100))) - $pu_wt, 'MU');
251
        $localtaxes[2] += $result[11];
252
    }
253
254
    $apply_tax = false;
255
    switch ($localtax2_type) {
256
        case '2':     // localtax on product or service
257
            $apply_tax = true;
258
            break;
259
        case '4':     // localtax on product
260
            if ($type == 0) {
261
                $apply_tax = true;
262
            }
263
            break;
264
        case '6':     // localtax on service
265
            if ($type == 1) {
266
                $apply_tax = true;
267
            }
268
            break;
269
    }
270
    if ($uselocaltax2_rate && $apply_tax) {
271
        $result[15] = price2num(($tot_sans_remise_wt * (1 + ($localtax2_rate / 100))) - $tot_sans_remise_wt, 'MT');
272
        $localtaxes[0] += $result[15];
273
274
        $result[10] = price2num(($tot_avec_remise_wt * (1 + ($localtax2_rate / 100))) - $tot_avec_remise_wt, 'MT');
275
        $localtaxes[1] += $result[10];
276
277
        $result[12] = price2num(($pu_wt * (1 + ($localtax2_rate / 100))) - $pu_wt, 'MU');
278
        $localtaxes[2] += $result[12];
279
    }
280
281
    //dol_syslog("price.lib::calcul_price_total $qty, $pu, $remise_percent_ligne, $txtva, $price_base_type $info_bits");
282
    if ($price_base_type == 'HT') {
283
        // We work to define prices using the price without tax
284
        $result[6] = price2num($tot_sans_remise, 'MT');
285
        $result[8] = price2num($tot_sans_remise * (1 + ((($info_bits & 1) ? 0 : $txtva) / 100)) + $localtaxes[0], 'MT'); // Selon TVA NPR ou non
286
        $result8bis = price2num($tot_sans_remise * (1 + ($txtva / 100)) + $localtaxes[0], 'MT'); // Si TVA consideree normal (non NPR)
287
        $result[7] = price2num((float)$result8bis - ((float)$result[6] + $localtaxes[0]), 'MT');
288
289
        $result[0] = price2num($tot_avec_remise, 'MT');
290
        $result[2] = price2num($tot_avec_remise * (1 + ((($info_bits & 1) ? 0 : $txtva) / 100)) + $localtaxes[1], 'MT'); // Selon TVA NPR ou non
291
        $result2bis = price2num($tot_avec_remise * (1 + ($txtva / 100)) + $localtaxes[1], 'MT'); // Si TVA consideree normal (non NPR)
292
        $result[1] = price2num((float)$result2bis - ((float)$result[0] + $localtaxes[1]), 'MT'); // Total VAT = TTC - (HT + localtax)
293
294
        $result[3] = price2num($pu, 'MU');
295
        $result[5] = price2num($pu * (1 + ((($info_bits & 1) ? 0 : $txtva) / 100)) + $localtaxes[2], 'MU'); // Selon TVA NPR ou non
296
        $result5bis = price2num($pu * (1 + ($txtva / 100)) + $localtaxes[2], 'MU'); // Si TVA consideree normal (non NPR)
297
        $result[4] = price2num((float)$result5bis - ((float)$result[3] + $localtaxes[2]), 'MU');
298
    } else {
299
        // We work to define prices using the price with tax
300
        $result[8] = price2num($tot_sans_remise + $localtaxes[0], 'MT');
301
        $result[6] = price2num($tot_sans_remise / (1 + ((($info_bits & 1) ? 0 : $txtva) / 100)), 'MT'); // Selon TVA NPR ou non
302
        $result6bis = price2num($tot_sans_remise / (1 + ($txtva / 100)), 'MT'); // Si TVA consideree normal (non NPR)
303
        $result[7] = price2num((float)$result[8] - ((float)$result6bis + $localtaxes[0]), 'MT');
304
305
        $result[2] = price2num((float)$tot_avec_remise + (float)$localtaxes[1], 'MT');
306
        $result[0] = price2num((float)$tot_avec_remise / (1 + ((($info_bits & 1) ? 0 : (float)$txtva) / 100)), 'MT'); // Selon TVA NPR ou non
307
        $result0bis = price2num((float)$tot_avec_remise / (1 + ((float)$txtva / 100)), 'MT'); // Si TVA consideree normal (non NPR)
308
        $result[1] = price2num((float)$result[2] - ((float)$result0bis + (float)$localtaxes[1]), 'MT'); // Total VAT = TTC - (HT + localtax)
309
310
        $result[5] = price2num($pu + $localtaxes[2], 'MU');
311
        $result[3] = price2num($pu / (1 + ((($info_bits & 1) ? 0 : $txtva) / 100)), 'MU'); // Selon TVA NPR ou non
312
        $result3bis = price2num($pu / (1 + ($txtva / 100)), 'MU'); // Si TVA consideree normal (non NPR)
313
        $result[4] = price2num((float)$result[5] - ((float)$result3bis + (float)$localtaxes[2]), 'MU');
314
    }
315
316
    // if there's some localtax without vat, we calculate localtaxes (we will add them at end)
317
318
    //If input unit price is 'TTC', we need to have the totals without main VAT for a correct calculation
319
    if ($price_base_type == 'TTC') {
320
        $tot_sans_remise = price2num($tot_sans_remise / (1 + ($txtva / 100)), 'MU');
321
        $tot_avec_remise = price2num($tot_avec_remise / (1 + ($txtva / 100)), 'MU');
322
        $pu = price2num($pu / (1 + ($txtva / 100)), 'MU');
323
    }
324
325
    $apply_tax = false;
326
    switch ($localtax1_type) {
327
        case '1':     // localtax on product or service
328
            $apply_tax = true;
329
            break;
330
        case '3':     // localtax on product
331
            if ($type == 0) {
332
                $apply_tax = true;
333
            }
334
            break;
335
        case '5':     // localtax on service
336
            if ($type == 1) {
337
                $apply_tax = true;
338
            }
339
            break;
340
    }
341
    if ($uselocaltax1_rate && $apply_tax) {
342
        $result[14] = price2num(($tot_sans_remise * (1 + ($localtax1_rate / 100))) - $tot_sans_remise, 'MT'); // amount tax1 for total_ht_without_discount
343
        $result[8] += $result[14]; // total_ttc_without_discount + tax1
344
345
        $result[9] = price2num(($tot_avec_remise * (1 + ($localtax1_rate / 100))) - $tot_avec_remise, 'MT'); // amount tax1 for total_ht
346
        $result[2] += $result[9]; // total_ttc + tax1
347
348
        $result[11] = price2num(($pu * (1 + ($localtax1_rate / 100))) - $pu, 'MU'); // amount tax1 for pu_ht
349
        $result[5] += $result[11]; // pu_ht + tax1
350
    }
351
352
    $apply_tax = false;
353
    switch ($localtax2_type) {
354
        case '1':     // localtax on product or service
355
            $apply_tax = true;
356
            break;
357
        case '3':     // localtax on product
358
            if ($type == 0) {
359
                $apply_tax = true;
360
            }
361
            break;
362
        case '5':     // localtax on service
363
            if ($type == 1) {
364
                $apply_tax = true;
365
            }
366
            break;
367
    }
368
    if ($uselocaltax2_rate && $apply_tax) {
369
        $result[15] = price2num(($tot_sans_remise * (1 + ($localtax2_rate / 100))) - $tot_sans_remise, 'MT'); // amount tax2 for total_ht_without_discount
370
        $result[8] += $result[15]; // total_ttc_without_discount + tax2
371
372
        $result[10] = price2num(($tot_avec_remise * (1 + ($localtax2_rate / 100))) - $tot_avec_remise, 'MT'); // amount tax2 for total_ht
373
        $result[2] += $result[10]; // total_ttc + tax2
374
375
        $result[12] = price2num(($pu * (1 + ($localtax2_rate / 100))) - $pu, 'MU'); // amount tax2 for pu_ht
376
        $result[5] += $result[12]; // pu_ht + tax2
377
    }
378
379
    // If rounding is not using base 10 (rare)
380
    if (getDolGlobalString('MAIN_ROUNDING_RULE_TOT')) {
381
        if ($price_base_type == 'HT') {
382
            $result[0] = price2num(round((float)$result[0] / (float)$conf->global->MAIN_ROUNDING_RULE_TOT, 0) * (float)$conf->global->MAIN_ROUNDING_RULE_TOT, 'MT');
383
            $result[1] = price2num(round((float)$result[1] / (float)$conf->global->MAIN_ROUNDING_RULE_TOT, 0) * (float)$conf->global->MAIN_ROUNDING_RULE_TOT, 'MT');
384
            $result[9] = price2num(round((float)$result[9] / (float)$conf->global->MAIN_ROUNDING_RULE_TOT, 0) * (float)$conf->global->MAIN_ROUNDING_RULE_TOT, 'MT');
385
            $result[10] = price2num(round((float)$result[10] / (float)$conf->global->MAIN_ROUNDING_RULE_TOT, 0) * (float)$conf->global->MAIN_ROUNDING_RULE_TOT, 'MT');
386
            $result[2] = price2num((float)$result[0] + (float)$result[1] + (float)$result[9] + (float)$result[10], 'MT');
387
        } else {
388
            $result[1] = price2num(round((float)$result[1] / (float)$conf->global->MAIN_ROUNDING_RULE_TOT, 0) * (float)$conf->global->MAIN_ROUNDING_RULE_TOT, 'MT');
389
            $result[2] = price2num(round((float)$result[2] / (float)$conf->global->MAIN_ROUNDING_RULE_TOT, 0) * (float)$conf->global->MAIN_ROUNDING_RULE_TOT, 'MT');
390
            $result[9] = price2num(round((float)$result[9] / (float)$conf->global->MAIN_ROUNDING_RULE_TOT, 0) * (float)$conf->global->MAIN_ROUNDING_RULE_TOT, 'MT');
391
            $result[10] = price2num(round((float)$result[10] / (float)$conf->global->MAIN_ROUNDING_RULE_TOT, 0) * (float)$conf->global->MAIN_ROUNDING_RULE_TOT, 'MT');
392
            $result[0] = price2num((float)$result[2] - (float)$result[1] - (float)$result[9] - (float)$result[10], 'MT');
393
        }
394
    }
395
396
    // Multicurrency
397
    if ($multicurrency_tx != 1) {
398
        if ($multicurrency_code) {
399
            $savMAIN_MAX_DECIMALS_UNIT = getDolGlobalString('MAIN_MAX_DECIMALS_UNIT');
400
            $savMAIN_MAX_DECIMALS_TOT = getDolGlobalString('MAIN_MAX_DECIMALS_TOT');
401
            $savMAIN_ROUNDING_RULE_TOT = getDolGlobalString('MAIN_ROUNDING_RULE_TOT');
402
403
            // Set parameter for currency accurency according to the value of $multicurrency_code (this is because a foreign currency may have different rounding rules)
404
            $keyforforeignMAIN_MAX_DECIMALS_UNIT = 'MAIN_MAX_DECIMALS_UNIT_' . $multicurrency_code;
405
            $keyforforeignMAIN_MAX_DECIMALS_TOT = 'MAIN_MAX_DECIMALS_TOT_' . $multicurrency_code;
406
            $keyforforeignMAIN_ROUNDING_RULE_TOT = 'MAIN_ROUNDING_RULE_TOT_' . $multicurrency_code;
407
            if (getDolGlobalString($keyforforeignMAIN_ROUNDING_RULE_TOT)) {
408
                $conf->global->MAIN_MAX_DECIMALS_UNIT = getDolGlobalString($keyforforeignMAIN_MAX_DECIMALS_UNIT);
409
                $conf->global->MAIN_MAX_DECIMALS_TOT = getDolGlobalString($keyforforeignMAIN_MAX_DECIMALS_TOT);
410
                $conf->global->MAIN_ROUNDING_RULE_TOT = getDolGlobalString($keyforforeignMAIN_ROUNDING_RULE_TOT);
411
            }
412
        }
413
414
        // Recall function using the multicurrency price as reference price. We must set param $multicurrency_tx to 1 to avoid infinite loop.
415
        $newresult = calcul_price_total($qty, $pu_devise, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $seller, $localtaxes_array, $progress, 1, 0, '');
416
417
        if ($multicurrency_code) {
418
            // Restore setup of currency accurency
419
            $conf->global->MAIN_MAX_DECIMALS_UNIT = $savMAIN_MAX_DECIMALS_UNIT;  // @phan-suppress-current-line PhanPossiblyUndeclaredVariable
420
            $conf->global->MAIN_MAX_DECIMALS_TOT = $savMAIN_MAX_DECIMALS_TOT;  // @phan-suppress-current-line PhanPossiblyUndeclaredVariable
421
            $conf->global->MAIN_ROUNDING_RULE_TOT = $savMAIN_ROUNDING_RULE_TOT;  // @phan-suppress-current-line PhanPossiblyUndeclaredVariable
422
        }
423
424
        $result[16] = $newresult[0];
425
        $result[17] = $newresult[1];
426
        $result[18] = $newresult[2];
427
        $result[19] = $newresult[3];
428
        $result[20] = $newresult[4];
429
        $result[21] = $newresult[5];
430
        $result[22] = $newresult[6];
431
        $result[23] = $newresult[7];
432
        $result[24] = $newresult[8];
433
        $result[25] = $newresult[9];
434
        $result[26] = $newresult[10];
435
    } else {
436
        $result[16] = $result[0];
437
        $result[17] = $result[1];
438
        $result[18] = $result[2];
439
        $result[19] = $result[3];
440
        $result[20] = $result[4];
441
        $result[21] = $result[5];
442
        $result[22] = $result[6];
443
        $result[23] = $result[7];
444
        $result[24] = $result[8];
445
        $result[25] = $result[9];
446
        $result[26] = $result[10];
447
    }
448
    dol_syslog('Price.lib::calcul_price_total MAIN_ROUNDING_RULE_TOT=' . getDolGlobalString('MAIN_ROUNDING_RULE_TOT') . ' pu=' . $pu . ' qty=' . $qty . ' price_base_type=' . $price_base_type . ' total_ht=' . $result[0] . '-total_vat=' . $result[1] . '-total_ttc=' . $result[2]);
449
450
    return $result;
451
}
452