diff --git a/app.json b/app.json index 9575a94..50ac6d7 100644 --- a/app.json +++ b/app.json @@ -3,8 +3,8 @@ "name": "Démat. Facturation DSI", "category": "SANTINOVA", "urls": { - "recette": "https://demat-facturation.recette.santinova-soft.org", - "prod": "https://demat-facturation.santinova-soft.org" + "recette": "https://demat-facturation-santinova.recette.santinova-soft.org", + "prod": "https://demat-facturation-santinova.santinova-soft.org" }, "containerName": "demat-facturation-app", "image": "images/demat-facturation-dsi.jpg", diff --git a/docker-compose.yml b/docker-compose.yml index 5759f6b..981ec2c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -59,7 +59,7 @@ services: JWT_SECRET: demat-facturation-jwt-secret-recette-2026 MISTRAL_API_KEY: ${MISTRAL_API_KEY:-} # Passerelle centralisée : le jeton reste dans l'environnement serveur. - REFERENTIEL_IA_URL: ${REFERENTIEL_IA_URL:-https://referentiel-ia.recette.santinova-soft.org} + REFERENTIEL_IA_URL: ${REFERENTIEL_IA_URL:-https://referentiel-ia-santinova.recette.santinova-soft.org} REFERENTIEL_IA_TOKEN: ${REFERENTIEL_IA_TOKEN:-} REFERENTIEL_IA_TOKEN_FILE: /run/secrets/referentiel_ia_token UPLOAD_DIR: /app/uploads @@ -95,7 +95,7 @@ services: priority: 100 labels: - "traefik.enable=true" - - "traefik.http.routers.demat-facturation.rule=Host(`${APP_DOMAIN:-demat-facturation.recette.santinova-soft.org}`)" + - "traefik.http.routers.demat-facturation.rule=Host(`demat-facturation.recette.santinova-soft.org`) || Host(`demat-facturation-santinova.recette.santinova-soft.org`)" - "traefik.http.routers.demat-facturation.entrypoints=websecure" - "traefik.http.routers.demat-facturation.tls.certresolver=letsencrypt" - "traefik.http.services.demat-facturation.loadbalancer.server.port=3000" diff --git a/scripts/web-import/README.md b/scripts/web-import/README.md index 2cbb71a..29137d3 100644 --- a/scripts/web-import/README.md +++ b/scripts/web-import/README.md @@ -23,7 +23,7 @@ Contenu de `config.json` : { "sfrLogin": "votre-login@sfr.fr", "sfrPassword": "votre-mot-de-passe", - "appUrl": "https://demat-facturation.santinova-soft.org", + "appUrl": "https://demat-facturation-santinova.santinova-soft.org", "apiToken": "votre-token-api-copié-depuis-lappli", "downloadDir": "/tmp/sfr-invoices", "processedFile": "/tmp/sfr-processed.json" @@ -34,7 +34,7 @@ Ou utiliser des variables d'environnement : ```bash export SFR_LOGIN=votre-login@sfr.fr export SFR_PASSWORD=votre-mot-de-passe -export APP_URL=https://demat-facturation.santinova-soft.org +export APP_URL=https://demat-facturation-santinova.santinova-soft.org export API_TOKEN=votre-token-api ``` diff --git a/scripts/web-import/sfr-connector.mjs b/scripts/web-import/sfr-connector.mjs index 4bd9c3d..8e4e3f1 100644 --- a/scripts/web-import/sfr-connector.mjs +++ b/scripts/web-import/sfr-connector.mjs @@ -1,16 +1,16 @@ /** * Connecteur SFR Pro - Script cron pour import automatique de factures - * + * * Prérequis sur le serveur LWS : * npm install playwright @playwright/test * npx playwright install chromium - * + * * Configuration : * Copier .env.example en .env et remplir les variables - * + * * Utilisation : * node sfr-connector.mjs - * + * * Cron (mensuel le 5 du mois à 8h) : * 0 8 5 * * /usr/bin/node /opt/web-import/sfr-connector.mjs >> /var/log/sfr-import.log 2>&1 */ @@ -33,7 +33,7 @@ const CONFIG = { login: process.env.SFR_LOGIN || '', password: process.env.SFR_PASSWORD || '', // URL de l'application de dématérialisation - appUrl: process.env.APP_URL || 'https://demat-facturation.santinova-soft.org', + appUrl: process.env.APP_URL || 'https://demat-facturation-santinova.santinova-soft.org', // Token API de la source web (récupéré depuis l'interface Connecteurs web) apiToken: process.env.API_TOKEN || '', // Dossier temporaire pour les PDFs téléchargés @@ -63,7 +63,7 @@ function saveProcessed(list) { async function pushInvoiceToApp(filePath, fileName) { const fileBuffer = fs.readFileSync(filePath); const fileBase64 = fileBuffer.toString('base64'); - + const body = JSON.stringify({ apiToken: CONFIG.apiToken, fileName, @@ -104,7 +104,7 @@ async function pushInvoiceToApp(filePath, fileName) { // ============ CONNECTEUR SFR ============ async function runSfrConnector() { log('Démarrage du connecteur SFR Pro'); - + if (!CONFIG.login || !CONFIG.password || !CONFIG.apiToken) { log('ERREUR : SFR_LOGIN, SFR_PASSWORD et API_TOKEN sont requis'); process.exit(1); @@ -140,14 +140,14 @@ async function runSfrConnector() { await page.fill('input[type="email"], input[name="login"], input[id*="login"], input[id*="email"]', CONFIG.login); await page.fill('input[type="password"], input[name="password"], input[id*="password"]', CONFIG.password); await page.click('button[type="submit"], input[type="submit"], button:has-text("Connexion"), button:has-text("Se connecter")'); - + await page.waitForNavigation({ waitUntil: 'networkidle', timeout: 15000 }).catch(() => {}); log('Connecté'); // 4. Naviguer vers la section factures // Adapter selon la structure réelle du site SFR Pro await page.goto(`${CONFIG.portalUrl}factures`, { waitUntil: 'networkidle', timeout: 15000 }).catch(() => {}); - + // Chercher les liens de factures PDF const invoiceLinks = await page.$$eval( 'a[href*=".pdf"], a[href*="facture"], a[href*="invoice"], a[download]', diff --git a/server/deploymentRouting.test.ts b/server/deploymentRouting.test.ts index eb9c10b..d210fa5 100644 --- a/server/deploymentRouting.test.ts +++ b/server/deploymentRouting.test.ts @@ -39,7 +39,7 @@ describe("routage et persistance de déploiement", () => { it("injecte uniquement les secrets serveur de la passerelle Référentiel IA", () => { const composeFile = readFileSync(join(process.cwd(), "docker-compose.yml"), "utf8"); - expect(composeFile).toContain("REFERENTIEL_IA_URL: ${REFERENTIEL_IA_URL:-https://referentiel-ia.recette.santinova-soft.org}"); + expect(composeFile).toContain("REFERENTIEL_IA_URL: ${REFERENTIEL_IA_URL:-https://referentiel-ia-santinova.recette.santinova-soft.org}"); expect(composeFile).toContain("REFERENTIEL_IA_TOKEN: ${REFERENTIEL_IA_TOKEN:-}"); expect(composeFile).toContain("REFERENTIEL_IA_TOKEN_FILE: /run/secrets/referentiel_ia_token"); expect(composeFile).toContain("file: /opt/manus-secrets/demat-facturation-referentiel-ia-token"); diff --git a/server/referentialIa.test.ts b/server/referentialIa.test.ts index 5ee9eae..e6b7b64 100644 --- a/server/referentialIa.test.ts +++ b/server/referentialIa.test.ts @@ -10,7 +10,7 @@ import { import { readSecretFile, resolveServerSecret } from "./_core/env"; const connection: ReferentielIaConnection = { - baseUrl: "https://referentiel-ia.recette.santinova-soft.org", + baseUrl: "https://referentiel-ia-santinova.recette.santinova-soft.org", token: "test-token", }; @@ -63,7 +63,7 @@ describe("Référentiel IA", () => { receivedUrl = String(url); receivedInit = init; if (callCount === 1) { - expect(receivedUrl).toBe("https://referentiel-ia.recette.santinova-soft.org/api/integration/v1/recommendations"); + expect(receivedUrl).toBe("https://referentiel-ia-santinova.recette.santinova-soft.org/api/integration/v1/recommendations"); expect(JSON.parse(String(receivedInit?.body))).toEqual({ useCase: "texte", optimizeCost: true, @@ -84,7 +84,7 @@ describe("Référentiel IA", () => { }, ); - expect(receivedUrl).toBe("https://referentiel-ia.recette.santinova-soft.org/api/integration/v1/invoke"); + expect(receivedUrl).toBe("https://referentiel-ia-santinova.recette.santinova-soft.org/api/integration/v1/invoke"); expect(receivedInit?.headers).toMatchObject({ authorization: "Bearer test-token" }); expect(JSON.parse(String(receivedInit?.body))).toMatchObject({ engineSlug: "santino-expert",