1195 lines
46 KiB
Python
1195 lines
46 KiB
Python
# 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="AssetCategory",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("name", models.CharField(max_length=100, unique=True)),
|
|
("code", models.CharField(max_length=20, unique=True)),
|
|
("description", models.TextField(blank=True)),
|
|
("is_active", models.BooleanField(default=True)),
|
|
(
|
|
"parent_category",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to="facility_management.assetcategory",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"verbose_name_plural": "Asset Categories",
|
|
"db_table": "facility_management_asset_categories",
|
|
"ordering": ["name"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="Building",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("name", models.CharField(max_length=100)),
|
|
(
|
|
"building_id",
|
|
models.UUIDField(default=uuid.uuid4, editable=False, unique=True),
|
|
),
|
|
("code", models.CharField(max_length=10, unique=True)),
|
|
(
|
|
"building_type",
|
|
models.CharField(
|
|
choices=[
|
|
("CLINICAL", "Clinical"),
|
|
("NON_CLINICAL", "Non Clinical"),
|
|
("OTHER", "Other"),
|
|
],
|
|
default="CLINICAL",
|
|
max_length=20,
|
|
),
|
|
),
|
|
("address", models.TextField()),
|
|
(
|
|
"latitude",
|
|
models.DecimalField(
|
|
blank=True, decimal_places=6, max_digits=9, null=True
|
|
),
|
|
),
|
|
(
|
|
"longitude",
|
|
models.DecimalField(
|
|
blank=True, decimal_places=6, max_digits=9, null=True
|
|
),
|
|
),
|
|
("floor_count", models.PositiveIntegerField(default=1)),
|
|
(
|
|
"total_area_sqm",
|
|
models.DecimalField(
|
|
blank=True, decimal_places=2, max_digits=10, null=True
|
|
),
|
|
),
|
|
(
|
|
"construction_year",
|
|
models.PositiveIntegerField(blank=True, null=True),
|
|
),
|
|
("architect", models.CharField(blank=True, max_length=100)),
|
|
("contractor", models.CharField(blank=True, max_length=100)),
|
|
("is_active", models.BooleanField(default=True)),
|
|
("last_major_renovation", models.DateField(blank=True, null=True)),
|
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
|
("updated_at", models.DateTimeField(auto_now=True)),
|
|
(
|
|
"facility_manager",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.SET_NULL,
|
|
to=settings.AUTH_USER_MODEL,
|
|
),
|
|
),
|
|
(
|
|
"tenant",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="buildings",
|
|
to="core.tenant",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"verbose_name_plural": "Buildings",
|
|
"db_table": "facility_management_buildings",
|
|
"ordering": ["code", "name"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="EnergyMeter",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("meter_id", models.CharField(max_length=50, unique=True)),
|
|
(
|
|
"meter_type",
|
|
models.CharField(
|
|
choices=[
|
|
("ELECTRICITY", "Electricity"),
|
|
("GAS", "Natural Gas"),
|
|
("WATER", "Water"),
|
|
("STEAM", "Steam"),
|
|
("CHILLED_WATER", "Chilled Water"),
|
|
("OTHER", "Other"),
|
|
],
|
|
help_text="Meter type",
|
|
max_length=20,
|
|
),
|
|
),
|
|
("location_description", models.CharField(max_length=200)),
|
|
("manufacturer", models.CharField(blank=True, max_length=100)),
|
|
("model", models.CharField(blank=True, max_length=100)),
|
|
("serial_number", models.CharField(blank=True, max_length=100)),
|
|
("installation_date", models.DateField(blank=True, null=True)),
|
|
(
|
|
"current_reading",
|
|
models.DecimalField(
|
|
decimal_places=2, default=Decimal("0.00"), max_digits=12
|
|
),
|
|
),
|
|
("last_reading_date", models.DateTimeField(blank=True, null=True)),
|
|
("is_active", models.BooleanField(default=True)),
|
|
("calibration_date", models.DateField(blank=True, null=True)),
|
|
("next_calibration_date", models.DateField(blank=True, null=True)),
|
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
|
("updated_at", models.DateTimeField(auto_now=True)),
|
|
(
|
|
"building",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to="facility_management.building",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"verbose_name_plural": "Energy Meters",
|
|
"db_table": "facility_management_energy_meters",
|
|
"ordering": ["building", "meter_type", "meter_id"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="EnergyReading",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("reading_date", models.DateTimeField()),
|
|
("reading_value", models.DecimalField(decimal_places=2, max_digits=12)),
|
|
(
|
|
"consumption",
|
|
models.DecimalField(
|
|
blank=True, decimal_places=2, max_digits=12, null=True
|
|
),
|
|
),
|
|
(
|
|
"cost",
|
|
models.DecimalField(
|
|
blank=True, decimal_places=2, max_digits=10, null=True
|
|
),
|
|
),
|
|
("is_estimated", models.BooleanField(default=False)),
|
|
("notes", models.TextField(blank=True)),
|
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
|
(
|
|
"meter",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="readings",
|
|
to="facility_management.energymeter",
|
|
),
|
|
),
|
|
(
|
|
"read_by",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to=settings.AUTH_USER_MODEL,
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"ordering": ["-reading_date"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="Floor",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
(
|
|
"floor_number",
|
|
models.IntegerField(
|
|
help_text="Use negative numbers for basement levels"
|
|
),
|
|
),
|
|
(
|
|
"name",
|
|
models.CharField(
|
|
help_text="e.g., Ground Floor, Mezzanine, B1", max_length=50
|
|
),
|
|
),
|
|
(
|
|
"area_sqm",
|
|
models.DecimalField(
|
|
blank=True, decimal_places=2, max_digits=10, null=True
|
|
),
|
|
),
|
|
(
|
|
"ceiling_height_m",
|
|
models.DecimalField(
|
|
blank=True, decimal_places=2, max_digits=5, null=True
|
|
),
|
|
),
|
|
("is_public_access", models.BooleanField(default=False)),
|
|
(
|
|
"building",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="floors",
|
|
to="facility_management.building",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"db_table": "facility_management_floors",
|
|
"ordering": ["building", "floor_number"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="Asset",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
(
|
|
"asset_id",
|
|
models.UUIDField(default=uuid.uuid4, editable=False, unique=True),
|
|
),
|
|
("name", models.CharField(max_length=200)),
|
|
("location_description", models.CharField(blank=True, max_length=200)),
|
|
("manufacturer", models.CharField(blank=True, max_length=100)),
|
|
("model", models.CharField(blank=True, max_length=100)),
|
|
("serial_number", models.CharField(blank=True, max_length=100)),
|
|
("purchase_date", models.DateField(blank=True, null=True)),
|
|
(
|
|
"purchase_cost",
|
|
models.DecimalField(
|
|
blank=True, decimal_places=2, max_digits=12, null=True
|
|
),
|
|
),
|
|
(
|
|
"current_value",
|
|
models.DecimalField(
|
|
blank=True, decimal_places=2, max_digits=12, null=True
|
|
),
|
|
),
|
|
(
|
|
"depreciation_rate",
|
|
models.DecimalField(
|
|
decimal_places=2,
|
|
default=Decimal("10.00"),
|
|
help_text="Annual depreciation percentage",
|
|
max_digits=5,
|
|
),
|
|
),
|
|
("warranty_start_date", models.DateField(blank=True, null=True)),
|
|
("warranty_end_date", models.DateField(blank=True, null=True)),
|
|
("service_provider", models.CharField(blank=True, max_length=100)),
|
|
(
|
|
"service_contract_number",
|
|
models.CharField(blank=True, max_length=50),
|
|
),
|
|
(
|
|
"status",
|
|
models.CharField(
|
|
choices=[
|
|
("OPERATIONAL", "Operational"),
|
|
("MAINTENANCE", "Under Maintenance"),
|
|
("REPAIR", "Needs Repair"),
|
|
("RETIRED", "Retired"),
|
|
("DISPOSED", "Disposed"),
|
|
],
|
|
default="OPERATIONAL",
|
|
max_length=20,
|
|
),
|
|
),
|
|
(
|
|
"condition",
|
|
models.CharField(
|
|
choices=[
|
|
("EXCELLENT", "Excellent"),
|
|
("GOOD", "Good"),
|
|
("FAIR", "Fair"),
|
|
("POOR", "Poor"),
|
|
("CRITICAL", "Critical"),
|
|
],
|
|
default="GOOD",
|
|
help_text="Current condition of the asset",
|
|
max_length=20,
|
|
),
|
|
),
|
|
("last_inspection_date", models.DateField(blank=True, null=True)),
|
|
("next_maintenance_date", models.DateField(blank=True, null=True)),
|
|
("notes", models.TextField(blank=True)),
|
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
|
("updated_at", models.DateTimeField(auto_now=True)),
|
|
(
|
|
"assigned_to",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.SET_NULL,
|
|
to=settings.AUTH_USER_MODEL,
|
|
),
|
|
),
|
|
(
|
|
"category",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to="facility_management.assetcategory",
|
|
),
|
|
),
|
|
(
|
|
"building",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to="facility_management.building",
|
|
),
|
|
),
|
|
(
|
|
"floor",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to="facility_management.floor",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"verbose_name_plural": "Assets",
|
|
"db_table": "facility_management_assets",
|
|
"ordering": ["asset_id"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="MaintenanceType",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("name", models.CharField(max_length=100, unique=True)),
|
|
("code", models.CharField(max_length=20, unique=True)),
|
|
("description", models.TextField(blank=True)),
|
|
(
|
|
"estimated_duration_hours",
|
|
models.DecimalField(
|
|
blank=True, decimal_places=2, max_digits=5, null=True
|
|
),
|
|
),
|
|
("is_active", models.BooleanField(default=True)),
|
|
],
|
|
options={
|
|
"verbose_name_plural": "Maintenance Types",
|
|
"db_table": "facility_management_maintenance_types",
|
|
"ordering": ["name"],
|
|
"indexes": [
|
|
models.Index(fields=["code"], name="facility_ma_code_54340b_idx")
|
|
],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="Room",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("room_number", models.CharField(max_length=20)),
|
|
("name", models.CharField(blank=True, max_length=100)),
|
|
(
|
|
"area_sqm",
|
|
models.DecimalField(
|
|
blank=True, decimal_places=2, max_digits=8, null=True
|
|
),
|
|
),
|
|
(
|
|
"capacity",
|
|
models.PositiveIntegerField(
|
|
blank=True, help_text="Maximum occupancy", null=True
|
|
),
|
|
),
|
|
(
|
|
"occupancy_status",
|
|
models.CharField(
|
|
choices=[
|
|
("VACANT", "Vacant"),
|
|
("OCCUPIED", "Occupied"),
|
|
("MAINTENANCE", "Under Maintenance"),
|
|
("RESERVED", "Reserved"),
|
|
],
|
|
default="VACANT",
|
|
max_length=20,
|
|
),
|
|
),
|
|
(
|
|
"is_accessible",
|
|
models.BooleanField(
|
|
default=True, help_text="ADA/accessibility compliant"
|
|
),
|
|
),
|
|
("notes", models.TextField(blank=True)),
|
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
|
("updated_at", models.DateTimeField(auto_now=True)),
|
|
(
|
|
"floor",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="rooms",
|
|
to="facility_management.floor",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"db_table": "facility_management_rooms",
|
|
"ordering": ["floor", "room_number"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="MaintenanceSchedule",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("name", models.CharField(max_length=200)),
|
|
("description", models.TextField()),
|
|
(
|
|
"frequency_interval",
|
|
models.IntegerField(
|
|
choices=[
|
|
(1, "Daily"),
|
|
(7, "Weekly"),
|
|
(30, "Monthly"),
|
|
(90, "Quarterly"),
|
|
(182, "Semi-Annual"),
|
|
(365, "Annual"),
|
|
],
|
|
default=365,
|
|
),
|
|
),
|
|
("start_date", models.DateField()),
|
|
("end_date", models.DateField(blank=True, null=True)),
|
|
(
|
|
"estimated_duration_hours",
|
|
models.DecimalField(
|
|
blank=True, decimal_places=2, max_digits=5, null=True
|
|
),
|
|
),
|
|
("is_active", models.BooleanField(default=True)),
|
|
("last_generated_date", models.DateField(blank=True, null=True)),
|
|
("next_due_date", models.DateField(blank=True, null=True)),
|
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
|
(
|
|
"asset",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to="facility_management.asset",
|
|
),
|
|
),
|
|
(
|
|
"assigned_to",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.SET_NULL,
|
|
to=settings.AUTH_USER_MODEL,
|
|
),
|
|
),
|
|
(
|
|
"building",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to="facility_management.building",
|
|
),
|
|
),
|
|
(
|
|
"maintenance_type",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to="facility_management.maintenancetype",
|
|
),
|
|
),
|
|
(
|
|
"room",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to="facility_management.room",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"db_table": "facility_management_maintenance_schedules",
|
|
"ordering": ["next_due_date"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="MaintenanceRequest",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
(
|
|
"request_id",
|
|
models.CharField(editable=False, max_length=50, unique=True),
|
|
),
|
|
("title", models.CharField(max_length=200)),
|
|
("description", models.TextField()),
|
|
(
|
|
"priority",
|
|
models.CharField(
|
|
choices=[
|
|
("LOW", "Low"),
|
|
("MEDIUM", "Medium"),
|
|
("HIGH", "High"),
|
|
("URGENT", "Urgent"),
|
|
("EMERGENCY", "Emergency"),
|
|
],
|
|
default="MEDIUM",
|
|
max_length=20,
|
|
),
|
|
),
|
|
(
|
|
"status",
|
|
models.CharField(
|
|
choices=[
|
|
("SUBMITTED", "Submitted"),
|
|
("ASSIGNED", "Assigned"),
|
|
("IN_PROGRESS", "In Progress"),
|
|
("COMPLETED", "Completed"),
|
|
("CANCELLED", "Cancelled"),
|
|
("ON_HOLD", "On Hold"),
|
|
],
|
|
default="SUBMITTED",
|
|
help_text="Current status of the request",
|
|
max_length=20,
|
|
),
|
|
),
|
|
("requested_date", models.DateTimeField(auto_now_add=True)),
|
|
("scheduled_date", models.DateTimeField(blank=True, null=True)),
|
|
("started_date", models.DateTimeField(blank=True, null=True)),
|
|
("completed_date", models.DateTimeField(blank=True, null=True)),
|
|
(
|
|
"estimated_hours",
|
|
models.DecimalField(
|
|
blank=True, decimal_places=2, max_digits=5, null=True
|
|
),
|
|
),
|
|
(
|
|
"estimated_cost",
|
|
models.DecimalField(
|
|
blank=True, decimal_places=2, max_digits=10, null=True
|
|
),
|
|
),
|
|
(
|
|
"actual_cost",
|
|
models.DecimalField(
|
|
blank=True, decimal_places=2, max_digits=10, null=True
|
|
),
|
|
),
|
|
("notes", models.TextField(blank=True)),
|
|
("completion_notes", models.TextField(blank=True)),
|
|
(
|
|
"asset",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to="facility_management.asset",
|
|
),
|
|
),
|
|
(
|
|
"assigned_to",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.SET_NULL,
|
|
related_name="assigned_maintenance",
|
|
to=settings.AUTH_USER_MODEL,
|
|
),
|
|
),
|
|
(
|
|
"building",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to="facility_management.building",
|
|
),
|
|
),
|
|
(
|
|
"floor",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to="facility_management.floor",
|
|
),
|
|
),
|
|
(
|
|
"requested_by",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="maintenance_requests",
|
|
to=settings.AUTH_USER_MODEL,
|
|
),
|
|
),
|
|
(
|
|
"maintenance_type",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to="facility_management.maintenancetype",
|
|
),
|
|
),
|
|
(
|
|
"room",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to="facility_management.room",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"verbose_name_plural": "Maintenance Requests",
|
|
"db_table": "facility_management_maintenance_requests",
|
|
"ordering": ["-requested_date"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="Inspection",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("inspection_id", models.CharField(max_length=50, unique=True)),
|
|
(
|
|
"inspection_type",
|
|
models.CharField(
|
|
choices=[
|
|
("SAFETY", "Safety Inspection"),
|
|
("FIRE", "Fire Safety"),
|
|
("HEALTH", "Health Inspection"),
|
|
("SECURITY", "Security Audit"),
|
|
("ENVIRONMENTAL", "Environmental"),
|
|
("STRUCTURAL", "Structural"),
|
|
("ELECTRICAL", "Electrical"),
|
|
("HVAC", "HVAC"),
|
|
("OTHER", "Other"),
|
|
],
|
|
help_text="Type of inspection",
|
|
max_length=20,
|
|
),
|
|
),
|
|
("title", models.CharField(max_length=200)),
|
|
("description", models.TextField(blank=True)),
|
|
("scheduled_date", models.DateTimeField()),
|
|
(
|
|
"estimated_duration_hours",
|
|
models.DecimalField(
|
|
blank=True, decimal_places=2, max_digits=5, null=True
|
|
),
|
|
),
|
|
(
|
|
"inspector_external",
|
|
models.CharField(
|
|
blank=True, help_text="External inspector name", max_length=100
|
|
),
|
|
),
|
|
(
|
|
"inspector_organization",
|
|
models.CharField(blank=True, max_length=100),
|
|
),
|
|
(
|
|
"status",
|
|
models.CharField(
|
|
choices=[
|
|
("SCHEDULED", "Scheduled"),
|
|
("IN_PROGRESS", "In Progress"),
|
|
("COMPLETED", "Completed"),
|
|
("CANCELLED", "Cancelled"),
|
|
],
|
|
default="SCHEDULED",
|
|
help_text="Current status of the inspection",
|
|
max_length=20,
|
|
),
|
|
),
|
|
("started_date", models.DateTimeField(blank=True, null=True)),
|
|
("completed_date", models.DateTimeField(blank=True, null=True)),
|
|
(
|
|
"overall_rating",
|
|
models.CharField(
|
|
blank=True, help_text="Pass/Fail/Conditional", max_length=20
|
|
),
|
|
),
|
|
("findings", models.TextField(blank=True)),
|
|
("recommendations", models.TextField(blank=True)),
|
|
("requires_followup", models.BooleanField(default=False)),
|
|
("followup_date", models.DateField(blank=True, null=True)),
|
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
|
("updated_at", models.DateTimeField(auto_now=True)),
|
|
(
|
|
"assets",
|
|
models.ManyToManyField(blank=True, to="facility_management.asset"),
|
|
),
|
|
(
|
|
"building",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to="facility_management.building",
|
|
),
|
|
),
|
|
(
|
|
"floors",
|
|
models.ManyToManyField(blank=True, to="facility_management.floor"),
|
|
),
|
|
(
|
|
"inspector",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
related_name="inspections_conducted",
|
|
to=settings.AUTH_USER_MODEL,
|
|
),
|
|
),
|
|
(
|
|
"rooms",
|
|
models.ManyToManyField(blank=True, to="facility_management.room"),
|
|
),
|
|
],
|
|
options={
|
|
"verbose_name_plural": "Inspections",
|
|
"db_table": "facility_management_inspections",
|
|
"ordering": ["-scheduled_date"],
|
|
},
|
|
),
|
|
migrations.AddField(
|
|
model_name="asset",
|
|
name="room",
|
|
field=models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to="facility_management.room",
|
|
),
|
|
),
|
|
migrations.CreateModel(
|
|
name="SpaceReservation",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("reservation_id", models.CharField(max_length=50, unique=True)),
|
|
("title", models.CharField(max_length=200)),
|
|
("description", models.TextField(blank=True)),
|
|
("start_datetime", models.DateTimeField()),
|
|
("end_datetime", models.DateTimeField()),
|
|
("contact_person", models.CharField(blank=True, max_length=100)),
|
|
("contact_email", models.EmailField(blank=True, max_length=254)),
|
|
("contact_phone", models.CharField(blank=True, max_length=20)),
|
|
(
|
|
"expected_attendees",
|
|
models.PositiveIntegerField(blank=True, null=True),
|
|
),
|
|
("setup_requirements", models.TextField(blank=True)),
|
|
("catering_required", models.BooleanField(default=False)),
|
|
(
|
|
"av_equipment_required",
|
|
models.BooleanField(
|
|
default=False,
|
|
help_text="Whether audio/visual equipment (projector, microphone, etc.) is needed",
|
|
),
|
|
),
|
|
(
|
|
"status",
|
|
models.CharField(
|
|
choices=[
|
|
("PENDING", "Pending"),
|
|
("CONFIRMED", "Confirmed"),
|
|
("CANCELLED", "Cancelled"),
|
|
("COMPLETED", "Completed"),
|
|
("NO_SHOW", "No Show"),
|
|
],
|
|
default="PENDING",
|
|
max_length=20,
|
|
),
|
|
),
|
|
("approved_at", models.DateTimeField(blank=True, null=True)),
|
|
(
|
|
"hourly_rate",
|
|
models.DecimalField(
|
|
blank=True, decimal_places=2, max_digits=8, null=True
|
|
),
|
|
),
|
|
(
|
|
"total_cost",
|
|
models.DecimalField(
|
|
blank=True, decimal_places=2, max_digits=10, null=True
|
|
),
|
|
),
|
|
("notes", models.TextField(blank=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_reservations",
|
|
to=settings.AUTH_USER_MODEL,
|
|
),
|
|
),
|
|
(
|
|
"reserved_by",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to=settings.AUTH_USER_MODEL,
|
|
),
|
|
),
|
|
(
|
|
"room",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to="facility_management.room",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"verbose_name_plural": "Space Reservations",
|
|
"db_table": "facility_management_space_reservations",
|
|
"ordering": ["-start_datetime"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="Vendor",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("name", models.CharField(max_length=200)),
|
|
(
|
|
"vendor_type",
|
|
models.CharField(
|
|
choices=[
|
|
("MAINTENANCE", "Maintenance Contractor"),
|
|
("CLEANING", "Cleaning Service"),
|
|
("SECURITY", "Security Service"),
|
|
("LANDSCAPING", "Landscaping"),
|
|
("HVAC", "HVAC Service"),
|
|
("ELECTRICAL", "Electrical Service"),
|
|
("PLUMBING", "Plumbing Service"),
|
|
("IT", "IT Service"),
|
|
("OTHER", "Other"),
|
|
],
|
|
max_length=20,
|
|
),
|
|
),
|
|
("contact_person", models.CharField(max_length=100)),
|
|
("email", models.EmailField(max_length=254)),
|
|
("phone", models.CharField(max_length=20)),
|
|
("address", models.TextField()),
|
|
(
|
|
"crn",
|
|
models.CharField(
|
|
blank=True,
|
|
max_length=10,
|
|
null=True,
|
|
verbose_name="Commercial Registration Number",
|
|
),
|
|
),
|
|
(
|
|
"vrn",
|
|
models.CharField(
|
|
blank=True,
|
|
max_length=15,
|
|
null=True,
|
|
verbose_name="VAT Registration Number",
|
|
),
|
|
),
|
|
(
|
|
"rating",
|
|
models.DecimalField(
|
|
blank=True,
|
|
decimal_places=2,
|
|
max_digits=3,
|
|
null=True,
|
|
validators=[
|
|
django.core.validators.MinValueValidator(Decimal("0.00")),
|
|
django.core.validators.MaxValueValidator(Decimal("5.00")),
|
|
],
|
|
),
|
|
),
|
|
("total_contracts", models.PositiveIntegerField(default=0)),
|
|
("is_active", models.BooleanField(default=True)),
|
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
|
("updated_at", models.DateTimeField(auto_now=True)),
|
|
(
|
|
"tenant",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE, to="core.tenant"
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"verbose_name_plural": "Vendors",
|
|
"db_table": "facility_management_vendors",
|
|
"ordering": ["name"],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name="ServiceContract",
|
|
fields=[
|
|
(
|
|
"id",
|
|
models.BigAutoField(
|
|
auto_created=True,
|
|
primary_key=True,
|
|
serialize=False,
|
|
verbose_name="ID",
|
|
),
|
|
),
|
|
("contract_number", models.CharField(max_length=50, unique=True)),
|
|
("title", models.CharField(max_length=200)),
|
|
("description", models.TextField()),
|
|
("start_date", models.DateField()),
|
|
("end_date", models.DateField()),
|
|
(
|
|
"contract_value",
|
|
models.DecimalField(decimal_places=2, max_digits=12),
|
|
),
|
|
(
|
|
"payment_terms",
|
|
models.CharField(help_text="e.g., Net 30 days", max_length=100),
|
|
),
|
|
(
|
|
"service_areas",
|
|
models.TextField(help_text="Description of service areas"),
|
|
),
|
|
(
|
|
"status",
|
|
models.CharField(
|
|
choices=[
|
|
("DRAFT", "Draft"),
|
|
("ACTIVE", "Active"),
|
|
("EXPIRED", "Expired"),
|
|
("TERMINATED", "Terminated"),
|
|
],
|
|
default="DRAFT",
|
|
max_length=20,
|
|
),
|
|
),
|
|
("auto_renewal", models.BooleanField(default=False)),
|
|
("renewal_notice_days", models.PositiveIntegerField(default=30)),
|
|
("notes", models.TextField(blank=True)),
|
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
|
("updated_at", models.DateTimeField(auto_now=True)),
|
|
(
|
|
"buildings",
|
|
models.ManyToManyField(
|
|
blank=True, to="facility_management.building"
|
|
),
|
|
),
|
|
(
|
|
"contract_manager",
|
|
models.ForeignKey(
|
|
blank=True,
|
|
null=True,
|
|
on_delete=django.db.models.deletion.SET_NULL,
|
|
to=settings.AUTH_USER_MODEL,
|
|
),
|
|
),
|
|
(
|
|
"vendor",
|
|
models.ForeignKey(
|
|
on_delete=django.db.models.deletion.CASCADE,
|
|
to="facility_management.vendor",
|
|
),
|
|
),
|
|
],
|
|
options={
|
|
"verbose_name_plural": "Service Contracts",
|
|
"db_table": "facility_management_service_contracts",
|
|
"ordering": ["-start_date"],
|
|
},
|
|
),
|
|
migrations.AddIndex(
|
|
model_name="assetcategory",
|
|
index=models.Index(fields=["code"], name="facility_ma_code_466577_idx"),
|
|
),
|
|
migrations.AddIndex(
|
|
model_name="building",
|
|
index=models.Index(
|
|
fields=["code", "name"], name="facility_ma_code_61bb9d_idx"
|
|
),
|
|
),
|
|
migrations.AlterUniqueTogether(
|
|
name="building",
|
|
unique_together={("code", "name")},
|
|
),
|
|
migrations.AlterUniqueTogether(
|
|
name="energyreading",
|
|
unique_together={("meter", "reading_date")},
|
|
),
|
|
migrations.AddIndex(
|
|
model_name="floor",
|
|
index=models.Index(
|
|
fields=["building", "floor_number"],
|
|
name="facility_ma_buildin_884b34_idx",
|
|
),
|
|
),
|
|
migrations.AlterUniqueTogether(
|
|
name="floor",
|
|
unique_together={("building", "floor_number")},
|
|
),
|
|
migrations.AddIndex(
|
|
model_name="room",
|
|
index=models.Index(
|
|
fields=["floor", "room_number"], name="facility_ma_floor_i_1f4028_idx"
|
|
),
|
|
),
|
|
migrations.AlterUniqueTogether(
|
|
name="room",
|
|
unique_together={("floor", "room_number")},
|
|
),
|
|
migrations.AddIndex(
|
|
model_name="maintenanceschedule",
|
|
index=models.Index(
|
|
fields=["asset", "building", "room"],
|
|
name="facility_ma_asset_i_fe5ae7_idx",
|
|
),
|
|
),
|
|
migrations.AlterUniqueTogether(
|
|
name="maintenanceschedule",
|
|
unique_together={("asset", "building", "room")},
|
|
),
|
|
migrations.AddIndex(
|
|
model_name="maintenancerequest",
|
|
index=models.Index(
|
|
fields=["building", "floor", "room", "asset"],
|
|
name="facility_ma_buildin_06372a_idx",
|
|
),
|
|
),
|
|
migrations.AddIndex(
|
|
model_name="asset",
|
|
index=models.Index(
|
|
fields=["building", "floor", "room", "serial_number"],
|
|
name="facility_ma_buildin_2c82c7_idx",
|
|
),
|
|
),
|
|
migrations.AlterUniqueTogether(
|
|
name="asset",
|
|
unique_together={("building", "floor", "room", "serial_number")},
|
|
),
|
|
migrations.AddIndex(
|
|
model_name="vendor",
|
|
index=models.Index(
|
|
fields=["tenant", "name"], name="facility_ma_tenant__cc4314_idx"
|
|
),
|
|
),
|
|
migrations.AddIndex(
|
|
model_name="servicecontract",
|
|
index=models.Index(
|
|
fields=["vendor"], name="facility_ma_vendor__870e50_idx"
|
|
),
|
|
),
|
|
]
|