From ea16d576461aada5b155a16f6bb3768b141e9d11 Mon Sep 17 00:00:00 2001 From: dmolinari Date: Fri, 17 Apr 2026 18:55:21 -0300 Subject: [PATCH] feat(web/adm-009): types y api client para fiscal IVA TipoDeIva types (UpdateRequest sin Porcentaje), ivaApi.ts con 8 endpoints, ApiError contract { error, message } alineado con backend ADM-009. --- src/web/src/features/fiscal/iva/api/ivaApi.ts | 68 +++++++++++++++++ .../fiscal/iva/types/tipoDeIva.types.ts | 74 +++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 src/web/src/features/fiscal/iva/api/ivaApi.ts create mode 100644 src/web/src/features/fiscal/iva/types/tipoDeIva.types.ts diff --git a/src/web/src/features/fiscal/iva/api/ivaApi.ts b/src/web/src/features/fiscal/iva/api/ivaApi.ts new file mode 100644 index 0000000..c7a3ea9 --- /dev/null +++ b/src/web/src/features/fiscal/iva/api/ivaApi.ts @@ -0,0 +1,68 @@ +// ADM-009 — API client tipado para fiscal/iva +import { axiosClient } from '@/api/axiosClient' +import type { + TipoDeIva, + CreateTipoDeIvaRequest, + UpdateTipoDeIvaRequest, + NuevaVersionTipoDeIvaRequest, + NuevaVersionResponse, + HistorialCadenaEntry, + TipoDeIvaFilter, + PagedResponse, +} from '../types/tipoDeIva.types' + +const BASE = '/api/v1/admin/fiscal/iva' + +export async function listTiposDeIva( + params: TipoDeIvaFilter, +): Promise> { + const p = new URLSearchParams() + if (params.page !== undefined) p.set('page', String(params.page)) + if (params.pageSize !== undefined) p.set('pageSize', String(params.pageSize)) + if (params.codigo !== undefined) p.set('codigo', params.codigo) + if (params.activo !== undefined) p.set('activo', String(params.activo)) + + const res = await axiosClient.get>(BASE, { params: p }) + return res.data +} + +export async function getTipoDeIvaById(id: number): Promise { + const res = await axiosClient.get(`${BASE}/${id}`) + return res.data +} + +export async function getHistorialTipoDeIva(id: number): Promise { + const res = await axiosClient.get(`${BASE}/${id}/historial`) + return res.data +} + +export async function createTipoDeIva(body: CreateTipoDeIvaRequest): Promise { + const res = await axiosClient.post(BASE, body) + return res.data +} + +export async function updateTipoDeIva( + id: number, + body: UpdateTipoDeIvaRequest, +): Promise { + const res = await axiosClient.patch(`${BASE}/${id}`, body) + return res.data +} + +export async function nuevaVersionTipoDeIva( + id: number, + body: NuevaVersionTipoDeIvaRequest, +): Promise { + const res = await axiosClient.post(`${BASE}/${id}/nueva-version`, body) + return res.data +} + +export async function deactivateTipoDeIva(id: number): Promise { + const res = await axiosClient.post(`${BASE}/${id}/deactivate`) + return res.data +} + +export async function reactivateTipoDeIva(id: number): Promise { + const res = await axiosClient.post(`${BASE}/${id}/reactivate`) + return res.data +} diff --git a/src/web/src/features/fiscal/iva/types/tipoDeIva.types.ts b/src/web/src/features/fiscal/iva/types/tipoDeIva.types.ts new file mode 100644 index 0000000..d73175f --- /dev/null +++ b/src/web/src/features/fiscal/iva/types/tipoDeIva.types.ts @@ -0,0 +1,74 @@ +// ADM-009 — Tipos TS para feature fiscal/iva +// Alineados con TipoDeIvaDto / FiscalContracts.cs del backend + +export interface TipoDeIva { + id: number + codigo: string + descripcion: string + porcentaje: number + vigenciaDesde: string // ISO date "yyyy-MM-dd" + vigenciaHasta: string | null + activo: boolean + aplicaIVA: boolean + predecesorId: number | null +} + +export interface CreateTipoDeIvaRequest { + codigo: string + descripcion: string + porcentaje: number + vigenciaDesde: string + aplicaIVA: boolean +} + +// UpdateTipoDeIvaRequest — SIN porcentaje (inmutable, usar NuevaVersion para cambiar) +export interface UpdateTipoDeIvaRequest { + codigo: string + descripcion: string + aplicaIVA: boolean + activo: boolean +} + +export interface NuevaVersionTipoDeIvaRequest { + porcentaje: number + vigenciaDesde: string // "yyyy-MM-dd" +} + +export interface NuevaVersionResponse { + predecesorId: number + nuevaId: number + nuevoPorcentaje: number + vigenciaDesde: string + predecesorVigenciaHasta: string +} + +export interface HistorialCadenaEntry { + id: number + codigo: string + porcentaje: number + vigenciaDesde: string + vigenciaHasta: string | null + activo: boolean + predecesorId: number | null + depth: number +} + +export interface TipoDeIvaFilter { + page?: number + pageSize?: number + codigo?: string + activo?: boolean +} + +export interface PagedResponse { + items: T[] + page: number + pageSize: number + total: number +} + +// ApiError — contrato unificado { error, message } de ADM-008/ADM-009 +export interface ApiError { + error: string + message: string +}