Clientes y facturas de cliente
This commit is contained in:
parent
a4f928b716
commit
bec5a54756
@ -45,6 +45,7 @@
|
|||||||
"@erp/core": "workspace:*",
|
"@erp/core": "workspace:*",
|
||||||
"@erp/customer-invoices": "workspace:*",
|
"@erp/customer-invoices": "workspace:*",
|
||||||
"@erp/customers": "workspace:*",
|
"@erp/customers": "workspace:*",
|
||||||
|
"@repo/rdx-logger": "workspace:*",
|
||||||
"bcrypt": "^5.1.1",
|
"bcrypt": "^5.1.1",
|
||||||
"cls-rtracer": "^2.6.3",
|
"cls-rtracer": "^2.6.3",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
@ -79,14 +80,9 @@
|
|||||||
"node": ">=22"
|
"node": ">=22"
|
||||||
},
|
},
|
||||||
"tsup": {
|
"tsup": {
|
||||||
"entry": [
|
"entry": ["src/index.ts"],
|
||||||
"src/index.ts"
|
|
||||||
],
|
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"format": [
|
"format": ["esm", "cjs"],
|
||||||
"esm",
|
|
||||||
"cjs"
|
|
||||||
],
|
|
||||||
"target": "ES2022",
|
"target": "ES2022",
|
||||||
"sourcemap": true,
|
"sourcemap": true,
|
||||||
"clean": true,
|
"clean": true,
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { logger } from "@/lib/logger";
|
|
||||||
import cors, { CorsOptions } from "cors";
|
import cors, { CorsOptions } from "cors";
|
||||||
import express, { Application } from "express";
|
import express, { Application } from "express";
|
||||||
import helmet from "helmet";
|
import helmet from "helmet";
|
||||||
import responseTime from "response-time";
|
import responseTime from "response-time";
|
||||||
|
import { logger } from "./lib/logger";
|
||||||
|
|
||||||
// ❗️ No cargamos dotenv aquí. Debe hacerse en el entrypoint o en ./config.
|
// ❗️ No cargamos dotenv aquí. Debe hacerse en el entrypoint o en ./config.
|
||||||
// dotenv.config();
|
// dotenv.config();
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { logger } from "@/lib/logger";
|
|
||||||
import { Sequelize } from "sequelize";
|
import { Sequelize } from "sequelize";
|
||||||
|
import { logger } from "../lib/logger";
|
||||||
import { ENV } from "./index";
|
import { ENV } from "./index";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { logger } from "@/lib/logger";
|
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
import http from "node:http";
|
import http from "node:http";
|
||||||
import os from "node:os";
|
import os from "node:os";
|
||||||
@ -7,7 +6,7 @@ import { createApp } from "./app";
|
|||||||
import { ENV } from "./config";
|
import { ENV } from "./config";
|
||||||
import { tryConnectToDatabase } from "./config/database";
|
import { tryConnectToDatabase } from "./config/database";
|
||||||
import { registerHealthRoutes } from "./health";
|
import { registerHealthRoutes } from "./health";
|
||||||
import { listRoutes } from "./lib";
|
import { listRoutes, logger } from "./lib";
|
||||||
import { initModules } from "./lib/modules";
|
import { initModules } from "./lib/modules";
|
||||||
import { registerModules } from "./register-modules";
|
import { registerModules } from "./register-modules";
|
||||||
|
|
||||||
|
|||||||
6
apps/server/src/lib/logger.ts
Normal file
6
apps/server/src/lib/logger.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { configureLogger, setLoggerSingleton } from "@repo/rdx-logger";
|
||||||
|
|
||||||
|
const logger = configureLogger("console"); // o según config/env
|
||||||
|
setLoggerSingleton(logger);
|
||||||
|
|
||||||
|
export { logger };
|
||||||
@ -1,8 +0,0 @@
|
|||||||
import { ILogger } from "@erp/core/api";
|
|
||||||
import { ConsoleLogger } from "./console-logger";
|
|
||||||
|
|
||||||
// Aquí podrías cambiar por SentryLogger en el futuro
|
|
||||||
const logger: ILogger = new ConsoleLogger();
|
|
||||||
|
|
||||||
export { logger };
|
|
||||||
export type { ILogger };
|
|
||||||
@ -2,5 +2,4 @@ export * from "./application";
|
|||||||
export * from "./domain";
|
export * from "./domain";
|
||||||
export * from "./helpers";
|
export * from "./helpers";
|
||||||
export * from "./infrastructure";
|
export * from "./infrastructure";
|
||||||
export * from "./logger";
|
|
||||||
export * from "./modules";
|
export * from "./modules";
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
export * from "./logger.interface";
|
|
||||||
@ -41,6 +41,7 @@
|
|||||||
"@hookform/resolvers": "^5.0.1",
|
"@hookform/resolvers": "^5.0.1",
|
||||||
"@repo/rdx-criteria": "workspace:*",
|
"@repo/rdx-criteria": "workspace:*",
|
||||||
"@repo/rdx-ddd": "workspace:*",
|
"@repo/rdx-ddd": "workspace:*",
|
||||||
|
"@repo/rdx-logger": "workspace:*",
|
||||||
"@repo/rdx-ui": "workspace:*",
|
"@repo/rdx-ui": "workspace:*",
|
||||||
"@repo/rdx-utils": "workspace:*",
|
"@repo/rdx-utils": "workspace:*",
|
||||||
"@repo/shadcn-ui": "workspace:*",
|
"@repo/shadcn-ui": "workspace:*",
|
||||||
|
|||||||
@ -34,6 +34,7 @@
|
|||||||
"@hookform/resolvers": "^5.0.1",
|
"@hookform/resolvers": "^5.0.1",
|
||||||
"@repo/rdx-criteria": "workspace:*",
|
"@repo/rdx-criteria": "workspace:*",
|
||||||
"@repo/rdx-ddd": "workspace:*",
|
"@repo/rdx-ddd": "workspace:*",
|
||||||
|
"@repo/rdx-logger": "workspace:*",
|
||||||
"@repo/rdx-ui": "workspace:*",
|
"@repo/rdx-ui": "workspace:*",
|
||||||
"@repo/rdx-utils": "workspace:*",
|
"@repo/rdx-utils": "workspace:*",
|
||||||
"@repo/shadcn-ui": "workspace:*",
|
"@repo/shadcn-ui": "workspace:*",
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { CompositeSpecification, UniqueID } from "@repo/rdx-ddd";
|
import { CompositeSpecification, UniqueID } from "@repo/rdx-ddd";
|
||||||
import { CustomerService } from "../../domain";
|
import { CustomerService } from "../../domain";
|
||||||
|
import { logger } from "../../helpers";
|
||||||
|
|
||||||
export class CustomerNotExistsInCompanySpecification extends CompositeSpecification<UniqueID> {
|
export class CustomerNotExistsInCompanySpecification extends CompositeSpecification<UniqueID> {
|
||||||
constructor(
|
constructor(
|
||||||
@ -11,11 +12,24 @@ export class CustomerNotExistsInCompanySpecification extends CompositeSpecificat
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async isSatisfiedBy(customerId: UniqueID): Promise<boolean> {
|
public async isSatisfiedBy(customerId: UniqueID): Promise<boolean> {
|
||||||
const exists = await this.service.existsByIdInCompany(
|
const existsCheck = await this.service.existsByIdInCompany(
|
||||||
customerId,
|
|
||||||
this.companyId,
|
this.companyId,
|
||||||
|
customerId,
|
||||||
this.transaction
|
this.transaction
|
||||||
);
|
);
|
||||||
return !exists;
|
|
||||||
|
if (existsCheck.isFailure) {
|
||||||
|
throw existsCheck.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
const customerExists = existsCheck.data;
|
||||||
|
logger.debug(
|
||||||
|
`customerExists => ${customerExists}, ${JSON.stringify({ customerId, companyId: this.companyId }, null, 2)}`,
|
||||||
|
{
|
||||||
|
label: "CustomerNotExistsInCompanySpecification",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return customerExists === false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { UniqueID } from "@repo/rdx-ddd";
|
|||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import { Transaction } from "sequelize";
|
import { Transaction } from "sequelize";
|
||||||
import { CreateCustomerRequestDTO } from "../../../../common";
|
import { CreateCustomerRequestDTO } from "../../../../common";
|
||||||
|
import { logger } from "../../..//helpers";
|
||||||
import { CustomerService } from "../../../domain";
|
import { CustomerService } from "../../../domain";
|
||||||
import { CustomerFullPresenter } from "../../presenters";
|
import { CustomerFullPresenter } from "../../presenters";
|
||||||
import { CustomerNotExistsInCompanySpecification } from "../../specs";
|
import { CustomerNotExistsInCompanySpecification } from "../../specs";
|
||||||
@ -52,12 +53,16 @@ export class CreateCustomerUseCase {
|
|||||||
companyId,
|
companyId,
|
||||||
transaction
|
transaction
|
||||||
);
|
);
|
||||||
|
|
||||||
const isNew = await spec.isSatisfiedBy(newCustomer.id);
|
const isNew = await spec.isSatisfiedBy(newCustomer.id);
|
||||||
|
logger.debug(`isNew => ${isNew}`, { label: "CreateCustomerUseCase.execute" });
|
||||||
|
|
||||||
if (!isNew) {
|
if (!isNew) {
|
||||||
return Result.fail(new DuplicateEntityError("Customer", "id", String(newCustomer.id)));
|
return Result.fail(new DuplicateEntityError("Customer", "id", String(newCustomer.id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.debug(JSON.stringify(newCustomer, null, 6));
|
||||||
|
|
||||||
const saveResult = await this.service.saveCustomer(newCustomer, transaction);
|
const saveResult = await this.service.saveCustomer(newCustomer, transaction);
|
||||||
if (saveResult.isFailure) {
|
if (saveResult.isFailure) {
|
||||||
return Result.fail(saveResult.error);
|
return Result.fail(saveResult.error);
|
||||||
|
|||||||
@ -40,10 +40,10 @@ export function mapDTOToCreateCustomerProps(dto: CreateCustomerRequestDTO) {
|
|||||||
const errors: ValidationErrorDetail[] = [];
|
const errors: ValidationErrorDetail[] = [];
|
||||||
|
|
||||||
const customerId = extractOrPushError(UniqueID.create(dto.id), "id", errors);
|
const customerId = extractOrPushError(UniqueID.create(dto.id), "id", errors);
|
||||||
const companyId = extractOrPushError(UniqueID.create(dto.company_id), "company_id", errors);
|
|
||||||
|
|
||||||
|
const status = CustomerStatus.createActive();
|
||||||
const isCompany = dto.is_company === "true";
|
const isCompany = dto.is_company === "true";
|
||||||
const status = extractOrPushError(CustomerStatus.create(dto.status), "status", errors);
|
|
||||||
const reference = extractOrPushError(
|
const reference = extractOrPushError(
|
||||||
maybeFromNullableVO(dto.reference, (value) => Name.create(value)),
|
maybeFromNullableVO(dto.reference, (value) => Name.create(value)),
|
||||||
"reference",
|
"reference",
|
||||||
@ -100,15 +100,39 @@ export function mapDTOToCreateCustomerProps(dto: CreateCustomerRequestDTO) {
|
|||||||
errors
|
errors
|
||||||
);
|
);
|
||||||
|
|
||||||
const emailAddress = extractOrPushError(
|
const primaryEmailAddress = extractOrPushError(
|
||||||
maybeFromNullableVO(dto.email, (value) => EmailAddress.create(value)),
|
maybeFromNullableVO(dto.email_primary, (value) => EmailAddress.create(value)),
|
||||||
"email",
|
"email_primary",
|
||||||
errors
|
errors
|
||||||
);
|
);
|
||||||
|
|
||||||
const phoneNumber = extractOrPushError(
|
const secondaryEmailAddress = extractOrPushError(
|
||||||
maybeFromNullableVO(dto.phone, (value) => PhoneNumber.create(value)),
|
maybeFromNullableVO(dto.email_secondary, (value) => EmailAddress.create(value)),
|
||||||
"phone",
|
"email_secondary",
|
||||||
|
errors
|
||||||
|
);
|
||||||
|
|
||||||
|
const primaryPhoneNumber = extractOrPushError(
|
||||||
|
maybeFromNullableVO(dto.phone_primary, (value) => PhoneNumber.create(value)),
|
||||||
|
"phone_primary",
|
||||||
|
errors
|
||||||
|
);
|
||||||
|
|
||||||
|
const secondaryPhoneNumber = extractOrPushError(
|
||||||
|
maybeFromNullableVO(dto.phone_secondary, (value) => PhoneNumber.create(value)),
|
||||||
|
"phone_secondary",
|
||||||
|
errors
|
||||||
|
);
|
||||||
|
|
||||||
|
const primaryMobileNumber = extractOrPushError(
|
||||||
|
maybeFromNullableVO(dto.mobile_primary, (value) => PhoneNumber.create(value)),
|
||||||
|
"mobile_primary",
|
||||||
|
errors
|
||||||
|
);
|
||||||
|
|
||||||
|
const secondaryMobileNumber = extractOrPushError(
|
||||||
|
maybeFromNullableVO(dto.mobile_secondary, (value) => PhoneNumber.create(value)),
|
||||||
|
"mobile_secondary",
|
||||||
errors
|
errors
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -145,7 +169,7 @@ export function mapDTOToCreateCustomerProps(dto: CreateCustomerRequestDTO) {
|
|||||||
const defaultTaxes = new Collection<TaxCode>();
|
const defaultTaxes = new Collection<TaxCode>();
|
||||||
|
|
||||||
if (!isNullishOrEmpty(dto.default_taxes)) {
|
if (!isNullishOrEmpty(dto.default_taxes)) {
|
||||||
dto.default_taxes.split(",").map((taxCode, index) => {
|
dto.default_taxes!.map((taxCode, index) => {
|
||||||
const tax = extractOrPushError(TaxCode.create(taxCode), `default_taxes.${index}`, errors);
|
const tax = extractOrPushError(TaxCode.create(taxCode), `default_taxes.${index}`, errors);
|
||||||
if (tax) {
|
if (tax) {
|
||||||
defaultTaxes.add(tax!);
|
defaultTaxes.add(tax!);
|
||||||
@ -172,8 +196,7 @@ export function mapDTOToCreateCustomerProps(dto: CreateCustomerRequestDTO) {
|
|||||||
errors
|
errors
|
||||||
);
|
);
|
||||||
|
|
||||||
const customerProps: CustomerProps = {
|
const customerProps: Omit<CustomerProps, "companyId"> = {
|
||||||
companyId: companyId!,
|
|
||||||
status: status!,
|
status: status!,
|
||||||
reference: reference!,
|
reference: reference!,
|
||||||
|
|
||||||
@ -184,8 +207,13 @@ export function mapDTOToCreateCustomerProps(dto: CreateCustomerRequestDTO) {
|
|||||||
|
|
||||||
address: postalAddress!,
|
address: postalAddress!,
|
||||||
|
|
||||||
email: emailAddress!,
|
emailPrimary: primaryEmailAddress!,
|
||||||
phone: phoneNumber!,
|
emailSecondary: secondaryEmailAddress!,
|
||||||
|
phonePrimary: primaryPhoneNumber!,
|
||||||
|
phoneSecondary: secondaryPhoneNumber!,
|
||||||
|
mobilePrimary: primaryMobileNumber!,
|
||||||
|
mobileSecondary: secondaryMobileNumber!,
|
||||||
|
|
||||||
fax: faxNumber!,
|
fax: faxNumber!,
|
||||||
website: website!,
|
website: website!,
|
||||||
|
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "../application/create-customer/map-dto-to-create-customer-props";
|
export * from "./logger";
|
||||||
|
|||||||
3
modules/customers/src/api/helpers/logger.ts
Normal file
3
modules/customers/src/api/helpers/logger.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { loggerSingleton } from "@repo/rdx-logger";
|
||||||
|
|
||||||
|
export const logger = loggerSingleton();
|
||||||
@ -32,7 +32,7 @@ export type CustomerDeps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function buildCustomerDependencies(params: ModuleParams): CustomerDeps {
|
export function buildCustomerDependencies(params: ModuleParams): CustomerDeps {
|
||||||
const { database } = params;
|
const { database, logger } = params;
|
||||||
const transactionManager = new SequelizeTransactionManager(database);
|
const transactionManager = new SequelizeTransactionManager(database);
|
||||||
|
|
||||||
// Mapper Registry
|
// Mapper Registry
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
|
||||||
export const CreateCustomerRequestSchema = z.object({
|
export const CreateCustomerRequestSchema = z.object({
|
||||||
reference: z.string().optional(),
|
id: z.string().nonempty(),
|
||||||
|
|
||||||
is_company: z.string().toLowerCase().default("false").optional(),
|
reference: z.string().optional(),
|
||||||
|
is_company: z.string().toLowerCase().default("false"),
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
trade_name: z.string().optional(),
|
trade_name: z.string().optional(),
|
||||||
tin: z.string().optional(),
|
tin: z.string().optional(),
|
||||||
@ -28,8 +29,8 @@ export const CreateCustomerRequestSchema = z.object({
|
|||||||
|
|
||||||
legal_record: z.string().optional(),
|
legal_record: z.string().optional(),
|
||||||
|
|
||||||
language_code: z.string().toLowerCase().default("es").optional(),
|
language_code: z.string().toLowerCase().default("es"),
|
||||||
currency_code: z.string().toUpperCase().default("EUR").optional(),
|
currency_code: z.string().toUpperCase().default("EUR"),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type CreateCustomerRequestDTO = z.infer<typeof CreateCustomerRequestSchema>;
|
export type CreateCustomerRequestDTO = z.infer<typeof CreateCustomerRequestSchema>;
|
||||||
|
|||||||
1
modules/verifactu/src/api/application/use-cases/index.ts
Normal file
1
modules/verifactu/src/api/application/use-cases/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from "./send-invoice-verifactu.use-case";
|
||||||
@ -0,0 +1 @@
|
|||||||
|
export * from "./send-invoice-verifactu.use-case";
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
import { IPresenterRegistry, ITransactionManager } from "@erp/core/api";
|
||||||
|
import { UniqueID } from "@repo/rdx-ddd";
|
||||||
|
import { Result } from "@repo/rdx-utils";
|
||||||
|
import { VerifactuRecordService } from "../../../domain/services/verifactu-record.service";
|
||||||
|
|
||||||
|
type SendInvoiceVerifactuUseCaseInput = {
|
||||||
|
invoice_id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class SendInvoiceVerifactuUseCase {
|
||||||
|
constructor(
|
||||||
|
private readonly service: VerifactuRecordService,
|
||||||
|
private readonly transactionManager: ITransactionManager,
|
||||||
|
private readonly presenterRegistry: IPresenterRegistry
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public async execute(params: SendInvoiceVerifactuUseCaseInput) {
|
||||||
|
const { invoice_id } = params;
|
||||||
|
|
||||||
|
const idOrError = UniqueID.create(invoice_id);
|
||||||
|
|
||||||
|
if (idOrError.isFailure) {
|
||||||
|
return Result.fail(idOrError.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
const invoiceId = idOrError.data;
|
||||||
|
return this.transactionManager.complete(async (Transaction) => {
|
||||||
|
try {
|
||||||
|
const invoiceOrError = await this.service.sendInvoiceToVerifactu(invoiceId, transaction);
|
||||||
|
if (invoiceOrError.isFailure) {
|
||||||
|
return Result.fail(invoiceOrError.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
const invoice = invoiceOrError.data;
|
||||||
|
return Result.ok({});
|
||||||
|
} catch (error: unknown) {
|
||||||
|
return Result.fail(error as Error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
1
modules/verifactu/src/api/domain/aggregates/index.ts
Normal file
1
modules/verifactu/src/api/domain/aggregates/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from "./verifactu-record";
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
import { AggregateRoot, UniqueID } from "@repo/rdx-ddd";
|
||||||
|
import { Result } from "@repo/rdx-utils";
|
||||||
|
|
||||||
|
export interface VerifactuRecordProps {
|
||||||
|
id: UniqueID;
|
||||||
|
invoiceId: UniqueID;
|
||||||
|
estado: string;
|
||||||
|
url: string;
|
||||||
|
qr1: JSON;
|
||||||
|
qr2: Blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IVerifactuRecord = {};
|
||||||
|
|
||||||
|
export class VerifactuRecord
|
||||||
|
extends AggregateRoot<VerifactuRecordProps>
|
||||||
|
implements IVerifactuRecord
|
||||||
|
{
|
||||||
|
protected constructor(props: VerifactuRecordProps, invoiceId: UniqueID) {
|
||||||
|
super(props, invoiceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
static create(props: VerifactuRecordProps, invoiceId: UniqueID): Result<VerifactuRecord, Error> {
|
||||||
|
const verifactuRecord = new VerifactuRecord(props, invoiceId);
|
||||||
|
|
||||||
|
// Reglas de negocio / validaciones
|
||||||
|
|
||||||
|
return Result.ok(verifactuRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
public get invoiceId(): UniqueID {
|
||||||
|
return this.props.invoiceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get estado(): string {
|
||||||
|
return this.props.estado;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get url(): string {
|
||||||
|
return this.props.url;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,75 +1,26 @@
|
|||||||
import { Criteria } from "@repo/rdx-criteria/server";
|
import { UniqueID } from "../../../../../../packages/rdx-ddd/src";
|
||||||
import { UniqueID } from "@repo/rdx-ddd";
|
import { Result } from "../../../../../../packages/rdx-utils/src";
|
||||||
import { Collection, Result } from "@repo/rdx-utils";
|
import { VerifactuRecord } from "../aggregates";
|
||||||
import { CustomerInvoiceListDTO } from "../../infrastructure";
|
|
||||||
import { CustomerInvoice } from "../aggregates";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interfaz del repositorio para el agregado `CustomerInvoice`.
|
* Interfaz del repositorio para el agregado `Verifactu`.
|
||||||
* El escopado multitenant está representado por `companyId`.
|
* El escopado multitenant está representado por `companyId`.
|
||||||
*/
|
*/
|
||||||
export interface ICustomerInvoiceRepository {
|
export interface IVerifactuRecordRepository {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Persiste una nueva factura o actualiza una existente.
|
* Persiste una nueva factura o actualiza una existente.
|
||||||
* Retorna el objeto actualizado tras la operación.
|
* Retorna el objeto actualizado tras la operación.
|
||||||
*
|
*
|
||||||
* @param invoice - El agregado a guardar.
|
* @param verifactuRecord - El agregado a guardar.
|
||||||
* @param transaction - Transacción activa para la operación.
|
* @param transaction - Transacción activa para la operación.
|
||||||
* @returns Result<CustomerInvoice, Error>
|
* @returns Result<VerifactuRecord, Error>
|
||||||
*/
|
*/
|
||||||
save(invoice: CustomerInvoice, transaction: any): Promise<Result<CustomerInvoice, Error>>;
|
save(verifactuRecord: VerifactuRecord, transaction: any): Promise<Result<VerifactuRecord, Error>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comprueba si existe una factura con un `id` dentro de una `company`.
|
* Recupera un registro por su ID.
|
||||||
*/
|
|
||||||
existsByIdInCompany(
|
|
||||||
companyId: UniqueID,
|
|
||||||
id: UniqueID,
|
|
||||||
transaction?: any
|
|
||||||
): Promise<Result<boolean, Error>>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recupera una factura por su ID y companyId.
|
|
||||||
* Devuelve un `NotFoundError` si no se encuentra.
|
* Devuelve un `NotFoundError` si no se encuentra.
|
||||||
*/
|
*/
|
||||||
getByIdInCompany(
|
getById(id: UniqueID, transaction?: any): Promise<Result<VerifactuRecord, Error>>;
|
||||||
companyId: UniqueID,
|
|
||||||
id: UniqueID,
|
|
||||||
transaction?: any
|
|
||||||
): Promise<Result<CustomerInvoice, Error>>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Consulta facturas dentro de una empresa usando un
|
|
||||||
* objeto Criteria (filtros, orden, paginación).
|
|
||||||
* El resultado está encapsulado en un objeto `Collection<T>`.
|
|
||||||
*
|
|
||||||
* @param companyId - ID de la empresa.
|
|
||||||
* @param criteria - Criterios de búsqueda.
|
|
||||||
* @param transaction - Transacción activa para la operación.
|
|
||||||
* @returns Result<Collection<CustomerInvoiceListDTO>, Error>
|
|
||||||
*
|
|
||||||
* @see Criteria
|
|
||||||
*/
|
|
||||||
findByCriteriaInCompany(
|
|
||||||
companyId: UniqueID,
|
|
||||||
criteria: Criteria,
|
|
||||||
transaction: any
|
|
||||||
): Promise<Result<Collection<CustomerInvoiceListDTO>, Error>>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Elimina o marca como eliminada una factura dentro de una empresa.
|
|
||||||
*
|
|
||||||
* @param companyId - ID de la empresa.
|
|
||||||
* @param id - UUID de la factura a eliminar.
|
|
||||||
* @param transaction - Transacción activa para la operación.
|
|
||||||
* @returns Result<void, Error>
|
|
||||||
*/
|
|
||||||
deleteByIdInCompany(
|
|
||||||
companyId: UniqueID,
|
|
||||||
id: UniqueID,
|
|
||||||
transaction: any
|
|
||||||
): Promise<Result<void, Error>>;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,72 @@
|
|||||||
|
import { UniqueID } from "@repo/rdx-ddd";
|
||||||
|
import { Result } from "@repo/rdx-utils";
|
||||||
|
import { Transaction } from "sequelize";
|
||||||
|
import { CustomerInvoice, VerifactuRecord } from "../aggregates";
|
||||||
|
import { IVerifactuRecordRepository } from "../repositories/verifactu-repository.interface";
|
||||||
|
|
||||||
|
export class VerifactuRecordService {
|
||||||
|
constructor(private readonly repository: IVerifactuRecordRepository) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guarda un registro de VerifactuRecord en persistencia.
|
||||||
|
*
|
||||||
|
* @param verifactuRecord - El agregado a guardar.
|
||||||
|
* @param transaction - Transacción activa para la operación.
|
||||||
|
* @returns Result<CustomerInvoice, Error> - El agregado guardado o un error si falla la operación.
|
||||||
|
*/
|
||||||
|
async saveVerifactuRecord(
|
||||||
|
verifactuRecord: VerifactuRecord,
|
||||||
|
transaction: any
|
||||||
|
): Promise<Result<VerifactuRecord, Error>> {
|
||||||
|
return this.repository.save(verifactuRecord, transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actualiza parcialmente una factura existente con nuevos datos.
|
||||||
|
* No lo guarda en el repositorio.
|
||||||
|
*
|
||||||
|
* @param companyId - Identificador de la empresa a la que pertenece el cliente.
|
||||||
|
* @param invoiceId - Identificador de la factura a actualizar.
|
||||||
|
* @param changes - Subconjunto de props válidas para aplicar.
|
||||||
|
* @param transaction - Transacción activa para la operación.
|
||||||
|
* @returns Result<CustomerInvoice, Error> - Factura actualizada o error.
|
||||||
|
*/
|
||||||
|
async sendInvoiceToVerifactu(
|
||||||
|
invoiceId: UniqueID,
|
||||||
|
transaction?: Transaction
|
||||||
|
): Promise<Result<CustomerInvoice, Error>> {
|
||||||
|
// Verificar si la factura existe
|
||||||
|
// const invoiceResult = await this.getInvoiceByIdInCompany(invoiceId, transaction);
|
||||||
|
|
||||||
|
// if (invoiceResult.isFailure) {
|
||||||
|
// return Result.fail(invoiceResult.error);
|
||||||
|
// }
|
||||||
|
|
||||||
|
const invoice = {
|
||||||
|
serie: "A",
|
||||||
|
numero: "1",
|
||||||
|
fecha_expedicion: "12-09-2025",
|
||||||
|
tipo_factura: "F1",
|
||||||
|
descripcion: "Venta de bienes",
|
||||||
|
nif: "A15022510",
|
||||||
|
nombre: "Empresa de prueba SL",
|
||||||
|
lineas: [
|
||||||
|
{
|
||||||
|
base_imponible: "200",
|
||||||
|
tipo_impositivo: "21",
|
||||||
|
cuota_repercutida: "42",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
base_imponible: "100",
|
||||||
|
tipo_impositivo: "10",
|
||||||
|
cuota_repercutida: "10",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
importe_total: "352.00",
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log("ESTO ES UNA PRUEBA>>>>>>");
|
||||||
|
|
||||||
|
return Result.ok(invoice);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,139 +0,0 @@
|
|||||||
import { Criteria } from "@repo/rdx-criteria/server";
|
|
||||||
import { UniqueID } from "@repo/rdx-ddd";
|
|
||||||
import { Collection, Result } from "@repo/rdx-utils";
|
|
||||||
import { Transaction } from "sequelize";
|
|
||||||
import { CustomerInvoiceListDTO } from "../../infrastructure";
|
|
||||||
import { CustomerInvoice, CustomerInvoicePatchProps, CustomerInvoiceProps } from "../aggregates";
|
|
||||||
import { ICustomerInvoiceRepository } from "../repositories";
|
|
||||||
|
|
||||||
export class CustomerInvoiceService {
|
|
||||||
constructor(private readonly repository: ICustomerInvoiceRepository) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construye un nuevo agregado CustomerInvoice a partir de props validadas.
|
|
||||||
*
|
|
||||||
* @param companyId - Identificador de la empresa a la que pertenece el cliente.
|
|
||||||
* @param props - Las propiedades ya validadas para crear la factura.
|
|
||||||
* @param invoiceId - Identificador UUID de la factura (opcional).
|
|
||||||
* @returns Result<CustomerInvoice, Error> - El agregado construido o un error si falla la creación.
|
|
||||||
*/
|
|
||||||
buildInvoiceInCompany(
|
|
||||||
companyId: UniqueID,
|
|
||||||
props: Omit<CustomerInvoiceProps, "companyId">,
|
|
||||||
invoiceId?: UniqueID
|
|
||||||
): Result<CustomerInvoice, Error> {
|
|
||||||
return CustomerInvoice.create({ ...props, companyId }, invoiceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Guarda una instancia de CustomerInvoice en persistencia.
|
|
||||||
*
|
|
||||||
* @param invoice - El agregado a guardar.
|
|
||||||
* @param transaction - Transacción activa para la operación.
|
|
||||||
* @returns Result<CustomerInvoice, Error> - El agregado guardado o un error si falla la operación.
|
|
||||||
*/
|
|
||||||
async saveInvoice(
|
|
||||||
invoice: CustomerInvoice,
|
|
||||||
transaction: any
|
|
||||||
): Promise<Result<CustomerInvoice, Error>> {
|
|
||||||
return this.repository.save(invoice, transaction);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Comprueba si existe o no en persistencia una factura con el ID proporcionado
|
|
||||||
*
|
|
||||||
* @param companyId - Identificador UUID de la empresa a la que pertenece el cliente.
|
|
||||||
* @param invoiceId - Identificador UUID de la factura.
|
|
||||||
* @param transaction - Transacción activa para la operación.
|
|
||||||
* @returns Result<Boolean, Error> - Existe la factura o no.
|
|
||||||
*/
|
|
||||||
|
|
||||||
async existsByIdInCompany(
|
|
||||||
companyId: UniqueID,
|
|
||||||
invoiceId: UniqueID,
|
|
||||||
transaction?: any
|
|
||||||
): Promise<Result<boolean, Error>> {
|
|
||||||
return this.repository.existsByIdInCompany(companyId, invoiceId, transaction);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtiene una colección de facturas que cumplen con los filtros definidos en un objeto Criteria.
|
|
||||||
*
|
|
||||||
* @param companyId - Identificador UUID de la empresa a la que pertenece el cliente.
|
|
||||||
* @param criteria - Objeto con condiciones de filtro, paginación y orden.
|
|
||||||
* @param transaction - Transacción activa para la operación.
|
|
||||||
* @returns Result<Collection<CustomerInvoiceListDTO>, Error> - Colección de facturas o error.
|
|
||||||
*/
|
|
||||||
async findInvoiceByCriteriaInCompany(
|
|
||||||
companyId: UniqueID,
|
|
||||||
criteria: Criteria,
|
|
||||||
transaction?: Transaction
|
|
||||||
): Promise<Result<Collection<CustomerInvoiceListDTO>, Error>> {
|
|
||||||
return this.repository.findByCriteriaInCompany(companyId, criteria, transaction);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recupera una factura por su identificador único.
|
|
||||||
*
|
|
||||||
* @param invoiceId - Identificador UUID de la factura.
|
|
||||||
* @param transaction - Transacción activa para la operación.
|
|
||||||
* @returns Result<CustomerInvoice, Error> - Factura encontrada o error.
|
|
||||||
*/
|
|
||||||
async getInvoiceByIdInCompany(
|
|
||||||
companyId: UniqueID,
|
|
||||||
invoiceId: UniqueID,
|
|
||||||
transaction?: Transaction
|
|
||||||
): Promise<Result<CustomerInvoice>> {
|
|
||||||
return await this.repository.getByIdInCompany(companyId, invoiceId, transaction);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Actualiza parcialmente una factura existente con nuevos datos.
|
|
||||||
* No lo guarda en el repositorio.
|
|
||||||
*
|
|
||||||
* @param companyId - Identificador de la empresa a la que pertenece el cliente.
|
|
||||||
* @param invoiceId - Identificador de la factura a actualizar.
|
|
||||||
* @param changes - Subconjunto de props válidas para aplicar.
|
|
||||||
* @param transaction - Transacción activa para la operación.
|
|
||||||
* @returns Result<CustomerInvoice, Error> - Factura actualizada o error.
|
|
||||||
*/
|
|
||||||
async updateInvoiceByIdInCompany(
|
|
||||||
companyId: UniqueID,
|
|
||||||
invoiceId: UniqueID,
|
|
||||||
changes: CustomerInvoicePatchProps,
|
|
||||||
transaction?: Transaction
|
|
||||||
): Promise<Result<CustomerInvoice, Error>> {
|
|
||||||
// Verificar si la factura existe
|
|
||||||
const invoiceResult = await this.getInvoiceByIdInCompany(companyId, invoiceId, transaction);
|
|
||||||
|
|
||||||
if (invoiceResult.isFailure) {
|
|
||||||
return Result.fail(invoiceResult.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const invoice = invoiceResult.data;
|
|
||||||
const updatedInvoice = invoice.update(changes);
|
|
||||||
|
|
||||||
if (updatedInvoice.isFailure) {
|
|
||||||
return Result.fail(updatedInvoice.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.ok(updatedInvoice.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Elimina (o marca como eliminada) una factura según su ID.
|
|
||||||
*
|
|
||||||
* @param companyId - Identificador de la empresa a la que pertenece el cliente.
|
|
||||||
* @param invoiceId - Identificador UUID de la factura.
|
|
||||||
* @param transaction - Transacción activa para la operación.
|
|
||||||
* @returns Result<boolean, Error> - Resultado de la operación.
|
|
||||||
*/
|
|
||||||
async deleteInvoiceByIdInCompany(
|
|
||||||
companyId: UniqueID,
|
|
||||||
invoiceId: UniqueID,
|
|
||||||
transaction?: Transaction
|
|
||||||
): Promise<Result<void, Error>> {
|
|
||||||
return this.repository.deleteByIdInCompany(companyId, invoiceId, transaction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1 @@
|
|||||||
|
export * from "./send-invoice-verifactu.controller";
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
import { ExpressController, authGuard, forbidQueryFieldGuard, tenantGuard } from "@erp/core/api";
|
||||||
|
import { SendInvoiceVerifactuUseCase } from "../../../application/use-cases/send";
|
||||||
|
|
||||||
|
export class SendInvoiceVerifactuController extends ExpressController {
|
||||||
|
public constructor(private readonly useCase: SendInvoiceVerifactuUseCase) {
|
||||||
|
super();
|
||||||
|
// 🔐 Reutiliza guards de auth/tenant y prohíbe 'companyId' en query
|
||||||
|
this.useGuards(authGuard(), tenantGuard(), forbidQueryFieldGuard("companyId"));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async executeImpl() {
|
||||||
|
const companyId = this.getTenantId();
|
||||||
|
if (!companyId) {
|
||||||
|
return this.forbiddenError("Tenant ID not found");
|
||||||
|
}
|
||||||
|
const { invoice_id } = this.req.params;
|
||||||
|
|
||||||
|
const result = await this.useCase.execute({ invoice_id, companyId });
|
||||||
|
|
||||||
|
return result.match(
|
||||||
|
({ data, filename }) => this.downloadPDF(data, filename),
|
||||||
|
(err) => this.handleError(err)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
import { RequestWithAuth, enforceTenant, enforceUser, mockUser } from "@erp/auth/api";
|
||||||
|
import { ILogger, ModuleParams, validateRequest } from "@erp/core/api";
|
||||||
|
import { Application, NextFunction, Request, Response, Router } from "express";
|
||||||
|
import { Sequelize } from "sequelize";
|
||||||
|
import { ReportCustomerInvoiceByIdRequestSchema } from "../../../common/dto";
|
||||||
|
import { SendInvoiceVerifactuController } from "./controllers";
|
||||||
|
|
||||||
|
export const verifactuRouter = (params: ModuleParams) => {
|
||||||
|
const { app, baseRoutePath, logger } = params as {
|
||||||
|
app: Application;
|
||||||
|
database: Sequelize;
|
||||||
|
baseRoutePath: string;
|
||||||
|
logger: ILogger;
|
||||||
|
};
|
||||||
|
|
||||||
|
//const deps = buildCustomerInvoiceDependencies(params);
|
||||||
|
|
||||||
|
const router: Router = Router({ mergeParams: true });
|
||||||
|
|
||||||
|
// 🔐 Autenticación + Tenancy para TODO el router
|
||||||
|
if (process.env.NODE_ENV === "development") {
|
||||||
|
router.use(
|
||||||
|
(req: Request, res: Response, next: NextFunction) =>
|
||||||
|
mockUser(req as RequestWithAuth, res, next) // Debe ir antes de las rutas protegidas
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
router.use([
|
||||||
|
(req: Request, res: Response, next: NextFunction) =>
|
||||||
|
enforceUser()(req as RequestWithAuth, res, next), // Debe ir antes de las rutas protegidas
|
||||||
|
|
||||||
|
(req: Request, res: Response, next: NextFunction) =>
|
||||||
|
enforceTenant()(req as RequestWithAuth, res, next), // Debe ir antes de las rutas protegidas
|
||||||
|
]);
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
|
||||||
|
router.get(
|
||||||
|
"/:invoice_id/sendVerifactu",
|
||||||
|
//checkTabContext,
|
||||||
|
validateRequest(ReportCustomerInvoiceByIdRequestSchema, "params"),
|
||||||
|
(req: Request, res: Response, next: NextFunction) => {
|
||||||
|
const useCase = deps.build.report();
|
||||||
|
const controller = new SendInvoiceVerifactuController(useCase);
|
||||||
|
return controller.execute(req, res, next);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
20
packages/rdx-logger/package.json
Normal file
20
packages/rdx-logger/package.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "@repo/rdx-logger",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"main": "src/index.ts",
|
||||||
|
"types": "src/index.ts",
|
||||||
|
"scripts": {
|
||||||
|
"clean": "rm -rf node_modules"
|
||||||
|
},
|
||||||
|
"exports": {
|
||||||
|
".": "./src/index.ts"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.8.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"cls-rtracer": "^2.6.3",
|
||||||
|
"winston": "^3.17.0",
|
||||||
|
"winston-daily-rotate-file": "^5.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
17
packages/rdx-logger/src/configure-logger.ts
Normal file
17
packages/rdx-logger/src/configure-logger.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { createConsoleLogger, createSentryLogger, createWinstonLogger } from "./strategies";
|
||||||
|
import type { ILogger } from "./types";
|
||||||
|
|
||||||
|
export type LoggerStrategy = "console" | "winston" | "sentry";
|
||||||
|
|
||||||
|
export function configureLogger(strategy: LoggerStrategy = "console"): ILogger {
|
||||||
|
switch (strategy) {
|
||||||
|
case "console":
|
||||||
|
return createConsoleLogger();
|
||||||
|
case "winston":
|
||||||
|
return createWinstonLogger();
|
||||||
|
case "sentry":
|
||||||
|
return createSentryLogger();
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown logger strategy: ${strategy}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
3
packages/rdx-logger/src/index.ts
Normal file
3
packages/rdx-logger/src/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export { configureLogger } from "./configure-logger";
|
||||||
|
export { loggerSingleton, setLoggerSingleton } from "./singleton";
|
||||||
|
export * from "./types";
|
||||||
15
packages/rdx-logger/src/singleton.ts
Normal file
15
packages/rdx-logger/src/singleton.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { configureLogger } from "./configure-logger";
|
||||||
|
import type { ILogger } from "./types";
|
||||||
|
|
||||||
|
let _loggerInstance: ILogger | null = null;
|
||||||
|
|
||||||
|
export const loggerSingleton = (): ILogger => {
|
||||||
|
if (!_loggerInstance) {
|
||||||
|
_loggerInstance = configureLogger("console"); // o desde process.env
|
||||||
|
}
|
||||||
|
return _loggerInstance;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const setLoggerSingleton = (logger: ILogger): void => {
|
||||||
|
_loggerInstance = logger;
|
||||||
|
};
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { ILogger } from "@erp/core/api";
|
import { ILogger } from "../types";
|
||||||
|
|
||||||
export class ConsoleLogger implements ILogger {
|
export class ConsoleLogger implements ILogger {
|
||||||
info(message: string, meta?: any) {
|
info(message: string, meta?: any) {
|
||||||
@ -17,3 +17,5 @@ export class ConsoleLogger implements ILogger {
|
|||||||
console.debug(`[DEBUG] ${message}`, meta ?? "");
|
console.debug(`[DEBUG] ${message}`, meta ?? "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const createConsoleLogger = (): ILogger => new ConsoleLogger();
|
||||||
3
packages/rdx-logger/src/strategies/index.ts
Normal file
3
packages/rdx-logger/src/strategies/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from "./console-logger";
|
||||||
|
export * from "./sentry-logger";
|
||||||
|
export * from "./winston-logger";
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { ILogger } from "@erp/core/api";
|
import { ILogger } from "../types";
|
||||||
|
|
||||||
export class SentryLogger implements ILogger {
|
export class SentryLogger implements ILogger {
|
||||||
// biome-ignore lint/complexity/noUselessConstructor: <explanation>
|
// biome-ignore lint/complexity/noUselessConstructor: <explanation>
|
||||||
@ -25,3 +25,5 @@ export class SentryLogger implements ILogger {
|
|||||||
//Sentry.captureMessage(message, "debug");
|
//Sentry.captureMessage(message, "debug");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const createSentryLogger = (): ILogger => new SentryLogger();
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import { ILogger } from "@erp/core/api";
|
|
||||||
import rTracer from "cls-rtracer";
|
import rTracer from "cls-rtracer";
|
||||||
import { createLogger, format, transports } from "winston";
|
import { createLogger, format, transports } from "winston";
|
||||||
|
import { ILogger } from "../types";
|
||||||
|
|
||||||
const winston = createLogger({
|
const winston = createLogger({
|
||||||
level: "info",
|
level: "info",
|
||||||
@ -61,3 +61,5 @@ export class WinstonLogger implements ILogger {
|
|||||||
winston.error(message, { error: error?.stack || error });
|
winston.error(message, { error: error?.stack || error });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const createWinstonLogger = (): ILogger => new WinstonLogger();
|
||||||
8
packages/rdx-logger/tsconfig.json
Normal file
8
packages/rdx-logger/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true
|
||||||
|
},
|
||||||
|
"include": ["src", "../../modules/core/src/web/lib/helpers/money-funcs.ts"],
|
||||||
|
"exclude": ["src/**/__tests__/*"]
|
||||||
|
}
|
||||||
@ -41,6 +41,9 @@ importers:
|
|||||||
'@erp/customers':
|
'@erp/customers':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../modules/customers
|
version: link:../../modules/customers
|
||||||
|
'@repo/rdx-logger':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../packages/rdx-logger
|
||||||
bcrypt:
|
bcrypt:
|
||||||
specifier: ^5.1.1
|
specifier: ^5.1.1
|
||||||
version: 5.1.1
|
version: 5.1.1
|
||||||
@ -465,6 +468,9 @@ importers:
|
|||||||
'@repo/rdx-ddd':
|
'@repo/rdx-ddd':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../packages/rdx-ddd
|
version: link:../../packages/rdx-ddd
|
||||||
|
'@repo/rdx-logger':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../packages/rdx-logger
|
||||||
'@repo/rdx-ui':
|
'@repo/rdx-ui':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../packages/rdx-ui
|
version: link:../../packages/rdx-ui
|
||||||
@ -574,6 +580,9 @@ importers:
|
|||||||
'@repo/rdx-ddd':
|
'@repo/rdx-ddd':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../packages/rdx-ddd
|
version: link:../../packages/rdx-ddd
|
||||||
|
'@repo/rdx-logger':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../packages/rdx-logger
|
||||||
'@repo/rdx-ui':
|
'@repo/rdx-ui':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../packages/rdx-ui
|
version: link:../../packages/rdx-ui
|
||||||
@ -692,6 +701,22 @@ importers:
|
|||||||
specifier: ^5.8.3
|
specifier: ^5.8.3
|
||||||
version: 5.8.3
|
version: 5.8.3
|
||||||
|
|
||||||
|
packages/rdx-logger:
|
||||||
|
dependencies:
|
||||||
|
cls-rtracer:
|
||||||
|
specifier: ^2.6.3
|
||||||
|
version: 2.6.3
|
||||||
|
winston:
|
||||||
|
specifier: ^3.17.0
|
||||||
|
version: 3.17.0
|
||||||
|
winston-daily-rotate-file:
|
||||||
|
specifier: ^5.0.0
|
||||||
|
version: 5.0.0(winston@3.17.0)
|
||||||
|
devDependencies:
|
||||||
|
typescript:
|
||||||
|
specifier: ^5.8.3
|
||||||
|
version: 5.8.3
|
||||||
|
|
||||||
packages/rdx-ui:
|
packages/rdx-ui:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@dnd-kit/core':
|
'@dnd-kit/core':
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user