feat(sync): harden the Hiboutik sync, share rate limits across instances, update dependencies (#4)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-08 13:45:08 +00:00
parent 8c8a2ccf15
commit cc3dcd3f0a
62 changed files with 1546 additions and 639 deletions

View File

@@ -2,29 +2,26 @@ import { OrderConverter } from './order.converter';
import { SaleHiboutikDto, SaleLineHiboutikDto } from '../hiboutikDTO/sale.hiboutik.dto';
const hiboutikLine = (overrides: Partial<SaleLineHiboutikDto> = {}): SaleLineHiboutikDto => ({
line_item_id: 3,
product_id: 746,
product_size: 1,
quantity: 2,
product_model: 'KATSEYE - WILD',
product_barcode: '2430010007467',
size_name: 'Daniela',
item_unit_gross_wo_discount: '19.00',
item_unit_gross: '17.10',
...overrides,
});
const hiboutikSale = (overrides: Partial<SaleHiboutikDto> = {}): SaleHiboutikDto =>
({
sale_id: 5,
created_at: '2026-10-18 11:00:21',
completed_at: '2026-10-18 11:01:04',
customer_id: 1,
total: '34.20',
quotation: 0,
line_items: [hiboutikLine()],
...overrides,
}) as SaleHiboutikDto;
const hiboutikSale = (overrides: Partial<SaleHiboutikDto> = {}): SaleHiboutikDto => ({
sale_id: 5,
created_at: '2026-10-18 11:00:21',
completed_at: '2026-10-18 11:01:04',
customer_id: 1,
total: '34.20',
quotation: 0,
line_items: [hiboutikLine()],
...overrides,
});
describe('OrderConverter', () => {
const converter = new OrderConverter();
@@ -32,7 +29,8 @@ describe('OrderConverter', () => {
it('maps a completed Hiboutik sale with its lines', () => {
expect(converter.fromHiboutik(hiboutikSale())).toEqual({
hiboutikSaleId: 5,
orderedAt: new Date('2026-10-18T11:01:04'),
// French summer time (UTC+2)
orderedAt: new Date('2026-10-18T09:01:04Z'),
source: 'STORE',
status: 'COMPLETED',
total: '34.20',
@@ -54,7 +52,7 @@ describe('OrderConverter', () => {
it('maps a sale not completed yet as PENDING, ordered at its creation date', () => {
const order = converter.fromHiboutik(hiboutikSale({ completed_at: '0000-00-00 00:00:00' }));
expect(order.status).toBe('PENDING');
expect(order.orderedAt).toEqual(new Date('2026-10-18T11:00:21'));
expect(order.orderedAt).toEqual(new Date('2026-10-18T09:00:21Z'));
});
it('throws when the sale has no valid date', () => {
@@ -75,6 +73,6 @@ describe('OrderConverter', () => {
});
it('accepts a sale without lines', () => {
expect(converter.fromHiboutik(hiboutikSale({ line_items: undefined as never })).lines).toEqual([]);
expect(converter.fromHiboutik(hiboutikSale({ line_items: [] })).lines).toEqual([]);
});
});