180 lines
6.8 KiB
Python
180 lines
6.8 KiB
Python
"""
|
|
Commande Django pour créer les commandes mensuelles 2026.
|
|
|
|
Pour chaque mois de mars à décembre 2026, crée 3 commandes dans un contrat donné :
|
|
- Appels <Mois> 2026
|
|
- Réparations <Mois> 2026
|
|
- Préventif <Mois> 2026
|
|
|
|
Vérifie l'existence avant d'insérer (idempotent).
|
|
|
|
Usage :
|
|
python manage.py create_monthly_orders_2026 --contract <contract_number>
|
|
python manage.py create_monthly_orders_2026 --contract <contract_number> --dry-run
|
|
"""
|
|
|
|
from django.core.management.base import BaseCommand, CommandError
|
|
from django.utils.translation import override as translation_override
|
|
from datetime import date
|
|
|
|
from contracts.models import Contract, ContractOrder
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Données de référence
|
|
# ---------------------------------------------------------------------------
|
|
|
|
MONTHS = [
|
|
# (numéro, nom_affichage, préposition)
|
|
(3, "Mars", "de mars"),
|
|
(4, "Avril", "d'avril"),
|
|
(5, "Mai", "de mai"),
|
|
(6, "Juin", "de juin"),
|
|
(7, "Juillet", "de juillet"),
|
|
(8, "Août", "d'août"),
|
|
(9, "Septembre", "de septembre"),
|
|
(10, "Octobre", "d'octobre"),
|
|
(11, "Novembre", "de novembre"),
|
|
(12, "Décembre", "de décembre"),
|
|
]
|
|
|
|
YEAR = 2026
|
|
|
|
# Modèle de commande : (suffixe_code, gabarit_description)
|
|
ORDER_TEMPLATES = [
|
|
("Appels", "Appels du mois {prep} {year}"),
|
|
("Réparations", "Réparations du mois {prep} {year}"),
|
|
("Préventif", "Interventions préventives du mois {prep} {year}"),
|
|
]
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Commande
|
|
# ---------------------------------------------------------------------------
|
|
|
|
class Command(BaseCommand):
|
|
help = (
|
|
"Crée les 3 commandes mensuelles (Appels / Réparations / Préventif) "
|
|
"pour chaque mois de mars à décembre 2026 dans le contrat spécifié."
|
|
)
|
|
|
|
def add_arguments(self, parser):
|
|
parser.add_argument(
|
|
"--contract",
|
|
required=True,
|
|
metavar="CONTRACT_NUMBER",
|
|
help="Numéro du contrat cible (ex: 2024-MAINT-001).",
|
|
)
|
|
parser.add_argument(
|
|
"--dry-run",
|
|
action="store_true",
|
|
default=False,
|
|
help="Simule sans écrire en base de données.",
|
|
)
|
|
parser.add_argument(
|
|
"--status",
|
|
default="pending",
|
|
metavar="STATUS",
|
|
help=(
|
|
"Statut des commandes créées. "
|
|
"Valeurs possibles : pending, sent, completed, invoiced, paid, cancelled. "
|
|
"(défaut : pending)"
|
|
),
|
|
)
|
|
|
|
def handle(self, *args, **options):
|
|
contract_number = options["contract"]
|
|
dry_run = options["dry_run"]
|
|
status = options["status"]
|
|
|
|
# Forcer le français pour les éventuelles traductions Django
|
|
with translation_override("fr"):
|
|
try:
|
|
contract = Contract.objects.get(contract_number=contract_number)
|
|
except Contract.DoesNotExist:
|
|
# Afficher les contrats disponibles pour aider l'utilisateur
|
|
available = list(
|
|
Contract.objects.values_list("contract_number", flat=True).order_by("contract_number")
|
|
)
|
|
raise CommandError(
|
|
f"Contrat « {contract_number} » introuvable.\n"
|
|
f"Contrats disponibles : {', '.join(available) if available else '(aucun)'}"
|
|
)
|
|
|
|
self.stdout.write(
|
|
self.style.SUCCESS(f"\nContrat trouvé : {contract}\n")
|
|
)
|
|
|
|
if dry_run:
|
|
self.stdout.write(self.style.WARNING("⚠ Mode simulation (--dry-run) : aucune donnée ne sera écrite.\n"))
|
|
|
|
created_count = 0
|
|
skipped_count = 0
|
|
|
|
for month_num, month_name, month_prep in MONTHS:
|
|
# Dates : 1er du mois → 1er du mois suivant (ou 1er janvier 2027 pour décembre)
|
|
order_date = date(YEAR, month_num, 1)
|
|
if month_num == 12:
|
|
delivery_date = date(YEAR + 1, 1, 1)
|
|
else:
|
|
delivery_date = date(YEAR, month_num + 1, 1)
|
|
|
|
self.stdout.write(f"\n--- {month_name} {YEAR} ---")
|
|
|
|
for prefix, desc_template in ORDER_TEMPLATES:
|
|
order_code = f"{prefix} {month_name} {YEAR}"
|
|
description = desc_template.format(prep=month_prep, year=YEAR)
|
|
|
|
# Vérification de l'existence (case-insensitive sur order_code)
|
|
existing = ContractOrder.objects.filter(
|
|
contract=contract,
|
|
order_code__iexact=order_code,
|
|
).first()
|
|
|
|
if existing:
|
|
self.stdout.write(
|
|
self.style.WARNING(
|
|
f" ⏭ EXISTANT — {existing.order_code!r} (id={existing.pk})"
|
|
)
|
|
)
|
|
skipped_count += 1
|
|
else:
|
|
if dry_run:
|
|
self.stdout.write(
|
|
self.style.SUCCESS(
|
|
f" ✔ À CRÉER — code={order_code!r} | desc={description!r}"
|
|
f" | commande={order_date} | livraison={delivery_date}"
|
|
)
|
|
)
|
|
else:
|
|
obj = ContractOrder.objects.create(
|
|
contract=contract,
|
|
order_code=order_code,
|
|
description=description,
|
|
order_date=order_date,
|
|
delivery_date=delivery_date,
|
|
order_status=status,
|
|
)
|
|
self.stdout.write(
|
|
self.style.SUCCESS(
|
|
f" ✔ CRÉÉ — {obj.order_code!r} (id={obj.pk})"
|
|
)
|
|
)
|
|
created_count += 1
|
|
|
|
# Résumé
|
|
self.stdout.write("\n" + "=" * 60)
|
|
if dry_run:
|
|
self.stdout.write(
|
|
self.style.WARNING(
|
|
f"Simulation terminée : {created_count} commande(s) à créer, "
|
|
f"{skipped_count} déjà existante(s)."
|
|
)
|
|
)
|
|
else:
|
|
self.stdout.write(
|
|
self.style.SUCCESS(
|
|
f"Terminé : {created_count} commande(s) créée(s), "
|
|
f"{skipped_count} déjà existante(s) (ignorée(s))."
|
|
)
|
|
)
|