# -*- 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 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") for p in parts: product, created = Product.objects.get_or_create(code=p['code']) 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'] product.is_serialized = p['is_serialized'] product.component_code = p['component_code'] 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() if p['exchange_price']: product.price_purchase_exchange = p['exchange_price'].to_integral_exact( rounding=ROUND_CEILING ) product.set_exchange_sales_price() product.save() 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 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 currency == "" or row[5] == "Part Currency": continue # Skip header row and rows without currency if currency != options['currency']: continue # Skip unwanted currency if re.match(r'~VIN', category): if options['import_vintage'] == False: continue # Skip vintage devices if so desired if re.match(r'675-', p_number): continue # Skip DEPOT REPAIR INVOICE # skip substitute component_group = row[10] or '' stock_price = Decimal(0.0) exchange_price = Decimal(0.0) if pricing_option.startswith("Exchange"): exchange_price = Decimal(price) if pricing_option.startswith("Stocking"): stock_price = Decimal(price) 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") } parts.append(part) return parts class Command(BaseCommand): help = "Imports complete GSX parts database" def add_arguments(self, parser): parser.add_argument('dbpath', type=str) parser.add_argument('currency', type=str) parser.add_argument( '--update_prices', action='store_true', help='Update part prices in inventory', ) parser.add_argument( '--import_vintage', action='store_true', help='Import vintage parts', ) 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(options['dbpath'])