NEW API endpoint for getting product price logs (#38420)

* New API endpoint for getting product price logs

* phan fixes build #16498 PR #38420

---------

Co-authored-by: Jon Bendtsen <jonbendtsen@jonb.dk>
This commit is contained in:
Jon Bendtsen 2026-05-25 02:41:33 +02:00 committed by GitHub
parent f647b232d6
commit 3e7dfdc02b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 123 additions and 0 deletions

View file

@ -1173,6 +1173,49 @@ class Products extends DolibarrApi
return $this->_cleanObjectDatas($product_fourn_list);
}
/**
* Get the history logs for all supplier prices of a specific product
*
* @since 26.0.0 Initial implementation
*
* @param int $id ID of product
* @param string $ref Ref of element
* @param string $ref_ext Ref ext of element
* @param string $barcode Barcode of element
* @return array<int, stdClass> Array of price logs
* @phan-return array<int, stdClass>
* @phpstan-return array<int, stdClass>
*
* @url GET {id}/purchase_prices/logs
*
* @throws RestException 400
* @throws RestException 403
* @throws RestException 404
*/
public function getPurchasePriceLogs($id, $ref = '', $ref_ext = '', $barcode = '')
{
dol_syslog(__METHOD__, LOG_DEBUG);
if (empty($id) && empty($ref) && empty($ref_ext) && empty($barcode)) {
throw new RestException(400, 'bad value for parameter id, ref, ref_ext or barcode');
}
$id = (empty($id) ? 0 : $id);
if (!DolibarrApiAccess::$user->hasRight('produit', 'lire')) {
throw new RestException(403);
}
$result = $this->product->fetch($id, $ref, $ref_ext, $barcode);
if (!$result) {
throw new RestException(404, 'Product not found');
}
if (!DolibarrApi::_checkAccessToResource('product', $this->product->id)) {
throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
}
$allLogs = $this->product->fetchAllPriceLogs($this->product->id);
return $allLogs;
}
/**
* Get attributes
*

View file

@ -2362,6 +2362,55 @@ class Product extends CommonObject
}
}
/**
* Get all price change logs for a product, enriched with supplier info
*
* @param int $id Id of the product
* @return array<int, stdClass> Array of log objects with supplier info
* @phan-return array<int, stdClass>
* @phpstan-return array<int, stdClass>
*/
public function fetchAllPriceLogs($id)
{
dol_syslog(__METHOD__, LOG_DEBUG);
$logs = array();
$sql = "SELECT";
$sql .= " pl.rowid as log_rowid,";
$sql .= " pl.datec,";
$sql .= " pl.price,";
$sql .= " pl.quantity,";
$sql .= " pl.fk_user,";
$sql .= " pl.multicurrency_code,";
$sql .= " pl.multicurrency_price,";
// Supplier info
$sql .= " pp.fk_soc as supplier_id,";
$sql .= " pp.ref_fourn as supplier_ref,";
$sql .= " pp.entity as entity";
$sql .= " FROM " . $this->db->prefix() . "product_fournisseur_price_log as pl";
$sql .= " INNER JOIN " . $this->db->prefix() . "product_fournisseur_price as pp ON pl.fk_product_fournisseur = pp.rowid";
$sql .= " WHERE pp.fk_product = " . ((int) $id);
$sql .= " AND pp.entity IN (" . getEntity('product') . ")";
$sql .= " ORDER BY pl.datec DESC";
$resql = $this->db->query($sql);
if ($resql) {
while ($obj = $this->db->fetch_object($resql)) {
if (is_string($obj->datec)) {
$obj->datec = strtotime($obj->datec);
}
$logs[] = $obj;
}
$this->db->free($resql);
} else {
$this->error = $this->db->lasterror();
}
return $logs;
}
/**
* Return price of sell of a product for a seller/buyer/product.

View file

@ -0,0 +1,31 @@
# ==============================================================================
# Dynamic Product Purchase Price Logs Tests
# ==============================================================================
# SETUP: Capture a valid Product ID from the first available product
GET http://{{hostnport}}/api/index.php/products?limit=1
HTTP 200
[Captures]
target_id: jsonpath "$[0].id"
# Validation: Test with ID 0 (Should fail)
GET http://{{hostnport}}/api/index.php/products/0/purchase_prices/logs
HTTP 400
{"error":{"code":400,"message":"Bad Request: bad value for parameter id, ref, ref_ext or barcode"}}
# Validation: Test with a non-existent ID (Should fail)
GET http://{{hostnport}}/api/index.php/products/999999/purchase_prices/logs
HTTP 404
{"error":{"code":404,"message":"Not Found: Product not found"}}
# Success: Fetch logs using the CAPTURED ID
GET http://{{hostnport}}/api/index.php/products/{{ target_id }}/purchase_prices/logs
HTTP 200
# Query Param: Test with pagination_data=false
GET http://{{hostnport}}/api/index.php/products/{{ target_id }}/purchase_prices/logs?pagination_data=false
HTTP 200
# Query Param: Test with pagination_data=true
GET http://{{hostnport}}/api/index.php/products/{{ target_id }}/purchase_prices/logs?pagination_data=true
HTTP 200