v0.6.0 - Subida a producción
This commit is contained in:
parent
67dc91eced
commit
330240deaa
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "WEB: Vite (Chrome)",
|
"name": "WEB: Vite (Chrome)",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/factuges-server",
|
"name": "@erp/factuges-server",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsup src/index.ts --config tsup.config.ts",
|
"build": "tsup src/index.ts --config tsup.config.ts",
|
||||||
@ -37,8 +37,6 @@
|
|||||||
"@erp/core": "workspace:*",
|
"@erp/core": "workspace:*",
|
||||||
"@erp/customer-invoices": "workspace:*",
|
"@erp/customer-invoices": "workspace:*",
|
||||||
"@erp/customers": "workspace:*",
|
"@erp/customers": "workspace:*",
|
||||||
"@erp/factuges": "workspace:*",
|
|
||||||
"@erp/suppliers": "workspace:*",
|
|
||||||
"@repo/rdx-logger": "workspace:*",
|
"@repo/rdx-logger": "workspace:*",
|
||||||
"@repo/rdx-utils": "workspace:*",
|
"@repo/rdx-utils": "workspace:*",
|
||||||
"bcrypt": "^6.0.0",
|
"bcrypt": "^6.0.0",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import customerInvoicesAPIModule from "@erp/customer-invoices/api";
|
import customerInvoicesAPIModule from "@erp/customer-invoices/api";
|
||||||
import customersAPIModule from "@erp/customers/api";
|
import customersAPIModule from "@erp/customers/api";
|
||||||
import factuGESAPIModule from "@erp/factuges/api";
|
|
||||||
import suppliersAPIModule from "@erp/suppliers/api";
|
//import suppliersAPIModule from "@erp/suppliers/api";
|
||||||
|
|
||||||
import { registerModule } from "./lib";
|
import { registerModule } from "./lib";
|
||||||
|
|
||||||
@ -9,6 +9,5 @@ export const registerModules = () => {
|
|||||||
//registerModule(authAPIModule);
|
//registerModule(authAPIModule);
|
||||||
registerModule(customersAPIModule);
|
registerModule(customersAPIModule);
|
||||||
registerModule(customerInvoicesAPIModule);
|
registerModule(customerInvoicesAPIModule);
|
||||||
registerModule(factuGESAPIModule);
|
//registerModule(suppliersAPIModule);
|
||||||
registerModule(suppliersAPIModule);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/factuges-web",
|
"name": "@erp/factuges-web",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --host --clearScreen false",
|
"dev": "vite --host --clearScreen false",
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./src/*"]
|
"@/*": ["./src/*"]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./src/*"]
|
"@/*": ["./src/*"]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/auth",
|
"name": "@erp/auth",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
"paths": {
|
||||||
"@erp/auth/*": ["./src/*"]
|
"@erp/auth/*": ["./src/*"]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/core",
|
"name": "@erp/core",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
export const formatDate = (value: string) => {
|
|
||||||
return new Date(value).toLocaleDateString();
|
|
||||||
};
|
|
||||||
@ -1,3 +1,2 @@
|
|||||||
export * from "./date-func";
|
|
||||||
export * from "./form-utils";
|
export * from "./form-utils";
|
||||||
export * from "./http-url-utils";
|
export * from "./http-url-utils";
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
"paths": {
|
||||||
"@erp/core/*": ["./src/*"]
|
"@erp/core/*": ["./src/*"]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/customer-invoices",
|
"name": "@erp/customer-invoices",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import type { UniqueID } from "@repo/rdx-ddd";
|
import type { UniqueID } from "@repo/rdx-ddd";
|
||||||
import type { Maybe, Result } from "@repo/rdx-utils";
|
import type { Result } from "@repo/rdx-utils";
|
||||||
|
|
||||||
import type { InvoiceNumber, InvoiceSerie } from "../../../domain";
|
import type { InvoiceNumber, InvoiceSerie } from "../../../domain";
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ export interface IIssuedInvoiceNumberGenerator {
|
|||||||
*/
|
*/
|
||||||
getNextForCompany(
|
getNextForCompany(
|
||||||
companyId: UniqueID,
|
companyId: UniqueID,
|
||||||
series: Maybe<InvoiceSerie>,
|
series: InvoiceSerie,
|
||||||
transaction: unknown
|
transaction: unknown
|
||||||
): Promise<Result<InvoiceNumber, Error>>;
|
): Promise<Result<InvoiceNumber, Error>>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -98,15 +98,15 @@ export class ProformaToIssuedInvoiceConverter implements IProformaToIssuedInvoic
|
|||||||
companyId: proforma.companyId,
|
companyId: proforma.companyId,
|
||||||
status: InvoiceStatus.issued(),
|
status: InvoiceStatus.issued(),
|
||||||
|
|
||||||
series: proforma.series,
|
series: proforma.series.getOrUndefined()!,
|
||||||
proformaId: proforma.id,
|
linkedProformaId: proforma.id,
|
||||||
|
|
||||||
invoiceNumber: proforma.invoiceNumber,
|
invoiceNumber: proforma.invoiceNumber,
|
||||||
|
|
||||||
invoiceDate: UtcDate.today(), // La fecha de la factura es la fecha de emisión, no la de la proforma
|
invoiceDate: UtcDate.today(), // La fecha de la factura es la fecha de emisión, no la de la proforma
|
||||||
operationDate: proforma.operationDate,
|
operationDate: proforma.operationDate,
|
||||||
|
|
||||||
description: proforma.description,
|
description: proforma.description.getOrUndefined()!,
|
||||||
|
|
||||||
languageCode: proforma.languageCode,
|
languageCode: proforma.languageCode,
|
||||||
currencyCode: proforma.currencyCode,
|
currencyCode: proforma.currencyCode,
|
||||||
@ -116,7 +116,7 @@ export class ProformaToIssuedInvoiceConverter implements IProformaToIssuedInvoic
|
|||||||
paymentMethod: proforma.paymentMethod,
|
paymentMethod: proforma.paymentMethod,
|
||||||
|
|
||||||
customerId: proforma.customerId,
|
customerId: proforma.customerId,
|
||||||
recipient: proforma.recipient,
|
recipient: proforma.recipient.getOrUndefined()!,
|
||||||
|
|
||||||
items: issuedItems,
|
items: issuedItems,
|
||||||
|
|
||||||
|
|||||||
@ -53,9 +53,7 @@ export class IssuedInvoiceFullSnapshotBuilder implements IIssuedInvoiceFullSnaps
|
|||||||
customer_id: invoice.customerId.toString(),
|
customer_id: invoice.customerId.toString(),
|
||||||
recipient,
|
recipient,
|
||||||
|
|
||||||
linked_proforma_id: maybeToNullable(invoice.linkedProformaId, (linkedId) =>
|
linked_proforma_id: invoice.linkedProformaId.toString(),
|
||||||
linkedId.toString()
|
|
||||||
),
|
|
||||||
|
|
||||||
taxes,
|
taxes,
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +1 @@
|
|||||||
export * from "./proforma-summary-snapshot.interface";
|
|
||||||
export * from "./proforma-summary-snapshot-builder";
|
export * from "./proforma-summary-snapshot-builder";
|
||||||
|
|||||||
@ -1,15 +1,14 @@
|
|||||||
import type { ISnapshotBuilder } from "@erp/core/api";
|
import type { ISnapshotBuilder } from "@erp/core/api";
|
||||||
import { maybeToEmptyString, maybeToNullable } from "@repo/rdx-ddd";
|
import { maybeToEmptyString, maybeToNullable } from "@repo/rdx-ddd";
|
||||||
|
|
||||||
|
import type { ProformaSummaryDTO } from "../../../../../common";
|
||||||
import type { ProformaSummary } from "../../models";
|
import type { ProformaSummary } from "../../models";
|
||||||
|
|
||||||
import type { IProformaSummarySnapshot } from "./proforma-summary-snapshot.interface";
|
|
||||||
|
|
||||||
export interface IProformaSummarySnapshotBuilder
|
export interface IProformaSummarySnapshotBuilder
|
||||||
extends ISnapshotBuilder<ProformaSummary, IProformaSummarySnapshot> {}
|
extends ISnapshotBuilder<ProformaSummary, ProformaSummaryDTO> {}
|
||||||
|
|
||||||
export class ProformaSummarySnapshotBuilder implements IProformaSummarySnapshotBuilder {
|
export class ProformaSummarySnapshotBuilder implements IProformaSummarySnapshotBuilder {
|
||||||
toOutput(proforma: ProformaSummary): IProformaSummarySnapshot {
|
toOutput(proforma: ProformaSummary): ProformaSummaryDTO {
|
||||||
const recipient = proforma.recipient.toObjectString();
|
const recipient = proforma.recipient.toObjectString();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -18,7 +17,7 @@ export class ProformaSummarySnapshotBuilder implements IProformaSummarySnapshotB
|
|||||||
is_proforma: proforma.isProforma,
|
is_proforma: proforma.isProforma,
|
||||||
|
|
||||||
invoice_number: proforma.invoiceNumber.toString(),
|
invoice_number: proforma.invoiceNumber.toString(),
|
||||||
status: proforma.status.toPrimitive(),
|
status: proforma.status.toPrimitive() as ProformaSummaryDTO["status"],
|
||||||
series: maybeToNullable(proforma.series, (value) => value.toString()),
|
series: maybeToNullable(proforma.series, (value) => value.toString()),
|
||||||
|
|
||||||
invoice_date: proforma.invoiceDate.toDateString(),
|
invoice_date: proforma.invoiceDate.toDateString(),
|
||||||
|
|||||||
@ -1,42 +0,0 @@
|
|||||||
/**
|
|
||||||
* Fijarse en ListProformasResponseDTO["items"]
|
|
||||||
*/
|
|
||||||
export interface IProformaSummarySnapshot {
|
|
||||||
id: string;
|
|
||||||
company_id: string;
|
|
||||||
is_proforma: boolean;
|
|
||||||
|
|
||||||
invoice_number: string;
|
|
||||||
status: string;
|
|
||||||
series: string | null;
|
|
||||||
|
|
||||||
invoice_date: string;
|
|
||||||
operation_date: string | null;
|
|
||||||
|
|
||||||
language_code: string;
|
|
||||||
currency_code: string;
|
|
||||||
|
|
||||||
reference: string | null;
|
|
||||||
description: string | null;
|
|
||||||
|
|
||||||
customer_id: string;
|
|
||||||
recipient: {
|
|
||||||
id: string;
|
|
||||||
tin: string;
|
|
||||||
name: string;
|
|
||||||
street: string | null;
|
|
||||||
street2: string | null;
|
|
||||||
city: string | null;
|
|
||||||
postal_code: string | null;
|
|
||||||
province: string | null;
|
|
||||||
country: string | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
subtotal_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 };
|
|
||||||
|
|
||||||
linked_invoice_id: string | null;
|
|
||||||
}
|
|
||||||
@ -32,7 +32,7 @@ export interface IIssuedInvoiceCreateProps {
|
|||||||
companyId: UniqueID;
|
companyId: UniqueID;
|
||||||
status: InvoiceStatus;
|
status: InvoiceStatus;
|
||||||
|
|
||||||
linkedProformaId: Maybe<UniqueID>; // <- id de la proforma padre en caso de issue
|
linkedProformaId: UniqueID; // <- id de la proforma padre en caso de issue
|
||||||
|
|
||||||
series: InvoiceSerie;
|
series: InvoiceSerie;
|
||||||
invoiceNumber: InvoiceNumber;
|
invoiceNumber: InvoiceNumber;
|
||||||
@ -178,7 +178,7 @@ export class IssuedInvoice
|
|||||||
return this.props.customerId;
|
return this.props.customerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get linkedProformaId(): Maybe<UniqueID> {
|
public get linkedProformaId(): UniqueID {
|
||||||
return this.props.linkedProformaId;
|
return this.props.linkedProformaId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -304,6 +304,97 @@ export class Proforma extends AggregateRoot<ProformaInternalProps> implements IP
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.series.isNone()) {
|
||||||
|
return Result.fail(
|
||||||
|
new DomainValidationError(
|
||||||
|
"MISSING_SERIES",
|
||||||
|
"series",
|
||||||
|
"Series is required to issue the proforma"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.description.isNone()) {
|
||||||
|
return Result.fail(
|
||||||
|
new DomainValidationError(
|
||||||
|
"MISSING_DESCRIPTION",
|
||||||
|
"description",
|
||||||
|
"Description is required to issue the proforma"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.recipient.isNone()) {
|
||||||
|
return Result.fail(
|
||||||
|
new DomainValidationError(
|
||||||
|
"MISSING_RECIPIENT",
|
||||||
|
"recipient",
|
||||||
|
"Recipient is required to issue the proforma"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.items.size() === 0) {
|
||||||
|
return Result.fail(
|
||||||
|
new DomainValidationError(
|
||||||
|
"NO_ITEMS",
|
||||||
|
"items",
|
||||||
|
"At least one item is required to issue the proforma"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const invalidItem = this.items.find((item) => !item.isValued());
|
||||||
|
if (invalidItem) {
|
||||||
|
return Result.fail(
|
||||||
|
new DomainValidationError(
|
||||||
|
"INVALID_ITEM",
|
||||||
|
"items",
|
||||||
|
`Item at position ${invalidItem.id} is not valid for invoicing`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.paymentMethod.isNone()) {
|
||||||
|
return Result.fail(
|
||||||
|
new DomainValidationError(
|
||||||
|
"MISSING_PAYMENT_METHOD",
|
||||||
|
"paymentMethod",
|
||||||
|
"Payment method is required to issue the proforma"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if (this.operationDate.isSome() && this.operationDate.unwrap() > new Date()) {
|
||||||
|
return Result.fail(
|
||||||
|
new DomainValidationError(
|
||||||
|
"INVALID_OPERATION_DATE",
|
||||||
|
"operationDate",
|
||||||
|
"Operation date cannot be in the future"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.operationDate.isSome() && this.operationDate.unwrap() < this.invoiceDate) {
|
||||||
|
return Result.fail(
|
||||||
|
new DomainValidationError(
|
||||||
|
"INVALID_OPERATION_DATE",
|
||||||
|
"operationDate",
|
||||||
|
"Operation date cannot be before invoice date"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
if (this.linkedInvoiceId.isSome()) {
|
||||||
|
return Result.fail(
|
||||||
|
new DomainValidationError(
|
||||||
|
"LINKED_INVOICE_NOT_ALLOWED",
|
||||||
|
"linkedInvoiceId",
|
||||||
|
"Proforma cannot be linked to an invoice"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
this.props.status = InvoiceStatus.issued();
|
this.props.status = InvoiceStatus.issued();
|
||||||
return Result.ok();
|
return Result.ok();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,7 +64,7 @@ export class SequelizeIssuedInvoiceDomainMapper extends SequelizeDomainMapper<
|
|||||||
const customerId = extractOrPushError(UniqueID.create(raw.customer_id), "customer_id", errors);
|
const customerId = extractOrPushError(UniqueID.create(raw.customer_id), "customer_id", errors);
|
||||||
|
|
||||||
const linkedProformaId = extractOrPushError(
|
const linkedProformaId = extractOrPushError(
|
||||||
maybeFromNullableResult(raw.proforma_id, (v) => UniqueID.create(String(v))),
|
UniqueID.create(String(raw.proforma_id)),
|
||||||
"proforma_id",
|
"proforma_id",
|
||||||
errors
|
errors
|
||||||
);
|
);
|
||||||
@ -435,6 +435,7 @@ export class SequelizeIssuedInvoiceDomainMapper extends SequelizeDomainMapper<
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3) Cliente
|
// 3) Cliente
|
||||||
|
console.debug(source.recipient);
|
||||||
const recipient = this._recipientMapper.mapToPersistence(source.recipient, {
|
const recipient = this._recipientMapper.mapToPersistence(source.recipient, {
|
||||||
errors,
|
errors,
|
||||||
parent: source,
|
parent: source,
|
||||||
@ -450,6 +451,7 @@ export class SequelizeIssuedInvoiceDomainMapper extends SequelizeDomainMapper<
|
|||||||
|
|
||||||
// 5) Si hubo errores de mapeo, devolvemos colección de validación
|
// 5) Si hubo errores de mapeo, devolvemos colección de validación
|
||||||
if (errors.length > 0) {
|
if (errors.length > 0) {
|
||||||
|
console.error("Errors mapping issued invoice to persistence:", errors);
|
||||||
return Result.fail(
|
return Result.fail(
|
||||||
new ValidationErrorCollection("Customer invoice mapping to persistence failed", errors)
|
new ValidationErrorCollection("Customer invoice mapping to persistence failed", errors)
|
||||||
);
|
);
|
||||||
@ -467,7 +469,7 @@ export class SequelizeIssuedInvoiceDomainMapper extends SequelizeDomainMapper<
|
|||||||
// Flags / estado / serie / número
|
// Flags / estado / serie / número
|
||||||
is_proforma: false,
|
is_proforma: false,
|
||||||
status: source.status.toPrimitive(),
|
status: source.status.toPrimitive(),
|
||||||
proforma_id: maybeToNullable(source.linkedProformaId, (v) => v.toPrimitive()),
|
proforma_id: source.linkedProformaId.toPrimitive(),
|
||||||
|
|
||||||
series: source.series.toPrimitive(),
|
series: source.series.toPrimitive(),
|
||||||
invoice_number: source.invoiceNumber.toPrimitive(),
|
invoice_number: source.invoiceNumber.toPrimitive(),
|
||||||
|
|||||||
@ -15,11 +15,7 @@ import {
|
|||||||
} from "@repo/rdx-ddd";
|
} from "@repo/rdx-ddd";
|
||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
|
|
||||||
import {
|
import { type IIssuedInvoiceCreateProps, InvoiceRecipient } from "../../../../../../domain";
|
||||||
type IIssuedInvoiceCreateProps,
|
|
||||||
InvoiceRecipient,
|
|
||||||
type IssuedInvoice,
|
|
||||||
} from "../../../../../../domain";
|
|
||||||
import type { CustomerInvoiceModel } from "../../../../../common";
|
import type { CustomerInvoiceModel } from "../../../../../common";
|
||||||
|
|
||||||
export class SequelizeIssuedInvoiceRecipientDomainMapper {
|
export class SequelizeIssuedInvoiceRecipientDomainMapper {
|
||||||
@ -118,27 +114,10 @@ export class SequelizeIssuedInvoiceRecipientDomainMapper {
|
|||||||
* En caso contrario, se agrega un error de validación.
|
* En caso contrario, se agrega un error de validación.
|
||||||
*/
|
*/
|
||||||
mapToPersistence(source: InvoiceRecipient, params?: MapperParamsType) {
|
mapToPersistence(source: InvoiceRecipient, params?: MapperParamsType) {
|
||||||
const { errors, parent } = params as {
|
/*const { errors, parent } = params as {
|
||||||
parent: IssuedInvoice;
|
parent: IssuedInvoice;
|
||||||
errors: ValidationErrorDetail[];
|
errors: ValidationErrorDetail[];
|
||||||
};
|
};*/
|
||||||
|
|
||||||
const { hasRecipient } = parent;
|
|
||||||
|
|
||||||
// Validación: facturas emitidas deben tener destinatario.
|
|
||||||
if (!hasRecipient) {
|
|
||||||
errors.push({
|
|
||||||
path: "recipient",
|
|
||||||
message: "[InvoiceRecipientDomainMapper] Issued customer invoice without recipient data",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si hay errores previos, devolvemos fallo de validación inmediatamente.
|
|
||||||
if (errors.length > 0) {
|
|
||||||
return Result.fail(
|
|
||||||
new ValidationErrorCollection("Customer invoice mapping to persistence failed", errors)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const recipient = source;
|
const recipient = source;
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import type { UniqueID } from "@repo/rdx-ddd";
|
import type { UniqueID } from "@repo/rdx-ddd";
|
||||||
import { type Maybe, Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import { type Transaction, type WhereOptions, literal } from "sequelize";
|
import { type Transaction, type WhereOptions, literal } from "sequelize";
|
||||||
|
|
||||||
import type { IIssuedInvoiceNumberGenerator } from "../../../../../application/issued-invoices";
|
import type { IIssuedInvoiceNumberGenerator } from "../../../../../application/issued-invoices";
|
||||||
@ -12,7 +12,7 @@ import { CustomerInvoiceModel } from "../../../../common/persistence";
|
|||||||
export class SequelizeIssuedInvoiceNumberGenerator implements IIssuedInvoiceNumberGenerator {
|
export class SequelizeIssuedInvoiceNumberGenerator implements IIssuedInvoiceNumberGenerator {
|
||||||
public async getNextForCompany(
|
public async getNextForCompany(
|
||||||
companyId: UniqueID,
|
companyId: UniqueID,
|
||||||
series: Maybe<InvoiceSerie>,
|
series: InvoiceSerie,
|
||||||
transaction: Transaction
|
transaction: Transaction
|
||||||
): Promise<Result<InvoiceNumber, Error>> {
|
): Promise<Result<InvoiceNumber, Error>> {
|
||||||
const where: WhereOptions = {
|
const where: WhereOptions = {
|
||||||
@ -20,14 +20,7 @@ export class SequelizeIssuedInvoiceNumberGenerator implements IIssuedInvoiceNumb
|
|||||||
is_proforma: false,
|
is_proforma: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
series.match(
|
where.series = series.toString();
|
||||||
(serieVO) => {
|
|
||||||
where.series = serieVO.toString();
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
where.series = null;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const lastInvoice = await CustomerInvoiceModel.findOne({
|
const lastInvoice = await CustomerInvoiceModel.findOne({
|
||||||
|
|||||||
@ -1,46 +1,8 @@
|
|||||||
import {
|
import { createPaginatedListSchema } from "@erp/core";
|
||||||
CurrencyCodeSchema,
|
import type { z } from "zod/v4";
|
||||||
IsoDateSchema,
|
|
||||||
LanguageCodeSchema,
|
|
||||||
MoneySchema,
|
|
||||||
PercentageSchema,
|
|
||||||
createPaginatedListSchema,
|
|
||||||
} from "@erp/core";
|
|
||||||
import { z } from "zod/v4";
|
|
||||||
|
|
||||||
import { ProformaRecipientSummarySchema, ProformaStatusSchema } from "../../shared/proforma";
|
import { ProformaSummarySchema } from "../../shared/proforma";
|
||||||
|
|
||||||
export const ListProformasResponseSchema = createPaginatedListSchema(
|
export const ListProformasResponseSchema = createPaginatedListSchema(ProformaSummarySchema);
|
||||||
z.object({
|
|
||||||
id: z.uuid(),
|
|
||||||
company_id: z.uuid(),
|
|
||||||
is_proforma: z.boolean(),
|
|
||||||
|
|
||||||
invoice_number: z.string(),
|
|
||||||
status: ProformaStatusSchema,
|
|
||||||
series: z.string().nullable(),
|
|
||||||
|
|
||||||
invoice_date: IsoDateSchema,
|
|
||||||
operation_date: IsoDateSchema.nullable(),
|
|
||||||
|
|
||||||
language_code: LanguageCodeSchema,
|
|
||||||
currency_code: CurrencyCodeSchema,
|
|
||||||
|
|
||||||
reference: z.string().nullable(),
|
|
||||||
description: z.string().nullable(),
|
|
||||||
|
|
||||||
customer_id: z.uuid(),
|
|
||||||
recipient: ProformaRecipientSummarySchema,
|
|
||||||
|
|
||||||
subtotal_amount: MoneySchema,
|
|
||||||
discount_percentage: PercentageSchema,
|
|
||||||
discount_amount: MoneySchema,
|
|
||||||
taxable_amount: MoneySchema,
|
|
||||||
taxes_amount: MoneySchema,
|
|
||||||
total_amount: MoneySchema,
|
|
||||||
|
|
||||||
linked_invoice_id: z.uuid().nullable(),
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
export type ListProformasResponseDTO = z.infer<typeof ListProformasResponseSchema>;
|
export type ListProformasResponseDTO = z.infer<typeof ListProformasResponseSchema>;
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
export * from "./proforma-item-detail.dto";
|
export * from "./proforma-item-detail.dto";
|
||||||
export * from "./proforma-recipient-summary.dto";
|
export * from "./proforma-recipient-summary.dto";
|
||||||
export * from "./proforma-status.dto";
|
export * from "./proforma-status.dto";
|
||||||
|
export * from "./proforma-summary.dto";
|
||||||
|
|||||||
@ -0,0 +1,37 @@
|
|||||||
|
import { CurrencyCodeSchema, IsoDateSchema, LanguageCodeSchema, MoneySchema } from "@erp/core";
|
||||||
|
import { z } from "zod/v4";
|
||||||
|
|
||||||
|
import { ProformaRecipientSummarySchema } from "./proforma-recipient-summary.dto";
|
||||||
|
import { ProformaStatusSchema } from "./proforma-status.dto";
|
||||||
|
|
||||||
|
export const ProformaSummarySchema = z.object({
|
||||||
|
id: z.uuid(),
|
||||||
|
company_id: z.uuid(),
|
||||||
|
is_proforma: z.boolean(),
|
||||||
|
|
||||||
|
invoice_number: z.string(),
|
||||||
|
status: ProformaStatusSchema,
|
||||||
|
series: z.string().nullable(),
|
||||||
|
|
||||||
|
invoice_date: IsoDateSchema,
|
||||||
|
operation_date: IsoDateSchema.nullable(),
|
||||||
|
|
||||||
|
language_code: LanguageCodeSchema,
|
||||||
|
currency_code: CurrencyCodeSchema,
|
||||||
|
|
||||||
|
reference: z.string().nullable(),
|
||||||
|
description: z.string().nullable(),
|
||||||
|
|
||||||
|
customer_id: z.uuid(),
|
||||||
|
recipient: ProformaRecipientSummarySchema,
|
||||||
|
|
||||||
|
subtotal_amount: MoneySchema,
|
||||||
|
total_discount_amount: MoneySchema,
|
||||||
|
taxable_amount: MoneySchema,
|
||||||
|
taxes_amount: MoneySchema,
|
||||||
|
total_amount: MoneySchema,
|
||||||
|
|
||||||
|
linked_invoice_id: z.uuid().nullable(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type ProformaSummaryDTO = z.infer<typeof ProformaSummarySchema>;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { formatDate } from "@erp/core/client";
|
import { DateHelper } from "@erp/core";
|
||||||
import { ReactQRCode } from "@lglab/react-qr-code";
|
import { ReactQRCode } from "@lglab/react-qr-code";
|
||||||
import { DataTableColumnHeader } from "@repo/rdx-ui/components";
|
import { DataTableColumnHeader } from "@repo/rdx-ui/components";
|
||||||
import {
|
import {
|
||||||
@ -205,7 +205,7 @@ export function useIssuedInvoicesGridColumns(
|
|||||||
),
|
),
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<div className="font-medium text-left tabular-nums">
|
<div className="font-medium text-left tabular-nums">
|
||||||
{formatDate(row.original.invoiceDate)}
|
{DateHelper.format(row.original.invoiceDate)}
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
enableSorting: false,
|
enableSorting: false,
|
||||||
@ -227,7 +227,7 @@ export function useIssuedInvoicesGridColumns(
|
|||||||
),
|
),
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<div className="font-medium text-left tabular-nums">
|
<div className="font-medium text-left tabular-nums">
|
||||||
{formatDate(row.original.operationDate)}
|
{DateHelper.format(row.original.operationDate)}
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
enableSorting: false,
|
enableSorting: false,
|
||||||
@ -284,6 +284,27 @@ export function useIssuedInvoicesGridColumns(
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Taxable amount
|
||||||
|
{
|
||||||
|
accessorKey: "taxableAmountFmt",
|
||||||
|
header: ({ column }) => (
|
||||||
|
<DataTableColumnHeader
|
||||||
|
className="text-right tabular-nums"
|
||||||
|
column={column}
|
||||||
|
title={t("pages.issued_invoices.list.grid_columns.taxable_amount", "Base imponible")}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<div className="font-medium text-right tabular-nums">{row.original.taxableAmountFmt}</div>
|
||||||
|
),
|
||||||
|
enableSorting: false,
|
||||||
|
size: 120,
|
||||||
|
minSize: 100,
|
||||||
|
meta: {
|
||||||
|
title: t("pages.issued_invoices.list.grid_columns.taxable_amount"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
// Taxes amount
|
// Taxes amount
|
||||||
{
|
{
|
||||||
accessorKey: "taxes_amount_fmt",
|
accessorKey: "taxes_amount_fmt",
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { DateHelper } from "@erp/core";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
@ -159,6 +160,10 @@ export function useProformasGridColumns(
|
|||||||
accessorKey: "series",
|
accessorKey: "series",
|
||||||
header: "Serie",
|
header: "Serie",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "reference",
|
||||||
|
header: "Referencia",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "invoiceDate",
|
accessorKey: "invoiceDate",
|
||||||
header: ({ column }) => {
|
header: ({ column }) => {
|
||||||
@ -173,6 +178,17 @@ export function useProformasGridColumns(
|
|||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<div className="font-medium text-left tabular-nums">
|
||||||
|
{DateHelper.format(row.original.invoiceDate)}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
enableSorting: false,
|
||||||
|
size: 140,
|
||||||
|
minSize: 120,
|
||||||
|
meta: {
|
||||||
|
title: t("pages.issued_invoices.list.grid_columns.invoice_date"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "operationDate",
|
accessorKey: "operationDate",
|
||||||
@ -193,30 +209,43 @@ export function useProformasGridColumns(
|
|||||||
accessorKey: "subtotalAmountFmt",
|
accessorKey: "subtotalAmountFmt",
|
||||||
header: () => <div className="text-right">Subtotal</div>,
|
header: () => <div className="text-right">Subtotal</div>,
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<div className="text-right tabular-nums">{row.getValue("subtotalAmountFmt")}</div>
|
<div className="text-right tabular-nums font-medium">
|
||||||
|
{row.getValue("subtotalAmountFmt")}
|
||||||
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "discountAmountFmt",
|
accessorKey: "totalDiscountAmountFmt",
|
||||||
header: () => <div className="text-right">Descuentos</div>,
|
header: () => <div className="text-right">Descuentos</div>,
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<div className="text-right tabular-nums">{row.getValue("discountAmountFmt")}</div>
|
<div className="text-right tabular-nums font-medium">
|
||||||
|
{row.getValue("totalDiscountAmountFmt")}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "taxableAmountFmt",
|
||||||
|
header: () => <div className="text-right">Base imponible</div>,
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<div className="text-right tabular-nums font-medium">
|
||||||
|
{row.getValue("taxableAmountFmt")}
|
||||||
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "taxesAmountFmt",
|
accessorKey: "taxesAmountFmt",
|
||||||
header: () => <div className="text-right">Impuestos</div>,
|
header: () => <div className="text-right">Impuestos</div>,
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<div className="text-right tabular-nums">{row.getValue("taxesAmountFmt")}</div>
|
<div className="text-right tabular-nums font-medium">
|
||||||
|
{row.getValue("taxesAmountFmt")}
|
||||||
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "totalAmountFmt",
|
accessorKey: "totalAmountFmt",
|
||||||
header: () => <div className="text-right">Importe total</div>,
|
header: () => <div className="text-right">Importe total</div>,
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<div className="text-right tabular-nums font-medium">
|
<div className="text-right tabular-nums font-bold">{row.getValue("totalAmountFmt")}</div>
|
||||||
{row.getValue("totalAmountFmt")}
|
|
||||||
</div>
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,28 +1,52 @@
|
|||||||
import { MoneyDTOHelper, PercentageDTOHelper, formatCurrency } from "@erp/core";
|
import { MoneyDTOHelper, formatCurrency } from "@erp/core";
|
||||||
|
|
||||||
import type { ListProformasResponseDTO } from "../../../../common";
|
import type { ListProformasResponseDTO } from "../../../../common";
|
||||||
|
import type { ListProformasResult } from "../api";
|
||||||
import type { ProformaList, ProformaListRow, ProformaStatus } from "../entities";
|
import type { ProformaList, ProformaListRow, ProformaStatus } from "../entities";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adaptador para transformar los datos de la API de ListProformasResponseDTO
|
||||||
|
* a la entidad ProformaList utilizada en la aplicación.
|
||||||
|
* Reglas de adaptación:
|
||||||
|
* - page, per_page, total_pages, total_items se asignan directamente.
|
||||||
|
* - items se transforma utilizando ProformaListRowAdapter para cada elemento.
|
||||||
|
*
|
||||||
|
* @param pageDto - lista de proformas desde la API.
|
||||||
|
* @param context - Contexto adicional opcional para la adaptación.
|
||||||
|
* @returns {ProformaList} Objeto adaptado a ProformaList.
|
||||||
|
*/
|
||||||
|
|
||||||
export const ListProformasAdapter = {
|
export const ListProformasAdapter = {
|
||||||
fromDto(dto: ListProformasResponseDTO): ProformaList {
|
fromDto(dto: ListProformasResult, context?: unknown): ProformaList {
|
||||||
return {
|
return {
|
||||||
items: dto.items.map(ProformaListRowAdapter.fromDto),
|
|
||||||
page: dto.page,
|
page: dto.page,
|
||||||
perPage: dto.per_page,
|
perPage: dto.per_page,
|
||||||
totalPages: dto.total_pages,
|
totalPages: dto.total_pages,
|
||||||
totalItems: dto.total_items,
|
totalItems: dto.total_items,
|
||||||
|
items: dto.items.map((rowDto) => ProformaListRowAdapter.fromDto(rowDto, context)),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
type ListProformasItemDTO = ListProformasResponseDTO["items"][number];
|
/**
|
||||||
|
* Adaptador para transformar los items de la API de ListProformasResult a la entidad ProformaListRow.
|
||||||
|
* Reglas de adaptación:
|
||||||
|
* - id, company_id, status, reference se asignan directamente.
|
||||||
|
* - is_proforma se convierte a booleano (true si es "1", false si es "0").
|
||||||
|
*
|
||||||
|
* @param rowDto - item de proforma desde la API.
|
||||||
|
* @param context - Contexto adicional opcional para la adaptación.
|
||||||
|
* @returns {ProformaListRow} Objeto adaptado a ProformaListRow.
|
||||||
|
*/
|
||||||
|
|
||||||
|
type ListProformasItemOutput = ListProformasResponseDTO["items"][number];
|
||||||
|
|
||||||
const ProformaListRowAdapter = {
|
const ProformaListRowAdapter = {
|
||||||
fromDto(dto: ListProformasItemDTO): ProformaListRow {
|
fromDto(dto: ListProformasItemOutput, context?: unknown): ProformaListRow {
|
||||||
return {
|
return {
|
||||||
id: dto.id,
|
id: dto.id,
|
||||||
companyId: dto.company_id,
|
companyId: dto.company_id,
|
||||||
isProforma: dto.is_proforma === "1",
|
isProforma: dto.is_proforma,
|
||||||
|
|
||||||
invoiceNumber: dto.invoice_number,
|
invoiceNumber: dto.invoice_number,
|
||||||
status: dto.status as ProformaStatus,
|
status: dto.status as ProformaStatus,
|
||||||
@ -57,12 +81,9 @@ const ProformaListRowAdapter = {
|
|||||||
dto.language_code
|
dto.language_code
|
||||||
),
|
),
|
||||||
|
|
||||||
discountPercentage: PercentageDTOHelper.toNumber(dto.discount_percentage),
|
totalDiscountAmount: MoneyDTOHelper.toNumber(dto.total_discount_amount),
|
||||||
discountPercentageFmt: PercentageDTOHelper.toNumericString(dto.discount_percentage),
|
totalDiscountAmountFmt: formatCurrency(
|
||||||
|
MoneyDTOHelper.toNumber(dto.total_discount_amount),
|
||||||
discountAmount: MoneyDTOHelper.toNumber(dto.discount_amount),
|
|
||||||
discountAmountFmt: formatCurrency(
|
|
||||||
MoneyDTOHelper.toNumber(dto.discount_amount),
|
|
||||||
Number(dto.total_amount.scale || 2),
|
Number(dto.total_amount.scale || 2),
|
||||||
dto.currency_code,
|
dto.currency_code,
|
||||||
dto.language_code
|
dto.language_code
|
||||||
|
|||||||
@ -15,27 +15,24 @@ export interface ProformaListRow {
|
|||||||
|
|
||||||
invoiceNumber: string;
|
invoiceNumber: string;
|
||||||
status: ProformaStatus;
|
status: ProformaStatus;
|
||||||
series: string;
|
series: string | null;
|
||||||
|
|
||||||
invoiceDate: string;
|
invoiceDate: string;
|
||||||
operationDate: string;
|
operationDate: string | null;
|
||||||
|
|
||||||
languageCode: string;
|
languageCode: string;
|
||||||
currencyCode: string;
|
currencyCode: string;
|
||||||
|
|
||||||
reference: string;
|
reference: string | null;
|
||||||
description: string;
|
description: string | null;
|
||||||
|
|
||||||
recipient: ProformaRecipient;
|
recipient: ProformaRecipient;
|
||||||
|
|
||||||
subtotalAmount: number;
|
subtotalAmount: number;
|
||||||
subtotalAmountFmt: string;
|
subtotalAmountFmt: string;
|
||||||
|
|
||||||
discountPercentage: number;
|
totalDiscountAmount: number;
|
||||||
discountPercentageFmt: string;
|
totalDiscountAmountFmt: string;
|
||||||
|
|
||||||
discountAmount: number;
|
|
||||||
discountAmountFmt: string;
|
|
||||||
|
|
||||||
taxableAmount: number;
|
taxableAmount: number;
|
||||||
taxableAmountFmt: string;
|
taxableAmountFmt: string;
|
||||||
@ -46,5 +43,5 @@ export interface ProformaListRow {
|
|||||||
totalAmount: number;
|
totalAmount: number;
|
||||||
totalAmountFmt: string;
|
totalAmountFmt: string;
|
||||||
|
|
||||||
linkedInvoiceId: string;
|
linkedInvoiceId: string | null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,14 +5,14 @@
|
|||||||
|
|
||||||
export interface ProformaRecipient {
|
export interface ProformaRecipient {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string | null;
|
||||||
tin: string;
|
tin: string | null;
|
||||||
|
|
||||||
street: string;
|
street: string | null;
|
||||||
street2: string;
|
street2: string | null;
|
||||||
|
|
||||||
city: string;
|
city: string | null;
|
||||||
province: string;
|
province: string | null;
|
||||||
postalCode: string;
|
postalCode: string | null;
|
||||||
country: string;
|
country: string | null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import type { CustomerSelectionOption } from "@erp/customers";
|
import type { CustomerSelectionOption } from "@erp/customers";
|
||||||
|
import { FormSectionCard } from "@repo/rdx-ui/components";
|
||||||
|
|
||||||
import { useTranslation } from "../../../../i18n";
|
import { useTranslation } from "../../../../i18n";
|
||||||
import { FormSectionCard, SelectedRecipientSummary } from "../blocks";
|
import { SelectedRecipientSummary } from "../blocks";
|
||||||
|
|
||||||
interface ProformaUpdateRecipientEditorProps {
|
interface ProformaUpdateRecipientEditorProps {
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
"paths": {
|
||||||
"@erp/customer-invoices/*": ["./src/*"]
|
"@erp/customer-invoices/*": ["./src/*"]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/customers",
|
"name": "@erp/customers",
|
||||||
"description": "Customers",
|
"description": "Customers",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { DateHelper } from "@erp/core";
|
||||||
import { Badge, Button } from "@repo/shadcn-ui/components";
|
import { Badge, Button } from "@repo/shadcn-ui/components";
|
||||||
import { FileTextIcon } from "lucide-react";
|
import { FileTextIcon } from "lucide-react";
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ export const CustomerProformasSection = ({
|
|||||||
>
|
>
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
<p className="text-sm font-medium text-foreground truncate">{pro.number}</p>
|
<p className="text-sm font-medium text-foreground truncate">{pro.number}</p>
|
||||||
<p className="text-xs text-muted-foreground">{formatDate(pro.date)}</p>
|
<p className="text-xs text-muted-foreground">{DateHelper.format(pro.date)}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2 shrink-0">
|
<div className="flex items-center gap-2 shrink-0">
|
||||||
<span className="text-sm font-medium">{formatCurrency(pro.amount)}</span>
|
<span className="text-sm font-medium">{formatCurrency(pro.amount)}</span>
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
"paths": {
|
||||||
"@erp/customers/*": ["./src/*"]
|
"@erp/customers/*": ["./src/*"]
|
||||||
},
|
},
|
||||||
@ -28,11 +27,6 @@
|
|||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"noUncheckedSideEffectImports": true
|
"noUncheckedSideEffectImports": true
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["src"],
|
||||||
"src",
|
|
||||||
"../customer-invoices/src/web/proformas/update/ui/blocks/selected-recipient/customer-view-dialog.tsx",
|
|
||||||
"../customer-invoices/src/web/proformas/update/ui/blocks/selected-recipient/customer-card.tsx",
|
|
||||||
"../customer-invoices/src/web/proformas/update/ui/blocks/selected-recipient/selected-recipient-empty-card.tsx"
|
|
||||||
],
|
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/factuges",
|
"name": "@erp/factuges",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -4,10 +4,10 @@ import {
|
|||||||
requireAuthenticatedGuard,
|
requireAuthenticatedGuard,
|
||||||
requireCompanyContextGuard,
|
requireCompanyContextGuard,
|
||||||
} from "@erp/core/api";
|
} from "@erp/core/api";
|
||||||
|
import type { CreateProformaFromFactugesUseCase } from "@erp/factuges/api/application";
|
||||||
|
import type { CreateProformaFromFactugesRequestDTO } from "@erp/factuges/common";
|
||||||
|
|
||||||
import type { CreateProformaFromFactugesRequestDTO } from "../../../../common/dto/request/create-proforma-from-factuges.request.dto.js";
|
import { factugesApiErrorMapper } from "../factuges-api-error-mapper";
|
||||||
import type { CreateProformaFromFactugesUseCase } from "../../../application/use-cases/create-proforma-from-factuges.use-case.js";
|
|
||||||
import { factugesApiErrorMapper } from "../factuges-api-error-mapper.js";
|
|
||||||
|
|
||||||
export class CreateProformaFromFactugesController extends ExpressController {
|
export class CreateProformaFromFactugesController extends ExpressController {
|
||||||
public constructor(private readonly useCase: CreateProformaFromFactugesUseCase) {
|
public constructor(private readonly useCase: CreateProformaFromFactugesUseCase) {
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
"paths": {
|
||||||
"@erp/factuges/*": ["./src/*"]
|
"@erp/factuges/*": ["./src/*"]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/supplier-invoices",
|
"name": "@erp/supplier-invoices",
|
||||||
"description": "Supplier invoices",
|
"description": "Supplier invoices",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
"paths": {
|
||||||
"@erp/supplier-invoices/*": ["./src/*"]
|
"@erp/supplier-invoices/*": ["./src/*"]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/suppliers",
|
"name": "@erp/suppliers",
|
||||||
"description": "Suppliers",
|
"description": "Suppliers",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
"paths": {
|
||||||
"@erp/suppliers/*": ["./src/*"]
|
"@erp/suppliers/*": ["./src/*"]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@repo/rdx-criteria",
|
"name": "@repo/rdx-criteria",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@repo/rdx-ddd",
|
"name": "@repo/rdx-ddd",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { ZodError } from "zod/v4";
|
import type { ZodError } from "zod/v4";
|
||||||
import { ValidationErrorCollection, ValidationErrorDetail } from "../errors";
|
|
||||||
|
import { ValidationErrorCollection, type ValidationErrorDetail } from "../errors";
|
||||||
|
|
||||||
export function translateZodValidationError<T>(
|
export function translateZodValidationError<T>(
|
||||||
message: string,
|
message: string,
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import { z } from "zod/v4";
|
import { z } from "zod/v4";
|
||||||
|
|
||||||
import { translateZodValidationError } from "../helpers";
|
import { translateZodValidationError } from "../helpers";
|
||||||
|
|
||||||
import { ValueObject } from "./value-object";
|
import { ValueObject } from "./value-object";
|
||||||
|
|
||||||
interface UtcDateProps {
|
interface UtcDateProps {
|
||||||
@ -101,4 +103,15 @@ export class UtcDate extends ValueObject<UtcDateProps> {
|
|||||||
equals(other: UtcDate): boolean {
|
equals(other: UtcDate): boolean {
|
||||||
return this.toISOString() === other.toISOString();
|
return this.toISOString() === other.toISOString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determina si la fecha representada
|
||||||
|
* es una fecha futura en comparación con la fecha actual.
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
|
||||||
|
isFuture(currentDate?: UtcDate): boolean {
|
||||||
|
const now = currentDate ? currentDate : UtcDate.today();
|
||||||
|
return this.date.getTime() > now.getTime();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@repo/rdx-logger",
|
"name": "@repo/rdx-logger",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "@repo/typescript-config/react-library.json",
|
"extends": "@repo/typescript-config/react-library.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
"paths": {
|
||||||
"@repo/rdx-ui/*": ["./src/*"]
|
"@repo/rdx-ui/*": ["./src/*"]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@repo/rdx-utils",
|
"name": "@repo/rdx-utils",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
{
|
{
|
||||||
"extends": "@repo/typescript-config/buildless.json",
|
"extends": "@repo/typescript-config/buildless.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"types": ["node"],
|
||||||
"rootDir": "src"
|
"rootDir": "src"
|
||||||
},
|
},
|
||||||
"include": ["src", "../../modules/core/src/api/application/mappers/patch-collector.ts"],
|
"include": ["src"],
|
||||||
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,21 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/tsconfig",
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
"display": "Root",
|
"display": "Root",
|
||||||
|
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
"paths": {
|
||||||
"@erp/core/*": ["modules/core/src/*"],
|
"@erp/core/*": [
|
||||||
"@erp/auth/*": ["modules/auth/src/*"],
|
"modules/core/src/*"
|
||||||
"@erp/customers/*": ["modules/customers/src/*"],
|
],
|
||||||
"@erp/customer-invoices/*": ["modules/customer-invoices/src/*"]
|
"@erp/auth/*": [
|
||||||
|
"modules/auth/src/*"
|
||||||
|
],
|
||||||
|
"@erp/customers/*": [
|
||||||
|
"modules/customers/src/*"
|
||||||
|
],
|
||||||
|
"@erp/customer-invoices/*": [
|
||||||
|
"modules/customer-invoices/src/*"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
"target": "ES2021",
|
"target": "ES2021",
|
||||||
"module": "CommonJS",
|
"module": "CommonJS",
|
||||||
"moduleResolution": "Node",
|
"moduleResolution": "Node",
|
||||||
@ -20,4 +25,4 @@
|
|||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"allowUnreachableCode": true
|
"allowUnreachableCode": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,12 +65,6 @@ importers:
|
|||||||
'@erp/customers':
|
'@erp/customers':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../modules/customers
|
version: link:../../modules/customers
|
||||||
'@erp/factuges':
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../../modules/factuges
|
|
||||||
'@erp/suppliers':
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../../modules/supplier
|
|
||||||
'@repo/rdx-logger':
|
'@repo/rdx-logger':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../packages/rdx-logger
|
version: link:../../packages/rdx-logger
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user