Marwan Alwali 4d06ca4b5e update
2025-09-20 14:26:19 +03:00

961 lines
30 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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()
class Employee(models.Model):
# """
# Employee model for hospital staff management.
# """
# GENDER_CHOICES = [
# ('MALE', 'Male'),
# ('FEMALE', 'Female'),
# ('OTHER', 'Other'),
# ('UNKNOWN', 'Unknown'),
# ]
# MARITAL_STATUS_CHOICES = [
# ('SINGLE', 'Single'),
# ('MARRIED', 'Married'),
# ('DIVORCED', 'Divorced'),
# ('WIDOWED', 'Widowed'),
# ('SEPARATED', 'Separated'),
# ('OTHER', 'Other'),
# ]
# EMPLOYMENT_TYPE_CHOICES = [
# ('FULL_TIME', 'Full Time'),
# ('PART_TIME', 'Part Time'),
# ('CONTRACT', 'Contract'),
# ('TEMPORARY', 'Temporary'),
# ('INTERN', 'Intern'),
# ('VOLUNTEER', 'Volunteer'),
# ('PER_DIEM', 'Per Diem'),
# ('CONSULTANT', 'Consultant'),
# ]
# EMPLOYMENT_STATUS_CHOICES = [
# ('ACTIVE', 'Active'),
# ('INACTIVE', 'Inactive'),
# ('TERMINATED', 'Terminated'),
# ('SUSPENDED', 'Suspended'),
# ('LEAVE', 'On Leave'),
# ('RETIRED', 'Retired'),
# ]
# # Tenant relationship
# tenant = models.ForeignKey(
# 'core.Tenant',
# on_delete=models.CASCADE,
# related_name='employees',
# help_text='Organization tenant'
# )
#
# # User relationship (optional - for employees who have system access)
# user = models.OneToOneField(
# settings.AUTH_USER_MODEL,
# on_delete=models.SET_NULL,
# null=True,
# blank=True,
# related_name='employee_profile',
# help_text='Associated user account'
# )
#
# # Employee Information
# employee_id = models.UUIDField(
# default=uuid.uuid4,
# unique=True,
# editable=False,
# help_text='Unique employee identifier'
# )
# employee_number = models.CharField(
# max_length=20,
# help_text='Employee number'
# )
#
# # Personal Information
# first_name = models.CharField(
# max_length=50,
# help_text='First name'
# )
# last_name = models.CharField(
# max_length=50,
# help_text='Last name'
# )
# middle_name = models.CharField(
# max_length=50,
# blank=True,
# null=True,
# help_text='Middle name'
# )
# preferred_name = models.CharField(
# max_length=50,
# blank=True,
# null=True,
# help_text='Preferred name'
# )
#
# # Contact Information
# email = models.EmailField(
# blank=True,
# null=True,
# help_text='Email address'
# )
# phone = models.CharField(
# max_length=20,
# blank=True,
# null=True,
# help_text='Phone number'
# )
# mobile_phone = models.CharField(
# max_length=20,
# blank=True,
# null=True,
# help_text='Mobile phone number'
# )
#
# # Address Information
# address_line_1 = models.CharField(
# max_length=100,
# blank=True,
# null=True,
# help_text='Address line 1'
# )
# address_line_2 = models.CharField(
# max_length=100,
# blank=True,
# null=True,
# help_text='Address line 2'
# )
# city = models.CharField(
# max_length=50,
# blank=True,
# null=True,
# help_text='City'
# )
# state = models.CharField(
# max_length=50,
# blank=True,
# null=True,
# help_text='State/Province'
# )
# postal_code = models.CharField(
# max_length=20,
# blank=True,
# null=True,
# help_text='Postal/ZIP code'
# )
# country = models.CharField(
# max_length=50,
# blank=True,
# null=True,
# help_text='Country'
# )
# national_id = models.CharField(
# max_length=10,
# blank=True,
# null=True,
# unique=True,
# help_text='National ID'
# )
# # Personal Details
# date_of_birth = models.DateField(
# blank=True,
# null=True,
# help_text='Date of birth'
# )
# gender = models.CharField(
# max_length=10,
# choices=GENDER_CHOICES,
# blank=True,
# null=True,
# help_text='Gender'
# )
# marital_status = models.CharField(
# max_length=20,
# choices=MARITAL_STATUS_CHOICES,
# blank=True,
# null=True,
# help_text='Marital status'
# )
#
# # Employment Information
# department = models.ForeignKey(
# 'Department',
# on_delete=models.SET_NULL,
# null=True,
# blank=True,
# related_name='employees',
# help_text='Department'
# )
# job_title = models.CharField(
# max_length=100,
# help_text='Job title'
# )
# employment_type = models.CharField(
# max_length=20,
# choices=EMPLOYMENT_TYPE_CHOICES,
# help_text='Employment type'
# )
# employment_status = models.CharField(
# max_length=20,
# choices=EMPLOYMENT_STATUS_CHOICES,
# default='ACTIVE',
# help_text='Employment status'
# )
#
# # Employment Dates
# hire_date = models.DateField(
# help_text='Hire date'
# )
# termination_date = models.DateField(
# blank=True,
# null=True,
# help_text='Termination date'
# )
#
# # Supervisor Information
# supervisor = models.ForeignKey(
# 'self',
# on_delete=models.SET_NULL,
# null=True,
# blank=True,
# related_name='direct_reports',
# help_text='Direct supervisor'
# )
#
# # Work Schedule Information
# standard_hours_per_week = models.DecimalField(
# max_digits=5,
# decimal_places=2,
# default=Decimal('40.00'),
# help_text='Standard hours per week'
# )
# fte_percentage = models.DecimalField(
# max_digits=5,
# decimal_places=2,
# default=Decimal('100.00'),
# validators=[MinValueValidator(0), MaxValueValidator(100)],
# help_text='FTE percentage'
# )
#
# # Compensation Information
# hourly_rate = models.DecimalField(
# max_digits=10,
# decimal_places=2,
# blank=True,
# null=True,
# help_text='Hourly rate'
# )
# annual_salary = models.DecimalField(
# max_digits=12,
# decimal_places=2,
# blank=True,
# null=True,
# help_text='Annual salary'
# )
#
# # Professional Information
# license_number = models.CharField(
# max_length=50,
# blank=True,
# null=True,
# help_text='Professional license number'
# )
# license_expiry_date = models.DateField(
# blank=True,
# null=True,
# help_text='License expiry date'
# )
# certifications = models.JSONField(
# default=list,
# help_text='Professional certifications'
# )
#
# # Emergency Contact
# emergency_contact_name = models.CharField(
# max_length=100,
# blank=True,
# null=True,
# help_text='Emergency contact name'
# )
# emergency_contact_relationship = models.CharField(
# max_length=50,
# blank=True,
# null=True,
# help_text='Emergency contact relationship'
# )
# emergency_contact_phone = models.CharField(
# max_length=20,
# blank=True,
# null=True,
# help_text='Emergency contact phone'
# )
#
# # Notes
# notes = models.TextField(
# blank=True,
# null=True,
# help_text='Employee notes'
# )
#
# # Metadata
# created_at = models.DateTimeField(auto_now_add=True)
# updated_at = models.DateTimeField(auto_now=True)
# created_by = models.ForeignKey(
# settings.AUTH_USER_MODEL,
# on_delete=models.SET_NULL,
# null=True,
# blank=True,
# related_name='created_employees',
# help_text='User who created the employee record'
# )
#
# class Meta:
# db_table = 'hr_employee'
# verbose_name = 'Employee'
# verbose_name_plural = 'Employees'
# ordering = ['last_name', 'first_name']
# indexes = [
# models.Index(fields=['tenant', 'employment_status']),
# models.Index(fields=['employee_number']),
# models.Index(fields=['last_name', 'first_name']),
# models.Index(fields=['department']),
# models.Index(fields=['hire_date']),
# ]
# unique_together = ['tenant', 'employee_number']
#
# def __str__(self):
# return f"{self.employee_number} - {self.get_full_name()}"
#
# def get_full_name(self):
# """
# Get employee's full name.
# """
# if self.middle_name:
# return f"{self.first_name} {self.middle_name} {self.last_name}"
# return f"{self.first_name} {self.last_name}"
#
# def get_display_name(self):
# """
# Get employee's display name (preferred name if available).
# """
# if self.preferred_name:
# return f"{self.preferred_name} {self.last_name}"
# return self.get_full_name()
#
# @property
# def age(self):
# """
# Calculate employee's age.
# """
# if self.date_of_birth:
# today = date.today()
# return today.year - self.date_of_birth.year - ((today.month, today.day) < (self.date_of_birth.month, self.date_of_birth.day))
# return None
#
# @property
# def years_of_service(self):
# """
# Calculate years of service.
# """
# if self.hire_date:
# end_date = self.termination_date or date.today()
# return (end_date - self.hire_date).days / 365.25
# return 0
#
# @property
# def is_license_expired(self):
# """
# Check if professional license is expired.
# """
# if self.license_expiry_date:
# return self.license_expiry_date < date.today()
# return False
#
# @property
# def full_address(self):
# """
# Get full address.
# """
# parts = [
# self.address_line_1,
# self.address_line_2,
# f"{self.city}, {self.state} {self.postal_code}",
# self.country
# ]
# return "\n".join([part for part in parts if part])
# class TrainingRecord(models.Model):
# """
# Training record model for employee training and certifications.
# """
#
# class TrainingType(models.TextChoices):
# ORIENTATION = 'ORIENTATION', 'Orientation'
# MANDATORY = 'MANDATORY', 'Mandatory Training'
# CONTINUING_ED = 'CONTINUING_ED', 'Continuing Education'
# CERTIFICATION = 'CERTIFICATION', 'Certification'
# SKILLS = 'SKILLS', 'Skills Training'
# SAFETY = 'SAFETY', 'Safety Training'
# COMPLIANCE = 'COMPLIANCE', 'Compliance Training'
# LEADERSHIP = 'LEADERSHIP', 'Leadership Development'
# TECHNICAL = 'TECHNICAL', 'Technical Training'
# OTHER = 'OTHER', 'Other'
#
# class TrainingStatus(models.TextChoices):
# SCHEDULED = 'SCHEDULED', 'Scheduled'
# IN_PROGRESS = 'IN_PROGRESS', 'In Progress'
# COMPLETED = 'COMPLETED', 'Completed'
# CANCELLED = 'CANCELLED', 'Cancelled'
# NO_SHOW = 'NO_SHOW', 'No Show'
# FAILED = 'FAILED', 'Failed'
#
# # Employee relationship
# employee = models.ForeignKey(
# Employee,
# on_delete=models.CASCADE,
# related_name='training_records',
# help_text='Employee'
# )
#
# # Training Information
# record_id = models.UUIDField(
# default=uuid.uuid4,
# unique=True,
# editable=False,
# help_text='Unique training record identifier'
# )
# training_name = models.CharField(
# max_length=200,
# help_text='Training name'
# )
# training_description = models.TextField(
# blank=True,
# null=True,
# help_text='Training description'
# )
#
# # Training Type
# training_type = models.CharField(
# max_length=20,
# choices=TrainingType.choices,
# help_text='Training type'
# )
#
# # Training Provider
# training_provider = models.CharField(
# max_length=200,
# blank=True,
# null=True,
# help_text='Training provider'
# )
# instructor = models.CharField(
# max_length=100,
# blank=True,
# null=True,
# help_text='Instructor name'
# )
#
# # Training Dates
# training_date = models.DateField(
# help_text='Training date'
# )
# completion_date = models.DateField(
# blank=True,
# null=True,
# help_text='Completion date'
# )
# expiry_date = models.DateField(
# blank=True,
# null=True,
# help_text='Certification expiry date'
# )
#
# # Training Details
# duration_hours = models.DecimalField(
# max_digits=5,
# decimal_places=2,
# default=Decimal('0.00'),
# help_text='Training duration in hours'
# )
# credits_earned = models.DecimalField(
# max_digits=5,
# decimal_places=2,
# default=Decimal('0.00'),
# help_text='Credits earned'
# )
#
# # Training Status
# status = models.CharField(
# max_length=20,
# choices=TrainingStatus.choices,
# default='SCHEDULED',
# help_text='Training status'
# )
#
# # Results
# score = models.DecimalField(
# max_digits=5,
# decimal_places=2,
# blank=True,
# null=True,
# help_text='Training score/grade'
# )
# passed = models.BooleanField(
# default=False,
# help_text='Training passed'
# )
# is_certified = models.BooleanField(
# default=False,
# help_text='Training is certified'
# )
# # Certification Information
# certificate_number = models.CharField(
# max_length=50,
# blank=True,
# null=True,
# help_text='Certificate number'
# )
# certification_body = models.CharField(
# max_length=200,
# blank=True,
# null=True,
# help_text='Certification body'
# )
#
# # Cost Information
# training_cost = models.DecimalField(
# max_digits=10,
# decimal_places=2,
# default=Decimal('0.00'),
# help_text='Training cost'
# )
#
# # Notes
# notes = models.TextField(
# blank=True,
# null=True,
# help_text='Training notes'
# )
#
# # Metadata
# created_at = models.DateTimeField(auto_now_add=True)
# updated_at = models.DateTimeField(auto_now=True)
# created_by = models.ForeignKey(
# settings.AUTH_USER_MODEL,
# on_delete=models.SET_NULL,
# null=True,
# blank=True,
# related_name='created_training_records',
# help_text='User who created the training record'
# )
#
# class Meta:
# db_table = 'hr_training_record'
# verbose_name = 'Training Record'
# verbose_name_plural = 'Training Records'
# ordering = ['-training_date']
# indexes = [
# models.Index(fields=['employee', 'training_date']),
# models.Index(fields=['training_type']),
# models.Index(fields=['status']),
# models.Index(fields=['expiry_date']),
# ]
#
# def __str__(self):
# return f"{self.employee.get_full_name()} - {self.training_name}"
#
# @property
# def tenant(self):
# """
# Get tenant from employee.
# """
# return self.employee.tenant
#
# @property
# def is_expired(self):
# """
# Check if certification is expired.
# """
# if self.expiry_date:
# return self.expiry_date < date.today()
# return False
#
# @property
# def days_to_expiry(self):
# """
# Calculate days to expiry.
# """
# if self.expiry_date:
# return (self.expiry_date - date.today()).days
# return None
#
# @property
# def is_due_for_renewal(self):
# """
# Check if certification is due for renewal (within 30 days).
# """
# if self.expiry_date:
# return (self.expiry_date - date.today()).days <= 30
# return False
# class Certification(models.Model):
# tenant = models.ForeignKey('core.Tenant', on_delete=models.PROTECT, related_name='certifications')
# name = models.CharField(max_length=100)
# issuer = models.CharField(max_length=150, blank=True, null=True)
# is_clinical = models.BooleanField(default=False)
#
# class Meta:
# unique_together = [('tenant', 'name')]
#
# class EmployeeCertification(models.Model):
# employee = models.ForeignKey(Employee, on_delete=models.CASCADE, related_name='employee_certifications')
# certification = models.ForeignKey(Certification, on_delete=models.PROTECT)
# credential_id = models.CharField(max_length=100, blank=True, null=True)
# issued_on = models.DateField(blank=True, null=True)
# expires_on = models.DateField(blank=True, null=True)
#
# class Meta:
# constraints = [
# models.UniqueConstraint(fields=['employee', 'certification'], name='uq_employee_cert_once')
# ]