# Generated by Django 5.2.8 on 2026-05-21 13:51 import common.storages import django.contrib.gis.db.models.fields import django.db.models.deletion import interventions.models from django.conf import settings from django.db import migrations, models class Migration(migrations.Migration): initial = True dependencies = [ ('assets', '0003_initial'), ('common', '0002_initial'), ('contenttypes', '0002_remove_content_type_name'), ('contracts', '0001_initial'), ('documents', '0001_initial'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( name='GuidedOperationData', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('data', models.JSONField(default=dict, verbose_name='Données')), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ], options={ 'verbose_name': "Données d'opérations guidées", 'verbose_name_plural': "Données d'opérations guidées", }, ), migrations.CreateModel( name='GuidedOperationTemplate', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('slug', models.SlugField(help_text='Identifiant unique. Doit correspondre au nom du fichier HTML: guided_operations/{slug}.html', max_length=100, unique=True, verbose_name='Slug')), ('name_fr', models.CharField(max_length=255, verbose_name='Nom (FR)')), ('name_nl', models.CharField(blank=True, max_length=255, verbose_name='Nom (NL)')), ('description', models.TextField(blank=True, verbose_name='Description')), ], options={ 'verbose_name': "Template d'opérations guidées", 'verbose_name_plural': "Templates d'opérations guidées", 'ordering': ['name_fr'], }, ), migrations.CreateModel( name='InterventionSequence', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('current_number', models.PositiveIntegerField(default=0)), ], ), migrations.CreateModel( name='MeasurementDefinition', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=255)), ('value_type', models.CharField(choices=[('numeric', 'Numérique'), ('duration', 'Durée (hh:mm:ss)'), ('datetime', 'Date et heure')], default='numeric', max_length=20, verbose_name='Type de valeur')), ('unit', models.CharField(blank=True, max_length=50)), ('min_value', models.DecimalField(blank=True, decimal_places=2, max_digits=8, null=True)), ('max_value', models.DecimalField(blank=True, decimal_places=2, max_digits=8, null=True)), ('min_duration', models.DurationField(blank=True, null=True, verbose_name='Durée min')), ('max_duration', models.DurationField(blank=True, null=True, verbose_name='Durée max')), ('min_datetime', models.DateTimeField(blank=True, null=True, verbose_name='Date/heure min')), ('max_datetime', models.DateTimeField(blank=True, null=True, verbose_name='Date/heure max')), ], ), migrations.CreateModel( name='OperationStatus', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('label_fr', models.CharField(max_length=50)), ('label_nl', models.CharField(max_length=50)), ('value', models.CharField(max_length=50)), ('order', models.PositiveIntegerField(default=0)), ('bootstrap_icon', models.CharField(blank=True, help_text='Icône Bootstrap (ex: bi-check-circle)', max_length=50, null=True)), ('bootstrap_color', models.CharField(blank=True, choices=[('primary', 'Primary'), ('secondary', 'Secondary'), ('success', 'Success'), ('danger', 'Danger'), ('warning', 'Warning'), ('info', 'Info'), ('light', 'Light'), ('dark', 'Dark')], help_text='Couleur Bootstrap', max_length=20, null=True)), ('requires_comment', models.BooleanField(default=False, help_text='Si coché, un commentaire sera requis lorsque ce statut est sélectionné', verbose_name='Commentaire obligatoire')), ], options={ 'ordering': ['order'], }, ), migrations.CreateModel( name='OperationStatusSet', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=255, unique=True)), ], ), migrations.CreateModel( name='OperationType', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('code', models.CharField(max_length=100, unique=True)), ('name_fr', models.CharField(max_length=255)), ('name_nl', models.CharField(max_length=255)), ], ), migrations.CreateModel( name='SourceCategory', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name_fr', models.CharField(max_length=200)), ('name_nl', models.CharField(max_length=200)), ('description', models.TextField(blank=True, null=True)), ('has_reference', models.BooleanField(default=False)), ('is_active', models.BooleanField(default=True)), ], options={ 'ordering': ['name_fr'], }, ), migrations.CreateModel( name='GuidedOperationMedia', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('field_key', models.CharField(blank=True, default='', help_text='Identifie la question à laquelle ce média est rattaché (vide = général).', max_length=100, verbose_name='Clé de question')), ('file', models.FileField(storage=common.storages.PrivateMediaStorage(), upload_to=interventions.models.guided_operation_media_upload_path, verbose_name='Fichier')), ('media_type', models.CharField(choices=[('photo', 'Photo'), ('document', 'Document')], default='photo', max_length=20, verbose_name='Type de média')), ('description', models.CharField(blank=True, max_length=255, verbose_name='Description')), ('uploaded_at', models.DateTimeField(auto_now_add=True)), ('guided_data', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='media', to='interventions.guidedoperationdata', verbose_name='Données guidées')), ('uploaded_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='uploaded_guided_media', to=settings.AUTH_USER_MODEL)), ], options={ 'verbose_name': "Média d'opérations guidées", 'verbose_name_plural': "Médias d'opérations guidées", 'ordering': ['field_key', '-uploaded_at'], }, ), migrations.AddField( model_name='guidedoperationdata', name='guided_template', field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='data_entries', to='interventions.guidedoperationtemplate', verbose_name='Template guidé'), ), migrations.CreateModel( name='Intervention', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('code', models.CharField(blank=True, db_index=True, max_length=50, unique=True)), ('title', models.CharField(max_length=200)), ('lon', models.FloatField(blank=True, null=True)), ('lat', models.FloatField(blank=True, null=True)), ('address', models.CharField(blank=True, max_length=500, null=True)), ('location_code', models.CharField(blank=True, max_length=500, null=True)), ('status', models.CharField(choices=[('in_preparation', 'En préparation'), ('to_be_approved', 'A approuver'), ('to_be_planned', 'A planifier'), ('to_be_processed', 'A traiter'), ('assigned', 'Pris en charge'), ('in_progress', 'Démarré'), ('on_pause', 'En pause'), ('finished', 'Terminé'), ('processed', 'Traité'), ('to_be_corrected', 'A corriger'), ('corrected', 'Corrigé'), ('validated', 'Validé'), ('invoiced', 'Comptabilisé'), ('closed', 'Finalisé'), ('canceled', 'Annulé')], default='in_preparation')), ('status_order', models.IntegerField(default=1)), ('pause_reason', models.CharField(blank=True, choices=[('reschedule', 'Intervention à replanifier'), ('order_material', 'Matériel à commander'), ('treated_in_next_maintenance', 'Traité dans le prochain entretien'), ('other', 'Autre')], max_length=50, null=True)), ('pause_reason_other', models.CharField(blank=True, max_length=255, null=True)), ('cancellation_type', models.CharField(blank=True, choices=[('duplicate', 'Doublon'), ('to_redirect', 'A rediriger'), ('not_our_assets', 'Pas sous notre gestion'), ('non_relevant', 'Non-relevant'), ('other', 'Autre')], max_length=50, null=True)), ('priority', models.CharField(choices=[('1', 'Urgent'), ('2', 'Elevé'), ('3', 'Normal'), ('4', 'Bas')], default='3')), ('description', models.TextField(blank=True, null=True)), ('maintain_type', models.CharField(choices=[('corrective', 'Maintenance corrective'), ('preventive', 'Maintenance préventive'), ('ameliorative', 'Maintenance améliorative')], default='corrective')), ('type', models.CharField(blank=True, choices=[('fixing', 'Dépannage'), ('repair', 'Réparation'), ('repair_post_preventive', 'Réparation post préventif'), ('replace', 'Remplacement'), ('care', 'Entretien'), ('control', 'Contrôle'), ('inspection', 'Inspection'), ('build', 'Construction')], null=True)), ('origin_type', models.CharField(choices=[('damage', 'Avarie'), ('defect', 'Défaut/Panne'), ('demand', 'Demande')], default='damage')), ('begin_time', models.DateTimeField(blank=True, null=True)), ('end_time', models.DateTimeField(blank=True, null=True)), ('planned_begin_time', models.DateTimeField(blank=True, null=True)), ('planned_end_time', models.DateTimeField(blank=True, null=True)), ('expected_begin_time', models.DateTimeField(blank=True, null=True)), ('expected_end_time', models.DateTimeField(blank=True, null=True)), ('source_detail', models.CharField(blank=True, null=True)), ('source_ref', models.CharField(blank=True, null=True)), ('origin_prego_nbr', models.IntegerField(blank=True, null=True)), ('origin_fms_nbr', models.IntegerField(blank=True, null=True)), ('pmo_number', models.IntegerField(blank=True, null=True, verbose_name='Numéro PMO')), ('creation_time', models.DateTimeField(auto_now_add=True)), ('last_modified_time', models.DateTimeField(auto_now=True, null=True)), ('transmission_time', models.DateTimeField(blank=True, null=True)), ('init_call_confirmed_time', models.DateTimeField(blank=True, null=True)), ('init_call_received', models.BooleanField(default=False)), ('init_description', models.TextField(blank=True, null=True)), ('osiris', models.IntegerField(blank=True, null=True)), ('linked_folder', models.CharField(blank=True, max_length=1024, null=True)), ('intervention_sheet', models.FileField(blank=True, null=True, storage=common.storages.PrivateMediaStorage(), upload_to=interventions.models.intervention_sheet_upload_path)), ('geom', django.contrib.gis.db.models.fields.MultiPolygonField(blank=True, null=True, srid=3812)), ('period_validation_enabled', models.BooleanField(default=False)), ('period_number', models.PositiveIntegerField(default=1)), ('period_is_final', models.BooleanField(default=False)), ('created_by_provider', models.BooleanField(default=False, help_text='Indique que cette intervention a été créée par un prestataire externe.', verbose_name='Créée par le prestataire')), ('processed_via_other_intervention', models.BooleanField(default=False, help_text='Indique que le traitement de cette intervention est réalisé via une autre intervention.', verbose_name='Traitement via une autre intervention')), ('reason_for_correction', models.TextField(blank=True, help_text='Raison pour laquelle une correction est demandée.', null=True, verbose_name='Raison de la correction')), ('correction_details', models.TextField(blank=True, help_text='Détails de ce qui a été corrigé.', null=True, verbose_name='Détails de la correction')), ('is_checked', models.BooleanField(default=False, help_text="Indique si l'intervention a été vérifiée par un utilisateur habilité.", verbose_name='Vérifiée')), ('follow_up_performed', models.CharField(blank=True, choices=[('ok', 'OK'), ('attention', 'Points d’attention'), ('not_ok', 'Not OK')], default=None, help_text='Résultat du contrôle / rapport de suivi.', max_length=20, null=True, verbose_name='Résultat du contrôle')), ('asset_category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.assetcategory')), ('assigned_member', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assigned_interventions', to='contracts.companymember')), ('assigned_provider', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assigned_interventions', to='contracts.company')), ('assigned_team', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assigned_interventions', to='contracts.companyteam')), ('contract', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='interventions', to='contracts.contract')), ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='created_interventions', to=settings.AUTH_USER_MODEL)), ('guided_operation_template', models.ForeignKey(blank=True, help_text="Assigné automatiquement lors du choix d'un template d'opérations avec un template guidé associé.", null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='interventions', to='interventions.guidedoperationtemplate', verbose_name="Template d'opérations guidées")), ('last_modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='modified_interventions', to=settings.AUTH_USER_MODEL)), ('order', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='interventions', to='contracts.contractorder')), ('thematic', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='common.thematic')), ], options={ 'ordering': ['-creation_time'], }, ), migrations.AddField( model_name='guidedoperationdata', name='intervention', field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='guided_operation_data', to='interventions.intervention', verbose_name='Intervention'), ), migrations.CreateModel( name='InterventionAsset', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('object_id', models.PositiveIntegerField()), ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')), ('intervention', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='interventions.intervention')), ], ), migrations.CreateModel( name='InterventionContractPost', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('quantity', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True, verbose_name='Quantité')), ('comment', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Commentaire')), ('control_status', models.CharField(blank=True, choices=[('validated', 'Approuvé'), ('refused', 'Refusé'), ('pending', 'A justifier')], null=True)), ('control_comment', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Commentaire de contrôle')), ('contract_post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contracts.contractpost')), ('intervention', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='interv_contract_posts', to='interventions.intervention')), ], options={ 'ordering': ['contract_post__order_number'], }, ), migrations.CreateModel( name='InterventionDocument', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('description', models.TextField(blank=True, null=True, verbose_name='Description du document')), ('status', models.CharField(choices=[('active', 'Actif'), ('archived', 'Archivé')], default='active')), ('file', models.FileField(max_length=255, storage=common.storages.PrivateMediaStorage(), upload_to=interventions.models.intervention_document_upload_path, verbose_name='Fichier')), ('thumbnail', models.ImageField(blank=True, max_length=255, null=True, storage=common.storages.PrivateMediaStorage(), upload_to=interventions.models.intervention_document_upload_path)), ('upload_date', models.DateTimeField(auto_now_add=True, null=True, verbose_name="Date d'upload")), ('intervention', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='documents', to='interventions.intervention', verbose_name='Intervention associée')), ('managed_document', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='%(app_label)s_%(class)s_sources', to='documents.manageddocument')), ('uploaded_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='uploaded_intervention_documents', to=settings.AUTH_USER_MODEL)), ], options={ 'ordering': ['upload_date'], 'abstract': False, }, ), migrations.CreateModel( name='InterventionEmailLog', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('email_type', models.CharField(choices=[('transmission', 'Envoi de la fiche'), ('reminder', 'Rappel'), ('modification', 'Modification'), ('cancellation', 'Annulation'), ('daily_summary', 'Résumé journalier')], max_length=50)), ('sent_at', models.DateTimeField(auto_now_add=True)), ('recipients', models.TextField(help_text='Liste des destinataires (séparés par des virgules)')), ('subject', models.CharField(blank=True, max_length=500, null=True)), ('detail', models.TextField(blank=True, help_text='Détails supplémentaires (ex: motif de modification)', null=True)), ('success', models.BooleanField(default=True)), ('error_message', models.TextField(blank=True, null=True)), ('intervention', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='email_logs', to='interventions.intervention')), ('sent_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='intervention_emails_sent', to=settings.AUTH_USER_MODEL)), ], options={ 'verbose_name': "Historique d'envoi d'email", 'verbose_name_plural': "Historiques d'envois d'emails", 'ordering': ['-sent_at'], }, ), migrations.CreateModel( name='InterventionNote', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('content', models.TextField()), ('note_time', models.DateTimeField()), ('note_type', models.CharField(choices=[('work_done', 'Travaux réalisés'), ('material', 'Matériel à prévoir'), ('equipment', 'Matériel utilisé'), ('important_info', 'Information importante'), ('origin', 'Origine'), ('comment', 'Commentaire'), ('other', 'Autre')], default='work_done', max_length=32, verbose_name='Type de note')), ('updated_at', models.DateTimeField(blank=True, null=True)), ('intervention', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notes', to='interventions.intervention')), ('note_author', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='interventions_notes', to=settings.AUTH_USER_MODEL)), ('updated_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='updated_interventions_notes', to=settings.AUTH_USER_MODEL)), ], ), migrations.CreateModel( name='InterventionOccupation', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('minutes', models.PositiveIntegerField()), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_intervention_occupations', to=settings.AUTH_USER_MODEL)), ('intervention', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='occupations', to='interventions.intervention')), ('member', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='occupations', to='contracts.companymember')), ('updated_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='updated_intervention_occupations', to=settings.AUTH_USER_MODEL)), ], options={ 'ordering': ['created_at'], }, ), migrations.CreateModel( name='InterventionPlanificationTimeLine', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('event_time', models.DateTimeField()), ('event_type', models.CharField(choices=[('expected_begin', 'Début prévu'), ('expected_end', 'Fin prévue'), ('planned_begin', 'Début planifié'), ('planned_end', 'Fin planifiée'), ('plan_other', 'Autre')], default='plan_other')), ('event_description', models.CharField(max_length=1024)), ('event_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='planned_actions', to=settings.AUTH_USER_MODEL)), ('intervention', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='planned_events', to='interventions.intervention')), ], options={ 'ordering': ['event_time'], }, ), migrations.CreateModel( name='InterventionRealizationTimeLine', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('event_time', models.DateTimeField()), ('event_type', models.CharField(choices=[('real_begin', "Démarrage de l'intervention"), ('real_end', "Fin de l'intervention"), ('real_pause', "Pause de l'intervention"), ('real_resume', "Reprise de l'intervention"), ('real_other', 'Autre')], default='real_other')), ('event_description', models.CharField(max_length=1024)), ('event_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='realized_actions', to=settings.AUTH_USER_MODEL)), ('intervention', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='realized_events', to='interventions.intervention')), ], options={ 'ordering': ['event_time'], }, ), migrations.CreateModel( name='InterventionTimeLine', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('event_time', models.DateTimeField()), ('event_type', models.CharField(choices=[('creation', 'Création'), ('status_change', 'Changement de statut'), ('transfer', 'Transfert')])), ('from_status', models.CharField(blank=True, choices=[('in_preparation', 'En préparation'), ('to_be_approved', 'A approuver'), ('to_be_planned', 'A planifier'), ('to_be_processed', 'A traiter'), ('assigned', 'Pris en charge'), ('in_progress', 'Démarré'), ('on_pause', 'En pause'), ('finished', 'Terminé'), ('processed', 'Traité'), ('to_be_corrected', 'A corriger'), ('corrected', 'Corrigé'), ('validated', 'Validé'), ('invoiced', 'Comptabilisé'), ('closed', 'Finalisé'), ('canceled', 'Annulé')], null=True)), ('to_status', models.CharField(blank=True, choices=[('in_preparation', 'En préparation'), ('to_be_approved', 'A approuver'), ('to_be_planned', 'A planifier'), ('to_be_processed', 'A traiter'), ('assigned', 'Pris en charge'), ('in_progress', 'Démarré'), ('on_pause', 'En pause'), ('finished', 'Terminé'), ('processed', 'Traité'), ('to_be_corrected', 'A corriger'), ('corrected', 'Corrigé'), ('validated', 'Validé'), ('invoiced', 'Comptabilisé'), ('closed', 'Finalisé'), ('canceled', 'Annulé')], null=True)), ('event_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='actions', to=settings.AUTH_USER_MODEL)), ('intervention', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='events', to='interventions.intervention')), ], options={ 'ordering': ['event_time'], }, ), migrations.CreateModel( name='Operation', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name_fr', models.CharField(max_length=255)), ('name_nl', models.CharField(max_length=255)), ('comment', models.TextField(blank=True)), ('measured_value', models.DecimalField(blank=True, decimal_places=2, max_digits=8, null=True)), ('measured_duration', models.DurationField(blank=True, null=True, verbose_name='Durée mesurée')), ('measured_datetime', models.DateTimeField(blank=True, null=True, verbose_name='Date/heure mesurée')), ('is_not_applicable', models.BooleanField(default=False, verbose_name='Non applicable')), ('order', models.PositiveIntegerField(default=0)), ('template_group', models.CharField(blank=True, max_length=255, null=True, verbose_name='Groupe de template')), ('asset_object_id', models.PositiveIntegerField(blank=True, null=True)), ('is_custom', models.BooleanField(default=False, verbose_name='Opération personnalisée')), ('created_at', models.DateTimeField(auto_now_add=True, null=True)), ('is_generic', models.BooleanField(default=False, verbose_name='Opération générique')), ('requires_photo', models.BooleanField(default=False, verbose_name='Requiert une photo')), ('asset_content_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='operations', to='contenttypes.contenttype')), ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_operations', to=settings.AUTH_USER_MODEL)), ('intervention', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='operations', to='interventions.intervention')), ('measurement_definition', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='interventions.measurementdefinition')), ('status', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='interventions.operationstatus')), ('status_set', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='interventions.operationstatusset')), ], options={ 'ordering': ['template_group', 'order'], }, ), migrations.CreateModel( name='OperationPhoto', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('photo', models.ImageField(storage=common.storages.PrivateMediaStorage(), upload_to=interventions.models.operation_photo_upload_path, verbose_name='Photo')), ('thumbnail', models.ImageField(blank=True, max_length=255, null=True, storage=common.storages.PrivateMediaStorage(), upload_to=interventions.models.operation_photo_upload_path)), ('uploaded_at', models.DateTimeField(auto_now_add=True, verbose_name="Date d'upload")), ('description', models.CharField(blank=True, max_length=255, null=True, verbose_name='Description')), ('operation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='photos', to='interventions.operation')), ('uploaded_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='uploaded_operation_photos', to=settings.AUTH_USER_MODEL)), ], options={ 'verbose_name': "Photo d'opération", 'verbose_name_plural': "Photos d'opérations", 'ordering': ['-uploaded_at'], }, ), migrations.AddField( model_name='operationstatus', name='status_set', field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='statuses', to='interventions.operationstatusset'), ), migrations.CreateModel( name='OperationTemplate', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('code', models.CharField(blank=True, max_length=100, null=True)), ('name', models.CharField(max_length=255, unique=True)), ('description', models.TextField(blank=True)), ('categories', models.ManyToManyField(blank=True, help_text='Si défini, les opérations équipement ne seront créées que pour les assets de ces catégories.', related_name='operation_templates', to='assets.assetcategory', verbose_name='Catégories')), ('guided_template', models.ForeignKey(blank=True, help_text="Si défini, ce template d'opérations déclenchera automatiquement l'assignation du template guidé à l'intervention préventive.", null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='operation_templates', to='interventions.guidedoperationtemplate', verbose_name='Template guidé associé')), ('thematic', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='common.thematic')), ], ), migrations.AddField( model_name='intervention', name='equipment_operation_templates', field=models.ManyToManyField(blank=True, related_name='interventions_equipment', to='interventions.operationtemplate'), ), migrations.CreateModel( name='OperationTemplateItem', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('code', models.CharField(blank=True, max_length=100, null=True)), ('name_fr', models.CharField(max_length=255)), ('name_nl', models.CharField(max_length=255)), ('order', models.PositiveIntegerField(default=0)), ('is_generic', models.BooleanField(default=False, help_text='Si coché, cette opération sera ajoutée une seule fois par intervention. Sinon, elle sera répétée pour chaque équipement.', verbose_name='Opération générique')), ('requires_photo', models.BooleanField(default=False, verbose_name='Requiert une photo')), ('measurement_definition', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='interventions.measurementdefinition')), ('status_set', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='interventions.operationstatusset')), ('template', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='interventions.operationtemplate')), ('operation_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='interventions.operationtype')), ], options={ 'ordering': ['order'], }, ), migrations.AddField( model_name='intervention', name='source_category', field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='interventions.sourcecategory'), ), migrations.CreateModel( name='Symptom', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('code', models.CharField(blank=True, help_text='Code unique optionnel pour identifier le symptôme (ex: pour les raccourcis).', max_length=50, null=True, unique=True)), ('name_fr', models.CharField(max_length=255)), ('name_nl', models.CharField(max_length=255)), ('priority', models.CharField(choices=[('1', 'Urgent'), ('2', 'Elevé'), ('3', 'Normal'), ('4', 'Bas')], default='3')), ('check_priority', models.BooleanField(default=False, help_text='Indique si la priorité doit être vérifiée.')), ('origin_type', models.CharField(blank=True, choices=[('damage', 'Avarie'), ('defect', 'Défaut/Panne'), ('demand', 'Demande')], default='damage', null=True)), ('maintenance_type', models.CharField(blank=True, choices=[('infra', 'TL - Infrastructure'), ('controller', 'TL - Contrôleur de traffic'), ('electromeca', 'TU - Electromécanique'), ('civil_engineering', 'TU - Génie civil'), ('equipments', 'ITS - Équipement'), ('clean', 'Clean - Nettoyage'), ('collection', 'Clean - Ramassage'), ('other', 'Autre')], help_text="Type de maintenance concerné (ex: 'controller' pour les contrôleurs de traffic).", max_length=50, null=True)), ('order_number', models.IntegerField(blank=True, null=True)), ('is_active', models.BooleanField(default=True)), ('recommended_next_status', models.CharField(blank=True, choices=[('in_preparation', 'En préparation'), ('to_be_approved', 'A approuver'), ('to_be_planned', 'A planifier'), ('to_be_processed', 'A traiter'), ('assigned', 'Pris en charge'), ('in_progress', 'Démarré'), ('on_pause', 'En pause'), ('finished', 'Terminé'), ('processed', 'Traité'), ('to_be_corrected', 'A corriger'), ('corrected', 'Corrigé'), ('validated', 'Validé'), ('invoiced', 'Comptabilisé'), ('closed', 'Finalisé'), ('canceled', 'Annulé')], default='to_be_processed', max_length=50, null=True)), ('internal_notification_emails', models.CharField(blank=True, help_text="Liste d'emails pour les notifications internes.", max_length=1000, null=True)), ('asset_categories', models.ManyToManyField(blank=True, related_name='symptoms', to='assets.assetcategory')), ('contract', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='contracts.contract')), ('provider', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='contracts.company')), ('teams', models.ManyToManyField(blank=True, help_text='Équipes désignées pour prendre en charge les observations liées à ce symptôme.', related_name='symptoms', to='contracts.companyteam', verbose_name='Équipes désignées')), ('thematic', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='common.thematic')), ], options={ 'ordering': ['thematic', 'order_number'], }, ), migrations.CreateModel( name='ReflexSheet', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('title_fr', models.CharField(max_length=255)), ('title_nl', models.CharField(max_length=255)), ('comment_fr', models.TextField(blank=True, null=True)), ('comment_nl', models.TextField(blank=True, null=True)), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('is_active', models.BooleanField(default=True)), ('asset_category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.assetcategory')), ('contact_persons', models.ManyToManyField(blank=True, related_name='reflex_sheets', to=settings.AUTH_USER_MODEL)), ('thematic', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='common.thematic')), ('symptoms', models.ManyToManyField(related_name='reflex_sheets', to='interventions.symptom')), ], options={ 'ordering': ['thematic', 'title_fr'], }, ), migrations.AddField( model_name='intervention', name='symptom', field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='interventions.symptom'), ), migrations.CreateModel( name='SymptomRecommendation', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('icon', models.CharField(blank=True, max_length=255, null=True)), ('text_fr', models.TextField()), ('text_nl', models.TextField()), ('order_number', models.PositiveIntegerField(blank=True, null=True)), ('document', models.FileField(blank=True, null=True, storage=common.storages.PrivateMediaStorage(), upload_to='symptom_recommendations/')), ('confirm_call', models.BooleanField(default=False)), ('symptom', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='recommendations', to='interventions.symptom')), ], options={ 'ordering': ['order_number'], }, ), migrations.CreateModel( name='ContractPauseReasonAssignment', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('pause_reason', models.CharField(choices=[('reschedule', 'Intervention à replanifier'), ('order_material', 'Matériel à commander'), ('treated_in_next_maintenance', 'Traité dans le prochain entretien'), ('other', 'Autre')], max_length=50, verbose_name='Motif de pause')), ('assigned_member', models.ForeignKey(blank=True, help_text="Membre à qui réassigner automatiquement l'intervention lors d'une mise en pause avec ce motif. Laisser vide pour désassigner.", null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pause_reason_assignments', to='contracts.companymember', verbose_name='Membre assigné')), ('contract', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pause_reason_assignments', to='contracts.contract', verbose_name='Contrat')), ], options={ 'verbose_name': 'Réassignation automatique sur pause', 'verbose_name_plural': 'Réassignations automatiques sur pause', 'unique_together': {('contract', 'pause_reason')}, }, ), migrations.CreateModel( name='InterventionLink', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('link_type', models.CharField(choices=[('related', 'Lien manuel'), ('repair', 'Réparation')], default='related', max_length=32)), ('created_at', models.DateTimeField(auto_now_add=True)), ('first', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='links_as_first', to='interventions.intervention')), ('second', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='links_as_second', to='interventions.intervention')), ], options={ 'ordering': ['-created_at'], 'constraints': [models.UniqueConstraint(fields=('first', 'second', 'link_type'), name='uniq_intervention_link'), models.CheckConstraint(condition=models.Q(('first', models.F('second')), _negated=True), name='prevent_self_link')], }, ), migrations.CreateModel( name='InterventionLocation', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('object_id', models.PositiveIntegerField(db_index=True)), ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')), ('intervention', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='locations', to='interventions.intervention')), ], options={ 'indexes': [models.Index(fields=['content_type', 'object_id'], name='ix_ct_obj'), models.Index(fields=['intervention', 'content_type'], name='ix_intv_ct')], 'constraints': [models.UniqueConstraint(fields=('intervention', 'content_type', 'object_id'), name='uniq_intervention_location')], }, ), migrations.CreateModel( name='InterventionPostPeriodQuantity', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('period_number', models.PositiveIntegerField()), ('quantity', models.DecimalField(decimal_places=2, max_digits=10)), ('validated_at', models.DateTimeField()), ('status', models.CharField(choices=[('pending', 'En attente'), ('validated', 'Validé'), ('invoiced', 'Facturé')], default='pending', max_length=20, verbose_name='Statut')), ('contract_post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='period_quantities', to='contracts.contractpost')), ('intervention', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='period_quantities', to='interventions.intervention')), ('validated_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), ], options={ 'ordering': ['intervention', 'period_number', 'contract_post__order_number'], 'unique_together': {('intervention', 'contract_post', 'period_number')}, }, ), migrations.AlterUniqueTogether( name='operationstatus', unique_together={('status_set', 'value')}, ), migrations.CreateModel( name='OperationTemplateAssetModelFilter', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('asset_model_object_id', models.PositiveIntegerField(verbose_name='ID du modèle')), ('asset_model_content_type', models.ForeignKey(limit_choices_to={'app_label': 'assets'}, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype', verbose_name="Type de modèle d'asset")), ('template', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='asset_model_filters', to='interventions.operationtemplate', verbose_name='Template')), ], options={ 'verbose_name': "Filtre de modèle d'asset", 'verbose_name_plural': "Filtres de modèles d'assets", 'unique_together': {('template', 'asset_model_content_type', 'asset_model_object_id')}, }, ), migrations.AddIndex( model_name='intervention', index=models.Index(fields=['status', 'thematic'], name='interventio_status_e47e89_idx'), ), migrations.AddIndex( model_name='intervention', index=models.Index(fields=['status', 'creation_time'], name='interventio_status_1befac_idx'), ), migrations.AddIndex( model_name='intervention', index=models.Index(fields=['thematic', 'creation_time'], name='interventio_themati_9c147f_idx'), ), migrations.AddIndex( model_name='intervention', index=models.Index(fields=['thematic', 'status', 'maintain_type'], name='intv_thematic_status_mtype_idx'), ), migrations.AddIndex( model_name='intervention', index=models.Index(fields=['contract', 'status'], name='intv_contract_status_idx'), ), migrations.AddIndex( model_name='intervention', index=models.Index(fields=['begin_time', 'planned_begin_time', 'expected_begin_time', 'maintain_type'], name='intv_chart_begin_maintain_idx'), ), ]