.
This commit is contained in:
parent
acd61cf6eb
commit
e9824ecf80
@ -1,8 +1,8 @@
|
||||
import type { ICustomerInvoiceRepository } from "../../../domain";
|
||||
import type { IIssuedInvoiceRepository } from "../repositories";
|
||||
import { type IIssuedInvoiceFinder, IssuedInvoiceFinder } from "../services/issued-invoice-finder";
|
||||
|
||||
export function buildIssuedInvoiceFinder(
|
||||
repository: ICustomerInvoiceRepository
|
||||
repository: IIssuedInvoiceRepository
|
||||
): IIssuedInvoiceFinder {
|
||||
return new IssuedInvoiceFinder(repository);
|
||||
}
|
||||
|
||||
@ -9,9 +9,9 @@ import {
|
||||
IssuedInvoiceVerifactuFullSnapshotBuilder,
|
||||
} from "../snapshot-builders/full";
|
||||
import {
|
||||
IssuedInvoiceItemReportSnapshotBuilder,
|
||||
IssuedInvoiceReportItemSnapshotBuilder,
|
||||
IssuedInvoiceReportSnapshotBuilder,
|
||||
IssuedInvoiceTaxReportSnapshotBuilder,
|
||||
IssuedInvoiceReportTaxSnapshotBuilder,
|
||||
} from "../snapshot-builders/report";
|
||||
|
||||
export function buildIssuedInvoiceSnapshotBuilders() {
|
||||
@ -32,8 +32,8 @@ export function buildIssuedInvoiceSnapshotBuilders() {
|
||||
|
||||
const listSnapshotBuilder = new IssuedInvoiceListItemSnapshotBuilder();
|
||||
|
||||
const itemsReportBuilder = new IssuedInvoiceItemReportSnapshotBuilder();
|
||||
const taxesReportBuilder = new IssuedInvoiceTaxReportSnapshotBuilder();
|
||||
const itemsReportBuilder = new IssuedInvoiceReportItemSnapshotBuilder();
|
||||
const taxesReportBuilder = new IssuedInvoiceReportTaxSnapshotBuilder();
|
||||
const reportSnapshotBuilder = new IssuedInvoiceReportSnapshotBuilder(
|
||||
itemsReportBuilder,
|
||||
taxesReportBuilder
|
||||
|
||||
@ -17,8 +17,7 @@ export interface IIssuedInvoiceRepository {
|
||||
existsByIdInCompany(
|
||||
companyId: UniqueID,
|
||||
id: UniqueID,
|
||||
transaction: unknown,
|
||||
options: unknown
|
||||
transaction: unknown
|
||||
): Promise<Result<boolean, Error>>;
|
||||
|
||||
findByCriteriaInCompany(
|
||||
|
||||
@ -43,9 +43,7 @@ export class IssuedInvoiceFinder implements IIssuedInvoiceFinder {
|
||||
invoiceId: UniqueID,
|
||||
transaction?: Transaction
|
||||
): Promise<Result<boolean, Error>> {
|
||||
return this.repository.existsByIdInCompany(companyId, invoiceId, transaction, {
|
||||
is_proforma: false,
|
||||
});
|
||||
return this.repository.existsByIdInCompany(companyId, invoiceId, transaction);
|
||||
}
|
||||
|
||||
async findIssuedInvoicesByCriteria(
|
||||
|
||||
@ -41,7 +41,6 @@ export class IssuedInvoiceFullSnapshotBuilder implements IIssuedInvoiceFullSnaps
|
||||
id: invoice.id.toString(),
|
||||
company_id: invoice.companyId.toString(),
|
||||
|
||||
is_proforma: "false",
|
||||
invoice_number: invoice.invoiceNumber.toString(),
|
||||
status: invoice.status.toPrimitive(),
|
||||
series: maybeToEmptyString(invoice.series, (value) => value.toString()),
|
||||
|
||||
@ -7,7 +7,6 @@ export interface IIssuedInvoiceFullSnapshot {
|
||||
id: string;
|
||||
company_id: string;
|
||||
|
||||
is_proforma: "true" | "false";
|
||||
invoice_number: string;
|
||||
status: string;
|
||||
series: string;
|
||||
|
||||
@ -15,6 +15,8 @@ export interface IIssuedInvoiceItemFullSnapshot {
|
||||
global_discount_percentage: { value: string; scale: string };
|
||||
global_discount_amount: { value: string; scale: string; currency_code: string };
|
||||
|
||||
total_discount_amount: { value: string; scale: string; currency_code: string };
|
||||
|
||||
taxable_amount: { value: string; scale: string; currency_code: string };
|
||||
|
||||
iva_code: string;
|
||||
|
||||
@ -6,7 +6,7 @@ import {
|
||||
maybeToEmptyString,
|
||||
} from "@repo/rdx-ddd";
|
||||
|
||||
import type { IssuedInvoiceItem, IssuedInvoiceItems } from "../../../../domain";
|
||||
import { type IssuedInvoiceItem, type IssuedInvoiceItems, ItemAmount } from "../../../../domain";
|
||||
|
||||
import type { IIssuedInvoiceItemFullSnapshot } from "./issued-invoice-item-full-snapshot.interface";
|
||||
|
||||
@ -17,9 +17,10 @@ export class IssuedInvoiceItemsFullSnapshotBuilder
|
||||
implements IIssuedInvoiceItemsFullSnapshotBuilder
|
||||
{
|
||||
private mapItem(invoiceItem: IssuedInvoiceItem, index: number): IIssuedInvoiceItemFullSnapshot {
|
||||
const isValued = invoiceItem.isValued;
|
||||
return {
|
||||
id: invoiceItem.id.toPrimitive(),
|
||||
is_valued: String(invoiceItem.isValued),
|
||||
is_valued: String(isValued),
|
||||
position: String(index),
|
||||
|
||||
description: maybeToEmptyString(invoiceItem.description, (value) => value.toString()),
|
||||
@ -27,32 +28,50 @@ export class IssuedInvoiceItemsFullSnapshotBuilder
|
||||
quantity: maybeToEmptyQuantityObjectString(invoiceItem.quantity),
|
||||
unit_amount: maybeToEmptyMoneyObjectString(invoiceItem.unitAmount),
|
||||
|
||||
subtotal_amount: maybeToEmptyMoneyObjectString(invoiceItem.subtotalAmount),
|
||||
subtotal_amount: isValued
|
||||
? invoiceItem.subtotalAmount.toObjectString()
|
||||
: ItemAmount.EMPTY_MONEY_OBJECT,
|
||||
|
||||
discount_percentage: maybeToEmptyPercentageObjectString(invoiceItem.itemDiscountPercentage),
|
||||
discount_amount: maybeToEmptyMoneyObjectString(invoiceItem.itemDiscountAmount),
|
||||
discount_amount: isValued
|
||||
? invoiceItem.itemDiscountAmount.toObjectString()
|
||||
: ItemAmount.EMPTY_MONEY_OBJECT,
|
||||
|
||||
global_discount_percentage: maybeToEmptyPercentageObjectString(
|
||||
invoiceItem.globalDiscountPercentage
|
||||
),
|
||||
global_discount_amount: maybeToEmptyMoneyObjectString(invoiceItem.globalDiscountAmount),
|
||||
global_discount_amount: isValued
|
||||
? invoiceItem.globalDiscountAmount.toObjectString()
|
||||
: ItemAmount.EMPTY_MONEY_OBJECT,
|
||||
|
||||
taxable_amount: maybeToEmptyMoneyObjectString(invoiceItem.taxableAmount),
|
||||
total_discount_amount: isValued
|
||||
? invoiceItem.totalDiscountAmount.toObjectString()
|
||||
: ItemAmount.EMPTY_MONEY_OBJECT,
|
||||
|
||||
taxable_amount: isValued
|
||||
? invoiceItem.taxableAmount.toObjectString()
|
||||
: ItemAmount.EMPTY_MONEY_OBJECT,
|
||||
|
||||
iva_code: maybeToEmptyString(invoiceItem.ivaCode),
|
||||
iva_percentage: maybeToEmptyPercentageObjectString(invoiceItem.ivaPercentage),
|
||||
iva_amount: maybeToEmptyMoneyObjectString(invoiceItem.ivaAmount),
|
||||
iva_amount: isValued ? invoiceItem.ivaAmount.toObjectString() : ItemAmount.EMPTY_MONEY_OBJECT,
|
||||
|
||||
rec_code: maybeToEmptyString(invoiceItem.recCode),
|
||||
rec_percentage: maybeToEmptyPercentageObjectString(invoiceItem.recPercentage),
|
||||
rec_amount: maybeToEmptyMoneyObjectString(invoiceItem.recAmount),
|
||||
rec_amount: isValued ? invoiceItem.recAmount.toObjectString() : ItemAmount.EMPTY_MONEY_OBJECT,
|
||||
|
||||
retention_code: maybeToEmptyString(invoiceItem.retentionCode),
|
||||
retention_percentage: maybeToEmptyPercentageObjectString(invoiceItem.retentionPercentage),
|
||||
retention_amount: maybeToEmptyMoneyObjectString(invoiceItem.retentionAmount),
|
||||
retention_amount: isValued
|
||||
? invoiceItem.retentionAmount.toObjectString()
|
||||
: ItemAmount.EMPTY_MONEY_OBJECT,
|
||||
|
||||
taxes_amount: maybeToEmptyMoneyObjectString(invoiceItem.taxesAmount),
|
||||
total_amount: maybeToEmptyMoneyObjectString(invoiceItem.totalAmount),
|
||||
taxes_amount: isValued
|
||||
? invoiceItem.taxesAmount.toObjectString()
|
||||
: ItemAmount.EMPTY_MONEY_OBJECT,
|
||||
total_amount: isValued
|
||||
? invoiceItem.totalAmount.toObjectString()
|
||||
: ItemAmount.EMPTY_MONEY_OBJECT,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -24,7 +24,6 @@ export class IssuedInvoiceListItemSnapshotBuilder implements IIssuedInvoiceListI
|
||||
return {
|
||||
id: invoice.id.toString(),
|
||||
company_id: invoice.companyId.toString(),
|
||||
is_proforma: invoice.isProforma,
|
||||
|
||||
customer_id: invoice.customerId.toString(),
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
export interface IIssuedInvoiceListItemSnapshot {
|
||||
id: string;
|
||||
company_id: string;
|
||||
is_proforma: boolean;
|
||||
|
||||
customer_id: string;
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
export * from "./issued-invoice-items-report-snapshot-builder";
|
||||
export * from "./issued-invoice-report-item-snapshot.interface";
|
||||
export * from "./issued-invoice-report-item-snapshot-builder";
|
||||
export * from "./issued-invoice-report-snapshot.interface";
|
||||
export * from "./issued-invoice-report-snapshot-builder";
|
||||
export * from "./issued-invoice-report-tax-snapshot.interface";
|
||||
export * from "./issued-invoice-tax-report-snapshot-builder";
|
||||
export * from "./issued-invoice-report-tax-snapshot-builder";
|
||||
|
||||
@ -1,21 +1,20 @@
|
||||
import { MoneyDTOHelper, PercentageDTOHelper, QuantityDTOHelper } from "@erp/core";
|
||||
import type { ISnapshotBuilder, ISnapshotBuilderParams } from "@erp/core/api";
|
||||
|
||||
import type {
|
||||
IssuedInvoiceFullSnapshot,
|
||||
IssuedInvoiceReportItemSnapshot,
|
||||
} from "../../application-models";
|
||||
import type { IIssuedInvoiceItemFullSnapshot } from "../full";
|
||||
|
||||
export interface IIssuedInvoiceItemReportSnapshotBuilder
|
||||
extends ISnapshotBuilder<IssuedInvoiceFullSnapshot["items"], IssuedInvoiceReportItemSnapshot[]> {}
|
||||
import type { IIssuedInvoiceReportItemSnapshot } from "./issued-invoice-report-item-snapshot.interface";
|
||||
|
||||
export class IssuedInvoiceItemReportSnapshotBuilder
|
||||
implements IIssuedInvoiceItemReportSnapshotBuilder
|
||||
export interface IIssuedInvoiceReportItemSnapshotBuilder
|
||||
extends ISnapshotBuilder<IIssuedInvoiceItemFullSnapshot[], IIssuedInvoiceReportItemSnapshot[]> {}
|
||||
|
||||
export class IssuedInvoiceReportItemSnapshotBuilder
|
||||
implements IIssuedInvoiceReportItemSnapshotBuilder
|
||||
{
|
||||
toOutput(
|
||||
items: IssuedInvoiceFullSnapshot["items"],
|
||||
items: IIssuedInvoiceItemFullSnapshot[],
|
||||
params?: ISnapshotBuilderParams
|
||||
): IssuedInvoiceReportItemSnapshot[] {
|
||||
): IIssuedInvoiceReportItemSnapshot[] {
|
||||
const locale = params?.locale as string;
|
||||
|
||||
const moneyOptions = {
|
||||
@ -1,4 +1,4 @@
|
||||
export interface IssuedInvoiceReportItemSnapshot {
|
||||
export interface IIssuedInvoiceReportItemSnapshot {
|
||||
description: string;
|
||||
quantity: string;
|
||||
unit_amount: string;
|
||||
|
||||
@ -1,32 +1,25 @@
|
||||
import { DateHelper, MoneyDTOHelper, PercentageDTOHelper } from "@erp/core";
|
||||
import type { ISnapshotBuilder, ISnapshotBuilderParams } from "@erp/core/api";
|
||||
|
||||
import type {
|
||||
IssuedInvoiceFullSnapshot,
|
||||
IssuedInvoiceReportItemSnapshot,
|
||||
IssuedInvoiceReportSnapshot,
|
||||
IssuedInvoiceReportTaxSnapshot,
|
||||
} from "../../application-models";
|
||||
import type { IIssuedInvoiceFullSnapshot } from "../full";
|
||||
|
||||
import type { IIssuedInvoiceReportItemSnapshotBuilder } from "./issued-invoice-report-item-snapshot-builder";
|
||||
import type { IIssuedInvoiceReportSnapshot } from "./issued-invoice-report-snapshot.interface";
|
||||
import type { IIssuedInvoiceReportTaxSnapshotBuilder } from "./issued-invoice-report-tax-snapshot-builder";
|
||||
|
||||
export interface IIssuedInvoiceReportSnapshotBuilder
|
||||
extends ISnapshotBuilder<IssuedInvoiceFullSnapshot, IssuedInvoiceReportSnapshot> {}
|
||||
extends ISnapshotBuilder<IIssuedInvoiceFullSnapshot, IIssuedInvoiceReportSnapshot> {}
|
||||
|
||||
export class IssuedInvoiceReportSnapshotBuilder implements IIssuedInvoiceReportSnapshotBuilder {
|
||||
constructor(
|
||||
private readonly itemsBuilder: ISnapshotBuilder<
|
||||
IssuedInvoiceFullSnapshot["items"],
|
||||
IssuedInvoiceReportItemSnapshot[]
|
||||
>,
|
||||
private readonly taxesBuilder: ISnapshotBuilder<
|
||||
IssuedInvoiceFullSnapshot["taxes"],
|
||||
IssuedInvoiceReportTaxSnapshot[]
|
||||
>
|
||||
private readonly itemsBuilder: IIssuedInvoiceReportItemSnapshotBuilder,
|
||||
private readonly taxesBuilder: IIssuedInvoiceReportTaxSnapshotBuilder
|
||||
) {}
|
||||
|
||||
toOutput(
|
||||
snapshot: IssuedInvoiceFullSnapshot,
|
||||
snapshot: IIssuedInvoiceFullSnapshot,
|
||||
params?: ISnapshotBuilderParams
|
||||
): IssuedInvoiceReportSnapshot {
|
||||
): IIssuedInvoiceReportSnapshot {
|
||||
const locale = params?.locale as string;
|
||||
|
||||
const moneyOptions = {
|
||||
@ -61,10 +54,10 @@ export class IssuedInvoiceReportSnapshotBuilder implements IIssuedInvoiceReportS
|
||||
taxes: this.taxesBuilder.toOutput(snapshot.taxes, { locale }),
|
||||
|
||||
subtotal_amount: MoneyDTOHelper.format(snapshot.subtotal_amount, locale, moneyOptions),
|
||||
discount_percentage: PercentageDTOHelper.format(snapshot.discount_percentage, locale, {
|
||||
discount_percentage: PercentageDTOHelper.format(snapshot.global_discount_percentage, locale, {
|
||||
hideZeros: true,
|
||||
}),
|
||||
discount_amount: MoneyDTOHelper.format(snapshot.discount_amount, locale, moneyOptions),
|
||||
discount_amount: MoneyDTOHelper.format(snapshot.global_discount_amount, locale, moneyOptions),
|
||||
taxable_amount: MoneyDTOHelper.format(snapshot.taxable_amount, locale, moneyOptions),
|
||||
taxes_amount: MoneyDTOHelper.format(snapshot.taxes_amount, locale, moneyOptions),
|
||||
total_amount: MoneyDTOHelper.format(snapshot.total_amount, locale, moneyOptions),
|
||||
@ -76,7 +69,7 @@ export class IssuedInvoiceReportSnapshotBuilder implements IIssuedInvoiceReportS
|
||||
};
|
||||
}
|
||||
|
||||
private formatAddress(recipient: IssuedInvoiceFullSnapshot["recipient"]): string {
|
||||
private formatAddress(recipient: IIssuedInvoiceFullSnapshot["recipient"]): string {
|
||||
const lines: string[] = [];
|
||||
|
||||
if (recipient.street) lines.push(recipient.street);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import type { IssuedInvoiceReportItemSnapshot } from "./issued-invoice-report-item-snapshot.interface";
|
||||
import type { IssuedInvoiceReportTaxSnapshot } from "./issued-invoice-report-tax-snapshot.interface";
|
||||
import type { IIssuedInvoiceReportItemSnapshot } from "./issued-invoice-report-item-snapshot.interface";
|
||||
import type { IIssuedInvoiceReportTaxSnapshot } from "./issued-invoice-report-tax-snapshot.interface";
|
||||
|
||||
export interface IssuedInvoiceReportSnapshot {
|
||||
export interface IIssuedInvoiceReportSnapshot {
|
||||
id: string;
|
||||
company_id: string;
|
||||
company_slug: string;
|
||||
@ -23,8 +23,8 @@ export interface IssuedInvoiceReportSnapshot {
|
||||
format_address: string;
|
||||
};
|
||||
|
||||
items: IssuedInvoiceReportItemSnapshot[];
|
||||
taxes: IssuedInvoiceReportTaxSnapshot[];
|
||||
items: IIssuedInvoiceReportItemSnapshot[];
|
||||
taxes: IIssuedInvoiceReportTaxSnapshot[];
|
||||
|
||||
subtotal_amount: string;
|
||||
discount_percentage: string;
|
||||
|
||||
@ -1,21 +1,20 @@
|
||||
import { MoneyDTOHelper, PercentageDTOHelper } from "@erp/core";
|
||||
import type { ISnapshotBuilder, ISnapshotBuilderParams } from "@erp/core/api";
|
||||
|
||||
import type {
|
||||
IssuedInvoiceFullSnapshot,
|
||||
IssuedInvoiceReportTaxSnapshot,
|
||||
} from "../../application-models";
|
||||
import type { IIssuedInvoiceTaxFullSnapshot } from "../full";
|
||||
|
||||
export interface IIssuedInvoiceTaxReportSnapshotBuilder
|
||||
extends ISnapshotBuilder<IssuedInvoiceFullSnapshot["taxes"], IssuedInvoiceReportTaxSnapshot[]> {}
|
||||
import type { IIssuedInvoiceReportTaxSnapshot } from "./issued-invoice-report-tax-snapshot.interface";
|
||||
|
||||
export class IssuedInvoiceTaxReportSnapshotBuilder
|
||||
implements IIssuedInvoiceTaxReportSnapshotBuilder
|
||||
export interface IIssuedInvoiceReportTaxSnapshotBuilder
|
||||
extends ISnapshotBuilder<IIssuedInvoiceTaxFullSnapshot[], IIssuedInvoiceReportTaxSnapshot[]> {}
|
||||
|
||||
export class IssuedInvoiceReportTaxSnapshotBuilder
|
||||
implements IIssuedInvoiceReportTaxSnapshotBuilder
|
||||
{
|
||||
toOutput(
|
||||
taxes: IssuedInvoiceFullSnapshot["taxes"],
|
||||
taxes: IIssuedInvoiceTaxFullSnapshot[],
|
||||
params?: ISnapshotBuilderParams
|
||||
): IssuedInvoiceReportTaxSnapshot[] {
|
||||
): IIssuedInvoiceReportTaxSnapshot[] {
|
||||
const locale = params?.locale as string;
|
||||
|
||||
const moneyOptions = {
|
||||
@ -1,4 +1,4 @@
|
||||
export interface IssuedInvoiceReportTaxSnapshot {
|
||||
export interface IIssuedInvoiceReportTaxSnapshot {
|
||||
taxable_amount: string;
|
||||
|
||||
iva_code: string;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { ICustomerInvoiceRepository } from "../../../domain";
|
||||
import type { IProformaRepository } from "../repositories";
|
||||
import { type IProformaFinder, ProformaFinder } from "../services";
|
||||
|
||||
export function buildProformaFinder(repository: ICustomerInvoiceRepository): IProformaFinder {
|
||||
export function buildProformaFinder(repository: IProformaRepository): IProformaFinder {
|
||||
return new ProformaFinder(repository);
|
||||
}
|
||||
|
||||
@ -13,31 +13,31 @@ export interface IProformaRepository {
|
||||
existsByIdInCompany(
|
||||
companyId: UniqueID,
|
||||
id: UniqueID,
|
||||
tx: unknown
|
||||
transaction: unknown
|
||||
): Promise<Result<boolean, Error>>;
|
||||
|
||||
getByIdInCompany(
|
||||
companyId: UniqueID,
|
||||
id: UniqueID,
|
||||
tx: unknown
|
||||
transaction: unknown
|
||||
): Promise<Result<Proforma, Error>>;
|
||||
|
||||
findByCriteriaInCompany(
|
||||
companyId: UniqueID,
|
||||
criteria: Criteria,
|
||||
tx: unknown
|
||||
transaction: unknown
|
||||
): Promise<Result<Collection<ProformaListDTO>, Error>>;
|
||||
|
||||
deleteByIdInCompany(
|
||||
companyId: UniqueID,
|
||||
id: UniqueID,
|
||||
tx: unknown
|
||||
transaction: unknown
|
||||
): Promise<Result<boolean, Error>>;
|
||||
|
||||
updateStatusByIdInCompany(
|
||||
companyId: UniqueID,
|
||||
id: UniqueID,
|
||||
newStatus: InvoiceStatus,
|
||||
tx: unknown
|
||||
transaction: unknown
|
||||
): Promise<Result<boolean, Error>>;
|
||||
}
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import type { CustomerInvoiceListDTO } from "@erp/customer-invoices/api/infrastructure";
|
||||
import type { Criteria } from "@repo/rdx-criteria/server";
|
||||
import type { UniqueID } from "@repo/rdx-ddd";
|
||||
import type { Collection, Result } from "@repo/rdx-utils";
|
||||
import type { Transaction } from "sequelize";
|
||||
|
||||
import type { ICustomerInvoiceRepository, Proforma } from "../../../domain";
|
||||
import type { Proforma } from "../../../domain";
|
||||
import type { ProformaListDTO } from "../dtos";
|
||||
import type { IProformaRepository } from "../repositories";
|
||||
|
||||
export interface IProformaFinder {
|
||||
findProformaById(
|
||||
@ -23,18 +24,18 @@ export interface IProformaFinder {
|
||||
companyId: UniqueID,
|
||||
criteria: Criteria,
|
||||
transaction?: Transaction
|
||||
): Promise<Result<Collection<CustomerInvoiceListDTO>, Error>>;
|
||||
): Promise<Result<Collection<ProformaListDTO>, Error>>;
|
||||
}
|
||||
|
||||
export class ProformaFinder implements IProformaFinder {
|
||||
constructor(private readonly repository: ICustomerInvoiceRepository) {}
|
||||
constructor(private readonly repository: IProformaRepository) {}
|
||||
|
||||
async findProformaById(
|
||||
companyId: UniqueID,
|
||||
proformaId: UniqueID,
|
||||
transaction?: Transaction
|
||||
): Promise<Result<Proforma, Error>> {
|
||||
return this.repository.getProformaByIdInCompany(companyId, proformaId, transaction, {});
|
||||
return this.repository.getByIdInCompany(companyId, proformaId, transaction, {});
|
||||
}
|
||||
|
||||
async proformaExists(
|
||||
@ -42,16 +43,14 @@ export class ProformaFinder implements IProformaFinder {
|
||||
proformaId: UniqueID,
|
||||
transaction?: Transaction
|
||||
): Promise<Result<boolean, Error>> {
|
||||
return this.repository.existsByIdInCompany(companyId, proformaId, transaction, {
|
||||
is_proforma: true,
|
||||
});
|
||||
return this.repository.existsByIdInCompany(companyId, proformaId, transaction);
|
||||
}
|
||||
|
||||
async findProformasByCriteria(
|
||||
companyId: UniqueID,
|
||||
criteria: Criteria,
|
||||
transaction?: Transaction
|
||||
): Promise<Result<Collection<CustomerInvoiceListDTO>, Error>> {
|
||||
return this.repository.findProformasByCriteriaInCompany(companyId, criteria, transaction, {});
|
||||
): Promise<Result<Collection<ProformaListDTO>, Error>> {
|
||||
return this.repository.findByCriteriaInCompany(companyId, criteria, transaction, {});
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,3 +4,5 @@ export * from "./proforma-item-full-snapshot.interface";
|
||||
export * from "./proforma-items-full-snapshot-builder";
|
||||
export * from "./proforma-recipient-full-snapshot.interface";
|
||||
export * from "./proforma-recipient-full-snapshot-builder";
|
||||
export * from "./proforma-tax-full-snapshot-interface";
|
||||
export * from "./proforma-taxes-full-snapshot-builder";
|
||||
|
||||
@ -83,7 +83,6 @@ export class ProformaFullSnapshotBuilder implements IProformaFullSnapshotBuilder
|
||||
id: invoice.id.toString(),
|
||||
company_id: invoice.companyId.toString(),
|
||||
|
||||
is_proforma: invoice.isProforma ? "true" : "false",
|
||||
invoice_number: invoice.invoiceNumber.toString(),
|
||||
status: invoice.status.toPrimitive(),
|
||||
series: maybeToEmptyString(invoice.series, (value) => value.toString()),
|
||||
|
||||
@ -5,7 +5,6 @@ export interface IProformaFullSnapshot {
|
||||
id: string;
|
||||
company_id: string;
|
||||
|
||||
is_proforma: "true" | "false";
|
||||
invoice_number: string;
|
||||
status: string;
|
||||
series: string;
|
||||
|
||||
@ -1,94 +1,76 @@
|
||||
import type { ISnapshotBuilder } from "@erp/core/api";
|
||||
import { maybeToEmptyString } from "@repo/rdx-ddd";
|
||||
import {
|
||||
maybeToEmptyMoneyObjectString,
|
||||
maybeToEmptyPercentageObjectString,
|
||||
maybeToEmptyQuantityObjectString,
|
||||
maybeToEmptyString,
|
||||
} from "@repo/rdx-ddd";
|
||||
import { Maybe } from "@repo/rdx-utils";
|
||||
|
||||
import type { CustomerInvoiceItems, IssuedInvoiceItem } from "../../../../domain";
|
||||
import { ItemAmount, type ProformaItem, type ProformaItems } from "../../../../domain";
|
||||
|
||||
import type { IProformaItemFullSnapshot } from "./proforma-item-full-snapshot.interface";
|
||||
|
||||
export interface IProformaItemsFullSnapshotBuilder
|
||||
extends ISnapshotBuilder<CustomerInvoiceItems, IProformaItemFullSnapshot[]> {}
|
||||
extends ISnapshotBuilder<ProformaItems, IProformaItemFullSnapshot[]> {}
|
||||
|
||||
export class ProformaItemsFullSnapshotBuilder implements IProformaItemsFullSnapshotBuilder {
|
||||
private mapItem(invoiceItem: IssuedInvoiceItem, index: number): IProformaItemFullSnapshot {
|
||||
const allAmounts = invoiceItem.calculateAllAmounts();
|
||||
private mapItem(proformaItem: ProformaItem, index: number): IProformaItemFullSnapshot {
|
||||
const allAmounts = proformaItem.calculateAllAmounts();
|
||||
const isValued = proformaItem.isValued;
|
||||
|
||||
const noneIfNotValued = <T>(value: Maybe<T>): Maybe<T> => (isValued ? value : Maybe.none<T>());
|
||||
|
||||
return {
|
||||
id: invoiceItem.id.toPrimitive(),
|
||||
is_valued: String(invoiceItem.isValued),
|
||||
id: proformaItem.id.toPrimitive(),
|
||||
is_valued: String(isValued),
|
||||
position: String(index),
|
||||
description: maybeToEmptyString(invoiceItem.description, (value) => value.toPrimitive()),
|
||||
|
||||
quantity: invoiceItem.quantity.match(
|
||||
(quantity) => quantity.toObjectString(),
|
||||
() => ({ value: "", scale: "" })
|
||||
description: maybeToEmptyString(proformaItem.description, (value) => value.toString()),
|
||||
|
||||
quantity: maybeToEmptyQuantityObjectString(proformaItem.quantity),
|
||||
unit_amount: maybeToEmptyMoneyObjectString(proformaItem.unitAmount),
|
||||
|
||||
subtotal_amount: isValued
|
||||
? allAmounts.subtotalAmount.toObjectString()
|
||||
: ItemAmount.EMPTY_MONEY_OBJECT,
|
||||
|
||||
discount_percentage: maybeToEmptyPercentageObjectString(proformaItem.itemDiscountPercentage),
|
||||
discount_amount: isValued
|
||||
? allAmounts.itemDiscountAmount.toObjectString()
|
||||
: ItemAmount.EMPTY_MONEY_OBJECT,
|
||||
|
||||
global_discount_percentage: maybeToEmptyPercentageObjectString(
|
||||
proformaItem.globalDiscountPercentage
|
||||
),
|
||||
global_discount_amount: maybeToEmptyMoneyObjectString(proformaItem.globalDiscountAmount),
|
||||
|
||||
unit_amount: invoiceItem.unitAmount.match(
|
||||
(unitAmount) => unitAmount.toObjectString(),
|
||||
() => ({ value: "", scale: "", currency_code: "" })
|
||||
),
|
||||
total_discount_amount: isValued
|
||||
? allAmounts.totalDiscountAmount.toObjectString()
|
||||
: ItemAmount.EMPTY_MONEY_OBJECT,
|
||||
|
||||
subtotal_amount: allAmounts.subtotalAmount.toObjectString(),
|
||||
taxable_amount: isValued
|
||||
? allAmounts.taxableAmount.toObjectString()
|
||||
: ItemAmount.EMPTY_MONEY_OBJECT,
|
||||
|
||||
discount_percentage: invoiceItem.itemDiscountPercentage.match(
|
||||
(discountPercentage) => discountPercentage.toObjectString(),
|
||||
() => ({ value: "", scale: "" })
|
||||
),
|
||||
iva_code: maybeToEmptyString(proformaItem.ivaCode),
|
||||
iva_percentage: maybeToEmptyPercentageObjectString(proformaItem.ivaPercentage),
|
||||
iva_amount: maybeToEmptyMoneyObjectString(proformaItem.ivaAmount),
|
||||
|
||||
discount_amount: allAmounts.itemDiscountAmount.toObjectString(),
|
||||
rec_code: maybeToEmptyString(proformaItem.recCode),
|
||||
rec_percentage: maybeToEmptyPercentageObjectString(proformaItem.recPercentage),
|
||||
rec_amount: maybeToEmptyMoneyObjectString(proformaItem.recAmount),
|
||||
|
||||
global_discount_percentage: invoiceItem.globalDiscountPercentage.match(
|
||||
(discountPercentage) => discountPercentage.toObjectString(),
|
||||
() => ({ value: "", scale: "" })
|
||||
),
|
||||
retention_code: maybeToEmptyString(proformaItem.retentionCode),
|
||||
retention_percentage: maybeToEmptyPercentageObjectString(proformaItem.retentionPercentage),
|
||||
retention_amount: maybeToEmptyMoneyObjectString(proformaItem.retentionAmount),
|
||||
|
||||
global_discount_amount: allAmounts.globalDiscountAmount.toObjectString(),
|
||||
|
||||
taxable_amount: allAmounts.taxableAmount.toObjectString(),
|
||||
|
||||
iva_code: invoiceItem.taxes.iva.match(
|
||||
(iva) => iva.code,
|
||||
() => ""
|
||||
),
|
||||
|
||||
iva_percentage: invoiceItem.taxes.iva.match(
|
||||
(iva) => iva.percentage.toObjectString(),
|
||||
() => ({ value: "", scale: "" })
|
||||
),
|
||||
|
||||
iva_amount: allAmounts.ivaAmount.toObjectString(),
|
||||
|
||||
rec_code: invoiceItem.taxes.rec.match(
|
||||
(rec) => rec.code,
|
||||
() => ""
|
||||
),
|
||||
|
||||
rec_percentage: invoiceItem.taxes.rec.match(
|
||||
(rec) => rec.percentage.toObjectString(),
|
||||
() => ({ value: "", scale: "" })
|
||||
),
|
||||
|
||||
rec_amount: allAmounts.recAmount.toObjectString(),
|
||||
|
||||
retention_code: invoiceItem.taxes.retention.match(
|
||||
(retention) => retention.code,
|
||||
() => ""
|
||||
),
|
||||
|
||||
retention_percentage: invoiceItem.taxes.retention.match(
|
||||
(retention) => retention.percentage.toObjectString(),
|
||||
() => ({ value: "", scale: "" })
|
||||
),
|
||||
|
||||
retention_amount: allAmounts.retentionAmount.toObjectString(),
|
||||
|
||||
taxes_amount: allAmounts.taxesAmount.toObjectString(),
|
||||
|
||||
total_amount: allAmounts.totalAmount.toObjectString(),
|
||||
taxes_amount: maybeToEmptyMoneyObjectString(proformaItem.taxesAmount),
|
||||
total_amount: maybeToEmptyMoneyObjectString(proformaItem.totalAmount),
|
||||
};
|
||||
}
|
||||
|
||||
toOutput(invoiceItems: CustomerInvoiceItems): IProformaItemFullSnapshot[] {
|
||||
toOutput(invoiceItems: ProformaItems): IProformaItemFullSnapshot[] {
|
||||
return invoiceItems.map((item, index) => this.mapItem(item, index));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,22 +2,23 @@ import type { ISnapshotBuilder } from "@erp/core/api";
|
||||
import { DomainValidationError, maybeToEmptyString } from "@repo/rdx-ddd";
|
||||
|
||||
import type { InvoiceRecipient, Proforma } from "../../../../domain";
|
||||
import type { ProformaRecipientFullSnapshot } from "../../application-models";
|
||||
|
||||
import type { IProformaRecipientFullSnapshot } from "./proforma-recipient-full-snapshot.interface";
|
||||
|
||||
export interface IProformaRecipientFullSnapshotBuilder
|
||||
extends ISnapshotBuilder<Proforma, ProformaRecipientFullSnapshot> {}
|
||||
extends ISnapshotBuilder<Proforma, IProformaRecipientFullSnapshot> {}
|
||||
|
||||
export class ProformaRecipientFullSnapshotBuilder implements IProformaRecipientFullSnapshotBuilder {
|
||||
toOutput(invoice: Proforma): ProformaRecipientFullSnapshot {
|
||||
if (!invoice.recipient) {
|
||||
toOutput(proforma: Proforma): IProformaRecipientFullSnapshot {
|
||||
if (!proforma.recipient) {
|
||||
throw DomainValidationError.requiredValue("recipient", {
|
||||
cause: invoice,
|
||||
cause: proforma,
|
||||
});
|
||||
}
|
||||
|
||||
return invoice.recipient.match(
|
||||
return proforma.recipient.match(
|
||||
(recipient: InvoiceRecipient) => ({
|
||||
id: invoice.customerId.toString(),
|
||||
id: proforma.customerId.toString(),
|
||||
name: recipient.name.toString(),
|
||||
tin: recipient.tin.toString(),
|
||||
street: maybeToEmptyString(recipient.street, (v) => v.toString()),
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
export interface IProformaTaxFullSnapshot {
|
||||
taxable_amount: { value: string; scale: string; currency_code: string };
|
||||
|
||||
iva_code: string;
|
||||
iva_percentage: { value: string; scale: string };
|
||||
iva_amount: { value: string; scale: string; currency_code: string };
|
||||
|
||||
rec_code: string;
|
||||
rec_percentage: { value: string; scale: string };
|
||||
rec_amount: { value: string; scale: string; currency_code: string };
|
||||
|
||||
retention_code: string;
|
||||
retention_percentage: { value: string; scale: string };
|
||||
retention_amount: { value: string; scale: string; currency_code: string };
|
||||
|
||||
taxes_amount: { value: string; scale: string; currency_code: string };
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
import type { ISnapshotBuilder } from "@erp/core/api";
|
||||
import {
|
||||
maybeToEmptyMoneyObjectString,
|
||||
maybeToEmptyPercentageObjectString,
|
||||
maybeToEmptyString,
|
||||
} from "@repo/rdx-ddd";
|
||||
|
||||
import type { ProformaTax, ProformaTaxes } from "../../../../domain";
|
||||
|
||||
import type { IProformaTaxFullSnapshot } from "./proforma-tax-full-snapshot-interface";
|
||||
|
||||
export interface IProformaTaxesFullSnapshotBuilder
|
||||
extends ISnapshotBuilder<ProformaTaxes, IProformaTaxFullSnapshot[]> {}
|
||||
|
||||
export class ProformaTaxesFullSnapshotBuilder implements IProformaTaxesFullSnapshotBuilder {
|
||||
private mapItem(proformaTax: ProformaTax, index: number): IProformaTaxFullSnapshot {
|
||||
return {
|
||||
taxable_amount: proformaTax.taxableAmount.toObjectString(),
|
||||
|
||||
iva_code: proformaTax.ivaCode.toString(),
|
||||
iva_percentage: proformaTax.ivaPercentage.toObjectString(),
|
||||
iva_amount: proformaTax.ivaAmount.toObjectString(),
|
||||
|
||||
rec_code: maybeToEmptyString(proformaTax.recCode),
|
||||
rec_percentage: maybeToEmptyPercentageObjectString(proformaTax.recPercentage),
|
||||
rec_amount: maybeToEmptyMoneyObjectString(proformaTax.recAmount),
|
||||
|
||||
retention_code: maybeToEmptyString(proformaTax.retentionCode),
|
||||
retention_percentage: maybeToEmptyPercentageObjectString(proformaTax.retentionPercentage),
|
||||
retention_amount: maybeToEmptyMoneyObjectString(proformaTax.retentionAmount),
|
||||
|
||||
taxes_amount: proformaTax.taxesAmount.toObjectString(),
|
||||
};
|
||||
}
|
||||
|
||||
toOutput(invoiceTaxes: ProformaTaxes): IProformaTaxFullSnapshot[] {
|
||||
return invoiceTaxes.map((item, index) => this.mapItem(item, index));
|
||||
}
|
||||
}
|
||||
@ -1,20 +1,20 @@
|
||||
import type { ISnapshotBuilder } from "@erp/core/api";
|
||||
import { maybeToEmptyString } from "@repo/rdx-ddd";
|
||||
|
||||
import type { CustomerInvoiceListDTO } from "../../../../infrastructure";
|
||||
import type { ProformaListItemSnapshot } from "../../application-models";
|
||||
import type { ProformaListDTO } from "../../dtos";
|
||||
|
||||
import type { IProformaListItemSnapshot } from "./proforma-list-item-snapshot.interface";
|
||||
|
||||
export interface IProformaListItemSnapshotBuilder
|
||||
extends ISnapshotBuilder<CustomerInvoiceListDTO, ProformaListItemSnapshot> {}
|
||||
extends ISnapshotBuilder<ProformaListDTO, IProformaListItemSnapshot> {}
|
||||
|
||||
export class ProformaListItemSnapshotBuilder implements IProformaListItemSnapshotBuilder {
|
||||
toOutput(proforma: CustomerInvoiceListDTO): ProformaListItemSnapshot {
|
||||
toOutput(proforma: ProformaListDTO): IProformaListItemSnapshot {
|
||||
const recipient = proforma.recipient.toObjectString();
|
||||
|
||||
return {
|
||||
id: proforma.id.toString(),
|
||||
company_id: proforma.companyId.toString(),
|
||||
is_proforma: proforma.isProforma,
|
||||
customer_id: proforma.customerId.toString(),
|
||||
|
||||
invoice_number: proforma.invoiceNumber.toString(),
|
||||
@ -32,8 +32,7 @@ export class ProformaListItemSnapshotBuilder implements IProformaListItemSnapsho
|
||||
currency_code: proforma.currencyCode.code,
|
||||
|
||||
subtotal_amount: proforma.subtotalAmount.toObjectString(),
|
||||
discount_percentage: proforma.discountPercentage.toObjectString(),
|
||||
discount_amount: proforma.discountAmount.toObjectString(),
|
||||
total_discount_amount: proforma.totalDiscountAmount.toObjectString(),
|
||||
taxable_amount: proforma.taxableAmount.toObjectString(),
|
||||
taxes_amount: proforma.taxesAmount.toObjectString(),
|
||||
total_amount: proforma.totalAmount.toObjectString(),
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
export interface IProformaListItemSnapshot {
|
||||
id: string;
|
||||
company_id: string;
|
||||
is_proforma: boolean;
|
||||
|
||||
customer_id: string;
|
||||
|
||||
@ -30,8 +29,7 @@ export interface IProformaListItemSnapshot {
|
||||
};
|
||||
|
||||
subtotal_amount: { value: string; scale: string; currency_code: string };
|
||||
discount_percentage: { value: string; scale: string };
|
||||
discount_amount: { value: string; scale: string; currency_code: string };
|
||||
total_discount_amount: { value: string; scale: string; currency_code: string };
|
||||
taxable_amount: { value: string; scale: string; currency_code: string };
|
||||
taxes_amount: { value: string; scale: string; currency_code: string };
|
||||
total_amount: { value: string; scale: string; currency_code: string };
|
||||
|
||||
@ -84,7 +84,6 @@ export class ProformaFullPresenter extends Presenter<Proforma, GetProformaByIdRe
|
||||
id: proforma.id.toString(),
|
||||
company_id: proforma.companyId.toString(),
|
||||
|
||||
is_proforma: proforma.isProforma ? "true" : "false",
|
||||
invoice_number: proforma.invoiceNumber.toString(),
|
||||
status: proforma.status.toPrimitive(),
|
||||
series: maybeToEmptyString(proforma.series, (value) => value.toString()),
|
||||
|
||||
@ -3,7 +3,6 @@ import { maybeToEmptyString } from "@repo/rdx-ddd";
|
||||
import type { ArrayElement, Collection } from "@repo/rdx-utils";
|
||||
|
||||
import type { ListIssuedInvoicesResponseDTO } from "../../../../../common/dto";
|
||||
import type { CustomerInvoiceListDTO } from "../../../../infrastructure";
|
||||
|
||||
export class IssuedInvoiceListPresenter extends Presenter {
|
||||
protected _mapInvoice(invoice: CustomerInvoiceListDTO) {
|
||||
@ -21,7 +20,6 @@ export class IssuedInvoiceListPresenter extends Presenter {
|
||||
const invoiceDTO: ArrayElement<ListIssuedInvoicesResponseDTO["items"]> = {
|
||||
id: invoice.id.toString(),
|
||||
company_id: invoice.companyId.toString(),
|
||||
is_proforma: invoice.isProforma,
|
||||
customer_id: invoice.customerId.toString(),
|
||||
|
||||
invoice_number: invoice.invoiceNumber.toString(),
|
||||
|
||||
@ -11,5 +11,4 @@ export * from "./item-amount.vo";
|
||||
export * from "./item-description.vo";
|
||||
export * from "./item-discount-percentage.vo";
|
||||
export * from "./item-quantity.vo";
|
||||
export * from "./item-tax-group.vo";
|
||||
export * from "./item-tax-percentage.vo";
|
||||
|
||||
@ -2,8 +2,9 @@ import type { Tax } from "@erp/core/api";
|
||||
import { ValueObject } from "@repo/rdx-ddd";
|
||||
import { type Maybe, Result } from "@repo/rdx-utils";
|
||||
|
||||
import type { ProformaItemTaxGroup } from "../../proformas/value-objects/proforma-item-tax-group.vo";
|
||||
|
||||
import { InvoiceAmount } from "./invoice-amount.vo";
|
||||
import type { ItemTaxGroup } from "./item-tax-group.vo";
|
||||
|
||||
export type InvoiceTaxGroupProps = {
|
||||
taxableAmount: InvoiceAmount;
|
||||
@ -20,7 +21,7 @@ export class InvoiceTaxGroup extends ValueObject<InvoiceTaxGroupProps> {
|
||||
/**
|
||||
* Crea un grupo vacío a partir de un ItemTaxGroup (línea)
|
||||
*/
|
||||
static fromItem(lineTaxes: ItemTaxGroup, taxableAmount: InvoiceAmount): InvoiceTaxGroup {
|
||||
static fromItem(lineTaxes: ProformaItemTaxGroup, taxableAmount: InvoiceAmount): InvoiceTaxGroup {
|
||||
const iva = lineTaxes.iva.unwrap(); // iva siempre obligatorio
|
||||
const rec = lineTaxes.rec;
|
||||
const retention = lineTaxes.retention;
|
||||
|
||||
@ -8,7 +8,6 @@ import {
|
||||
import { type Maybe, Result } from "@repo/rdx-utils";
|
||||
|
||||
import type {
|
||||
InvoiceAmount,
|
||||
ItemAmount,
|
||||
ItemDescription,
|
||||
ItemDiscountPercentage,
|
||||
@ -31,40 +30,38 @@ export type IssuedInvoiceItemProps = {
|
||||
quantity: Maybe<ItemQuantity>;
|
||||
unitAmount: Maybe<ItemAmount>;
|
||||
|
||||
subtotalAmount: Maybe<InvoiceAmount>;
|
||||
subtotalAmount: ItemAmount;
|
||||
|
||||
itemDiscountPercentage: Maybe<ItemDiscountPercentage>;
|
||||
itemDiscountAmount: Maybe<InvoiceAmount>;
|
||||
itemDiscountAmount: ItemAmount;
|
||||
|
||||
globalDiscountPercentage: Maybe<ItemDiscountPercentage>;
|
||||
globalDiscountAmount: Maybe<InvoiceAmount>;
|
||||
globalDiscountAmount: ItemAmount;
|
||||
|
||||
totalDiscountAmount: Maybe<InvoiceAmount>;
|
||||
totalDiscountAmount: ItemAmount;
|
||||
|
||||
taxableAmount: Maybe<InvoiceAmount>;
|
||||
taxableAmount: ItemAmount;
|
||||
|
||||
ivaCode: Maybe<string>;
|
||||
ivaPercentage: Maybe<ItemDiscountPercentage>;
|
||||
ivaAmount: Maybe<InvoiceAmount>;
|
||||
ivaAmount: ItemAmount;
|
||||
|
||||
recCode: Maybe<string>;
|
||||
recPercentage: Maybe<ItemDiscountPercentage>;
|
||||
recAmount: Maybe<InvoiceAmount>;
|
||||
recAmount: ItemAmount;
|
||||
|
||||
retentionCode: Maybe<string>;
|
||||
retentionPercentage: Maybe<ItemDiscountPercentage>;
|
||||
retentionAmount: Maybe<InvoiceAmount>;
|
||||
retentionAmount: ItemAmount;
|
||||
|
||||
taxesAmount: Maybe<InvoiceAmount>;
|
||||
totalAmount: Maybe<InvoiceAmount>;
|
||||
taxesAmount: ItemAmount;
|
||||
totalAmount: ItemAmount;
|
||||
|
||||
languageCode: LanguageCode;
|
||||
currencyCode: CurrencyCode;
|
||||
};
|
||||
|
||||
export class IssuedInvoiceItem extends DomainEntity<IssuedInvoiceItemProps> {
|
||||
protected _isValued!: boolean;
|
||||
|
||||
public static create(
|
||||
props: IssuedInvoiceItemProps,
|
||||
id?: UniqueID
|
||||
@ -80,14 +77,12 @@ export class IssuedInvoiceItem extends DomainEntity<IssuedInvoiceItemProps> {
|
||||
|
||||
protected constructor(props: IssuedInvoiceItemProps, id?: UniqueID) {
|
||||
super(props, id);
|
||||
|
||||
this._isValued = this.quantity.isSome() || this.unitAmount.isSome();
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
get isValued(): boolean {
|
||||
return this._isValued;
|
||||
return this.quantity.isSome() || this.unitAmount.isSome();
|
||||
}
|
||||
|
||||
get description() {
|
||||
@ -144,7 +139,7 @@ export class IssuedInvoiceItem extends DomainEntity<IssuedInvoiceItemProps> {
|
||||
public get ivaPercentage(): Maybe<Percentage> {
|
||||
return this.props.ivaPercentage;
|
||||
}
|
||||
public get ivaAmount(): Maybe<InvoiceAmount> {
|
||||
public get ivaAmount(): ItemAmount {
|
||||
return this.props.ivaAmount;
|
||||
}
|
||||
|
||||
@ -154,7 +149,7 @@ export class IssuedInvoiceItem extends DomainEntity<IssuedInvoiceItemProps> {
|
||||
public get recPercentage(): Maybe<Percentage> {
|
||||
return this.props.recPercentage;
|
||||
}
|
||||
public get recAmount(): Maybe<InvoiceAmount> {
|
||||
public get recAmount(): ItemAmount {
|
||||
return this.props.recAmount;
|
||||
}
|
||||
|
||||
@ -164,7 +159,7 @@ export class IssuedInvoiceItem extends DomainEntity<IssuedInvoiceItemProps> {
|
||||
public get retentionPercentage(): Maybe<Percentage> {
|
||||
return this.props.retentionPercentage;
|
||||
}
|
||||
public get retentionAmount(): Maybe<InvoiceAmount> {
|
||||
public get retentionAmount(): ItemAmount {
|
||||
return this.props.retentionAmount;
|
||||
}
|
||||
|
||||
|
||||
@ -20,12 +20,11 @@ import {
|
||||
InvoiceTaxGroup,
|
||||
type ItemAmount,
|
||||
} from "../../common/value-objects";
|
||||
import type { ProformaTaxes } from "../entities";
|
||||
import { ProformaItems } from "../entities/proforma-items";
|
||||
|
||||
export type ProformaProps = {
|
||||
companyId: UniqueID;
|
||||
|
||||
isProforma: boolean;
|
||||
status: InvoiceStatus;
|
||||
|
||||
series: Maybe<InvoiceSerie>;
|
||||
@ -44,18 +43,37 @@ export type ProformaProps = {
|
||||
languageCode: LanguageCode;
|
||||
currencyCode: CurrencyCode;
|
||||
|
||||
items: ProformaItems;
|
||||
|
||||
paymentMethod: Maybe<InvoicePaymentMethod>;
|
||||
|
||||
items: ProformaItems;
|
||||
globalDiscountPercentage: Percentage;
|
||||
};
|
||||
|
||||
export interface IProforma extends AggregateRoot<ProformaProps> {
|
||||
getTaxes: ProformaTaxes;
|
||||
|
||||
getSubtotalAmount: InvoiceAmount;
|
||||
|
||||
getItemsDiscountAmount: InvoiceAmount;
|
||||
getGlobalDiscountPercentage: Percentage;
|
||||
getGlobalDiscountAmount: InvoiceAmount;
|
||||
getTotalDiscountAmount: InvoiceAmount;
|
||||
|
||||
getTaxableAmount: InvoiceAmount;
|
||||
|
||||
getIvaAmount: InvoiceAmount;
|
||||
getRecAmount: InvoiceAmount;
|
||||
getRetentionAmount: InvoiceAmount;
|
||||
|
||||
getTaxesAmount: InvoiceAmount;
|
||||
getTotalAmount: InvoiceAmount;
|
||||
}
|
||||
|
||||
export type ProformaPatchProps = Partial<Omit<ProformaProps, "companyId" | "items">> & {
|
||||
items?: ProformaItems;
|
||||
};
|
||||
|
||||
export class Proforma extends AggregateRoot<ProformaProps> {
|
||||
export class Proforma extends AggregateRoot<ProformaProps> implements IProforma {
|
||||
private _items!: ProformaItems;
|
||||
|
||||
protected constructor(props: ProformaProps, id?: UniqueID) {
|
||||
@ -120,10 +138,6 @@ export class Proforma extends AggregateRoot<ProformaProps> {
|
||||
return this.props.customerId;
|
||||
}
|
||||
|
||||
public get isProforma(): boolean {
|
||||
return this.props.isProforma;
|
||||
}
|
||||
|
||||
public get status(): InvoiceStatus {
|
||||
return this.props.status;
|
||||
}
|
||||
|
||||
@ -1 +1,2 @@
|
||||
export * from "./proforma-items";
|
||||
export * from "./proforma-taxes";
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import type { Tax } from "@erp/core/api";
|
||||
import { type CurrencyCode, DomainEntity, type LanguageCode, type UniqueID } from "@repo/rdx-ddd";
|
||||
import { type Maybe, Result } from "@repo/rdx-utils";
|
||||
|
||||
@ -6,8 +7,8 @@ import {
|
||||
type ItemDescription,
|
||||
ItemDiscountPercentage,
|
||||
ItemQuantity,
|
||||
type ItemTaxGroup,
|
||||
} from "../../../common";
|
||||
import type { ProformaItemTaxGroup } from "../../value-objects/proforma-item-tax-group.vo";
|
||||
|
||||
/**
|
||||
*
|
||||
@ -28,21 +29,64 @@ import {
|
||||
|
||||
export type ProformaItemProps = {
|
||||
description: Maybe<ItemDescription>;
|
||||
|
||||
quantity: Maybe<ItemQuantity>; // Cantidad de unidades
|
||||
unitAmount: Maybe<ItemAmount>; // Precio unitario en la moneda de la factura
|
||||
|
||||
itemDiscountPercentage: Maybe<ItemDiscountPercentage>; // % descuento
|
||||
globalDiscountPercentage: Maybe<ItemDiscountPercentage>; // % descuento de la cabecera
|
||||
itemDiscountPercentage: Maybe<ItemDiscountPercentage>; // % descuento de línea
|
||||
|
||||
taxes: ItemTaxGroup;
|
||||
taxes: ProformaItemTaxGroup;
|
||||
|
||||
// Estos campos vienen de la cabecera,
|
||||
// pero se necesitan para cálculos y representaciones de la línea.
|
||||
globalDiscountPercentage: Maybe<ItemDiscountPercentage>; // % descuento de la cabecera
|
||||
languageCode: LanguageCode; // Para formateos específicos de idioma
|
||||
currencyCode: CurrencyCode; // Para cálculos y formateos de moneda
|
||||
};
|
||||
|
||||
export interface IProformaItem extends ProformaItemProps {
|
||||
description: Maybe<ItemDescription>;
|
||||
|
||||
isValued: boolean; // Indica si el item tiene cantidad o precio (o ambos) para ser considerado "valorizado"
|
||||
|
||||
quantity: Maybe<ItemQuantity>;
|
||||
unitAmount: Maybe<ItemAmount>;
|
||||
|
||||
getSubtotalAmount: Maybe<ItemAmount>;
|
||||
|
||||
itemDiscountPercentage: Maybe<ItemDiscountPercentage>; // % descuento de línea
|
||||
getItemDiscountAmount: Maybe<ItemAmount>;
|
||||
|
||||
globalDiscountPercentage: Maybe<ItemDiscountPercentage>; // % descuento de la cabecera
|
||||
getGlobalDiscountAmount: Maybe<ItemAmount>;
|
||||
|
||||
getTotalDiscountAmount: Maybe<ItemAmount>;
|
||||
|
||||
getTaxableAmount: Maybe<ItemAmount>;
|
||||
|
||||
getIva: Maybe<Tax>;
|
||||
getIvaCode: Maybe<string>;
|
||||
getIvaPercentage: Maybe<ItemDiscountPercentage>;
|
||||
getIvaAmount: ItemAmount;
|
||||
|
||||
getRec: Maybe<Tax>;
|
||||
getRecCode: Maybe<string>;
|
||||
getRecPercentage: Maybe<ItemDiscountPercentage>;
|
||||
getRecAmount: ItemAmount;
|
||||
|
||||
getRetention: Maybe<Tax>;
|
||||
getRetentionCode: Maybe<string>;
|
||||
getRetentionPercentage: Maybe<ItemDiscountPercentage>;
|
||||
getRetentionAmount: ItemAmount;
|
||||
|
||||
getTaxesAmount: ItemAmount;
|
||||
getTotalAmount: ItemAmount;
|
||||
|
||||
languageCode: LanguageCode;
|
||||
currencyCode: CurrencyCode;
|
||||
};
|
||||
}
|
||||
|
||||
export class ProformaItem extends DomainEntity<ProformaItemProps> {
|
||||
protected _isValued!: boolean;
|
||||
|
||||
public static create(props: ProformaItemProps, id?: UniqueID): Result<ProformaItem, Error> {
|
||||
const item = new ProformaItem(props, id);
|
||||
|
||||
@ -55,14 +99,12 @@ export class ProformaItem extends DomainEntity<ProformaItemProps> {
|
||||
|
||||
protected constructor(props: ProformaItemProps, id?: UniqueID) {
|
||||
super(props, id);
|
||||
|
||||
this._isValued = this.quantity.isSome() || this.unitAmount.isSome();
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
get isValued(): boolean {
|
||||
return this._isValued;
|
||||
return this.props.quantity.isSome() || this.props.unitAmount.isSome();
|
||||
}
|
||||
|
||||
get description() {
|
||||
@ -105,6 +147,69 @@ export class ProformaItem extends DomainEntity<ProformaItemProps> {
|
||||
return this.getProps();
|
||||
}
|
||||
|
||||
// Getters específicos para cálculos y representaciones
|
||||
|
||||
public getSubtotalAmount(): ItemAmount {
|
||||
return this.calculateAllAmounts().subtotalAmount;
|
||||
}
|
||||
|
||||
public getItemDiscountAmount(): ItemAmount {
|
||||
return this.calculateAllAmounts().itemDiscountAmount;
|
||||
}
|
||||
|
||||
public getGlobalDiscountAmount(): ItemAmount {
|
||||
return this.calculateAllAmounts().globalDiscountAmount;
|
||||
}
|
||||
|
||||
public getTotalDiscountAmount(): ItemAmount {
|
||||
return this.calculateAllAmounts().totalDiscountAmount;
|
||||
}
|
||||
|
||||
public getTaxableAmount(): ItemAmount {
|
||||
return this.calculateAllAmounts().taxableAmount;
|
||||
}
|
||||
|
||||
public getIva(): Maybe<Tax> {
|
||||
return this.taxes.iva;
|
||||
}
|
||||
|
||||
public getIvaCode(): Maybe<string> {
|
||||
return this.taxes.iva.map((tax) => tax.code);
|
||||
}
|
||||
|
||||
public getIvaPercentage(): Maybe<ItemDiscountPercentage> {
|
||||
return this.taxes.iva.map((tax) => tax.percentage);
|
||||
}
|
||||
|
||||
public getIvaAmount(): ItemAmount {
|
||||
return this.calculateAllAmounts().ivaAmount;
|
||||
}
|
||||
|
||||
public getRec(): Maybe<Tax> {
|
||||
return this.taxes.rec;
|
||||
}
|
||||
|
||||
public getRecCode(): Maybe<string> {
|
||||
return this.taxes.rec.map((tax) => tax.code);
|
||||
}
|
||||
|
||||
public getRecPercentage(): Maybe<ItemDiscountPercentage> {
|
||||
return this.taxes.rec.map((tax) => tax.percentage);
|
||||
}
|
||||
|
||||
public getIndividualTaxAmounts() {
|
||||
const { ivaAmount, recAmount, retentionAmount } = this.calculateAllAmounts();
|
||||
return { ivaAmount, recAmount, retentionAmount };
|
||||
}
|
||||
|
||||
public getTaxesAmount(): ItemAmount {
|
||||
return this.calculateAllAmounts().taxesAmount;
|
||||
}
|
||||
|
||||
public getTotalAmount(): ItemAmount {
|
||||
return this.calculateAllAmounts().totalAmount;
|
||||
}
|
||||
|
||||
// Ayudantes
|
||||
|
||||
/**
|
||||
@ -162,13 +267,6 @@ export class ProformaItem extends DomainEntity<ProformaItemProps> {
|
||||
return itemDiscountAmount.add(globalDiscountAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Helper puro para calcular impuestos individuales.
|
||||
*/
|
||||
private _calculateIndividualTaxes(taxable: ItemAmount) {
|
||||
return this.taxes.calculateAmounts(taxable);
|
||||
}
|
||||
|
||||
// Cálculos
|
||||
|
||||
/**
|
||||
@ -201,7 +299,8 @@ export class ProformaItem extends DomainEntity<ProformaItemProps> {
|
||||
|
||||
const taxableAmount = subtotalAmount.subtract(totalDiscountAmount);
|
||||
|
||||
const { ivaAmount, recAmount, retentionAmount } = this._calculateIndividualTaxes(taxableAmount);
|
||||
// Calcular impuestos individuales a partir de la base imponible
|
||||
const { ivaAmount, recAmount, retentionAmount } = this.taxes.calculateAmounts(taxableAmount);
|
||||
|
||||
const taxesAmount = ivaAmount.add(recAmount).add(retentionAmount);
|
||||
const totalAmount = taxableAmount.add(taxesAmount);
|
||||
@ -223,37 +322,4 @@ export class ProformaItem extends DomainEntity<ProformaItemProps> {
|
||||
totalAmount,
|
||||
} as const;
|
||||
}
|
||||
|
||||
public getSubtotalAmount(): ItemAmount {
|
||||
return this.calculateAllAmounts().subtotalAmount;
|
||||
}
|
||||
|
||||
public getItemDiscountAmount(): ItemAmount {
|
||||
return this.calculateAllAmounts().itemDiscountAmount;
|
||||
}
|
||||
|
||||
public getGlobalDiscountAmount(): ItemAmount {
|
||||
return this.calculateAllAmounts().globalDiscountAmount;
|
||||
}
|
||||
|
||||
public getTotalDiscountAmount(): ItemAmount {
|
||||
return this.calculateAllAmounts().totalDiscountAmount;
|
||||
}
|
||||
|
||||
public getTaxableAmount(): ItemAmount {
|
||||
return this.calculateAllAmounts().taxableAmount;
|
||||
}
|
||||
|
||||
public getIndividualTaxAmounts() {
|
||||
const { ivaAmount, recAmount, retentionAmount } = this.calculateAllAmounts();
|
||||
return { ivaAmount, recAmount, retentionAmount };
|
||||
}
|
||||
|
||||
public getTaxesAmount(): ItemAmount {
|
||||
return this.calculateAllAmounts().taxesAmount;
|
||||
}
|
||||
|
||||
public getTotalAmount(): ItemAmount {
|
||||
return this.calculateAllAmounts().totalAmount;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
export * from "./proforma-tax.entity";
|
||||
export * from "./proforma-taxes.collection";
|
||||
@ -0,0 +1,70 @@
|
||||
import { DomainEntity, type Percentage, type UniqueID } from "@repo/rdx-ddd";
|
||||
import { type Maybe, Result } from "@repo/rdx-utils";
|
||||
|
||||
import type { InvoiceAmount } from "../../../common";
|
||||
|
||||
export type ProformaTaxProps = {
|
||||
taxableAmount: InvoiceAmount;
|
||||
|
||||
ivaCode: string;
|
||||
ivaPercentage: Percentage;
|
||||
ivaAmount: InvoiceAmount;
|
||||
|
||||
recCode: Maybe<string>;
|
||||
recPercentage: Maybe<Percentage>;
|
||||
recAmount: Maybe<InvoiceAmount>;
|
||||
|
||||
retentionCode: Maybe<string>;
|
||||
retentionPercentage: Maybe<Percentage>;
|
||||
retentionAmount: Maybe<InvoiceAmount>;
|
||||
|
||||
taxesAmount: InvoiceAmount;
|
||||
};
|
||||
|
||||
export class ProformaTax extends DomainEntity<ProformaTaxProps> {
|
||||
public static create(props: ProformaTaxProps, id?: UniqueID): Result<ProformaTax, Error> {
|
||||
return Result.ok(new ProformaTax(props, id));
|
||||
}
|
||||
|
||||
public get taxableAmount(): InvoiceAmount {
|
||||
return this.props.taxableAmount;
|
||||
}
|
||||
|
||||
public get ivaCode(): string {
|
||||
return this.props.ivaCode;
|
||||
}
|
||||
public get ivaPercentage(): Percentage {
|
||||
return this.props.ivaPercentage;
|
||||
}
|
||||
public get ivaAmount(): InvoiceAmount {
|
||||
return this.props.ivaAmount;
|
||||
}
|
||||
|
||||
public get recCode(): Maybe<string> {
|
||||
return this.props.recCode;
|
||||
}
|
||||
public get recPercentage(): Maybe<Percentage> {
|
||||
return this.props.recPercentage;
|
||||
}
|
||||
public get recAmount(): Maybe<InvoiceAmount> {
|
||||
return this.props.recAmount;
|
||||
}
|
||||
|
||||
public get retentionCode(): Maybe<string> {
|
||||
return this.props.retentionCode;
|
||||
}
|
||||
public get retentionPercentage(): Maybe<Percentage> {
|
||||
return this.props.retentionPercentage;
|
||||
}
|
||||
public get retentionAmount(): Maybe<InvoiceAmount> {
|
||||
return this.props.retentionAmount;
|
||||
}
|
||||
|
||||
public get taxesAmount(): InvoiceAmount {
|
||||
return this.props.taxesAmount;
|
||||
}
|
||||
|
||||
public getProps(): ProformaTaxProps {
|
||||
return this.props;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
import type { CurrencyCode, LanguageCode } from "@repo/rdx-ddd";
|
||||
import { Collection } from "@repo/rdx-utils";
|
||||
|
||||
import type { ProformaTax } from "./proforma-tax.entity";
|
||||
|
||||
export type ProformaTaxesProps = {
|
||||
taxes?: ProformaTax[];
|
||||
languageCode: LanguageCode;
|
||||
currencyCode: CurrencyCode;
|
||||
};
|
||||
|
||||
export class ProformaTaxes extends Collection<ProformaTax> {
|
||||
private _languageCode!: LanguageCode;
|
||||
private _currencyCode!: CurrencyCode;
|
||||
|
||||
constructor(props: ProformaTaxesProps) {
|
||||
super(props.taxes ?? []);
|
||||
this._languageCode = props.languageCode;
|
||||
this._currencyCode = props.currencyCode;
|
||||
}
|
||||
|
||||
public static create(props: ProformaTaxesProps): ProformaTaxes {
|
||||
return new ProformaTaxes(props);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
export * from "./proforma-item-tax-group.vo";
|
||||
export * from "./proforma-tax-group.vo";
|
||||
@ -2,17 +2,17 @@ import type { Tax } from "@erp/core/api";
|
||||
import { ValueObject } from "@repo/rdx-ddd";
|
||||
import { type Maybe, Result } from "@repo/rdx-utils";
|
||||
|
||||
import { ItemAmount } from ".";
|
||||
import { ItemAmount } from "../../common/value-objects";
|
||||
|
||||
export interface ItemTaxGroupProps {
|
||||
export interface ProformaItemTaxGroupProps {
|
||||
iva: Maybe<Tax>; // si existe
|
||||
rec: Maybe<Tax>; // si existe
|
||||
retention: Maybe<Tax>; // si existe
|
||||
}
|
||||
|
||||
export class ItemTaxGroup extends ValueObject<ItemTaxGroupProps> {
|
||||
static create(props: ItemTaxGroupProps) {
|
||||
return Result.ok(new ItemTaxGroup(props));
|
||||
export class ProformaItemTaxGroup extends ValueObject<ProformaItemTaxGroupProps> {
|
||||
static create(props: ProformaItemTaxGroupProps) {
|
||||
return Result.ok(new ProformaItemTaxGroup(props));
|
||||
}
|
||||
|
||||
calculateAmounts(taxableAmount: ItemAmount) {
|
||||
@ -0,0 +1,66 @@
|
||||
import type { Tax } from "@erp/core/api";
|
||||
import { ValueObject } from "@repo/rdx-ddd";
|
||||
import { type Maybe, Result } from "@repo/rdx-utils";
|
||||
|
||||
import type { InvoiceAmount } from "../../common";
|
||||
|
||||
export type ProformaTaxGroupProps = {
|
||||
taxableAmount: InvoiceAmount;
|
||||
|
||||
iva: Tax;
|
||||
ivaAmount: InvoiceAmount;
|
||||
|
||||
rec: Maybe<Tax>; // si existe
|
||||
recAmount: Maybe<InvoiceAmount>;
|
||||
|
||||
retention: Maybe<Tax>; // si existe
|
||||
retentionAmount: Maybe<InvoiceAmount>;
|
||||
|
||||
taxesAmount: InvoiceAmount;
|
||||
};
|
||||
|
||||
export class ProformaTaxGroup extends ValueObject<ProformaTaxGroupProps> {
|
||||
static create(props: ProformaTaxGroupProps) {
|
||||
return Result.ok(new ProformaTaxGroup(props));
|
||||
}
|
||||
|
||||
get taxableAmount(): InvoiceAmount {
|
||||
return this.props.taxableAmount;
|
||||
}
|
||||
|
||||
get iva(): Tax {
|
||||
return this.props.iva;
|
||||
}
|
||||
|
||||
get ivaAmount(): InvoiceAmount {
|
||||
return this.props.ivaAmount;
|
||||
}
|
||||
|
||||
get rec(): Maybe<Tax> {
|
||||
return this.props.rec;
|
||||
}
|
||||
|
||||
get recAmount(): Maybe<InvoiceAmount> {
|
||||
return this.props.recAmount;
|
||||
}
|
||||
|
||||
get retention(): Maybe<Tax> {
|
||||
return this.props.retention;
|
||||
}
|
||||
|
||||
get retentionAmount(): Maybe<InvoiceAmount> {
|
||||
return this.props.retentionAmount;
|
||||
}
|
||||
|
||||
get taxesAmount(): InvoiceAmount {
|
||||
return this.props.taxesAmount;
|
||||
}
|
||||
|
||||
getProps() {
|
||||
return this.props;
|
||||
}
|
||||
|
||||
toPrimitive() {
|
||||
return this.getProps();
|
||||
}
|
||||
}
|
||||
@ -33,7 +33,7 @@ export class CustomerInvoiceItemModel extends Model<
|
||||
declare unit_amount_scale: number;
|
||||
|
||||
// Subtotal (cantidad * importe unitario)
|
||||
declare subtotal_amount_value: CreationOptional<number | null>;
|
||||
declare subtotal_amount_value: number;
|
||||
declare subtotal_amount_scale: number;
|
||||
|
||||
// Discount percentage
|
||||
@ -41,7 +41,7 @@ export class CustomerInvoiceItemModel extends Model<
|
||||
declare discount_percentage_scale: number;
|
||||
|
||||
// Discount amount
|
||||
declare discount_amount_value: CreationOptional<number | null>;
|
||||
declare discount_amount_value: number;
|
||||
declare discount_amount_scale: number;
|
||||
|
||||
// Porcentaje de descuento global proporcional a esta línea.
|
||||
@ -49,15 +49,15 @@ export class CustomerInvoiceItemModel extends Model<
|
||||
declare global_discount_percentage_scale: number;
|
||||
|
||||
// Importe del descuento global para esta línea
|
||||
declare global_discount_amount_value: CreationOptional<number | null>;
|
||||
declare global_discount_amount_value: number;
|
||||
declare global_discount_amount_scale: number;
|
||||
|
||||
// Suma de los dos descuentos: el de la linea + el global
|
||||
declare total_discount_amount_value: CreationOptional<number | null>;
|
||||
declare total_discount_amount_value: number;
|
||||
declare total_discount_amount_scale: number;
|
||||
|
||||
// Taxable amount (base imponible tras los dos descuentos)
|
||||
declare taxable_amount_value: CreationOptional<number | null>;
|
||||
declare taxable_amount_value: number;
|
||||
declare taxable_amount_scale: number;
|
||||
|
||||
// IVA percentage
|
||||
@ -67,8 +67,7 @@ export class CustomerInvoiceItemModel extends Model<
|
||||
declare iva_percentage_scale: number;
|
||||
|
||||
// IVA amount
|
||||
|
||||
declare iva_amount_value: CreationOptional<number | null>;
|
||||
declare iva_amount_value: number;
|
||||
declare iva_amount_scale: number;
|
||||
|
||||
// Recargo de equivalencia percentage
|
||||
@ -78,7 +77,7 @@ export class CustomerInvoiceItemModel extends Model<
|
||||
declare rec_percentage_scale: number;
|
||||
|
||||
// Recargo de equivalencia amount
|
||||
declare rec_amount_value: CreationOptional<number | null>;
|
||||
declare rec_amount_value: number;
|
||||
declare rec_amount_scale: number;
|
||||
|
||||
// Retention percentage
|
||||
@ -88,15 +87,15 @@ export class CustomerInvoiceItemModel extends Model<
|
||||
declare retention_percentage_scale: number;
|
||||
|
||||
// Retention amount
|
||||
declare retention_amount_value: CreationOptional<number | null>;
|
||||
declare retention_amount_value: number;
|
||||
declare retention_amount_scale: number;
|
||||
|
||||
// Total taxes amount / taxes total
|
||||
declare taxes_amount_value: CreationOptional<number | null>;
|
||||
declare taxes_amount_value: number;
|
||||
declare taxes_amount_scale: number;
|
||||
|
||||
// Total
|
||||
declare total_amount_value: CreationOptional<number | null>;
|
||||
declare total_amount_value: number;
|
||||
declare total_amount_scale: number;
|
||||
|
||||
// Relaciones
|
||||
@ -176,8 +175,8 @@ export default (database: Sequelize) => {
|
||||
|
||||
subtotal_amount_value: {
|
||||
type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
|
||||
subtotal_amount_scale: {
|
||||
@ -200,8 +199,8 @@ export default (database: Sequelize) => {
|
||||
|
||||
discount_amount_value: {
|
||||
type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
|
||||
discount_amount_scale: {
|
||||
@ -224,8 +223,8 @@ export default (database: Sequelize) => {
|
||||
|
||||
global_discount_amount_value: {
|
||||
type: new DataTypes.BIGINT(),
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
|
||||
global_discount_amount_scale: {
|
||||
@ -236,8 +235,8 @@ export default (database: Sequelize) => {
|
||||
|
||||
total_discount_amount_value: {
|
||||
type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
|
||||
total_discount_amount_scale: {
|
||||
@ -248,8 +247,8 @@ export default (database: Sequelize) => {
|
||||
|
||||
taxable_amount_value: {
|
||||
type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
|
||||
taxable_amount_scale: {
|
||||
@ -278,8 +277,8 @@ export default (database: Sequelize) => {
|
||||
|
||||
iva_amount_value: {
|
||||
type: DataTypes.BIGINT,
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
iva_amount_scale: {
|
||||
type: DataTypes.SMALLINT,
|
||||
@ -307,8 +306,8 @@ export default (database: Sequelize) => {
|
||||
|
||||
rec_amount_value: {
|
||||
type: DataTypes.BIGINT,
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
rec_amount_scale: {
|
||||
type: DataTypes.SMALLINT,
|
||||
@ -336,8 +335,8 @@ export default (database: Sequelize) => {
|
||||
|
||||
retention_amount_value: {
|
||||
type: DataTypes.BIGINT,
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
retention_amount_scale: {
|
||||
type: DataTypes.SMALLINT,
|
||||
@ -347,8 +346,8 @@ export default (database: Sequelize) => {
|
||||
|
||||
taxes_amount_value: {
|
||||
type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
|
||||
taxes_amount_scale: {
|
||||
@ -359,8 +358,8 @@ export default (database: Sequelize) => {
|
||||
|
||||
total_amount_value: {
|
||||
type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
|
||||
total_amount_scale: {
|
||||
|
||||
@ -46,7 +46,7 @@ export class CustomerInvoiceTaxModel extends Model<
|
||||
declare rec_percentage_scale: number;
|
||||
|
||||
// Recargo de equivalencia amount
|
||||
declare rec_amount_value: CreationOptional<number | null>;
|
||||
declare rec_amount_value: number;
|
||||
declare rec_amount_scale: number;
|
||||
|
||||
// Retention percentage
|
||||
@ -56,7 +56,7 @@ export class CustomerInvoiceTaxModel extends Model<
|
||||
declare retention_percentage_scale: number;
|
||||
|
||||
// Retention amount
|
||||
declare retention_amount_value: CreationOptional<number | null>;
|
||||
declare retention_amount_value: number;
|
||||
declare retention_amount_scale: number;
|
||||
|
||||
// Total taxes amount / taxes total
|
||||
|
||||
@ -85,9 +85,10 @@ export class SequelizeIssuedInvoiceItemDomainMapper extends SequelizeDomainMappe
|
||||
);
|
||||
|
||||
const subtotalAmount = extractOrPushError(
|
||||
maybeFromNullableResult(raw.subtotal_amount_value, (value) =>
|
||||
ItemAmount.create({ value, currency_code: attributes.currencyCode?.code })
|
||||
),
|
||||
ItemAmount.create({
|
||||
value: raw.subtotal_amount_value,
|
||||
currency_code: attributes.currencyCode?.code,
|
||||
}),
|
||||
`items[${index}].subtotal_amount_value`,
|
||||
errors
|
||||
);
|
||||
@ -101,9 +102,10 @@ export class SequelizeIssuedInvoiceItemDomainMapper extends SequelizeDomainMappe
|
||||
);
|
||||
|
||||
const itemDiscountAmount = extractOrPushError(
|
||||
maybeFromNullableResult(raw.discount_amount_value, (value) =>
|
||||
ItemAmount.create({ value, currency_code: attributes.currencyCode?.code })
|
||||
),
|
||||
ItemAmount.create({
|
||||
value: raw.discount_amount_value,
|
||||
currency_code: attributes.currencyCode?.code,
|
||||
}),
|
||||
`items[${index}].discount_amount_value`,
|
||||
errors
|
||||
);
|
||||
@ -117,21 +119,32 @@ export class SequelizeIssuedInvoiceItemDomainMapper extends SequelizeDomainMappe
|
||||
);
|
||||
|
||||
const globalDiscountAmount = extractOrPushError(
|
||||
maybeFromNullableResult(raw.global_discount_amount_value, (value) =>
|
||||
ItemAmount.create({ value, currency_code: attributes.currencyCode?.code })
|
||||
),
|
||||
ItemAmount.create({
|
||||
value: raw.global_discount_amount_value,
|
||||
currency_code: attributes.currencyCode?.code,
|
||||
}),
|
||||
`items[${index}].global_discount_amount_value`,
|
||||
errors
|
||||
);
|
||||
|
||||
const totalDiscountAmount = extractOrPushError(
|
||||
maybeFromNullableResult(raw.total_discount_amount_value, (value) =>
|
||||
ItemAmount.create({ value, currency_code: attributes.currencyCode?.code })
|
||||
),
|
||||
ItemAmount.create({
|
||||
value: raw.total_discount_amount_value,
|
||||
currency_code: attributes.currencyCode?.code,
|
||||
}),
|
||||
`items[${index}].total_discount_amount_value`,
|
||||
errors
|
||||
);
|
||||
|
||||
const taxableAmount = extractOrPushError(
|
||||
ItemAmount.create({
|
||||
value: raw.taxable_amount_value,
|
||||
currency_code: attributes.currencyCode?.code,
|
||||
}),
|
||||
`items[${index}].taxable_amount_value`,
|
||||
errors
|
||||
);
|
||||
|
||||
const ivaCode = maybeFromNullableOrEmptyString(raw.iva_code);
|
||||
|
||||
const ivaPercentage = extractOrPushError(
|
||||
@ -143,9 +156,10 @@ export class SequelizeIssuedInvoiceItemDomainMapper extends SequelizeDomainMappe
|
||||
);
|
||||
|
||||
const ivaAmount = extractOrPushError(
|
||||
maybeFromNullableResult(raw.iva_amount_value, (value) =>
|
||||
ItemAmount.create({ value, currency_code: attributes.currencyCode?.code })
|
||||
),
|
||||
ItemAmount.create({
|
||||
value: raw.iva_amount_value,
|
||||
currency_code: attributes.currencyCode?.code,
|
||||
}),
|
||||
`items[${index}].iva_amount_value`,
|
||||
errors
|
||||
);
|
||||
@ -161,9 +175,10 @@ export class SequelizeIssuedInvoiceItemDomainMapper extends SequelizeDomainMappe
|
||||
);
|
||||
|
||||
const recAmount = extractOrPushError(
|
||||
maybeFromNullableResult(raw.rec_amount_value, (value) =>
|
||||
ItemAmount.create({ value, currency_code: attributes.currencyCode?.code })
|
||||
),
|
||||
ItemAmount.create({
|
||||
value: raw.rec_amount_value,
|
||||
currency_code: attributes.currencyCode?.code,
|
||||
}),
|
||||
`items[${index}].rec_amount_value`,
|
||||
errors
|
||||
);
|
||||
@ -179,25 +194,28 @@ export class SequelizeIssuedInvoiceItemDomainMapper extends SequelizeDomainMappe
|
||||
);
|
||||
|
||||
const retentionAmount = extractOrPushError(
|
||||
maybeFromNullableResult(raw.retention_amount_value, (value) =>
|
||||
ItemAmount.create({ value, currency_code: attributes.currencyCode?.code })
|
||||
),
|
||||
ItemAmount.create({
|
||||
value: raw.retention_amount_value,
|
||||
currency_code: attributes.currencyCode?.code,
|
||||
}),
|
||||
`items[${index}].retention_amount_value`,
|
||||
errors
|
||||
);
|
||||
|
||||
const taxesAmount = extractOrPushError(
|
||||
maybeFromNullableResult(raw.taxes_amount_value, (value) =>
|
||||
ItemAmount.create({ value, currency_code: attributes.currencyCode?.code })
|
||||
),
|
||||
ItemAmount.create({
|
||||
value: raw.taxes_amount_value,
|
||||
currency_code: attributes.currencyCode?.code,
|
||||
}),
|
||||
`items[${index}].taxes_amount_value`,
|
||||
errors
|
||||
);
|
||||
|
||||
const totalAmount = extractOrPushError(
|
||||
maybeFromNullableResult(raw.total_amount_value, (value) =>
|
||||
ItemAmount.create({ value, currency_code: attributes.currencyCode?.code })
|
||||
),
|
||||
ItemAmount.create({
|
||||
value: raw.total_amount_value,
|
||||
currency_code: attributes.currencyCode?.code,
|
||||
}),
|
||||
`items[${index}].total_amount_value`,
|
||||
errors
|
||||
);
|
||||
@ -218,6 +236,8 @@ export class SequelizeIssuedInvoiceItemDomainMapper extends SequelizeDomainMappe
|
||||
globalDiscountAmount,
|
||||
totalDiscountAmount,
|
||||
|
||||
taxableAmount,
|
||||
|
||||
ivaCode,
|
||||
ivaPercentage,
|
||||
ivaAmount,
|
||||
@ -334,10 +354,8 @@ export class SequelizeIssuedInvoiceItemDomainMapper extends SequelizeDomainMappe
|
||||
maybeToNullable(source.unitAmount, (v) => v.toPrimitive().scale) ??
|
||||
ItemAmount.DEFAULT_SCALE,
|
||||
|
||||
subtotal_amount_value: maybeToNullable(source.subtotalAmount, (v) => v.toPrimitive().value),
|
||||
subtotal_amount_scale:
|
||||
maybeToNullable(source.subtotalAmount, (v) => v.toPrimitive().scale) ??
|
||||
ItemAmount.DEFAULT_SCALE,
|
||||
subtotal_amount_value: source.subtotalAmount.toPrimitive().value,
|
||||
subtotal_amount_scale: source.subtotalAmount.toPrimitive().scale,
|
||||
|
||||
discount_percentage_value: maybeToNullable(
|
||||
source.itemDiscountPercentage,
|
||||
@ -347,13 +365,8 @@ export class SequelizeIssuedInvoiceItemDomainMapper extends SequelizeDomainMappe
|
||||
maybeToNullable(source.itemDiscountPercentage, (v) => v.toPrimitive().scale) ??
|
||||
ItemDiscountPercentage.DEFAULT_SCALE,
|
||||
|
||||
discount_amount_value: maybeToNullable(
|
||||
source.itemDiscountAmount,
|
||||
(v) => v.toPrimitive().value
|
||||
),
|
||||
discount_amount_scale:
|
||||
maybeToNullable(source.itemDiscountPercentage, (v) => v.toPrimitive().scale) ??
|
||||
ItemDiscountPercentage.DEFAULT_SCALE,
|
||||
discount_amount_value: source.itemDiscountAmount.toPrimitive().value,
|
||||
discount_amount_scale: source.itemDiscountAmount.toPrimitive().scale,
|
||||
|
||||
global_discount_percentage_value: maybeToNullable(
|
||||
source.globalDiscountPercentage,
|
||||
@ -363,30 +376,14 @@ export class SequelizeIssuedInvoiceItemDomainMapper extends SequelizeDomainMappe
|
||||
maybeToNullable(source.globalDiscountPercentage, (v) => v.toPrimitive().scale) ??
|
||||
ItemDiscountPercentage.DEFAULT_SCALE,
|
||||
|
||||
global_discount_amount_value: maybeToNullable(
|
||||
source.globalDiscountAmount,
|
||||
(v) => v.toPrimitive().value
|
||||
),
|
||||
global_discount_amount_scale:
|
||||
maybeToNullable(source.globalDiscountAmount, (v) => v.toPrimitive().scale) ??
|
||||
ItemAmount.DEFAULT_SCALE,
|
||||
global_discount_amount_value: source.globalDiscountAmount.value,
|
||||
global_discount_amount_scale: source.globalDiscountAmount.scale,
|
||||
|
||||
total_discount_amount_value: maybeToNullable(
|
||||
source.totalDiscountAmount,
|
||||
(v) => v.toPrimitive().value
|
||||
),
|
||||
total_discount_amount_scale:
|
||||
maybeToNullable(source.totalDiscountAmount, (v) => v.toPrimitive().scale) ??
|
||||
ItemAmount.DEFAULT_SCALE,
|
||||
total_discount_amount_value: source.totalDiscountAmount.value,
|
||||
total_discount_amount_scale: source.totalDiscountAmount.scale,
|
||||
|
||||
// Te has quedado aquí --- IGNORE ---
|
||||
// !!!!!!!!!!!!!!!!!!!
|
||||
|
||||
//
|
||||
taxable_amount_value: maybeToNullable(source.taxableAmount, (v) => v.toPrimitive().value),
|
||||
taxable_amount_scale:
|
||||
maybeToNullable(source.taxableAmount, (v) => v.toPrimitive().scale) ??
|
||||
ItemAmount.DEFAULT_SCALE,
|
||||
taxable_amount_value: source.taxableAmount.value,
|
||||
taxable_amount_scale: source.taxableAmount.scale,
|
||||
|
||||
// IVA
|
||||
iva_code: maybeToNullableString(source.ivaCode),
|
||||
@ -395,8 +392,8 @@ export class SequelizeIssuedInvoiceItemDomainMapper extends SequelizeDomainMappe
|
||||
iva_percentage_scale:
|
||||
maybeToNullable(source.ivaPercentage, (v) => v.toPrimitive().scale) ?? 2,
|
||||
|
||||
iva_amount_value: maybeToNullable(source.ivaAmount, (v) => v.toPrimitive().value),
|
||||
iva_amount_scale: maybeToNullable(source.ivaAmount, (v) => v.toPrimitive().scale) ?? 4,
|
||||
iva_amount_value: source.ivaAmount.value,
|
||||
iva_amount_scale: source.ivaAmount.scale,
|
||||
|
||||
// REC
|
||||
rec_code: maybeToNullableString(source.recCode),
|
||||
@ -405,8 +402,8 @@ export class SequelizeIssuedInvoiceItemDomainMapper extends SequelizeDomainMappe
|
||||
rec_percentage_scale:
|
||||
maybeToNullable(source.recPercentage, (v) => v.toPrimitive().scale) ?? 2,
|
||||
|
||||
rec_amount_value: maybeToNullable(source.recAmount, (v) => v.toPrimitive().value),
|
||||
rec_amount_scale: maybeToNullable(source.recAmount, (v) => v.toPrimitive().scale) ?? 4,
|
||||
rec_amount_value: source.recAmount.value,
|
||||
rec_amount_scale: source.recAmount.scale,
|
||||
|
||||
// RET
|
||||
retention_code: maybeToNullableString(source.retentionCode),
|
||||
@ -418,21 +415,16 @@ export class SequelizeIssuedInvoiceItemDomainMapper extends SequelizeDomainMappe
|
||||
retention_percentage_scale:
|
||||
maybeToNullable(source.retentionPercentage, (v) => v.toPrimitive().scale) ?? 2,
|
||||
|
||||
retention_amount_value: maybeToNullable(source.retentionAmount, (v) => v.toPrimitive().value),
|
||||
retention_amount_scale:
|
||||
maybeToNullable(source.retentionAmount, (v) => v.toPrimitive().scale) ?? 4,
|
||||
retention_amount_value: source.retentionAmount.value,
|
||||
retention_amount_scale: source.retentionAmount.scale,
|
||||
|
||||
//
|
||||
taxes_amount_value: maybeToNullable(source.taxesAmount, (v) => v.toPrimitive().value),
|
||||
taxes_amount_scale:
|
||||
maybeToNullable(source.taxesAmount, (v) => v.toPrimitive().scale) ??
|
||||
ItemAmount.DEFAULT_SCALE,
|
||||
taxes_amount_value: source.taxesAmount.value,
|
||||
taxes_amount_scale: source.taxesAmount.scale,
|
||||
|
||||
//
|
||||
total_amount_value: maybeToNullable(source.totalAmount, (v) => v.toPrimitive().value),
|
||||
total_amount_scale:
|
||||
maybeToNullable(source.totalAmount, (v) => v.toPrimitive().scale) ??
|
||||
ItemAmount.DEFAULT_SCALE,
|
||||
total_amount_value: source.totalAmount.value,
|
||||
total_amount_scale: source.totalAmount.scale,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,6 @@ export const GetIssuedInvoiceByIdResponseSchema = z.object({
|
||||
id: z.uuid(),
|
||||
company_id: z.uuid(),
|
||||
|
||||
is_proforma: z.string(),
|
||||
invoice_number: z.string(),
|
||||
status: z.string(),
|
||||
series: z.string(),
|
||||
|
||||
@ -5,7 +5,6 @@ export const ListIssuedInvoicesResponseSchema = createPaginatedListSchema(
|
||||
z.object({
|
||||
id: z.uuid(),
|
||||
company_id: z.uuid(),
|
||||
is_proforma: z.boolean(),
|
||||
|
||||
customer_id: z.string(),
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user