From c84d4c53e5f785b413d366b46ce44bde638aa94b Mon Sep 17 00:00:00 2001 From: atm-GregM <85485123+atm-GregM@users.noreply.github.com> Date: Wed, 17 Sep 2025 14:19:36 +0200 Subject: [PATCH 1/2] New develop import export product customer price (#35349) * NEW import/export product customer price * back travis and more * back travis 2 --- htdocs/core/modules/modProduct.class.php | 49 ++++++++++++++++++++++++ htdocs/langs/fr_FR/products.lang | 5 +++ 2 files changed, 54 insertions(+) diff --git a/htdocs/core/modules/modProduct.class.php b/htdocs/core/modules/modProduct.class.php index baa6e2350eb..77f7e4909ed 100644 --- a/htdocs/core/modules/modProduct.class.php +++ b/htdocs/core/modules/modProduct.class.php @@ -981,6 +981,55 @@ class modProduct extends DolibarrModules 'pr.date_price' => '2020-12-31'); } + + if (getDolGlobalInt('PRODUIT_CUSTOMER_PRICES')) { + $r++; + $this->import_code[$r] = $this->rights_class.'_productcustomerprice'; + $this->import_label[$r] = "ProductsPricePerCustomer"; // Translation key + $this->import_icon[$r] = $this->picto; + $this->import_entities_array[$r] = array(); // We define here only fields that use another icon that the one defined into import_icon + $this->import_tables_array[$r] = array('sp' => $this->db->prefix().'product_customer_price', 'extra' => $this->db->prefix().'product_customer_price_extrafields'); + $this->import_tables_creator_array[$r] = array('sp' => 'fk_user'); // Fields to store import user id + $this->import_fields_array[$r] = array( + 'sp.fk_product' => "Products*", + 'sp.fk_soc' => "Customer*", + 'sp.ref_customer' => "RefCustomer", + 'sp.date_begin' => "AppliedPricesFrom*", + 'sp.date_end' => "AppliedPricesTo", + 'sp.tva_tx' => "VATRate*", + 'sp.default_vat_code' => 'PriceVATCode', + 'sp.discount_percent' => 'Discount', + 'sp.price_base_type' => "PriceBase*", + 'sp.price' => "SellingUnitPriceHT*", + 'sp.price_min' => "SellingUnitMinPriceHT", + 'sp.price_ttc' => "SellingUnitPriceTTC", + 'sp.price_min_ttc' => "SellingUnitMinPriceTTC", + 'sp.datec' => "DateCreation"); + + $this->import_convertvalue_array[$r] = array( + 'sp.fk_soc' => array('rule' => 'fetchidfromref', 'classfile' => '/societe/class/societe.class.php', 'class' => 'Societe', 'method' => 'fetch', 'element' => 'ThirdParty'), + 'sp.fk_product' => array('rule' => 'fetchidfromref', 'classfile' => '/product/class/product.class.php', 'class' => 'Product', 'method' => 'fetch', 'element' => 'Product') + ); + + $this->import_examplevalues_array[$r] = array_merge($import_sample, $import_extrafield_sample); + $this->import_examplevalues_array[$r] = array( + 'sp.fk_product' => "ref:PRODUCT_REF or id:123456", + 'sp.fk_soc' => "My Supplier", + 'sp.ref_customer' => "XYZ-F123456", + 'sp.date_begin' => "2025-06-30", + 'sp.date_end' => "2027-06-30", + 'sp.tva_tx' => '20', + 'sp.default_vat_code' => '5', + 'sp.discount_percent' => '30', + 'sp.price_base_type'=> 'HT (for excl tax) or TTC (for inc tax)', + 'sp.price' => "100", + 'sp.price_min' => "80", + 'sp.price_ttc' => "120", + 'sp.price_min_ttc' => "96", + 'sp.datec' => "2025-09-30" + ); + } + if (getDolGlobalInt('MAIN_MULTILANGS')) { // Import translations of product names and descriptions $r++; diff --git a/htdocs/langs/fr_FR/products.lang b/htdocs/langs/fr_FR/products.lang index 728959a982b..a3aae093043 100644 --- a/htdocs/langs/fr_FR/products.lang +++ b/htdocs/langs/fr_FR/products.lang @@ -73,8 +73,13 @@ AppliedPricesTo=Appliqué jusqu'au ErrorAppliedPricesIntersectAnotherPeriod=La date de début ou de fin croise une autre période existante. SellingPrice=Prix de vente SellingPriceHT=Prix de vente HT +SellingMinPriceHT=Prix de vente minimum (HT) +SellingUnitPriceHT=Prix de vente unitaire (HT) +SellingUnitMinPriceHT=Prix de vente unitaire minimum (HT) SellingPriceTTC=Prix de vente TTC SellingMinPriceTTC=Prix de vente min. (TTC) +SellingUnitMinPriceTTC=Prix de vente unitaire minimum (TTC) +SellingUnitPriceTTC=Prix de vente unitaire (TTC) CostPriceDescription=Ce champ de prix (hors taxes) peut être utilisé pour saisir le montant moyen que ce produit coûte à votre société. Il peut s'agir de n'importe quel prix que vous calculez vous-même, par exemple à partir du prix d'achat moyen plus le coût moyen de production et de distribution. CostPriceUsage=Cette valeur peut être utilisée dans le calcul des marges. ManufacturingPrice=Prix de fabrication From c8458c22e8a9f3742b624d5d4a7a4e1fa5b61720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Wed, 17 Sep 2025 14:22:58 +0200 Subject: [PATCH 2/2] clean code (#35358) * clean code * clean code * clean code * clean code * clean code * clean code --------- Co-authored-by: Laurent Destailleur --- dev/build/phpstan/phpstan-baseline.neon | 42 ------------------- .../class/accountingaccount.class.php | 42 +++++++++---------- 2 files changed, 20 insertions(+), 64 deletions(-) diff --git a/dev/build/phpstan/phpstan-baseline.neon b/dev/build/phpstan/phpstan-baseline.neon index 19eb4a4564b..4925d9f3802 100644 --- a/dev/build/phpstan/phpstan-baseline.neon +++ b/dev/build/phpstan/phpstan-baseline.neon @@ -252,48 +252,6 @@ parameters: count: 4 path: ../../../htdocs/accountancy/class/accountancyexport.class.php - - - message: '#^Negated boolean expression is always true\.$#' - identifier: booleanNot.alwaysTrue - count: 1 - path: ../../../htdocs/accountancy/class/accountingaccount.class.php - - - - message: '#^Property AccountingAccount\:\:\$account_number \(string\) in isset\(\) is not nullable\.$#' - identifier: isset.property - count: 3 - path: ../../../htdocs/accountancy/class/accountingaccount.class.php - - - - message: '#^Property AccountingAccount\:\:\$fk_pcg_version \(string\) in isset\(\) is not nullable\.$#' - identifier: isset.property - count: 1 - path: ../../../htdocs/accountancy/class/accountingaccount.class.php - - - - message: '#^Property AccountingAccount\:\:\$label \(string\) in isset\(\) is not nullable\.$#' - identifier: isset.property - count: 1 - path: ../../../htdocs/accountancy/class/accountingaccount.class.php - - - - message: '#^Property AccountingAccount\:\:\$labelshort \(string\) in isset\(\) is not nullable\.$#' - identifier: isset.property - count: 1 - path: ../../../htdocs/accountancy/class/accountingaccount.class.php - - - - message: '#^Property AccountingAccount\:\:\$pcg_type \(string\) in isset\(\) is not nullable\.$#' - identifier: isset.property - count: 1 - path: ../../../htdocs/accountancy/class/accountingaccount.class.php - - - - message: '#^Ternary operator condition is always true\.$#' - identifier: ternary.alwaysTrue - count: 1 - path: ../../../htdocs/accountancy/class/accountingaccount.class.php - - message: '#^Call to function array_key_exists\(\) with ''error'' and array\{ref\: mixed, label\: mixed, acquisition_value_ht\: mixed, depreciation\: non\-empty\-array\, disposal\?\: array\{date\: mixed, amount\: mixed, subject_to_vat\: bool\}\} will always evaluate to false\.$#' identifier: function.impossibleType diff --git a/htdocs/accountancy/class/accountingaccount.class.php b/htdocs/accountancy/class/accountingaccount.class.php index 97960271195..6f519987532 100644 --- a/htdocs/accountancy/class/accountingaccount.class.php +++ b/htdocs/accountancy/class/accountingaccount.class.php @@ -1,11 +1,11 @@ - * Copyright (C) 2013-2024 Alexandre Spangaro - * Copyright (C) 2013-2021 Florian Henry - * Copyright (C) 2014 Juanjo Menent - * Copyright (C) 2015 Ari Elbaz (elarifr) - * Copyright (C) 2018-2025 Frédéric France - * Copyright (C) 2024 MDW +/* Copyright (C) 2013-2014 Olivier Geffroy + * Copyright (C) 2013-2024 Alexandre Spangaro + * Copyright (C) 2013-2021 Florian Henry + * Copyright (C) 2014 Juanjo Menent + * Copyright (C) 2015 Ari Elbaz (elarifr) + * Copyright (C) 2018-2025 Frédéric France + * Copyright (C) 2024 MDW * * 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 @@ -80,17 +80,17 @@ class AccountingAccount extends CommonObject public $datec; /** - * @var string pcg version + * @var ?string pcg version */ public $fk_pcg_version; /** - * @var string pcg type + * @var ?string pcg type */ public $pcg_type; /** - * @var string account number + * @var ?string account number */ public $account_number; @@ -115,12 +115,12 @@ class AccountingAccount extends CommonObject public $status; /** - * @var string Label of account + * @var ?string Label of account */ public $label; /** - * @var string Label short of account + * @var ?string Label short of account */ public $labelshort; @@ -358,7 +358,7 @@ class AccountingAccount extends CommonObject $sql = "UPDATE " . $this->db->prefix() . $this->table_element; $sql .= " SET fk_pcg_version = " . ($this->fk_pcg_version ? "'" . $this->db->escape($this->fk_pcg_version) . "'" : "null"); - $sql .= " , pcg_type = " . ($this->pcg_type ? "'" . $this->db->escape($this->pcg_type) . "'" : "null"); + $sql .= " , pcg_type = '" . $this->db->escape($this->pcg_type) . "'"; $sql .= " , account_number = '" . $this->db->escape($this->account_number) . "'"; $sql .= " , account_parent = " . (int) $this->account_parent; $sql .= " , label = " . ($this->label ? "'" . $this->db->escape($this->label) . "'" : "''"); @@ -436,16 +436,14 @@ class AccountingAccount extends CommonObject if ($result > 0) { $this->db->begin(); - if (!$error) { - $sql = "DELETE FROM " . $this->db->prefix() . $this->table_element; - $sql .= " WHERE rowid=" . ((int) $this->id); + $sql = "DELETE FROM " . $this->db->prefix() . $this->table_element; + $sql .= " WHERE rowid=" . ((int) $this->id); - dol_syslog(get_class($this) . "::delete sql=" . $sql); - $resql = $this->db->query($sql); - if (!$resql) { - $error++; - $this->errors[] = "Error " . $this->db->lasterror(); - } + dol_syslog(get_class($this) . "::delete sql=" . $sql); + $resql = $this->db->query($sql); + if (!$resql) { + $error++; + $this->errors[] = "Error " . $this->db->lasterror(); } // Commit or rollback