mirror of
https://github.com/inventree/InvenTree.git
synced 2026-09-01 17:51:23 +00:00
Pricing bugs (#12305)
* bug fix for get_price method - Remove unused argument moq - Allow case where 'multiples' = False * Error handling for convert_to * Error handling for PartPricing.save * Remove unused function * Revert function definition * coverage ignore
This commit is contained in:
@@ -162,13 +162,21 @@ def currency_exchange_plugins() -> Optional[list]:
|
|||||||
def get_price(
|
def get_price(
|
||||||
instance,
|
instance,
|
||||||
quantity,
|
quantity,
|
||||||
moq=True,
|
moq: bool = True,
|
||||||
multiples=True,
|
multiples: bool = True,
|
||||||
currency=None,
|
currency: Optional[str] = None,
|
||||||
break_name: str = 'price_breaks',
|
break_name: str = 'price_breaks',
|
||||||
):
|
):
|
||||||
"""Calculate the price based on quantity price breaks.
|
"""Calculate the price based on quantity price breaks.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
instance: The model instance which contains the price break information
|
||||||
|
quantity: The quantity to calculate the price for
|
||||||
|
moq: If True, then minimum order quantity will be observed (CURRENTLY NOT IMPLEMENTED)
|
||||||
|
multiples: If True, then order multiples will be observed
|
||||||
|
currency: The currency code to use for the calculation (default is None)
|
||||||
|
break_name: The name of the price break field on the instance (default is 'price_breaks')
|
||||||
|
|
||||||
- Don't forget to add in flat-fee cost (base_cost field)
|
- Don't forget to add in flat-fee cost (base_cost field)
|
||||||
- If MOQ (minimum order quantity) is required, bump quantity
|
- If MOQ (minimum order quantity) is required, bump quantity
|
||||||
- If order multiples are to be observed, then we need to calculate based on that, too
|
- If order multiples are to be observed, then we need to calculate based on that, too
|
||||||
@@ -185,7 +193,7 @@ def get_price(
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
# Check if quantity is fraction and disable multiples
|
# Check if quantity is fraction and disable multiples
|
||||||
multiples = quantity % 1 == 0
|
multiples = multiples and (quantity % 1 == 0)
|
||||||
|
|
||||||
# Order multiples
|
# Order multiples
|
||||||
if multiples:
|
if multiples:
|
||||||
|
|||||||
@@ -1388,21 +1388,27 @@ class PriceBreak(MetaMixin):
|
|||||||
help_text=_('Unit price at specified quantity'),
|
help_text=_('Unit price at specified quantity'),
|
||||||
)
|
)
|
||||||
|
|
||||||
def convert_to(self, currency_code):
|
def convert_to(self, currency_code: str, raise_error: bool = False):
|
||||||
"""Convert the unit-price at this price break to the specified currency code.
|
"""Convert the unit-price at this price break to the specified currency code.
|
||||||
|
|
||||||
Args:
|
Arguments:
|
||||||
currency_code: The currency code to convert to (e.g "USD" or "AUD")
|
currency_code: The currency code to convert to (e.g "USD" or "AUD")
|
||||||
|
raise_error: If True, raise an error if the conversion fails. If False, return None.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
converted = convert_money(self.price, currency_code)
|
converted = convert_money(self.price, currency_code)
|
||||||
except MissingRate:
|
except MissingRate: # pragma: no cover
|
||||||
|
InvenTree.exceptions.log_error('PriceBreak.convert_to')
|
||||||
logger.warning(
|
logger.warning(
|
||||||
'No currency conversion rate available for %s -> %s',
|
'No currency conversion rate available for %s -> %s',
|
||||||
self.price_currency,
|
self.price_currency,
|
||||||
currency_code,
|
currency_code,
|
||||||
)
|
)
|
||||||
return self.price.amount
|
|
||||||
|
if raise_error:
|
||||||
|
raise
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
return converted.amount
|
return converted.amount
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ from common.settings import get_global_setting
|
|||||||
from InvenTree import helpers, validators
|
from InvenTree import helpers, validators
|
||||||
from InvenTree.exceptions import log_error
|
from InvenTree.exceptions import log_error
|
||||||
from InvenTree.fields import InvenTreeURLField
|
from InvenTree.fields import InvenTreeURLField
|
||||||
from InvenTree.helpers import decimal2money, decimal2string, normalize
|
from InvenTree.helpers import decimal2string, normalize
|
||||||
from order import models as OrderModels
|
from order import models as OrderModels
|
||||||
from order.status_codes import (
|
from order.status_codes import (
|
||||||
PurchaseOrderStatus,
|
PurchaseOrderStatus,
|
||||||
@@ -3001,15 +3001,12 @@ class PartPricing(common.models.MetaMixin):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
self.update_overall_cost()
|
self.update_overall_cost()
|
||||||
except Exception:
|
|
||||||
# If something has happened to the Part model, might throw an error
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
super().save(*args, **kwargs)
|
super().save(*args, **kwargs)
|
||||||
except Exception:
|
except Exception:
|
||||||
# This error may be thrown if there is already duplicate pricing data
|
log_error('PartPricing.save')
|
||||||
pass
|
logger.error(
|
||||||
|
"Could not save PartPricing for part '%s' to the database", self.part
|
||||||
|
)
|
||||||
|
|
||||||
def update_bom_cost(self, save=True):
|
def update_bom_cost(self, save=True):
|
||||||
"""Recalculate BOM cost for the referenced Part instance.
|
"""Recalculate BOM cost for the referenced Part instance.
|
||||||
@@ -4426,29 +4423,6 @@ class BomItem(InvenTree.models.MetadataMixin, InvenTree.models.InvenTreeModel):
|
|||||||
|
|
||||||
return required
|
return required
|
||||||
|
|
||||||
@property
|
|
||||||
def price_range(self, internal=False):
|
|
||||||
"""Return the price-range for this BOM item."""
|
|
||||||
# get internal price setting
|
|
||||||
use_internal = get_global_setting('PART_BOM_USE_INTERNAL_PRICE', False)
|
|
||||||
p_range = self.sub_part.get_price_range(
|
|
||||||
self.quantity, internal=use_internal and internal
|
|
||||||
)
|
|
||||||
|
|
||||||
if p_range is None:
|
|
||||||
return p_range
|
|
||||||
|
|
||||||
p_min, p_max = p_range
|
|
||||||
|
|
||||||
if p_min == p_max:
|
|
||||||
return decimal2money(p_min)
|
|
||||||
|
|
||||||
# Convert to better string representation
|
|
||||||
p_min = decimal2money(p_min)
|
|
||||||
p_max = decimal2money(p_max)
|
|
||||||
|
|
||||||
return f'{p_min} to {p_max}'
|
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=BomItem, dispatch_uid='update_bom_build_lines')
|
@receiver(post_save, sender=BomItem, dispatch_uid='update_bom_build_lines')
|
||||||
def update_bom_build_lines(sender, instance, created, **kwargs):
|
def update_bom_build_lines(sender, instance, created, **kwargs):
|
||||||
|
|||||||
Reference in New Issue
Block a user