InvenTree/InvenTree/plugin/builtin/suppliers/test_supplier_barcodes.py

309 lines
12 KiB
Python

"""Tests barcode parsing for all suppliers."""
from django.urls import reverse
from company.models import Company, ManufacturerPart, SupplierPart
from InvenTree.unit_test import InvenTreeAPITestCase
from order.models import PurchaseOrder, PurchaseOrderLineItem
from part.models import Part
from stock.models import StockItem, StockLocation
class SupplierBarcodeTests(InvenTreeAPITestCase):
"""Tests barcode parsing for all suppliers."""
@classmethod
def setUpTestData(cls):
"""Create supplier parts for barcodes."""
super().setUpTestData()
part = Part.objects.create(name="Test Part", description="Test Part")
manufacturer = Company.objects.create(
name="Test Manufacturer", is_manufacturer=True)
mpart1 = ManufacturerPart.objects.create(
part=part, manufacturer=manufacturer, MPN="MC34063ADR")
mpart2 = ManufacturerPart.objects.create(
part=part, manufacturer=manufacturer, MPN="LDK320ADU33R")
supplier = Company.objects.create(name="Supplier", is_supplier=True)
mouser = Company.objects.create(name="Mouser Test", is_supplier=True)
supplier_parts = [
SupplierPart(SKU="296-LM358BIDDFRCT-ND", part=part, supplier=supplier),
SupplierPart(SKU="1", part=part, manufacturer_part=mpart1, supplier=mouser),
SupplierPart(SKU="2", part=part, manufacturer_part=mpart2, supplier=mouser),
SupplierPart(SKU="C312270", part=part, supplier=supplier),
SupplierPart(SKU="WBP-302", part=part, supplier=supplier),
]
SupplierPart.objects.bulk_create(supplier_parts)
def test_digikey_barcode(self):
"""Test digikey barcode."""
url = reverse("api-barcode-scan")
result = self.post(url, data={"barcode": DIGIKEY_BARCODE})
supplier_part_data = result.data.get("supplierpart")
assert "pk" in supplier_part_data
supplier_part = SupplierPart.objects.get(pk=supplier_part_data["pk"])
assert supplier_part.SKU == "296-LM358BIDDFRCT-ND"
def test_mouser_barcode(self):
"""Test mouser barcode with custom order number."""
url = reverse("api-barcode-scan")
result = self.post(url, data={"barcode": MOUSER_BARCODE})
supplier_part_data = result.data.get("supplierpart")
assert "pk" in supplier_part_data
supplier_part = SupplierPart.objects.get(pk=supplier_part_data["pk"])
assert supplier_part.SKU == "1"
def test_old_mouser_barcode(self):
"""Test old mouser barcode with messed up header."""
url = reverse("api-barcode-scan")
result = self.post(url, data={"barcode": MOUSER_BARCODE_OLD})
supplier_part_data = result.data.get("supplierpart")
assert "pk" in supplier_part_data
supplier_part = SupplierPart.objects.get(pk=supplier_part_data["pk"])
assert supplier_part.SKU == "2"
def test_lcsc_barcode(self):
"""Test LCSC barcode."""
url = reverse("api-barcode-scan")
result = self.post(url, data={"barcode": LCSC_BARCODE})
supplier_part_data = result.data.get("supplierpart")
assert supplier_part_data is not None
assert "pk" in supplier_part_data
supplier_part = SupplierPart.objects.get(pk=supplier_part_data["pk"])
assert supplier_part.SKU == "C312270"
def test_tme_qrcode(self):
"""Test TME QR-Code."""
url = reverse("api-barcode-scan")
result = self.post(url, data={"barcode": TME_QRCODE})
supplier_part_data = result.data.get("supplierpart")
assert supplier_part_data is not None
assert "pk" in supplier_part_data
supplier_part = SupplierPart.objects.get(pk=supplier_part_data["pk"])
assert supplier_part.SKU == "WBP-302"
def test_tme_barcode2d(self):
"""Test TME DataMatrix-Code."""
url = reverse("api-barcode-scan")
result = self.post(url, data={"barcode": TME_DATAMATRIX_CODE})
supplier_part_data = result.data.get("supplierpart")
assert supplier_part_data is not None
assert "pk" in supplier_part_data
supplier_part = SupplierPart.objects.get(pk=supplier_part_data["pk"])
assert supplier_part.SKU == "WBP-302"
class SupplierBarcodePOReceiveTests(InvenTreeAPITestCase):
"""Tests barcode scanning to receive a purchase order item."""
def setUp(self):
"""Create supplier part and purchase_order."""
super().setUp()
part = Part.objects.create(name="Test Part", description="Test Part")
supplier = Company.objects.create(name="Supplier", is_supplier=True)
manufacturer = Company.objects.create(
name="Test Manufacturer", is_manufacturer=True)
mouser = Company.objects.create(name="Mouser Test", is_supplier=True)
mpart = ManufacturerPart.objects.create(
part=part, manufacturer=manufacturer, MPN="MC34063ADR")
self.purchase_order1 = PurchaseOrder.objects.create(
supplier_reference="72991337", supplier=supplier)
supplier_parts1 = [
SupplierPart(SKU=f"1_{i}", part=part, supplier=supplier)
for i in range(6)
]
supplier_parts1.insert(
2, SupplierPart(SKU="296-LM358BIDDFRCT-ND", part=part, supplier=supplier))
for supplier_part in supplier_parts1:
supplier_part.save()
self.purchase_order1.add_line_item(supplier_part, 8)
self.purchase_order2 = PurchaseOrder.objects.create(
reference="P0-1337", supplier=mouser)
self.purchase_order2.place_order()
supplier_parts2 = [
SupplierPart(SKU=f"2_{i}", part=part, supplier=mouser)
for i in range(6)
]
supplier_parts2.insert(
3, SupplierPart(SKU="42", part=part, manufacturer_part=mpart, supplier=mouser))
for supplier_part in supplier_parts2:
supplier_part.save()
self.purchase_order2.add_line_item(supplier_part, 5)
def test_receive(self):
"""Test receiving an item from a barcode."""
url = reverse("api-barcode-po-receive")
result1 = self.post(url, data={"barcode": DIGIKEY_BARCODE})
assert result1.status_code == 400
assert result1.data["error"].startswith("Failed to find placed purchase order")
self.purchase_order1.place_order()
result2 = self.post(url, data={"barcode": DIGIKEY_BARCODE})
assert result2.status_code == 200
assert "success" in result2.data
result3 = self.post(url, data={"barcode": DIGIKEY_BARCODE})
assert result3.status_code == 400
assert result3.data["error"].startswith(
"Item has already been received")
result4 = self.post(url, data={"barcode": DIGIKEY_BARCODE[:-1]})
assert result4.status_code == 400
assert result4.data["error"].startswith(
"Failed to find pending line item for supplier part")
result5 = self.post(reverse("api-barcode-scan"), data={"barcode": DIGIKEY_BARCODE})
assert result5.status_code == 200
stock_item = StockItem.objects.get(pk=result5.data["stockitem"]["pk"])
assert stock_item.supplier_part.SKU == "296-LM358BIDDFRCT-ND"
assert stock_item.quantity == 10
assert stock_item.location is None
def test_receive_custom_order_number(self):
"""Test receiving an item from a barcode with a custom order number."""
url = reverse("api-barcode-po-receive")
result1 = self.post(url, data={"barcode": MOUSER_BARCODE})
assert "success" in result1.data
result2 = self.post(reverse("api-barcode-scan"), data={"barcode": MOUSER_BARCODE})
stock_item = StockItem.objects.get(pk=result2.data["stockitem"]["pk"])
assert stock_item.supplier_part.SKU == "42"
assert stock_item.supplier_part.manufacturer_part.MPN == "MC34063ADR"
assert stock_item.quantity == 3
assert stock_item.location is None
def test_receive_one_stock_location(self):
"""Test receiving an item when only one stock location exists"""
stock_location = StockLocation.objects.create(name="Test Location")
url = reverse("api-barcode-po-receive")
result1 = self.post(url, data={"barcode": MOUSER_BARCODE})
assert "success" in result1.data
result2 = self.post(reverse("api-barcode-scan"), data={"barcode": MOUSER_BARCODE})
stock_item = StockItem.objects.get(pk=result2.data["stockitem"]["pk"])
assert stock_item.location == stock_location
def test_receive_default_line_item_location(self):
"""Test receiving an item into the default line_item location"""
StockLocation.objects.create(name="Test Location 1")
stock_location2 = StockLocation.objects.create(name="Test Location 2")
line_item = PurchaseOrderLineItem.objects.filter(part__SKU="42")[0]
line_item.destination = stock_location2
line_item.save()
url = reverse("api-barcode-po-receive")
result1 = self.post(url, data={"barcode": MOUSER_BARCODE})
assert "success" in result1.data
result2 = self.post(reverse("api-barcode-scan"), data={"barcode": MOUSER_BARCODE})
stock_item = StockItem.objects.get(pk=result2.data["stockitem"]["pk"])
assert stock_item.location == stock_location2
def test_receive_default_part_location(self):
"""Test receiving an item into the default part location"""
StockLocation.objects.create(name="Test Location 1")
stock_location2 = StockLocation.objects.create(name="Test Location 2")
part = Part.objects.all()[0]
part.default_location = stock_location2
part.save()
url = reverse("api-barcode-po-receive")
result1 = self.post(url, data={"barcode": MOUSER_BARCODE})
assert "success" in result1.data
result2 = self.post(reverse("api-barcode-scan"), data={"barcode": MOUSER_BARCODE})
stock_item = StockItem.objects.get(pk=result2.data["stockitem"]["pk"])
assert stock_item.location == stock_location2
def test_receive_specific_order_and_location(self):
"""Test receiving an item from a specific order into a specific location"""
StockLocation.objects.create(name="Test Location 1")
stock_location2 = StockLocation.objects.create(name="Test Location 2")
url = reverse("api-barcode-po-receive")
barcode = MOUSER_BARCODE.replace("\x1dKP0-1337", "")
result1 = self.post(url, data={
"barcode": barcode,
"purchase_order": self.purchase_order2.pk,
"location": stock_location2.pk,
})
assert "success" in result1.data
result2 = self.post(reverse("api-barcode-scan"), data={"barcode": barcode})
stock_item = StockItem.objects.get(pk=result2.data["stockitem"]["pk"])
assert stock_item.location == stock_location2
def test_receive_missing_quantity(self):
"""Test receiving an with missing quantity information"""
url = reverse("api-barcode-po-receive")
barcode = MOUSER_BARCODE.replace("\x1dQ3", "")
result = self.post(url, data={"barcode": barcode})
assert "lineitem" in result.data
assert "quantity" not in result.data["lineitem"]
DIGIKEY_BARCODE = (
"[)>\x1e06\x1dP296-LM358BIDDFRCT-ND\x1d1PLM358BIDDFR\x1dK\x1d1K72991337\x1d"
"10K85781337\x1d11K1\x1d4LPH\x1dQ10\x1d11ZPICK\x1d12Z15221337\x1d13Z361337"
"\x1d20Z0000000000000000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000"
)
MOUSER_BARCODE = (
"[)>\x1e06\x1dKP0-1337\x1d14K011\x1d1PMC34063ADR\x1dQ3\x1d11K073121337\x1d4"
"LMX\x1d1VTI\x1e\x04"
)
MOUSER_BARCODE_OLD = (
">[)>06\x1dK21421337\x1d14K033\x1d1PLDK320ADU33R\x1dQ32\x1d11K060931337\x1d"
"4LCN\x1d1VSTMicro"
)
LCSC_BARCODE = (
"{pbn:PICK2009291337,on:SO2009291337,pc:C312270,pm:ST-1-102-A01-T000-RS,qty"
":2,mc:,cc:1,pdi:34421807}"
)
TME_QRCODE = (
"QTY:1 PN:WBP-302 PO:19361337/1 CPO:PO-2023-06-08-001337 MFR:WISHERENTERPRI"
"SE MPN:WBP-302 RoHS https://www.tme.eu/details/WBP-302"
)
TME_DATAMATRIX_CODE = "PWBP-302 1PMPNWBP-302 Q1 K19361337/1"