Hi,
Thank you for proposing this solution. If I understand correctly, you
are suggesting to receive the goods (using the receiveInventoryProduct
service) and then somehow automatically perform the unit conversion
during the transfer order from the UI level?
You mentioned that it is not advisable to modify data inside the
receiveInventoryProduct service. What do you think about using SECA
(Service ECA) rules instead? Rather than modifying the data within
receiveInventoryProduct itself, we could perform the conversion right
after this service executes. My concept relies on two additional ECA
services. The first one would be triggered after the createInventoryItem
service completes, and the second one after the receiveInventoryProduct
service completes.
The first service (called after createInventoryItem) checks if the
InventoryItem is linked to a supplier and if its uomId == null. If so,
it sets the uomId based on the SupplierProduct's UOM. This ensures that
the InventoryItem stores the supplier's unit of measure.
The second service (called after receiveInventoryProduct) would perform
the following steps:
1. Retrieve all InventoryItems that meet the following requirements:
- are linked to the given product
- have a UOM different from Product.quantityUomId
- the fields quantityOnHandTotal != 0 OR availableToPromiseTotal != 0 OR
accountingQuantityTotal != 0
If I sell the product in the same unit of measure as the supplier, this
InventoryItem list should be empty. Otherwise, usually one InventoryItem
element will appear (we could also trigger this ECA service after the
updateProduct service to detect if the Product.quantityUomId value has
changed — in that case, the number of elements on the InventoryItem list
would be greater).
2. For each InventoryItem element from the list created in step one:
- create an InventoryItemDetail that resets quantityOnHandTotal,
availableToPromiseTotal, and accountingQuantityTotal to zero in the
original InventoryItem.
- calculate the new quantityOnHandTotal, availableToPromiseTotal,
accountingQuantityTotal, and unitCost based on the original values (unit
conversion). For instance, when converting from WT_kg to WT_g, each of
these values would be multiplied by 1000, except for the cost, which
would be divided by 1000 (I would use the convertUom service you
mentioned earlier for this). This would result in new variables:
newQuantityOnHandTotal, newAvailableToPromiseTotal,
newAccountingQuantityTotal, and newUnitCost.
- create a new InventoryItem, set its uomId field to
Product.quantityUomId, and then add a new InventoryItemDetail record
(quantityOnHandDiff = newQuantityOnHandTotal, availableToPromiseDiff =
newAvailableToPromiseTotal, accountingQuantityDiff =
newAccountingQuantityTotal, unitCost = newUnitCost) linked to this new
InventoryItem.
The outcome of the above algorithm will be the creation of a new
InventoryItem based on the desired units of measure. The old
InventoryItem will be kept purely for informational/historical purposes
(it will no longer contain any available products).
What do you think about this approach?
Best regards,
Tomek
W dniu 16.06.2026 o 17:38, Aditi Patel pisze:
Hi Tomek,
Glad the earlier note helped. Here is how I would suggest handling UoM
across the lifecycle.
The cleanest pattern is to keep the purchasing side in the supplier's unit
and switch to your stocking unit only when goods enter the warehouse. The
PO carries the supplier product's UoM (copied from SupplierProduct, e.g.
kg), the shipment is received in that same UoM, and the InventoryItem is
created in the UoM from the ShipmentReceipt. When you then move that stock
into the warehouse, you convert using the SupplierProduct and Product UoMs
and stock it in the Product's UoM (g).
PO (kg) -> Receipt (kg) -> InventoryItem (kg) -> Stock move to warehouse,
convert kg -> g -> On-hand and sales in g
So the PO lifecycle stays in the supplier product's UoM and the stocking is
in the product's UoM, with the conversion happening at the stock move.
Receiving in the PO's unit also keeps a clean match between the PO, the
receipt, and the supplier invoice (OFBiz generates purchase invoicing from
ShipmentReceipt quantities), so AP reconciliation and unit cost stay
accurate.
On your questions:
1. The data model does support UoM management at the inventory level, and
InventoryItem.uomId is part of that - I have seen it used across various
inventory flows, including receiving, to record the unit an item is held
in. Just keep in mind the core ATP/QOH and reservation logic does not read
it out of the box, so it labels the unit rather than driving the conversion
on its own.
2. There is no single enforced "stocking UoM" field - inventory is
effectively 1 unit = 1. By convention the stocking unit lives on
Product.quantityUomId, the supplier's unit on
SupplierProduct.quantityUomId, and the conversion factor (wt_kg -> wt_g =
1000) in the UomConversion entity that convertUom reads.
3. Rather than converting inside receiveInventoryProduct, I would do it at
the stock move into the warehouse: a small service (for example in a
hot-deploy component, around the inventory transfer / stock move) that
calls convertUom using the SupplierProduct and Product UoMs, records the
on-hand in g, and stamps InventoryItem.uomId. Everything downstream then
stays consistent.
If at any point the UoM management or the conversions are not behaving as
expected, feel free to reach out - happy to help.
Best regards,
Aditi
On Tue, Jun 16, 2026 08:17 PM, Tomek <[email protected]> wrote:
Hi,
Thank you very much for your response.
Indeed, this issue can be managed by:
- multiplying the quantity by 1000 and dividing the cost by 1000 during
the purchase order receipt,
- multiplying the quantity by 1000 and dividing the cost by 1000 at the
stage of purchase order creation.
This works and is actually a viable solution, but it makes me wonder:
what is the purpose of the uomId field in InventoryItem then? Is it used
anywhere at all? Is it a legacy remnant or perhaps a placeholder
designed for future process customization?
Let's assume I would like to automatically convert units from the
supplier's purchase unit to my own preferred unit. For instance, I store
Product X in my warehouse in grams, but the supplier sells it in
kilograms. I would like this conversion to happen automatically.
With that in mind, I have a couple of questions:
1. Where should I define my internal stocking unit (the UoM for products
stored in my own warehouse)?
2. What would be the best way to handle this conversion? Should I
override the receiveInventoryProduct service, or is there a better, more
recommended approach?
Best regards,
Tomek
W dniu 16.06.2026 o 13:06, Aditi Patel pisze:
Hi,
Thanks for the clear write-up and reproduction steps! The good news is
that
nothing is broken here. What you are seeing is OFBiz working as designed:
it does not perform automatic unit-of-measure conversion across the
purchase -> inventory -> sales flow.
A few things that explain both observations:
- Inventory is counted in stocking units, not by weight. ATP and QOH are
plain numeric quantities with no associated UoM, and reservation simply
subtracts the ordered quantity. That is why selling 1 reduces ATP by
exactly 1 rather than 0.25.
- receiveInventoryProduct does not copy Product.quantityUomId or the
SupplierProduct UoM onto InventoryItem.uomId, so it is left null. And
even
when you set it manually, the reservation logic never reads it, so the
math
is unchanged.
- Product.quantityIncluded / quantityUomId are descriptive packaging
metadata, not conversion factors applied to inventory or orders.
So both behaviors are expected rather than a bug. If you need to buy in
one
unit and stock or sell in another, the cleanest options are:
- Normalize everything to a single stocking UoM and convert at receipt
time, e.g. receive the 1 kg PO line as quantityAccepted = 1000 and keep
the
product stocked in grams; or
- Add your own conversion using the convertUom service together with the
UomConversion entity in framework/common.
Hope this helps clear things up, and happy to elaborate on any of the
above.
Best regards,
Aditi Patel
On Tue, Jun 16, 2026 04:15 PM, Tomek <[email protected]> wrote:
Hi everyone,
I am facing an issue with UoM (Unit of Measure) handling in OFBiz and
would appreciate some guidance.
Here is my setup and the steps to reproduce the issue:
1. I created a test product and configured it with:
- Quantity Included: 250
- Quantity Uom Id: Grams (wt_g)
2. In the Suppliers tab, I added a supplier and set their supplier UoM
to Kilograms (wt_kg).
3. I created a Purchase Order (PO) from this supplier, who sells the
item in wt_kg.
4. I received the shipment for this PO, which automatically created an
InventoryItem.
Problem:
The uomId field in the newly created InventoryItem was not populated (it
is null).
Next, I simulated a sales order for this test product. After adding the
product to the order and approving it, the system decreased the
Available To Promise (ATP) on the aforementioned InventoryItem by
exactly
1.
This issue persists even if I manually update the uomId field to wt_kg
directly in the InventoryItem.
Questions:
1. Why does OFBiz seem to ignore the Units of Measure in this scenario?
2. Shouldn't the sales order reduce the ATP value by 0.25 instead of 1,
given the product configuration?
Any insights on what might be missing or if this is an out-of-the-box
limitation would be highly appreciated.
Thanks in advance!