mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-17 12:35:46 +00:00
Merge remote-tracking branch 'inventree/master' into drf-api-forms
This commit is contained in:
@ -10,10 +10,17 @@ from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from mptt.fields import TreeNodeChoiceField
|
||||
|
||||
from djmoney.forms.fields import MoneyField
|
||||
|
||||
from InvenTree.forms import HelperForm
|
||||
from InvenTree.fields import RoundingDecimalFormField
|
||||
from InvenTree.fields import DatePickerFormField
|
||||
|
||||
from InvenTree.helpers import clean_decimal
|
||||
|
||||
from common.models import InvenTreeSetting
|
||||
from common.forms import MatchItemForm
|
||||
|
||||
import part.models
|
||||
|
||||
from stock.models import StockLocation
|
||||
@ -291,3 +298,37 @@ class EditSalesOrderAllocationForm(HelperForm):
|
||||
'line',
|
||||
'item',
|
||||
'quantity']
|
||||
|
||||
|
||||
class OrderMatchItemForm(MatchItemForm):
|
||||
""" Override MatchItemForm fields """
|
||||
|
||||
def get_special_field(self, col_guess, row, file_manager):
|
||||
""" Set special fields """
|
||||
|
||||
# set quantity field
|
||||
if 'quantity' in col_guess.lower():
|
||||
return forms.CharField(
|
||||
required=False,
|
||||
widget=forms.NumberInput(attrs={
|
||||
'name': 'quantity' + str(row['index']),
|
||||
'class': 'numberinput',
|
||||
'type': 'number',
|
||||
'min': '0',
|
||||
'step': 'any',
|
||||
'value': clean_decimal(row.get('quantity', '')),
|
||||
})
|
||||
)
|
||||
# set price field
|
||||
elif 'price' in col_guess.lower():
|
||||
return MoneyField(
|
||||
label=_(col_guess),
|
||||
default_currency=InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY'),
|
||||
decimal_places=5,
|
||||
max_digits=19,
|
||||
required=False,
|
||||
default_amount=clean_decimal(row.get('purchase_price', '')),
|
||||
)
|
||||
|
||||
# return default
|
||||
return super().get_special_field(col_guess, row, file_manager)
|
||||
|
@ -17,8 +17,7 @@ from InvenTree.serializers import InvenTreeAttachmentSerializerField
|
||||
|
||||
from company.serializers import CompanyBriefSerializer, SupplierPartSerializer
|
||||
from part.serializers import PartBriefSerializer
|
||||
from stock.serializers import LocationBriefSerializer
|
||||
from stock.serializers import StockItemSerializer, LocationSerializer
|
||||
from stock.serializers import LocationBriefSerializer, StockItemSerializer, LocationSerializer
|
||||
|
||||
from .models import PurchaseOrder, PurchaseOrderLineItem
|
||||
from .models import PurchaseOrderAttachment, SalesOrderAttachment
|
||||
|
@ -2,6 +2,7 @@
|
||||
{% load inventree_extras %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block form_alert %}
|
||||
{% if form.errors %}
|
||||
@ -67,7 +68,7 @@
|
||||
<td>
|
||||
{% for field in form.visible_fields %}
|
||||
{% if field.name == row.quantity %}
|
||||
{{ field }}
|
||||
{{ field|as_crispy_field }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if row.errors.quantity %}
|
||||
@ -80,19 +81,19 @@
|
||||
{% if item.column.guess == 'Purchase_Price' %}
|
||||
{% for field in form.visible_fields %}
|
||||
{% if field.name == row.purchase_price %}
|
||||
{{ field }}
|
||||
{{ field|as_crispy_field }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% elif item.column.guess == 'Reference' %}
|
||||
{% for field in form.visible_fields %}
|
||||
{% if field.name == row.reference %}
|
||||
{{ field }}
|
||||
{{ field|as_crispy_field }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% elif item.column.guess == 'Notes' %}
|
||||
{% for field in form.visible_fields %}
|
||||
{% if field.name == row.notes %}
|
||||
{{ field }}
|
||||
{{ field|as_crispy_field }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
|
@ -30,7 +30,9 @@ from stock.models import StockItem, StockLocation
|
||||
from part.models import Part
|
||||
|
||||
from common.models import InvenTreeSetting
|
||||
from common.forms import UploadFileForm, MatchFieldForm
|
||||
from common.views import FileManagementFormView
|
||||
from common.files import FileManager
|
||||
|
||||
from . import forms as order_forms
|
||||
from part.views import PartPricing
|
||||
@ -572,7 +574,28 @@ class SalesOrderShip(AjaxUpdateView):
|
||||
class PurchaseOrderUpload(FileManagementFormView):
|
||||
''' PurchaseOrder: Upload file, match to fields and parts (using multi-Step form) '''
|
||||
|
||||
class OrderFileManager(FileManager):
|
||||
REQUIRED_HEADERS = [
|
||||
'Quantity',
|
||||
]
|
||||
|
||||
ITEM_MATCH_HEADERS = [
|
||||
'Manufacturer_MPN',
|
||||
'Supplier_SKU',
|
||||
]
|
||||
|
||||
OPTIONAL_HEADERS = [
|
||||
'Purchase_Price',
|
||||
'Reference',
|
||||
'Notes',
|
||||
]
|
||||
|
||||
name = 'order'
|
||||
form_list = [
|
||||
('upload', UploadFileForm),
|
||||
('fields', MatchFieldForm),
|
||||
('items', order_forms.OrderMatchItemForm),
|
||||
]
|
||||
form_steps_template = [
|
||||
'order/order_wizard/po_upload.html',
|
||||
'order/order_wizard/match_fields.html',
|
||||
@ -583,7 +606,6 @@ class PurchaseOrderUpload(FileManagementFormView):
|
||||
_("Match Fields"),
|
||||
_("Match Supplier Parts"),
|
||||
]
|
||||
# Form field name: PurchaseOrderLineItem field
|
||||
form_field_map = {
|
||||
'item_select': 'part',
|
||||
'quantity': 'quantity',
|
||||
@ -591,6 +613,7 @@ class PurchaseOrderUpload(FileManagementFormView):
|
||||
'reference': 'reference',
|
||||
'notes': 'notes',
|
||||
}
|
||||
file_manager_class = OrderFileManager
|
||||
|
||||
def get_order(self):
|
||||
""" Get order or return 404 """
|
||||
@ -598,6 +621,8 @@ class PurchaseOrderUpload(FileManagementFormView):
|
||||
return get_object_or_404(PurchaseOrder, pk=self.kwargs['pk'])
|
||||
|
||||
def get_context_data(self, form, **kwargs):
|
||||
""" Handle context data for order """
|
||||
|
||||
context = super().get_context_data(form=form, **kwargs)
|
||||
|
||||
order = self.get_order()
|
||||
@ -708,26 +733,7 @@ class PurchaseOrderUpload(FileManagementFormView):
|
||||
""" Once all the data is in, process it to add PurchaseOrderLineItem instances to the order """
|
||||
|
||||
order = self.get_order()
|
||||
|
||||
items = {}
|
||||
|
||||
for form_key, form_value in self.get_all_cleaned_data().items():
|
||||
# Split key from row value
|
||||
try:
|
||||
(field, idx) = form_key.split('-')
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
if idx not in items:
|
||||
# Insert into items
|
||||
items.update({
|
||||
idx: {
|
||||
self.form_field_map[field]: form_value,
|
||||
}
|
||||
})
|
||||
else:
|
||||
# Update items
|
||||
items[idx][self.form_field_map[field]] = form_value
|
||||
items = self.get_clean_items()
|
||||
|
||||
# Create PurchaseOrderLineItem instances
|
||||
for purchase_order_item in items.values():
|
||||
|
Reference in New Issue
Block a user