feat(sync): synchronize customer adresses and orders from Hiboutik sales (#1)

Co-authored-by: MastersGame <quentin.duwa1210@gmail.com>
Reviewed-on: #1
This commit is contained in:
2026-11-07 09:56:53 +00:00
parent c5f65dcb62
commit 9dddf7562a
16 changed files with 755 additions and 17 deletions

View File

@@ -0,0 +1,49 @@
import { Injectable } from '@nestjs/common';
import { Converter } from './converter';
import { CustomerAddressCreateInput } from '../../../prisma/generated/models/CustomerAddress';
import { CustomerAddressDetailsHiboutikDto, CustomerAddressHiboutikDto } from '../hiboutikDTO/customer.hiboutik.dto';
/** Trimmed value, `null` when empty so that a value removed in Hiboutik is also removed in database. */
const optional = (value: string | null | undefined): string | null => value?.trim() || null;
const required = (value: string | null | undefined): string => value?.trim() ?? '';
/**
* Maps an address. Company details (tax/company number, legal status) are:
* - `null` when the address has no company,
* - mapped when `dto` comes from `GET /customers_addresses/:id` ({@link CustomerAddressDetailsHiboutikDto}),
* - `undefined` (stored values kept) when the details were not fetched.
*/
@Injectable()
export class CustomerAddressConverter extends Converter<
CustomerAddressCreateInput,
CustomerAddressHiboutikDto | CustomerAddressDetailsHiboutikDto
> {
fromHiboutik(dto: CustomerAddressHiboutikDto | CustomerAddressDetailsHiboutikDto): CustomerAddressCreateInput {
const company = optional(dto.company);
const hasDetails = 'tax_number' in dto;
const companyDetail = (value: string | null | undefined) => (!company ? null : hasDetails ? optional(value) : undefined);
const details = dto as Partial<CustomerAddressDetailsHiboutikDto>;
return {
address: required(dto.address),
city: required(dto.city),
company,
companyNumber: companyDetail(details.company_number),
country: required(dto.country),
firstName: required(dto.first_name),
hiboutikId: Number(dto.address_id),
isDefault: Number(dto.default) === 1,
lastName: required(dto.last_name),
legalStatus: companyDetail(details.legal_status),
other: optional(dto.other),
phone: optional(dto.phone),
state: optional(dto.state),
taxNumber: companyDetail(details.tax_number),
zipCode: required(dto.zip_code),
customer: { connect: { hiboutikId: Number(dto.customers_id) } },
};
}
toHiboutik(): CustomerAddressHiboutikDto {
throw new Error('Method not implemented.');
}
}