feat: implement organization fiscal profile management including ARCA activity search and fiscal data configuration

This commit is contained in:
2026-08-10 13:05:09 -03:00
parent ebd8096112
commit 6e7bf6e835
23 changed files with 1876 additions and 187 deletions
@@ -34,6 +34,8 @@ export class OrganizationFiscalProfilesAdapterMongoose implements IOrganizationF
enum: Object.values(ORGANIZATION_FISCAL_PROFILE_TAX_CONDITION),
},
pointOfSale: { type: Number, required: true },
activityCode: { type: String, required: false },
activityDescription: { type: String, required: false },
status: {
type: String,
required: true,
@@ -17,6 +17,8 @@ export type UpsertOrganizationFiscalProfileParams = {
legalName: string;
taxCondition: ORGANIZATION_FISCAL_PROFILE_TAX_CONDITION;
pointOfSale: number;
activityCode?: string;
activityDescription?: string;
sessionUser: string;
};
@@ -33,6 +35,8 @@ export type CreateOrganizationFiscalProfileParams = {
legalName: string;
taxCondition: ORGANIZATION_FISCAL_PROFILE_TAX_CONDITION;
pointOfSale: number;
activityCode?: string;
activityDescription?: string;
status: ORGANIZATION_FISCAL_PROFILE_STATUS;
createdAt: Date;
updatedAt: Date;
@@ -43,6 +47,8 @@ export type UpdateOrganizationFiscalProfileParams = FindOrganizationFiscalProfil
legalName?: string;
taxCondition?: ORGANIZATION_FISCAL_PROFILE_TAX_CONDITION;
pointOfSale?: number;
activityCode?: string;
activityDescription?: string;
status?: ORGANIZATION_FISCAL_PROFILE_STATUS;
updatedAt: Date;
};
@@ -54,6 +60,8 @@ export interface IOrganizationFiscalProfile {
legalName: string;
taxCondition: ORGANIZATION_FISCAL_PROFILE_TAX_CONDITION;
pointOfSale: number;
activityCode?: string;
activityDescription?: string;
status: ORGANIZATION_FISCAL_PROFILE_STATUS;
createdAt: Date;
updatedAt: Date;
@@ -1,4 +1,5 @@
import { validatePermissionsByCompany, validateSessionUser } from "../../helpers/check";
import { findArcaActivityByCode } from "../ArcaActivities/ArcaActivities.Catalog";
import { OrganizationFiscalProfilesAdapterMongoose } from "./OrganizationFiscalProfiles.Adapter.Mongoose";
import {
FindOrganizationFiscalProfilesParams,
@@ -31,6 +32,31 @@ class OrganizationFiscalProfilesManager implements IOrganizationFiscalProfilesMa
if (!data.pointOfSale || data.pointOfSale <= 0) {
throw new Error("El punto de venta debe ser mayor a 0");
}
const activityCode = data.activityCode?.trim();
if (activityCode && !/^\d{6}$/.test(activityCode)) {
throw new Error("El código de actividad debe contener 6 dígitos");
}
if (activityCode && !findArcaActivityByCode(activityCode)) {
throw new Error("La actividad ARCA/CLAE seleccionada no existe en el catálogo");
}
}
private buildProfileData(data: UpsertOrganizationFiscalProfileParams) {
const activityCode = data.activityCode?.trim();
const activity = activityCode ? findArcaActivityByCode(activityCode) : undefined;
return {
cuit: data.cuit,
legalName: data.legalName.trim(),
taxCondition: data.taxCondition,
pointOfSale: data.pointOfSale,
activityCode: activity?.code || "",
activityDescription: activity?.description || "",
status: ORGANIZATION_FISCAL_PROFILE_STATUS.ACTIVE,
};
}
public async upsert(
@@ -51,15 +77,12 @@ class OrganizationFiscalProfilesManager implements IOrganizationFiscalProfilesMa
});
const now = new Date();
const profileData = this.buildProfileData(data);
if (existingProfile) {
const updatedProfile = await this.organizationFiscalProfiles.update({
companyId: data.companyId,
cuit: data.cuit,
legalName: data.legalName.trim(),
taxCondition: data.taxCondition,
pointOfSale: data.pointOfSale,
status: ORGANIZATION_FISCAL_PROFILE_STATUS.ACTIVE,
...profileData,
updatedAt: now,
});
@@ -73,11 +96,7 @@ class OrganizationFiscalProfilesManager implements IOrganizationFiscalProfilesMa
try {
return await this.organizationFiscalProfiles.create({
companyId: data.companyId,
cuit: data.cuit,
legalName: data.legalName.trim(),
taxCondition: data.taxCondition,
pointOfSale: data.pointOfSale,
status: ORGANIZATION_FISCAL_PROFILE_STATUS.ACTIVE,
...profileData,
createdAt: now,
updatedAt: now,
});
@@ -85,11 +104,7 @@ class OrganizationFiscalProfilesManager implements IOrganizationFiscalProfilesMa
if (this.isDuplicateKeyError(error)) {
const updatedProfile = await this.organizationFiscalProfiles.update({
companyId: data.companyId,
cuit: data.cuit,
legalName: data.legalName.trim(),
taxCondition: data.taxCondition,
pointOfSale: data.pointOfSale,
status: ORGANIZATION_FISCAL_PROFILE_STATUS.ACTIVE,
...profileData,
updatedAt: new Date(),
});