import { IUseCase, IUseCaseError, IUseCaseRequest, UseCaseError, } from "@/contexts/common/application/useCases"; import { IRepositoryManager } from "@/contexts/common/domain"; import { ISequelizeAdapter } from "@/contexts/common/infrastructure/sequelize"; import { Collection, IDomainError, Result, UniqueID, UTCDateValue } from "@shared/contexts"; import { Dealer, IQuoteRepository, QuoteCustomerReference, QuoteItem, QuoteReference, QuoteStatus, } from "../../domain"; import { IInfrastructureError } from "@/contexts/common/infrastructure"; import { SequelizeBusinessTransactionType } from "@/contexts/common/infrastructure/sequelize/SequelizeBusinessTransaction"; import { Quote } from "../../domain/entities/Quotes/Quote"; import { ISalesContext } from "../../infrastructure"; import { findQuoteById, generateQuoteReferenceForDealer } from "../services"; export interface IDuplicateQuoteUseCaseRequest extends IUseCaseRequest { sourceId: UniqueID; } export type DuplicateQuoteResponseOrError = | Result // Misc errors (value objects) | Result; // Success! export class DuplicateQuoteUseCase implements IUseCase> { private _adapter: ISequelizeAdapter; private _repositoryManager: IRepositoryManager; private _dealer: Dealer; private _transaction: SequelizeBusinessTransactionType; constructor(context: ISalesContext) { this._adapter = context.adapter; this._repositoryManager = context.repositoryManager; this._dealer = context.dealer!; } async execute(request: IDuplicateQuoteUseCaseRequest): Promise { const { sourceId } = request; const targetId = UniqueID.generateNewID().object; const transaction = this._adapter.startTransaction(); const QuoteRepoBuilder = this._repositoryManager.getRepository("Quote"); let sourceQuote: Quote | null = null; let quoteReference: QuoteReference; let targetQuoteOrError: Result; // Buscar el quote try { return await transaction.complete(async (t) => { const quoteRepo = QuoteRepoBuilder({ transaction: t }); sourceQuote = await findQuoteById(sourceId, quoteRepo); if (!sourceQuote) { return Result.fail(UseCaseError.create(UseCaseError.NOT_FOUND_ERROR, "Quote not found")); } // Generate Reference quoteReference = await generateQuoteReferenceForDealer(this._dealer, quoteRepo); targetQuoteOrError = this._tryDuplicateQuoteInstance(sourceQuote, targetId, quoteReference); await quoteRepo.create(targetQuoteOrError.object); return Result.ok(targetQuoteOrError.object); }); } catch (error: unknown) { const _error = error as IInfrastructureError; return Result.fail(UseCaseError.create(UseCaseError.REPOSITORY_ERROR, _error.message)); } } private _tryDuplicateQuoteInstance( sourceQuote: Quote, targetId: UniqueID, targetReference: QuoteReference ): Result { const dealerId: UniqueID = this._dealer.id; const status = QuoteStatus.createDraft(); const date = UTCDateValue.createCurrentDate().object; const customerReference = QuoteCustomerReference.create("").object; const dateSent = UTCDateValue.create(null).object; // items let items: Collection; try { items = new Collection( sourceQuote.items.toArray().map((item) => QuoteItem.create(item).object) ); } catch (e: unknown) { return Result.fail(e as IDomainError); } return Quote.create( { status, date, reference: targetReference, language: sourceQuote.language, customerReference, customer: sourceQuote.customer, currency: sourceQuote.currency, paymentMethod: sourceQuote.paymentMethod, notes: sourceQuote.notes, validity: sourceQuote.validity, discount: sourceQuote.discount, tax: sourceQuote.tax, items, dealerId, dateSent, }, targetId ); } }