feat(patching/import): ajout colonnes Resp Domaine DTS, Referent technique, Mode operatoire, Impacts, BDD - support nouveau format S07+ + Date au lieu de Jour
This commit is contained in:
parent
13a5625710
commit
488b5a980b
@ -23,24 +23,31 @@ from ..config import APP_NAME
|
|||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
templates = Jinja2Templates(directory="app/templates")
|
templates = Jinja2Templates(directory="app/templates")
|
||||||
|
|
||||||
# Colonnes attendues dans les feuilles Sxx (ordre indicatif, on matche par regex/lower)
|
# Colonnes attendues dans les feuilles Sxx (ordre = priorité, on matche par regex/lower)
|
||||||
|
# Le fichier 2026 a 12 variantes d'en-têtes selon la semaine
|
||||||
|
# (ancien format S02-S06, nouveau format DTS S07+)
|
||||||
KNOWN_COLUMNS = {
|
KNOWN_COLUMNS = {
|
||||||
"asset_name": [r"asset\s*name", r"\bnom\b"],
|
"asset_name": [r"asset\s*name", r"\bnom\b"],
|
||||||
"intervenant": [r"intervenant"],
|
"intervenant": [r"intervenant"],
|
||||||
"environnement": [r"environnement|environement"],
|
"environnement": [r"environnement|environement"],
|
||||||
"domaine": [r"^domaine"],
|
"domaine": [r"^domaine"],
|
||||||
"os": [r"^\s*os\s*$"],
|
"os": [r"^\s*os\s*$"],
|
||||||
"os_version": [r"version\s*os"],
|
"os_version": [r"version\s*os"], # matche "Version OS" et "Version OS->Nom"
|
||||||
"application_name": [r"application", r"logiciel"],
|
"application_name": [r"logiciel", r"application", r"^nom\s*complet$"],
|
||||||
"valideur_ra": [r"valideur"],
|
"valideur_ra": [r"valideur"],
|
||||||
|
"responsable_domaine_dts":[r"responsable\s*domaine"],
|
||||||
"description": [r"description"],
|
"description": [r"description"],
|
||||||
"assistant": [r"^assistant"],
|
"assistant": [r"^assistant"],
|
||||||
"commentaire": [r"commentaire|impact"],
|
"referent_technique": [r"r.f.rent\s*tech"],
|
||||||
|
"mode_operatoire": [r"mode\s*op.ratoire"],
|
||||||
|
"impacts": [r"^impact"],
|
||||||
|
"commentaire": [r"commentaire"],
|
||||||
|
"base_de_donnees": [r"base\s*de\s*donn"],
|
||||||
"duree_coupure": [r"dur.+coupure"],
|
"duree_coupure": [r"dur.+coupure"],
|
||||||
"jour": [r"^\s*jour\s*$|date\s*pr.+vis"],
|
"jour": [r"^\s*jour\s*$", r"^\s*date\s*$", r"date\s*pr.+vis"],
|
||||||
"heure": [r"^\s*heure"],
|
"heure": [r"^\s*heure"],
|
||||||
"pb_espace_disque": [r"espace\s*disque"],
|
"pb_espace_disque": [r"espace\s*disque"],
|
||||||
"date_patch_realise":[r"date\s*du?\s*patch.+r.+alis"],
|
"date_patch_realise": [r"date\s*du?\s*patch.+r.+alis"],
|
||||||
}
|
}
|
||||||
|
|
||||||
SHEET_WEEK_RE = re.compile(r"^S\s*0?(\d+)$", re.IGNORECASE)
|
SHEET_WEEK_RE = re.compile(r"^S\s*0?(\d+)$", re.IGNORECASE)
|
||||||
@ -228,9 +235,11 @@ async def import_sheet_json(request: Request, import_id: int, sheet_name: str,
|
|||||||
|
|
||||||
rows = db.execute(text("""
|
rows = db.execute(text("""
|
||||||
SELECT r.id, r.row_index, r.asset_name, r.intervenant, r.environnement,
|
SELECT r.id, r.row_index, r.asset_name, r.intervenant, r.environnement,
|
||||||
r.domaine, r.os, r.os_version, r.application_name, r.valideur_ra,
|
r.domaine, r.os, r.os_version, r.application_name,
|
||||||
r.description, r.assistant, r.commentaire, r.duree_coupure,
|
r.valideur_ra, r.responsable_domaine_dts,
|
||||||
r.jour, r.heure, r.pb_espace_disque, r.date_patch_realise,
|
r.description, r.assistant, r.referent_technique,
|
||||||
|
r.mode_operatoire, r.impacts, r.commentaire, r.base_de_donnees,
|
||||||
|
r.duree_coupure, r.jour, r.heure, r.pb_espace_disque, r.date_patch_realise,
|
||||||
r.server_id, s.hostname as resolved_hostname
|
r.server_id, s.hostname as resolved_hostname
|
||||||
FROM patch_planning_import_rows r
|
FROM patch_planning_import_rows r
|
||||||
LEFT JOIN servers s ON s.id = r.server_id
|
LEFT JOIN servers s ON s.id = r.server_id
|
||||||
@ -251,9 +260,14 @@ async def import_sheet_json(request: Request, import_id: int, sheet_name: str,
|
|||||||
"os_version": r.os_version,
|
"os_version": r.os_version,
|
||||||
"application_name": r.application_name,
|
"application_name": r.application_name,
|
||||||
"valideur_ra": r.valideur_ra,
|
"valideur_ra": r.valideur_ra,
|
||||||
|
"responsable_domaine_dts": r.responsable_domaine_dts,
|
||||||
"description": r.description,
|
"description": r.description,
|
||||||
"assistant": r.assistant,
|
"assistant": r.assistant,
|
||||||
|
"referent_technique": r.referent_technique,
|
||||||
|
"mode_operatoire": r.mode_operatoire,
|
||||||
|
"impacts": r.impacts,
|
||||||
"commentaire": r.commentaire,
|
"commentaire": r.commentaire,
|
||||||
|
"base_de_donnees": r.base_de_donnees,
|
||||||
"duree_coupure": r.duree_coupure,
|
"duree_coupure": r.duree_coupure,
|
||||||
"jour": r.jour.isoformat() if r.jour else None,
|
"jour": r.jour.isoformat() if r.jour else None,
|
||||||
"heure": r.heure,
|
"heure": r.heure,
|
||||||
@ -338,13 +352,17 @@ async def import_upload(request: Request, db=Depends(get_db),
|
|||||||
INSERT INTO patch_planning_import_rows (
|
INSERT INTO patch_planning_import_rows (
|
||||||
import_id, sheet_name, week_number, row_index,
|
import_id, sheet_name, week_number, row_index,
|
||||||
asset_name, intervenant, environnement, domaine, os, os_version,
|
asset_name, intervenant, environnement, domaine, os, os_version,
|
||||||
application_name, valideur_ra, description, assistant, commentaire,
|
application_name, valideur_ra, responsable_domaine_dts,
|
||||||
|
description, assistant, referent_technique, mode_operatoire, impacts,
|
||||||
|
commentaire, base_de_donnees,
|
||||||
duree_coupure, jour, heure, pb_espace_disque, date_patch_realise,
|
duree_coupure, jour, heure, pb_espace_disque, date_patch_realise,
|
||||||
raw_data, server_id
|
raw_data, server_id
|
||||||
) VALUES (
|
) VALUES (
|
||||||
:imp, :sn, :wn, :ri,
|
:imp, :sn, :wn, :ri,
|
||||||
:an, :it, :en, :do, :os, :ov,
|
:an, :it, :en, :do, :os, :ov,
|
||||||
:ap, :vr, :de, :as_, :co,
|
:ap, :vr, :rd,
|
||||||
|
:de, :as_, :rt, :mo, :im,
|
||||||
|
:co, :bdd,
|
||||||
:dc, :jr, :hr, :pb, :dpr,
|
:dc, :jr, :hr, :pb, :dpr,
|
||||||
:raw, :sid
|
:raw, :sid
|
||||||
)
|
)
|
||||||
@ -358,9 +376,14 @@ async def import_upload(request: Request, db=Depends(get_db),
|
|||||||
"ov": str(rec.get("os_version")) if rec.get("os_version") else None,
|
"ov": str(rec.get("os_version")) if rec.get("os_version") else None,
|
||||||
"ap": str(rec.get("application_name")) if rec.get("application_name") else None,
|
"ap": str(rec.get("application_name")) if rec.get("application_name") else None,
|
||||||
"vr": str(rec.get("valideur_ra")) if rec.get("valideur_ra") else None,
|
"vr": str(rec.get("valideur_ra")) if rec.get("valideur_ra") else None,
|
||||||
|
"rd": str(rec.get("responsable_domaine_dts")) if rec.get("responsable_domaine_dts") else None,
|
||||||
"de": str(rec.get("description")) if rec.get("description") else None,
|
"de": str(rec.get("description")) if rec.get("description") else None,
|
||||||
"as_": str(rec.get("assistant")) if rec.get("assistant") else None,
|
"as_": str(rec.get("assistant")) if rec.get("assistant") else None,
|
||||||
|
"rt": str(rec.get("referent_technique")) if rec.get("referent_technique") else None,
|
||||||
|
"mo": str(rec.get("mode_operatoire")) if rec.get("mode_operatoire") else None,
|
||||||
|
"im": str(rec.get("impacts")) if rec.get("impacts") else None,
|
||||||
"co": str(rec.get("commentaire")) if rec.get("commentaire") else None,
|
"co": str(rec.get("commentaire")) if rec.get("commentaire") else None,
|
||||||
|
"bdd": str(rec.get("base_de_donnees")) if rec.get("base_de_donnees") else None,
|
||||||
"dc": str(rec.get("duree_coupure")) if rec.get("duree_coupure") else None,
|
"dc": str(rec.get("duree_coupure")) if rec.get("duree_coupure") else None,
|
||||||
"jr": _coerce_date(rec.get("jour")),
|
"jr": _coerce_date(rec.get("jour")),
|
||||||
"hr": str(rec.get("heure")) if rec.get("heure") else None,
|
"hr": str(rec.get("heure")) if rec.get("heure") else None,
|
||||||
|
|||||||
@ -137,10 +137,16 @@
|
|||||||
<th class="text-left p-1">Env</th>
|
<th class="text-left p-1">Env</th>
|
||||||
<th class="text-left p-1">Domaine</th>
|
<th class="text-left p-1">Domaine</th>
|
||||||
<th class="text-left p-1">OS</th>
|
<th class="text-left p-1">OS</th>
|
||||||
|
<th class="text-left p-1">Version OS</th>
|
||||||
<th class="text-left p-1">Application</th>
|
<th class="text-left p-1">Application</th>
|
||||||
<th class="text-left p-1">Intervenant</th>
|
<th class="text-left p-1">Intervenant</th>
|
||||||
<th class="text-left p-1">Valideur RA</th>
|
<th class="text-left p-1">Valideur RA</th>
|
||||||
<th class="text-left p-1">Jour</th>
|
<th class="text-left p-1">Resp. Domaine DTS</th>
|
||||||
|
<th class="text-left p-1">Référent tech.</th>
|
||||||
|
<th class="text-left p-1">Mode op.</th>
|
||||||
|
<th class="text-left p-1">Impacts</th>
|
||||||
|
<th class="text-left p-1">BDD</th>
|
||||||
|
<th class="text-left p-1">Date</th>
|
||||||
<th class="text-left p-1">Heure</th>
|
<th class="text-left p-1">Heure</th>
|
||||||
<th class="text-left p-1">Coupure</th>
|
<th class="text-left p-1">Coupure</th>
|
||||||
<th class="text-left p-1">Pb disque</th>
|
<th class="text-left p-1">Pb disque</th>
|
||||||
@ -246,9 +252,15 @@
|
|||||||
+ '<td class="p-1">' + escapeHTML(r.environnement||'') + '</td>'
|
+ '<td class="p-1">' + escapeHTML(r.environnement||'') + '</td>'
|
||||||
+ '<td class="p-1">' + escapeHTML(r.domaine||'') + '</td>'
|
+ '<td class="p-1">' + escapeHTML(r.domaine||'') + '</td>'
|
||||||
+ '<td class="p-1">' + escapeHTML(r.os||'') + '</td>'
|
+ '<td class="p-1">' + escapeHTML(r.os||'') + '</td>'
|
||||||
|
+ '<td class="p-1">' + escapeHTML(r.os_version||'') + '</td>'
|
||||||
+ '<td class="p-1">' + escapeHTML(r.application_name||'') + '</td>'
|
+ '<td class="p-1">' + escapeHTML(r.application_name||'') + '</td>'
|
||||||
+ '<td class="p-1">' + escapeHTML(r.intervenant||'') + '</td>'
|
+ '<td class="p-1">' + escapeHTML(r.intervenant||'') + '</td>'
|
||||||
+ '<td class="p-1">' + escapeHTML(r.valideur_ra||'') + '</td>'
|
+ '<td class="p-1">' + escapeHTML(r.valideur_ra||'') + '</td>'
|
||||||
|
+ '<td class="p-1">' + escapeHTML(r.responsable_domaine_dts||'') + '</td>'
|
||||||
|
+ '<td class="p-1">' + escapeHTML(r.referent_technique||'') + '</td>'
|
||||||
|
+ '<td class="p-1">' + escapeHTML(r.mode_operatoire||'') + '</td>'
|
||||||
|
+ '<td class="p-1">' + escapeHTML(r.impacts||'') + '</td>'
|
||||||
|
+ '<td class="p-1">' + escapeHTML(r.base_de_donnees||'') + '</td>'
|
||||||
+ '<td class="p-1">' + escapeHTML(r.jour||'') + '</td>'
|
+ '<td class="p-1">' + escapeHTML(r.jour||'') + '</td>'
|
||||||
+ '<td class="p-1">' + escapeHTML(r.heure||'') + '</td>'
|
+ '<td class="p-1">' + escapeHTML(r.heure||'') + '</td>'
|
||||||
+ '<td class="p-1">' + escapeHTML(r.duree_coupure||'') + '</td>'
|
+ '<td class="p-1">' + escapeHTML(r.duree_coupure||'') + '</td>'
|
||||||
|
|||||||
12
migrate_planning_imports_v2.sql
Normal file
12
migrate_planning_imports_v2.sql
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
-- Migration v2 : ajout des colonnes manquantes dans patch_planning_import_rows
|
||||||
|
-- (variations d'en-têtes selon semaines : nouveau format DTS introduit en cours d'année)
|
||||||
|
-- Idempotent
|
||||||
|
|
||||||
|
ALTER TABLE public.patch_planning_import_rows
|
||||||
|
ADD COLUMN IF NOT EXISTS responsable_domaine_dts text,
|
||||||
|
ADD COLUMN IF NOT EXISTS referent_technique text,
|
||||||
|
ADD COLUMN IF NOT EXISTS mode_operatoire text,
|
||||||
|
ADD COLUMN IF NOT EXISTS impacts text,
|
||||||
|
ADD COLUMN IF NOT EXISTS base_de_donnees text;
|
||||||
|
|
||||||
|
-- Pas de nouveau GRANT nécessaire (la table est déjà accessible à patchcenter)
|
||||||
Loading…
Reference in New Issue
Block a user