From 8dc99fdbe3ceb59a6e49b5038a44c073ec0a308c Mon Sep 17 00:00:00 2001 From: Filipp Lepalaan Date: Mon, 24 May 2021 12:54:22 +0300 Subject: Fix GSX parts DB upload --- servo/management/commands/importparts.py | 174 +++++++++++++++++++------------ 1 file changed, 109 insertions(+), 65 deletions(-) (limited to 'servo/management') diff --git a/servo/management/commands/importparts.py b/servo/management/commands/importparts.py index 006c10d..8909773 100644 --- a/servo/management/commands/importparts.py +++ b/servo/management/commands/importparts.py @@ -1,103 +1,147 @@ # -*- coding: utf-8 -*- - +""" +Headers: + "Product Name"', 'Part Number', 'Part Description', 'Part Type', + 'Labor Tier', 'Part Currency', 'Pricing Option', 'Price', + 'EEE Code', 'Substitute Part', 'Component Group', 'Serialized Module' +""" import re import os -import logging - +import csv from decimal import Decimal, InvalidOperation, ROUND_CEILING +import django_rq +import django +django.setup() + from django.db import DatabaseError from django.core.management.base import BaseCommand from django.contrib.contenttypes.models import ContentType from servo.models import Product, TaggedItem +def import_parts(parts, **options): + content_type = ContentType.objects.get(model="product") -class Command(BaseCommand): + for p in parts: + product, created = Product.objects.get_or_create(code=p['code']) - help = "Imports complete GSX parts database" + product.title = p['title'] + product.eee_code = p['eee_code'] + product.currency = p['currency'] + product.part_type = p['part_type'] + product.labour_tier = p['labour_tier'] - def handle(self, *args, **options): + product.is_serialized = p['is_serialized'] + product.component_code = p['component_code'] - update_prices = True - import_vintage = True - dbpath = "servo/uploads/products/partsdb.csv" + if options['update_prices']: + if p['stock_price']: + product.price_purchase_stock = p['stock_price'].to_integral_exact( + rounding=ROUND_CEILING + ) + product.set_stock_sales_price() - try: - partsdb = open(dbpath, "r") - except Exception: - pass + if p['exchange_price']: + product.price_purchase_exchange = p['exchange_price'].to_integral_exact( + rounding=ROUND_CEILING + ) + product.set_exchange_sales_price() - content_type = ContentType.objects.get(model="product") + product.save() - for l in partsdb.readlines(): + if created: + try: + tag, _ = TaggedItem.objects.get_or_create( + content_type=content_type, + object_id=product.pk, + tag=p['category']) + tag.save() + except DatabaseError: + pass - line = l.decode("iso-8859-1") - row = line.strip().split("\t") +def process_parts(reader, **options): + parts = [] + for row in reader: + category = row[0] + p_number = row[1] + p_title = row[2] + p_type = row[3] + lab_tier = row[4] + currency = row[5] + pricing_option = row[6] + price = row[7] + eee_code = row[8] - if row[5] == "" or row[5] == "Currency": - continue # Skip header row and rows without currency + if currency == "" or row[5] == "Part Currency": + continue # Skip header row and rows without currency - logging.debug(row) + if currency != options['currency']: + continue # Skip unwanted currency - category = row[0] + if re.match(r'~VIN', category): + if options['import_vintage'] == False: + continue # Skip vintage devices if so desired - if re.match(r'~VIN', category) and not import_vintage: - continue # Skip vintage devices if so desired + if re.match(r'675-', p_number): + continue # Skip DEPOT REPAIR INVOICE - p_number = row[1] + # skip substitute + component_group = row[10] or '' - if re.match(r'675-', p_number): - continue # Skip DEPOT REPAIR INVOICE + stock_price = Decimal(0.0) + exchange_price = Decimal(0.0) - p_title = row[2] - p_type = row[3] - lab_tier = row[4] + if pricing_option.startswith("Exchange"): + exchange_price = Decimal(price) - try: - stock_price = Decimal(row[6]) - except InvalidOperation: - continue # Skip parts with no stock price + if pricing_option.startswith("Stocking"): + stock_price = Decimal(price) - exchange_price = Decimal(row[7]) + part = { + 'code': p_number, + 'title': p_title, + 'eee_code': eee_code, + 'currency': currency, + 'category': category, + 'labour_tier': lab_tier, + 'stock_price': stock_price, + 'exchange_price': exchange_price, + 'part_type': p_type or "OTHER", + 'component_code': component_group, + 'is_serialized': (row[11] == "Y") + } - eee_code = row[8] + parts.append(part) - # skip substitute - component_group = row[10] or None - is_serialized = row[11] - req_diag = (row[12] == "Y") + return parts - product, created = Product.objects.get_or_create(code=p_number) - product.title = p_title - product.eee_code = eee_code - product.labour_tier = lab_tier - product.part_type = p_type or "OTHER" +class Command(BaseCommand): - product.component_code = component_group - product.is_serialized = (is_serialized == "Y") + help = "Imports complete GSX parts database" - if update_prices: - if stock_price: - purchase_sp = Decimal(stock_price) - product.price_purchase_stock = purchase_sp.to_integral_exact(rounding=ROUND_CEILING) - product.set_stock_sales_price() + def add_arguments(self, parser): + parser.add_argument('dbpath', type=str) + parser.add_argument('currency', type=str) - if exchange_price: - purchase_ep = Decimal(exchange_price) - product.price_purchase_exchange = purchase_ep.to_integral_exact(rounding=ROUND_CEILING) - product.set_exchange_sales_price() + parser.add_argument( + '--update_prices', + action='store_true', + help='Update part prices in inventory', + ) - product.save() + parser.add_argument( + '--import_vintage', + action='store_true', + help='Import vintage parts', + ) - try: - tag, created = TaggedItem.objects.get_or_create( - content_type=content_type, - object_id=product.pk, - tag=category) - tag.save() - except DatabaseError: - pass + def handle(self, *args, **options): + + with open(options['dbpath'], newline='') as partsdb: + reader = csv.reader(partsdb, delimiter=',', quotechar='"') + parts = process_parts(reader, **options) + django_rq.enqueue(import_parts, parts, **options) - os.unlink(dbpath) + os.unlink(options['dbpath']) -- cgit v1.2.3