import os import django # Set up Django environment os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hospital_management.settings') django.setup() import random import uuid from datetime import datetime, timedelta from decimal import Decimal from django.utils import timezone as django_timezone from django.contrib.auth import get_user_model from core.models import Tenant from inventory.models import InventoryItem, InventoryStock, InventoryLocation, PurchaseOrder, PurchaseOrderItem, \ Supplier User = get_user_model() # Saudi Arabian Inventory Data SAUDI_MEDICAL_CATEGORIES = [ 'Pharmaceuticals', 'Medical Devices', 'Surgical Instruments', 'Laboratory Supplies', 'PPE & Safety', 'IV Therapy', 'Emergency Supplies' ] SAUDI_SUPPLIERS = [ 'Saudi Medical Supply Co.', 'Gulf Medical Equipment', 'Arabian Healthcare Supplies', 'Riyadh Medical Trading', 'Al-Dawaa Medical', 'Nahdi Medical Company', 'United Pharmaceuticals' ] SAUDI_CITIES = ['Riyadh', 'Jeddah', 'Dammam', 'Medina', 'Taif', 'Khobar'] MEDICAL_ITEMS = [ {'name': 'Paracetamol 500mg', 'category': 'Pharmaceuticals', 'unit': 'TAB'}, {'name': 'Disposable Syringe 5ml', 'category': 'Medical Devices', 'unit': 'PCS'}, {'name': 'Surgical Gloves Size M', 'category': 'PPE & Safety', 'unit': 'PAIR'}, {'name': 'Blood Collection Tube', 'category': 'Laboratory Supplies', 'unit': 'PCS'}, {'name': 'IV Bag Normal Saline', 'category': 'IV Therapy', 'unit': 'BAG'}, {'name': 'Emergency Oxygen Mask', 'category': 'Emergency Supplies', 'unit': 'PCS'} ] def create_saudi_suppliers(tenants): """Create Saudi suppliers""" suppliers = [] for tenant in tenants: print(f"Creating suppliers for {tenant.name}...") for i, supplier_name in enumerate(SAUDI_SUPPLIERS): supplier_code = f"SUP-{tenant.id}-{i + 1:03d}" try: supplier = Supplier.objects.create( tenant=tenant, supplier_code=supplier_code, name=supplier_name, supplier_type='DISTRIBUTOR', city=random.choice(SAUDI_CITIES), country='Saudi Arabia', is_active=True ) suppliers.append(supplier) print(f" ✓ Created supplier: {supplier_name}") except Exception as e: print(f" ✗ Error creating supplier {supplier_name}: {e}") continue print(f"Created {len(suppliers)} suppliers") return suppliers def create_saudi_inventory_locations(tenants): """Create Saudi inventory locations""" locations = [] storage_rooms = ['Pharmacy', 'Central Supply', 'OR Storage', 'ICU Supply', 'Ward Storage'] for tenant in tenants: print(f"Creating locations for {tenant.name}...") for i, room in enumerate(storage_rooms): location_code = f"LOC-{tenant.id}-{i + 1:03d}" try: location = InventoryLocation.objects.create( tenant=tenant, location_code=location_code, name=f"{room} - {tenant.city}", description=f"Storage location in {room}", location_type='WAREHOUSE', building='Main Hospital', floor='Ground Floor', room=room, is_active=True ) locations.append(location) print(f" ✓ Created location: {location.name}") except Exception as e: print(f" ✗ Error creating location {room}: {e}") continue print(f"Created {len(locations)} locations") return locations def create_saudi_inventory_items(tenants): """Create Saudi inventory items""" items = [] for tenant in tenants: print(f"Creating items for {tenant.name}...") for i, item_data in enumerate(MEDICAL_ITEMS): item_code = f"ITM-{tenant.id}-{i + 1:03d}" try: item = InventoryItem.objects.create( tenant=tenant, item_code=item_code, item_name=item_data['name'], description=f"Medical item: {item_data['name']}", category=item_data['category'], subcategory=item_data['category'], item_type='STOCK', manufacturer='Saudi Medical Industries', unit_of_measure=item_data['unit'], package_size=1, unit_cost=Decimal(str(random.uniform(10, 100))), list_price=Decimal(str(random.uniform(15, 150))), has_expiration=item_data['category'] == 'Pharmaceuticals', is_active=True, is_tracked=True, reorder_point=random.randint(10, 50), reorder_quantity=random.randint(100, 500), max_stock_level=random.randint(500, 1000) ) items.append(item) print(f" ✓ Created item: {item.item_name}") except Exception as e: print(f" ✗ Error creating item {item_data['name']}: {e}") continue print(f"Created {len(items)} items") return items def create_saudi_inventory_stock(items, locations): """Create Saudi inventory stock entries""" stocks = [] for item in items: print(f"Creating stock for {item.item_name}...") # Get locations for this tenant tenant_locations = [loc for loc in locations if loc.tenant == item.tenant] if not tenant_locations: continue location = random.choice(tenant_locations) try: stock = InventoryStock.objects.create( inventory_item=item, location=location, quantity_on_hand=random.randint(50, 500), quantity_reserved=random.randint(0, 20), received_date=django_timezone.now().date() - timedelta(days=random.randint(1, 90)), expiration_date=django_timezone.now().date() + timedelta(days=365) if item.has_expiration else None, unit_cost=item.unit_cost, quality_status='AVAILABLE' ) stocks.append(stock) print(f" ✓ Created stock for: {item.item_name}") except Exception as e: print(f" ✗ Error creating stock for {item.item_name}: {e}") continue print(f"Created {len(stocks)} stock entries") return stocks def create_saudi_purchase_orders(tenants, suppliers): """Create Saudi purchase orders""" orders = [] for tenant in tenants: print(f"Creating purchase orders for {tenant.name}...") # Get suppliers for this tenant tenant_suppliers = [supplier for supplier in suppliers if supplier.tenant == tenant] if not tenant_suppliers: print(f" No suppliers found for {tenant.name}, skipping...") continue # Get delivery locations try: locations = InventoryLocation.objects.filter(tenant=tenant) delivery_location = locations.first() if locations.exists() else None except: delivery_location = None for i in range(3): # Create 3 orders per tenant po_number = f"PO-{tenant.id}-{django_timezone.now().year}-{i + 1:04d}" supplier = random.choice(tenant_suppliers) try: order = PurchaseOrder.objects.create( tenant=tenant, po_number=po_number, supplier=supplier, order_date=django_timezone.now().date() - timedelta(days=random.randint(1, 30)), requested_delivery_date=django_timezone.now().date() + timedelta(days=random.randint(7, 30)), order_type='STANDARD', priority='NORMAL', subtotal=Decimal(str(random.uniform(1000, 10000))), tax_amount=Decimal('0.00'), shipping_amount=Decimal('0.00'), total_amount=Decimal(str(random.uniform(1000, 10000))), status='DRAFT', delivery_location=delivery_location, payment_terms='NET_30' ) orders.append(order) print(f" ✓ Created PO: {po_number}") except Exception as e: print(f" ✗ Error creating PO {po_number}: {e}") continue print(f"Created {len(orders)} purchase orders") return orders def create_saudi_purchase_order_items(orders, items): """Create Saudi purchase order items""" po_items = [] for order in orders: print(f"Creating items for PO {order.po_number}...") # Get items for this tenant tenant_items = [item for item in items if item.tenant == order.tenant] if not tenant_items: continue # Create 2-3 items per order num_items = min(3, len(tenant_items)) selected_items = random.sample(tenant_items, num_items) for line_num, item in enumerate(selected_items, 1): quantity_ordered = random.randint(10, 100) unit_price = item.unit_cost * Decimal(str(random.uniform(0.9, 1.1))) total_price = unit_price * quantity_ordered try: po_item = PurchaseOrderItem.objects.create( purchase_order=order, line_number=line_num, inventory_item=item, quantity_ordered=quantity_ordered, quantity_received=0, unit_price=unit_price, total_price=total_price, requested_delivery_date=order.requested_delivery_date, status='PENDING' ) po_items.append(po_item) print(f" ✓ Created PO item: {item.item_name}") except Exception as e: print(f" ✗ Error creating PO item for {item.item_name}: {e}") continue print(f"Created {len(po_items)} purchase order items") return po_items def main(): """Main function to create all Saudi inventory data""" print("🏥 Starting Saudi Inventory Data Generation...") # Get tenants try: tenants = list(Tenant.objects.filter(is_active=True)[:5]) # Limit to first 5 tenants if not tenants: print("❌ No active tenants found. Please run core_data.py first.") return print(f"📋 Found {len(tenants)} active tenants") except Exception as e: print(f"❌ Error getting tenants: {e}") return # Create data step by step print("\n1️⃣ Creating Suppliers...") suppliers = create_saudi_suppliers(tenants) if not suppliers: print("❌ No suppliers created. Stopping.") return print("\n2️⃣ Creating Locations...") locations = create_saudi_inventory_locations(tenants) if not locations: print("❌ No locations created. Stopping.") return print("\n3️⃣ Creating Items...") items = create_saudi_inventory_items(tenants) if not items: print("❌ No items created. Stopping.") return print("\n4️⃣ Creating Stock...") stocks = create_saudi_inventory_stock(items, locations) print("\n5️⃣ Creating Purchase Orders...") orders = create_saudi_purchase_orders(tenants, suppliers) print("\n6️⃣ Creating Purchase Order Items...") po_items = create_saudi_purchase_order_items(orders, items) print("\n🎉 Saudi Inventory Data Generation Complete!") print(f"📊 Summary:") print(f" - Suppliers: {len(suppliers)}") print(f" - Locations: {len(locations)}") print(f" - Items: {len(items)}") print(f" - Stock Entries: {len(stocks)}") print(f" - Purchase Orders: {len(orders)}") print(f" - PO Items: {len(po_items)}") if __name__ == "__main__": main() # import random # import uuid # from datetime import datetime, timedelta # from decimal import Decimal # from django.utils import timezone as django_timezone # from django.db import transaction # # from core.models import Tenant # from accounts.models import User # from inventory.models import InventoryItem, InventoryStock, InventoryLocation, PurchaseOrder, PurchaseOrderItem, \ # Supplier # # # Saudi Arabian Inventory Data # SAUDI_MEDICAL_CATEGORIES = [ # 'Pharmaceuticals', # 'Medical Devices', # 'Surgical Instruments', # 'Laboratory Supplies', # 'Radiology Supplies', # 'PPE & Safety', # 'Wound Care', # 'IV Therapy', # 'Respiratory Care', # 'Cardiology Equipment', # 'Orthopedic Supplies', # 'Emergency Supplies', # 'Cleaning & Disinfection', # 'Office Supplies', # 'Food & Nutrition' # ] # # SAUDI_PHARMACEUTICAL_SUBCATEGORIES = { # 'Pharmaceuticals': [ # 'Antibiotics', 'Analgesics', 'Cardiovascular', 'Diabetes Care', # 'Respiratory', 'Oncology', 'Psychiatric', 'Emergency Drugs', # 'Anesthetics', 'Vaccines', 'IV Solutions', 'Blood Products' # ] # } # # SAUDI_MEDICAL_MANUFACTURERS = [ # 'Saudi Pharmaceutical Industries (SPIMACO)', # 'Tabuk Pharmaceuticals', # 'Jamjoom Pharmaceuticals', # 'Al-Jazeera Pharmaceutical Industries', # 'Medical Supplies Company', # 'Saudi Medical Supplies', # 'Gulf Pharmaceutical Industries', # 'Middle East Healthcare', # 'Arabian Medical Equipment', # 'Riyadh Pharma', # 'Johnson & Johnson Saudi', # 'Pfizer Saudi Arabia', # 'Novartis Saudi', # 'Roche Saudi Arabia', # 'Abbott Saudi Arabia' # ] # # SAUDI_STORAGE_LOCATIONS = { # 'buildings': ['Main Hospital', 'Outpatient Clinic', 'Emergency Wing', 'Research Center', 'Administrative Building'], # 'floors': ['Ground Floor', 'First Floor', 'Second Floor', 'Third Floor', 'Basement'], # 'rooms': ['Pharmacy', 'Central Supply', 'OR Storage', 'ICU Supply', 'Ward Storage', 'Emergency Supply'], # 'zones': ['Zone A', 'Zone B', 'Zone C', 'Zone D'], # 'aisles': ['Aisle 1', 'Aisle 2', 'Aisle 3', 'Aisle 4', 'Aisle 5'], # 'shelves': ['Shelf A', 'Shelf B', 'Shelf C', 'Shelf D', 'Shelf E'], # 'bins': ['Bin 1', 'Bin 2', 'Bin 3', 'Bin 4', 'Bin 5'] # } # # SAUDI_SUPPLIER_DATA = [ # { # 'name': 'Saudi Medical Supply Co.', # 'type': 'DISTRIBUTOR', # 'city': 'Riyadh', # 'phone': '+966-11-234-5678' # }, # { # 'name': 'Gulf Medical Equipment', # 'type': 'MANUFACTURER', # 'city': 'Dammam', # 'phone': '+966-13-345-6789' # }, # { # 'name': 'Arabian Healthcare Supplies', # 'type': 'WHOLESALER', # 'city': 'Jeddah', # 'phone': '+966-12-456-7890' # }, # { # 'name': 'Riyadh Medical Trading', # 'type': 'DISTRIBUTOR', # 'city': 'Riyadh', # 'phone': '+966-11-567-8901' # }, # { # 'name': 'Al-Dawaa Medical', # 'type': 'MANUFACTURER', # 'city': 'Medina', # 'phone': '+966-14-678-9012' # }, # { # 'name': 'Nahdi Medical Company', # 'type': 'RETAILER', # 'city': 'Jeddah', # 'phone': '+966-12-789-0123' # }, # { # 'name': 'United Pharmaceuticals', # 'type': 'MANUFACTURER', # 'city': 'Khobar', # 'phone': '+966-13-890-1234' # }, # { # 'name': 'Middle East Medical', # 'type': 'DISTRIBUTOR', # 'city': 'Taif', # 'phone': '+966-12-901-2345' # }, # { # 'name': 'Kingdom Medical Supplies', # 'type': 'WHOLESALER', # 'city': 'Buraidah', # 'phone': '+966-16-012-3456' # }, # { # 'name': 'Eastern Province Medical Co.', # 'type': 'DISTRIBUTOR', # 'city': 'Dhahran', # 'phone': '+966-13-123-4567' # } # ] # # SAUDI_CITIES = [ # 'Riyadh', 'Jeddah', 'Mecca', 'Medina', 'Dammam', 'Khobar', 'Dhahran', # 'Taif', 'Buraidah', 'Tabuk', 'Hail', 'Khamis Mushait', 'Hofuf', 'Jubail', # 'Hafar Al-Batin', 'Yanbu', 'Abha', 'Najran', 'Qatif', 'Sakaka' # ] # # COMMON_MEDICAL_ITEMS = [ # # Pharmaceuticals # {'name': 'Paracetamol 500mg', 'category': 'Pharmaceuticals', 'subcategory': 'Analgesics', 'unit': 'TAB', # 'controlled': False}, # {'name': 'Amoxicillin 250mg', 'category': 'Pharmaceuticals', 'subcategory': 'Antibiotics', 'unit': 'CAP', # 'controlled': False}, # {'name': 'Insulin Regular', 'category': 'Pharmaceuticals', 'subcategory': 'Diabetes Care', 'unit': 'VIAL', # 'controlled': False}, # {'name': 'Morphine 10mg/ml', 'category': 'Pharmaceuticals', 'subcategory': 'Analgesics', 'unit': 'AMP', # 'controlled': True}, # {'name': 'Diazepam 5mg', 'category': 'Pharmaceuticals', 'subcategory': 'Psychiatric', 'unit': 'TAB', # 'controlled': True}, # {'name': 'Normal Saline 0.9%', 'category': 'Pharmaceuticals', 'subcategory': 'IV Solutions', 'unit': 'BAG', # 'controlled': False}, # # # Medical Devices # {'name': 'Disposable Syringe 5ml', 'category': 'Medical Devices', 'subcategory': 'Injection Equipment', # 'unit': 'PCS', 'controlled': False}, # {'name': 'Blood Pressure Cuff', 'category': 'Medical Devices', 'subcategory': 'Monitoring Equipment', 'unit': 'PCS', # 'controlled': False}, # {'name': 'ECG Electrodes', 'category': 'Medical Devices', 'subcategory': 'Cardiology Equipment', 'unit': 'PCS', # 'controlled': False}, # {'name': 'Surgical Gloves Size M', 'category': 'PPE & Safety', 'subcategory': 'Protective Equipment', # 'unit': 'PAIR', 'controlled': False}, # # # Surgical Instruments # {'name': 'Scalpel Blade #15', 'category': 'Surgical Instruments', 'subcategory': 'Cutting Instruments', # 'unit': 'PCS', 'controlled': False}, # {'name': 'Forceps Straight', 'category': 'Surgical Instruments', 'subcategory': 'Grasping Instruments', # 'unit': 'PCS', 'controlled': False}, # # # Laboratory Supplies # {'name': 'Blood Collection Tube EDTA', 'category': 'Laboratory Supplies', 'subcategory': 'Collection Tubes', # 'unit': 'PCS', 'controlled': False}, # {'name': 'Urine Container', 'category': 'Laboratory Supplies', 'subcategory': 'Collection Containers', # 'unit': 'PCS', 'controlled': False}, # ] # # # def generate_saudi_item_code(): # """Generate Saudi medical item code""" # return f"SAU-{random.randint(100000, 999999)}" # # # def generate_saudi_lot_number(): # """Generate Saudi lot number""" # return f"LOT{random.randint(2024, 2025)}{random.randint(100, 999)}" # # # def generate_saudi_po_number(): # """Generate Saudi purchase order number""" # return f"PO-{random.randint(2024, 2025)}-{random.randint(1000, 9999)}" # # # def create_saudi_suppliers(tenants): # """Create Saudi suppliers""" # suppliers = [] # # for tenant in tenants: # print(f"Creating suppliers for {tenant.name}...") # # # Get or create creator # try: # creators = User.objects.filter(tenant=tenant) # creator = random.choice(creators) if creators.exists() else None # except: # creator = None # # for i, supplier_data in enumerate(SAUDI_SUPPLIER_DATA): # supplier_code = f"SUP-{i + 1:03d}" # # # Ensure unique supplier code # counter = 1 # original_code = supplier_code # try: # while Supplier.objects.filter(tenant=tenant, supplier_code=supplier_code).exists(): # supplier_code = f"{original_code}-{counter}" # counter += 1 # except: # pass # # try: # with transaction.savepoint(): # supplier = Supplier.objects.create( # tenant=tenant, # supplier_code=supplier_code, # name=supplier_data['name'], # supplier_type=supplier_data['type'], # contact_person=f"Manager - {supplier_data['name']}", # phone=supplier_data['phone'], # email=f"contact@{supplier_data['name'].lower().replace(' ', '').replace('.', '')}.sa", # website=f"https://www.{supplier_data['name'].lower().replace(' ', '').replace('.', '')}.sa", # address_line_1=f"{random.randint(1, 999)} King {random.choice(['Fahd', 'Abdullah', 'Saud'])} Road", # city=supplier_data['city'], # state=f"{supplier_data['city']} Province", # postal_code=f"{random.randint(10000, 99999)}", # country='Saudi Arabia', # tax_id=f"TAX-{random.randint(100000000, 999999999)}", # payment_terms=random.choice(['NET_30', 'NET_60', 'COD']), # performance_rating=Decimal(str(random.uniform(3.5, 5.0))), # on_time_delivery_rate=Decimal(str(random.uniform(85, 98))), # quality_rating=Decimal(str(random.uniform(3.5, 5.0))), # is_active=True, # is_preferred=random.choice([True, False]), # certifications=[ # {'name': 'ISO 13485', 'number': f"ISO-{random.randint(10000, 99999)}", # 'expiry': '2025-12-31'}, # {'name': 'Saudi FDA', 'number': f"SFDA-{random.randint(10000, 99999)}", # 'expiry': '2025-06-30'} # ], # notes=f"Saudi medical supplier - {supplier_data['name']}", # created_by=creator # ) # suppliers.append(supplier) # # except Exception as e: # print(f"Error creating supplier {supplier_code}: {e}") # continue # # print(f"Created {len(suppliers)} suppliers") # return suppliers # # # def create_saudi_inventory_locations(tenants, locations_per_tenant=20): # """Create Saudi inventory locations""" # locations = [] # # for tenant in tenants: # print(f"Creating inventory locations for {tenant.name}...") # # for i in range(locations_per_tenant): # location_code = f"LOC-{i + 1:03d}" # building = random.choice(SAUDI_STORAGE_LOCATIONS['buildings']) # floor = random.choice(SAUDI_STORAGE_LOCATIONS['floors']) # room = random.choice(SAUDI_STORAGE_LOCATIONS['rooms']) # zone = random.choice(SAUDI_STORAGE_LOCATIONS['zones']) if random.choice([True, False]) else None # aisle = random.choice(SAUDI_STORAGE_LOCATIONS['aisles']) if random.choice([True, False]) else None # shelf = random.choice(SAUDI_STORAGE_LOCATIONS['shelves']) if random.choice([True, False]) else None # bin_location = random.choice(SAUDI_STORAGE_LOCATIONS['bins']) if random.choice([True, False]) else None # # location_type = random.choice(['WAREHOUSE', 'PHARMACY', 'DEPARTMENT', 'MOBILE', 'EXTERNAL']) # # # Temperature controlled for pharmaceuticals # temp_controlled = random.choice([True, False]) # temp_min = random.choice([2, 15, 20]) if temp_controlled else None # temp_max = random.choice([8, 25, 30]) if temp_controlled else None # # # Humidity controlled # humidity_controlled = random.choice([True, False]) # humidity_min = random.randint(30, 45) if humidity_controlled else None # humidity_max = random.randint(55, 70) if humidity_controlled else None # # # Secure location for controlled substances # secure_location = random.choice([True, False]) # # # Get or create manager # try: # managers = User.objects.filter(tenant=tenant) # manager = random.choice(managers) if managers.exists() else None # except: # manager = None # # try: # with transaction.savepoint(): # location = InventoryLocation.objects.create( # tenant=tenant, # location_code=location_code, # name=f"{building} - {room}", # description=f"Storage location in {building}, {floor}, {room}", # location_type=location_type, # building=building, # floor=floor, # room=room, # zone=zone, # aisle=aisle, # shelf=shelf, # bin=bin_location, # capacity_cubic_feet=Decimal(str(random.randint(100, 1000))), # max_weight_pounds=Decimal(str(random.randint(500, 5000))), # temperature_controlled=temp_controlled, # temperature_min=temp_min, # temperature_max=temp_max, # humidity_controlled=humidity_controlled, # humidity_min=humidity_min, # humidity_max=humidity_max, # secure_location=secure_location, # access_control=random.choice( # ['KEYCARD', 'PIN', 'BIOMETRIC', 'KEY']) if secure_location else None, # is_active=True, # location_manager=manager, # notes=f"Created for {tenant.name} inventory management", # created_by=manager # ) # locations.append(location) # # except Exception as e: # print(f"Error creating location {location_code}: {e}") # continue # # print(f"Created {len(locations)} inventory locations") # return locations # # # def create_saudi_inventory_items(tenants, items_per_tenant=100): # """Create Saudi inventory items""" # items = [] # # for tenant in tenants: # print(f"Creating inventory items for {tenant.name}...") # # # Get or create creator # try: # creators = User.objects.filter(tenant=tenant) # creator = random.choice(creators) if creators.exists() else None # except: # creator = None # # # Create mix of common items and random items # items_to_create = COMMON_MEDICAL_ITEMS.copy() # # # Add random items # for i in range(items_per_tenant - len(COMMON_MEDICAL_ITEMS)): # category = random.choice(SAUDI_MEDICAL_CATEGORIES) # subcategory = SAUDI_PHARMACEUTICAL_SUBCATEGORIES.get(category, [f"{category} Supplies"])[ # 0] if category in SAUDI_PHARMACEUTICAL_SUBCATEGORIES else f"{category} Supplies" # # items_to_create.append({ # 'name': f"{category} Item {i + 1}", # 'category': category, # 'subcategory': subcategory, # 'unit': random.choice(['PCS', 'BOX', 'VIAL', 'TAB', 'CAP', 'ML', 'GM']), # 'controlled': random.choice([True, False]) if category == 'Pharmaceuticals' else False # }) # # for item_data in items_to_create[:items_per_tenant]: # item_code = generate_saudi_item_code() # # # Ensure unique item code # counter = 1 # original_code = item_code # try: # while InventoryItem.objects.filter(tenant=tenant, item_code=item_code).exists(): # item_code = f"{original_code}-{counter}" # counter += 1 # except: # pass # # manufacturer = random.choice(SAUDI_MEDICAL_MANUFACTURERS) # # # Generate costs in SAR # unit_cost = Decimal(str(random.uniform(10, 1000))) # list_price = unit_cost * Decimal(str(random.uniform(1.2, 3.0))) # # # Storage requirements # storage_temp_min = random.choice([2, 15, 20]) if random.choice([True, False]) else None # storage_temp_max = random.choice([8, 25, 30]) if storage_temp_min else None # # # Controlled substance info # controlled = item_data.get('controlled', False) # dea_schedule = random.choice(['II', 'III', 'IV', 'V']) if controlled else None # # try: # with transaction.savepoint(): # item = InventoryItem.objects.create( # tenant=tenant, # item_code=item_code, # item_name=item_data['name'], # description=f"Medical supply item for {tenant.name}", # category=item_data['category'], # subcategory=item_data['subcategory'], # item_type=random.choice(['STOCK', 'NON_STOCK', 'SERVICE', 'KIT']), # manufacturer=manufacturer, # model_number=f"MOD-{random.randint(1000, 9999)}" if random.choice([True, False]) else None, # part_number=f"PN-{random.randint(100000, 999999)}" if random.choice([True, False]) else None, # upc_code=str(random.randint(100000000000, 999999999999)) if random.choice( # [True, False]) else None, # ndc_code=f"{random.randint(10000, 99999)}-{random.randint(100, 999)}-{random.randint(10, 99)}" if # item_data['category'] == 'Pharmaceuticals' else None, # unit_of_measure=item_data['unit'], # package_size=random.randint(1, 100), # package_type=random.choice(['BOTTLE', 'BOX', 'VIAL', 'TUBE', 'POUCH']), # unit_cost=unit_cost, # list_price=list_price, # storage_temperature_min=storage_temp_min, # storage_temperature_max=storage_temp_max, # storage_humidity_min=random.randint(30, 45) if random.choice([True, False]) else None, # storage_humidity_max=random.randint(55, 70) if random.choice([True, False]) else None, # storage_requirements="Store in cool, dry place" if random.choice([True, False]) else None, # has_expiration=True if item_data['category'] == 'Pharmaceuticals' else random.choice( # [True, False]), # shelf_life_days=random.randint(365, 1095) if item_data[ # 'category'] == 'Pharmaceuticals' else None, # fda_approved=random.choice([True, False]), # controlled_substance=controlled, # dea_schedule=dea_schedule, # is_active=True, # is_tracked=True, # is_serialized=random.choice([True, False]), # is_lot_tracked=True if item_data['category'] == 'Pharmaceuticals' else random.choice( # [True, False]), # reorder_point=random.randint(10, 100), # reorder_quantity=random.randint(50, 500), # max_stock_level=random.randint(200, 1000), # clinical_use=f"Used for {item_data['subcategory'].lower()} treatment" if random.choice( # [True, False]) else None, # notes=f"Saudi medical supply item - {item_data['name']}", # created_by=creator # ) # items.append(item) # # except Exception as e: # print(f"Error creating item {item_code}: {e}") # continue # # print(f"Created {len(items)} inventory items") # return items # # # def create_saudi_inventory_stock(items, locations, stock_entries_per_item=2): # """Create Saudi inventory stock entries""" # stocks = [] # # for item in items: # print(f"Creating stock for {item.item_name}...") # # # Get locations for this tenant # tenant_locations = [loc for loc in locations if loc.tenant == item.tenant] # if not tenant_locations: # continue # # for _ in range(min(stock_entries_per_item, len(tenant_locations))): # location = random.choice(tenant_locations) # # # Generate stock details # lot_number = generate_saudi_lot_number() if item.is_lot_tracked else None # serial_number = f"SN{random.randint(100000, 999999)}" if item.is_serialized else None # # quantity_on_hand = random.randint(0, 500) # quantity_reserved = random.randint(0, min(quantity_on_hand, 50)) # # # Dates # received_date = django_timezone.now().date() - timedelta(days=random.randint(1, 365)) # expiration_date = received_date + timedelta( # days=item.shelf_life_days) if item.has_expiration and item.shelf_life_days else None # # # Costs # unit_cost = item.unit_cost * Decimal(str(random.uniform(0.9, 1.1))) # Some variation # # # Quality status # quality_status = 'AVAILABLE' # if expiration_date and expiration_date <= django_timezone.now().date(): # quality_status = 'EXPIRED' # elif expiration_date and expiration_date <= django_timezone.now().date() + timedelta(days=30): # quality_status = 'EXPIRING_SOON' # elif random.choice([True, False, False, False]): # 25% chance # quality_status = random.choice(['QUARANTINED', 'DAMAGED', 'RECALLED']) # # try: # with transaction.savepoint(): # stock = InventoryStock.objects.create( # inventory_item=item, # location=location, # lot_number=lot_number, # serial_number=serial_number, # quantity_on_hand=quantity_on_hand, # quantity_reserved=quantity_reserved, # received_date=received_date, # expiration_date=expiration_date, # unit_cost=unit_cost, # quality_status=quality_status, # notes=f"Stock entry for {item.item_name} at {location.name}" # ) # stocks.append(stock) # # except Exception as e: # print(f"Error creating stock for {item.item_code}: {e}") # continue # # print(f"Created {len(stocks)} stock entries") # return stocks # # # def create_saudi_purchase_orders(tenants, suppliers, orders_per_tenant=10): # """Create Saudi purchase orders""" # orders = [] # # for tenant in tenants: # print(f"Creating purchase orders for {tenant.name}...") # # # Get suppliers for this tenant # tenant_suppliers = [supplier for supplier in suppliers if supplier.tenant == tenant] # if not tenant_suppliers: # print(f"No suppliers found for {tenant.name}, skipping purchase orders...") # continue # # # Get users who can create POs # try: # requesters = User.objects.filter(tenant=tenant) # approvers = User.objects.filter(tenant=tenant) # # requester = random.choice(requesters) if requesters.exists() else None # approver = random.choice(approvers) if approvers.exists() else None # except: # requester = None # approver = None # # # Get delivery locations # try: # locations = InventoryLocation.objects.filter(tenant=tenant) # delivery_location = random.choice(locations) if locations.exists() else None # except: # delivery_location = None # # for i in range(orders_per_tenant): # po_number = generate_saudi_po_number() # # # Ensure unique PO number # counter = 1 # original_po = po_number # try: # while PurchaseOrder.objects.filter(tenant=tenant, po_number=po_number).exists(): # po_number = f"{original_po}-{counter}" # counter += 1 # except: # pass # # supplier = random.choice(tenant_suppliers) # # # Generate dates # order_date = django_timezone.now().date() - timedelta(days=random.randint(1, 90)) # requested_delivery = order_date + timedelta(days=random.randint(7, 30)) # # # Determine status # status = random.choices( # ['DRAFT', 'PENDING_APPROVAL', 'APPROVED', 'SENT', 'PARTIAL_RECEIVED', 'RECEIVED', 'CANCELLED'], # weights=[10, 15, 10, 20, 15, 25, 5] # )[0] # # # Generate amounts in SAR # subtotal = Decimal(str(random.uniform(1000, 50000))) # tax_rate = Decimal('0.15') # 15% VAT in Saudi Arabia # tax_amount = subtotal * tax_rate # shipping_amount = Decimal(str(random.uniform(100, 1000))) # total_amount = subtotal + tax_amount + shipping_amount # # try: # with transaction.savepoint(): # order = PurchaseOrder.objects.create( # tenant=tenant, # po_number=po_number, # supplier=supplier, # Now using the Supplier object # order_date=order_date, # requested_delivery_date=requested_delivery, # promised_delivery_date=requested_delivery + timedelta( # days=random.randint(0, 7)) if status != 'DRAFT' else None, # actual_delivery_date=requested_delivery + timedelta(days=random.randint(-3, 10)) if status in [ # 'RECEIVED', 'PARTIAL_RECEIVED'] else None, # order_type=random.choice(['STANDARD', 'RUSH', 'EMERGENCY', 'BLANKET']), # priority=random.choice(['LOW', 'NORMAL', 'HIGH', 'URGENT']), # subtotal=subtotal, # tax_amount=tax_amount, # shipping_amount=shipping_amount, # total_amount=total_amount, # status=status, # delivery_location=delivery_location, # delivery_instructions=f"Deliver to {delivery_location.name} during business hours" if delivery_location else None, # payment_terms=random.choice(['NET_30', 'NET_60', 'COD', 'PREPAID']), # requested_by=requester, # approved_by=approver if status not in ['DRAFT', 'PENDING_APPROVAL'] else None, # approval_date=order_date + timedelta(days=random.randint(1, 5)) if status not in ['DRAFT', # 'PENDING_APPROVAL'] else None, # notes=f"Purchase order for {tenant.name} medical supplies", # created_by=requester # ) # orders.append(order) # # except Exception as e: # print(f"Error creating PO {po_number}: {e}") # continue # # print(f"Created {len(orders)} purchase orders") # return orders # # # def create_saudi_purchase_order_items(orders, items): # """Create Saudi purchase order items""" # po_items = [] # # for order in orders: # print(f"Creating items for PO {order.po_number}...") # # # Get items for this tenant # tenant_items = [item for item in items if item.tenant == order.tenant] # if not tenant_items: # continue # # # Create 1-10 items per order # num_items = random.randint(1, min(10, len(tenant_items))) # selected_items = random.sample(tenant_items, num_items) # # for line_num, item in enumerate(selected_items, 1): # quantity_ordered = random.randint(10, 500) # quantity_received = 0 # # if order.status in ['PARTIAL_RECEIVED', 'RECEIVED']: # if order.status == 'RECEIVED': # quantity_received = quantity_ordered # else: # quantity_received = random.randint(0, quantity_ordered) # # # Price variations # unit_price = item.unit_cost * Decimal(str(random.uniform(0.8, 1.2))) # total_price = unit_price * quantity_ordered # # status = 'PENDING' # if order.status == 'RECEIVED': # status = 'RECEIVED' # elif order.status == 'PARTIAL_RECEIVED': # status = 'PARTIAL_RECEIVED' if quantity_received < quantity_ordered else 'RECEIVED' # elif order.status == 'CANCELLED': # status = 'CANCELLED' # # try: # with transaction.savepoint(): # po_item = PurchaseOrderItem.objects.create( # purchase_order=order, # line_number=line_num, # inventory_item=item, # quantity_ordered=quantity_ordered, # quantity_received=quantity_received, # unit_price=unit_price, # total_price=total_price, # requested_delivery_date=order.requested_delivery_date, # status=status, # notes=f"PO item for {item.item_name}" # ) # po_items.append(po_item) # # except Exception as e: # print(f"Error creating PO item for {item.item_code}: {e}") # continue # # print(f"Created {len(po_items)} purchase order items") # return po_items # # # def main(): # """Main function to create all Saudi inventory data""" # print("Starting Saudi inventory data generation...") # # # Get tenants # try: # tenants = list(Tenant.objects.filter(is_active=True)) # if not tenants: # print("No active tenants found. Please create tenants first.") # return # # print(f"Found {len(tenants)} active tenants") # except Exception as e: # print(f"Error getting tenants: {e}") # return # # # Create suppliers first (required for purchase orders) # suppliers = create_saudi_suppliers(tenants) # # # Create inventory locations # locations = create_saudi_inventory_locations(tenants, locations_per_tenant=15) # # # Create inventory items # items = create_saudi_inventory_items(tenants, items_per_tenant=50) # # # Create inventory stock # stocks = create_saudi_inventory_stock(items, locations, stock_entries_per_item=2) # # # Create purchase orders # orders = create_saudi_purchase_orders(tenants, suppliers, orders_per_tenant=8) # # # Create purchase order items # po_items = create_saudi_purchase_order_items(orders, items) # # print("\n=== Saudi Inventory Data Generation Complete ===") # print(f"Created {len(suppliers)} suppliers") # print(f"Created {len(locations)} inventory locations") # print(f"Created {len(items)} inventory items") # print(f"Created {len(stocks)} stock entries") # print(f"Created {len(orders)} purchase orders") # print(f"Created {len(po_items)} purchase order items") # # # if __name__ == "__main__": # main()