From 9f9b088d476ef82c9355a82aeb447274b77811c2 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Wed, 25 Mar 2026 10:08:51 +0100 Subject: [PATCH 1/2] Fix trigger product resolution for buy/sell price events --- ...icsPrices_DynamicsPricesTriggers.class.php | 76 +++++++++++++++---- 1 file changed, 63 insertions(+), 13 deletions(-) diff --git a/core/triggers/interface_99_modDynamicsPrices_DynamicsPricesTriggers.class.php b/core/triggers/interface_99_modDynamicsPrices_DynamicsPricesTriggers.class.php index 93962d2..784a017 100644 --- a/core/triggers/interface_99_modDynamicsPrices_DynamicsPricesTriggers.class.php +++ b/core/triggers/interface_99_modDynamicsPrices_DynamicsPricesTriggers.class.php @@ -76,19 +76,17 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf require_once __DIR__.'/../../lib/dynamicsprices.lib.php'; $updateFunction = getDolGlobalString('LMDB_COST_PRICE_ONLY') ? 'update_customer_prices_from_cost_price' : 'update_customer_prices_from_suppliers'; $affectedActions = array('SUPPLIER_PRODUCT_BUYPRICE_CREATE', 'SUPPLIER_PRODUCT_BUYPRICE_MODIFY', 'SUPPLIER_PRODUCT_BUYPRICE_DELETE', 'PRODUCT_MODIFY', 'PRODUCT_CREATE', 'PRODUCT_CLONE', 'PRODUCT_PRICE_CREATE', 'PRODUCT_PRICE_MODIFY', 'PRODUCT_PRICE_DELETE', 'PRODUCT_BUYPRICE_CREATE', 'PRODUCT_BUYPRICE_MODIFY', 'PRODUCT_BUYPRICE_DELETE', 'PRODUCT_SUBPRODUCT_ADD', 'PRODUCT_SUBPRODUCT_UPDATE', 'PRODUCT_SUBPRODUCT_DELETE'); - //var_dump($updateFunction); - //var_dump($action); - if (getDolGlobalString('LMDB_SUPPLIER_BUYPRICE_ALTERED') && in_array($action, $affectedActions, true)) { - dol_include_once('/product/class/product.class.php'); - $productId = !empty($object->fk_product) ? $object->fk_product : (isset($object->id) ? $object->id : 0); - $product = new Product($db); - if ($productId > 0 && $product->fetch($productId) > 0) { - if ((int) $product->type !== Product::TYPE_PRODUCT) { - return 0; - } - } - if ($productId > 0) { - call_user_func($updateFunction, $db, $user, $langs, $conf, $productId); + if (getDolGlobalString('LMDB_SUPPLIER_BUYPRICE_ALTERED') && in_array($action, $affectedActions, true)) { + dol_include_once('/product/class/product.class.php'); + $productId = $this->resolveProductIdFromTriggerAction($db, $action, $object); + $product = new Product($db); + if ($productId > 0 && $product->fetch($productId) > 0) { + if ((int) $product->type !== Product::TYPE_PRODUCT) { + return 0; + } + } + if ($productId > 0) { + call_user_func($updateFunction, $db, $user, $langs, $conf, $productId); $parentKits = dynamicsprices_get_parent_kits($db, $productId); foreach ($parentKits as $kitId) { call_user_func($updateFunction, $db, $user, $langs, $conf, $kitId); @@ -335,4 +333,56 @@ public function runTrigger($action, $object, User $user, Translate $langs, Conf return 0; } + + /** + * Resolve related product id from trigger context. + * + * @param DoliDB $db Database handler + * @param string $action Trigger action + * @param CommonObject $object Trigger object + * @return int + */ + private function resolveProductIdFromTriggerAction($db, $action, $object) + { + if (!empty($object->fk_product)) { + return (int) $object->fk_product; + } + + if (in_array($action, array('PRODUCT_CREATE', 'PRODUCT_MODIFY', 'PRODUCT_CLONE', 'PRODUCT_SUBPRODUCT_ADD', 'PRODUCT_SUBPRODUCT_UPDATE', 'PRODUCT_SUBPRODUCT_DELETE'), true) && !empty($object->id)) { + return (int) $object->id; + } + + if (in_array($action, array('PRODUCT_PRICE_CREATE', 'PRODUCT_PRICE_MODIFY', 'PRODUCT_PRICE_DELETE'), true) && !empty($object->id)) { + $sql = "SELECT fk_product FROM ".MAIN_DB_PREFIX."product_price WHERE rowid = ".((int) $object->id); + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + if (!empty($obj->fk_product)) { + return (int) $obj->fk_product; + } + } + } + + if (in_array($action, array('SUPPLIER_PRODUCT_BUYPRICE_CREATE', 'SUPPLIER_PRODUCT_BUYPRICE_MODIFY', 'SUPPLIER_PRODUCT_BUYPRICE_DELETE', 'PRODUCT_BUYPRICE_CREATE', 'PRODUCT_BUYPRICE_MODIFY', 'PRODUCT_BUYPRICE_DELETE'), true)) { + $priceRowId = 0; + if (!empty($object->product_fourn_price_id)) { + $priceRowId = (int) $object->product_fourn_price_id; + } elseif (!empty($object->id)) { + $priceRowId = (int) $object->id; + } + + if ($priceRowId > 0) { + $sql = "SELECT fk_product FROM ".MAIN_DB_PREFIX."product_fournisseur_price WHERE rowid = ".$priceRowId; + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + if (!empty($obj->fk_product)) { + return (int) $obj->fk_product; + } + } + } + } + + return 0; + } } From acbcf23c1454ab53f60e46843820b7487bcc6a5c Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Wed, 25 Mar 2026 22:59:42 +0100 Subject: [PATCH 2/2] Bump module version to 2.0.1 and update changelog --- ChangeLog.md | 3 +++ core/modules/modDynamicsPrices.class.php | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index af22b78..f3f9c99 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,8 @@ # Changelog DynamicsPrices +## 2.0.1 +- Correction du déclenchement des recalculs de prix lors des événements de prix d'achat/vente quand l'identifiant produit n'est pas directement porté par l'objet trigger. / Fixed price recalculation trigger execution on buy/sell price events when the product identifier is not directly available on the trigger object. + ## 2.0.0 - Ajout du support des kits : le prix d'un kit est recalculé après ses composants pour éviter les doublons et refléter le coût cumulé. / Added kit support: a kit price is recalculated after its components to avoid duplicates and reflect the cumulative cost. - Correction des mises à jour intempestives des services : seuls les produits physiques sont recalculés (`fk_product_type = 0`). / Fixed unintended service updates: only physical products are recalculated (`fk_product_type = 0`). diff --git a/core/modules/modDynamicsPrices.class.php b/core/modules/modDynamicsPrices.class.php index 4b2304b..19c70f7 100644 --- a/core/modules/modDynamicsPrices.class.php +++ b/core/modules/modDynamicsPrices.class.php @@ -75,8 +75,8 @@ public function __construct($db) $this->editor_url = 'lesmetiersdubatiment.fr'; // Must be an external online web site $this->editor_squarred_logo = 'logo.png@dynamicsprices'; // Must be image filename into the module/img directory followed with @modulename. Example: 'myimage.png@dynamicsprices' -// Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated', 'experimental_deprecated' or a version string like 'x.y.z' -$this->version = '2.0.0'; + // Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated', 'experimental_deprecated' or a version string like 'x.y.z' + $this->version = '2.0.1'; // Url to the file with your last numberversion of this module //$this->url_last_version = 'http://www.example.com/versionmodule.txt';