mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-30 20:55:42 +00:00 
			
		
		
		
	Separate purchase_price and purchase_price_currency for StockItem serializer
- Add "purchase_price_string" for a read-only stringified representation - Unit testing
This commit is contained in:
		| @@ -12,6 +12,8 @@ | |||||||
|     tree_id: 0 |     tree_id: 0 | ||||||
|     lft: 0 |     lft: 0 | ||||||
|     rght: 0 |     rght: 0 | ||||||
|  |     purchase_price: 123 | ||||||
|  |     purchase_price_currency: AUD | ||||||
|  |  | ||||||
| # 5,000 screws in the bathroom | # 5,000 screws in the bathroom | ||||||
| - model: stock.stockitem | - model: stock.stockitem | ||||||
|   | |||||||
| @@ -4,6 +4,8 @@ JSON serializers for Stock app | |||||||
|  |  | ||||||
| from rest_framework import serializers | from rest_framework import serializers | ||||||
|  |  | ||||||
|  | from django.utils.translation import ugettext_lazy as _ | ||||||
|  |  | ||||||
| from .models import StockItem, StockLocation | from .models import StockItem, StockLocation | ||||||
| from .models import StockItemTracking | from .models import StockItemTracking | ||||||
| from .models import StockItemAttachment | from .models import StockItemAttachment | ||||||
| @@ -22,9 +24,11 @@ from decimal import Decimal | |||||||
| from datetime import datetime, timedelta | from datetime import datetime, timedelta | ||||||
|  |  | ||||||
| import common.models | import common.models | ||||||
|  | from common.settings import currency_code_default, currency_code_mappings | ||||||
|  |  | ||||||
| from company.serializers import SupplierPartSerializer | from company.serializers import SupplierPartSerializer | ||||||
| from part.serializers import PartBriefSerializer | from part.serializers import PartBriefSerializer | ||||||
| from InvenTree.serializers import UserSerializerBrief, InvenTreeModelSerializer | from InvenTree.serializers import UserSerializerBrief, InvenTreeModelSerializer, InvenTreeMoneySerializer | ||||||
| from InvenTree.serializers import InvenTreeAttachmentSerializer, InvenTreeAttachmentSerializerField | from InvenTree.serializers import InvenTreeAttachmentSerializer, InvenTreeAttachmentSerializerField | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -139,17 +143,28 @@ class StockItemSerializer(InvenTreeModelSerializer): | |||||||
|  |  | ||||||
|     required_tests = serializers.IntegerField(source='required_test_count', read_only=True, required=False) |     required_tests = serializers.IntegerField(source='required_test_count', read_only=True, required=False) | ||||||
|  |  | ||||||
|     purchase_price = serializers.SerializerMethodField() |     purchase_price = InvenTreeMoneySerializer( | ||||||
|  |         label=_('Purchase Price'), | ||||||
|  |         max_digits=19, decimal_places=4, | ||||||
|  |         allow_null=True | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |     purchase_price_currency = serializers.ChoiceField( | ||||||
|  |         choices=currency_code_mappings(), | ||||||
|  |         default=currency_code_default, | ||||||
|  |         label=_('Currency'), | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |     purchase_price_string = serializers.SerializerMethodField() | ||||||
|  |  | ||||||
|  |     def get_purchase_price_string(self, obj): | ||||||
|  |  | ||||||
|  |         return str(obj.purchase_price) if obj.purchase_price else '-' | ||||||
|  |  | ||||||
|     purchase_order_reference = serializers.CharField(source='purchase_order.reference', read_only=True) |     purchase_order_reference = serializers.CharField(source='purchase_order.reference', read_only=True) | ||||||
|  |  | ||||||
|     sales_order_reference = serializers.CharField(source='sales_order.reference', read_only=True) |     sales_order_reference = serializers.CharField(source='sales_order.reference', read_only=True) | ||||||
|  |  | ||||||
|     def get_purchase_price(self, obj): |  | ||||||
|         """ Return purchase_price (Money field) as string (includes currency) """ |  | ||||||
|  |  | ||||||
|         return str(obj.purchase_price) if obj.purchase_price else '-' |  | ||||||
|  |  | ||||||
|     def __init__(self, *args, **kwargs): |     def __init__(self, *args, **kwargs): | ||||||
|  |  | ||||||
|         part_detail = kwargs.pop('part_detail', False) |         part_detail = kwargs.pop('part_detail', False) | ||||||
| @@ -208,9 +223,12 @@ class StockItemSerializer(InvenTreeModelSerializer): | |||||||
|             'uid', |             'uid', | ||||||
|             'updated', |             'updated', | ||||||
|             'purchase_price', |             'purchase_price', | ||||||
|  |             'purchase_price_currency', | ||||||
|  |             'purchase_price_string', | ||||||
|         ] |         ] | ||||||
|  |  | ||||||
|         """ These fields are read-only in this context. |         """ | ||||||
|  |         These fields are read-only in this context. | ||||||
|         They can be updated by accessing the appropriate API endpoints |         They can be updated by accessing the appropriate API endpoints | ||||||
|         """ |         """ | ||||||
|         read_only_fields = [ |         read_only_fields = [ | ||||||
|   | |||||||
| @@ -428,6 +428,67 @@ class StockItemTest(StockAPITestCase): | |||||||
|  |  | ||||||
|         self.assertEqual(response.data['expiry_date'], expiry.isoformat()) |         self.assertEqual(response.data['expiry_date'], expiry.isoformat()) | ||||||
|  |  | ||||||
|  |     def test_purchase_price(self): | ||||||
|  |         """ | ||||||
|  |         Test that we can correctly read and adjust purchase price information via the API | ||||||
|  |         """ | ||||||
|  |  | ||||||
|  |         url = reverse('api-stock-detail', kwargs={'pk': 1}) | ||||||
|  |  | ||||||
|  |         data = self.get(url, expected_code=200).data | ||||||
|  |  | ||||||
|  |         # Check fixture values | ||||||
|  |         self.assertEqual(data['purchase_price'], '123.0000') | ||||||
|  |         self.assertEqual(data['purchase_price_currency'], 'AUD') | ||||||
|  |         self.assertEqual(data['purchase_price_string'], 'A$123.0000') | ||||||
|  |  | ||||||
|  |         # Update just the amount | ||||||
|  |         data = self.patch( | ||||||
|  |             url, | ||||||
|  |             { | ||||||
|  |                 'purchase_price': 456 | ||||||
|  |             }, | ||||||
|  |             expected_code=200 | ||||||
|  |         ).data | ||||||
|  |  | ||||||
|  |         self.assertEqual(data['purchase_price'], '456.0000') | ||||||
|  |         self.assertEqual(data['purchase_price_currency'], 'AUD') | ||||||
|  |  | ||||||
|  |         # Update the currency | ||||||
|  |         data = self.patch( | ||||||
|  |             url, | ||||||
|  |             { | ||||||
|  |                 'purchase_price_currency': 'NZD', | ||||||
|  |             }, | ||||||
|  |             expected_code=200 | ||||||
|  |         ).data | ||||||
|  |  | ||||||
|  |         self.assertEqual(data['purchase_price_currency'], 'NZD') | ||||||
|  |  | ||||||
|  |         # Clear the price field | ||||||
|  |         data = self.patch( | ||||||
|  |             url, | ||||||
|  |             { | ||||||
|  |                 'purchase_price': None, | ||||||
|  |             }, | ||||||
|  |             expected_code=200 | ||||||
|  |         ).data | ||||||
|  |  | ||||||
|  |         self.assertEqual(data['purchase_price'], None) | ||||||
|  |         self.assertEqual(data['purchase_price_string'], '-') | ||||||
|  |  | ||||||
|  |         # Invalid currency code | ||||||
|  |         data = self.patch( | ||||||
|  |             url, | ||||||
|  |             { | ||||||
|  |                 'purchase_price_currency': 'xyz', | ||||||
|  |             }, | ||||||
|  |             expected_code=400 | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         data = self.get(url).data | ||||||
|  |         self.assertEqual(data['purchase_price_currency'], 'NZD') | ||||||
|  |  | ||||||
|  |  | ||||||
| class StocktakeTest(StockAPITestCase): | class StocktakeTest(StockAPITestCase): | ||||||
|     """ |     """ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user