diff --git a/inventree_data.json b/inventree_data.json index 023363d..0b74be8 100644 --- a/inventree_data.json +++ b/inventree_data.json @@ -4,7 +4,7 @@ "pk": 1, "fields": { "password": "pbkdf2_sha256$260000$NNqALp0c36DPuISI5Q6iM3$+ILiuXGdDbEo4PXR5myUO/zHaNXhzHMPdtN2lZaKrg8=", - "last_login": "2021-07-28T12:51:26.950Z", + "last_login": "2021-08-02T13:14:16.179Z", "is_superuser": true, "username": "admin", "first_name": "", @@ -21,7 +21,7 @@ "model": "common.inventreesetting", "pk": 1, "fields": { - "value": "0.4.0", + "value": "0.4.2", "key": "INVENTREE_LATEST_VERSION" } }, @@ -353,6 +353,22 @@ "key": "PART_SHOW_IMPORT" } }, + { + "model": "common.inventreesetting", + "pk": 43, + "fields": { + "value": "False", + "key": "PART_CREATE_INITIAL" + } + }, + { + "model": "common.inventreesetting", + "pk": 44, + "fields": { + "value": "True", + "key": "PART_SHOW_PRICE_IN_FORMS" + } + }, { "model": "common.inventreeusersetting", "pk": 1, @@ -915,6 +931,26 @@ "currency": "USD" } }, + { + "model": "company.company", + "pk": 29, + "fields": { + "name": "Texas Instruments", + "description": "", + "website": "https://www.ti.com/", + "address": "", + "phone": "", + "email": "", + "contact": "", + "link": "", + "image": "company_images/company_29_img.jpg", + "notes": "", + "is_customer": false, + "is_supplier": true, + "is_manufacturer": true, + "currency": "USD" + } + }, { "model": "company.manufacturerpart", "pk": 1, @@ -2895,6 +2931,17 @@ "description": null } }, + { + "model": "company.manufacturerpart", + "pk": 191, + "fields": { + "part": 61, + "manufacturer": 29, + "MPN": "MAX232IDR", + "link": "", + "description": "MAX232IDR" + } + }, { "model": "company.supplierpart", "pk": 11, @@ -5775,6 +5822,22 @@ "multiple": 1 } }, + { + "model": "company.supplierpart", + "pk": 196, + "fields": { + "part": 61, + "supplier": 1, + "SKU": "2156-MAX232IDR-ND", + "manufacturer_part": 191, + "link": "https://www.digikey.com/en/products/detail/texas-instruments/MAX232IDR/13523247", + "description": "", + "note": "", + "base_cost": "0.000", + "packaging": "", + "multiple": 1 + } + }, { "model": "label.stockitemlabel", "pk": 1, @@ -5841,7 +5904,7 @@ "default_location": null, "default_keywords": null, "lft": 1, - "rght": 10, + "rght": 16, "tree_id": 1, "level": 0 } @@ -5885,8 +5948,8 @@ "parent": 1, "default_location": null, "default_keywords": null, - "lft": 2, - "rght": 9, + "lft": 8, + "rght": 15, "tree_id": 1, "level": 1 } @@ -5900,8 +5963,8 @@ "parent": 4, "default_location": null, "default_keywords": "passive resistor", - "lft": 7, - "rght": 8, + "lft": 13, + "rght": 14, "tree_id": 1, "level": 2 } @@ -5915,8 +5978,8 @@ "parent": 4, "default_location": null, "default_keywords": "passive capacitor", - "lft": 3, - "rght": 4, + "lft": 9, + "rght": 10, "tree_id": 1, "level": 2 } @@ -5930,6 +5993,51 @@ "parent": 4, "default_location": null, "default_keywords": null, + "lft": 11, + "rght": 12, + "tree_id": 1, + "level": 2 + } + }, + { + "model": "part.partcategory", + "pk": 8, + "fields": { + "name": "IC", + "description": "Integrated Circuits", + "parent": 1, + "default_location": null, + "default_keywords": null, + "lft": 2, + "rght": 7, + "tree_id": 1, + "level": 1 + } + }, + { + "model": "part.partcategory", + "pk": 9, + "fields": { + "name": "Interface", + "description": "Drivers, receivers, transceivers", + "parent": 8, + "default_location": null, + "default_keywords": null, + "lft": 3, + "rght": 4, + "tree_id": 1, + "level": 2 + } + }, + { + "model": "part.partcategory", + "pk": 11, + "fields": { + "name": "MCU", + "description": "Microcontrollers and processors", + "parent": 8, + "default_location": null, + "default_keywords": null, "lft": 5, "rght": 6, "tree_id": 1, @@ -8396,6 +8504,293 @@ "level": 0 } }, + { + "model": "part.part", + "pk": 61, + "fields": { + "name": "MAX232IDR", + "is_template": false, + "variant_of": null, + "description": "Dual RS232 transceiver in SOIC-16 package", + "keywords": null, + "category": 9, + "IPN": null, + "revision": null, + "link": null, + "image": "part_images/soic-16.jpg", + "default_location": null, + "default_supplier": null, + "default_expiry": 0, + "minimum_stock": 0, + "units": null, + "assembly": false, + "component": true, + "trackable": false, + "purchaseable": true, + "salable": false, + "active": true, + "virtual": false, + "notes": null, + "bom_checksum": "", + "bom_checked_by": null, + "bom_checked_date": null, + "creation_date": "2021-08-02", + "creation_user": 1, + "responsible": null, + "base_cost": "0.000", + "multiple": 1, + "lft": 1, + "rght": 2, + "tree_id": 61, + "level": 0 + } + }, + { + "model": "part.part", + "pk": 62, + "fields": { + "name": "MCP2561SN", + "is_template": false, + "variant_of": null, + "description": "High speed CAN transceiver in SOIC-8 package", + "keywords": null, + "category": 9, + "IPN": null, + "revision": null, + "link": null, + "image": "part_images/soic-8.jpg", + "default_location": null, + "default_supplier": null, + "default_expiry": 0, + "minimum_stock": 0, + "units": null, + "assembly": false, + "component": true, + "trackable": false, + "purchaseable": true, + "salable": false, + "active": true, + "virtual": false, + "notes": null, + "bom_checksum": "", + "bom_checked_by": null, + "bom_checked_date": null, + "creation_date": "2021-08-02", + "creation_user": 1, + "responsible": null, + "base_cost": "0.000", + "multiple": 1, + "lft": 1, + "rght": 2, + "tree_id": 62, + "level": 0 + } + }, + { + "model": "part.part", + "pk": 63, + "fields": { + "name": "M3x8 SHCS", + "is_template": false, + "variant_of": null, + "description": "Socket head cap screw, M3 thread, 8.0mm", + "keywords": "screw", + "category": 3, + "IPN": "", + "revision": "", + "link": "", + "image": "part_images/SHCS.jpg", + "default_location": null, + "default_supplier": null, + "default_expiry": 0, + "minimum_stock": 0, + "units": "", + "assembly": false, + "component": true, + "trackable": false, + "purchaseable": true, + "salable": false, + "active": true, + "virtual": false, + "notes": null, + "bom_checksum": "", + "bom_checked_by": null, + "bom_checked_date": null, + "creation_date": "2021-08-02", + "creation_user": 1, + "responsible": null, + "base_cost": "0.000", + "multiple": 1, + "lft": 1, + "rght": 2, + "tree_id": 63, + "level": 0 + } + }, + { + "model": "part.part", + "pk": 64, + "fields": { + "name": "M2x6 SHCS", + "is_template": false, + "variant_of": null, + "description": "Socket head cap screw, M2 thread, 6.0mm", + "keywords": "screw", + "category": 3, + "IPN": null, + "revision": null, + "link": null, + "image": "part_images/SHCS.jpg", + "default_location": null, + "default_supplier": null, + "default_expiry": 0, + "minimum_stock": 0, + "units": null, + "assembly": false, + "component": true, + "trackable": false, + "purchaseable": true, + "salable": false, + "active": true, + "virtual": false, + "notes": null, + "bom_checksum": "", + "bom_checked_by": null, + "bom_checked_date": null, + "creation_date": "2021-08-02", + "creation_user": 1, + "responsible": null, + "base_cost": "0.000", + "multiple": 1, + "lft": 1, + "rght": 2, + "tree_id": 64, + "level": 0 + } + }, + { + "model": "part.part", + "pk": 65, + "fields": { + "name": "M2x4 SHCS", + "is_template": false, + "variant_of": null, + "description": "Socket head cap screw, M2 thread, 4.0mm", + "keywords": "screw", + "category": 3, + "IPN": null, + "revision": null, + "link": null, + "image": "part_images/SHCS.jpg", + "default_location": null, + "default_supplier": null, + "default_expiry": 0, + "minimum_stock": 0, + "units": null, + "assembly": false, + "component": true, + "trackable": false, + "purchaseable": true, + "salable": false, + "active": true, + "virtual": false, + "notes": null, + "bom_checksum": "", + "bom_checked_by": null, + "bom_checked_date": null, + "creation_date": "2021-08-02", + "creation_user": 1, + "responsible": null, + "base_cost": "0.000", + "multiple": 1, + "lft": 1, + "rght": 2, + "tree_id": 65, + "level": 0 + } + }, + { + "model": "part.part", + "pk": 66, + "fields": { + "name": "M3x8 Torx", + "is_template": false, + "variant_of": null, + "description": "Torx head screw, M3 thread, 8.0mm", + "keywords": "screw", + "category": 3, + "IPN": null, + "revision": null, + "link": null, + "image": "part_images/torx.jpg", + "default_location": null, + "default_supplier": null, + "default_expiry": 0, + "minimum_stock": 0, + "units": null, + "assembly": false, + "component": true, + "trackable": false, + "purchaseable": true, + "salable": false, + "active": true, + "virtual": false, + "notes": null, + "bom_checksum": "", + "bom_checked_by": null, + "bom_checked_date": null, + "creation_date": "2021-08-02", + "creation_user": 1, + "responsible": null, + "base_cost": "0.000", + "multiple": 1, + "lft": 1, + "rght": 2, + "tree_id": 66, + "level": 0 + } + }, + { + "model": "part.part", + "pk": 67, + "fields": { + "name": "M3x10 Torx", + "is_template": false, + "variant_of": null, + "description": "Torx head screw, M3 thread, 10.0mm", + "keywords": "screw", + "category": 3, + "IPN": null, + "revision": null, + "link": null, + "image": "part_images/torx.jpg", + "default_location": null, + "default_supplier": null, + "default_expiry": 0, + "minimum_stock": 0, + "units": null, + "assembly": false, + "component": true, + "trackable": false, + "purchaseable": true, + "salable": false, + "active": true, + "virtual": false, + "notes": null, + "bom_checksum": "", + "bom_checked_by": null, + "bom_checked_date": null, + "creation_date": "2021-08-02", + "creation_user": 1, + "responsible": null, + "base_cost": "0.000", + "multiple": 1, + "lft": 1, + "rght": 2, + "tree_id": 67, + "level": 0 + } + }, { "model": "part.partparametertemplate", "pk": 1, @@ -8420,6 +8815,22 @@ "units": "%" } }, + { + "model": "part.partparametertemplate", + "pk": 4, + "fields": { + "name": "Length", + "units": "mm" + } + }, + { + "model": "part.partparametertemplate", + "pk": 5, + "fields": { + "name": "Thread", + "units": "" + } + }, { "model": "part.partparameter", "pk": 1, @@ -9716,6 +10127,96 @@ "data": "1%" } }, + { + "model": "part.partparameter", + "pk": 145, + "fields": { + "part": 63, + "template": 4, + "data": "8" + } + }, + { + "model": "part.partparameter", + "pk": 146, + "fields": { + "part": 63, + "template": 5, + "data": "M3" + } + }, + { + "model": "part.partparameter", + "pk": 147, + "fields": { + "part": 64, + "template": 4, + "data": "6" + } + }, + { + "model": "part.partparameter", + "pk": 148, + "fields": { + "part": 64, + "template": 5, + "data": "M2" + } + }, + { + "model": "part.partparameter", + "pk": 149, + "fields": { + "part": 65, + "template": 4, + "data": "4" + } + }, + { + "model": "part.partparameter", + "pk": 150, + "fields": { + "part": 65, + "template": 5, + "data": "M2" + } + }, + { + "model": "part.partparameter", + "pk": 151, + "fields": { + "part": 66, + "template": 4, + "data": "8" + } + }, + { + "model": "part.partparameter", + "pk": 152, + "fields": { + "part": 66, + "template": 5, + "data": "M3" + } + }, + { + "model": "part.partparameter", + "pk": 153, + "fields": { + "part": 67, + "template": 4, + "data": "10" + } + }, + { + "model": "part.partparameter", + "pk": 154, + "fields": { + "part": 67, + "template": 5, + "data": "M3" + } + }, { "model": "report.testreport", "pk": 1, @@ -15365,6 +15866,82 @@ "level": 0 } }, + { + "model": "stock.stockitem", + "pk": 172, + "fields": { + "uid": "", + "parent": null, + "part": 66, + "supplier_part": null, + "location": 3, + "packaging": "bag", + "belongs_to": null, + "customer": null, + "serial": null, + "link": "", + "batch": null, + "quantity": "580.00000", + "updated": "2021-08-02", + "build": null, + "is_building": false, + "purchase_order": null, + "sales_order": null, + "expiry_date": null, + "stocktake_date": null, + "stocktake_user": null, + "review_needed": false, + "delete_on_deplete": true, + "status": 10, + "notes": null, + "purchase_price_currency": "USD", + "purchase_price": "0.2800", + "owner": null, + "infinite": false, + "lft": 1, + "rght": 2, + "tree_id": 146, + "level": 0 + } + }, + { + "model": "stock.stockitem", + "pk": 173, + "fields": { + "uid": "", + "parent": null, + "part": 65, + "supplier_part": null, + "location": 3, + "packaging": "box", + "belongs_to": null, + "customer": null, + "serial": null, + "link": "", + "batch": null, + "quantity": "5000.00000", + "updated": "2021-08-02", + "build": null, + "is_building": false, + "purchase_order": null, + "sales_order": null, + "expiry_date": null, + "stocktake_date": null, + "stocktake_user": null, + "review_needed": false, + "delete_on_deplete": true, + "status": 10, + "notes": null, + "purchase_price_currency": "USD", + "purchase_price": null, + "owner": null, + "infinite": false, + "lft": 1, + "rght": 2, + "tree_id": 147, + "level": 0 + } + }, { "model": "stock.stockitemtracking", "pk": 2, @@ -15883,7 +16460,7 @@ "fields": { "tracking_type": 1, "item": 34, - "date": "2021-07-28T14:37:56.000Z", + "date": "2021-07-28T14:37:56Z", "notes": "", "user": null, "deltas": { @@ -17684,5 +18261,37 @@ "quantity": 500.0 } } + }, + { + "model": "stock.stockitemtracking", + "pk": 172, + "fields": { + "tracking_type": 1, + "item": 172, + "date": "2021-08-02T13:35:56.313Z", + "notes": "", + "user": 1, + "deltas": { + "status": 10, + "location": 3, + "quantity": 580.0 + } + } + }, + { + "model": "stock.stockitemtracking", + "pk": 173, + "fields": { + "tracking_type": 1, + "item": 173, + "date": "2021-08-02T13:36:47.681Z", + "notes": "", + "user": 1, + "deltas": { + "status": 10, + "location": 3, + "quantity": 5000.0 + } + } } ] \ No newline at end of file diff --git a/media/company_images/company_29_img.jpg b/media/company_images/company_29_img.jpg new file mode 100644 index 0000000..9bbe2d3 Binary files /dev/null and b/media/company_images/company_29_img.jpg differ diff --git a/media/company_images/company_29_img.thumbnail.jpg b/media/company_images/company_29_img.thumbnail.jpg new file mode 100644 index 0000000..886aee4 Binary files /dev/null and b/media/company_images/company_29_img.thumbnail.jpg differ diff --git a/media/part_images/SHCS.jpg b/media/part_images/SHCS.jpg new file mode 100644 index 0000000..e7702c2 Binary files /dev/null and b/media/part_images/SHCS.jpg differ diff --git a/media/part_images/SHCS.thumbnail.jpg b/media/part_images/SHCS.thumbnail.jpg new file mode 100644 index 0000000..c40eb39 Binary files /dev/null and b/media/part_images/SHCS.thumbnail.jpg differ diff --git a/media/part_images/soic-16.jpg b/media/part_images/soic-16.jpg new file mode 100644 index 0000000..af7b47c Binary files /dev/null and b/media/part_images/soic-16.jpg differ diff --git a/media/part_images/soic-16.thumbnail.jpg b/media/part_images/soic-16.thumbnail.jpg new file mode 100644 index 0000000..b9aca97 Binary files /dev/null and b/media/part_images/soic-16.thumbnail.jpg differ diff --git a/media/part_images/soic-8.jpg b/media/part_images/soic-8.jpg new file mode 100644 index 0000000..ef49d97 Binary files /dev/null and b/media/part_images/soic-8.jpg differ diff --git a/media/part_images/soic-8.thumbnail.jpg b/media/part_images/soic-8.thumbnail.jpg new file mode 100644 index 0000000..35ebf3c Binary files /dev/null and b/media/part_images/soic-8.thumbnail.jpg differ diff --git a/media/part_images/torx.jpg b/media/part_images/torx.jpg new file mode 100644 index 0000000..51ff1f1 Binary files /dev/null and b/media/part_images/torx.jpg differ diff --git a/media/part_images/torx.thumbnail.jpg b/media/part_images/torx.thumbnail.jpg new file mode 100644 index 0000000..8599efb Binary files /dev/null and b/media/part_images/torx.thumbnail.jpg differ diff --git a/scripts/capacitor_digikey.py b/scripts/capacitor_digikey.py new file mode 100644 index 0000000..28a4e36 --- /dev/null +++ b/scripts/capacitor_digikey.py @@ -0,0 +1,134 @@ +from inventree.api import InvenTreeAPI +from inventree.part import Part, PartCategory +from inventree.base import Parameter +from inventree.company import Company, ManufacturerPart, SupplierPart, ManufacturerPartParameter + +import os +import sys +import digikey +from digikey.v3.productinformation import KeywordSearchRequest + +os.environ['DIGIKEY_CLIENT_ID'] = 'DjV4w1v0ebNTiL7Nqvslw0GkNYuYdrLG' +os.environ['DIGIKEY_CLIENT_SECRET'] = 'dK0dTRimeq3aiPH1' +os.environ['DIGIKEY_CLIENT_SANDBOX'] = 'False' +os.environ['DIGIKEY_STORAGE_PATH'] = 'C:\\Users\\Oliver\\Desktop\\digikey\\' + +INVENTREE_URL = "http://localhost:8000" +INVENTREE_USERNAME = "admin" +INVENTREE_PASSWORD = "inventree" + +inventree = InvenTreeAPI(INVENTREE_URL, username=INVENTREE_USERNAME, password=INVENTREE_PASSWORD) + +resistors = Part.list(inventree, category=6) + +def getParameter(result, name): + + for param in result.parameters: + if param.parameter.lower() == name.lower(): + return param + + return None + + +def getValue(result, name): + + param = getParameter(result, name) + + if param: + return param.value + else: + return None + +manufacturers = {} + +DIGIKEY_PK = 1 + +for res in resistors: + + search_term = res.name.replace('_', ' ').replace('C ' , 'Capacitor ceramic X7R ') + + print(f"Capacitor: {res.name} -> {search_term}") + + request = KeywordSearchRequest(search_term, record_count=25) + + result = digikey.keyword_search(body=request) + + # Set of manufacturer part numbers + MPN = set() + + if len(result.products) == 0: + print("--- NO RESULTS FOUND ---") + + for product in result.products: + + mpn = product.manufacturer_part_number + + if mpn in MPN or len(MPN) >= 2: + continue + + print(f"MPN > {mpn}") + + MPN.add(mpn) + + sku = product.digi_key_part_number + + man_name = product.manufacturer.value + + if man_name in manufacturers.keys(): + manufacturer = manufacturers[man_name] + else: + + # Search InvenTree for manufacturer name + query = Company.list(inventree, search=man_name) + + if len(query) == 0: + + print(f"Creating new manufacturer: '{man_name}'") + + manufacturer = Company.create(inventree, data={ + 'is_supplier': False, + 'is_manufacturer': True, + 'name': man_name, + }) + + else: + manufacturer = query[0] + + if manufacturer == None: + continue + + manufacturers[man_name] = manufacturer + + m_parts = ManufacturerPart.list(inventree, MPN=mpn) + + if len(m_parts) == 0: + print(f"Creating new part: {man_name} -> {mpn}") + manufacturer_part = ManufacturerPart.create(inventree, data={ + 'part': res.pk, + 'manufacturer': manufacturer.pk, + 'MPN': mpn, + }) + + print(manufacturer_part) + else: + manufacturer_part = m_parts[0] + + # Check if a "supplier part" exists + s_parts = SupplierPart.list( + inventree, + manufacturer_part=manufacturer_part.pk, + supplier=DIGIKEY_PK + ) + + if s_parts is None or len(s_parts) == 0: + print(f"Creating new supplier part") + + SupplierPart.create(inventree, data={ + 'part': res.pk, + 'supplier': DIGIKEY_PK, + 'manufacturer_part': manufacturer_part.pk, + 'SKU': sku, + 'link': product.product_url, + 'description': product.product_description, + }) + diff --git a/scripts/create_capacitor_stock.py b/scripts/create_capacitor_stock.py new file mode 100644 index 0000000..046862f --- /dev/null +++ b/scripts/create_capacitor_stock.py @@ -0,0 +1,67 @@ +from inventree.api import InvenTreeAPI + +from inventree.part import Part, PartCategory +from inventree.stock import StockItem, StockLocation +from inventree.company import SupplierPart + +import random +import sys + +INVENTREE_URL = "http://localhost:8000" +INVENTREE_USERNAME = "admin" +INVENTREE_PASSWORD = "inventree" + +api = InvenTreeAPI(INVENTREE_URL, username=INVENTREE_USERNAME, password=INVENTREE_PASSWORD) + +capacitors = Part.list(api, category=6) + +storage = StockLocation(api, pk=8) + +count = 0 + +for cap in capacitors: + + if random.random() > 0.65: + continue + + # Get the first matching supplierpart + sp_list = SupplierPart.list(api, part=cap.pk) + + for sp in sp_list: + if random.random() > 0.6: + continue + + status = 10 + + q = random.random() + + quantity = 1000 + + if q < 0.1: + quantity = 500 + + elif q > 0.85: + quantity = 4000 + + if random.random() < 0.2: + quantity += int(random.random() * 2000) + + if random.random() > 0.95: + status = 55 # Damaged + elif random.random() > 0.95: + status = 50 # Attention + + StockItem.create(api, data={ + 'location': storage.pk, + 'part': cap.pk, + 'quantity': quantity, + 'supplier_part': sp.pk, + 'packaging': 'reel', + 'status': status, + }) + + count += 1 + +print(f"Created {count} new stock items") + + diff --git a/scripts/create_capacitors.py b/scripts/create_capacitors.py new file mode 100644 index 0000000..c87b0ff --- /dev/null +++ b/scripts/create_capacitors.py @@ -0,0 +1,43 @@ +from inventree.api import InvenTreeAPI + +from inventree.part import Part, PartCategory +from inventree.stock import StockItem, StockLocation +from inventree.company import SupplierPart + +import random +import sys + +INVENTREE_URL = "http://localhost:8000" +INVENTREE_USERNAME = "admin" +INVENTREE_PASSWORD = "inventree" + +api = InvenTreeAPI(INVENTREE_URL, username=INVENTREE_USERNAME, password=INVENTREE_PASSWORD) + +category = 6 + +packages = [ + '0402', + '0603', + '0805', +] + +values = [ + # '100pF', + '100nF', + '1uF', + '10uF', +] + +for package in packages: + for value in values: + name = f"C_{value}_{package}" + description = f"{value} in {package} SMD package" + keywords = "cap smd ceramic" + + Part.create(api, data={ + 'name': name, + 'category': category, + 'description': description, + 'keywords': keywords, + 'purchaseable': True, + }) diff --git a/scripts/create_resistor_stock.py b/scripts/create_resistor_stock.py new file mode 100644 index 0000000..27df822 --- /dev/null +++ b/scripts/create_resistor_stock.py @@ -0,0 +1,64 @@ +from inventree.api import InvenTreeAPI + +from inventree.part import Part, PartCategory +from inventree.stock import StockItem, StockLocation +from inventree.company import SupplierPart + +import random +import sys + +INVENTREE_URL = "http://localhost:8000" +INVENTREE_USERNAME = "admin" +INVENTREE_PASSWORD = "inventree" + +api = InvenTreeAPI(INVENTREE_URL, username=INVENTREE_USERNAME, password=INVENTREE_PASSWORD) + +resistors = Part.list(api, category=5) + +storage = StockLocation(api, pk=8) + +count = 0 + +for resistor in resistors: + + if random.random() > 0.65: + continue + + q = random.random() + + quantity = 1000 + + if q < 0.1: + quantity = 2000 + + elif q > 0.85: + quantity = 4000 + + # Get the first matching supplierpart + sp_list = SupplierPart.list(api, part=resistor.pk) + + for sp in sp_list: + if random.random() > 0.6: + continue + + status = 10 + + if random.random() > 0.95: + status = 55 # Damaged + elif random.random() > 0.95: + status = 50 # Attention + + StockItem.create(api, data={ + 'location': storage.pk, + 'part': resistor.pk, + 'quantity': quantity, + 'supplier_part': sp.pk, + 'packaging': 'reel', + 'status': status, + }) + + count += 1 + +print(f"Created {count} new stock items") + + diff --git a/scripts/resistors_digikey.py b/scripts/resistors_digikey.py new file mode 100644 index 0000000..77b4dcd --- /dev/null +++ b/scripts/resistors_digikey.py @@ -0,0 +1,131 @@ +from inventree.api import InvenTreeAPI +from inventree.part import Part, PartCategory +from inventree.base import Parameter +from inventree.company import Company, ManufacturerPart, SupplierPart, ManufacturerPartParameter + +import os +import sys +import digikey +from digikey.v3.productinformation import KeywordSearchRequest + +os.environ['DIGIKEY_CLIENT_ID'] = 'DjV4w1v0ebNTiL7Nqvslw0GkNYuYdrLG' +os.environ['DIGIKEY_CLIENT_SECRET'] = 'dK0dTRimeq3aiPH1' +os.environ['DIGIKEY_CLIENT_SANDBOX'] = 'False' +os.environ['DIGIKEY_STORAGE_PATH'] = 'C:\\Users\\Oliver\\Desktop\\digikey\\' + +INVENTREE_URL = "http://localhost:8000" +INVENTREE_USERNAME = "admin" +INVENTREE_PASSWORD = "inventree" + +inventree = InvenTreeAPI(INVENTREE_URL, username=INVENTREE_USERNAME, password=INVENTREE_PASSWORD) + +resistors = Part.list(inventree, category=5) + +def getParameter(result, name): + + for param in result.parameters: + if param.parameter.lower() == name.lower(): + return param + + return None + + +def getValue(result, name): + + param = getParameter(result, name) + + if param: + return param.value + else: + return None + +manufacturers = {} + +DIGIKEY_PK = 1 + +for res in resistors: + + search_term = res.name.replace('_', ' ').replace('R ' , 'Resistor ') + + print(res.name, res.description) + + request = KeywordSearchRequest(search_term, record_count=25) + + result = digikey.keyword_search(body=request) + + # Set of manufacturer part numbers + MPN = set() + + for product in result.products: + + mpn = product.manufacturer_part_number + + print(f"> {mpn}") + + if mpn in MPN or len(MPN) >= 5: + continue + + MPN.add(mpn) + + sku = product.digi_key_part_number + + man_name = product.manufacturer.value + + if man_name in manufacturers.keys(): + manufacturer = manufacturers[man_name] + else: + + # Search InvenTree for manufacturer name + query = Company.list(inventree, search=man_name) + + if len(query) == 0: + + print(f"Creating new manufacturer: '{man_name}'") + + manufacturer = Company.create(inventree, data={ + 'is_supplier': False, + 'is_manufacturer': True, + 'name': man_name, + }) + + else: + manufacturer = query[0] + + manufacturers[man_name] = manufacturer + + m_parts = ManufacturerPart.list(inventree, MPN=mpn) + + print("Existing Manufacturer Parts:") + + for mp in m_parts: + print(f" - {mp.MPN}, {mp.manufacturer}") + + if len(m_parts) == 0: + print(f"Creating new part: {man_name} -> {mpn}") + manufacturer_part = ManufacturerPart.create(inventree, data={ + 'part': res.pk, + 'manufacturer': manufacturer.pk, + 'MPN': mpn, + }) + else: + manufacturer_part = m_parts[0] + + # Check if a "supplier part" exists + s_parts = SupplierPart.list( + inventree, + manufacturer_part=manufacturer_part.pk, + supplier=DIGIKEY_PK + ) + + if s_parts is None or len(s_parts) == 0: + print(f"Creating new supplier part") + + SupplierPart.create(inventree, data={ + 'part': res.pk, + 'supplier': DIGIKEY_PK, + 'manufacturer_part': manufacturer_part.pk, + 'SKU': sku, + 'link': product.product_url, + 'description': product.product_description, + }) +