feat(sync): synchronize Hiboutik data through POST /sync
POST /sync starts the full synchronization in the background (202, or 409 when one is already running). Entities are synced in dependency order: brands, categories, suppliers, products (with versions and stocks), customers. Each row is synced independently so that a failure is logged without stopping the rest. Replaces the default AppService.
This commit is contained in:
38
src/services/hiboutik/supplier.hiboutik.service.ts
Normal file
38
src/services/hiboutik/supplier.hiboutik.service.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
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}`,
|
||||
);
|
||||
|
||||
// Safety net: an empty answer from Hiboutik most likely means an API issue
|
||||
if (hiboutikSuppliers.length === 0) {
|
||||
this.logger.warn('Hiboutik returned no suppliers: deletion skipped.');
|
||||
return;
|
||||
}
|
||||
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.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user