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:
@@ -1,23 +1,22 @@
|
||||
import { CustomerAddressConverter } from './customerAddress.converter';
|
||||
import { CustomerAddressHiboutikDto } from '../hiboutikDTO/customer.hiboutik.dto';
|
||||
|
||||
const hiboutikAddress = (overrides: Partial<CustomerAddressHiboutikDto> = {}): CustomerAddressHiboutikDto =>
|
||||
({
|
||||
address_id: 7,
|
||||
customers_id: 42,
|
||||
first_name: 'Jane',
|
||||
last_name: 'Doe',
|
||||
company: 'ACME',
|
||||
phone: '0600000000',
|
||||
address: ' 1 rue de la Paix ',
|
||||
zip_code: '75002',
|
||||
city: 'Paris',
|
||||
state: '',
|
||||
country: 'FRA',
|
||||
other: 'Bât. B',
|
||||
default: 1,
|
||||
...overrides,
|
||||
}) as CustomerAddressHiboutikDto;
|
||||
const hiboutikAddress = (overrides: Partial<CustomerAddressHiboutikDto> = {}): CustomerAddressHiboutikDto => ({
|
||||
address_id: 7,
|
||||
customers_id: 42,
|
||||
first_name: 'Jane',
|
||||
last_name: 'Doe',
|
||||
company: 'ACME',
|
||||
phone: '0600000000',
|
||||
address: ' 1 rue de la Paix ',
|
||||
zip_code: '75002',
|
||||
city: 'Paris',
|
||||
state: '',
|
||||
country: 'FRA',
|
||||
other: 'Bât. B',
|
||||
default: 1,
|
||||
...overrides,
|
||||
});
|
||||
|
||||
describe('CustomerAddressConverter', () => {
|
||||
const converter = new CustomerAddressConverter();
|
||||
@@ -40,17 +39,8 @@ describe('CustomerAddressConverter', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('accepts ids and flags sent as strings', () => {
|
||||
const address = converter.fromHiboutik(hiboutikAddress({ address_id: '8', customers_id: '43', default: '0' } as never));
|
||||
expect(address.hiboutikId).toBe(8);
|
||||
expect(address.isDefault).toBe(false);
|
||||
expect(address.customer).toEqual({ connect: { hiboutikId: 43 } });
|
||||
});
|
||||
|
||||
it('erases empty optional fields (null) and defaults empty required ones to ""', () => {
|
||||
const address = converter.fromHiboutik(
|
||||
hiboutikAddress({ company: ' ', phone: null as unknown as string, other: '', first_name: null as unknown as string }),
|
||||
);
|
||||
const address = converter.fromHiboutik(hiboutikAddress({ company: ' ', phone: '', other: '', first_name: '' }));
|
||||
expect(address.company).toBeNull();
|
||||
expect(address.phone).toBeNull();
|
||||
expect(address.other).toBeNull();
|
||||
|
||||
Reference in New Issue
Block a user