# Generated by Django 5.2.6 on 2025-09-19 10:58 import django.core.validators import django.db.models.deletion import uuid from decimal import Decimal from django.conf import settings from django.db import migrations, models class Migration(migrations.Migration): initial = True dependencies = [ ("core", "0001_initial"), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( name="Department", fields=[ ( "id", models.BigAutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ( "department_id", models.UUIDField( default=uuid.uuid4, editable=False, help_text="Unique department identifier", unique=True, ), ), ( "code", models.CharField( help_text="Department code (e.g., CARD, EMER, SURG)", max_length=20, ), ), ("name", models.CharField(help_text="Department name", max_length=100)), ( "description", models.TextField( blank=True, help_text="Department description", null=True ), ), ( "department_type", models.CharField( choices=[ ("CLINICAL", "Clinical"), ("ADMINISTRATIVE", "Administrative"), ("SUPPORT", "Support"), ("ANCILLARY", "Ancillary"), ("EXECUTIVE", "Executive"), ], help_text="Department type", max_length=20, ), ), ( "phone", models.CharField( blank=True, help_text="Department phone number", max_length=20, null=True, ), ), ( "extension", models.CharField( blank=True, help_text="Phone extension", max_length=10, null=True, ), ), ( "email", models.EmailField( blank=True, help_text="Department email", max_length=254, null=True, ), ), ( "annual_budget", models.DecimalField( blank=True, decimal_places=2, help_text="Annual budget", max_digits=12, null=True, ), ), ( "cost_center", models.CharField( blank=True, help_text="Cost center code", max_length=20, null=True, ), ), ( "authorized_positions", models.PositiveIntegerField( default=0, help_text="Number of authorized positions" ), ), ( "location", models.CharField( blank=True, help_text="Department location", max_length=100, null=True, ), ), ( "is_active", models.BooleanField(default=True, help_text="Department is active"), ), ( "is_24_hour", models.BooleanField( default=False, help_text="Department operates 24 hours" ), ), ( "operating_hours", models.JSONField( blank=True, default=dict, help_text="Operating hours by day of week", ), ), ( "accreditation_required", models.BooleanField( default=False, help_text="Department requires special accreditation", ), ), ( "accreditation_body", models.CharField( blank=True, help_text="Accrediting body (e.g., Joint Commission, CAP)", max_length=100, null=True, ), ), ( "last_inspection_date", models.DateField( blank=True, help_text="Last inspection date", null=True ), ), ( "next_inspection_date", models.DateField( blank=True, help_text="Next scheduled inspection date", null=True, ), ), ( "notes", models.TextField( blank=True, help_text="Department notes", null=True ), ), ("created_at", models.DateTimeField(auto_now_add=True)), ("updated_at", models.DateTimeField(auto_now=True)), ( "parent_department", models.ForeignKey( blank=True, help_text="Parent department", null=True, on_delete=django.db.models.deletion.CASCADE, related_name="sub_departments", to="hr.department", ), ), ( "tenant", models.ForeignKey( help_text="Organization tenant", on_delete=django.db.models.deletion.CASCADE, related_name="departments", to="core.tenant", ), ), ], options={ "verbose_name": "Department", "verbose_name_plural": "Departments", "db_table": "hr_department", "ordering": ["name"], }, ), migrations.CreateModel( name="Employee", fields=[ ( "id", models.BigAutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ( "employee_id", models.CharField(editable=False, max_length=50, unique=True), ), ("identification_number", models.CharField(blank=True, max_length=20)), ( "id_type", models.CharField( choices=[ ("NATIONAL_ID", "National ID"), ("IQAMA", "IQAMA"), ("PASSPORT", "Passport"), ("OTHER", "Other"), ], default="NATIONAL_ID", max_length=20, ), ), ("first_name", models.CharField(blank=True, max_length=50)), ( "father_name", models.CharField(blank=True, max_length=100, null=True), ), ( "grandfather_name", models.CharField(blank=True, max_length=100, null=True), ), ("last_name", models.CharField(blank=True, max_length=50)), ("email", models.EmailField(blank=True, max_length=254, null=True)), ( "phone", models.CharField( blank=True, max_length=16, null=True, validators=[ django.core.validators.RegexValidator( message="Use E.164 format: +9665XXXXXXXX", regex="^\\+?9665\\d{8}$", ) ], ), ), ( "mobile_phone", models.CharField( blank=True, max_length=16, null=True, validators=[ django.core.validators.RegexValidator( message="Use E.164 format: +9665XXXXXXXX", regex="^\\+?9665\\d{8}$", ) ], ), ), ( "address_line_1", models.CharField(blank=True, max_length=100, null=True), ), ( "address_line_2", models.CharField(blank=True, max_length=100, null=True), ), ("city", models.CharField(blank=True, max_length=50, null=True)), ("postal_code", models.CharField(blank=True, max_length=10, null=True)), ("country", models.CharField(blank=True, max_length=50, null=True)), ("date_of_birth", models.DateField(blank=True, null=True)), ( "gender", models.CharField( blank=True, choices=[ ("MALE", "Male"), ("FEMALE", "Female"), ("OTHER", "Other"), ], max_length=20, null=True, ), ), ( "marital_status", models.CharField( blank=True, choices=[ ("SINGLE", "Single"), ("MARRIED", "Married"), ("DIVORCED", "Divorced"), ("WIDOWED", "Widowed"), ("SEPARATED", "Separated"), ("OTHER", "Other"), ], max_length=20, null=True, ), ), ( "user_timezone", models.CharField(default="Asia/Riyadh", max_length=50), ), ("language", models.CharField(default="ar", max_length=10)), ( "theme", models.CharField( choices=[ ("LIGHT", "Light"), ("DARK", "Dark"), ("AUTO", "Auto"), ], default="LIGHT", max_length=20, ), ), ( "role", models.CharField( choices=[ ("SUPER_ADMIN", "Super Administrator"), ("ADMIN", "Administrator"), ("PHYSICIAN", "Physician"), ("SURGEON", "Surgeon"), ("NURSE", "Nurse"), ("NURSE_PRACTITIONER", "Nurse Practitioner"), ("PHYSICIAN_ASSISTANT", "Physician Assistant"), ("SURGICAL_TECHNICIAN", "Surgical Technician"), ("ANESTHESIOLOGIST", "Anesthesiologist"), ( "ANESTHESIOLOGIST_ASSOCIATE", "Anesthesiologist Associate", ), ("CLINICAL_NURSE_ASSOCIATE", "Clinical Nurse Associate"), ("CLINICAL_NURSE_SPECIALIST", "Clinical Nurse Specialist"), ("CLINICAL_NURSE_MANAGER", "Clinical Nurse Manager"), ("CLINICAL_NURSE_TECHNICIAN", "Clinical Nurse Technician"), ( "CLINICAL_NURSE_COORDINATOR", "Clinical Nurse Coordinator", ), ("FELLOW", "Fellow"), ("INTERN", "Intern"), ("INTERNSHIP", "Internship"), ("RESIDENT", "Resident"), ("WORK_FROM_HOME", "Work from Home"), ("WORK_FROM_HOME_PART_TIME", "Work from Home Part-time"), ("PHARMACIST", "Pharmacist"), ("PHARMACY_TECH", "Pharmacy Technician"), ("LAB_TECH", "Laboratory Technician"), ("RADIOLOGIST", "Radiologist"), ("RAD_TECH", "Radiology Technician"), ("THERAPIST", "Therapist"), ("SOCIAL_WORKER", "Social Worker"), ("CASE_MANAGER", "Case Manager"), ("BILLING_SPECIALIST", "Billing Specialist"), ("REGISTRATION", "Registration Staff"), ("SCHEDULER", "Scheduler"), ("MEDICAL_ASSISTANT", "Medical Assistant"), ("CLERICAL", "Clerical Staff"), ("IT_SUPPORT", "IT Support"), ("QUALITY_ASSURANCE", "Quality Assurance"), ("COMPLIANCE", "Compliance Officer"), ("SECURITY", "Security"), ("MAINTENANCE", "Maintenance"), ("VOLUNTEER", "Volunteer"), ("STUDENT", "Student"), ("RESEARCHER", "Researcher"), ("CONSULTANT", "Consultant"), ("VENDOR", "Vendor"), ("GUEST", "Guest"), ], default="GUEST", max_length=50, ), ), ( "job_title", models.CharField( blank=True, help_text="Job title", max_length=100, null=True ), ), ( "license_number", models.CharField( blank=True, help_text="Professional license number", max_length=50, null=True, ), ), ( "license_expiry_date", models.DateField( blank=True, help_text="License expiry date", null=True ), ), ( "license_state", models.CharField( blank=True, help_text="Issuing state/authority", max_length=50, null=True, ), ), ( "dea_number", models.CharField( blank=True, help_text="DEA number (if applicable)", max_length=20, null=True, ), ), ( "npi_number", models.CharField( blank=True, help_text="NPI (if applicable)", max_length=10, null=True, ), ), ( "employment_status", models.CharField( choices=[ ("ACTIVE", "Active"), ("INACTIVE", "Inactive"), ("TERMINATED", "Terminated"), ("SUSPENDED", "Suspended"), ("LEAVE", "On Leave"), ("RETIRED", "Retired"), ], default="ACTIVE", max_length=20, ), ), ( "employment_type", models.CharField( blank=True, choices=[ ("FULL_TIME", "Full Time"), ("PART_TIME", "Part Time"), ("CONTRACT", "Contract"), ("TEMPORARY", "Temporary"), ("INTERN", "Intern"), ("VOLUNTEER", "Volunteer"), ("PER_DIEM", "Per Diem"), ("CONSULTANT", "Consultant"), ], help_text="Employment type", max_length=20, null=True, ), ), ( "hire_date", models.DateField(blank=True, help_text="Hire date", null=True), ), ( "termination_date", models.DateField( blank=True, help_text="Termination date", null=True ), ), ( "hourly_rate", models.DecimalField( blank=True, decimal_places=2, max_digits=10, null=True ), ), ( "standard_hours_per_week", models.DecimalField( decimal_places=2, default=Decimal("40.00"), max_digits=5 ), ), ( "annual_salary", models.DecimalField( blank=True, decimal_places=2, max_digits=12, null=True ), ), ( "fte_percentage", models.DecimalField( decimal_places=2, default=Decimal("100.00"), max_digits=5, validators=[ django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(100), ], ), ), ( "profile_picture", models.ImageField( blank=True, null=True, upload_to="profile_pictures/" ), ), ( "bio", models.TextField( blank=True, help_text="Professional bio", null=True ), ), ( "emergency_contact_name", models.CharField(blank=True, max_length=100, null=True), ), ( "emergency_contact_relationship", models.CharField(blank=True, max_length=50, null=True), ), ( "emergency_contact_phone", models.CharField(blank=True, max_length=20, null=True), ), ("notes", models.TextField(blank=True, null=True)), ("is_verified", models.BooleanField(default=False)), ("is_approved", models.BooleanField(default=False)), ("approval_date", models.DateTimeField(blank=True, null=True)), ("created_at", models.DateTimeField(auto_now_add=True)), ("updated_at", models.DateTimeField(auto_now=True)), ( "approved_by", models.ForeignKey( blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="approved_employees", to=settings.AUTH_USER_MODEL, ), ), ( "created_by", models.ForeignKey( blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="created_employees", to=settings.AUTH_USER_MODEL, ), ), ( "department", models.ForeignKey( blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="employees", to="hr.department", ), ), ( "supervisor", models.ForeignKey( blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="direct_reports", to="hr.employee", ), ), ( "tenant", models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, related_name="employees", to="core.tenant", ), ), ( "user", models.OneToOneField( on_delete=django.db.models.deletion.CASCADE, related_name="employee_profile", to=settings.AUTH_USER_MODEL, ), ), ], options={ "verbose_name": "Employee", "verbose_name_plural": "Employees", "db_table": "hr_employee", "ordering": ["last_name", "first_name"], }, ), migrations.AddField( model_name="department", name="created_by", field=models.ForeignKey( blank=True, help_text="User who created the department", null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="created_hr_departments", to="hr.employee", ), ), migrations.AddField( model_name="department", name="department_head", field=models.ForeignKey( blank=True, help_text="Department head", null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="headed_departments", to="hr.employee", ), ), migrations.CreateModel( name="PerformanceReview", fields=[ ( "id", models.BigAutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ( "review_id", models.UUIDField( default=uuid.uuid4, editable=False, help_text="Unique review identifier", ), ), ( "review_period_start", models.DateField(help_text="Review period start date"), ), ( "review_period_end", models.DateField(help_text="Review period end date"), ), ("review_date", models.DateField(help_text="Review date")), ( "review_type", models.CharField( choices=[ ("ANNUAL", "Annual Review"), ("PROBATIONARY", "Probationary Review"), ("MID_YEAR", "Mid-Year Review"), ("PROJECT", "Project Review"), ("DISCIPLINARY", "Disciplinary Review"), ("PROMOTION", "Promotion Review"), ("OTHER", "Other Review"), ], help_text="Review type", max_length=20, ), ), ( "overall_rating", models.DecimalField( decimal_places=1, help_text="Overall rating (1-5)", max_digits=3, validators=[ django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(5), ], ), ), ( "competency_ratings", models.JSONField( default=dict, help_text="Individual competency ratings" ), ), ( "goals_achieved", models.TextField( blank=True, help_text="Goals achieved during review period", null=True, ), ), ( "goals_not_achieved", models.TextField( blank=True, help_text="Goals not achieved during review period", null=True, ), ), ( "future_goals", models.TextField( blank=True, help_text="Goals for next review period", null=True ), ), ( "strengths", models.TextField( blank=True, help_text="Employee strengths", null=True ), ), ( "areas_for_improvement", models.TextField( blank=True, help_text="Areas for improvement", null=True ), ), ( "development_plan", models.TextField( blank=True, help_text="Professional development plan", null=True ), ), ( "training_recommendations", models.TextField( blank=True, help_text="Training recommendations", null=True ), ), ( "employee_comments", models.TextField( blank=True, help_text="Employee comments", null=True ), ), ( "employee_signature_date", models.DateField( blank=True, help_text="Employee signature date", null=True ), ), ( "status", models.CharField( choices=[ ("DRAFT", "Draft"), ("SUBMITTED", "Submitted"), ("IN_PROGRESS", "In Progress"), ("COMPLETED", "Completed"), ("ACKNOWLEDGED", "Acknowledged by Employee"), ("DISPUTED", "Disputed"), ], default="DRAFT", help_text="Review status", max_length=20, ), ), ( "notes", models.TextField( blank=True, help_text="Additional notes", null=True ), ), ("created_at", models.DateTimeField(auto_now_add=True)), ("updated_at", models.DateTimeField(auto_now=True)), ( "employee", models.ForeignKey( help_text="Employee being reviewed", on_delete=django.db.models.deletion.CASCADE, related_name="performance_reviews", to="hr.employee", ), ), ( "reviewer", models.ForeignKey( blank=True, help_text="Reviewer", null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="conducted_reviews", to=settings.AUTH_USER_MODEL, ), ), ], options={ "verbose_name": "Performance Review", "verbose_name_plural": "Performance Reviews", "db_table": "hr_performance_review", "ordering": ["-review_date"], }, ), migrations.CreateModel( name="Schedule", fields=[ ( "id", models.BigAutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ( "schedule_id", models.UUIDField( default=uuid.uuid4, editable=False, help_text="Unique schedule identifier", unique=True, ), ), ("name", models.CharField(help_text="Schedule name", max_length=100)), ( "description", models.TextField( blank=True, help_text="Schedule description", null=True ), ), ( "schedule_type", models.CharField( choices=[ ("REGULAR", "Regular"), ("ROTATING", "Rotating"), ("FLEXIBLE", "Flexible"), ("ON_CALL", "On-Call"), ("TEMPORARY", "Temporary"), ], help_text="Schedule type", max_length=20, ), ), ("effective_date", models.DateField(help_text="Effective date")), ( "end_date", models.DateField(blank=True, help_text="End date", null=True), ), ( "schedule_pattern", models.JSONField( default=dict, help_text="Schedule pattern configuration" ), ), ( "is_active", models.BooleanField(default=True, help_text="Schedule is active"), ), ( "approval_date", models.DateTimeField( blank=True, help_text="Approval date and time", null=True ), ), ( "notes", models.TextField(blank=True, help_text="Schedule notes", null=True), ), ("created_at", models.DateTimeField(auto_now_add=True)), ("updated_at", models.DateTimeField(auto_now=True)), ( "approved_by", models.ForeignKey( blank=True, help_text="User who approved the schedule", null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="approved_schedules", to=settings.AUTH_USER_MODEL, ), ), ( "created_by", models.ForeignKey( blank=True, help_text="User who created the schedule", null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="created_schedules", to=settings.AUTH_USER_MODEL, ), ), ( "employee", models.ForeignKey( help_text="Employee", on_delete=django.db.models.deletion.CASCADE, related_name="schedules", to="hr.employee", ), ), ], options={ "verbose_name": "Schedule", "verbose_name_plural": "Schedules", "db_table": "hr_schedule", "ordering": ["-effective_date"], }, ), migrations.CreateModel( name="ScheduleAssignment", fields=[ ( "id", models.BigAutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ( "assignment_id", models.UUIDField( default=uuid.uuid4, editable=False, help_text="Unique assignment identifier", unique=True, ), ), ("assignment_date", models.DateField(help_text="Assignment date")), ("start_time", models.TimeField(help_text="Start time")), ("end_time", models.TimeField(help_text="End time")), ( "shift_type", models.CharField( choices=[ ("DAY", "Day Shift"), ("EVENING", "Evening Shift"), ("NIGHT", "Night Shift"), ("WEEKEND", "Weekend Shift"), ("HOLIDAY", "Holiday Shift"), ("ON_CALL", "On-Call"), ("OVERTIME", "Overtime"), ], help_text="Shift type", max_length=20, ), ), ( "location", models.CharField( blank=True, help_text="Specific location", max_length=100, null=True, ), ), ( "status", models.CharField( choices=[ ("SCHEDULED", "Scheduled"), ("CONFIRMED", "Confirmed"), ("COMPLETED", "Completed"), ("CANCELLED", "Cancelled"), ("NO_SHOW", "No Show"), ], default="SCHEDULED", help_text="Assignment status", max_length=20, ), ), ( "break_minutes", models.PositiveIntegerField( default=0, help_text="Break time in minutes" ), ), ( "lunch_minutes", models.PositiveIntegerField( default=0, help_text="Lunch time in minutes" ), ), ( "notes", models.TextField( blank=True, help_text="Assignment notes", null=True ), ), ("created_at", models.DateTimeField(auto_now_add=True)), ("updated_at", models.DateTimeField(auto_now=True)), ( "department", models.ForeignKey( blank=True, help_text="Department", null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="schedule_assignments", to="hr.department", ), ), ( "schedule", models.ForeignKey( help_text="Schedule", on_delete=django.db.models.deletion.CASCADE, related_name="assignments", to="hr.schedule", ), ), ], options={ "verbose_name": "Schedule Assignment", "verbose_name_plural": "Schedule Assignments", "db_table": "hr_schedule_assignment", "ordering": ["assignment_date", "start_time"], }, ), migrations.CreateModel( name="TimeEntry", fields=[ ( "id", models.BigAutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ( "entry_id", models.UUIDField( default=uuid.uuid4, editable=False, help_text="Unique time entry identifier", unique=True, ), ), ("work_date", models.DateField(help_text="Work date")), ( "clock_in_time", models.DateTimeField( blank=True, help_text="Clock in time", null=True ), ), ( "clock_out_time", models.DateTimeField( blank=True, help_text="Clock out time", null=True ), ), ( "break_start_time", models.DateTimeField( blank=True, help_text="Break start time", null=True ), ), ( "break_end_time", models.DateTimeField( blank=True, help_text="Break end time", null=True ), ), ( "lunch_start_time", models.DateTimeField( blank=True, help_text="Lunch start time", null=True ), ), ( "lunch_end_time", models.DateTimeField( blank=True, help_text="Lunch end time", null=True ), ), ( "regular_hours", models.DecimalField( decimal_places=2, default=Decimal("0.00"), help_text="Regular hours worked", max_digits=5, ), ), ( "overtime_hours", models.DecimalField( decimal_places=2, default=Decimal("0.00"), help_text="Overtime hours worked", max_digits=5, ), ), ( "total_hours", models.DecimalField( decimal_places=2, default=Decimal("0.00"), help_text="Total hours worked", max_digits=5, ), ), ( "entry_type", models.CharField( choices=[ ("REGULAR", "Regular Time"), ("OVERTIME", "Overtime"), ("HOLIDAY", "Holiday"), ("VACATION", "Vacation"), ("SICK", "Sick Leave"), ("PERSONAL", "Personal Time"), ("TRAINING", "Training"), ], default="REGULAR", help_text="Entry type", max_length=20, ), ), ( "location", models.CharField( blank=True, help_text="Work location", max_length=100, null=True ), ), ( "approval_date", models.DateTimeField( blank=True, help_text="Approval date and time", null=True ), ), ( "status", models.CharField( choices=[ ("DRAFT", "Draft"), ("SUBMITTED", "Submitted"), ("APPROVED", "Approved"), ("REJECTED", "Rejected"), ("PAID", "Paid"), ], default="DRAFT", help_text="Entry status", max_length=20, ), ), ( "notes", models.TextField( blank=True, help_text="Time entry notes", null=True ), ), ("created_at", models.DateTimeField(auto_now_add=True)), ("updated_at", models.DateTimeField(auto_now=True)), ( "approved_by", models.ForeignKey( blank=True, help_text="User who approved the time entry", null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="approved_time_entries", to=settings.AUTH_USER_MODEL, ), ), ( "department", models.ForeignKey( blank=True, help_text="Department", null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="time_entries", to="hr.department", ), ), ( "employee", models.ForeignKey( help_text="Employee", on_delete=django.db.models.deletion.CASCADE, related_name="time_entries", to="hr.employee", ), ), ], options={ "verbose_name": "Time Entry", "verbose_name_plural": "Time Entries", "db_table": "hr_time_entry", "ordering": ["-work_date"], }, ), migrations.CreateModel( name="TrainingPrograms", fields=[ ( "id", models.BigAutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ( "program_id", models.UUIDField(default=uuid.uuid4, editable=False, unique=True), ), ("name", models.CharField(max_length=200)), ("description", models.TextField(blank=True, null=True)), ( "program_type", models.CharField( choices=[ ("ORIENTATION", "Orientation"), ("MANDATORY", "Mandatory Training"), ("CONTINUING_ED", "Continuing Education"), ("CERTIFICATION", "Certification"), ("SKILLS", "Skills Training"), ("SAFETY", "Safety Training"), ("COMPLIANCE", "Compliance Training"), ("LEADERSHIP", "Leadership Development"), ("TECHNICAL", "Technical Training"), ("OTHER", "Other"), ], max_length=20, ), ), ( "program_provider", models.CharField(blank=True, max_length=200, null=True), ), ("start_date", models.DateField(blank=True, null=True)), ("end_date", models.DateField(blank=True, null=True)), ( "duration_hours", models.DecimalField( decimal_places=2, default=Decimal("0.00"), max_digits=5 ), ), ( "cost", models.DecimalField( decimal_places=2, default=Decimal("0.00"), max_digits=10 ), ), ("is_certified", models.BooleanField(default=False)), ("validity_days", models.PositiveIntegerField(blank=True, null=True)), ( "notify_before_days", models.PositiveIntegerField(blank=True, null=True), ), ("created_at", models.DateTimeField(auto_now_add=True)), ("updated_at", models.DateTimeField(auto_now=True)), ( "created_by", models.ForeignKey( blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="created_training_programs", to="hr.employee", ), ), ( "instructor", models.ForeignKey( blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="instructor_programs", to="hr.employee", ), ), ( "tenant", models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, related_name="training_programs", to="core.tenant", ), ), ], options={ "db_table": "hr_training_program", "ordering": ["name"], }, ), migrations.CreateModel( name="ProgramPrerequisite", fields=[ ( "id", models.BigAutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ( "program", models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, related_name="prerequisites", to="hr.trainingprograms", ), ), ( "required_program", models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, related_name="unlocking_programs", to="hr.trainingprograms", ), ), ], options={ "db_table": "hr_training_program_prerequisite", }, ), migrations.CreateModel( name="ProgramModule", fields=[ ( "id", models.BigAutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ("title", models.CharField(max_length=200)), ("order", models.PositiveIntegerField(default=1)), ( "hours", models.DecimalField( decimal_places=2, default=Decimal("0.00"), max_digits=5 ), ), ( "program", models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, related_name="modules", to="hr.trainingprograms", ), ), ], options={ "db_table": "hr_training_program_module", "ordering": ["program", "order"], }, ), migrations.CreateModel( name="TrainingRecord", fields=[ ( "id", models.BigAutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ( "record_id", models.UUIDField(default=uuid.uuid4, editable=False, unique=True), ), ("enrolled_at", models.DateTimeField(auto_now_add=True)), ("started_at", models.DateTimeField(blank=True, null=True)), ("completion_date", models.DateField(blank=True, null=True)), ( "status", models.CharField( choices=[ ("SCHEDULED", "Scheduled"), ("IN_PROGRESS", "In Progress"), ("COMPLETED", "Completed"), ("CANCELLED", "Cancelled"), ("NO_SHOW", "No Show"), ("FAILED", "Failed"), ("WAITLISTED", "Waitlisted"), ], default="SCHEDULED", max_length=20, ), ), ( "credits_earned", models.DecimalField( decimal_places=2, default=Decimal("0.00"), max_digits=5 ), ), ( "score", models.DecimalField( blank=True, decimal_places=2, max_digits=5, null=True ), ), ("passed", models.BooleanField(default=False)), ("notes", models.TextField(blank=True, null=True)), ( "cost_paid", models.DecimalField( blank=True, decimal_places=2, max_digits=10, null=True ), ), ("created_at", models.DateTimeField(auto_now_add=True)), ("updated_at", models.DateTimeField(auto_now=True)), ( "created_by", models.ForeignKey( blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="created_training_records", to=settings.AUTH_USER_MODEL, ), ), ( "employee", models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, related_name="training_records", to="hr.employee", ), ), ( "program", models.ForeignKey( on_delete=django.db.models.deletion.PROTECT, related_name="training_records", to="hr.trainingprograms", ), ), ], options={ "verbose_name": "Training Enrollment", "verbose_name_plural": "Training Enrollments", "db_table": "hr_training_record", "ordering": ["-enrolled_at"], }, ), migrations.CreateModel( name="TrainingCertificates", fields=[ ( "id", models.BigAutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ( "certificate_id", models.UUIDField(default=uuid.uuid4, editable=False, unique=True), ), ("certificate_name", models.CharField(max_length=200)), ( "certificate_number", models.CharField(blank=True, max_length=50, null=True), ), ( "certification_body", models.CharField(blank=True, max_length=200, null=True), ), ("issued_date", models.DateField(auto_now_add=True)), ("expiry_date", models.DateField(blank=True, null=True)), ( "file", models.FileField(blank=True, null=True, upload_to="certificates/"), ), ("created_at", models.DateTimeField(auto_now_add=True)), ("updated_at", models.DateTimeField(auto_now=True)), ( "created_by", models.ForeignKey( blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="created_training_certificates", to="hr.employee", ), ), ( "employee", models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, related_name="training_certificates", to="hr.employee", ), ), ( "signed_by", models.ForeignKey( blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="signed_training_certificates", to="hr.employee", ), ), ( "program", models.ForeignKey( on_delete=django.db.models.deletion.PROTECT, related_name="certificates", to="hr.trainingprograms", ), ), ( "enrollment", models.OneToOneField( on_delete=django.db.models.deletion.CASCADE, related_name="certificate", to="hr.trainingrecord", ), ), ], options={ "verbose_name": "Training Certificate", "verbose_name_plural": "Training Certificates", "db_table": "hr_training_certificate", "ordering": ["-issued_date"], }, ), migrations.CreateModel( name="TrainingAttendance", fields=[ ( "id", models.BigAutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ("checked_in_at", models.DateTimeField(blank=True, null=True)), ("checked_out_at", models.DateTimeField(blank=True, null=True)), ( "status", models.CharField( choices=[ ("PRESENT", "Present"), ("LATE", "Late"), ("ABSENT", "Absent"), ("EXCUSED", "Excused"), ], default="PRESENT", max_length=10, ), ), ("notes", models.CharField(blank=True, max_length=255, null=True)), ( "enrollment", models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, related_name="attendance", to="hr.trainingrecord", ), ), ], options={ "db_table": "hr_training_attendance", "ordering": ["enrollment_id", "checked_in_at"], }, ), migrations.CreateModel( name="TrainingAssessment", fields=[ ( "id", models.BigAutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ("name", models.CharField(max_length=200)), ( "max_score", models.DecimalField(decimal_places=2, default=100, max_digits=7), ), ( "score", models.DecimalField( blank=True, decimal_places=2, max_digits=7, null=True ), ), ("passed", models.BooleanField(default=False)), ("taken_at", models.DateTimeField(blank=True, null=True)), ("notes", models.TextField(blank=True, null=True)), ( "enrollment", models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, related_name="assessments", to="hr.trainingrecord", ), ), ], options={ "db_table": "hr_training_assessment", "ordering": ["-taken_at"], }, ), migrations.CreateModel( name="TrainingSession", fields=[ ( "id", models.BigAutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ( "session_id", models.UUIDField(default=uuid.uuid4, editable=False, unique=True), ), ( "title", models.CharField( blank=True, help_text="Optional run title; falls back to program name", max_length=200, null=True, ), ), ( "delivery_method", models.CharField( choices=[ ("IN_PERSON", "In Person"), ("VIRTUAL", "Virtual"), ("HYBRID", "Hybrid"), ("SELF_PACED", "Self Paced"), ], default="IN_PERSON", max_length=12, ), ), ("start_at", models.DateTimeField()), ("end_at", models.DateTimeField()), ("location", models.CharField(blank=True, max_length=200, null=True)), ("capacity", models.PositiveIntegerField(default=0)), ( "cost_override", models.DecimalField( blank=True, decimal_places=2, max_digits=10, null=True ), ), ( "hours_override", models.DecimalField( blank=True, decimal_places=2, max_digits=5, null=True ), ), ("created_at", models.DateTimeField(auto_now_add=True)), ( "created_by", models.ForeignKey( blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="created_training_sessions", to="hr.employee", ), ), ( "instructor", models.ForeignKey( blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name="instructed_sessions", to="hr.employee", ), ), ( "program", models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, related_name="sessions", to="hr.trainingprograms", ), ), ], options={ "verbose_name": "Training Session", "verbose_name_plural": "Training Sessions", "db_table": "hr_training_session", "ordering": ["-start_at"], }, ), migrations.AddField( model_name="trainingrecord", name="session", field=models.ForeignKey( on_delete=django.db.models.deletion.PROTECT, related_name="enrollments", to="hr.trainingsession", ), ), migrations.AddIndex( model_name="employee", index=models.Index( fields=["tenant", "employee_id"], name="hr_employee_tenant__d723cf_idx" ), ), migrations.AddIndex( model_name="employee", index=models.Index( fields=["tenant", "role"], name="hr_employee_tenant__1c6def_idx" ), ), migrations.AddIndex( model_name="employee", index=models.Index( fields=["tenant", "department"], name="hr_employee_tenant__1baa3c_idx" ), ), migrations.AddIndex( model_name="employee", index=models.Index( fields=["tenant", "employment_status"], name="hr_employee_tenant__54b199_idx", ), ), migrations.AddIndex( model_name="department", index=models.Index( fields=["tenant", "department_type"], name="hr_departme_tenant__87fa85_idx", ), ), migrations.AddIndex( model_name="department", index=models.Index(fields=["code"], name="hr_departme_code_d27daf_idx"), ), migrations.AddIndex( model_name="department", index=models.Index(fields=["name"], name="hr_departme_name_00be75_idx"), ), migrations.AddIndex( model_name="department", index=models.Index( fields=["is_active"], name="hr_departme_is_acti_b443d7_idx" ), ), migrations.AlterUniqueTogether( name="department", unique_together={("tenant", "code")}, ), migrations.AddIndex( model_name="performancereview", index=models.Index( fields=["employee", "review_date"], name="hr_performa_employe_604c29_idx", ), ), migrations.AddIndex( model_name="performancereview", index=models.Index( fields=["review_type"], name="hr_performa_review__a7c664_idx" ), ), migrations.AddIndex( model_name="performancereview", index=models.Index(fields=["status"], name="hr_performa_status_460939_idx"), ), migrations.AddIndex( model_name="performancereview", index=models.Index( fields=["overall_rating"], name="hr_performa_overall_0257f6_idx" ), ), migrations.AddIndex( model_name="schedule", index=models.Index( fields=["employee", "effective_date"], name="hr_schedule_employe_2bbf02_idx", ), ), migrations.AddIndex( model_name="schedule", index=models.Index( fields=["schedule_type"], name="hr_schedule_schedul_19e2a5_idx" ), ), migrations.AddIndex( model_name="schedule", index=models.Index( fields=["is_active"], name="hr_schedule_is_acti_2e906a_idx" ), ), migrations.AddIndex( model_name="scheduleassignment", index=models.Index( fields=["schedule", "assignment_date"], name="hr_schedule_schedul_85a37e_idx", ), ), migrations.AddIndex( model_name="scheduleassignment", index=models.Index( fields=["assignment_date"], name="hr_schedule_assignm_cf8fba_idx" ), ), migrations.AddIndex( model_name="scheduleassignment", index=models.Index(fields=["status"], name="hr_schedule_status_a9da0d_idx"), ), migrations.AddIndex( model_name="timeentry", index=models.Index( fields=["employee", "work_date"], name="hr_time_ent_employe_9f8566_idx" ), ), migrations.AddIndex( model_name="timeentry", index=models.Index( fields=["work_date"], name="hr_time_ent_work_da_898420_idx" ), ), migrations.AddIndex( model_name="timeentry", index=models.Index(fields=["status"], name="hr_time_ent_status_c67efb_idx"), ), migrations.AddIndex( model_name="timeentry", index=models.Index( fields=["entry_type"], name="hr_time_ent_entry_t_eba769_idx" ), ), migrations.AddIndex( model_name="trainingprograms", index=models.Index( fields=["tenant", "program_type"], name="hr_training_tenant__d8062d_idx" ), ), migrations.AddIndex( model_name="trainingprograms", index=models.Index( fields=["tenant", "is_certified"], name="hr_training_tenant__4892af_idx" ), ), migrations.AlterUniqueTogether( name="trainingprograms", unique_together={("tenant", "name")}, ), migrations.AlterUniqueTogether( name="programprerequisite", unique_together={("program", "required_program")}, ), migrations.AddIndex( model_name="programmodule", index=models.Index( fields=["program", "order"], name="hr_training_program_f99b01_idx" ), ), migrations.AlterUniqueTogether( name="programmodule", unique_together={("program", "order")}, ), migrations.AddIndex( model_name="trainingcertificates", index=models.Index( fields=["certificate_number"], name="hr_training_certifi_928fdb_idx" ), ), migrations.AlterUniqueTogether( name="trainingcertificates", unique_together={("employee", "program", "enrollment")}, ), migrations.AddIndex( model_name="trainingattendance", index=models.Index( fields=["enrollment"], name="hr_training_enrollm_104874_idx" ), ), migrations.AddIndex( model_name="trainingassessment", index=models.Index( fields=["enrollment"], name="hr_training_enrollm_71763a_idx" ), ), migrations.AlterUniqueTogether( name="trainingrecord", unique_together={("employee", "session")}, ), ]