mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 05:05: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 |         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 '-' |         return '-' | ||||||
|  |  | ||||||
|     if currency is not None: |     if currency is not None: | ||||||
|   | |||||||
| @@ -1313,6 +1313,28 @@ class ReturnOrderDetail(RetrieveUpdateDestroyAPI): | |||||||
|         return self.serializer_class(*args, **kwargs) |         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): | class OrderCalendarExport(ICalFeed): | ||||||
|     """Calendar export for Purchase/Sales Orders |     """Calendar export for Purchase/Sales Orders | ||||||
|  |  | ||||||
| @@ -1474,7 +1496,7 @@ order_api_urls = [ | |||||||
|         ])), |         ])), | ||||||
|  |  | ||||||
|         # Individual purchase order detail 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'^cancel/', PurchaseOrderCancel.as_view(), name='api-po-cancel'), | ||||||
|             re_path(r'^complete/', PurchaseOrderComplete.as_view(), name='api-po-complete'), |             re_path(r'^complete/', PurchaseOrderComplete.as_view(), name='api-po-complete'), | ||||||
|             re_path(r'^issue/', PurchaseOrderIssue.as_view(), name='api-po-issue'), |             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'^shipment/', include([ | ||||||
|             re_path(r'^(?P<pk>\d+)/', include([ |             path(r'<int:pk>/', include([ | ||||||
|                 path('ship/', SalesOrderShipmentComplete.as_view(), name='api-so-shipment-ship'), |                 path('ship/', SalesOrderShipmentComplete.as_view(), name='api-so-shipment-ship'), | ||||||
|                 re_path(r'^.*$', SalesOrderShipmentDetail.as_view(), name='api-so-shipment-detail'), |                 re_path(r'^.*$', SalesOrderShipmentDetail.as_view(), name='api-so-shipment-detail'), | ||||||
|             ])), |             ])), | ||||||
| @@ -1517,7 +1539,7 @@ order_api_urls = [ | |||||||
|         ])), |         ])), | ||||||
|  |  | ||||||
|         # Sales order detail view |         # 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/', SalesOrderAllocate.as_view(), name='api-so-allocate'), | ||||||
|             re_path(r'^allocate-serials/', SalesOrderAllocateSerials.as_view(), name='api-so-allocate-serials'), |             re_path(r'^allocate-serials/', SalesOrderAllocateSerials.as_view(), name='api-so-allocate-serials'), | ||||||
|             re_path(r'^cancel/', SalesOrderCancel.as_view(), name='api-so-cancel'), |             re_path(r'^cancel/', SalesOrderCancel.as_view(), name='api-so-cancel'), | ||||||
| @@ -1553,6 +1575,11 @@ order_api_urls = [ | |||||||
|     # API endpoints for return orders |     # API endpoints for return orders | ||||||
|     re_path(r'^return/', include([ |     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 |         # Return Order detail | ||||||
|         path('<int:pk>/', ReturnOrderDetail.as_view(), name='api-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,6 +209,7 @@ | |||||||
|         ); |         ); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|  |     onPanelLoad('order-attachments', function() { | ||||||
|         enableDragAndDrop( |         enableDragAndDrop( | ||||||
|             '#attachment-dropzone', |             '#attachment-dropzone', | ||||||
|             '{% url "api-so-attachment-list" %}', |             '{% url "api-so-attachment-list" %}', | ||||||
| @@ -234,6 +235,7 @@ | |||||||
|                 }, |                 }, | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|     loadBuildTable($("#builds-table"), { |     loadBuildTable($("#builds-table"), { | ||||||
|         locale: '{{ request.LANGUAGE_CODE }}', |         locale: '{{ request.LANGUAGE_CODE }}', | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
| - Detail view of Purchase Orders | - Detail view of Purchase Orders | ||||||
| """ | """ | ||||||
|  |  | ||||||
| from django.urls import include, re_path | from django.urls import include, path, re_path | ||||||
|  |  | ||||||
| from . import views | from . import views | ||||||
|  |  | ||||||
| @@ -21,7 +21,7 @@ purchase_order_urls = [ | |||||||
|     re_path(r'^pricing/', views.LineItemPricing.as_view(), name='line-pricing'), |     re_path(r'^pricing/', views.LineItemPricing.as_view(), name='line-pricing'), | ||||||
|  |  | ||||||
|     # Display detail view for a single purchase order |     # 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 |     # Display complete list of purchase orders | ||||||
|     re_path(r'^.*$', views.PurchaseOrderIndex.as_view(), name='purchase-order-index'), |     re_path(r'^.*$', views.PurchaseOrderIndex.as_view(), name='purchase-order-index'), | ||||||
| @@ -35,7 +35,7 @@ sales_order_detail_urls = [ | |||||||
|  |  | ||||||
| sales_order_urls = [ | sales_order_urls = [ | ||||||
|     # Display detail view for a single SalesOrder |     # 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 |     # Display list of all sales orders | ||||||
|     re_path(r'^.*$', views.SalesOrderIndex.as_view(), name='sales-order-index'), |     re_path(r'^.*$', views.SalesOrderIndex.as_view(), name='sales-order-index'), | ||||||
| @@ -43,6 +43,7 @@ sales_order_urls = [ | |||||||
|  |  | ||||||
|  |  | ||||||
| return_order_urls = [ | return_order_urls = [ | ||||||
|  |     path(r'<int:pk>/', views.ReturnOrderDetail.as_view(), name='return-order-detail'), | ||||||
|  |  | ||||||
|     # Display list of all return orders |     # Display list of all return orders | ||||||
|     re_path(r'^.*$', views.ReturnOrderIndex.as_view(), name='return-order-index'), |     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' |     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): | class PurchaseOrderUpload(FileManagementFormView): | ||||||
|     """PurchaseOrder: Upload file, match to fields and parts (using multi-Step form)""" |     """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 django.utils.safestring import mark_safe | ||||||
|  |  | ||||||
| from InvenTree.status_codes import (BuildStatus, PurchaseOrderStatus, | from InvenTree.status_codes import (BuildStatus, PurchaseOrderStatus, | ||||||
|                                     SalesOrderStatus, StockStatus) |                                     ReturnOrderStatus, SalesOrderStatus, | ||||||
|  |                                     StockStatus) | ||||||
|  |  | ||||||
| register = template.Library() | 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))) |     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 | @register.simple_tag | ||||||
| def stock_status_label(key, *args, **kwargs): | def stock_status_label(key, *args, **kwargs): | ||||||
|     """Render a StockItem status label.""" |     """Render a StockItem status label.""" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user