Preuve · code, extrait

backend/flexylead-update-sale.mjs

Dépôt jeremy-flexylead/flexylead-crm · commit ccbbaa07870e0f786729003dd6f8862e4bcc8256 · dossier de production synchronisé le 14 septembre 2026 à 08 h 46

Extrait tel qu'à ce commit : lignes 216–278, sur 781 (numérotation d'origine, 30 lignes de contexte autour de chaque citation) · fichier intégral sur GitHub (dépôt privé, accès requis)

Lignes citées par l'audit : 246–248

63 lignes reproduites · ← retour à l'audit · catalogue des preuves

216    ["revenue_cents_snapshot", "number"],
217    ["revenue_currency", "text"],
218    ["revenue_rule_id", "text"],
219    ["validated_at", "datetime"],
220  ]) {
221    if (columns.has(name)) continue;
222    try {
223      await context.call("tables", "tables_alter", { name: "ventes", add: { name, type, nullable: true } });
224    } catch (err) {
225      if (!/already exists/i.test(String(err?.message || err))) throw err;
226    }
227  }
228  await ensureTable(context, AUDIT_TABLE, [
229    ["request_id", "text", false], ["sale_id", "number", false], ["sale_local_id", "text", true],
230    ["commercial_id", "text", false], ["actor_auth_user_id", "text", false],
231    ["previous_version", "text", false], ["before_state", "json", false], ["after_state", "json", false],
232    ["status", "text", false], ["occurred_at", "datetime", false], ["applied_at", "datetime", true],
233    ["error", "text", true],
234  ]);
235  await ensureTable(context, CLAIM_TABLE, [
236    ["request_id", "text", false], ["contract_key", "text", false], ["commercial_id", "text", false],
237    ["actor_auth_user_id", "text", false], ["status", "text", false], ["expires_at", "datetime", true],
238  ]);
239}
240
241async function ensureTable(context, name, columns) {
242  try {
243    await context.call("tables", "tables_create", {
244      name,
245      columns: columns.map(([columnName, type, nullable]) => ({ name: columnName, type, nullable })),
246    });
247  } catch (err) {
248    if (!/already exists/i.test(String(err?.message || err))) throw err;
249  }
250}
251
252async function getSale(context, body) {
253  const rowId = Number(body?.sale_row_id || 0);
254  if (rowId) {
255    const got = await context.call("tables", "rows_get", { table: "ventes", id: rowId });
256    if (got?.found) return got.row;
257  }
258  const localId = clean(body?.sale_local_id);
259  if (!localId) return null;
260  const found = await context.call("tables", "rows_search", {
261    table: "ventes", where: [{ col: "local_id", op: "eq", value: localId }], limit: 1,
262  });
263  return found?.rows?.[0] || null;
264}
265
266async function getOffer(context, id) {
267  if (!id) return null;
268  const found = await context.call("tables", "rows_search", {
269    table: "offres", where: [{ col: "local_id", op: "eq", value: id }], limit: 1,
270  });
271  if (found?.rows?.[0]) return found.rows[0];
272  const rowId = Number(id);
273  if (!rowId) return null;
274  const got = await context.call("tables", "rows_get", { table: "offres", id: rowId });
275  return got?.found ? got.row : null;
276}
277
278async function assertOfferAllowedForSale(context, sale, offer) {