Passed
Push — main ( f1540e...02d90d )
by Rafael
45:15
created

calcul_price_total()   F

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