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:
Oliver 2021-08-23 21:44:12 +10:00
parent d267d04bed
commit bb8b85c375
3 changed files with 89 additions and 8 deletions

View File

@ -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

View File

@ -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 = [

View File

@ -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):
""" """