From 3f3433685d04a041013e90ad507285e62d31d862 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 21 May 2026 16:43:49 +1000 Subject: [PATCH] Normalize BomItem quantity (#11975) - Limit decimal places before save - Prevents error in BomItem validation --- src/backend/InvenTree/part/models.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/backend/InvenTree/part/models.py b/src/backend/InvenTree/part/models.py index 3ad08f999d..a38870df5e 100644 --- a/src/backend/InvenTree/part/models.py +++ b/src/backend/InvenTree/part/models.py @@ -2,14 +2,13 @@ from __future__ import annotations -import decimal import hashlib import inspect import math import os import re from datetime import timedelta -from decimal import Decimal, InvalidOperation +from decimal import ROUND_HALF_UP, Decimal, InvalidOperation from typing import TypedDict, cast from django.conf import settings @@ -2052,8 +2051,9 @@ class Part( 'part', 'sub_part' ) - for item in bom_items: - item.validate_hash(valid=valid) + if valid: + for item in bom_items: + item.validate_hash(valid=True) self.bom_validated = valid self.bom_checksum = self.get_bom_hash() if valid else '' @@ -2233,8 +2233,8 @@ class Part( logger.warning('WARNING: BomItem ID %s contains itself in BOM', item.pk) continue - q = decimal.Decimal(quantity) - i = decimal.Decimal(item.quantity) + q = Decimal(quantity) + i = Decimal(item.quantity) prices = item.sub_part.get_price_range( q * i, internal=internal, purchase=purchase @@ -3934,14 +3934,18 @@ class BomItem(InvenTree.models.MetadataMixin, InvenTree.models.InvenTreeModel): 'raw_amount': _('Quantity must be greater than zero') }) - self.quantity = Decimal(quantity.magnitude) + # Normalize the quantity, to maximum 5 decimal places + quantity = Decimal(quantity.magnitude) except ValidationError as e: raise ValidationError({'raw_amount': e.messages}) # Ensure that the raw_amount is converted to a Decimal value + # and quantized to a maximum of 5 decimal places (to avoid floating point issues) try: - self.quantity = Decimal(self.quantity) + self.quantity = Decimal(quantity).quantize( + Decimal('0.00001'), rounding=ROUND_HALF_UP + ) except InvalidOperation: msg = _('Invalid quantity provided') raise ValidationError({'quantity': msg, 'raw_amount': msg})