Merge pull request #2003 from SchrodingersGat/edit-purchase-prices

Edit purchase prices
This commit is contained in:
Oliver 2021-08-23 22:54:12 +10:00 committed by GitHub
commit f136c974cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 113 additions and 20 deletions

View File

@ -46,10 +46,12 @@ class InvenTreeMoneySerializer(MoneyField):
amount = None
try:
if amount is not None:
if amount is not None and amount is not empty:
amount = Decimal(amount)
except:
raise ValidationError(_("Must be a valid number"))
raise ValidationError({
self.field_name: _("Must be a valid number")
})
currency = data.get(get_currency_field_name(self.field_name), self.default_currency)

View File

@ -10,34 +10,39 @@ import common.models
INVENTREE_SW_VERSION = "0.5.0 pre"
INVENTREE_API_VERSION = 9
INVENTREE_API_VERSION = 10
"""
Increment this API version number whenever there is a significant change to the API that any clients need to know about
v9 -> 2021-08-09
v10 -> 2021-08-23
- Adds "purchase_price_currency" to StockItem serializer
- Adds "purchase_price_string" to StockItem serializer
- Purchase price is now writable for StockItem serializer
v9 -> 2021-08-09
- Adds "price_string" to part pricing serializers
v8 -> 2021-07-19
v8 -> 2021-07-19
- Refactors the API interface for SupplierPart and ManufacturerPart models
- ManufacturerPart objects can no longer be created via the SupplierPart API endpoint
v7 -> 2021-07-03
v7 -> 2021-07-03
- Introduced the concept of "API forms" in https://github.com/inventree/InvenTree/pull/1716
- API OPTIONS endpoints provide comprehensive field metedata
- Multiple new API endpoints added for database models
v6 -> 2021-06-23
v6 -> 2021-06-23
- Part and Company images can now be directly uploaded via the REST API
v5 -> 2021-06-21
v5 -> 2021-06-21
- Adds API interface for manufacturer part parameters
v4 -> 2021-06-01
v4 -> 2021-06-01
- BOM items can now accept "variant stock" to be assigned against them
- Many slight API tweaks were needed to get this to work properly!
v3 -> 2021-05-22:
v3 -> 2021-05-22:
- The updated StockItem "history tracking" now uses a different interface
"""

View File

@ -26,6 +26,11 @@ from django.core.exceptions import ValidationError
import InvenTree.helpers
import InvenTree.fields
import logging
logger = logging.getLogger('inventree')
class BaseInvenTreeSetting(models.Model):
"""
@ -1040,7 +1045,7 @@ class PriceBreak(models.Model):
try:
converted = convert_money(self.price, currency_code)
except MissingRate:
print(f"WARNING: No currency conversion rate available for {self.price_currency} -> {currency_code}")
logger.warning(f"No currency conversion rate available for {self.price_currency} -> {currency_code}")
return self.price.amount
return converted.amount

View File

@ -12,6 +12,8 @@
tree_id: 0
lft: 0
rght: 0
purchase_price: 123
purchase_price_currency: AUD
# 5,000 screws in the bathroom
- model: stock.stockitem

View File

@ -4,6 +4,8 @@ JSON serializers for Stock app
from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _
from .models import StockItem, StockLocation
from .models import StockItemTracking
from .models import StockItemAttachment
@ -22,9 +24,11 @@ from decimal import Decimal
from datetime import datetime, timedelta
import common.models
from common.settings import currency_code_default, currency_code_mappings
from company.serializers import SupplierPartSerializer
from part.serializers import PartBriefSerializer
from InvenTree.serializers import UserSerializerBrief, InvenTreeModelSerializer
from InvenTree.serializers import UserSerializerBrief, InvenTreeModelSerializer, InvenTreeMoneySerializer
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)
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)
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):
part_detail = kwargs.pop('part_detail', False)
@ -208,9 +223,12 @@ class StockItemSerializer(InvenTreeModelSerializer):
'uid',
'updated',
'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
"""
read_only_fields = [

View File

@ -428,6 +428,67 @@ class StockItemTest(StockAPITestCase):
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):
"""

View File

@ -1080,7 +1080,7 @@ function loadStockTable(table, options) {
}
},
{
field: 'purchase_price',
field: 'purchase_price_string',
title: '{% trans "Purchase Price" %}',
sortable: true,
},