commit 716bfcc1c083c4a987e833dc845d078103cad4bf
parent 564f9a34383e2980ac8ebff5626504e9f73835dc
Author: bohdan-potuzhnyi <bohdan.potuzhnyi@gmail.com>
Date: Wed, 29 Oct 2025 11:40:37 +0100
#0010506
Diffstat:
| M | core/api-merchant.rst | | | 188 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------- |
1 file changed, 139 insertions(+), 49 deletions(-)
diff --git a/core/api-merchant.rst b/core/api-merchant.rst
@@ -2683,12 +2683,29 @@ Adding products to the inventory
// Unit in which the product is measured (liters, kilograms, packages, etc.).
unit: string;
- // The price for one ``unit`` of the product. Zero is used
- // to imply that this product is not sold separately, or
- // that the price is not fixed, and must be supplied by the
- // front-end. If non-zero, this price MUST include applicable
- // taxes.
- price: Amount;
+ // Optional override to control whether fractional quantities are permitted.
+ // Defaults to the policy implied by ``unit``.
+ unit_allow_fraction?: boolean;
+
+ // Override for the fractional precision level (0-6). Only relevant if
+ // ``unit_allow_fraction`` is true. Defaults come from ``unit``.
+ unit_precision_level?: Integer;
+
+ // Preferred way to express inventory counts using "<integer>[.<fraction>]" syntax.
+ // Use "-1" for unlimited stock. Required unless ``total_stock`` is provided.
+ unit_total_stock?: string;
+
+ // Legacy stock counter. Deprecated, use ``unit_total_stock`` instead.
+ // Still required when ``unit_total_stock`` is omitted.
+ total_stock?: Integer;
+
+ // Preferred way to express the per-unit price of the product. Zero implies that
+ // the product is not sold separately or that the price must be supplied by the frontend.
+ // If non-zero, this price MUST include applicable taxes.
+ unit_price?: Amount;
+
+ // Legacy price field. Deprecated; when present it must match ``unit_price``.
+ price?: Amount;
// An optional base64-encoded product image.
image?: ImageDataUrl;
@@ -2696,12 +2713,6 @@ Adding products to the inventory
// A list of taxes paid by the merchant for one unit of this product.
taxes?: Tax[];
- // Number of units of the product in stock in sum in total,
- // including all existing sales ever. Given in product-specific
- // units.
- // A value of -1 indicates "infinite" (i.e. for "electronic" books).
- total_stock: Integer;
-
// Identifies where the product is in stock.
address?: Location;
@@ -2713,6 +2724,32 @@ Adding products to the inventory
}
+ Clients SHOULD migrate to the new ``unit_*`` fields and treat ``total_stock`` and ``price``
+ as deprecated compatibility shims. If both the legacy and the new representation are supplied,
+ their values must match. Omitting both ``unit_total_stock`` and ``total_stock`` (or both
+ ``unit_price`` and ``price``) results in a ``400 Bad Request``.
+
+ ``unit_total_stock`` uses a fixed-point decimal string in the form ``INTEGER[.FRACTION]`` with
+ at most eight fractional digits. Scientific notation or special values such as ``NaN`` are not
+ accepted. Supply ``"-1"`` to represent unlimited stock.
+
+ Fractional behaviour defaults to the value of ``unit``. The backend disables fractions for
+ ``Piece``, ``Set``, ``Custom``, ``WeightUnitMg`` and ``SizeUnitMm``. Other predefined units
+ allow fractional quantities with the following default precision levels:
+
+ - Precision ``1``: ``WeightUnitG``, ``SizeUnitCm``, ``SurfaceUnitMm2``, ``VolumeUnitMm3``.
+ - Precision ``2``: ``WeightUnitOunce``, ``SizeUnitInch``, ``SurfaceUnitCm2``,
+ ``VolumeUnitInch3``, ``VolumeUnitOunce``, ``TimeUnitHour``, ``TimeUnitMonth``.
+ - Precision ``3``: ``WeightUnitTon``, ``WeightUnitKg``, ``WeightUnitPound``, ``SizeUnitM``,
+ ``SizeUnitDm``, ``SizeUnitFoot``, ``SurfaceUnitDm2``, ``SurfaceUnitFoot2``, ``VolumeUnitCm3``,
+ ``VolumeUnitLitre``, ``VolumeUnitGallon``, ``TimeUnitSecond``, ``TimeUnitMinute``,
+ ``TimeUnitDay``, ``TimeUnitWeek``.
+ - Precision ``4``: ``SurfaceUnitM2``, ``SurfaceUnitInch2``, ``TimeUnitYear``.
+ - Precision ``5``: ``VolumeUnitDm3``, ``VolumeUnitFoot3``.
+ - Precision ``6``: ``VolumeUnitM3``.
+
+ Integrations can override these defaults by explicitly setting ``unit_allow_fraction`` and/or
+ ``unit_precision_level``.
.. http:patch:: [/instances/$INSTANCE]/private/products/$PRODUCT_ID
@@ -2763,17 +2800,25 @@ Adding products to the inventory
// Unit in which the product is measured (liters, kilograms, packages, etc.).
unit: string;
+ // Optional override to control whether fractional quantities are permitted.
+ unit_allow_fraction?: boolean;
+
+ // Override for the fractional precision level (0-6). Only relevant if
+ // ``unit_allow_fraction`` is true.
+ unit_precision_level?: Integer;
+
// Categories into which the product belongs.
// Used in the POS-endpoint.
// Since API version **v16**.
categories?: Integer[];
- // The price for one ``unit`` of the product. Zero is used
- // to imply that this product is not sold separately, or
- // that the price is not fixed, and must be supplied by the
- // front-end. If non-zero, this price MUST include applicable
- // taxes.
- price: Amount;
+ // Preferred way to express the per-unit price. Zero implies that
+ // the product is not sold separately or that the price must be supplied by the frontend.
+ // If non-zero, this price MUST include applicable taxes.
+ unit_price?: Amount;
+
+ // Legacy price field. Deprecated; when present it must match ``unit_price``.
+ price?: Amount;
// An optional base64-encoded product image.
image?: ImageDataUrl;
@@ -2781,11 +2826,12 @@ Adding products to the inventory
// A list of taxes paid by the merchant for one unit of this product.
taxes?: Tax[];
- // Number of units of the product in stock in sum in total,
- // including all existing sales ever. Given in product-specific
- // units.
- // A value of -1 indicates "infinite" (i.e. for "electronic" books).
- total_stock: Integer;
+ // Preferred way to express inventory counts using "<integer>[.<fraction>]" syntax.
+ // Use "-1" for unlimited stock.
+ unit_total_stock?: string;
+
+ // Legacy stock counter. Deprecated, use ``unit_total_stock`` instead.
+ total_stock?: Integer;
// Number of units of the product that were lost (spoiled, stolen, etc.).
total_lost?: Integer;
@@ -2801,6 +2847,9 @@ Adding products to the inventory
}
+ The same compatibility rules for the ``unit_*`` fields and their deprecated counterparts apply
+ when patching an existing product.
+
Inspecting inventory
^^^^^^^^^^^^^^^^^^^^
@@ -2880,15 +2929,22 @@ Inspecting inventory
// Unit in which the product is measured (liters, kilograms, packages, etc.).
unit: string;
+ // Does the backend allow fractional quantities for this unit?
+ unit_allow_fraction: boolean;
+
+ // Maximum fractional precision (0-6) enforced for inventory operations.
+ unit_precision_level: Integer;
+
// Categories into which the product belongs.
// Since API version **v16**.
categories: Integer[];
- // The price for one ``unit`` of the product. Zero is used
- // to imply that this product is not sold separately, or
- // that the price is not fixed, and must be supplied by the
- // front-end. If non-zero, this price MUST include applicable
- // taxes.
+ // Price for one ``unit`` of the product. Zero is used to imply that this product
+ // is not sold separately, or that the price is not fixed, and must be supplied by the
+ // front-end. If non-zero, this price MUST include applicable taxes.
+ unit_price: Amount;
+
+ // Legacy price field kept for compatibility. Deprecated; equal to ``unit_price``.
price: Amount;
// An optional base64-encoded product image.
@@ -2898,12 +2954,13 @@ Inspecting inventory
// Optional since **v15**.
taxes?: Tax[];
- // Number of units of the product in stock in sum in total,
- // including all existing sales ever. Given in product-specific
- // units.
- // A value of -1 indicates "infinite" (i.e. for "electronic" books).
+ // Legacy integer stock counter kept for compatibility. ``-1`` indicates unlimited stock.
total_stock: Integer;
+ // Stock expressed using "<integer>[.<fraction>]" syntax with up to eight fractional digits.
+ // Use ``"-1"`` for unlimited stock.
+ unit_total_stock: string;
+
// Number of units of the product that have already been sold.
total_sold: Integer;
@@ -2979,11 +3036,18 @@ Inspecting inventory
// Unit in which the product is measured (liters, kilograms, packages, etc.).
unit: string;
- // The price for one ``unit`` of the product. Zero is used
- // to imply that this product is not sold separately, or
- // that the price is not fixed, and must be supplied by the
- // front-end. If non-zero, this price MUST include applicable
- // taxes.
+ // Does the backend allow fractional quantities for this unit?
+ unit_allow_fraction: boolean;
+
+ // Maximum fractional precision (0-6) enforced for inventory operations.
+ unit_precision_level: Integer;
+
+ // Price for one ``unit`` of the product. Zero is used to imply that this product
+ // is not sold separately, or that the price is not fixed, and must be supplied by the
+ // front-end. If non-zero, this price MUST include applicable taxes.
+ unit_price: Amount;
+
+ // Legacy price field kept for compatibility. Deprecated; equal to ``unit_price``.
price: Amount;
// An optional base64-encoded product image.
@@ -2992,12 +3056,13 @@ Inspecting inventory
// A list of taxes paid by the merchant for one unit of this product.
taxes?: Tax[];
- // Number of units of the product in stock in sum in total,
- // including all existing sales ever. Given in product-specific
- // units.
- // Optional, if missing treat as "infinite".
+ // Legacy integer stock counter kept for compatibility. ``-1`` indicates unlimited stock.
total_stock?: Integer;
+ // Stock expressed using "<integer>[.<fraction>]" syntax with up to eight fractional digits.
+ // Use ``"-1"`` for unlimited stock.
+ unit_total_stock: string;
+
// Minimum age buyer must have (in years).
minimum_age?: Integer;
@@ -3052,7 +3117,7 @@ Reserving inventory
:http:statuscode:`404 Not found`:
The backend has does not know this product.
:http:statuscode:`410 Gone`:
- The backend does not have enough of product in stock.
+ The backend does not have enough of product in stock. Returns an `OutOfStockResponse`.
**Details:**
@@ -3067,11 +3132,19 @@ Reserving inventory
// How long does the frontend intend to hold the lock?
duration: RelativeTime;
- // How many units should be locked?
- quantity: Integer;
+ // Legacy integer quantity to lock. Deprecated; defaults to 1 if both
+ // ``quantity`` and ``unit_quantity`` are absent.
+ quantity?: Integer;
+
+ // Preferred way to express the requested quantity using "<integer>[.<fraction>]" syntax.
+ unit_quantity?: string;
}
+ At least one of ``quantity`` or ``unit_quantity`` must be supplied; omitting both defaults to a
+ quantity of one. ``unit_quantity`` follows the same decimal-string format described for
+ ``unit_total_stock``.
+
.. note::
The ``GNUNET_CRYPTO_random_timeflake()`` C API can be used
@@ -3465,10 +3538,18 @@ Creating orders
// Which product is requested (here mandatory!).
product_id: string;
- // How many units of the product are requested.
- quantity: Integer;
+ // Legacy integer quantity. Deprecated; defaults to 1 if both
+ // ``quantity`` and ``unit_quantity`` are absent.
+ quantity?: Integer;
+
+ // Preferred quantity string using "<integer>[.<fraction>]" syntax.
+ unit_quantity?: string;
}
+ Supply either ``quantity`` or ``unit_quantity`` when referencing inventory products. If both are
+ missing the backend assumes a quantity of one. ``unit_quantity`` follows the same decimal-string
+ rules as ``unit_total_stock``.
+
.. ts:def:: PostOrderResponse
interface PostOrderResponse {
@@ -3492,12 +3573,18 @@ Creating orders
// Product ID of an out-of-stock item.
product_id: string;
- // Requested quantity.
+ // Legacy integer quantity requested. Deprecated; see ``unit_requested_quantity``.
requested_quantity: Integer;
- // Available quantity (must be below ``requested_quantity``).
+ // Requested quantity using "<integer>[.<fraction>]" syntax with up to eight fractional digits.
+ unit_requested_quantity: string;
+
+ // Legacy integer availability (must be below ``requested_quantity``).
available_quantity: Integer;
+ // Available quantity using "<integer>[.<fraction>]" syntax with up to eight fractional digits.
+ unit_available_quantity: string;
+
// When do we expect the product to be again in stock?
// Optional, not given if unknown.
restock_expected?: Timestamp;
@@ -5805,9 +5892,12 @@ It has the following structure:
// Map from IETF BCP 47 language tags to localized descriptions.
description_i18n?: { [lang_tag: string]: string };
- // The number of units of the product to deliver to the customer.
+ // Legacy integer portion of the quantity to deliver defaults to 1 if not specified.
quantity?: Integer;
+ // Preferred quantity string using "<integer>[.<fraction>]" syntax with up to eight fractional digits.
+ unit_quantity?: string;
+
// Unit in which the product is measured (liters, kilograms, packages, etc.).
unit?: string;