]> git.digitality.be Git - pdw25-26/commitdiff
Mise à jour price pour shema db demande par stephane
authorValentin Hulin <e23743@eps-marche.be>
Sat, 28 Feb 2026 20:45:54 +0000 (21:45 +0100)
committerValentin Hulin <e23743@eps-marche.be>
Sat, 28 Feb 2026 20:45:54 +0000 (21:45 +0100)
Wallette/server/modules/price/repositories/pair.repository.js
Wallette/server/modules/price/repositories/price.repository.js
Wallette/server/modules/price/routes/api.router.js
Wallette/server/modules/price/server.js [deleted file]

index 484251b9c02ec486b5f7ecb7c8019f5c8a1a7243..609b549025d50a5238699549b707629b020722cd 100644 (file)
@@ -3,11 +3,13 @@ import { db } from "../db.js";
 /**
  * Accepte:
  * - BTC/EUR, BTC_USDT, BTC-USDT, "btc eur"
- * Et match la DB qui stocke pair_code = BTC_EUR etc.
+ * Et match la DB qui stocke pair_code = BTC/EUR etc.
  */
 export async function getActivePairIdByCode(pairCode) {
   const raw = String(pairCode || "").trim().toUpperCase();
-  const normalized = raw.replace(/\s+/g, "").replace(/[-/]/g, "_");
+  // IMPORTANT: la DB du projet stocke la paire AVEC le slash (ex: "BTC/EUR").
+  // On ne convertit donc plus "/" (ni "-") en "_".
+  const normalized = raw.replace(/\s+/g, "");
 
   const [rows] = await db.execute(
     `
index 6dec8cbd18cf25c454832bfacb3a54eb9350ee62..0218a6769de80e7633e8d10a082223b6a06f5a9b 100644 (file)
@@ -2,15 +2,19 @@ import { db } from "../db.js";
 import crypto from "crypto";
 
 /**
- * Insère / met à jour une BOUGIE OHLC (5 minutes) dans la table existante.
- * - interval_sec = 300
- * - timestamp_ms = début du bucket (arrondi)
- * - open = premier prix du bucket
- * - high/low = extrêmes du bucket
- * - close = dernier prix du bucket
+ * Schéma officiel du projet (table: price_points)
+ * Colonnes utilisées:
+ * - current_price
+ * - volume_24h
+ * - candle_close
+ * (+ métadonnées habituelles: price_id, pair_id, source, timestamp_ms, created_at_ms)
+ */
+
+/**
+ * Insère un point de prix.
  *
- * ⚠️ Pour que high/low varient, il faut appeler insertPricePoint
- * plus souvent que toutes les 5 minutes (ex: toutes les 10–30s).
+ * NOTE: On n'utilise pas de colonnes OHLC (open/high/low/close) car elles n'existent
+ * pas dans le schéma du projet.
  */
 export async function insertPricePoint({
   pair_id,
@@ -30,100 +34,38 @@ export async function insertPricePoint({
   if (!Number.isFinite(price) || price <= 0) throw new Error("current_price invalide (>0)");
   if (!src) throw new Error("source obligatoire");
 
-  const intervalSec = 300; // 5 minutes
-
-  // ✅ bucket start (début de la bougie)
-  const bucketStart = Math.floor(ts / (intervalSec * 1000)) * (intervalSec * 1000);
-  const bucketEnd = bucketStart + (intervalSec * 1000) - 1;
-
-  const closeValue = candle_close != null ? Number(candle_close) : price;
-  if (!Number.isFinite(closeValue) || closeValue <= 0) {
-    throw new Error("candle_close invalide (>0)");
-  }
-
   const vol = volume_24h == null ? null : Number(volume_24h);
   if (vol != null && (!Number.isFinite(vol) || vol < 0)) {
-    throw new Error("volume invalide (>=0)");
+    throw new Error("volume_24h invalide (>=0)");
   }
 
-  // ✅ Cherche une bougie existante DANS le bucket (même si timestamp_ms n'est pas arrondi)
-  const [existing] = await db.execute(
-    `
-    SELECT price_id, open_price, high_price, low_price, close_price, timestamp_ms
-    FROM price_points
-    WHERE pair_id = ?
-      AND source = ?
-      AND interval_sec = ?
-      AND timestamp_ms BETWEEN ? AND ?
-    ORDER BY timestamp_ms ASC
-    LIMIT 1
-    `,
-    [pid, src, intervalSec, bucketStart, bucketEnd]
-  );
-
-  // 2) Si pas de bougie -> on crée une nouvelle
-  if (existing.length === 0) {
-    const priceId = crypto.randomUUID();
-
-    await db.execute(
-      `
-      INSERT INTO price_points (
-        price_id,
-        pair_id,
-        source,
-        interval_sec,
-        timestamp_ms,
-        open_price,
-        high_price,
-        low_price,
-        close_price,
-        volume,
-        created_at_ms
-      )
-      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
-      `,
-      [
-        priceId,
-        pid,
-        src,
-        intervalSec,
-        bucketStart,
-        price,      // open
-        price,      // high
-        price,      // low
-        closeValue, // close
-        vol,
-        Date.now()
-      ]
-    );
-    return;
+  const closeValue = candle_close == null ? price : Number(candle_close);
+  if (!Number.isFinite(closeValue) || closeValue <= 0) {
+    throw new Error("candle_close invalide (>0)");
   }
 
-  // 3) Sinon -> update OHLC (open ne change pas)
-  const row = existing[0];
-  const prevHigh = Number(row.high_price);
-  const prevLow = Number(row.low_price);
-
-  const newHigh = Number.isFinite(prevHigh) ? Math.max(prevHigh, price) : price;
-  const newLow = Number.isFinite(prevLow) ? Math.min(prevLow, price) : price;
+  const priceId = crypto.randomUUID();
 
   await db.execute(
     `
-    UPDATE price_points
-    SET timestamp_ms = ?,      -- ✅ on "recalle" la bougie sur le bucketStart
-        high_price = ?,
-        low_price = ?,
-        close_price = ?,
-        volume = ?,
-        created_at_ms = ?
-    WHERE price_id = ?
+    INSERT INTO price_points (
+      price_id,
+      pair_id,
+      source,
+      timestamp_ms,
+      current_price,
+      volume_24h,
+      candle_close,
+      created_at_ms
+    )
+    VALUES (?, ?, ?, ?, ?, ?, ?, ?)
     `,
-    [bucketStart, newHigh, newLow, closeValue, vol, Date.now(), row.price_id]
+    [priceId, pid, src, ts, price, vol, closeValue, Date.now()]
   );
 }
 
 /**
- * Prix courant = dernière bougie (close_price)
+ * Prix courant = dernier point (ORDER BY timestamp_ms DESC, created_at_ms DESC)
  */
 export async function getCurrentPrice(pair_id) {
   const pid = Number(pair_id);
@@ -133,11 +75,9 @@ export async function getCurrentPrice(pair_id) {
     SELECT
       source,
       timestamp_ms,
-      open_price,
-      high_price,
-      low_price,
-      close_price,
-      volume
+      current_price,
+      volume_24h,
+      candle_close
     FROM price_points
     WHERE pair_id = ?
     ORDER BY timestamp_ms DESC, created_at_ms DESC
@@ -152,18 +92,14 @@ export async function getCurrentPrice(pair_id) {
   return {
     source: r.source,
     timestamp_ms: r.timestamp_ms,
-    current_price: r.close_price,
-    open_price: r.open_price,
-    high_price: r.high_price,
-    low_price: r.low_price,
-    close_price: r.close_price,
-    volume_24h: r.volume ?? null,
-    candle_close: r.close_price
+    current_price: r.current_price,
+    volume_24h: r.volume_24h ?? null,
+    candle_close: r.candle_close ?? null
   };
 }
 
 /**
- * Historique = dernières bougies (OHLC)
+ * Historique = derniers points de prix.
  */
 export async function getPriceHistory(pair_id, limit = 200) {
   const pid = Number(pair_id);
@@ -174,11 +110,9 @@ export async function getPriceHistory(pair_id, limit = 200) {
     SELECT
       source,
       timestamp_ms,
-      open_price,
-      high_price,
-      low_price,
-      close_price,
-      volume
+      current_price,
+      volume_24h,
+      candle_close
     FROM price_points
     WHERE pair_id = ?
     ORDER BY timestamp_ms DESC, created_at_ms DESC
@@ -190,12 +124,8 @@ export async function getPriceHistory(pair_id, limit = 200) {
   return rows.reverse().map((r) => ({
     source: r.source,
     timestamp_ms: r.timestamp_ms,
-    current_price: r.close_price,
-    open_price: r.open_price,
-    high_price: r.high_price,
-    low_price: r.low_price,
-    close_price: r.close_price,
-    volume_24h: r.volume ?? null,
-    candle_close: r.close_price
+    current_price: r.current_price,
+    volume_24h: r.volume_24h ?? null,
+    candle_close: r.candle_close ?? null
   }));
-}
\ No newline at end of file
+}
index e0e16ae358d6b15f6f8a8e9df5fe431afed8310c..999c494865a758cc3c3069c6d22e4a911c5c21fb 100644 (file)
@@ -70,11 +70,8 @@ router.get("/price/current", async (req, res) => {
       source: row.source,
       timestamp_ms: row.timestamp_ms,
       current_price: row.current_price,
-      open_price: row.open_price,
-      high_price: row.high_price,
-      low_price: row.low_price,
-      close_price: row.close_price,
-      volume_24h: row.volume_24h ?? null
+      volume_24h: row.volume_24h ?? null,
+      candle_close: row.candle_close ?? null
     });
   } catch (err) {
     return fail(res, 500, "DB_ERROR", "Erreur lecture prix courant", err.message);
diff --git a/Wallette/server/modules/price/server.js b/Wallette/server/modules/price/server.js
deleted file mode 100644 (file)
index 566194c..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-// =========================================================
-// PRICE SERVICE - Serveur standalone
-// =========================================================
-// Ce fichier encapsule le module price
-// en microservice Express indépendant sur port 3001.
-//
-// USAGE : node modules/price/server.js (depuis Wallette/server/)
-// PORT  : process.env.PRICE_PORT || 3001
-// =========================================================
-
-import cors from 'cors';
-import dotenv from 'dotenv';
-import express from 'express';
-import path from 'path';
-import { fileURLToPath } from 'url';
-
-// Charger .env depuis Wallette/server/.env
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = path.dirname(__filename);
-dotenv.config({ path: path.resolve(__dirname, '../../.env') });
-
-// IMPORTANT : dotenv doit être chargé AVANT l'import du router
-// car db.js lit process.env au moment de l'import
-const { default: priceApiRouter } = await import('./routes/api.router.js');
-
-const PORT = process.env.PRICE_PORT || 3001;
-
-const app = express();
-app.use(cors());
-app.use(express.json());
-app.use(express.static(path.join(__dirname, 'public')));
-
-// ─── Health check (requis par le gateway) ────────────────
-app.get('/health', (req, res) => {
-    res.json({ ok: true, service: 'price-service', port: PORT });
-});
-
-// ─── Routes API price ─────────────────────────────────────
-// Le router expose /price/current, /price/history...
-// On le monte sur /api pour que le gateway route /api/price/* correctement
-app.use('/api', priceApiRouter);
-
-// ─── 404 ─────────────────────────────────────────────────
-app.use((req, res) => {
-    res.status(404).json({ ok: false, error: { code: 'NOT_FOUND', message: 'Route non trouvée' } });
-});
-
-// ─── Démarrage ────────────────────────────────────────────
-app.listen(PORT, () => {
-    console.log(`
-    ╔══════════════════════════════════════════╗
-    ║          PRICE SERVICE                   ║
-    ║  HTTP : http://localhost:${PORT}              ║
-    ║  → /health                  = OK         ║
-    ║  → /api/price/current?pair= = prix       ║
-    ║  → /api/price/history?pair= = historique ║
-    ╚══════════════════════════════════════════╝`);
-});