All checks were successful
Deploy Beta (NATIVE) / deploy (push) Successful in 33s
100 lines
3.1 KiB
Python
100 lines
3.1 KiB
Python
import re
|
|
import logging
|
|
|
|
logger = logging.getLogger('api')
|
|
|
|
CATEGORY_CODES = {
|
|
'Food & Beverages': 'FNB',
|
|
'Personal Care': 'PCR',
|
|
'Hygiene & Reusable Care': 'HYG',
|
|
'Clothing & Textiles': 'TEX',
|
|
'Bags, Footwear & Leather': 'LEA',
|
|
'Jewellery': 'JWL',
|
|
'Home Decor & Furnishings': 'DEC',
|
|
'Kitchen & Dining': 'KIT',
|
|
'Eco Packaging & Disposables': 'PKG',
|
|
'Handicrafts & Folk Art': 'ART',
|
|
'Wooden, Bamboo & Coir Products': 'WOD',
|
|
'Toys & Games': 'TOY',
|
|
'Baby & Kids': 'KID',
|
|
'Pet Products': 'PET',
|
|
'Eco Cleaning Products': 'CLN',
|
|
'Farm, Garden & Compost': 'GRD',
|
|
'Stationery, Office & Tech': 'STN',
|
|
'Engineering & Manufactured Goods': 'ENG',
|
|
# Legacy categories mapped to official codes
|
|
'Handicrafts & Art': 'ART',
|
|
'Handloom & Textiles': 'TEX',
|
|
'Home & Living': 'DEC',
|
|
'Food & Organic': 'FNB',
|
|
'Beauty & Herbs': 'PCR',
|
|
'Toys & Folk Art': 'TOY',
|
|
'Pottery & Ceramics': 'ART',
|
|
'Brass & Metal Craft': 'ART',
|
|
'Woodcraft & Carvings': 'WOD',
|
|
'Apparel': 'TEX',
|
|
'Sculptures': 'ART',
|
|
'Kitchenware': 'KIT',
|
|
'Textiles': 'TEX',
|
|
}
|
|
|
|
def get_category_code(category_name):
|
|
"""
|
|
Returns the standardized 3-letter uppercase category code.
|
|
"""
|
|
if not category_name:
|
|
return 'GEN'
|
|
clean = str(category_name).strip()
|
|
if clean in CATEGORY_CODES:
|
|
return CATEGORY_CODES[clean]
|
|
|
|
lower = clean.lower()
|
|
for cat, code in CATEGORY_CODES.items():
|
|
if cat.lower() == lower or cat.lower() in lower or lower in cat.lower():
|
|
return code
|
|
|
|
alnum = re.sub(r'[^A-Z0-9]', '', clean.upper())
|
|
return (alnum[:3] if len(alnum) >= 3 else alnum.ljust(3, 'X'))
|
|
|
|
def normalize_merchant_id(user):
|
|
"""
|
|
Extracts and standardizes the seller's Merchant ID (TRDPX000001 format).
|
|
"""
|
|
if not user:
|
|
return 'TRDPX000001'
|
|
|
|
profile = getattr(user, 'profile', None)
|
|
mid = getattr(profile, 'merchant_id', None)
|
|
if not mid:
|
|
draft = getattr(user, 'onboarding_draft', None)
|
|
mid = getattr(draft, 'merchant_id', None)
|
|
|
|
if mid and str(mid).strip():
|
|
return str(mid).strip().upper().replace(' ', '')
|
|
|
|
user_id = getattr(user, 'id', 1)
|
|
return f"TRDPX{str(user_id).zfill(6)}"
|
|
|
|
def generate_product_sku(user, category_name=None, product_model=None):
|
|
"""
|
|
Generates a unique SKU in format: TRDX-[categorycode]-[sellermid]-[productsno]
|
|
e.g. TRDX-TEX-TRDPX000042-001
|
|
"""
|
|
if product_model is None:
|
|
from .models import Product
|
|
product_model = Product
|
|
|
|
cat_code = get_category_code(category_name)
|
|
mid = normalize_merchant_id(user)
|
|
|
|
user_product_count = product_model.objects.filter(supplier=user).count() if user else 0
|
|
seq = user_product_count + 1
|
|
|
|
candidate_sku = f"TRDX-{cat_code}-{mid}-{seq:03d}"
|
|
while product_model.objects.filter(sku=candidate_sku).exists():
|
|
seq += 1
|
|
candidate_sku = f"TRDX-{cat_code}-{mid}-{seq:03d}"
|
|
|
|
logger.info("Generated SKU: %s for user=%s category=%s", candidate_sku, getattr(user, 'username', 'anon'), category_name)
|
|
return candidate_sku
|
|
|