# Generated by Django 5.2.9 on 2026-01-11 03:31

import apps.ocpp.models.charger_log_request
import apps.ocpp.models.cp_forwarder
import django.db.migrations.operations.special
import django.db.models.deletion
import django.utils.timezone
from django.conf import settings
from django.db import migrations, models


# Functions from the following migrations need manual copying.
# Move them and any dependencies into this file, then update the
# RunPython operations to refer to the local versions:
# apps.ocpp.migrations.0008_forwarder_defaults_and_exports


def enable_forwarders_and_exports(apps, schema_editor):
    CPForwarder = apps.get_model("ocpp", "CPForwarder")
    Charger = apps.get_model("ocpp", "Charger")
    CPForwarder.objects.all().update(enabled=True)
    Charger.objects.all().update(export_transactions=True)


class Migration(migrations.Migration):

    replaces = [('ocpp', '0001_initial'), ('ocpp', '0002_initial'), ('ocpp', '0003_charger_configuration_check_enabled_and_more'), ('ocpp', '0004_remove_rfid_proxy'), ('ocpp', '0005_certificateoperation_certificaterequest_and_more'), ('ocpp', '0006_monitoringreport_variable_monitoringrule_and_more'), ('ocpp', '0007_customer_information_display_messages'), ('ocpp', '0008_forwarder_defaults_and_exports'), ('ocpp', '0009_costupdate'), ('ocpp', '0009_clearedcharginglimitevent'), ('ocpp', '0010_merge_0009_clearedcharginglimitevent_0009_costupdate'), ('ocpp', '0010_charger_last_charging_limit_and_more'), ('ocpp', '0011_merge_20260103_1323'), ('ocpp', '0012_device_inventory_snapshot'), ('ocpp', '0013_alter_deviceinventoryitem_options_and_more')]

    initial = False

    dependencies = [
        ('cards', '0002_initial'),
        ('energy', '0001_initial'),
        ('groups', '0001_initial'),
        ('groups', '0002_initial'),
        ('links', '0002_initial'),
        ('locale', '0001_initial'),
        ('maps', '0001_initial'),
        ('maps', '0002_initial'),
        ('media', '0001_initial'),
        ('nodes', '0001_initial'),
        ('nodes', '0002_initial'),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    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='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='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')),
                ('owner_users', models.ManyToManyField(blank=True, help_text='Users who can view this charge point.', related_name='owned_chargers', to=settings.AUTH_USER_MODEL)),
                ('reference', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='links.reference')),
                ('ws_auth_group', models.ForeignKey(blank=True, help_text='Charge point connections must authenticate with HTTP Basic as a member of this security group.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='ws_group_authenticated_chargers', to='groups.securitygroup', verbose_name='WS Auth Group')),
                ('ws_auth_user', models.ForeignKey(blank=True, help_text='Charge point connections must authenticate with HTTP Basic using this user.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='ws_authenticated_chargers', to=settings.AUTH_USER_MODEL, verbose_name='WS Auth User')),
                ('configuration', models.ForeignKey(blank=True, help_text='Latest GetConfiguration response received from this charge point.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='chargers', to='ocpp.chargerconfiguration')),
                ('network_profile', models.ForeignKey(blank=True, help_text='Last network profile that was successfully applied to this charge point.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='chargers', to='ocpp.cpnetworkprofile')),
            ],
            options={
                'verbose_name': 'Charge Point',
                'verbose_name_plural': 'Charge Points',
            },
        ),
        migrations.CreateModel(
            name='EVCSChargePoint',
            fields=[
            ],
            options={
                'verbose_name': 'EVCS Charge Point',
                'verbose_name_plural': 'EVCS Charge Points',
                'proxy': True,
                'indexes': [],
                'constraints': [],
            },
            bases=('ocpp.charger',),
        ),
        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)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='log_requests', to='ocpp.charger')),
            ],
            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)),
                ('charger', models.ForeignKey(blank=True, help_text='Optional default charger context for the profile.', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='charging_profiles', to='ocpp.charger', verbose_name='Charger')),
            ],
            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)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='charging_profile_dispatches', to='ocpp.charger')),
                ('profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='dispatches', to='ocpp.chargingprofile')),
            ],
            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)),
                ('profile', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='schedule', to='ocpp.chargingprofile')),
            ],
            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)),
                ('configuration', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='configuration_entries', to='ocpp.chargerconfiguration')),
            ],
            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)),
                ('source_charger', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='downloaded_firmware', to='ocpp.charger', verbose_name='Source charge point')),
                ('source_node', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='downloaded_firmware', to='nodes.node', verbose_name='Source node')),
            ],
            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)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='firmware_deployments', to='ocpp.charger', verbose_name='Charge point')),
                ('firmware', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='deployments', to='ocpp.cpfirmware', verbose_name='Firmware')),
                ('node', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='firmware_deployments', to='nodes.node', verbose_name='Node')),
            ],
            options={
                'verbose_name': 'CP Firmware Deployment',
                'verbose_name_plural': 'CP Firmware Deployments',
                '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)),
                ('source_node', models.ForeignKey(blank=True, help_text='Node providing the original charge point connection.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='outgoing_forwarders', to='nodes.node')),
                ('target_node', models.ForeignKey(help_text='Remote node that will receive forwarded sessions.', on_delete=django.db.models.deletion.CASCADE, related_name='incoming_forwarders', to='nodes.node')),
            ],
            options={
                'verbose_name': 'CP Forwarder',
                'verbose_name_plural': 'CP Forwarders',
                'db_table': 'protocols_cpforwarder',
                'ordering': ['target_node__hostname', 'target_node__pk'],
            },
        ),
        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)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='network_profile_deployments', to='ocpp.charger', verbose_name='Charge point')),
                ('network_profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='deployments', to='ocpp.cpnetworkprofile', verbose_name='Network profile')),
                ('node', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='network_profile_deployments', to='nodes.node', verbose_name='Node')),
            ],
            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')),
                ('account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='cp_reservations', to='energy.customeraccount', verbose_name='Energy account')),
                ('connector', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='reservations', to='ocpp.charger', verbose_name='Connector')),
                ('location', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='reservations', to='maps.location', verbose_name='Location')),
                ('rfid', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='cp_reservations', to='cards.rfid', verbose_name='RFID')),
            ],
            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)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='data_transfer_messages', to='ocpp.charger')),
            ],
            options={
                'verbose_name': 'CP Data Message',
                'verbose_name_plural': 'CP Data Messages',
                'ordering': ['-created_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)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='firmware_requests', to='ocpp.charger')),
                ('message', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='firmware_request', to='ocpp.datatransfermessage')),
            ],
            options={
                'verbose_name': 'CP Firmware Request',
                'verbose_name_plural': 'CP Firmware Requests',
                'ordering': ['-requested_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)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='meter_values', to='ocpp.charger')),
            ],
            options={
                'verbose_name': 'Meter Value',
                'verbose_name_plural': 'Meter Values',
            },
        ),
        migrations.CreateModel(
            name='MeterReading',
            fields=[
            ],
            options={
                'verbose_name': 'Meter Value',
                'verbose_name_plural': 'Meter Values',
                'proxy': True,
                'indexes': [],
                'constraints': [],
            },
            bases=('ocpp.metervalue',),
        ),
        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)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='power_projections', to='ocpp.charger', verbose_name='Charger')),
            ],
            options={
                'verbose_name': 'Power Projection',
                'verbose_name_plural': 'Power Projections',
                'ordering': ['-received_at', '-requested_at', '-pk'],
            },
        ),
        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)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='security_events', to='ocpp.charger')),
            ],
            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.')),
                ('configuration', models.ForeignKey(blank=True, help_text='CP Configuration returned for GetConfiguration calls.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='simulators', to='ocpp.chargerconfiguration')),
            ],
            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',
                'unique_together': {('vendor', 'model_family', 'model')},
            },
        ),
        migrations.AddField(
            model_name='charger',
            name='station_model',
            field=models.ForeignKey(blank=True, help_text='Optional hardware model for this EVCS.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='chargers', to='ocpp.stationmodel', verbose_name='Station Model'),
        ),
        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)),
                ('account', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='transactions', to='energy.customeraccount')),
                ('charger', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='transactions', to='ocpp.charger')),
            ],
            options={
                'verbose_name': 'Transaction',
                'verbose_name_plural': 'CP Transactions',
            },
        ),
        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)),
                ('account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='rfid_attempts', to='energy.customeraccount')),
                ('charger', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rfid_attempts', to='ocpp.charger')),
                ('transaction', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='rfid_attempts', to='ocpp.transaction')),
            ],
            options={
                'verbose_name': 'RFID Session Attempt',
                'verbose_name_plural': 'RFID Session Attempts',
                'ordering': ['-attempted_at'],
            },
        ),
        migrations.AddField(
            model_name='metervalue',
            name='transaction',
            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='meter_values', to='ocpp.transaction'),
        ),
        migrations.AddConstraint(
            model_name='chargingprofile',
            constraint=models.UniqueConstraint(condition=models.Q(('charger__isnull', False)), fields=('charger', 'connector_id', 'charging_profile_id'), name='unique_charging_profile_per_connector'),
        ),
        migrations.AddConstraint(
            model_name='chargingprofiledispatch',
            constraint=models.UniqueConstraint(fields=('profile', 'charger', 'message_id'), name='unique_charging_profile_dispatch_message'),
        ),
        migrations.AddIndex(
            model_name='cpfirmwaredeployment',
            index=models.Index(fields=['ocpp_message_id'], name='ocpp_cpfirm_ocpp_me_881925_idx'),
        ),
        migrations.AddIndex(
            model_name='cpfirmwaredeployment',
            index=models.Index(fields=['download_token'], name='ocpp_cpfirm_downloa_7f183a_idx'),
        ),
        migrations.AddConstraint(
            model_name='cpforwarder',
            constraint=models.UniqueConstraint(fields=('source_node', 'target_node'), name='unique_forwarder_per_target'),
        ),
        migrations.AddIndex(
            model_name='cpnetworkprofiledeployment',
            index=models.Index(fields=['ocpp_message_id'], name='ocpp_cpnetw_ocpp_me_cc48cb_idx'),
        ),
        migrations.AddIndex(
            model_name='datatransfermessage',
            index=models.Index(fields=['ocpp_message_id'], name='ocpp_datatr_ocpp_me_70d17f_idx'),
        ),
        migrations.AddIndex(
            model_name='datatransfermessage',
            index=models.Index(fields=['vendor_id'], name='ocpp_datatr_vendor__59e1c7_idx'),
        ),
        migrations.AddConstraint(
            model_name='simulator',
            constraint=models.UniqueConstraint(condition=models.Q(('default', True), ('is_deleted', False)), fields=('default',), name='unique_default_simulator'),
        ),
        migrations.AddConstraint(
            model_name='charger',
            constraint=models.UniqueConstraint(condition=models.Q(('connector_id__isnull', False)), fields=('charger_id', 'connector_id'), name='charger_connector_unique'),
        ),
        migrations.AddConstraint(
            model_name='charger',
            constraint=models.UniqueConstraint(condition=models.Q(('connector_id__isnull', True)), fields=('charger_id',), name='charger_unique_without_connector'),
        ),
        migrations.AddConstraint(
            model_name='charger',
            constraint=models.CheckConstraint(condition=models.Q(('ws_auth_user__isnull', True), ('ws_auth_group__isnull', True), _connector='OR'), name='charger_ws_auth_user_or_group'),
        ),
        migrations.AddField(
            model_name='charger',
            name='configuration_check_enabled',
            field=models.BooleanField(default=False, help_text='Allow scheduled configuration checks for this charger.', verbose_name='Configuration Check'),
        ),
        migrations.AddField(
            model_name='charger',
            name='firmware_snapshot_enabled',
            field=models.BooleanField(default=False, help_text='Allow scheduled firmware snapshot requests for this charger.', verbose_name='Firmware Snapshot'),
        ),
        migrations.AddField(
            model_name='charger',
            name='power_projection_enabled',
            field=models.BooleanField(default=False, help_text='Allow scheduled power projection requests for this charger.', verbose_name='Power Projection'),
        ),
        migrations.DeleteModel(
            name='RFID',
        ),
        migrations.CreateModel(
            name='CertificateOperation',
            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)),
                ('action', models.CharField(choices=[('InstallCertificate', 'Install certificate'), ('DeleteCertificate', 'Delete certificate'), ('CertificateSigned', 'Certificate signed'), ('GetInstalledCertificateIds', 'Get installed certificate ids')], max_length=80)),
                ('certificate_type', models.CharField(blank=True, default='', max_length=80)),
                ('certificate_hash_data', models.JSONField(blank=True, default=dict)),
                ('status', models.CharField(choices=[('Pending', 'Pending'), ('Accepted', 'Accepted'), ('Rejected', 'Rejected'), ('Error', 'Error')], default='Pending', max_length=20)),
                ('status_info', models.TextField(blank=True, default='')),
                ('request_payload', models.JSONField(blank=True, default=dict)),
                ('response_payload', models.JSONField(blank=True, default=dict)),
                ('error_code', models.CharField(blank=True, default='', max_length=120)),
                ('error_description', models.TextField(blank=True, default='')),
                ('requested_at', models.DateTimeField(auto_now_add=True)),
                ('responded_at', models.DateTimeField(blank=True, null=True)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='certificate_operations', to='ocpp.charger')),
            ],
            options={
                'verbose_name': 'Certificate operation',
                'verbose_name_plural': 'Certificate operations',
                'ordering': ['-requested_at', '-pk'],
            },
        ),
        migrations.CreateModel(
            name='CertificateRequest',
            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)),
                ('action', models.CharField(choices=[('SignCertificate', 'Sign Certificate'), ('Get15118EVCertificate', 'Get 15118 EV Certificate')], max_length=80)),
                ('certificate_type', models.CharField(blank=True, default='', max_length=80)),
                ('csr', models.TextField(blank=True, default='')),
                ('signed_certificate', models.TextField(blank=True, default='')),
                ('status', models.CharField(choices=[('Pending', 'Pending'), ('Accepted', 'Accepted'), ('Rejected', 'Rejected'), ('Error', 'Error')], default='Pending', max_length=20)),
                ('status_info', models.TextField(blank=True, default='')),
                ('request_payload', models.JSONField(blank=True, default=dict)),
                ('response_payload', models.JSONField(blank=True, default=dict)),
                ('requested_at', models.DateTimeField(auto_now_add=True)),
                ('responded_at', models.DateTimeField(blank=True, null=True)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='certificate_requests', to='ocpp.charger')),
            ],
            options={
                'verbose_name': 'Certificate request',
                'verbose_name_plural': 'Certificate requests',
                'ordering': ['-requested_at', '-pk'],
            },
        ),
        migrations.CreateModel(
            name='CertificateStatusCheck',
            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)),
                ('certificate_hash_data', models.JSONField(blank=True, default=dict)),
                ('ocsp_result', models.JSONField(blank=True, default=dict)),
                ('status', models.CharField(choices=[('Pending', 'Pending'), ('Accepted', 'Accepted'), ('Rejected', 'Rejected'), ('Error', 'Error')], default='Pending', max_length=20)),
                ('status_info', models.TextField(blank=True, default='')),
                ('request_payload', models.JSONField(blank=True, default=dict)),
                ('response_payload', models.JSONField(blank=True, default=dict)),
                ('requested_at', models.DateTimeField(auto_now_add=True)),
                ('responded_at', models.DateTimeField(blank=True, null=True)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='certificate_status_checks', to='ocpp.charger')),
            ],
            options={
                'verbose_name': 'Certificate status check',
                'verbose_name_plural': 'Certificate status checks',
                'ordering': ['-requested_at', '-pk'],
            },
        ),
        migrations.CreateModel(
            name='InstalledCertificate',
            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)),
                ('certificate_type', models.CharField(blank=True, default='', max_length=80)),
                ('certificate', models.TextField(blank=True, default='')),
                ('certificate_hash_data', models.JSONField(blank=True, default=dict)),
                ('status', models.CharField(choices=[('Pending', 'Pending'), ('Installed', 'Installed'), ('Rejected', 'Rejected'), ('DeletePending', 'Delete pending'), ('Deleted', 'Deleted'), ('Error', 'Error')], default='Pending', max_length=20)),
                ('last_action', models.CharField(blank=True, default='', max_length=80)),
                ('installed_at', models.DateTimeField(blank=True, null=True)),
                ('deleted_at', models.DateTimeField(blank=True, null=True)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='installed_certificates', to='ocpp.charger')),
            ],
            options={
                'verbose_name': 'Installed certificate',
                'verbose_name_plural': 'Installed certificates',
                'ordering': ['-pk'],
            },
        ),
        migrations.CreateModel(
            name='TrustAnchor',
            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='', max_length=120)),
                ('certificate', models.TextField(blank=True, default='')),
                ('certificate_hash_data', models.JSONField(blank=True, default=dict)),
                ('is_active', models.BooleanField(default=True)),
                ('charger', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='trust_anchors', to='ocpp.charger')),
            ],
            options={
                'verbose_name': 'Trust anchor',
                'verbose_name_plural': 'Trust anchors',
                'ordering': ['name', 'pk'],
            },
        ),
        migrations.CreateModel(
            name='MonitoringReport',
            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(blank=True, null=True, verbose_name='Request ID')),
                ('seq_no', models.BigIntegerField(blank=True, null=True, verbose_name='Sequence Number')),
                ('generated_at', models.DateTimeField(blank=True, null=True, verbose_name='Generated At')),
                ('tbc', models.BooleanField(default=False, verbose_name='To Be Continued')),
                ('raw_payload', models.JSONField(blank=True, default=dict)),
                ('reported_at', models.DateTimeField(auto_now_add=True, verbose_name='Reported at')),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='monitoring_reports', to='ocpp.charger')),
            ],
            options={
                'verbose_name': 'Monitoring Report',
                'verbose_name_plural': 'Monitoring Reports',
                'ordering': ['-reported_at', '-pk'],
            },
        ),
        migrations.CreateModel(
            name='Variable',
            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)),
                ('component_name', models.CharField(max_length=200, verbose_name='Component')),
                ('component_instance', models.CharField(blank=True, default='', max_length=200, verbose_name='Component Instance')),
                ('variable_name', models.CharField(max_length=200, verbose_name='Variable')),
                ('variable_instance', models.CharField(blank=True, default='', max_length=200, verbose_name='Variable Instance')),
                ('attribute_type', models.CharField(blank=True, default='', max_length=32, verbose_name='Attribute Type')),
                ('attribute_status', models.CharField(blank=True, default='', max_length=32, verbose_name='Attribute Status')),
                ('value', models.TextField(blank=True, default='', verbose_name='Value')),
                ('value_type', models.CharField(blank=True, default='', max_length=32, verbose_name='Value Type')),
                ('created_on', models.DateTimeField(auto_now_add=True, verbose_name='Created on')),
                ('updated_on', models.DateTimeField(auto_now=True, verbose_name='Updated on')),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ocpp_variables', to='ocpp.charger')),
            ],
            options={
                'verbose_name': 'Variable',
                'verbose_name_plural': 'Variables',
                'ordering': ['component_name', 'variable_name', 'pk'],
            },
        ),
        migrations.CreateModel(
            name='MonitoringRule',
            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)),
                ('monitoring_id', models.BigIntegerField(verbose_name='Monitoring ID')),
                ('severity', models.PositiveIntegerField(blank=True, null=True, verbose_name='Severity')),
                ('monitor_type', models.CharField(blank=True, default='', max_length=32, verbose_name='Type')),
                ('threshold', models.CharField(blank=True, default='', max_length=255, verbose_name='Threshold')),
                ('is_transaction', models.BooleanField(default=False, verbose_name='Transaction')),
                ('is_active', models.BooleanField(default=True, verbose_name='Active')),
                ('raw_payload', models.JSONField(blank=True, default=dict)),
                ('created_on', models.DateTimeField(auto_now_add=True, verbose_name='Created on')),
                ('updated_on', models.DateTimeField(auto_now=True, verbose_name='Updated on')),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='monitoring_rules', to='ocpp.charger')),
                ('variable', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='monitoring_rules', to='ocpp.variable')),
            ],
            options={
                'verbose_name': 'Monitoring Rule',
                'verbose_name_plural': 'Monitoring Rules',
                'ordering': ['-updated_on', 'monitoring_id', 'pk'],
            },
        ),
        migrations.AddConstraint(
            model_name='variable',
            constraint=models.UniqueConstraint(fields=('charger', 'component_name', 'component_instance', 'variable_name', 'variable_instance', 'attribute_type'), name='ocpp_variable_unique_component'),
        ),
        migrations.AddConstraint(
            model_name='monitoringrule',
            constraint=models.UniqueConstraint(fields=('charger', 'monitoring_id'), name='ocpp_monitoring_rule_unique_id'),
        ),
        migrations.CreateModel(
            name='CustomerInformationRequest',
            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')),
                ('request_id', models.BigIntegerField(blank=True, null=True, verbose_name='Request ID')),
                ('payload', models.JSONField(blank=True, default=dict)),
                ('last_notified_at', models.DateTimeField(blank=True, null=True)),
                ('completed_at', models.DateTimeField(blank=True, null=True)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='customer_information_requests', to='ocpp.charger')),
            ],
            options={
                'verbose_name': 'Customer Information Request',
                'verbose_name_plural': 'Customer Information Requests',
                'ordering': ['-created_at', '-pk'],
            },
        ),
        migrations.CreateModel(
            name='DisplayMessageNotification',
            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(max_length=64, verbose_name='OCPP message ID')),
                ('request_id', models.BigIntegerField(blank=True, null=True, verbose_name='Request ID')),
                ('tbc', models.BooleanField(default=False, verbose_name='To Be Continued')),
                ('raw_payload', models.JSONField(blank=True, default=dict)),
                ('received_at', models.DateTimeField(auto_now_add=True)),
                ('completed_at', models.DateTimeField(blank=True, null=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='display_message_notifications', to='ocpp.charger')),
            ],
            options={
                'verbose_name': 'Display Message Notification',
                'verbose_name_plural': 'Display Message Notifications',
                'ordering': ['-received_at', '-pk'],
            },
        ),
        migrations.CreateModel(
            name='CustomerInformationChunk',
            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(max_length=64, verbose_name='OCPP message ID')),
                ('request_id', models.BigIntegerField(blank=True, null=True, verbose_name='Request ID')),
                ('data', models.TextField(blank=True, default='')),
                ('tbc', models.BooleanField(default=False, verbose_name='To Be Continued')),
                ('raw_payload', models.JSONField(blank=True, default=dict)),
                ('received_at', models.DateTimeField(auto_now_add=True)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='customer_information_chunks', to='ocpp.charger')),
                ('request_record', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='chunks', to='ocpp.customerinformationrequest')),
            ],
            options={
                'verbose_name': 'Customer Information Chunk',
                'verbose_name_plural': 'Customer Information Chunks',
                'ordering': ['-received_at', '-pk'],
            },
        ),
        migrations.CreateModel(
            name='DisplayMessage',
            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.BigIntegerField(blank=True, null=True, verbose_name='Message ID')),
                ('priority', models.CharField(blank=True, max_length=32)),
                ('state', models.CharField(blank=True, max_length=32)),
                ('valid_from', models.DateTimeField(blank=True, null=True)),
                ('valid_to', models.DateTimeField(blank=True, null=True)),
                ('language', models.CharField(blank=True, max_length=16)),
                ('content', models.TextField(blank=True)),
                ('component_name', models.CharField(blank=True, max_length=200)),
                ('component_instance', models.CharField(blank=True, max_length=200)),
                ('variable_name', models.CharField(blank=True, max_length=200)),
                ('variable_instance', models.CharField(blank=True, max_length=200)),
                ('raw_payload', models.JSONField(blank=True, default=dict)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='display_messages', to='ocpp.charger')),
                ('notification', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='ocpp.displaymessagenotification')),
            ],
            options={
                'verbose_name': 'Display Message',
                'verbose_name_plural': 'Display Messages',
                'ordering': ['-created_at', '-pk'],
            },
        ),
        migrations.AddIndex(
            model_name='customerinformationrequest',
            index=models.Index(fields=['ocpp_message_id'], name='ocpp_custinfo_ocpp_idx'),
        ),
        migrations.AddIndex(
            model_name='customerinformationrequest',
            index=models.Index(fields=['charger', 'request_id'], name='ocpp_custinfo_req_idx'),
        ),
        migrations.AddIndex(
            model_name='displaymessagenotification',
            index=models.Index(fields=['ocpp_message_id'], name='ocpp_display_ocpp_idx'),
        ),
        migrations.AddIndex(
            model_name='displaymessagenotification',
            index=models.Index(fields=['charger', 'request_id'], name='ocpp_display_req_idx'),
        ),
        migrations.AddIndex(
            model_name='customerinformationchunk',
            index=models.Index(fields=['ocpp_message_id'], name='ocpp_custinfochunk_ocpp_idx'),
        ),
        migrations.AddIndex(
            model_name='customerinformationchunk',
            index=models.Index(fields=['charger', 'request_id'], name='ocpp_custinfochunk_req_idx'),
        ),
        migrations.AddIndex(
            model_name='displaymessage',
            index=models.Index(fields=['message_id'], name='ocpp_display_msg_idx'),
        ),
        migrations.AlterField(
            model_name='cpforwarder',
            name='enabled',
            field=models.BooleanField(default=True, help_text='Enable to forward eligible charge points to the remote node. Charge points must also have Export transactions enabled.'),
        ),
        migrations.AlterField(
            model_name='charger',
            name='export_transactions',
            field=models.BooleanField(default=True, help_text="Enable to share this charge point's transactions with remote nodes or export tools. Required for CP forwarders."),
        ),
        migrations.RunPython(
            code=enable_forwarders_and_exports,
            reverse_code=django.db.migrations.operations.special.RunPython.noop,
        ),
        migrations.CreateModel(
            name='CostUpdate',
            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_transaction_id', models.CharField(blank=True, default='', help_text='OCPP transaction identifier provided by the charge point.', max_length=128)),
                ('connector_id', models.PositiveIntegerField(blank=True, null=True, verbose_name='Connector ID')),
                ('total_cost', models.DecimalField(blank=True, decimal_places=3, max_digits=12, null=True, verbose_name='Total cost')),
                ('currency', models.CharField(blank=True, default='', max_length=8)),
                ('payload', models.JSONField(blank=True, default=dict)),
                ('reported_at', models.DateTimeField(default=django.utils.timezone.now)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='cost_updates', to='ocpp.charger', verbose_name='Charger')),
                ('transaction', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='cost_updates', to='ocpp.transaction', verbose_name='Transaction')),
            ],
            options={
                'verbose_name': 'Cost Update',
                'verbose_name_plural': 'Cost Updates',
                'ordering': ['-reported_at', '-created_at', '-pk'],
            },
        ),
        migrations.CreateModel(
            name='ClearedChargingLimitEvent',
            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, default='', max_length=120)),
                ('evse_id', models.PositiveIntegerField(blank=True, null=True)),
                ('charging_limit_source', models.CharField(blank=True, default='', max_length=120)),
                ('raw_payload', models.JSONField(blank=True, default=dict)),
                ('cleared_at', models.DateTimeField(auto_now_add=True)),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='cleared_charging_limits', to='ocpp.charger')),
            ],
            options={
                'verbose_name': 'Cleared Charging Limit Event',
                'verbose_name_plural': 'Cleared Charging Limit Events',
                'ordering': ['-cleared_at', '-pk'],
            },
        ),
        migrations.AddField(
            model_name='charger',
            name='last_charging_limit',
            field=models.JSONField(blank=True, default=dict),
        ),
        migrations.AddField(
            model_name='charger',
            name='last_charging_limit_at',
            field=models.DateTimeField(blank=True, null=True),
        ),
        migrations.AddField(
            model_name='charger',
            name='last_charging_limit_is_grid_critical',
            field=models.BooleanField(blank=True, null=True),
        ),
        migrations.AddField(
            model_name='charger',
            name='last_charging_limit_source',
            field=models.CharField(blank=True, default='', max_length=120),
        ),
        migrations.CreateModel(
            name='DeviceInventorySnapshot',
            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(blank=True, null=True, verbose_name='Request ID')),
                ('seq_no', models.BigIntegerField(blank=True, null=True, verbose_name='Sequence Number')),
                ('generated_at', models.DateTimeField(blank=True, null=True, verbose_name='Generated At')),
                ('tbc', models.BooleanField(default=False, verbose_name='To Be Continued')),
                ('raw_payload', models.JSONField(blank=True, default=dict)),
                ('reported_at', models.DateTimeField(auto_now_add=True, verbose_name='Reported at')),
                ('charger', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='device_inventory_snapshots', to='ocpp.charger')),
            ],
            options={
                'verbose_name': 'Device Inventory Snapshot',
                'verbose_name_plural': 'Device Inventory Snapshots',
                'ordering': ['-reported_at', '-pk'],
            },
        ),
        migrations.CreateModel(
            name='DeviceInventoryItem',
            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)),
                ('component_name', models.CharField(max_length=200, verbose_name='Component')),
                ('component_instance', models.CharField(blank=True, default='', max_length=200, verbose_name='Component Instance')),
                ('variable_name', models.CharField(max_length=200, verbose_name='Variable')),
                ('variable_instance', models.CharField(blank=True, default='', max_length=200, verbose_name='Variable Instance')),
                ('attributes', models.JSONField(blank=True, default=list)),
                ('characteristics', models.JSONField(blank=True, default=dict)),
                ('reported_at', models.DateTimeField(auto_now_add=True, verbose_name='Reported at')),
                ('snapshot', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='ocpp.deviceinventorysnapshot')),
            ],
            options={
                'verbose_name': 'Device Inventory Item',
                'verbose_name_plural': 'Device Inventory Items',
                'ordering': ['snapshot', 'component_name', 'variable_name', 'pk'],
            },
        ),
    ]
