# Generated by Django 5.2.8 on 2025-12-06 15:03

import apps.ocpp.models.charger_log_request
import apps.ocpp.models.cp_forwarder
import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
        ("cards", "0002_initial"),
        ("groups", "0001_initial"),
        ("locale", "0001_initial"),
        ("maps", "0001_initial"),
        ("media", "0001_initial"),
        ("nodes", "0001_initial"),
    ]

    operations = [
        migrations.CreateModel(
            name="ChargerConfiguration",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                (
                    "charger_identifier",
                    models.CharField(max_length=100, verbose_name="Serial Number"),
                ),
                (
                    "connector_id",
                    models.PositiveIntegerField(
                        blank=True,
                        help_text="Connector that returned this configuration (if specified).",
                        null=True,
                        verbose_name="Connector ID",
                    ),
                ),
                (
                    "unknown_keys",
                    models.JSONField(
                        blank=True,
                        default=list,
                        help_text="Keys returned in the unknownKey list.",
                    ),
                ),
                (
                    "evcs_snapshot_at",
                    models.DateTimeField(
                        blank=True,
                        help_text="Timestamp when this configuration was received from the charge point.",
                        null=True,
                        verbose_name="EVCS snapshot at",
                    ),
                ),
                (
                    "raw_payload",
                    models.JSONField(
                        blank=True,
                        default=dict,
                        help_text="Raw payload returned by the GetConfiguration call.",
                    ),
                ),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
            ],
            options={
                "verbose_name": "CP Configuration",
                "verbose_name_plural": "CP Configurations",
                "ordering": ["-created_at"],
            },
        ),
        migrations.CreateModel(
            name="ChargerLogRequest",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                (
                    "request_id",
                    models.BigIntegerField(
                        default=apps.ocpp.models.charger_log_request.generate_log_request_id,
                        unique=True,
                        verbose_name="Request Id",
                    ),
                ),
                ("message_id", models.CharField(blank=True, default="", max_length=64)),
                ("log_type", models.CharField(blank=True, default="", max_length=64)),
                ("status", models.CharField(blank=True, default="", max_length=32)),
                ("filename", models.CharField(blank=True, default="", max_length=255)),
                ("location", models.CharField(blank=True, default="", max_length=500)),
                (
                    "session_key",
                    models.CharField(blank=True, default="", max_length=200),
                ),
                ("requested_at", models.DateTimeField(auto_now_add=True)),
                ("responded_at", models.DateTimeField(blank=True, null=True)),
                ("last_status_at", models.DateTimeField(blank=True, null=True)),
                ("last_status_payload", models.JSONField(blank=True, default=dict)),
                ("raw_response", models.JSONField(blank=True, default=dict)),
            ],
            options={
                "verbose_name": "Log Request",
                "verbose_name_plural": "Log Requests",
                "ordering": ["-requested_at", "-pk"],
            },
        ),
        migrations.CreateModel(
            name="ChargingProfile",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                (
                    "connector_id",
                    models.PositiveIntegerField(
                        default=0,
                        help_text="Connector targeted by this profile (0 sends the profile to the EVCS).",
                        verbose_name="Connector ID",
                    ),
                ),
                (
                    "charging_profile_id",
                    models.PositiveIntegerField(
                        help_text="Identifier sent as chargingProfileId in OCPP payloads.",
                        verbose_name="Charging Profile ID",
                    ),
                ),
                (
                    "stack_level",
                    models.PositiveIntegerField(
                        default=0,
                        help_text="Priority applied when multiple profiles overlap.",
                        verbose_name="Stack Level",
                    ),
                ),
                (
                    "purpose",
                    models.CharField(
                        choices=[
                            ("ChargePointMaxProfile", "Charge Point Max Profile"),
                            ("TxDefaultProfile", "Transaction Default Profile"),
                            ("TxProfile", "Transaction Profile"),
                        ],
                        max_length=32,
                        verbose_name="Purpose",
                    ),
                ),
                (
                    "kind",
                    models.CharField(
                        choices=[
                            ("Absolute", "Absolute"),
                            ("Recurring", "Recurring"),
                            ("Relative", "Relative"),
                        ],
                        max_length=16,
                        verbose_name="Profile Kind",
                    ),
                ),
                (
                    "recurrency_kind",
                    models.CharField(
                        blank=True,
                        choices=[("Daily", "Daily"), ("Weekly", "Weekly")],
                        default="",
                        max_length=16,
                        verbose_name="Recurrency Kind",
                    ),
                ),
                (
                    "transaction_id",
                    models.PositiveIntegerField(
                        blank=True,
                        help_text="Required when Purpose is TxProfile.",
                        null=True,
                        verbose_name="Transaction ID",
                    ),
                ),
                ("valid_from", models.DateTimeField(blank=True, null=True)),
                ("valid_to", models.DateTimeField(blank=True, null=True)),
                (
                    "description",
                    models.CharField(blank=True, default="", max_length=255),
                ),
                (
                    "last_status",
                    models.CharField(blank=True, default="", max_length=32),
                ),
                (
                    "last_status_info",
                    models.CharField(blank=True, default="", max_length=255),
                ),
                ("last_response_payload", models.JSONField(blank=True, default=dict)),
                ("last_response_at", models.DateTimeField(blank=True, null=True)),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
            ],
            options={
                "verbose_name": "Charging Profile",
                "verbose_name_plural": "Charging Profiles",
                "ordering": [
                    "charger__charger_id",
                    "connector_id",
                    "-stack_level",
                    "charging_profile_id",
                ],
            },
        ),
        migrations.CreateModel(
            name="ChargingProfileDispatch",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                ("message_id", models.CharField(blank=True, default="", max_length=36)),
                ("status", models.CharField(blank=True, default="", max_length=32)),
                (
                    "status_info",
                    models.CharField(blank=True, default="", max_length=255),
                ),
                ("request_payload", models.JSONField(blank=True, default=dict)),
                ("response_payload", models.JSONField(blank=True, default=dict)),
                ("responded_at", models.DateTimeField(blank=True, null=True)),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
            ],
            options={
                "verbose_name": "Charging Profile Dispatch",
                "verbose_name_plural": "Charging Profile Dispatches",
                "ordering": ["-created_at"],
            },
        ),
        migrations.CreateModel(
            name="ChargingSchedule",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                (
                    "start_schedule",
                    models.DateTimeField(
                        blank=True,
                        help_text="Optional schedule start time; defaults to immediate execution.",
                        null=True,
                    ),
                ),
                (
                    "duration_seconds",
                    models.PositiveIntegerField(
                        blank=True, null=True, verbose_name="Duration (seconds)"
                    ),
                ),
                (
                    "charging_rate_unit",
                    models.CharField(
                        choices=[("A", "Amperes"), ("W", "Watts")],
                        max_length=2,
                        verbose_name="Charging Rate Unit",
                    ),
                ),
                (
                    "charging_schedule_periods",
                    models.JSONField(
                        blank=True,
                        default=list,
                        help_text="List of schedule periods including start_period, limit, number_phases, and phase_to_use values.",
                    ),
                ),
                (
                    "min_charging_rate",
                    models.DecimalField(
                        blank=True,
                        decimal_places=3,
                        max_digits=10,
                        null=True,
                        verbose_name="Minimum Charging Rate",
                    ),
                ),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
            ],
            options={
                "verbose_name": "Charging Schedule",
                "verbose_name_plural": "Charging Schedules",
                "ordering": ["profile_id"],
            },
        ),
        migrations.CreateModel(
            name="ConfigurationKey",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                ("position", models.PositiveIntegerField(default=0)),
                ("key", models.CharField(max_length=255)),
                ("readonly", models.BooleanField(default=False)),
                ("has_value", models.BooleanField(default=False)),
                ("value", models.JSONField(blank=True, null=True)),
                ("extra_data", models.JSONField(blank=True, default=dict)),
            ],
            options={
                "verbose_name": "Configuration Key",
                "verbose_name_plural": "Configuration Keys",
                "ordering": ["position", "id"],
            },
        ),
        migrations.CreateModel(
            name="CPFirmware",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                (
                    "name",
                    models.CharField(blank=True, max_length=200, verbose_name="Name"),
                ),
                (
                    "description",
                    models.TextField(blank=True, verbose_name="Description"),
                ),
                (
                    "source",
                    models.CharField(
                        choices=[("download", "Downloaded"), ("upload", "Uploaded")],
                        default="download",
                        max_length=16,
                        verbose_name="Source",
                    ),
                ),
                (
                    "content_type",
                    models.CharField(
                        blank=True,
                        default="application/octet-stream",
                        max_length=100,
                        verbose_name="Content type",
                    ),
                ),
                (
                    "filename",
                    models.CharField(
                        blank=True, max_length=255, verbose_name="Filename"
                    ),
                ),
                ("payload_json", models.JSONField(blank=True, null=True)),
                ("payload_binary", models.BinaryField(blank=True, null=True)),
                (
                    "payload_encoding",
                    models.CharField(
                        blank=True, max_length=32, verbose_name="Encoding"
                    ),
                ),
                (
                    "payload_size",
                    models.PositiveIntegerField(default=0, verbose_name="Payload size"),
                ),
                (
                    "checksum",
                    models.CharField(
                        blank=True, max_length=128, verbose_name="Checksum"
                    ),
                ),
                ("metadata", models.JSONField(blank=True, default=dict)),
                (
                    "download_vendor_id",
                    models.CharField(
                        blank=True, max_length=255, verbose_name="Vendor ID"
                    ),
                ),
                (
                    "download_message_id",
                    models.CharField(
                        blank=True, max_length=64, verbose_name="Message ID"
                    ),
                ),
                (
                    "downloaded_at",
                    models.DateTimeField(
                        blank=True, null=True, verbose_name="Downloaded at"
                    ),
                ),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
            ],
            options={
                "verbose_name": "CP Firmware",
                "verbose_name_plural": "CP Firmware",
                "ordering": ["-created_at"],
            },
        ),
        migrations.CreateModel(
            name="CPFirmwareDeployment",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                (
                    "ocpp_message_id",
                    models.CharField(
                        blank=True, max_length=64, verbose_name="OCPP message ID"
                    ),
                ),
                (
                    "status",
                    models.CharField(blank=True, max_length=32, verbose_name="Status"),
                ),
                (
                    "status_info",
                    models.CharField(
                        blank=True, max_length=255, verbose_name="Status details"
                    ),
                ),
                (
                    "status_timestamp",
                    models.DateTimeField(
                        blank=True, null=True, verbose_name="Status timestamp"
                    ),
                ),
                (
                    "requested_at",
                    models.DateTimeField(
                        auto_now_add=True, verbose_name="Requested at"
                    ),
                ),
                (
                    "completed_at",
                    models.DateTimeField(
                        blank=True, null=True, verbose_name="Completed at"
                    ),
                ),
                (
                    "retrieve_date",
                    models.DateTimeField(
                        blank=True, null=True, verbose_name="Retrieve date"
                    ),
                ),
                (
                    "retry_count",
                    models.PositiveIntegerField(default=0, verbose_name="Retries"),
                ),
                (
                    "retry_interval",
                    models.PositiveIntegerField(
                        default=0, verbose_name="Retry interval (seconds)"
                    ),
                ),
                (
                    "download_token",
                    models.CharField(
                        blank=True, max_length=64, verbose_name="Download token"
                    ),
                ),
                (
                    "download_token_expires_at",
                    models.DateTimeField(
                        blank=True, null=True, verbose_name="Token expires at"
                    ),
                ),
                (
                    "downloaded_at",
                    models.DateTimeField(
                        blank=True, null=True, verbose_name="Downloaded at"
                    ),
                ),
                ("request_payload", models.JSONField(blank=True, default=dict)),
                ("response_payload", models.JSONField(blank=True, default=dict)),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
            ],
            options={
                "verbose_name": "CP Firmware Deployment",
                "verbose_name_plural": "CP Firmware Deployments",
                "ordering": ["-requested_at"],
            },
        ),
        migrations.CreateModel(
            name="CPFirmwareRequest",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                (
                    "connector_id",
                    models.PositiveIntegerField(
                        blank=True, null=True, verbose_name="Connector ID"
                    ),
                ),
                ("vendor_id", models.CharField(blank=True, max_length=255)),
                ("requested_at", models.DateTimeField(auto_now_add=True)),
                ("responded_at", models.DateTimeField(blank=True, null=True)),
                ("status", models.CharField(blank=True, max_length=64)),
                ("response_payload", models.JSONField(blank=True, null=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
            ],
            options={
                "verbose_name": "CP Firmware Request",
                "verbose_name_plural": "CP Firmware Requests",
                "ordering": ["-requested_at"],
            },
        ),
        migrations.CreateModel(
            name="CPForwarder",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                (
                    "name",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Optional label used when listing this forwarder.",
                        max_length=100,
                        verbose_name="Name",
                    ),
                ),
                (
                    "enabled",
                    models.BooleanField(
                        default=False,
                        help_text="Enable to forward eligible charge points to the remote node. Charge points must also have Export transactions enabled.",
                    ),
                ),
                (
                    "forwarded_messages",
                    models.JSONField(
                        blank=True,
                        default=apps.ocpp.models.cp_forwarder.default_forwarded_messages,
                        help_text="Select the OCPP messages that should be forwarded to the remote node.",
                    ),
                ),
                (
                    "is_running",
                    models.BooleanField(
                        default=False,
                        editable=False,
                        help_text="Indicates whether an active forwarding websocket is connected.",
                    ),
                ),
                (
                    "last_forwarded_at",
                    models.DateTimeField(
                        blank=True,
                        help_text="Timestamp of the most recent forwarding activity.",
                        null=True,
                        verbose_name="Last forwarded at",
                    ),
                ),
                (
                    "last_status",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Summary of the last forwarding synchronization.",
                        max_length=255,
                        verbose_name="Last status",
                    ),
                ),
                (
                    "last_error",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Most recent error encountered while configuring forwarding.",
                        max_length=255,
                        verbose_name="Last error",
                    ),
                ),
                (
                    "last_synced_at",
                    models.DateTimeField(
                        blank=True,
                        help_text="When the forwarder last attempted to apply its configuration.",
                        null=True,
                        verbose_name="Last synced at",
                    ),
                ),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
            ],
            options={
                "verbose_name": "CP Forwarder",
                "verbose_name_plural": "CP Forwarders",
                "db_table": "protocols_cpforwarder",
                "ordering": ["target_node__hostname", "target_node__pk"],
            },
        ),
        migrations.CreateModel(
            name="CPNetworkProfile",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                ("name", models.CharField(max_length=200, verbose_name="Name")),
                (
                    "description",
                    models.TextField(blank=True, verbose_name="Description"),
                ),
                (
                    "configuration_slot",
                    models.PositiveIntegerField(
                        default=1,
                        help_text="Target configurationSlot.",
                        verbose_name="Configuration slot",
                    ),
                ),
                (
                    "connection_data",
                    models.JSONField(
                        blank=True,
                        default=dict,
                        help_text="connectionData payload for SetNetworkProfile.",
                    ),
                ),
                (
                    "apn",
                    models.JSONField(
                        blank=True,
                        default=dict,
                        help_text="Optional APN settings to include with the profile.",
                    ),
                ),
                (
                    "vpn",
                    models.JSONField(
                        blank=True,
                        default=dict,
                        help_text="Optional VPN settings to include with the profile.",
                    ),
                ),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
            ],
            options={
                "verbose_name": "CP Network Profile",
                "verbose_name_plural": "CP Network Profiles",
                "ordering": ["name", "configuration_slot"],
            },
        ),
        migrations.CreateModel(
            name="CPNetworkProfileDeployment",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                (
                    "ocpp_message_id",
                    models.CharField(
                        blank=True, max_length=64, verbose_name="OCPP message ID"
                    ),
                ),
                (
                    "status",
                    models.CharField(blank=True, max_length=32, verbose_name="Status"),
                ),
                (
                    "status_info",
                    models.CharField(
                        blank=True, max_length=255, verbose_name="Status details"
                    ),
                ),
                (
                    "status_timestamp",
                    models.DateTimeField(
                        blank=True, null=True, verbose_name="Status timestamp"
                    ),
                ),
                (
                    "requested_at",
                    models.DateTimeField(
                        auto_now_add=True, verbose_name="Requested at"
                    ),
                ),
                (
                    "completed_at",
                    models.DateTimeField(
                        blank=True, null=True, verbose_name="Completed at"
                    ),
                ),
                ("request_payload", models.JSONField(blank=True, default=dict)),
                ("response_payload", models.JSONField(blank=True, default=dict)),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
            ],
            options={
                "verbose_name": "CP Network Profile Deployment",
                "verbose_name_plural": "CP Network Profile Deployments",
                "ordering": ["-requested_at"],
            },
        ),
        migrations.CreateModel(
            name="CPReservation",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                (
                    "id_tag",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Identifier sent to the EVCS when reserving the connector.",
                        max_length=255,
                        verbose_name="Id Tag",
                    ),
                ),
                ("start_time", models.DateTimeField(verbose_name="Start time")),
                (
                    "duration_minutes",
                    models.PositiveIntegerField(
                        default=120,
                        help_text="Reservation window length in minutes.",
                        verbose_name="Duration (minutes)",
                    ),
                ),
                (
                    "evcs_status",
                    models.CharField(
                        blank=True,
                        default="",
                        max_length=32,
                        verbose_name="EVCS status",
                    ),
                ),
                (
                    "evcs_error",
                    models.CharField(
                        blank=True,
                        default="",
                        max_length=255,
                        verbose_name="EVCS error",
                    ),
                ),
                (
                    "evcs_confirmed",
                    models.BooleanField(
                        default=False, verbose_name="Reservation confirmed"
                    ),
                ),
                (
                    "evcs_confirmed_at",
                    models.DateTimeField(
                        blank=True, null=True, verbose_name="Confirmed at"
                    ),
                ),
                (
                    "ocpp_message_id",
                    models.CharField(
                        blank=True,
                        default="",
                        editable=False,
                        max_length=36,
                        verbose_name="OCPP Message ID",
                    ),
                ),
                (
                    "created_on",
                    models.DateTimeField(auto_now_add=True, verbose_name="Created on"),
                ),
                (
                    "updated_on",
                    models.DateTimeField(auto_now=True, verbose_name="Updated on"),
                ),
            ],
            options={
                "verbose_name": "CP Reservation",
                "verbose_name_plural": "CP Reservations",
                "ordering": ["-start_time"],
            },
        ),
        migrations.CreateModel(
            name="DataTransferMessage",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                (
                    "connector_id",
                    models.PositiveIntegerField(
                        blank=True, null=True, verbose_name="Connector ID"
                    ),
                ),
                (
                    "direction",
                    models.CharField(
                        choices=[
                            ("cp_to_csms", "Charge Point → CSMS"),
                            ("csms_to_cp", "CSMS → Charge Point"),
                        ],
                        max_length=16,
                    ),
                ),
                (
                    "ocpp_message_id",
                    models.CharField(max_length=64, verbose_name="OCPP message ID"),
                ),
                (
                    "vendor_id",
                    models.CharField(
                        blank=True, max_length=255, verbose_name="Vendor ID"
                    ),
                ),
                (
                    "message_id",
                    models.CharField(
                        blank=True, max_length=255, verbose_name="Message ID"
                    ),
                ),
                ("payload", models.JSONField(blank=True, default=dict)),
                ("status", models.CharField(blank=True, max_length=64)),
                ("response_data", models.JSONField(blank=True, null=True)),
                ("error_code", models.CharField(blank=True, max_length=64)),
                ("error_description", models.TextField(blank=True)),
                ("error_details", models.JSONField(blank=True, null=True)),
                ("responded_at", models.DateTimeField(blank=True, null=True)),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
            ],
            options={
                "verbose_name": "CP Data Message",
                "verbose_name_plural": "CP Data Messages",
                "ordering": ["-created_at"],
            },
        ),
        migrations.CreateModel(
            name="MeterValue",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                ("connector_id", models.PositiveIntegerField(blank=True, null=True)),
                ("timestamp", models.DateTimeField()),
                ("context", models.CharField(blank=True, max_length=32)),
                (
                    "energy",
                    models.DecimalField(
                        blank=True, decimal_places=3, max_digits=12, null=True
                    ),
                ),
                (
                    "voltage",
                    models.DecimalField(
                        blank=True, decimal_places=3, max_digits=12, null=True
                    ),
                ),
                (
                    "current_import",
                    models.DecimalField(
                        blank=True, decimal_places=3, max_digits=12, null=True
                    ),
                ),
                (
                    "current_offered",
                    models.DecimalField(
                        blank=True, decimal_places=3, max_digits=12, null=True
                    ),
                ),
                (
                    "temperature",
                    models.DecimalField(
                        blank=True, decimal_places=3, max_digits=12, null=True
                    ),
                ),
                (
                    "soc",
                    models.DecimalField(
                        blank=True, decimal_places=3, max_digits=12, null=True
                    ),
                ),
            ],
            options={
                "verbose_name": "Meter Value",
                "verbose_name_plural": "Meter Values",
            },
        ),
        migrations.CreateModel(
            name="PowerProjection",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                (
                    "connector_id",
                    models.PositiveIntegerField(
                        default=0,
                        help_text="Connector targeted by the projection (0 for the EVCS).",
                        verbose_name="Connector ID",
                    ),
                ),
                (
                    "duration_seconds",
                    models.PositiveIntegerField(
                        blank=True, null=True, verbose_name="Duration (seconds)"
                    ),
                ),
                (
                    "charging_rate_unit",
                    models.CharField(
                        blank=True,
                        choices=[("A", "Amperes"), ("W", "Watts")],
                        default="",
                        max_length=2,
                        verbose_name="Charging rate unit",
                    ),
                ),
                (
                    "charging_schedule_periods",
                    models.JSONField(
                        blank=True,
                        default=list,
                        help_text="Composite schedule periods returned by the EVCS.",
                    ),
                ),
                (
                    "schedule_start",
                    models.DateTimeField(
                        blank=True, null=True, verbose_name="Schedule start"
                    ),
                ),
                ("status", models.CharField(blank=True, default="", max_length=32)),
                ("raw_response", models.JSONField(blank=True, default=dict)),
                ("requested_at", models.DateTimeField(auto_now_add=True)),
                ("received_at", models.DateTimeField(blank=True, null=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
            ],
            options={
                "verbose_name": "Power Projection",
                "verbose_name_plural": "Power Projections",
                "ordering": ["-received_at", "-requested_at", "-pk"],
            },
        ),
        migrations.CreateModel(
            name="RFIDSessionAttempt",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                (
                    "rfid",
                    models.CharField(blank=True, max_length=255, verbose_name="RFID"),
                ),
                (
                    "status",
                    models.CharField(
                        choices=[("accepted", "Accepted"), ("rejected", "Rejected")],
                        max_length=16,
                    ),
                ),
                ("attempted_at", models.DateTimeField(auto_now_add=True)),
            ],
            options={
                "verbose_name": "RFID Session Attempt",
                "verbose_name_plural": "RFID Session Attempts",
                "ordering": ["-attempted_at"],
            },
        ),
        migrations.CreateModel(
            name="SecurityEvent",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                (
                    "event_type",
                    models.CharField(max_length=120, verbose_name="Event Type"),
                ),
                (
                    "event_timestamp",
                    models.DateTimeField(verbose_name="Event Timestamp"),
                ),
                ("trigger", models.CharField(blank=True, default="", max_length=120)),
                ("tech_info", models.TextField(blank=True, default="")),
                ("sequence_number", models.BigIntegerField(blank=True, null=True)),
                ("raw_payload", models.JSONField(blank=True, default=dict)),
                ("reported_at", models.DateTimeField(auto_now_add=True)),
            ],
            options={
                "verbose_name": "Security Event",
                "verbose_name_plural": "Security Events",
                "ordering": ["-event_timestamp", "-pk"],
            },
        ),
        migrations.CreateModel(
            name="Simulator",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                ("name", models.CharField(max_length=100, unique=True)),
                (
                    "default",
                    models.BooleanField(
                        default=False,
                        help_text="Mark this simulator as the default option.",
                    ),
                ),
                (
                    "cp_path",
                    models.CharField(max_length=100, verbose_name="Serial Number"),
                ),
                ("host", models.CharField(default="127.0.0.1", max_length=100)),
                (
                    "ws_port",
                    models.IntegerField(
                        blank=True, default=8000, null=True, verbose_name="WS Port"
                    ),
                ),
                (
                    "rfid",
                    models.CharField(
                        default="FFFFFFFF", max_length=255, verbose_name="RFID"
                    ),
                ),
                ("vin", models.CharField(blank=True, max_length=17)),
                (
                    "serial_number",
                    models.CharField(
                        blank=True, max_length=100, verbose_name="Serial Number"
                    ),
                ),
                (
                    "connector_id",
                    models.IntegerField(default=1, verbose_name="Connector ID"),
                ),
                ("duration", models.IntegerField(default=600)),
                ("interval", models.FloatField(default=5.0)),
                (
                    "pre_charge_delay",
                    models.FloatField(default=10.0, verbose_name="Delay"),
                ),
                ("average_kwh", models.FloatField(default=60.0)),
                ("amperage", models.FloatField(default=90.0)),
                ("repeat", models.BooleanField(default=False)),
                ("username", models.CharField(blank=True, max_length=100)),
                ("password", models.CharField(blank=True, max_length=100)),
                (
                    "door_open",
                    models.BooleanField(
                        default=False,
                        help_text="Send a DoorOpen error StatusNotification when enabled.",
                        verbose_name="Door Open",
                    ),
                ),
                (
                    "configuration_keys",
                    models.JSONField(
                        blank=True,
                        default=list,
                        help_text="List of configurationKey entries to return for GetConfiguration calls.",
                    ),
                ),
                (
                    "configuration_unknown_keys",
                    models.JSONField(
                        blank=True,
                        default=list,
                        help_text="Keys to include in the GetConfiguration unknownKey response.",
                    ),
                ),
            ],
            options={
                "verbose_name": "CP Simulator",
                "verbose_name_plural": "CP Simulators",
            },
        ),
        migrations.CreateModel(
            name="StationModel",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                ("vendor", models.CharField(max_length=100, verbose_name="Vendor")),
                (
                    "model_family",
                    models.CharField(max_length=100, verbose_name="Model Family"),
                ),
                ("model", models.CharField(max_length=100, verbose_name="Model")),
                (
                    "max_power_kw",
                    models.DecimalField(
                        blank=True,
                        decimal_places=2,
                        help_text="Maximum sustained charging power supported by this model.",
                        max_digits=6,
                        null=True,
                        verbose_name="Max Power (kW)",
                    ),
                ),
                (
                    "max_voltage_v",
                    models.PositiveIntegerField(
                        blank=True,
                        help_text="Maximum supported operating voltage.",
                        null=True,
                        verbose_name="Max Voltage (V)",
                    ),
                ),
                (
                    "preferred_ocpp_version",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Optional OCPP protocol version usually paired with this EVCS model.",
                        max_length=16,
                        verbose_name="Preferred OCPP Version",
                    ),
                ),
                (
                    "connector_type",
                    models.CharField(
                        blank=True,
                        help_text="Primary connector format supported by this model.",
                        max_length=64,
                        verbose_name="Connector Type",
                    ),
                ),
                (
                    "notes",
                    models.TextField(
                        blank=True,
                        default="",
                        help_text="Optional comments about capabilities or certifications.",
                    ),
                ),
            ],
            options={
                "verbose_name": "Station Model",
                "verbose_name_plural": "Station Models",
                "db_table": "core_stationmodel",
            },
        ),
        migrations.CreateModel(
            name="Transaction",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                (
                    "rfid",
                    models.CharField(blank=True, max_length=20, verbose_name="RFID"),
                ),
                (
                    "vid",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Vehicle identifier reported by the charger.",
                        max_length=64,
                        verbose_name="VID",
                    ),
                ),
                (
                    "vin",
                    models.CharField(
                        blank=True,
                        help_text="Deprecated. Use VID instead.",
                        max_length=17,
                    ),
                ),
                (
                    "ocpp_transaction_id",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Transaction identifier reported by the charge point or generated by OCPP.",
                        max_length=128,
                        verbose_name="OCPP Transaction ID",
                    ),
                ),
                ("connector_id", models.PositiveIntegerField(blank=True, null=True)),
                ("meter_start", models.IntegerField(blank=True, null=True)),
                ("meter_stop", models.IntegerField(blank=True, null=True)),
                (
                    "voltage_start",
                    models.DecimalField(
                        blank=True, decimal_places=3, max_digits=12, null=True
                    ),
                ),
                (
                    "voltage_stop",
                    models.DecimalField(
                        blank=True, decimal_places=3, max_digits=12, null=True
                    ),
                ),
                (
                    "current_import_start",
                    models.DecimalField(
                        blank=True, decimal_places=3, max_digits=12, null=True
                    ),
                ),
                (
                    "current_import_stop",
                    models.DecimalField(
                        blank=True, decimal_places=3, max_digits=12, null=True
                    ),
                ),
                (
                    "current_offered_start",
                    models.DecimalField(
                        blank=True, decimal_places=3, max_digits=12, null=True
                    ),
                ),
                (
                    "current_offered_stop",
                    models.DecimalField(
                        blank=True, decimal_places=3, max_digits=12, null=True
                    ),
                ),
                (
                    "temperature_start",
                    models.DecimalField(
                        blank=True, decimal_places=3, max_digits=12, null=True
                    ),
                ),
                (
                    "temperature_stop",
                    models.DecimalField(
                        blank=True, decimal_places=3, max_digits=12, null=True
                    ),
                ),
                (
                    "soc_start",
                    models.DecimalField(
                        blank=True, decimal_places=3, max_digits=12, null=True
                    ),
                ),
                (
                    "soc_stop",
                    models.DecimalField(
                        blank=True, decimal_places=3, max_digits=12, null=True
                    ),
                ),
                ("start_time", models.DateTimeField()),
                ("stop_time", models.DateTimeField(blank=True, null=True)),
                ("received_start_time", models.DateTimeField(blank=True, null=True)),
                ("received_stop_time", models.DateTimeField(blank=True, null=True)),
            ],
            options={
                "verbose_name": "Transaction",
                "verbose_name_plural": "CP Transactions",
            },
        ),
        migrations.CreateModel(
            name="RFID",
            fields=[],
            options={
                "verbose_name": "RFID",
                "verbose_name_plural": "RFIDs",
                "proxy": True,
                "indexes": [],
                "constraints": [],
            },
            bases=("cards.rfid",),
        ),
        migrations.CreateModel(
            name="Charger",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("is_seed_data", models.BooleanField(default=False, editable=False)),
                ("is_user_data", models.BooleanField(default=False, editable=False)),
                ("is_deleted", models.BooleanField(default=False, editable=False)),
                (
                    "charger_id",
                    models.CharField(
                        help_text="Unique identifier reported by the charger.",
                        max_length=100,
                        verbose_name="Serial Number",
                    ),
                ),
                (
                    "display_name",
                    models.CharField(
                        blank=True,
                        help_text="Optional friendly name shown on public pages.",
                        max_length=200,
                        verbose_name="Display Name",
                    ),
                ),
                (
                    "connector_id",
                    models.PositiveIntegerField(
                        blank=True,
                        help_text="Optional connector identifier for multi-connector chargers.",
                        null=True,
                        verbose_name="Connector ID",
                    ),
                ),
                (
                    "public_display",
                    models.BooleanField(
                        default=True,
                        help_text="Display this charger on the public status dashboard.",
                        verbose_name="Public",
                    ),
                ),
                (
                    "preferred_ocpp_version",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Optional OCPP protocol version to prefer when multiple are available.",
                        max_length=16,
                        verbose_name="Preferred OCPP Version",
                    ),
                ),
                (
                    "energy_unit",
                    models.CharField(
                        choices=[("kW", "kW"), ("W", "W")],
                        default="kW",
                        help_text="Energy unit expected from this charger.",
                        max_length=4,
                        verbose_name="Charger Units",
                    ),
                ),
                (
                    "require_rfid",
                    models.BooleanField(
                        default=False,
                        help_text="Require a valid RFID before starting a charging session.",
                        verbose_name="Require RFID Authorization",
                    ),
                ),
                (
                    "firmware_status",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Latest firmware status reported by the charger.",
                        max_length=32,
                        verbose_name="Status",
                    ),
                ),
                (
                    "firmware_status_info",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Additional information supplied with the firmware status.",
                        max_length=255,
                        verbose_name="Status Details",
                    ),
                ),
                (
                    "firmware_timestamp",
                    models.DateTimeField(
                        blank=True,
                        help_text="When the charger reported the current firmware status.",
                        null=True,
                        verbose_name="Status Timestamp",
                    ),
                ),
                ("last_heartbeat", models.DateTimeField(blank=True, null=True)),
                ("last_meter_values", models.JSONField(blank=True, default=dict)),
                ("last_status", models.CharField(blank=True, max_length=64)),
                ("last_error_code", models.CharField(blank=True, max_length=64)),
                ("last_status_vendor_info", models.JSONField(blank=True, null=True)),
                ("last_status_timestamp", models.DateTimeField(blank=True, null=True)),
                (
                    "availability_state",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Current availability reported by the charger (Operative/Inoperative).",
                        max_length=16,
                        verbose_name="State",
                    ),
                ),
                (
                    "availability_state_updated_at",
                    models.DateTimeField(
                        blank=True,
                        help_text="When the current availability state became effective.",
                        null=True,
                        verbose_name="State Updated At",
                    ),
                ),
                (
                    "availability_requested_state",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Last availability state requested via ChangeAvailability.",
                        max_length=16,
                        verbose_name="Requested State",
                    ),
                ),
                (
                    "availability_requested_at",
                    models.DateTimeField(
                        blank=True,
                        help_text="When the last ChangeAvailability request was sent.",
                        null=True,
                        verbose_name="Requested At",
                    ),
                ),
                (
                    "availability_request_status",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Latest response status for ChangeAvailability (Accepted/Rejected/Scheduled).",
                        max_length=16,
                        verbose_name="Request Status",
                    ),
                ),
                (
                    "availability_request_status_at",
                    models.DateTimeField(
                        blank=True,
                        help_text="When the last ChangeAvailability response was received.",
                        null=True,
                        verbose_name="Request Status At",
                    ),
                ),
                (
                    "availability_request_details",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Additional details from the last ChangeAvailability response.",
                        max_length=255,
                        verbose_name="Request Details",
                    ),
                ),
                (
                    "temperature",
                    models.DecimalField(
                        blank=True, decimal_places=1, max_digits=5, null=True
                    ),
                ),
                ("temperature_unit", models.CharField(blank=True, max_length=16)),
                (
                    "diagnostics_status",
                    models.CharField(
                        blank=True,
                        help_text="Most recent diagnostics status reported by the charger.",
                        max_length=32,
                        null=True,
                    ),
                ),
                (
                    "diagnostics_timestamp",
                    models.DateTimeField(
                        blank=True,
                        help_text="Timestamp associated with the latest diagnostics status.",
                        null=True,
                    ),
                ),
                (
                    "diagnostics_location",
                    models.CharField(
                        blank=True,
                        help_text="Location or URI reported for the latest diagnostics upload.",
                        max_length=255,
                        null=True,
                    ),
                ),
                ("last_path", models.CharField(blank=True, max_length=255)),
                (
                    "local_auth_list_version",
                    models.PositiveIntegerField(
                        blank=True,
                        help_text="Last RFID list version acknowledged by the charge point.",
                        null=True,
                        verbose_name="Local list version",
                    ),
                ),
                (
                    "local_auth_list_updated_at",
                    models.DateTimeField(
                        blank=True,
                        help_text="When the charge point reported or accepted the RFID list.",
                        null=True,
                        verbose_name="Local list updated at",
                    ),
                ),
                (
                    "forwarding_watermark",
                    models.DateTimeField(
                        blank=True,
                        help_text="Timestamp of the last forwarded transaction.",
                        null=True,
                    ),
                ),
                (
                    "allow_remote",
                    models.BooleanField(
                        default=False,
                        help_text="Permit this charge point to receive remote commands from its manager or forwarding target.",
                    ),
                ),
                (
                    "export_transactions",
                    models.BooleanField(
                        default=False,
                        help_text="Enable to share this charge point's transactions with remote nodes or export tools. Required for CP forwarders.",
                    ),
                ),
                ("last_online_at", models.DateTimeField(blank=True, null=True)),
                (
                    "diagnostics_bucket",
                    models.ForeignKey(
                        blank=True,
                        help_text="Media bucket where this charge point should upload diagnostics.",
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="chargers",
                        to="media.mediabucket",
                    ),
                ),
                (
                    "forwarded_to",
                    models.ForeignKey(
                        blank=True,
                        help_text="Remote node receiving forwarded transactions.",
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="forwarded_chargers",
                        to="nodes.node",
                    ),
                ),
                (
                    "language",
                    models.ForeignKey(
                        blank=True,
                        help_text="Preferred language for the public landing page.",
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="chargers",
                        to="locale.language",
                        verbose_name="Language",
                    ),
                ),
                (
                    "location",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="chargers",
                        to="maps.location",
                    ),
                ),
                (
                    "manager_node",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="managed_chargers",
                        to="nodes.node",
                    ),
                ),
                (
                    "node_origin",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="origin_chargers",
                        to="nodes.node",
                    ),
                ),
                (
                    "owner_groups",
                    models.ManyToManyField(
                        blank=True,
                        help_text="Security groups that can view this charge point.",
                        related_name="owned_chargers",
                        to="groups.securitygroup",
                    ),
                ),
            ],
            options={
                "verbose_name": "Charge Point",
                "verbose_name_plural": "Charge Points",
            },
        ),
    ]
