mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-18 13:05:42 +00:00
* Fix check for static dir * Fix export price field for SalesOrderLineItem * Automatically detect which non-nullable fields need conversion * Fix bug during import - fulfilled_quantity and allocated_quantity must have a pk - Cannot work before imported!
374 lines
10 KiB
Python
374 lines
10 KiB
Python
"""Admin functionality for the 'order' app."""
|
|
|
|
from django.contrib import admin
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
from import_export import widgets
|
|
from import_export.admin import ImportExportModelAdmin
|
|
from import_export.fields import Field
|
|
|
|
import stock.models
|
|
from InvenTree.admin import InvenTreeResource
|
|
from order import models
|
|
|
|
|
|
class ProjectCodeResourceMixin:
|
|
"""Mixin for exporting project code data."""
|
|
|
|
project_code = Field(attribute='project_code', column_name=_('Project Code'))
|
|
|
|
def dehydrate_project_code(self, order):
|
|
"""Return the project code value, not the pk."""
|
|
if order.project_code:
|
|
return order.project_code.code
|
|
return ''
|
|
|
|
|
|
class TotalPriceResourceMixin:
|
|
"""Mixin for exporting total price data."""
|
|
|
|
total_price = Field(attribute='total_price', column_name=_('Total Price'))
|
|
|
|
def dehydrate_total_price(self, order):
|
|
"""Return the total price amount, not the object itself."""
|
|
if order.total_price:
|
|
return order.total_price.amount
|
|
return ''
|
|
|
|
|
|
class PriceResourceMixin:
|
|
"""Mixin for 'price' field."""
|
|
|
|
price = Field(attribute='price', column_name=_('Price'))
|
|
|
|
def dehydrate_price(self, line):
|
|
"""Return the price amount, not the object itself."""
|
|
if line.price:
|
|
return line.price.amount
|
|
return ''
|
|
|
|
|
|
# region general classes
|
|
class GeneralExtraLineAdmin:
|
|
"""Admin class template for the 'ExtraLineItem' models."""
|
|
|
|
list_display = ('order', 'quantity', 'reference')
|
|
|
|
search_fields = ['order__reference', 'order__customer__name', 'reference']
|
|
|
|
autocomplete_fields = ('order',)
|
|
|
|
|
|
class GeneralExtraLineMeta:
|
|
"""Metaclass template for the 'ExtraLineItem' models."""
|
|
|
|
skip_unchanged = True
|
|
report_skipped = False
|
|
clean_model_instances = True
|
|
|
|
|
|
# endregion
|
|
|
|
|
|
class PurchaseOrderLineItemInlineAdmin(admin.StackedInline):
|
|
"""Inline admin class for the PurchaseOrderLineItem model."""
|
|
|
|
model = models.PurchaseOrderLineItem
|
|
extra = 0
|
|
|
|
|
|
class PurchaseOrderResource(
|
|
ProjectCodeResourceMixin, TotalPriceResourceMixin, InvenTreeResource
|
|
):
|
|
"""Class for managing import / export of PurchaseOrder data."""
|
|
|
|
class Meta:
|
|
"""Metaclass options."""
|
|
|
|
model = models.PurchaseOrder
|
|
skip_unchanged = True
|
|
clean_model_instances = True
|
|
exclude = ['metadata']
|
|
|
|
# Add number of line items
|
|
line_items = Field(
|
|
attribute='line_count', widget=widgets.IntegerWidget(), readonly=True
|
|
)
|
|
|
|
# Is this order overdue?
|
|
overdue = Field(
|
|
attribute='is_overdue', widget=widgets.BooleanWidget(), readonly=True
|
|
)
|
|
|
|
|
|
class PurchaseOrderAdmin(ImportExportModelAdmin):
|
|
"""Admin class for the PurchaseOrder model."""
|
|
|
|
resource_class = PurchaseOrderResource
|
|
|
|
exclude = ['reference_int']
|
|
|
|
list_display = ('reference', 'supplier', 'status', 'description', 'creation_date')
|
|
|
|
search_fields = ['reference', 'supplier__name', 'description']
|
|
|
|
inlines = [PurchaseOrderLineItemInlineAdmin]
|
|
|
|
autocomplete_fields = ('supplier',)
|
|
|
|
|
|
class SalesOrderResource(
|
|
ProjectCodeResourceMixin, TotalPriceResourceMixin, InvenTreeResource
|
|
):
|
|
"""Class for managing import / export of SalesOrder data."""
|
|
|
|
class Meta:
|
|
"""Metaclass options."""
|
|
|
|
model = models.SalesOrder
|
|
skip_unchanged = True
|
|
clean_model_instances = True
|
|
exclude = ['metadata']
|
|
|
|
# Add number of line items
|
|
line_items = Field(
|
|
attribute='line_count', widget=widgets.IntegerWidget(), readonly=True
|
|
)
|
|
|
|
# Is this order overdue?
|
|
overdue = Field(
|
|
attribute='is_overdue', widget=widgets.BooleanWidget(), readonly=True
|
|
)
|
|
|
|
|
|
class SalesOrderAdmin(ImportExportModelAdmin):
|
|
"""Admin class for the SalesOrder model."""
|
|
|
|
resource_class = SalesOrderResource
|
|
|
|
exclude = ['reference_int']
|
|
|
|
list_display = ('reference', 'customer', 'status', 'description', 'creation_date')
|
|
|
|
search_fields = ['reference', 'customer__name', 'description']
|
|
|
|
autocomplete_fields = ('customer',)
|
|
|
|
|
|
class PurchaseOrderLineItemResource(PriceResourceMixin, InvenTreeResource):
|
|
"""Class for managing import / export of PurchaseOrderLineItem data."""
|
|
|
|
class Meta:
|
|
"""Metaclass."""
|
|
|
|
model = models.PurchaseOrderLineItem
|
|
skip_unchanged = True
|
|
report_skipped = False
|
|
clean_model_instances = True
|
|
|
|
part_name = Field(attribute='part__part__name', readonly=True)
|
|
|
|
manufacturer = Field(attribute='part__manufacturer', readonly=True)
|
|
|
|
MPN = Field(attribute='part__MPN', readonly=True)
|
|
|
|
SKU = Field(attribute='part__SKU', readonly=True)
|
|
|
|
destination = Field(
|
|
attribute='destination',
|
|
widget=widgets.ForeignKeyWidget(stock.models.StockLocation),
|
|
)
|
|
|
|
def dehydrate_purchase_price(self, line):
|
|
"""Return a string value of the 'purchase_price' field, rather than the 'Money' object."""
|
|
if line.purchase_price:
|
|
return line.purchase_price.amount
|
|
return ''
|
|
|
|
|
|
class PurchaseOrderExtraLineResource(PriceResourceMixin, InvenTreeResource):
|
|
"""Class for managing import / export of PurchaseOrderExtraLine data."""
|
|
|
|
class Meta(GeneralExtraLineMeta):
|
|
"""Metaclass options."""
|
|
|
|
model = models.PurchaseOrderExtraLine
|
|
|
|
|
|
class SalesOrderLineItemResource(PriceResourceMixin, InvenTreeResource):
|
|
"""Class for managing import / export of SalesOrderLineItem data."""
|
|
|
|
class Meta:
|
|
"""Metaclass options."""
|
|
|
|
model = models.SalesOrderLineItem
|
|
skip_unchanged = True
|
|
report_skipped = False
|
|
clean_model_instances = True
|
|
|
|
part_name = Field(attribute='part__name', readonly=True)
|
|
|
|
IPN = Field(attribute='part__IPN', readonly=True)
|
|
|
|
description = Field(attribute='part__description', readonly=True)
|
|
|
|
fulfilled = Field(attribute='fulfilled_quantity', readonly=True)
|
|
|
|
def dehydrate_sale_price(self, item):
|
|
"""Return a string value of the 'sale_price' field, rather than the 'Money' object.
|
|
|
|
Ref: https://github.com/inventree/InvenTree/issues/2207
|
|
"""
|
|
if item.sale_price:
|
|
return item.sale_price.amount
|
|
return ''
|
|
|
|
|
|
class SalesOrderExtraLineResource(PriceResourceMixin, InvenTreeResource):
|
|
"""Class for managing import / export of SalesOrderExtraLine data."""
|
|
|
|
class Meta(GeneralExtraLineMeta):
|
|
"""Metaclass options."""
|
|
|
|
model = models.SalesOrderExtraLine
|
|
|
|
|
|
class PurchaseOrderLineItemAdmin(ImportExportModelAdmin):
|
|
"""Admin class for the PurchaseOrderLine model."""
|
|
|
|
resource_class = PurchaseOrderLineItemResource
|
|
|
|
list_display = ('order', 'part', 'quantity', 'reference')
|
|
|
|
search_fields = ('reference',)
|
|
|
|
autocomplete_fields = ('order', 'part', 'destination')
|
|
|
|
|
|
class PurchaseOrderExtraLineAdmin(GeneralExtraLineAdmin, ImportExportModelAdmin):
|
|
"""Admin class for the PurchaseOrderExtraLine model."""
|
|
|
|
resource_class = PurchaseOrderExtraLineResource
|
|
|
|
|
|
class SalesOrderLineItemAdmin(ImportExportModelAdmin):
|
|
"""Admin class for the SalesOrderLine model."""
|
|
|
|
resource_class = SalesOrderLineItemResource
|
|
|
|
list_display = ('order', 'part', 'quantity', 'reference')
|
|
|
|
search_fields = [
|
|
'part__name',
|
|
'order__reference',
|
|
'order__customer__name',
|
|
'reference',
|
|
]
|
|
|
|
autocomplete_fields = ('order', 'part')
|
|
|
|
|
|
class SalesOrderExtraLineAdmin(GeneralExtraLineAdmin, ImportExportModelAdmin):
|
|
"""Admin class for the SalesOrderExtraLine model."""
|
|
|
|
resource_class = SalesOrderExtraLineResource
|
|
|
|
|
|
class SalesOrderShipmentAdmin(ImportExportModelAdmin):
|
|
"""Admin class for the SalesOrderShipment model."""
|
|
|
|
list_display = ['order', 'shipment_date', 'reference']
|
|
|
|
search_fields = ['reference', 'order__reference', 'order__customer__name']
|
|
|
|
autocomplete_fields = ('order',)
|
|
|
|
|
|
class SalesOrderAllocationAdmin(ImportExportModelAdmin):
|
|
"""Admin class for the SalesOrderAllocation model."""
|
|
|
|
list_display = ('line', 'item', 'quantity')
|
|
|
|
autocomplete_fields = ('line', 'shipment', 'item')
|
|
|
|
|
|
class ReturnOrderResource(
|
|
ProjectCodeResourceMixin, TotalPriceResourceMixin, InvenTreeResource
|
|
):
|
|
"""Class for managing import / export of ReturnOrder data."""
|
|
|
|
class Meta:
|
|
"""Metaclass options."""
|
|
|
|
model = models.ReturnOrder
|
|
skip_unchanged = True
|
|
clean_model_instances = True
|
|
exclude = ['metadata']
|
|
|
|
|
|
class ReturnOrderAdmin(ImportExportModelAdmin):
|
|
"""Admin class for the ReturnOrder model."""
|
|
|
|
resource_class = ReturnOrderResource
|
|
|
|
exclude = ['reference_int']
|
|
|
|
list_display = ['reference', 'customer', 'status']
|
|
|
|
search_fields = ['reference', 'customer__name', 'description']
|
|
|
|
autocomplete_fields = ['customer']
|
|
|
|
|
|
class ReturnOrderLineItemResource(PriceResourceMixin, InvenTreeResource):
|
|
"""Class for managing import / export of ReturnOrderLineItem data."""
|
|
|
|
class Meta:
|
|
"""Metaclass options."""
|
|
|
|
model = models.ReturnOrderLineItem
|
|
skip_unchanged = True
|
|
report_skipped = False
|
|
clean_model_instances = True
|
|
|
|
|
|
class ReturnOrderLineItemAdmin(ImportExportModelAdmin):
|
|
"""Admin class for ReturnOrderLine model."""
|
|
|
|
resource_class = ReturnOrderLineItemResource
|
|
|
|
list_display = ['order', 'item', 'reference']
|
|
|
|
|
|
class ReturnOrderExtraLineClass(PriceResourceMixin, InvenTreeResource):
|
|
"""Class for managing import/export of ReturnOrderExtraLine data."""
|
|
|
|
class Meta(GeneralExtraLineMeta):
|
|
"""Metaclass options."""
|
|
|
|
model = models.ReturnOrderExtraLine
|
|
|
|
|
|
class ReturnOrdeerExtraLineAdmin(GeneralExtraLineAdmin, ImportExportModelAdmin):
|
|
"""Admin class for the ReturnOrderExtraLine model."""
|
|
|
|
resource_class = ReturnOrderExtraLineClass
|
|
|
|
|
|
# Purchase Order models
|
|
admin.site.register(models.PurchaseOrder, PurchaseOrderAdmin)
|
|
admin.site.register(models.PurchaseOrderLineItem, PurchaseOrderLineItemAdmin)
|
|
admin.site.register(models.PurchaseOrderExtraLine, PurchaseOrderExtraLineAdmin)
|
|
|
|
# Sales Order models
|
|
admin.site.register(models.SalesOrder, SalesOrderAdmin)
|
|
admin.site.register(models.SalesOrderLineItem, SalesOrderLineItemAdmin)
|
|
admin.site.register(models.SalesOrderExtraLine, SalesOrderExtraLineAdmin)
|
|
admin.site.register(models.SalesOrderShipment, SalesOrderShipmentAdmin)
|
|
admin.site.register(models.SalesOrderAllocation, SalesOrderAllocationAdmin)
|
|
|
|
# Return Order models
|
|
admin.site.register(models.ReturnOrder, ReturnOrderAdmin)
|
|
admin.site.register(models.ReturnOrderLineItem, ReturnOrderLineItemAdmin)
|
|
admin.site.register(models.ReturnOrderExtraLine, ReturnOrdeerExtraLineAdmin)
|