diff --git a/InvenTree/report/apps.py b/InvenTree/report/apps.py
index e55053b1c1..63c994fa87 100644
--- a/InvenTree/report/apps.py
+++ b/InvenTree/report/apps.py
@@ -22,6 +22,9 @@ class ReportConfig(AppConfig):
if canAppAccessDatabase(allow_test=True):
self.create_default_test_reports()
self.create_default_build_reports()
+ self.create_default_bill_of_materials_reports()
+ self.create_default_purchase_order_reports()
+ self.create_default_sales_order_reports()
def create_default_reports(self, model, reports):
"""Copy defualt report files across to the media directory."""
@@ -96,6 +99,25 @@ class ReportConfig(AppConfig):
self.create_default_reports(TestReport, reports)
+ def create_default_bill_of_materials_reports(self):
+ """Create database entries for the default Bill of Material templates (if they do not already exist)"""
+ try:
+ from .models import BillOfMaterialsReport
+ except Exception: # pragma: no cover
+ # Database is not ready yet
+ return
+
+ # List of Build reports to copy across
+ reports = [
+ {
+ 'file': 'inventree_bill_of_materials_report.html',
+ 'name': 'Bill of Materials',
+ 'description': 'Bill of Materials report',
+ }
+ ]
+
+ self.create_default_reports(BillOfMaterialsReport, reports)
+
def create_default_build_reports(self):
"""Create database entries for the default BuildReport templates (if they do not already exist)"""
try:
@@ -114,3 +136,41 @@ class ReportConfig(AppConfig):
]
self.create_default_reports(BuildReport, reports)
+
+ def create_default_purchase_order_reports(self):
+ """Create database entries for the default SalesOrderReport templates (if they do not already exist)"""
+ try:
+ from .models import PurchaseOrderReport
+ except Exception: # pragma: no cover
+ # Database is not ready yet
+ return
+
+ # List of Build reports to copy across
+ reports = [
+ {
+ 'file': 'inventree_po_report.html',
+ 'name': 'InvenTree Purchase Order',
+ 'description': 'Purchase Order example report',
+ }
+ ]
+
+ self.create_default_reports(PurchaseOrderReport, reports)
+
+ def create_default_sales_order_reports(self):
+ """Create database entries for the default Sales Order report templates (if they do not already exist)"""
+ try:
+ from .models import SalesOrderReport
+ except Exception: # pragma: no cover
+ # Database is not ready yet
+ return
+
+ # List of Build reports to copy across
+ reports = [
+ {
+ 'file': 'inventree_so_report.html',
+ 'name': 'InvenTree Sales Order',
+ 'description': 'Sales Order example report',
+ }
+ ]
+
+ self.create_default_reports(SalesOrderReport, reports)
diff --git a/InvenTree/report/templates/report/inventree_bill_of_materials_report.html b/InvenTree/report/templates/report/inventree_bill_of_materials_report.html
new file mode 100644
index 0000000000..7ed000cf18
--- /dev/null
+++ b/InvenTree/report/templates/report/inventree_bill_of_materials_report.html
@@ -0,0 +1,162 @@
+{% extends "report/inventree_report_base.html" %}
+
+{% load i18n %}
+{% load report %}
+{% load barcode %}
+{% load inventree_extras %}
+
+{% block page_margin %}
+margin: 2cm;
+margin-top: 4cm;
+{% endblock %}
+
+{% block bottom_left %}
+content: "v{{report_revision}} - {{ date.isoformat }}";
+{% endblock %}
+
+{% block bottom_center %}
+content: "{% inventree_version shortstring=True %}";
+{% endblock %}
+
+{% block style %}
+
+.header-right {
+ text-align: right;
+ float: right;
+}
+
+.logo {
+ height: 20mm;
+ vertical-align: middle;
+}
+
+.thumb-container {
+ width: 32px;
+ display: inline;
+}
+
+.part-thumb {
+ max-width: 32px;
+ max-height: 32px;
+ display: inline;
+}
+
+.part-text {
+ display: inline;
+}
+
+.part-logo {
+ max-width: 60px;
+ max-height: 60px;
+ display: inline;
+}
+
+table {
+ border: 1px solid #eee;
+ border-radius: 3px;
+ border-collapse: collapse;
+ width: 100%;
+ font-size: 80%;
+}
+
+table td {
+ border: 1px solid #eee;
+}
+
+table td.shrink {
+ white-space: nowrap
+}
+
+table td.expand {
+ width: 99%
+}
+
+.invisible-table {
+ border: 0px solid transparent;
+ border-collapse: collapse;
+ width: 100%;
+ font-size: 80%;
+}
+
+.invisible-table td {
+ border: 0px solid transparent;
+}
+
+.main-part-text {
+ display: inline;
+}
+
+.main-part-description {
+ display: inline;
+}
+
+{% endblock %}
+
+{% block header_content %}
+
+
+
+
{% trans "Part" %} |
+ |
---|---|
+
+ {{ part.full_name }}
+
+ +
+ {{ part.description }}
+
+ |
+
+
+
+ |
+
{% trans "Part" %} | +{% trans "Quantity" %} | +{% trans "Reference" %} | +{% trans "Note" %} | +
---|---|---|---|
+
+
+
+ {{ line.part.full_name }}
+
+ |
+ {% decimal line.quantity %} | +{{ line.reference }} | +{{ line.notes }} | +