From 234134d8f975a94011d31800b7efcfb065702df8 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Tue, 21 Feb 2023 21:32:29 +1100 Subject: [PATCH] Clean out existing pricing functions --- InvenTree/part/models.py | 133 +------------------------------- InvenTree/part/test_bom_item.py | 16 ---- 2 files changed, 1 insertion(+), 148 deletions(-) diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 72c3cfd2dc..07d7b25480 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -2,7 +2,6 @@ from __future__ import annotations -import decimal import hashlib import logging import os @@ -44,7 +43,7 @@ from common.settings import currency_code_default from company.models import SupplierPart from InvenTree import helpers, validators from InvenTree.fields import InvenTreeNotesField, InvenTreeURLField -from InvenTree.helpers import decimal2money, decimal2string, normalize +from InvenTree.helpers import decimal2money, decimal2string from InvenTree.models import (DataImportMixin, InvenTreeAttachment, InvenTreeBarcodeMixin, InvenTreeTree) from InvenTree.status_codes import (BuildStatus, PurchaseOrderStatus, @@ -1667,119 +1666,6 @@ class Part(InvenTreeBarcodeMixin, MetadataMixin, MPTTModel): except (PartPricing.DoesNotExist, IntegrityError): pass - def get_supplier_price_range(self, quantity=1): - """Return the supplier price range of this part: - - - Checks if there is any supplier pricing information associated with this Part - - Iterate through available supplier pricing and select (min, max) - - Returns tuple of (min, max) - - Arguments: - quantity: Quantity at which to calculate price (default=1) - - Returns: (min, max) tuple or (None, None) if no supplier pricing available - """ - min_price = None - max_price = None - - for supplier in self.supplier_parts.all(): - - price = supplier.get_price(quantity) - - if price is None: - continue - - if min_price is None or price < min_price: - min_price = price - - if max_price is None or price > max_price: - max_price = price - - if min_price is None or max_price is None: - return None - - min_price = normalize(min_price) - max_price = normalize(max_price) - - return (min_price, max_price) - - def get_bom_price_range(self, quantity=1, internal=False, purchase=False): - """Return the price range of the BOM for this part. - - Adds the minimum price for all components in the BOM. - Note: If the BOM contains items without pricing information, - these items cannot be included in the BOM! - """ - min_price = None - max_price = None - - for item in self.get_bom_items().select_related('sub_part'): - - if item.sub_part.pk == self.pk: - logger.warning(f"WARNING: BomItem ID {item.pk} contains itself in BOM") - continue - - q = decimal.Decimal(quantity) - i = decimal.Decimal(item.quantity) - - prices = item.sub_part.get_price_range(q * i, internal=internal, purchase=purchase) - - if prices is None: - continue - - low, high = prices - - if min_price is None: - min_price = 0 - - if max_price is None: - max_price = 0 - - min_price += low - max_price += high - - if min_price is None or max_price is None: - return None - - min_price = normalize(min_price) - max_price = normalize(max_price) - - return (min_price, max_price) - - def get_price_range(self, quantity=1, buy=True, bom=True, internal=False, purchase=False): - """Return the price range for this part. - - This price can be either: - - Supplier price (if purchased from suppliers) - - BOM price (if built from other parts) - - Internal price (if set for the part) - - Purchase price (if set for the part) - - Returns: - Minimum of the supplier, BOM, internal or purchase price. If no pricing available, returns None - """ - - # only get purchase price if set and should be used - if purchase: - purchase_price = self.get_purchase_price(quantity) - if purchase_price: - return purchase_price - - buy_price_range = self.get_supplier_price_range(quantity) if buy else None - bom_price_range = self.get_bom_price_range(quantity, internal=internal) if bom else None - - if buy_price_range is None: - return bom_price_range - - elif bom_price_range is None: - return buy_price_range - - else: - return ( - min(buy_price_range[0], bom_price_range[0]), - max(buy_price_range[1], bom_price_range[1]) - ) - base_cost = models.DecimalField(max_digits=19, decimal_places=6, default=0, validators=[MinValueValidator(0)], verbose_name=_('base cost'), help_text=_('Minimum charge (e.g. stocking fee)')) multiple = models.PositiveIntegerField(default=1, validators=[MinValueValidator(1)], verbose_name=_('multiple'), help_text=_('Sell multiple')) @@ -1828,23 +1714,6 @@ class Part(InvenTreeBarcodeMixin, MetadataMixin, MPTTModel): """Return the associated price breaks in the correct order.""" return self.internalpricebreaks.order_by('quantity').all() - def get_purchase_price(self, quantity): - """Calculate the purchase price for this part at the specified quantity - - - Looks at available supplier pricing data - - Calculates the price base on the closest price point - """ - currency = currency_code_default() - try: - prices = [convert_money(item.purchase_price, currency).amount for item in self.stock_items.all() if item.purchase_price] - except MissingRate: - prices = None - - if prices: - return min(prices) * quantity, max(prices) * quantity - - return None - @transaction.atomic def copy_bom_from(self, other, clear=True, **kwargs): """Copy the BOM from another part. diff --git a/InvenTree/part/test_bom_item.py b/InvenTree/part/test_bom_item.py index 7d2ca582a0..902fbc8b7e 100644 --- a/InvenTree/part/test_bom_item.py +++ b/InvenTree/part/test_bom_item.py @@ -1,8 +1,6 @@ """Unit tests for the BomItem model""" -from decimal import Decimal - import django.core.exceptions as django_exceptions from django.db import transaction from django.test import TestCase @@ -117,20 +115,6 @@ class BomItemTest(TestCase): self.assertNotEqual(h1, h2) - def test_pricing(self): - """Test BOM pricing""" - self.bob.get_price(1) - self.assertEqual( - self.bob.get_bom_price_range(1, internal=True), - (Decimal(29.5), Decimal(89.5)) - ) - # remove internal price for R_2K2_0805 - self.r1.internal_price_breaks.delete() - self.assertEqual( - self.bob.get_bom_price_range(1, internal=True), - (Decimal(27.5), Decimal(87.5)) - ) - def test_substitutes(self): """Tests for BOM item substitutes.""" # We will make some subtitute parts for the "orphan" part