This commit is contained in:
David Arranz 2026-04-21 19:13:59 +02:00
parent 330240deaa
commit 108bbea5fc
41 changed files with 252 additions and 74 deletions

2
.vscode/launch.json vendored
View File

@ -1,5 +1,5 @@
{
"version": "0.6.0",
"version": "0.6.1",
"configurations": [
{
"name": "WEB: Vite (Chrome)",

View File

@ -1,6 +1,6 @@
{
"name": "@erp/factuges-server",
"version": "0.6.0",
"version": "0.6.1",
"private": true,
"scripts": {
"build": "tsup src/index.ts --config tsup.config.ts",
@ -37,6 +37,7 @@
"@erp/core": "workspace:*",
"@erp/customer-invoices": "workspace:*",
"@erp/customers": "workspace:*",
"@erp/factuges": "workspace:*",
"@repo/rdx-logger": "workspace:*",
"@repo/rdx-utils": "workspace:*",
"bcrypt": "^6.0.0",

View File

@ -1,5 +1,6 @@
import customerInvoicesAPIModule from "@erp/customer-invoices/api";
import customersAPIModule from "@erp/customers/api";
import factuGESAPIModule from "@erp/factuges/api";
//import suppliersAPIModule from "@erp/suppliers/api";
@ -9,5 +10,6 @@ export const registerModules = () => {
//registerModule(authAPIModule);
registerModule(customersAPIModule);
registerModule(customerInvoicesAPIModule);
registerModule(factuGESAPIModule);
//registerModule(suppliersAPIModule);
};

View File

@ -1,7 +1,7 @@
{
"name": "@erp/factuges-web",
"private": true,
"version": "0.6.0",
"version": "0.6.1",
"type": "module",
"scripts": {
"dev": "vite --host --clearScreen false",

View File

@ -4,6 +4,7 @@
"compilerOptions": {
"resolveJsonModule": true,
"esModuleInterop": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}

View File

@ -1,6 +1,6 @@
{
"name": "@erp/auth",
"version": "0.6.0",
"version": "0.6.1",
"private": true,
"type": "module",
"sideEffects": false,

View File

@ -1,6 +1,6 @@
{
"name": "@erp/core",
"version": "0.6.0",
"version": "0.6.1",
"private": true,
"type": "module",
"sideEffects": false,

View File

@ -64,7 +64,7 @@ export class SequelizeTransactionManager extends TransactionManager {
}
try {
// Usa la forma gestionada: si `work` resuelve => commit, si lanza => rollback.
// Usa la forma gestionada: si `work` resuelve => commit, si lanza excepción => rollback.
const result = await this._database.transaction(async (t) => {
const workResult = await work(t);
if (workResult instanceof Result && workResult.isFailure) {

View File

@ -4,7 +4,7 @@
"paths": {
"@erp/core/*": ["./src/*"]
},
"baseUrl": ".",
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2022",
"useDefineForClassFields": true,

View File

@ -1,6 +1,6 @@
{
"name": "@erp/customer-invoices",
"version": "0.6.0",
"version": "0.6.1",
"private": true,
"type": "module",
"sideEffects": false,

View File

@ -22,6 +22,12 @@ export interface IProformaRepository {
transaction: unknown
): Promise<Result<Proforma, Error>>;
getByFactuGESIdInCompany(
companyId: UniqueID,
factugesId: string,
transaction: unknown
): Promise<Result<Proforma, Error>>;
findByCriteriaInCompany(
companyId: UniqueID,
criteria: Criteria,

View File

@ -13,6 +13,12 @@ export interface IProformaFinder {
transaction?: unknown
): Promise<Result<Proforma, Error>>;
findProformaByFactuGESId(
companyId: UniqueID,
factugesId: string,
transaction?: unknown
): Promise<Result<Proforma, Error>>;
proformaExists(
companyId: UniqueID,
invoiceId: UniqueID,
@ -37,6 +43,14 @@ export class ProformaFinder implements IProformaFinder {
return this.repository.getByIdInCompany(companyId, proformaId, transaction);
}
async findProformaByFactuGESId(
companyId: UniqueID,
factugesId: string,
transaction?: unknown
): Promise<Result<Proforma, Error>> {
return this.repository.getByFactuGESIdInCompany(companyId, factugesId, transaction);
}
async proformaExists(
companyId: UniqueID,
proformaId: UniqueID,

View File

@ -11,6 +11,8 @@ export interface IProformaServicesContext {
companyId: UniqueID;
}
// TODO: Eliminar para pasar a usar el tipo ProformaPublicServices
export interface IProformaPublicServices {
createProforma: (
id: UniqueID,
@ -25,6 +27,11 @@ export interface IProformaPublicServices {
context: IProformaServicesContext
) => Promise<Result<Proforma, Error>>;
getProformaByFactuGESId: (
factugesId: string,
context: IProformaServicesContext
) => Promise<Result<Proforma, Error>>;
getProformaSnapshotById: (
id: UniqueID,
context: IProformaServicesContext

View File

@ -10,6 +10,8 @@ import {
proformasRouter,
} from "./infrastructure";
export type { IProformaPublicServices } from "./application";
export const customerInvoicesAPIModule: IModuleServer = {
name: "customer-invoices",
version: "1.0.0",

View File

@ -64,7 +64,7 @@ export class SequelizeIssuedInvoiceDomainMapper extends SequelizeDomainMapper<
const customerId = extractOrPushError(UniqueID.create(raw.customer_id), "customer_id", errors);
const linkedProformaId = extractOrPushError(
UniqueID.create(String(raw.proforma_id)),
maybeFromNullableResult(raw.proforma_id, (v) => UniqueID.create(String(v))),
"proforma_id",
errors
);

View File

@ -28,6 +28,11 @@ export type ProformaPublicServices = {
context: ProformaServicesContext
) => Promise<Result<Proforma, Error>>;
getProformaByFactuGESId: (
factugesId: string,
context: ProformaServicesContext
) => Promise<Result<Proforma, Error>>;
getProformaSnapshotById: (
id: UniqueID,
context: ProformaServicesContext
@ -88,6 +93,22 @@ export function buildProformaPublicServices(
return Result.ok(proformaResult.data);
},
getProformaByFactuGESId: async (factugesId: string, context: ProformaServicesContext) => {
const { transaction, companyId } = context;
const proformaResult = await finder.findProformaByFactuGESId(
companyId,
factugesId,
transaction
);
if (proformaResult.isFailure) {
console.error("Error fetching proforma by FactuGES ID:", proformaResult.error);
return Result.fail(proformaResult.error);
}
return Result.ok(proformaResult.data);
},
getProformaSnapshotById: async (id: UniqueID, context: ProformaServicesContext) => {
const { transaction, companyId } = context;
const proformaResult = await finder.findProformaById(companyId, id, transaction);

View File

@ -14,7 +14,7 @@ import {
} from "@repo/rdx-ddd";
import { Maybe, Result } from "@repo/rdx-utils";
import { InvoiceRecipient, type ProformaCreateProps } from "../../../../../../domain";
import { type IProformaCreateProps, InvoiceRecipient } from "../../../../../../domain";
import type { CustomerInvoiceModel } from "../../../../../common";
export class SequelizeProformaRecipientDomainMapper {
@ -28,17 +28,17 @@ export class SequelizeProformaRecipientDomainMapper {
const { errors, parent } = params as {
errors: ValidationErrorDetail[];
parent: Partial<ProformaCreateProps>;
parent: Partial<IProformaCreateProps>;
};
const _name = source.current_customer.name;
const _tin = source.current_customer.tin;
const _street = source.current_customer.street;
const _street2 = source.current_customer.street2;
const _city = source.current_customer.city;
const _postal_code = source.current_customer.postal_code;
const _province = source.current_customer.province;
const _country = source.current_customer.country;
const _name = source.current_customer?.name;
const _tin = source.current_customer?.tin;
const _street = source.current_customer?.street;
const _street2 = source.current_customer?.street2;
const _city = source.current_customer?.city;
const _postal_code = source.current_customer?.postal_code;
const _province = source.current_customer?.province;
const _country = source.current_customer?.country;
// Customer (snapshot)
const customerName = extractOrPushError(Name.create(_name!), "customer_name", errors);

View File

@ -326,6 +326,93 @@ export class ProformaRepository
}
}
/**
*
* Busca una factura por su identificador único de FactuGES.
*
* @param companyId - Identificador UUID de la empresa a la que pertenece la factura.
* @param factugesId - ID de la factura en FactuGES.
* @param transaction - Transacción activa para la operación.
* @param options - Opciones adicionales para la consulta (Sequelize FindOptions)
* @returns Result<CustomerInvoice, Error>
*/
async getByFactuGESIdInCompany(
companyId: UniqueID,
factugesId: string,
transaction: Transaction,
options: FindOptions<InferAttributes<CustomerInvoiceModel>> = {}
): Promise<Result<Proforma, Error>> {
const { CustomerModel } = this.database.models;
try {
// Normalización defensiva de order/include
const normalizedOrder = Array.isArray(options.order)
? options.order
: options.order
? [options.order]
: [];
const normalizedInclude = Array.isArray(options.include)
? options.include
: options.include
? [options.include]
: [];
const mergedOptions: FindOptions<InferAttributes<CustomerInvoiceModel>> = {
...options,
where: {
...(options.where ?? {}),
factuges_id: factugesId,
is_proforma: true,
company_id: companyId.toString(),
},
order: [
...normalizedOrder,
[{ model: CustomerInvoiceItemModel, as: "items" }, "position", "ASC"],
],
include: [
...normalizedInclude,
{
model: CustomerModel,
as: "current_customer",
required: false,
},
{
model: CustomerInvoiceItemModel,
as: "items",
required: false,
},
{
model: CustomerInvoiceTaxModel,
as: "taxes",
required: false,
},
{
model: CustomerInvoiceModel,
as: "linked_invoice",
required: false,
attributes: ["id"],
},
],
transaction,
};
const row = await CustomerInvoiceModel.findOne(mergedOptions);
if (!row) {
return Result.fail(
new EntityNotFoundError("CustomerInvoice", "factuges_id", factugesId.toString())
);
}
const invoice = this.domainMapper.mapToDomain(row);
return invoice;
} catch (err: unknown) {
return Result.fail(translateSequelizeError(err));
}
}
/**
*
* Consulta facturas usando un objeto Criteria (filtros, orden, paginación).

View File

@ -4,7 +4,7 @@
"paths": {
"@erp/customer-invoices/*": ["./src/*"]
},
"baseUrl": ".",
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2022",
"useDefineForClassFields": true,

View File

@ -1,7 +1,7 @@
{
"name": "@erp/customers",
"description": "Customers",
"version": "0.6.0",
"version": "0.6.1",
"private": true,
"type": "module",
"sideEffects": false,

View File

@ -11,7 +11,7 @@ export interface ICustomerCreator {
companyId: UniqueID;
id: UniqueID;
props: ICustomerCreateProps;
unknown: unknown;
transaction?: unknown;
}): Promise<Result<Customer, Error>>;
}
@ -30,12 +30,16 @@ export class CustomerCreator implements ICustomerCreator {
companyId: UniqueID;
id: UniqueID;
props: ICustomerCreateProps;
unknown: unknown;
transaction?: unknown;
}): Promise<Result<Customer, Error>> {
const { companyId, id, props, unknown } = params;
const { companyId, id, props, transaction } = params;
// 1. Verificar unicidad
const spec = new CustomerNotExistsInCompanySpecification(this.repository, companyId, unknown);
const spec = new CustomerNotExistsInCompanySpecification(
this.repository,
companyId,
transaction
);
const isNew = await spec.isSatisfiedBy(id);
@ -59,7 +63,7 @@ export class CustomerCreator implements ICustomerCreator {
const newCustomer = createResult.data;
// 3. Persistir agregado
const saveResult = await this.repository.create(newCustomer, unknown);
const saveResult = await this.repository.create(newCustomer, transaction);
if (saveResult.isFailure) {
return Result.fail(saveResult.error);

View File

@ -10,25 +10,25 @@ export interface ICustomerFinder {
findCustomerById(
companyId: UniqueID,
customerId: UniqueID,
unknown?: unknown
transaction?: unknown
): Promise<Result<Customer, Error>>;
findCustomerByTIN(
companyId: UniqueID,
tin: TINNumber,
unknown?: unknown
transaction?: unknown
): Promise<Result<Customer, Error>>;
customerExists(
companyId: UniqueID,
invoiceId: UniqueID,
unknown?: unknown
transaction?: unknown
): Promise<Result<boolean, Error>>;
findCustomersByCriteria(
companyId: UniqueID,
criteria: Criteria,
unknown?: unknown
transaction?: unknown
): Promise<Result<Collection<CustomerSummary>, Error>>;
}
@ -38,32 +38,32 @@ export class CustomerFinder implements ICustomerFinder {
async findCustomerById(
companyId: UniqueID,
customerId: UniqueID,
unknown?: unknown
transaction?: unknown
): Promise<Result<Customer, Error>> {
return this.repository.getByIdInCompany(companyId, customerId, unknown);
return this.repository.getByIdInCompany(companyId, customerId, transaction);
}
findCustomerByTIN(
companyId: UniqueID,
tin: TINNumber,
unknown?: unknown
transaction?: unknown
): Promise<Result<Customer, Error>> {
return this.repository.getByTINInCompany(companyId, tin, unknown);
return this.repository.getByTINInCompany(companyId, tin, transaction);
}
async customerExists(
companyId: UniqueID,
customerId: UniqueID,
unknown?: unknown
transaction?: unknown
): Promise<Result<boolean, Error>> {
return this.repository.existsByIdInCompany(companyId, customerId, unknown);
return this.repository.existsByIdInCompany(companyId, customerId, transaction);
}
async findCustomersByCriteria(
companyId: UniqueID,
criteria: Criteria,
unknown?: unknown
transaction?: unknown
): Promise<Result<Collection<CustomerSummary>, Error>> {
return this.repository.findByCriteriaInCompany(companyId, criteria, unknown);
return this.repository.findByCriteriaInCompany(companyId, criteria, transaction);
}
}

View File

@ -4,6 +4,7 @@ import type { ICustomerPublicServices } from "./application";
import { customersRouter, models } from "./infrastructure";
import { buildCustomerPublicServices, buildCustomersDependencies } from "./infrastructure/di";
export type { ICustomerPublicServices } from "./application";
export * from "./infrastructure/persistence/sequelize";
export const customersAPIModule: IModuleServer = {

View File

@ -4,7 +4,7 @@
"paths": {
"@erp/customers/*": ["./src/*"]
},
"baseUrl": ".",
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2022",
"useDefineForClassFields": true,

View File

@ -1,6 +1,6 @@
{
"name": "@erp/factuges",
"version": "0.6.0",
"version": "0.6.1",
"private": true,
"type": "module",
"sideEffects": false,

View File

@ -83,6 +83,7 @@ export type ProformaDraftItem = {
};
export type ProformaDraft = {
factugesID: string;
series: Maybe<InvoiceSerie>;
invoiceDate: UtcDate;
operationDate: Maybe<UtcDate>;
@ -222,7 +223,7 @@ export class CreateProformaFromFactugesInputMapper
errors
);*/
//const factugesID = String(dto.factuges_id);
const factugesID = String(dto.factuges_id);
const reference = extractOrPushError(
maybeFromNullableResult(dto.reference, (value) => Result.ok(String(value))),
@ -327,6 +328,7 @@ export class CreateProformaFromFactugesInputMapper
//status: defaultStatus,
//invoiceNumber: proformaNumber!,
factugesID: factugesID,
series: series!,
invoiceDate: invoiceDate!,

View File

@ -1,6 +1,6 @@
import type { JsonTaxCatalogProvider } from "@erp/core";
import { type ITransactionManager, isEntityNotFoundError } from "@erp/core/api";
import type { ProformaPublicServices } from "@erp/customer-invoices/api";
import type { IProformaPublicServices } from "@erp/customer-invoices/api";
import {
type InvoiceAmount,
InvoicePaymentMethod,
@ -9,7 +9,7 @@ import {
type ItemAmount,
type Proforma,
} from "@erp/customer-invoices/api/domain";
import type { CustomerPublicServices } from "@erp/customers/api";
import type { ICustomerPublicServices } from "@erp/customers/api";
import {
type Customer,
CustomerStatus,
@ -44,19 +44,19 @@ type CreateProformaFromFactugesUseCaseInput = {
};
type CreateProformaFromFactugesUseCaseDeps = {
customerServices: CustomerPublicServices;
proformaServices: ProformaPublicServices;
customerServices: ICustomerPublicServices;
proformaServices: IProformaPublicServices;
dtoMapper: ICreateProformaFromFactugesInputMapper;
taxCatalog: JsonTaxCatalogProvider;
transactionManager: ITransactionManager;
};
type CreateProformaProps = Parameters<ProformaPublicServices["createProforma"]>["1"];
type CreateProformaProps = Parameters<IProformaPublicServices["createProforma"]>["1"];
export class CreateProformaFromFactugesUseCase {
private readonly dtoMapper: ICreateProformaFromFactugesInputMapper;
private readonly customerServices: CustomerPublicServices;
private readonly proformaServices: ProformaPublicServices;
private readonly customerServices: ICustomerPublicServices;
private readonly proformaServices: IProformaPublicServices;
private readonly taxCatalog: JsonTaxCatalogProvider;
private readonly transactionManager: ITransactionManager;
@ -80,6 +80,22 @@ export class CreateProformaFromFactugesUseCase {
const { customerLookup, paymentLookup, customerDraft, proformaDraft, paymentDraft } =
mappedPropsResult.data;
// 2) Comprobar si la proforma ya existe (idempotencia)
const existingProformaResult = await this.proformaServices.getProformaByFactuGESId(
proformaDraft.factugesID,
{ companyId, transaction: null }
);
if (existingProformaResult.isSuccess) {
const existingProforma = existingProformaResult.data;
return Result.ok({
customer_id: existingProforma.customerId.toString(),
proforma_id: existingProforma.id.toString(),
});
}
// 3) Si no existe la proforma, la creamos dentro de una transacción.
return this.transactionManager.complete(async (transaction: Transaction) => {
try {
const customerResult = await this.resolveCustomer(customerLookup, customerDraft, {
@ -132,6 +148,8 @@ export class CreateProformaFromFactugesUseCase {
return Result.fail(createResult.error);
}
console.log(createResult.data);
// Valida que los datos de entrada coincidan con el snapshot
const proforma = createResult.data;
const validationResult = this.validateDraftAgainstProforma(proformaDraft, proforma);

View File

@ -4,7 +4,7 @@
"paths": {
"@erp/factuges/*": ["./src/*"]
},
"baseUrl": ".",
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2022",
"useDefineForClassFields": true,

View File

@ -1,7 +1,7 @@
{
"name": "@erp/supplier-invoices",
"description": "Supplier invoices",
"version": "0.6.0",
"version": "0.6.1",
"private": true,
"type": "module",
"sideEffects": false,

View File

@ -4,7 +4,7 @@
"paths": {
"@erp/supplier-invoices/*": ["./src/*"]
},
"baseUrl": ".",
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2022",
"useDefineForClassFields": true,

View File

@ -1,7 +1,7 @@
{
"name": "@erp/suppliers",
"description": "Suppliers",
"version": "0.6.0",
"version": "0.6.1",
"private": true,
"type": "module",
"sideEffects": false,

View File

@ -11,7 +11,7 @@ export interface ISupplierCreator {
companyId: UniqueID;
id: UniqueID;
props: ISupplierCreateProps;
unknown: unknown;
transaction?: unknown;
}): Promise<Result<Supplier, Error>>;
}
@ -30,12 +30,16 @@ export class SupplierCreator implements ISupplierCreator {
companyId: UniqueID;
id: UniqueID;
props: ISupplierCreateProps;
unknown: unknown;
transaction?: unknown;
}): Promise<Result<Supplier, Error>> {
const { companyId, id, props, unknown } = params;
const { companyId, id, props, transaction } = params;
// 1. Verificar unicidad
const spec = new SupplierNotExistsInCompanySpecification(this.repository, companyId, unknown);
const spec = new SupplierNotExistsInCompanySpecification(
this.repository,
companyId,
transaction
);
const isNew = await spec.isSatisfiedBy(id);
@ -59,7 +63,7 @@ export class SupplierCreator implements ISupplierCreator {
const newSupplier = createResult.data;
// 3. Persistir agregado
const saveResult = await this.repository.create(newSupplier, unknown);
const saveResult = await this.repository.create(newSupplier, transaction);
if (saveResult.isFailure) {
return Result.fail(saveResult.error);

View File

@ -10,25 +10,25 @@ export interface ISupplierFinder {
findSupplierById(
companyId: UniqueID,
supplierId: UniqueID,
unknown?: unknown
transaction?: unknown
): Promise<Result<Supplier, Error>>;
findSupplierByTIN(
companyId: UniqueID,
tin: TINNumber,
unknown?: unknown
transaction?: unknown
): Promise<Result<Supplier, Error>>;
supplierExists(
companyId: UniqueID,
invoiceId: UniqueID,
unknown?: unknown
transaction?: unknown
): Promise<Result<boolean, Error>>;
findSuppliersByCriteria(
companyId: UniqueID,
criteria: Criteria,
unknown?: unknown
transaction?: unknown
): Promise<Result<Collection<SupplierSummary>, Error>>;
}
@ -38,32 +38,32 @@ export class SupplierFinder implements ISupplierFinder {
async findSupplierById(
companyId: UniqueID,
supplierId: UniqueID,
unknown?: unknown
transaction?: unknown
): Promise<Result<Supplier, Error>> {
return this.repository.getByIdInCompany(companyId, supplierId, unknown);
return this.repository.getByIdInCompany(companyId, supplierId, transaction);
}
findSupplierByTIN(
companyId: UniqueID,
tin: TINNumber,
unknown?: unknown
transaction?: unknown
): Promise<Result<Supplier, Error>> {
return this.repository.getByTINInCompany(companyId, tin, unknown);
return this.repository.getByTINInCompany(companyId, tin, transaction);
}
async supplierExists(
companyId: UniqueID,
supplierId: UniqueID,
unknown?: unknown
transaction?: unknown
): Promise<Result<boolean, Error>> {
return this.repository.existsByIdInCompany(companyId, supplierId, unknown);
return this.repository.existsByIdInCompany(companyId, supplierId, transaction);
}
async findSuppliersByCriteria(
companyId: UniqueID,
criteria: Criteria,
unknown?: unknown
transaction?: unknown
): Promise<Result<Collection<SupplierSummary>, Error>> {
return this.repository.findByCriteriaInCompany(companyId, criteria, unknown);
return this.repository.findByCriteriaInCompany(companyId, criteria, transaction);
}
}

View File

@ -4,7 +4,7 @@
"paths": {
"@erp/suppliers/*": ["./src/*"]
},
"baseUrl": ".",
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2022",
"useDefineForClassFields": true,

View File

@ -1,6 +1,6 @@
{
"name": "@repo/rdx-criteria",
"version": "0.6.0",
"version": "0.6.1",
"private": true,
"type": "module",
"sideEffects": false,

View File

@ -1,6 +1,6 @@
{
"name": "@repo/rdx-ddd",
"version": "0.6.0",
"version": "0.6.1",
"private": true,
"type": "module",
"sideEffects": false,

View File

@ -1,6 +1,6 @@
{
"name": "@repo/rdx-logger",
"version": "0.6.0",
"version": "0.6.1",
"private": true,
"type": "module",
"sideEffects": false,

View File

@ -1,6 +1,7 @@
{
"extends": "@repo/typescript-config/react-library.json",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@repo/rdx-ui/*": ["./src/*"]
},

View File

@ -1,6 +1,6 @@
{
"name": "@repo/rdx-utils",
"version": "0.6.0",
"version": "0.6.1",
"private": true,
"type": "module",
"sideEffects": false,

View File

@ -2,6 +2,7 @@
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Root",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@erp/core/*": [
"modules/core/src/*"
@ -14,6 +15,9 @@
],
"@erp/customer-invoices/*": [
"modules/customer-invoices/src/*"
],
"@erp/factuges/*": [
"modules/factuges/src/*"
]
},
"target": "ES2021",

View File

@ -65,6 +65,9 @@ importers:
'@erp/customers':
specifier: workspace:*
version: link:../../modules/customers
'@erp/factuges':
specifier: workspace:*
version: link:../../modules/factuges
'@repo/rdx-logger':
specifier: workspace:*
version: link:../../packages/rdx-logger