131 lines
4.1 KiB
TypeScript
131 lines
4.1 KiB
TypeScript
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<never, IUseCaseError> // Misc errors (value objects)
|
|
| Result<Quote, never>; // Success!
|
|
|
|
export class DuplicateQuoteUseCase
|
|
implements IUseCase<IDuplicateQuoteUseCaseRequest, Promise<DuplicateQuoteResponseOrError>>
|
|
{
|
|
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<DuplicateQuoteResponseOrError> {
|
|
const { sourceId } = request;
|
|
const targetId = UniqueID.generateNewID().object;
|
|
|
|
const transaction = this._adapter.startTransaction();
|
|
const QuoteRepoBuilder = this._repositoryManager.getRepository<IQuoteRepository>("Quote");
|
|
|
|
let sourceQuote: Quote | null = null;
|
|
let quoteReference: QuoteReference;
|
|
let targetQuoteOrError: Result<Quote, IDomainError>;
|
|
|
|
// 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<Quote>(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<Quote, IDomainError> {
|
|
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<QuoteItem>;
|
|
|
|
try {
|
|
items = new Collection<QuoteItem>(
|
|
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
|
|
);
|
|
}
|
|
}
|