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.`, ); } }