diff --git a/docs/docs/report/samples.md b/docs/docs/report/samples.md
index d6dff5678b..ed00e5ec43 100644
--- a/docs/docs/report/samples.md
+++ b/docs/docs/report/samples.md
@@ -19,6 +19,7 @@ The following report templates are provided "out of the box" and can be used as
| [Purchase Order](#purchase-order) | [PurchaseOrder](../order/purchase_order.md) | Purchase Order report |
| [Return Order](#return-order) | [ReturnOrder](../order/return_order.md) | Return Order report |
| [Sales Order](#sales-order) | [SalesOrder](../order/sales_order.md) | Sales Order report |
+| [Sales Order Shipment](#sales-order-shipment) | [SalesOrderShipment](../order/sales_order.md) | Sales Order Shipment report |
| [Stock Location](#stock-location) | [StockLocation](../stock/stock.md#stock-location) | Stock Location report |
| [Test Report](#test-report) | [StockItem](../stock/stock.md#stock-item) | Test Report |
@@ -42,6 +43,10 @@ The following report templates are provided "out of the box" and can be used as
{{ templatefile("report/inventree_sales_order_report.html") }}
+### Sales Order Shipment
+
+{{ templatefile("report/inventree_sales_order_shipment_report.html") }}
+
### Stock Location
{{ templatefile("report/inventree_stock_location_report.html") }}
diff --git a/src/backend/InvenTree/InvenTree/api_version.py b/src/backend/InvenTree/InvenTree/api_version.py
index 747ef01e37..52525f523d 100644
--- a/src/backend/InvenTree/InvenTree/api_version.py
+++ b/src/backend/InvenTree/InvenTree/api_version.py
@@ -1,13 +1,16 @@
"""InvenTree API version information."""
# InvenTree API version
-INVENTREE_API_VERSION = 262
+INVENTREE_API_VERSION = 263
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
INVENTREE_API_TEXT = """
+263 - 2024-09-30 : https://github.com/inventree/InvenTree/pull/8194
+ - Adds Sales Order Shipment report
+
262 - 2024-09-30 : https://github.com/inventree/InvenTree/pull/8220
- Tweak permission requirements for uninstalling plugins via API
diff --git a/src/backend/InvenTree/order/models.py b/src/backend/InvenTree/order/models.py
index f0b61df84a..13372fc2c0 100644
--- a/src/backend/InvenTree/order/models.py
+++ b/src/backend/InvenTree/order/models.py
@@ -1739,6 +1739,7 @@ class SalesOrderLineItem(OrderLineItem):
class SalesOrderShipment(
InvenTree.models.InvenTreeNotesMixin,
+ report.mixins.InvenTreeReportMixin,
InvenTree.models.MetadataMixin,
InvenTree.models.InvenTreeModel,
):
@@ -1768,6 +1769,17 @@ class SalesOrderShipment(
"""Return the API URL associated with the SalesOrderShipment model."""
return reverse('api-so-shipment-list')
+ def report_context(self):
+ """Generate context data for the reporting interface."""
+ return {
+ 'allocations': self.allocations,
+ 'order': self.order,
+ 'reference': self.reference,
+ 'shipment': self,
+ 'tracking_number': self.tracking_number,
+ 'title': str(self),
+ }
+
order = models.ForeignKey(
SalesOrder,
on_delete=models.CASCADE,
diff --git a/src/backend/InvenTree/report/apps.py b/src/backend/InvenTree/report/apps.py
index 83e2979614..1018a28835 100644
--- a/src/backend/InvenTree/report/apps.py
+++ b/src/backend/InvenTree/report/apps.py
@@ -173,6 +173,13 @@ class ReportConfig(AppConfig):
'model_type': 'salesorder',
'filename_pattern': 'SalesOrder-{{ reference }}.pdf',
},
+ {
+ 'file': 'inventree_sales_order_shipment_report.html',
+ 'name': 'InvenTree Sales Order Shipment',
+ 'description': 'Sample sales order shipment report',
+ 'model_type': 'salesordershipment',
+ 'filename_pattern': 'SalesOrderShipment-{{ reference }}.pdf',
+ },
{
'file': 'inventree_return_order_report.html',
'name': 'InvenTree Return Order',
diff --git a/src/backend/InvenTree/report/templates/report/inventree_sales_order_shipment_report.html b/src/backend/InvenTree/report/templates/report/inventree_sales_order_shipment_report.html
new file mode 100644
index 0000000000..98aab3e4ed
--- /dev/null
+++ b/src/backend/InvenTree/report/templates/report/inventree_sales_order_shipment_report.html
@@ -0,0 +1,56 @@
+{% extends "report/inventree_order_report_base.html" %}
+
+{% load i18n %}
+{% load report %}
+{% load barcode %}
+{% load inventree_extras %}
+{% load markdownify %}
+
+{% block header_content %}
+
+
+
+
{% trans "Part" %} | +{% trans "Stock Item" %} | +||
---|---|---|---|
+
+
+
+ {{ allocation.line.part.full_name }}
+
+ |
+
+ {% if allocation.item and allocation.item.serial and allocation.quantity == 1 %}
+ {% trans "Serial Number" %}: {{ allocation.item.serial }} | + {% elif allocation.item and allocation.item.batch %} +{% trans "Quantity" %}: {% decimal allocation.quantity %} - {% trans "Batch" %}: {{ allocation.item.batch }} | + {% else %} +{% trans "Quantity" %}: {% decimal allocation.quantity %} | + {% endif %} +