mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Adds detail page for ReturnOrder
This commit is contained in:
parent
e6e76c7a2c
commit
9ae6160353
@ -1122,7 +1122,10 @@ def render_currency(money, decimal_places=None, currency=None, include_symbol=Tr
|
||||
include_symbol: Render with the appropriate currency symbol
|
||||
"""
|
||||
|
||||
if money is None or money.amount is None:
|
||||
if money in [None, '']:
|
||||
return '-'
|
||||
|
||||
if type(money) is not Money:
|
||||
return '-'
|
||||
|
||||
if currency is not None:
|
||||
|
@ -1313,6 +1313,28 @@ class ReturnOrderDetail(RetrieveUpdateDestroyAPI):
|
||||
return self.serializer_class(*args, **kwargs)
|
||||
|
||||
|
||||
class ReturnOrderAttachmentList(AttachmentMixin, ListCreateDestroyAPIView):
|
||||
"""API endpoint for listing (and creating) a ReturnOrderAttachment (file upload)"""
|
||||
|
||||
queryset = models.ReturnOrderAttachment.objects.all()
|
||||
serializer_class = serializers.ReturnOrderAttachmentSerializer
|
||||
|
||||
filter_backends = [
|
||||
rest_filters.DjangoFilterBackend,
|
||||
]
|
||||
|
||||
filterset_fields = [
|
||||
'order',
|
||||
]
|
||||
|
||||
|
||||
class ReturnOrderAttachmentDetail(AttachmentMixin, RetrieveUpdateDestroyAPI):
|
||||
"""Detail endpoint for the ReturnOrderAttachment model"""
|
||||
|
||||
queryset = models.ReturnOrderAttachment.objects.all()
|
||||
serializer_class = serializers.ReturnOrderAttachmentSerializer
|
||||
|
||||
|
||||
class OrderCalendarExport(ICalFeed):
|
||||
"""Calendar export for Purchase/Sales Orders
|
||||
|
||||
@ -1474,7 +1496,7 @@ order_api_urls = [
|
||||
])),
|
||||
|
||||
# Individual purchase order detail URLs
|
||||
re_path(r'^(?P<pk>\d+)/', include([
|
||||
path(r'<int:pk>/', include([
|
||||
re_path(r'^cancel/', PurchaseOrderCancel.as_view(), name='api-po-cancel'),
|
||||
re_path(r'^complete/', PurchaseOrderComplete.as_view(), name='api-po-complete'),
|
||||
re_path(r'^issue/', PurchaseOrderIssue.as_view(), name='api-po-issue'),
|
||||
@ -1509,7 +1531,7 @@ order_api_urls = [
|
||||
])),
|
||||
|
||||
re_path(r'^shipment/', include([
|
||||
re_path(r'^(?P<pk>\d+)/', include([
|
||||
path(r'<int:pk>/', include([
|
||||
path('ship/', SalesOrderShipmentComplete.as_view(), name='api-so-shipment-ship'),
|
||||
re_path(r'^.*$', SalesOrderShipmentDetail.as_view(), name='api-so-shipment-detail'),
|
||||
])),
|
||||
@ -1517,7 +1539,7 @@ order_api_urls = [
|
||||
])),
|
||||
|
||||
# Sales order detail view
|
||||
re_path(r'^(?P<pk>\d+)/', include([
|
||||
path(r'<int:pk>/', include([
|
||||
re_path(r'^allocate/', SalesOrderAllocate.as_view(), name='api-so-allocate'),
|
||||
re_path(r'^allocate-serials/', SalesOrderAllocateSerials.as_view(), name='api-so-allocate-serials'),
|
||||
re_path(r'^cancel/', SalesOrderCancel.as_view(), name='api-so-cancel'),
|
||||
@ -1553,6 +1575,11 @@ order_api_urls = [
|
||||
# API endpoints for return orders
|
||||
re_path(r'^return/', include([
|
||||
|
||||
re_path(r'^attachment/', include([
|
||||
path('<int:pk>/', ReturnOrderAttachmentDetail.as_view(), name='api-return-order-attachment-detail'),
|
||||
re_path(r'^.*$', ReturnOrderAttachmentList.as_view(), name='api-return-order-attachment-list'),
|
||||
])),
|
||||
|
||||
# Return Order detail
|
||||
path('<int:pk>/', ReturnOrderDetail.as_view(), name='api-return-order-detail'),
|
||||
|
||||
|
115
InvenTree/order/templates/order/return_order_base.html
Normal file
115
InvenTree/order/templates/order/return_order_base.html
Normal file
@ -0,0 +1,115 @@
|
||||
{% extends "page_base.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% load inventree_extras %}
|
||||
{% load status_codes %}
|
||||
|
||||
{% block page_title %}
|
||||
{% inventree_title %} | {% trans "Return Order" %}
|
||||
{% endblock page_title %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<li class='breadcrumb-item'><a href='{% url "return-order-index" %}'>{% trans "Return Orders" %}</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page"><a href='{% url "return-order-detail" order.id %}'>{{ order }}</a></li>
|
||||
{% endblock breadcrumbs %}
|
||||
|
||||
{% block thumbnail %}
|
||||
<img class='part-thumb'
|
||||
{% if order.customer and order.customer.image %}
|
||||
src="{{ order.customer.image.url }}"
|
||||
{% else %}
|
||||
src="{% static 'img/blank_image.png' %}"
|
||||
{% endif %}
|
||||
/>
|
||||
{% endblock thumbnail%}
|
||||
|
||||
{% block heading %}
|
||||
{% trans "Return Order" %} {{ order.reference }}
|
||||
{% endblock heading %}
|
||||
|
||||
{% block actions %}
|
||||
{% if user.is_staff and roles.return_order.change %}
|
||||
{% url 'admin:order_returnorder_change' order.pk as url %}
|
||||
{% include "admin_button.html" with url=url %}
|
||||
{% endif %}
|
||||
<!-- TODO: Printing actions -->
|
||||
<!-- TODO: Order actions-->
|
||||
{% endblock actions %}
|
||||
|
||||
{% block details %}
|
||||
|
||||
<table class='table table-striped table-condensed'>
|
||||
<col width='25'>
|
||||
<tr>
|
||||
<td><span class='fas fa-hashtag'></span></td>
|
||||
<td>{% trans "Order Reference" %}</td>
|
||||
<td>{{ order.reference }}{% include "clip.html"%}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class='fas fa-info-circle'></span></td>
|
||||
<td>{% trans "Order Description" %}</td>
|
||||
<td>{{ order.description }}{% include "clip.html" %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class='fas fa-info'></span></td>
|
||||
<td>{% trans "Order Status" %}</td>
|
||||
<td>
|
||||
{% return_order_status_label order.status %}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{% endblock details %}
|
||||
|
||||
{% block details_right %}
|
||||
<table class='table table-striped table-condensed'>
|
||||
<col width='25'>
|
||||
{% if order.customer %}
|
||||
<tr>
|
||||
<td><span class='fas fa-building'></span></td>
|
||||
<td>{% trans "Customer" %}</td>
|
||||
<td><a href="{% url 'company-detail' order.customer.id %}">{{ order.customer.name }}</a>{% include "clip.html"%}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if order.customer_reference %}
|
||||
<tr>
|
||||
<td><span class='fas fa-hashtag'></span></td>
|
||||
<td>{% trans "Customer Reference" %}</td>
|
||||
<td>{{ order.customer_reference }}{% include "clip.html"%}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if order.link %}
|
||||
<tr>
|
||||
<td><span class='fas fa-link'></span></td>
|
||||
<td>External Link</td>
|
||||
<td><a href="{{ order.link }}">{{ order.link }}</a>{% include "clip.html"%}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<td><span class='fas fa-calendar-alt'></span></td>
|
||||
<td>{% trans "Created" %}</td>
|
||||
<td>{% render_date order.creation_date %}<span class='badge badge-right rounded-pill bg-dark'>{{ order.created_by }}</span></td>
|
||||
</tr>
|
||||
{% if order.responsible %}
|
||||
<tr>
|
||||
<td><span class='fas fa-users'></span></td>
|
||||
<td>{% trans "Responsible" %}</td>
|
||||
<td>{{ order.responsible }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</table>
|
||||
{% endblock details_right %}
|
||||
|
||||
{% block js_ready %}
|
||||
{{ block.super }}
|
||||
|
||||
<!-- TODO: Javascript callbacks -->
|
||||
|
||||
{% if report_enabled %}
|
||||
<!-- TODO: Report callbacks -->
|
||||
{% endif %}
|
||||
|
||||
<!-- TODO: Export order callback -->
|
||||
|
||||
{% endblock js_ready %}
|
111
InvenTree/order/templates/order/return_order_detail.html
Normal file
111
InvenTree/order/templates/order/return_order_detail.html
Normal file
@ -0,0 +1,111 @@
|
||||
{% extends "order/return_order_base.html" %}
|
||||
|
||||
{% load inventree_extras %}
|
||||
{% load status_codes %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
|
||||
{% block sidebar %}
|
||||
{% include "order/return_order_sidebar.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block page_content %}
|
||||
|
||||
<div class='panel panel-hidden' id='panel-order-details'>
|
||||
<div class='panel-heading'>
|
||||
<h4>{% trans "Order Details" %}</h4>
|
||||
{% include "spacer.html" %}
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<!-- TODO: Order details here -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='panel panel-hidden' id='panel-order-attachments'>
|
||||
<div class='panel-heading'>
|
||||
<div class='d-flex flex-wrap'>
|
||||
<h4>{% trans "Attachments" %}</h4>
|
||||
{% include "spacer.html" %}
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "attachment_button.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
{% include "attachment_table.html" %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='panel panel-hidden' id='panel-order-notes'>
|
||||
<div class='panel-heading'>
|
||||
<div class='d-flex flex-wrap'>
|
||||
<h4>{% trans "Order Notes" %}</h4>
|
||||
{% include "spacer.html" %}
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "notes_buttons.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<textarea id='order-notes'></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock page_content %}
|
||||
|
||||
{% block js_ready %}
|
||||
{{ block.super }}
|
||||
|
||||
// Callback function when the 'details' panel is loaded
|
||||
onPanelLoad('order-details', function() {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// Callback function when the 'notes' panel is loaded
|
||||
onPanelLoad('order-notes', function() {
|
||||
setupNotesField(
|
||||
'order-notes',
|
||||
'{% url "api-return-order-detail" order.pk %}',
|
||||
{
|
||||
{% if roles.purchase_order.change %}
|
||||
editable: true,
|
||||
{% else %}
|
||||
editable: false,
|
||||
{% endif %}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Callback function when the 'attachments' panel is loaded
|
||||
onPanelLoad('order-attachments', function() {
|
||||
enableDragAndDrop(
|
||||
'#attachment-dropzone',
|
||||
'{% url "api-return-order-attachment-list" %}',
|
||||
{
|
||||
data: {
|
||||
order: {{ order.id }},
|
||||
},
|
||||
label: 'attachment',
|
||||
success: function(data, status, xhr) {
|
||||
reloadAttachmentTable();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
loadAttachmentTable('{% url "api-return-order-attachment-list" %}', {
|
||||
filters: {
|
||||
order: {{ order.pk }},
|
||||
},
|
||||
fields: {
|
||||
order: {
|
||||
value: {{ order.pk }},
|
||||
hidden: true,
|
||||
},
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
enableSidebar('returnorder');
|
||||
|
||||
{% endblock js_ready %}
|
10
InvenTree/order/templates/order/return_order_sidebar.html
Normal file
10
InvenTree/order/templates/order/return_order_sidebar.html
Normal file
@ -0,0 +1,10 @@
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% load inventree_extras %}
|
||||
|
||||
{% trans "Order Details" as text %}
|
||||
{% include "sidebar_item.html" with label='order-details' text=text icon="fa-info-circle" %}
|
||||
{% trans "Attachments" as text %}
|
||||
{% include "sidebar_item.html" with label='order-attachments' text=text icon="fa-paperclip" %}
|
||||
{% trans "Notes" as text %}
|
||||
{% include "sidebar_item.html" with label='order-notes' text=text icon="fa-clipboard" %}
|
@ -209,30 +209,32 @@
|
||||
);
|
||||
});
|
||||
|
||||
enableDragAndDrop(
|
||||
'#attachment-dropzone',
|
||||
'{% url "api-so-attachment-list" %}',
|
||||
{
|
||||
data: {
|
||||
order: {{ order.id }},
|
||||
},
|
||||
label: 'attachment',
|
||||
success: function(data, status, xhr) {
|
||||
reloadAttachmentTable();
|
||||
onPanelLoad('order-attachments', function() {
|
||||
enableDragAndDrop(
|
||||
'#attachment-dropzone',
|
||||
'{% url "api-so-attachment-list" %}',
|
||||
{
|
||||
data: {
|
||||
order: {{ order.id }},
|
||||
},
|
||||
label: 'attachment',
|
||||
success: function(data, status, xhr) {
|
||||
reloadAttachmentTable();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
loadAttachmentTable('{% url "api-so-attachment-list" %}', {
|
||||
filters: {
|
||||
order: {{ order.pk }},
|
||||
},
|
||||
fields: {
|
||||
order: {
|
||||
value: {{ order.pk }},
|
||||
hidden: true,
|
||||
loadAttachmentTable('{% url "api-so-attachment-list" %}', {
|
||||
filters: {
|
||||
order: {{ order.pk }},
|
||||
},
|
||||
}
|
||||
fields: {
|
||||
order: {
|
||||
value: {{ order.pk }},
|
||||
hidden: true,
|
||||
},
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
loadBuildTable($("#builds-table"), {
|
||||
|
@ -4,7 +4,7 @@
|
||||
- Detail view of Purchase Orders
|
||||
"""
|
||||
|
||||
from django.urls import include, re_path
|
||||
from django.urls import include, path, re_path
|
||||
|
||||
from . import views
|
||||
|
||||
@ -21,7 +21,7 @@ purchase_order_urls = [
|
||||
re_path(r'^pricing/', views.LineItemPricing.as_view(), name='line-pricing'),
|
||||
|
||||
# Display detail view for a single purchase order
|
||||
re_path(r'^(?P<pk>\d+)/', include(purchase_order_detail_urls)),
|
||||
path(r'<int:pk>/', include(purchase_order_detail_urls)),
|
||||
|
||||
# Display complete list of purchase orders
|
||||
re_path(r'^.*$', views.PurchaseOrderIndex.as_view(), name='purchase-order-index'),
|
||||
@ -35,7 +35,7 @@ sales_order_detail_urls = [
|
||||
|
||||
sales_order_urls = [
|
||||
# Display detail view for a single SalesOrder
|
||||
re_path(r'^(?P<pk>\d+)/', include(sales_order_detail_urls)),
|
||||
path(r'<int:pk>/', include(sales_order_detail_urls)),
|
||||
|
||||
# Display list of all sales orders
|
||||
re_path(r'^.*$', views.SalesOrderIndex.as_view(), name='sales-order-index'),
|
||||
@ -43,6 +43,7 @@ sales_order_urls = [
|
||||
|
||||
|
||||
return_order_urls = [
|
||||
path(r'<int:pk>/', views.ReturnOrderDetail.as_view(), name='return-order-detail'),
|
||||
|
||||
# Display list of all return orders
|
||||
re_path(r'^.*$', views.ReturnOrderIndex.as_view(), name='return-order-index'),
|
||||
|
@ -75,6 +75,14 @@ class SalesOrderDetail(InvenTreeRoleMixin, InvenTreePluginViewMixin, DetailView)
|
||||
template_name = 'order/sales_order_detail.html'
|
||||
|
||||
|
||||
class ReturnOrderDetail(InvenTreeRoleMixin, InvenTreePluginViewMixin, DetailView):
|
||||
"""Detail view for a ReturnOrder object"""
|
||||
|
||||
context_object_name = 'order'
|
||||
queryset = ReturnOrder.objects.all()
|
||||
template_name = 'order/return_order_detail.html'
|
||||
|
||||
|
||||
class PurchaseOrderUpload(FileManagementFormView):
|
||||
"""PurchaseOrder: Upload file, match to fields and parts (using multi-Step form)"""
|
||||
|
||||
|
@ -4,7 +4,8 @@ from django import template
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from InvenTree.status_codes import (BuildStatus, PurchaseOrderStatus,
|
||||
SalesOrderStatus, StockStatus)
|
||||
ReturnOrderStatus, SalesOrderStatus,
|
||||
StockStatus)
|
||||
|
||||
register = template.Library()
|
||||
|
||||
@ -21,6 +22,12 @@ def sales_order_status_label(key, *args, **kwargs):
|
||||
return mark_safe(SalesOrderStatus.render(key, large=kwargs.get('large', False)))
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def return_order_status_label(key, *args, **kwargs):
|
||||
"""Render a ReturnOrder status label"""
|
||||
return mark_safe(ReturnOrderStatus.render(key, large=kwargs.get('large', False)))
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def stock_status_label(key, *args, **kwargs):
|
||||
"""Render a StockItem status label."""
|
||||
|
Loading…
Reference in New Issue
Block a user