mirror of
https://github.com/inventree/InvenTree.git
synced 2025-07-01 11:10:54 +00:00
Order barcodes (#4575)
* Add barcode support to external orders - ReturnOrder - PurchaseOrder - SalesOrder * Support scanning for new model types * Integrate UI elements for ReturnOrder * Update PurchaseOrder page * SalesOrder implementation
This commit is contained in:
43
InvenTree/order/migrations/0089_auto_20230404_0030.py
Normal file
43
InvenTree/order/migrations/0089_auto_20230404_0030.py
Normal file
@ -0,0 +1,43 @@
|
||||
# Generated by Django 3.2.18 on 2023-04-04 00:30
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('order', '0088_auto_20230403_1402'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='purchaseorder',
|
||||
name='barcode_data',
|
||||
field=models.CharField(blank=True, help_text='Third party barcode data', max_length=500, verbose_name='Barcode Data'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='purchaseorder',
|
||||
name='barcode_hash',
|
||||
field=models.CharField(blank=True, help_text='Unique hash of barcode data', max_length=128, verbose_name='Barcode Hash'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='returnorder',
|
||||
name='barcode_data',
|
||||
field=models.CharField(blank=True, help_text='Third party barcode data', max_length=500, verbose_name='Barcode Data'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='returnorder',
|
||||
name='barcode_hash',
|
||||
field=models.CharField(blank=True, help_text='Unique hash of barcode data', max_length=128, verbose_name='Barcode Hash'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='salesorder',
|
||||
name='barcode_data',
|
||||
field=models.CharField(blank=True, help_text='Third party barcode data', max_length=500, verbose_name='Barcode Data'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='salesorder',
|
||||
name='barcode_hash',
|
||||
field=models.CharField(blank=True, help_text='Unique hash of barcode data', max_length=128, verbose_name='Barcode Hash'),
|
||||
),
|
||||
]
|
@ -35,7 +35,8 @@ from InvenTree.exceptions import log_error
|
||||
from InvenTree.fields import (InvenTreeModelMoneyField, InvenTreeNotesField,
|
||||
InvenTreeURLField, RoundingDecimalField)
|
||||
from InvenTree.helpers import decimal2string, getSetting, notify_responsible
|
||||
from InvenTree.models import InvenTreeAttachment, ReferenceIndexingMixin
|
||||
from InvenTree.models import (InvenTreeAttachment, InvenTreeBarcodeMixin,
|
||||
ReferenceIndexingMixin)
|
||||
from InvenTree.status_codes import (PurchaseOrderStatus, ReturnOrderLineStatus,
|
||||
ReturnOrderStatus, SalesOrderStatus,
|
||||
StockHistoryCode, StockStatus)
|
||||
@ -130,7 +131,7 @@ class TotalPriceMixin(models.Model):
|
||||
return total
|
||||
|
||||
|
||||
class Order(MetadataMixin, ReferenceIndexingMixin):
|
||||
class Order(InvenTreeBarcodeMixin, MetadataMixin, ReferenceIndexingMixin):
|
||||
"""Abstract model for an order.
|
||||
|
||||
Instances of this class:
|
||||
|
@ -66,6 +66,8 @@ class AbstractOrderSerializer(serializers.Serializer):
|
||||
# Boolean field indicating if this order is overdue (Note: must be annotated)
|
||||
overdue = serializers.BooleanField(required=False, read_only=True)
|
||||
|
||||
barcode_hash = serializers.CharField(read_only=True)
|
||||
|
||||
def validate_reference(self, reference):
|
||||
"""Custom validation for the reference field"""
|
||||
|
||||
@ -101,6 +103,7 @@ class AbstractOrderSerializer(serializers.Serializer):
|
||||
'status',
|
||||
'status_text',
|
||||
'notes',
|
||||
'barcode_hash',
|
||||
'overdue',
|
||||
] + extra_fields
|
||||
|
||||
|
@ -23,6 +23,24 @@
|
||||
{% url 'admin:order_purchaseorder_change' order.pk as url %}
|
||||
{% include "admin_button.html" with url=url %}
|
||||
{% endif %}
|
||||
{% if barcodes %}
|
||||
<!-- Barcode actions menu -->
|
||||
<div class='btn-group' role='group'>
|
||||
<button id='barcode-options' title='{% trans "Barcode actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'>
|
||||
<span class='fas fa-qrcode'></span> <span class='caret'></span>
|
||||
</button>
|
||||
<ul class='dropdown-menu' role='menu'>
|
||||
<li><a class='dropdown-item' href='#' id='show-qr-code'><span class='fas fa-qrcode'></span> {% trans "Show QR Code" %}</a></li>
|
||||
{% if roles.purchase_order.change %}
|
||||
{% if order.barcode_hash %}
|
||||
<li><a class='dropdown-item' href='#' id='barcode-unlink'><span class='fas fa-unlink'></span> {% trans "Unlink Barcode" %}</a></li>
|
||||
{% else %}
|
||||
<li><a class='dropdown-item' href='#' id='barcode-link'><span class='fas fa-link'></span> {% trans "Link Barcode" %}</a></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<!-- Printing options -->
|
||||
<div class='btn-group' role='group'>
|
||||
<button id='print-options' title='{% trans "Print actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'>
|
||||
@ -97,6 +115,7 @@ src="{% static 'img/blank_image.png' %}"
|
||||
<td>{% trans "Order Description" %}</td>
|
||||
<td>{{ order.description }}{% include "clip.html" %}</td>
|
||||
</tr>
|
||||
{% include "barcode_data.html" with instance=order %}
|
||||
<tr>
|
||||
<td><span class='fas fa-info'></span></td>
|
||||
<td>{% trans "Order Status" %}</td>
|
||||
@ -304,5 +323,33 @@ $("#export-order").click(function() {
|
||||
exportOrder('{% url "po-export" order.id %}');
|
||||
});
|
||||
|
||||
{% if barcodes %}
|
||||
<!-- Barcode functionality callbacks -->
|
||||
$('#show-qr-code').click(function() {
|
||||
showQRDialog(
|
||||
'{% trans "Purchase Order QR Code" %}',
|
||||
'{"purchaseorder": {{ order.pk }}}'
|
||||
);
|
||||
});
|
||||
|
||||
{% if roles.purchase_order.change %}
|
||||
$("#barcode-link").click(function() {
|
||||
linkBarcodeDialog(
|
||||
{
|
||||
purchaseorder: {{ order.pk }},
|
||||
},
|
||||
{
|
||||
title: '{% trans "Link Barcode to Purchase Order" %}',
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
$("#barcode-unlink").click(function() {
|
||||
unlinkBarcode({
|
||||
purchaseorder: {{ order.pk }},
|
||||
});
|
||||
});
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% endblock js_ready %}
|
||||
|
@ -33,6 +33,24 @@ src="{% static 'img/blank_image.png' %}"
|
||||
{% url 'admin:order_returnorder_change' order.pk as url %}
|
||||
{% include "admin_button.html" with url=url %}
|
||||
{% endif %}
|
||||
{% if barcodes %}
|
||||
<!-- Barcode actions menu -->
|
||||
<div class='btn-group' role='group'>
|
||||
<button id='barcode-options' title='{% trans "Barcode actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'>
|
||||
<span class='fas fa-qrcode'></span> <span class='caret'></span>
|
||||
</button>
|
||||
<ul class='dropdown-menu' role='menu'>
|
||||
<li><a class='dropdown-item' href='#' id='show-qr-code'><span class='fas fa-qrcode'></span> {% trans "Show QR Code" %}</a></li>
|
||||
{% if roles.return_order.change %}
|
||||
{% if order.barcode_hash %}
|
||||
<li><a class='dropdown-item' href='#' id='barcode-unlink'><span class='fas fa-unlink'></span> {% trans "Unlink Barcode" %}</a></li>
|
||||
{% else %}
|
||||
<li><a class='dropdown-item' href='#' id='barcode-link'><span class='fas fa-link'></span> {% trans "Link Barcode" %}</a></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<!-- Printing actions -->
|
||||
<div class='btn-group' role='group'>
|
||||
<button id='print-options' title='{% trans "Print actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'>
|
||||
@ -89,6 +107,9 @@ src="{% static 'img/blank_image.png' %}"
|
||||
<td>{% trans "Order Description" %}</td>
|
||||
<td>{{ order.description }}{% include "clip.html" %}</td>
|
||||
</tr>
|
||||
|
||||
{% include "barcode_data.html" with instance=order %}
|
||||
|
||||
<tr>
|
||||
<td><span class='fas fa-info'></span></td>
|
||||
<td>{% trans "Order Status" %}</td>
|
||||
@ -230,6 +251,35 @@ $('#print-order-report').click(function() {
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
{% if barcodes %}
|
||||
<!-- Barcode functionality callbacks -->
|
||||
$('#show-qr-code').click(function() {
|
||||
showQRDialog(
|
||||
'{% trans "Return Order QR Code" %}',
|
||||
'{"returnorder": {{ order.pk }}}'
|
||||
);
|
||||
});
|
||||
|
||||
{% if roles.return_order.change %}
|
||||
$("#barcode-link").click(function() {
|
||||
linkBarcodeDialog(
|
||||
{
|
||||
returnorder: {{ order.pk }},
|
||||
},
|
||||
{
|
||||
title: '{% trans "Link Barcode to Return Order" %}',
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
$("#barcode-unlink").click(function() {
|
||||
unlinkBarcode({
|
||||
returnorder: {{ order.pk }},
|
||||
});
|
||||
});
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<!-- TODO: Export order callback -->
|
||||
|
||||
{% endblock js_ready %}
|
||||
|
@ -33,6 +33,24 @@ src="{% static 'img/blank_image.png' %}"
|
||||
{% url 'admin:order_salesorder_change' order.pk as url %}
|
||||
{% include "admin_button.html" with url=url %}
|
||||
{% endif %}
|
||||
{% if barcodes %}
|
||||
<!-- Barcode actions menu -->
|
||||
<div class='btn-group' role='group'>
|
||||
<button id='barcode-options' title='{% trans "Barcode actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'>
|
||||
<span class='fas fa-qrcode'></span> <span class='caret'></span>
|
||||
</button>
|
||||
<ul class='dropdown-menu' role='menu'>
|
||||
<li><a class='dropdown-item' href='#' id='show-qr-code'><span class='fas fa-qrcode'></span> {% trans "Show QR Code" %}</a></li>
|
||||
{% if roles.sales_order.change %}
|
||||
{% if order.barcode_hash %}
|
||||
<li><a class='dropdown-item' href='#' id='barcode-unlink'><span class='fas fa-unlink'></span> {% trans "Unlink Barcode" %}</a></li>
|
||||
{% else %}
|
||||
<li><a class='dropdown-item' href='#' id='barcode-link'><span class='fas fa-link'></span> {% trans "Link Barcode" %}</a></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<!-- Printing actions -->
|
||||
<div class='btn-group' role='group'>
|
||||
<button id='print-options' title='{% trans "Print actions" %}' class='btn btn-outline-secondary dropdown-toggle' type='button' data-bs-toggle='dropdown'>
|
||||
@ -94,6 +112,7 @@ src="{% static 'img/blank_image.png' %}"
|
||||
<td>{% trans "Order Description" %}</td>
|
||||
<td>{{ order.description }}{% include "clip.html" %}</td>
|
||||
</tr>
|
||||
{% include "barcode_data.html" with instance=order %}
|
||||
<tr>
|
||||
<td><span class='fas fa-info'></span></td>
|
||||
<td>{% trans "Order Status" %}</td>
|
||||
@ -279,6 +298,35 @@ $('#print-order-report').click(function() {
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
{% if barcodes %}
|
||||
<!-- Barcode functionality callbacks -->
|
||||
$('#show-qr-code').click(function() {
|
||||
showQRDialog(
|
||||
'{% trans "Sales Order QR Code" %}',
|
||||
'{"salesorder": {{ order.pk }}}'
|
||||
);
|
||||
});
|
||||
|
||||
{% if roles.sales_order.change %}
|
||||
$("#barcode-link").click(function() {
|
||||
linkBarcodeDialog(
|
||||
{
|
||||
salesorder: {{ order.pk }},
|
||||
},
|
||||
{
|
||||
title: '{% trans "Link Barcode to Sales Order" %}',
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
$("#barcode-unlink").click(function() {
|
||||
unlinkBarcode({
|
||||
salesorder: {{ order.pk }},
|
||||
});
|
||||
});
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
$('#export-order').click(function() {
|
||||
exportOrder('{% url "so-export" order.id %}');
|
||||
});
|
||||
|
Reference in New Issue
Block a user