mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-30 12:45:42 +00:00 
			
		
		
		
	Adds detail page for ReturnOrder
This commit is contained in:
		| @@ -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.""" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user