devices: import du manquant + fix liens SS.device orphelins + catch-up quotidien
- import_devices_and_enrich.py : creds via env (secret hors repo) + SKIP_ENRICH (devices seuls).
Rattrapage : 1160 devices importés (tous les devices F courants sont maintenant en Service Equipment).
- FIX bug d'import : rename_all_doctypes.py avait renommé Service Equipment (EQ-{md5}→EQP-{seq})
sans cascader vers Service Subscription.device → 6980 liens orphelins ("Could not find Device: EQ-…",
bloquait les saves pleine-doc). 5241 remappés via legacy_device_id+md5 (UPDATE PG direct).
Résiduel 1739 = device supprimé côté F (1584 Actif / 155 Annulé) → décision NULL vs relink en attente.
- Récurrence : tickets-daily.sh importe désormais AUSSI les devices (SKIP_ENRICH=1), quotidien 04:30.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
d8052bb17c
commit
8a51925da8
|
|
@ -26,9 +26,9 @@ now_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
|
|||
# LEGACY DB CONNECTION
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
conn = pymysql.connect(
|
||||
host="legacy-db",
|
||||
host=os.environ.get("LEGACY_HOST", "10.100.80.100"),
|
||||
user="facturation",
|
||||
password="*******",
|
||||
password=os.environ.get("LEGACY_PW", ""), # secret via env (jamais commité)
|
||||
database="gestionclient",
|
||||
cursorclass=pymysql.cursors.DictCursor
|
||||
)
|
||||
|
|
@ -225,6 +225,11 @@ if batch:
|
|||
|
||||
print("Inserted {} new devices ({} already existed)".format(inserted, skipped))
|
||||
|
||||
if os.environ.get("SKIP_ENRICH", "0") == "1":
|
||||
print("SKIP_ENRICH=1 → devices importés, on saute l'enrichissement (Phase 3) + Phase 4")
|
||||
conn.close()
|
||||
import sys; sys.exit(0)
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# PHASE 3: Enrich Service Locations with fibre data
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
|
|
|||
|
|
@ -52,13 +52,23 @@ Réconciliation visible dans OPS : page **/sync-legacy** → carte « Réconcili
|
|||
|
||||
## Fichiers
|
||||
|
||||
## Tickets → Issue (cron QUOTIDIEN séparé)
|
||||
## Catch-up QUOTIDIEN — tickets + appareils (cron séparé)
|
||||
|
||||
`tickets-daily.sh` (cron `30 4 * * *`) lance `migrate_tickets.py` (idempotent, skip par
|
||||
`legacy_ticket_id`) pour n'importer que les nouveaux tickets. Séparé de `run.sh` (horaire) car
|
||||
le scan de 252k tickets est trop lourd pour l'horaire. Le canonique de `migrate_tickets.py` est
|
||||
`scripts/migration/` ; en déployer une copie dans `/opt/targo-sync/`. Messages des tickets *closed*
|
||||
non importés (deferred ; `import_ticket_msgs.py` au besoin).
|
||||
`tickets-daily.sh` (cron `30 4 * * *`) lance deux imports idempotents (skip par `legacy_*_id`,
|
||||
n'importent que les nouveaux) :
|
||||
- **`migrate_tickets.py`** → `tabIssue` (skip par `legacy_ticket_id`). Messages des tickets *closed*
|
||||
non importés (deferred ; `import_ticket_msgs.py` au besoin).
|
||||
- **`import_devices_and_enrich.py`** (avec `SKIP_ENRICH=1` = devices seulement) → `tabService Equipment`
|
||||
(skip par `legacy_device_id`). Sans `SKIP_ENRICH`, enrichit aussi les Service Location (fibre/OLT/VLAN).
|
||||
|
||||
Séparé de `run.sh` (horaire) car les scans complets (252k tickets / 11k devices) sont trop lourds
|
||||
pour l'horaire. Canoniques dans `scripts/migration/` ; en déployer une copie dans `/opt/targo-sync/`.
|
||||
|
||||
⚠️ **Bug d'import historique corrigé 2026-07-06** : `rename_all_doctypes.py` a renommé les
|
||||
`Service Equipment` (`EQ-{md5}` → `EQP-{seq}`) SANS mettre à jour `Service Subscription.device`
|
||||
→ 6980 liens orphelins (`Could not find Device: EQ-…`, bloquait les saves pleine-doc Frappe).
|
||||
5241 remappés (via `legacy_device_id`+md5) ; 1739 résiduels pointaient un device supprimé côté F
|
||||
(à trancher : NULL vs relink au device courant du lieu). Voir mémoire `feedback_device_hierarchy`.
|
||||
|
||||
## 🔐 Secrets — JAMAIS dans le repo
|
||||
|
||||
|
|
@ -73,5 +83,7 @@ Ne **jamais** committer une copie prod d'un script qui aurait le mot de passe en
|
|||
| `run.sh` | Orchestrateur cron horaire (4 étapes DAG) |
|
||||
| `sync_services_incremental.py` | Service Location (delivery) + Service Subscription (service) : création + prix + **statut (fix fantômes raffiné)** |
|
||||
| `sync_invoices_incremental.py` | Sales Invoice (miroir des factures F ; statut reflétant F) |
|
||||
| `tickets-daily.sh` | Wrapper cron quotidien → `migrate_tickets.py` (secret via `secrets.env`) |
|
||||
| `tickets-daily.sh` | Wrapper cron quotidien → `migrate_tickets.py` + `import_devices_and_enrich.py` (secret via `secrets.env`) |
|
||||
| `migrate_tickets.py` | (déployé depuis `scripts/migration/`) tickets F → Issue |
|
||||
| `import_devices_and_enrich.py` | (déployé depuis `scripts/migration/`) devices F → Service Equipment |
|
||||
| `secrets.env` | **Hôte seulement, non versionné** : `LEGACY_PW=…` |
|
||||
|
|
|
|||
|
|
@ -1,25 +1,34 @@
|
|||
#!/bin/bash
|
||||
# Import QUOTIDIEN incrémental des tickets F → ERPNext Issue.
|
||||
# migrate_tickets.py est idempotent (skip par legacy_ticket_id) : ne crée que les nouveaux.
|
||||
# Complète le rattrapage 2026-07-06. Séparé du cron horaire run.sh (le scan de 252k tickets
|
||||
# est trop lourd pour l'horaire ; quotidien suffit — les tickets s'accumulent lentement).
|
||||
# Catch-up QUOTIDIEN legacy → ERPNext : tickets (Issue) + appareils (Service Equipment).
|
||||
# Scripts idempotents (skip par legacy_*_id) : n'importent que les nouveaux.
|
||||
# Séparé de run.sh (horaire) car les scans complets (252k tickets / 11k devices) sont lourds.
|
||||
# (Nom de fichier conservé pour la stabilité du crontab.)
|
||||
#
|
||||
# Déploiement (hôte) :
|
||||
# scp scripts/migration/migrate_tickets.py root@<prod>:/opt/targo-sync/migrate_tickets.py
|
||||
# scp scripts/targo-sync/tickets-daily.sh root@<prod>:/opt/targo-sync/ && chmod +x /opt/targo-sync/tickets-daily.sh
|
||||
# scp scripts/migration/migrate_tickets.py scripts/migration/import_devices_and_enrich.py root@<prod>:/opt/targo-sync/
|
||||
# scp scripts/targo-sync/tickets-daily.sh root@<prod>:/opt/targo-sync/ && chmod +x /opt/targo-sync/tickets-daily.sh
|
||||
# echo 'LEGACY_PW=<mdp F>' > /opt/targo-sync/secrets.env && chmod 600 /opt/targo-sync/secrets.env # secret HORS repo
|
||||
# crontab: 30 4 * * * /opt/targo-sync/tickets-daily.sh
|
||||
set -uo pipefail
|
||||
DIR=/opt/targo-sync
|
||||
LOG="$DIR/tickets-sync.log"
|
||||
[ -f "$LOG" ] && tail -n 2000 "$LOG" > "$LOG.tmp" 2>/dev/null && mv "$LOG.tmp" "$LOG"
|
||||
[ -f "$LOG" ] && tail -n 3000 "$LOG" > "$LOG.tmp" 2>/dev/null && mv "$LOG.tmp" "$LOG"
|
||||
exec >> "$LOG" 2>&1
|
||||
echo "===== $(date -Is) tickets-daily ====="
|
||||
echo "===== $(date -Is) daily-catchup (tickets + appareils) ====="
|
||||
exec 9>"$DIR/.tickets.lock"
|
||||
flock -n 9 || { echo "déjà en cours, skip"; exit 0; }
|
||||
# secret (LEGACY_PW) chargé depuis un fichier hôte non versionné
|
||||
[ -f "$DIR/secrets.env" ] && . "$DIR/secrets.env"
|
||||
[ -f "$DIR/secrets.env" ] && set -a && . "$DIR/secrets.env" && set +a
|
||||
LH="${LEGACY_HOST:-10.100.80.100}"
|
||||
|
||||
echo "-- tickets → Issue --"
|
||||
docker cp "$DIR/migrate_tickets.py" erpnext-backend-1:/tmp/migrate_tickets.py 2>/dev/null
|
||||
docker exec -e LEGACY_PW="${LEGACY_PW:-}" -e LEGACY_HOST="${LEGACY_HOST:-10.100.80.100}" -e PG_HOST=db \
|
||||
erpnext-backend-1 /home/frappe/frappe-bench/env/bin/python /tmp/migrate_tickets.py 2>&1 | tail -12
|
||||
docker exec -e LEGACY_PW="${LEGACY_PW:-}" -e LEGACY_HOST="$LH" -e PG_HOST=db \
|
||||
erpnext-backend-1 /home/frappe/frappe-bench/env/bin/python /tmp/migrate_tickets.py 2>&1 | tail -6
|
||||
|
||||
echo "-- appareils → Service Equipment (device-only) --"
|
||||
docker cp "$DIR/import_devices_and_enrich.py" erpnext-backend-1:/tmp/import_devices.py 2>/dev/null
|
||||
docker exec -e LEGACY_PW="${LEGACY_PW:-}" -e LEGACY_HOST="$LH" -e SKIP_ENRICH=1 \
|
||||
erpnext-backend-1 /home/frappe/frappe-bench/env/bin/python /tmp/import_devices.py 2>&1 | tail -4
|
||||
|
||||
echo "done $(date -Is)"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user