2012-12-13 13:08:03 +01:00
< ? php
/* Copyright ( C ) 2002 - 2006 Rodolphe Quiedeville < rodolphe @ quiedeville . org >
* Copyright ( C ) 2006 - 2008 Laurent Destailleur < eldy @ users . sourceforge . net >
2013-09-10 17:07:38 +02:00
* Copyright ( C ) 2010 - 2013 Juanjo Menent < jmenent @ 2 byte . es >
2012-12-13 13:08:03 +01:00
* Copyright ( C ) 2012 Christophe Battarel < christophe . battarel @ altairis . fr >
2014-11-14 16:43:49 +01:00
* Copyright ( C ) 2012 Cédric Salvador < csalvador @ gpcsolutions . fr >
* Copyright ( C ) 2012 - 2014 Raphaël Doursenaud < rdoursenaud @ gpcsolutions . fr >
2024-03-09 14:48:06 +01:00
* Copyright ( C ) 2024 Frédéric France < frederic . france @ free . fr >
2025-01-18 16:15:31 +01:00
* Copyright ( C ) 2024 - 2025 MDW < mdeweerd @ users . noreply . github . com >
2012-12-13 13:08:03 +01:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
2013-01-16 15:36:08 +01:00
* the Free Software Foundation ; either version 3 of the License , or
2012-12-13 13:08:03 +01:00
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2019-09-23 21:55:30 +02:00
* along with this program . If not , see < https :// www . gnu . org / licenses />.
2012-12-13 13:08:03 +01:00
*/
/**
* \file htdocs / core / lib / price . lib . php
* \brief Library with functions to calculate prices
*/
/**
* Calculate totals ( net , vat , ... ) of a line .
* Value for localtaxX_type are '0' : local tax not applied
2015-04-11 22:51:53 +02:00
* '1' : local tax apply on products and services without vat ( localtax is calculated on amount without tax )
* '2' : local tax apply on products and services including vat ( localtax is calculated on amount + tax )
* '3' : local tax apply on products without vat ( localtax is calculated on amount without tax )
* '4' : local tax apply on products including vat ( localtax is calculated on amount + tax )
* '5' : local tax apply on services without vat ( localtax is calculated on amount without tax )
* '6' : local tax apply on services including vat ( localtax is calculated on amount + tax )
2012-12-13 13:08:03 +01:00
*
2024-03-19 15:55:46 +01:00
* @ param float $qty Quantity
2022-05-06 05:02:29 +02:00
* @ 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 )
2012-12-13 13:08:03 +01:00
* @ param float $remise_percent_ligne Discount for line
2024-08-07 01:20:43 +02:00
* @ 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 already have all tax info into $localtaxes_array )
2020-07-25 02:59:49 +02:00
* @ 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.
* @ 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.
2012-12-13 13:08:03 +01:00
* @ param float $remise_percent_global 0
2022-05-06 05:02:29 +02:00
* @ 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 )
2024-01-13 19:48:20 +01:00
* @ param int $info_bits Miscellaneous information on line
2025-01-18 16:15:31 +01:00
* @ param int < 0 , 1 > $type 0 / 1 = Product / service
2025-01-21 00:33:58 +01:00
* @ param string | Societe | null $seller Third party seller ( we need $seller -> country_id property ) . Provided only if seller is the supplier , otherwise $seller will be $mysoc .
2024-11-04 12:32:13 +01:00
* @ param array { 0 : string , 1 : int | string , 2 : string , 3 : string } | array { 0 : string , 1 : int | string , 2 : string , 3 : int | string , 4 : string , 5 : string } $localtaxes_array Array with localtaxes info array ( '0' => type1 , '1' => rate1 , '2' => type2 , '3' => rate2 ) ( loaded by getLocalTaxesFromRate ( vatrate , 0 , ... ) function ) .
* @ param float $progress Situation invoices progress ( value from 0 to 100 , 100 by default )
* @ param float $multicurrency_tx Currency rate ( 1 by default )
* @ param float $pu_devise Amount in currency
2019-12-11 17:58:14 +01:00
* @ param string $multicurrency_code Value of the foreign currency if multicurrency is used ( 'EUR' , 'USD' , ... ) . It will be used for rounding according to currency .
2024-11-04 12:32:13 +01:00
* @ return array {} | array < int < 0 , 26 > , string > Array [
2016-04-07 20:01:52 +02:00
* 0 = total_ht ,
2015-04-11 22:51:53 +02:00
* 1 = total_vat , ( main vat only )
* 2 = total_ttc , ( total_ht + main vat + local taxes )
2012-12-13 13:08:03 +01:00
* 3 = pu_ht ,
2024-11-06 15:15:55 +01:00
* 4 = pu_vat , ( main vat only ) !! should not be used
* 5 = pu_ttc , !! should not be used except if it is stored in database one day
2012-12-13 13:08:03 +01:00
* 6 = total_ht_without_discount ,
2015-04-11 22:51:53 +02:00
* 7 = total_vat_without_discount , ( main vat only )
* 8 = total_ttc_without_discount , ( total_ht + main vat + local taxes )
* 9 = total_tax1 for total_ht ,
* 10 = total_tax2 for total_ht ,
2018-01-05 01:26:57 +01:00
*
* 11 = pu_tax1 for pu_ht , !! should not be used
* 12 = pu_tax2 for pu_ht , !! should not be used
* 13 = ? ? !! should not be used
* 14 = total_tax1 for total_ht_without_discount , !! should not be used
* 15 = total_tax2 for total_ht_without_discount , !! should not be used
2017-09-13 19:27:21 +02:00
*
2016-01-18 19:45:27 +01:00
* 16 = multicurrency_total_ht
* 17 = multicurrency_total_tva
* 18 = multicurrency_total_ttc
2016-12-10 22:07:05 +01:00
* 19 = multicurrency_pu_ht
2018-01-05 01:26:57 +01:00
* 20 = multicurrency_pu_vat
* 21 = multicurrency_pu_ttc
* 22 = multicurrency_total_ht_without_discount
* 23 = multicurrency_total_vat_without_discount
* 24 = multicurrency_total_ttc_without_discount
* 25 = multicurrency_total_tax1 for total_ht
* 26 = multicurrency_total_tax2 for total_ht
2024-11-04 12:32:13 +01:00
*
* @ phan - suppress PhanTypeMismatchDefault
2012-12-13 13:08:03 +01:00
*/
2025-01-21 00:33:58 +01:00
function calcul_price_total ( $qty , $pu , $remise_percent_ligne , $txtva , $uselocaltax1_rate , $uselocaltax2_rate , $remise_percent_global , $price_base_type , $info_bits , $type , $seller = null , $localtaxes_array = [], $progress = 100 , $multicurrency_tx = 1 , $pu_devise = 0 , $multicurrency_code = '' ) // @phpstan-ignore-line
2012-12-13 13:08:03 +01:00
{
2019-12-16 13:06:25 +01:00
global $conf , $mysoc , $db ;
2012-12-13 13:08:03 +01:00
2019-12-16 13:06:25 +01:00
$result = array ();
2012-12-13 13:08:03 +01:00
2013-08-01 18:01:25 +02:00
// Clean parameters
2021-02-23 22:03:23 +01:00
if ( empty ( $info_bits )) {
$info_bits = 0 ;
}
if ( empty ( $txtva )) {
$txtva = 0 ;
}
if ( empty ( $seller ) || ! is_object ( $seller )) {
2016-10-30 17:42:34 +01:00
dol_syslog ( " Price.lib::calcul_price_total Warning: function is called with parameter seller that is missing " , LOG_WARNING );
2021-02-23 22:03:23 +01:00
if ( ! is_object ( $mysoc )) { // mysoc may be not defined (during migration process)
2019-12-16 13:06:25 +01:00
$mysoc = new Societe ( $db );
2013-03-09 18:55:57 +01:00
$mysoc -> setMysoc ( $conf );
2012-12-13 13:08:03 +01:00
}
2019-12-16 13:06:25 +01:00
$seller = $mysoc ; // If sell is done to a customer, $seller is not provided, we use $mysoc
2012-12-13 13:08:03 +01:00
//var_dump($seller->country_id);exit;
}
2020-11-27 14:24:15 +01:00
if ( empty ( $localtaxes_array ) || ! is_array ( $localtaxes_array )) {
2020-12-18 14:40:45 +01:00
dol_syslog ( " Price.lib::calcul_price_total Warning: function is called with parameter localtaxes_array that is missing or empty " , LOG_WARNING );
2013-09-18 16:46:54 +02:00
}
2020-11-27 14:24:15 +01:00
if ( ! is_numeric ( $txtva )) {
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 );
} elseif ( $txtva >= 1000 ) {
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 );
}
2013-05-31 21:33:48 +02:00
// Too verbose. Enable for debug only
2024-03-09 14:48:06 +01:00
// 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);
2013-09-18 16:46:54 +02:00
2019-12-16 13:06:25 +01:00
$countryid = $seller -> country_id ;
2017-09-13 19:27:21 +02:00
2021-02-23 22:03:23 +01:00
if ( is_numeric ( $uselocaltax1_rate )) {
$uselocaltax1_rate = ( float ) $uselocaltax1_rate ;
}
if ( is_numeric ( $uselocaltax2_rate )) {
$uselocaltax2_rate = ( float ) $uselocaltax2_rate ;
}
2017-09-13 19:27:21 +02:00
2021-02-23 22:03:23 +01:00
if ( $uselocaltax1_rate < 0 ) {
$uselocaltax1_rate = $seller -> localtax1_assuj ;
}
if ( $uselocaltax2_rate < 0 ) {
$uselocaltax2_rate = $seller -> localtax2_assuj ;
}
2012-12-13 13:08:03 +01:00
2018-01-05 01:26:57 +01:00
//var_dump($uselocaltax1_rate.' - '.$uselocaltax2_rate);
2016-01-07 09:37:04 +01:00
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 );
2015-01-18 21:04:39 +01:00
2020-10-31 14:32:18 +01:00
// Now we search localtaxes information ourself (rates and types).
2019-12-16 13:06:25 +01:00
$localtax1_type = 0 ;
$localtax2_type = 0 ;
2024-11-04 12:32:13 +01:00
$localtax1_rate = 1000 ; // For static analysis, exaggerated value to help detect bugs
$localtax2_rate = 1000 ; // For static analysis, exaggerated value to help detect bugs
2013-09-18 16:46:54 +02:00
2020-12-21 17:56:31 +01:00
if ( is_array ( $localtaxes_array ) && count ( $localtaxes_array )) {
2013-09-11 10:05:01 +02:00
$localtax1_type = $localtaxes_array [ 0 ];
$localtax1_rate = $localtaxes_array [ 1 ];
$localtax2_type = $localtaxes_array [ 2 ];
$localtax2_rate = $localtaxes_array [ 3 ];
2020-12-06 17:59:49 +01:00
} else {
// deprecated method. values and type for localtaxes must be provided by caller and loaded with getLocalTaxesFromRate using the full vat rate (including text code)
// also, with this method, we may get several possible values (for example with localtax2 in spain), so we take the first one.
2020-10-31 14:32:18 +01:00
dol_syslog ( " Price.lib::calcul_price_total search vat information using old deprecated method " , LOG_WARNING );
2019-04-30 18:11:35 +02:00
2020-10-31 14:32:18 +01:00
$sql = " SELECT taux, localtax1, localtax2, localtax1_type, localtax2_type " ;
2019-12-16 13:06:25 +01:00
$sql .= " FROM " . MAIN_DB_PREFIX . " c_tva as cv " ;
2021-03-30 17:53:25 +02:00
$sql .= " WHERE cv.taux = " . (( float ) $txtva );
$sql .= " AND cv.fk_pays = " . (( int ) $countryid );
2023-06-06 04:56:57 +02:00
$sql .= " AND cv.entity IN ( " . getEntity ( 'c_tva' ) . " ) " ;
2013-09-10 17:07:38 +02:00
$resql = $db -> query ( $sql );
2021-02-23 22:03:23 +01:00
if ( $resql ) {
2013-09-10 17:07:38 +02:00
$obj = $db -> fetch_object ( $resql );
2021-02-23 22:03:23 +01:00
if ( $obj ) {
2021-10-25 22:07:31 +02:00
$localtax1_rate = ( float ) $obj -> localtax1 ; // Use float to force to get first numeric value when value is x:y:z
$localtax2_rate = ( float ) $obj -> localtax2 ; // Use float to force to get first numeric value when value is -19:-15:-9
2019-12-16 13:06:25 +01:00
$localtax1_type = $obj -> localtax1_type ;
$localtax2_type = $obj -> localtax2_type ;
2020-12-06 17:59:49 +01:00
//var_dump($localtax1_rate.' '.$localtax2_rate.' '.$localtax1_type.' '.$localtax2_type);
2013-09-10 17:07:38 +02:00
}
2021-02-23 22:03:23 +01:00
} else {
dol_print_error ( $db );
}
2012-12-13 13:08:03 +01:00
}
2017-09-13 19:27:21 +02:00
2016-12-10 19:54:16 +01:00
// pu calculation from pu_devise if pu empty
2018-04-27 09:18:25 +02:00
if ( empty ( $pu ) && ! empty ( $pu_devise )) {
2021-02-23 22:03:23 +01:00
if ( ! empty ( $multicurrency_tx )) {
$pu = $pu_devise / $multicurrency_tx ;
} else {
2018-04-27 09:18:25 +02:00
dol_syslog ( 'Price.lib::calcul_price_total function called with bad parameters combination (multicurrency_tx empty when pu_devise not) ' , LOG_ERR );
return array ();
}
2017-09-13 19:27:21 +02:00
}
2021-02-23 22:03:23 +01:00
if ( $pu === '' ) {
$pu = 0 ;
}
2018-04-27 09:18:25 +02:00
// pu_devise calculation from pu
if ( empty ( $pu_devise ) && ! empty ( $multicurrency_tx )) {
2021-02-23 22:03:23 +01:00
if ( is_numeric ( $pu ) && is_numeric ( $multicurrency_tx )) {
$pu_devise = $pu * $multicurrency_tx ;
} else {
2018-04-27 09:18:25 +02:00
dol_syslog ( 'Price.lib::calcul_price_total function called with bad parameters combination (pu or multicurrency_tx are not numeric)' , LOG_ERR );
return array ();
}
2016-12-10 19:54:16 +01:00
}
2017-09-13 19:27:21 +02:00
2012-12-13 13:08:03 +01:00
// initialize total (may be HT or TTC depending on price_base_type)
2024-11-06 15:15:55 +01:00
$tot_sans_remise = $pu * $qty * ( $progress / 100 );
2022-11-25 23:59:06 +01:00
$tot_avec_remise_ligne = $tot_sans_remise * ( 1 - (( float ) $remise_percent_ligne / 100 ));
$tot_avec_remise = $tot_avec_remise_ligne * ( 1 - (( float ) $remise_percent_global / 100 ));
2012-12-13 13:08:03 +01:00
2015-04-11 22:51:53 +02:00
// initialize result array
2021-02-23 22:03:23 +01:00
for ( $i = 0 ; $i <= 15 ; $i ++ ) {
$result [ $i ] = 0 ;
}
2012-12-13 13:08:03 +01:00
// if there's some localtax including vat, we calculate localtaxes (we will add later)
2015-04-11 22:51:53 +02:00
2020-10-31 14:32:18 +01:00
// if input unit price is 'HT', we need to have the totals with main VAT for a correct calculation
2021-02-23 22:03:23 +01:00
if ( $price_base_type != 'TTC' ) {
2024-11-06 15:15:55 +01:00
$tot_sans_remise_withvat = price2num ( $tot_sans_remise * ( 1 + ( $txtva / 100 )), 'MU' );
$tot_avec_remise_withvat = price2num ( $tot_avec_remise * ( 1 + ( $txtva / 100 )), 'MU' );
$tot_sans_remise_withoutvat = $tot_sans_remise ;
$tot_avec_remise_withoutvat = $tot_avec_remise ;
$pu_withouttax = $pu ;
$pu_withmainvat = price2num ( $pu * ( 1 + ( $txtva / 100 )), 'MU' );
2020-10-31 14:32:18 +01:00
} else {
2024-11-06 15:15:55 +01:00
$tot_sans_remise_withvat = $tot_sans_remise ;
$tot_avec_remise_withvat = $tot_avec_remise ;
$tot_sans_remise_withoutvat = price2num ( $tot_sans_remise / ( 1 + ( $txtva / 100 )), 'MU' );
$tot_avec_remise_withoutvat = price2num ( $tot_avec_remise / ( 1 + ( $txtva / 100 )), 'MU' );
$pu_withouttax = price2num ( $pu / ( 1 + ( $txtva / 100 )), 'MU' );
$pu_withmainvat = $pu ;
2020-10-31 14:32:18 +01:00
}
2015-04-13 13:08:46 +02:00
2024-11-06 15:15:55 +01:00
//print 'rr'.$price_base_type.'-'.$txtva.'-'.$tot_sans_remise_withvat."-".$pu_withmainvat."-".$uselocaltax1_rate."-".$localtax1_rate."-".$localtax1_type."\n";
2015-04-13 13:08:46 +02:00
2020-10-31 14:32:18 +01:00
$localtaxes = array ( 0 , 0 , 0 );
$apply_tax = false ;
switch ( $localtax1_type ) {
case '2' : // localtax on product or service
$apply_tax = true ;
break ;
case '4' : // localtax on product
2021-02-23 22:03:23 +01:00
if ( $type == 0 ) {
$apply_tax = true ;
}
2020-10-31 14:32:18 +01:00
break ;
case '6' : // localtax on service
2021-02-23 22:03:23 +01:00
if ( $type == 1 ) {
$apply_tax = true ;
}
2020-10-31 14:32:18 +01:00
break ;
}
if ( $uselocaltax1_rate && $apply_tax ) {
2024-11-06 15:15:55 +01:00
$result [ 14 ] = price2num (( $tot_sans_remise_withvat * ( 1 + ( $localtax1_rate / 100 ))) - $tot_sans_remise_withvat , 'MT' );
2021-02-23 22:03:23 +01:00
$localtaxes [ 0 ] += $result [ 14 ];
2012-12-13 13:08:03 +01:00
2024-11-06 15:15:55 +01:00
$result [ 9 ] = price2num (( $tot_avec_remise_withvat * ( 1 + ( $localtax1_rate / 100 ))) - $tot_avec_remise_withvat , 'MT' );
2021-02-23 22:03:23 +01:00
$localtaxes [ 1 ] += $result [ 9 ];
2012-12-13 13:08:03 +01:00
2024-11-06 15:15:55 +01:00
$result [ 11 ] = price2num (( $pu_withmainvat * ( 1 + ( $localtax1_rate / 100 ))) - $pu_withmainvat , 'MU' );
2021-02-23 22:03:23 +01:00
$localtaxes [ 2 ] += $result [ 11 ];
2020-10-31 14:32:18 +01:00
}
$apply_tax = false ;
switch ( $localtax2_type ) {
case '2' : // localtax on product or service
$apply_tax = true ;
break ;
case '4' : // localtax on product
2021-02-23 22:03:23 +01:00
if ( $type == 0 ) {
$apply_tax = true ;
}
2020-10-31 14:32:18 +01:00
break ;
case '6' : // localtax on service
2021-02-23 22:03:23 +01:00
if ( $type == 1 ) {
$apply_tax = true ;
}
2020-10-31 14:32:18 +01:00
break ;
}
if ( $uselocaltax2_rate && $apply_tax ) {
2024-11-06 15:15:55 +01:00
$result [ 15 ] = price2num (( $tot_sans_remise_withvat * ( 1 + ( $localtax2_rate / 100 ))) - $tot_sans_remise_withvat , 'MT' );
2021-02-23 22:03:23 +01:00
$localtaxes [ 0 ] += $result [ 15 ];
2012-12-13 13:08:03 +01:00
2024-11-06 15:15:55 +01:00
$result [ 10 ] = price2num (( $tot_avec_remise_withvat * ( 1 + ( $localtax2_rate / 100 ))) - $tot_avec_remise_withvat , 'MT' );
2021-02-23 22:03:23 +01:00
$localtaxes [ 1 ] += $result [ 10 ];
2012-12-13 13:08:03 +01:00
2024-11-06 15:15:55 +01:00
$result [ 12 ] = price2num (( $pu_withmainvat * ( 1 + ( $localtax2_rate / 100 ))) - $pu_withmainvat , 'MU' );
2021-02-23 22:03:23 +01:00
$localtaxes [ 2 ] += $result [ 12 ];
2020-10-31 14:32:18 +01:00
}
2012-12-13 13:08:03 +01:00
//dol_syslog("price.lib::calcul_price_total $qty, $pu, $remise_percent_ligne, $txtva, $price_base_type $info_bits");
2021-02-23 22:03:23 +01:00
if ( $price_base_type == 'HT' ) {
2012-12-13 13:08:03 +01:00
// We work to define prices using the price without tax
$result [ 6 ] = price2num ( $tot_sans_remise , 'MT' );
2019-12-16 13:06:25 +01:00
$result [ 8 ] = price2num ( $tot_sans_remise * ( 1 + ((( $info_bits & 1 ) ? 0 : $txtva ) / 100 )) + $localtaxes [ 0 ], 'MT' ); // Selon TVA NPR ou non
2024-01-13 19:48:20 +01:00
$result8bis = price2num ( $tot_sans_remise * ( 1 + ( $txtva / 100 )) + $localtaxes [ 0 ], 'MT' ); // Si TVA consideree normal (non NPR)
2024-03-23 01:12:39 +01:00
$result [ 7 ] = price2num (( float ) $result8bis - (( float ) $result [ 6 ] + $localtaxes [ 0 ]), 'MT' );
2012-12-13 13:08:03 +01:00
$result [ 0 ] = price2num ( $tot_avec_remise , 'MT' );
2019-12-16 13:06:25 +01:00
$result [ 2 ] = price2num ( $tot_avec_remise * ( 1 + ((( $info_bits & 1 ) ? 0 : $txtva ) / 100 )) + $localtaxes [ 1 ], 'MT' ); // Selon TVA NPR ou non
2024-01-13 19:48:20 +01:00
$result2bis = price2num ( $tot_avec_remise * ( 1 + ( $txtva / 100 )) + $localtaxes [ 1 ], 'MT' ); // Si TVA consideree normal (non NPR)
2024-03-23 01:12:39 +01:00
$result [ 1 ] = price2num (( float ) $result2bis - (( float ) $result [ 0 ] + $localtaxes [ 1 ]), 'MT' ); // Total VAT = TTC - (HT + localtax)
2012-12-13 13:08:03 +01:00
$result [ 3 ] = price2num ( $pu , 'MU' );
2019-12-16 13:06:25 +01:00
$result [ 5 ] = price2num ( $pu * ( 1 + ((( $info_bits & 1 ) ? 0 : $txtva ) / 100 )) + $localtaxes [ 2 ], 'MU' ); // Selon TVA NPR ou non
2024-01-13 19:48:20 +01:00
$result5bis = price2num ( $pu * ( 1 + ( $txtva / 100 )) + $localtaxes [ 2 ], 'MU' ); // Si TVA consideree normal (non NPR)
2024-03-23 01:12:39 +01:00
$result [ 4 ] = price2num (( float ) $result5bis - (( float ) $result [ 3 ] + $localtaxes [ 2 ]), 'MU' );
2020-05-21 15:05:19 +02:00
} else {
2012-12-13 13:08:03 +01:00
// We work to define prices using the price with tax
$result [ 8 ] = price2num ( $tot_sans_remise + $localtaxes [ 0 ], 'MT' );
2019-12-16 13:06:25 +01:00
$result [ 6 ] = price2num ( $tot_sans_remise / ( 1 + ((( $info_bits & 1 ) ? 0 : $txtva ) / 100 )), 'MT' ); // Selon TVA NPR ou non
2024-01-13 19:48:20 +01:00
$result6bis = price2num ( $tot_sans_remise / ( 1 + ( $txtva / 100 )), 'MT' ); // Si TVA consideree normal (non NPR)
2024-03-23 01:12:39 +01:00
$result [ 7 ] = price2num (( float ) $result [ 8 ] - (( float ) $result6bis + $localtaxes [ 0 ]), 'MT' );
2012-12-13 13:08:03 +01:00
2024-03-21 22:10:24 +01:00
$result [ 2 ] = price2num (( float ) $tot_avec_remise + ( float ) $localtaxes [ 1 ], 'MT' );
$result [ 0 ] = price2num (( float ) $tot_avec_remise / ( 1 + ((( $info_bits & 1 ) ? 0 : ( float ) $txtva ) / 100 )), 'MT' ); // Selon TVA NPR ou non
$result0bis = price2num (( float ) $tot_avec_remise / ( 1 + (( float ) $txtva / 100 )), 'MT' ); // Si TVA consideree normal (non NPR)
$result [ 1 ] = price2num (( float ) $result [ 2 ] - (( float ) $result0bis + ( float ) $localtaxes [ 1 ]), 'MT' ); // Total VAT = TTC - (HT + localtax)
2012-12-13 13:08:03 +01:00
2015-04-11 22:51:53 +02:00
$result [ 5 ] = price2num ( $pu + $localtaxes [ 2 ], 'MU' );
2019-12-16 13:06:25 +01:00
$result [ 3 ] = price2num ( $pu / ( 1 + ((( $info_bits & 1 ) ? 0 : $txtva ) / 100 )), 'MU' ); // Selon TVA NPR ou non
2024-01-13 19:48:20 +01:00
$result3bis = price2num ( $pu / ( 1 + ( $txtva / 100 )), 'MU' ); // Si TVA consideree normal (non NPR)
2024-03-21 22:10:24 +01:00
$result [ 4 ] = price2num (( float ) $result [ 5 ] - (( float ) $result3bis + ( float ) $localtaxes [ 2 ]), 'MU' );
2012-12-13 13:08:03 +01:00
}
// if there's some localtax without vat, we calculate localtaxes (we will add them at end)
$apply_tax = false ;
2020-10-31 14:32:18 +01:00
switch ( $localtax1_type ) {
case '1' : // localtax on product or service
$apply_tax = true ;
break ;
case '3' : // localtax on product
2021-02-23 22:03:23 +01:00
if ( $type == 0 ) {
$apply_tax = true ;
}
2020-10-31 14:32:18 +01:00
break ;
case '5' : // localtax on service
2021-02-23 22:03:23 +01:00
if ( $type == 1 ) {
$apply_tax = true ;
}
2020-10-31 14:32:18 +01:00
break ;
}
if ( $uselocaltax1_rate && $apply_tax ) {
2024-11-06 15:15:55 +01:00
$result [ 14 ] = price2num (( $tot_sans_remise_withoutvat * ( 1 + ( $localtax1_rate / 100 ))) - $tot_sans_remise_withoutvat , 'MT' ); // amount tax1 for total_ht_without_discount
2021-02-23 22:03:23 +01:00
$result [ 8 ] += $result [ 14 ]; // total_ttc_without_discount + tax1
2012-12-13 13:08:03 +01:00
2024-11-06 15:15:55 +01:00
$result [ 9 ] = price2num (( $tot_avec_remise_withoutvat * ( 1 + ( $localtax1_rate / 100 ))) - $tot_avec_remise_withoutvat , 'MT' ); // amount tax1 for total_ht
2021-02-23 22:03:23 +01:00
$result [ 2 ] += $result [ 9 ]; // total_ttc + tax1
2012-12-13 13:08:03 +01:00
2024-11-06 15:15:55 +01:00
$result [ 11 ] = price2num (( $pu_withouttax * ( 1 + ( $localtax1_rate / 100 ))) - $pu_withouttax , 'MU' ); // amount tax1 for pu_ht
2021-02-23 22:03:23 +01:00
$result [ 5 ] += $result [ 11 ]; // pu_ht + tax1
2020-10-31 14:32:18 +01:00
}
$apply_tax = false ;
switch ( $localtax2_type ) {
case '1' : // localtax on product or service
$apply_tax = true ;
break ;
case '3' : // localtax on product
2021-02-23 22:03:23 +01:00
if ( $type == 0 ) {
$apply_tax = true ;
}
2020-10-31 14:32:18 +01:00
break ;
case '5' : // localtax on service
2021-02-23 22:03:23 +01:00
if ( $type == 1 ) {
$apply_tax = true ;
}
2020-10-31 14:32:18 +01:00
break ;
}
if ( $uselocaltax2_rate && $apply_tax ) {
2024-11-06 15:15:55 +01:00
$result [ 15 ] = price2num (( $tot_sans_remise_withoutvat * ( 1 + ( $localtax2_rate / 100 ))) - $tot_sans_remise_withoutvat , 'MT' ); // amount tax2 for total_ht_without_discount
2021-02-23 22:03:23 +01:00
$result [ 8 ] += $result [ 15 ]; // total_ttc_without_discount + tax2
2012-12-13 13:08:03 +01:00
2024-11-06 15:15:55 +01:00
$result [ 10 ] = price2num (( $tot_avec_remise_withoutvat * ( 1 + ( $localtax2_rate / 100 ))) - $tot_avec_remise_withoutvat , 'MT' ); // amount tax2 for total_ht
2021-02-23 22:03:23 +01:00
$result [ 2 ] += $result [ 10 ]; // total_ttc + tax2
2012-12-13 13:08:03 +01:00
2024-11-06 15:15:55 +01:00
$result [ 12 ] = price2num (( $pu_withouttax * ( 1 + ( $localtax2_rate / 100 ))) - $pu_withouttax , 'MU' ); // amount tax2 for pu_ht
2021-02-23 22:03:23 +01:00
$result [ 5 ] += $result [ 12 ]; // pu_ht + tax2
2020-10-31 14:32:18 +01:00
}
2012-12-13 13:08:03 +01:00
// If rounding is not using base 10 (rare)
2023-11-27 11:39:32 +01:00
if ( getDolGlobalString ( 'MAIN_ROUNDING_RULE_TOT' )) {
2021-02-23 22:03:23 +01:00
if ( $price_base_type == 'HT' ) {
2024-03-23 01:12:39 +01:00
$result [ 0 ] = price2num ( round (( float ) $result [ 0 ] / ( float ) $conf -> global -> MAIN_ROUNDING_RULE_TOT , 0 ) * ( float ) $conf -> global -> MAIN_ROUNDING_RULE_TOT , 'MT' );
$result [ 1 ] = price2num ( round (( float ) $result [ 1 ] / ( float ) $conf -> global -> MAIN_ROUNDING_RULE_TOT , 0 ) * ( float ) $conf -> global -> MAIN_ROUNDING_RULE_TOT , 'MT' );
$result [ 9 ] = price2num ( round (( float ) $result [ 9 ] / ( float ) $conf -> global -> MAIN_ROUNDING_RULE_TOT , 0 ) * ( float ) $conf -> global -> MAIN_ROUNDING_RULE_TOT , 'MT' );
$result [ 10 ] = price2num ( round (( float ) $result [ 10 ] / ( float ) $conf -> global -> MAIN_ROUNDING_RULE_TOT , 0 ) * ( float ) $conf -> global -> MAIN_ROUNDING_RULE_TOT , 'MT' );
2024-03-21 22:10:24 +01:00
$result [ 2 ] = price2num (( float ) $result [ 0 ] + ( float ) $result [ 1 ] + ( float ) $result [ 9 ] + ( float ) $result [ 10 ], 'MT' );
2020-05-21 15:05:19 +02:00
} else {
2024-03-23 01:12:39 +01:00
$result [ 1 ] = price2num ( round (( float ) $result [ 1 ] / ( float ) $conf -> global -> MAIN_ROUNDING_RULE_TOT , 0 ) * ( float ) $conf -> global -> MAIN_ROUNDING_RULE_TOT , 'MT' );
$result [ 2 ] = price2num ( round (( float ) $result [ 2 ] / ( float ) $conf -> global -> MAIN_ROUNDING_RULE_TOT , 0 ) * ( float ) $conf -> global -> MAIN_ROUNDING_RULE_TOT , 'MT' );
$result [ 9 ] = price2num ( round (( float ) $result [ 9 ] / ( float ) $conf -> global -> MAIN_ROUNDING_RULE_TOT , 0 ) * ( float ) $conf -> global -> MAIN_ROUNDING_RULE_TOT , 'MT' );
$result [ 10 ] = price2num ( round (( float ) $result [ 10 ] / ( float ) $conf -> global -> MAIN_ROUNDING_RULE_TOT , 0 ) * ( float ) $conf -> global -> MAIN_ROUNDING_RULE_TOT , 'MT' );
2024-03-21 22:10:24 +01:00
$result [ 0 ] = price2num (( float ) $result [ 2 ] - ( float ) $result [ 1 ] - ( float ) $result [ 9 ] - ( float ) $result [ 10 ], 'MT' );
2012-12-13 13:08:03 +01:00
}
}
2017-09-13 19:27:21 +02:00
2016-01-26 22:18:31 +01:00
// Multicurrency
2021-02-23 22:03:23 +01:00
if ( $multicurrency_tx != 1 ) {
2019-12-11 17:58:14 +01:00
if ( $multicurrency_code ) {
2024-01-05 04:18:53 +01:00
$savMAIN_MAX_DECIMALS_UNIT = getDolGlobalString ( 'MAIN_MAX_DECIMALS_UNIT' );
$savMAIN_MAX_DECIMALS_TOT = getDolGlobalString ( 'MAIN_MAX_DECIMALS_TOT' );
$savMAIN_ROUNDING_RULE_TOT = getDolGlobalString ( 'MAIN_ROUNDING_RULE_TOT' );
2019-12-11 17:58:14 +01:00
// Set parameter for currency accurency according to the value of $multicurrency_code (this is because a foreign currency may have different rounding rules)
$keyforforeignMAIN_MAX_DECIMALS_UNIT = 'MAIN_MAX_DECIMALS_UNIT_' . $multicurrency_code ;
$keyforforeignMAIN_MAX_DECIMALS_TOT = 'MAIN_MAX_DECIMALS_TOT_' . $multicurrency_code ;
$keyforforeignMAIN_ROUNDING_RULE_TOT = 'MAIN_ROUNDING_RULE_TOT_' . $multicurrency_code ;
2024-05-10 11:53:09 +02:00
if ( getDolGlobalString ( $keyforforeignMAIN_ROUNDING_RULE_TOT )) {
2024-01-05 04:18:53 +01:00
$conf -> global -> MAIN_MAX_DECIMALS_UNIT = getDolGlobalString ( $keyforforeignMAIN_MAX_DECIMALS_UNIT );
$conf -> global -> MAIN_MAX_DECIMALS_TOT = getDolGlobalString ( $keyforforeignMAIN_MAX_DECIMALS_TOT );
$conf -> global -> MAIN_ROUNDING_RULE_TOT = getDolGlobalString ( $keyforforeignMAIN_ROUNDING_RULE_TOT );
2019-12-11 17:58:14 +01:00
}
}
2022-01-10 03:24:01 +01:00
// Recall function using the multicurrency price as reference price. We must set param $multicurrency_tx to 1 to avoid infinite loop.
2024-11-04 12:32:13 +01:00
$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 , '' ); // pu_devise is normally arg#15, here as arg#2 @phan-suppress-current-line PhanPluginSuspiciousParamPosition
2019-12-11 17:58:14 +01:00
if ( $multicurrency_code ) {
// Restore setup of currency accurency
2024-05-10 11:53:09 +02:00
$conf -> global -> MAIN_MAX_DECIMALS_UNIT = $savMAIN_MAX_DECIMALS_UNIT ; // @phan-suppress-current-line PhanPossiblyUndeclaredVariable
$conf -> global -> MAIN_MAX_DECIMALS_TOT = $savMAIN_MAX_DECIMALS_TOT ; // @phan-suppress-current-line PhanPossiblyUndeclaredVariable
$conf -> global -> MAIN_ROUNDING_RULE_TOT = $savMAIN_ROUNDING_RULE_TOT ; // @phan-suppress-current-line PhanPossiblyUndeclaredVariable
2019-12-11 17:58:14 +01:00
}
2017-09-13 19:27:21 +02:00
$result [ 16 ] = $newresult [ 0 ];
$result [ 17 ] = $newresult [ 1 ];
$result [ 18 ] = $newresult [ 2 ];
$result [ 19 ] = $newresult [ 3 ];
$result [ 20 ] = $newresult [ 4 ];
$result [ 21 ] = $newresult [ 5 ];
$result [ 22 ] = $newresult [ 6 ];
$result [ 23 ] = $newresult [ 7 ];
$result [ 24 ] = $newresult [ 8 ];
$result [ 25 ] = $newresult [ 9 ];
$result [ 26 ] = $newresult [ 10 ];
2020-05-21 15:05:19 +02:00
} else {
2017-09-13 21:50:14 +02:00
$result [ 16 ] = $result [ 0 ];
$result [ 17 ] = $result [ 1 ];
$result [ 18 ] = $result [ 2 ];
$result [ 19 ] = $result [ 3 ];
$result [ 20 ] = $result [ 4 ];
$result [ 21 ] = $result [ 5 ];
$result [ 22 ] = $result [ 6 ];
$result [ 23 ] = $result [ 7 ];
$result [ 24 ] = $result [ 8 ];
2024-05-23 15:47:25 +02:00
$result [ 25 ] = $result [ 9 ];
$result [ 26 ] = $result [ 10 ];
2017-09-13 20:48:24 +02:00
}
2024-03-09 14:48:06 +01:00
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 ]);
2012-12-13 13:08:03 +01:00
return $result ;
}