A successful (2xx) answer from Hiboutik is now the truth, even an empty list: records missing from it are deleted. The "empty list means API issue" safety nets are removed. Deletion stays safe because a failed call deletes nothing: HTTP errors throw, and the new HiboutikClient.getList (used by getAllPages and the non-paginated lists) also throws on a 2xx body that is not a list, so a malformed answer is never mistaken for an empty list. A 2xx without body is an empty list. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
35 lines
1.7 KiB
TypeScript
35 lines
1.7 KiB
TypeScript
import { Injectable, Logger } from '@nestjs/common';
|
|
import { SupplierHiboutikRepository } from '../../hiboutik/supplier.hiboutik.repository';
|
|
import { SupplierDatabaseRepository } from '../../database/supplier.database.repository';
|
|
import { SupplierConverter } from '../../models/converter/supplier.converter';
|
|
import { forEachSafely } from '../../utils/sync';
|
|
|
|
@Injectable()
|
|
export class SupplierHiboutikService {
|
|
private readonly logger = new Logger('SupplierHiboutikService');
|
|
|
|
constructor(
|
|
private readonly supplierHiboutikRepository: SupplierHiboutikRepository,
|
|
private readonly supplierDatabaseRepository: SupplierDatabaseRepository,
|
|
private readonly supplierConverter: SupplierConverter,
|
|
) {}
|
|
|
|
/** Mirrors Hiboutik suppliers: upserts each of them, then deletes the suppliers missing from Hiboutik. */
|
|
async syncSuppliers() {
|
|
const hiboutikSuppliers = await this.supplierHiboutikRepository.getSuppliers();
|
|
// One upsert per supplier: an invalid supplier must not prevent the others from being saved
|
|
const nbFailed = await forEachSafely(
|
|
this.supplierConverter.fromHiboutikList(hiboutikSuppliers),
|
|
(supplier) => this.supplierDatabaseRepository.upsert(supplier),
|
|
this.logger,
|
|
(supplier) => `Hiboutik supplier ${supplier.hiboutikId}`,
|
|
);
|
|
|
|
// Hiboutik is trusted: a successful (2xx) answer, even an empty list, is the truth. An HTTP error throws before this point.
|
|
const nbDeleted = await this.supplierDatabaseRepository.deleteMissing(hiboutikSuppliers.map((dto) => Number(dto.supplier_id)));
|
|
this.logger.log(
|
|
`Suppliers sync ended: ${hiboutikSuppliers.length - nbFailed}/${hiboutikSuppliers.length} synced, ${nbFailed} failed, ${nbDeleted} deleted.`,
|
|
);
|
|
}
|
|
}
|