import { EmailAddress, PhoneNumber, PostalAddress, TINNumber, UniqueID, } from "@/core/common/domain"; import { type Account, AccountStatus, type IAccountProps, type IAccountService, } from "@/contexts/accounts/domain"; import { ITransactionManager } from "@/core/common/infrastructure/database"; import { logger } from "@/core/logger"; import { Maybe, Result } from "@repo/rdx-utils"; import { ICreateAccountRequestDTO } from "../presentation"; export class CreateAccountUseCase { constructor( private readonly accountService: IAccountService, private readonly transactionManager: ITransactionManager ) {} public execute( accountID: UniqueID, dto: ICreateAccountRequestDTO ): Promise> { return this.transactionManager.complete(async (transaction) => { try { const validOrErrors = this.validateAccountData(dto); if (validOrErrors.isFailure) { return Result.fail(validOrErrors.error); } const data = validOrErrors.data; // Update account with dto return await this.accountService.createAccount(accountID, data, transaction); } catch (error: unknown) { logger.error(error as Error); return Result.fail(error as Error); } }); } private validateAccountData(dto: ICreateAccountRequestDTO): Result { const errors: Error[] = []; const tinOrError = TINNumber.create(dto.tin); const emailOrError = EmailAddress.create(dto.email); const phoneOrError = PhoneNumber.create(dto.phone); const faxOrError = PhoneNumber.createNullable(dto.fax); const postalAddressOrError = PostalAddress.create({ street: dto.street, city: dto.city, state: dto.state, postalCode: dto.postal_code, country: dto.country, }); const result = Result.combine([ tinOrError, emailOrError, phoneOrError, faxOrError, postalAddressOrError, ]); if (result.isFailure) { return Result.fail(result.error); } const validatedData: IAccountProps = { status: AccountStatus.createInactive(), isFreelancer: dto.is_companyr, name: dto.name, tradeName: dto.trade_name ? Maybe.some(dto.trade_name) : Maybe.none(), tin: tinOrError.data, address: postalAddressOrError.data, email: emailOrError.data, phone: phoneOrError.data, fax: faxOrError.data, website: dto.website ? Maybe.some(dto.website) : Maybe.none(), legalRecord: dto.legal_record, defaultTax: dto.default_tax, langCode: dto.language_code, currencyCode: dto.currency_code, logo: dto.logo ? Maybe.some(dto.logo) : Maybe.none(), }; if (errors.length > 0) { const message = errors.map((err) => err.message).toString(); return Result.fail(new Error(message)); } return Result.ok(validatedData); } }