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) {