feat(sync): validate Hiboutik payloads, read French dates and guard deletions

- Hiboutik payloads are zod schemas, validated by HiboutikClient (getOne
  added for single resources: null on 404 or empty answer).
- Hiboutik dates are read as Europe/Paris whatever the server time zone.
- Paginated lists driving deletions are walked twice when they span several
  pages (brands, categories, products); categories are sorted by id.
- A customer missing from the list is deleted only once Hiboutik confirms
  it; completed orders that lost their customer are linked back.
- Each product and its versions are written in one transaction.
- An email removed in Hiboutik is erased in database.
- A 429 is retried with backoff, then stops the synchronization.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
MastersGame
2026-11-08 12:20:58 +01:00
parent 4b0cda1740
commit 35a7c27cb7
44 changed files with 1065 additions and 467 deletions

View File

@@ -1,10 +1,13 @@
import { z } from 'zod';
import { hiboutikId, hiboutikNumber, hiboutikRef } from './hiboutik.schema';
/** Available stock of one product size, as returned by Hiboutik `GET /stock_available/all_wh` (all warehouses). */
export interface StockHiboutikDto {
product_id: number;
export const stockHiboutikSchema = z.object({
product_id: hiboutikId,
/** Size id, 0 for a product without sizes. */
product_size: number;
/** Decimal as a string, e.g. "3". Stays at 0 while stock management is disabled in Hiboutik. */
stock_available: string;
product_barcode: string;
product_supplier_reference: string;
}
product_size: hiboutikRef,
/** Sent as a decimal string, e.g. "3". Stays at 0 while stock management is disabled in Hiboutik. */
stock_available: hiboutikNumber,
});
export type StockHiboutikDto = z.output<typeof stockHiboutikSchema>;