961 lines
30 KiB
Plaintext
961 lines
30 KiB
Plaintext
# 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')
|
||
# ] |