/** * Tipos del widget WithholdingsPanel (FEAT-105-11) — sub-componente de * MasterDocument. * * Espejo TypeScript del read-model de retenciones del backend (`WithholdingDto`, * 105-10) más los contratos de props del widget reutilizable. Las retenciones * (TF3, tabla genérica `document_header_withholdings`) son un child genérico de * documento: el mismo panel sirve para compras/ventas/inventario inyectando sus * endpoints e IO por props (precedente: InstallmentsPanel / AdvanceApplicationsPanel). * * @see feat-105-11-panel-retenciones-masterdocument-spec.md */ /** * Acción de la retención sobre el total del documento. * 1=IncreasesTotal · 2=DecreasesTotal · 3=NoActionDocumentTotal · 4=NoActionNoAccounting. * En el PUT solo se admiten 1/2/3 (0 y 4 → 400). */ export type WithholdingAction = 1 | 2 | 3 | 4; /** * Retención (TF3) — espejo de `WithholdingDto` (camelCase). Tabla genérica * `document_header_withholdings`, keyed por `documentId = document_headers.id`. * * Origen de la fila (derivado de `isManual`/`isManipulated`): * - `isManual = true` → creada manualmente por el usuario (POST). * - `isManipulated = true` → automática del motor que el usuario editó (PUT). * - ambos `false` → automática "pura" del motor LEGO-13. * (Restricción DB: nunca ambos `true` a la vez.) */ export interface WithholdingDto { /** PK de la retención. */ id: string; /** FK al documento (header). */ documentId: string; /** Clase de retención (UUID). El nombre legible es opcional (ver GAP-2). */ withholdingClassId: string; /** Clave de retención (UUID). */ withholdingKeyId: string; /** Código denormalizado de la clave (≤20). */ withholdingKeyCode: string; /** Acción sobre el total (1|2|3|4). */ withholdingAction: WithholdingAction; /** Base de cálculo (decimal 18,6). */ baseValue: number; /** Valor retenido (decimal 18,6). */ totalValue: number; /** Centro de operación (UUID) o null si la clave es de regionalidad nacional. */ operationCenterId: string | null; /** Fila creada manualmente. */ isManual: boolean; /** Fila automática editada por el usuario (con `original_*` congelado). */ isManipulated: boolean; /** Retención provisional. */ isProvisional: boolean; /** Autorretención. */ isSelfWithholding: boolean; /** Versión de fila para concurrencia optimista. */ rowVersion: number; /** Auditoría. */ createdByUserId?: string; updatedByUserId?: string; /** Nombre legible de la clase (columna "Clase"). GAP-2: puede no venir. */ withholdingClassName?: string; /** Tasa porcentual de la clave (columna "Tasa"). GAP-2: puede no venir. */ rate?: number | null; /** Base original del motor antes de manipular (tooltip "valor original"). GAP-2. */ originalBaseValue?: number | null; /** Valor original del motor antes de manipular (tooltip "valor original"). GAP-2. */ originalTotalValue?: number | null; } /** * Forma cruda como puede llegar del backend. Booleanos defensivos + acción * tolerante; se normaliza con {@link normalizeWithholding}. */ export interface RawWithholdingDto extends Partial> { id: string; documentId: string; withholdingAction?: number | null; } /** Origen visual de una retención (badge de la columna "Origen"). */ export type WithholdingOrigin = 'manual' | 'manipulated' | 'automatic'; /** Deriva el origen visual de una retención a partir de sus flags. */ export declare function getWithholdingOrigin(w: Pick): WithholdingOrigin; /** Normaliza una retención cruda del backend al DTO de UI. */ export declare function normalizeWithholding(raw: RawWithholdingDto): WithholdingDto; /** * Orden canónico de UI: manuales primero, luego manipuladas, luego automáticas; * dentro de cada grupo por código de clave. Estable y determinista. */ export declare function sortWithholdings(withholdings: WithholdingDto[]): WithholdingDto[]; /** * Payload del POST de creación manual (`CreateWithholdingDto`). * * ⚠ Nomenclatura BE: el create usa `baseAmount` (NO `baseValue`). `withholdingAction` * NO se envía: el backend lo calcula desde una matriz de decisión. */ export interface CreateWithholdingPayload { /** Clase de retención (UUID, requerido). */ withholdingClassId: string; /** Clave de retención (UUID, requerido; debe pertenecer a la clase). */ withholdingKeyId: string; /** Centro de operación (UUID); requerido si la clave es municipal, null si nacional. */ operationCenterId: string | null; /** Base de cálculo (> 0). ⚠ `baseAmount`, no `baseValue`. */ baseAmount: number; /** Valor retenido (> 0). */ totalValue: number; /** Base en moneda alterna (opcional). */ baseAmountAlt?: number | null; /** Valor en moneda alterna (opcional). */ totalValueAlt?: number | null; } /** * Payload del PUT de modificación (`UpdateWithholdingDto`). * * ⚠ Nomenclatura BE: el update usa `baseValue` (NO `baseAmount`). `withholdingAction` * sí se respeta (solo 1/2/3). `rowVersion` requerido (concurrencia). */ export interface ModifyWithholdingPayload { /** Base de cálculo (> 0). */ baseValue: number; /** Valor retenido (> 0). */ totalValue: number; /** Base en moneda alterna (opcional). */ baseValueAlt?: number | null; /** Valor en moneda alterna (opcional). */ totalValueAlt?: number | null; /** Acción sobre el total (1|2|3; 0 y 4 → 400). */ withholdingAction: 1 | 2 | 3; /** Versión de fila requerida (concurrencia optimista). */ rowVersion: number; } /** Resumen del recálculo (`RecalculateSummaryDto`). */ export interface RecalculateSummary { /** Filas preservadas (manuales + manipuladas restauradas). */ preserved: number; /** Filas automáticas regeneradas por el motor. */ recalculated: number; } /** Respuesta del recálculo (`RecalculateWithholdingsResponse`). */ export interface RecalculateWithholdingsResponse { /** Set TF3 completo tras el recálculo. */ withholdings: WithholdingDto[]; summary: RecalculateSummary; } /** * Envelope de las mutaciones de child (ADR-011): POST/PUT devuelven * `{ child, header }`; DELETE devuelve `{ header }`. El `header` es el * `DocumentHeaderDto` (totales recalculados); el widget no lo tipa fuerte. */ export interface WithholdingChildEnvelope { child: RawWithholdingDto; header?: unknown; } export interface WithholdingDeleteEnvelope { header?: unknown; } /** * Cliente HTTP inyectado para las operaciones REST del widget. * * El kit no depende de `axios`; el documento consumidor inyecta su instancia ya * configurada (interceptores de auth/company) envuelta en esta firma. Debe * rechazar con un error que exponga `status` (número HTTP) para que el widget * distinga 409 (conflicto/duplicado) / 422 (negocio) / 403 (sin permiso). */ export type WithholdingsHttpRequest = (method: 'GET' | 'POST' | 'PUT' | 'DELETE', url: string, body?: unknown) => Promise; /** Error normalizado que el widget interpreta para el manejo de UI. */ export interface WithholdingsHttpError extends Error { status?: number; /** `ProblemDetails.detail` ya traducido por `Accept-Language` (si llega). */ detail?: string; } /** Opción de clase de retención para el `Select` del modal Agregar. */ export interface WithholdingClassOption { id: string; name: string; } /** Regionalidad de la clave: determina si el centro de operación es requerido. */ export type WithholdingKeyRegionality = 'national' | 'municipal'; /** Opción de clave de retención (filtrada por clase) para el modal Agregar. */ export interface WithholdingKeyOption { id: string; code: string; name: string; /** Tasa porcentual (informativa). */ percentRate?: number | null; /** Si es municipal, el centro de operación es obligatorio. @default 'national' */ regionality?: WithholdingKeyRegionality; } /** Opción de centro de operación para el modal Agregar. */ export interface WithholdingOperationCenterOption { id: string; name: string; } /** * Loaders de catálogo inyectados (decoplan el widget del transporte/rutas * concretas, que son específicos del host). Si se omite `catalogs`, el botón * "Agregar" no se muestra (Modificar/Eliminar/Recalcular siguen disponibles). */ export interface WithholdingsCatalogs { /** Lista de clases de retención disponibles. */ loadClasses: () => Promise; /** Lista de claves de la clase seleccionada. */ loadKeys: (classId: string) => Promise; /** Lista de centros de operación (solo si alguna clave es municipal). */ loadOperationCenters?: () => Promise; } /** * Props del panel principal `WithholdingsPanel`. * * El widget es agnóstico del documento: recibe sus endpoints e IO por props, * lo que permite montarlo en cualquier MasterDocument (compras/ventas/inventario). */ export interface WithholdingsPanelProps { /** UUID del documento (PK de `document_headers.id`), no el número legible. */ documentId: string; /** * `true` solo cuando el documento es editable (DRAFT). Cuando es `false`, la * grilla es read-only y la barra de acciones se elimina del DOM. */ isEditable: boolean; /** * `true` si el usuario tiene permiso de escritura de TF3 * (`commercial.core.withholdings.write`). Gatea Agregar/Modificar/Eliminar. */ canWrite: boolean; /** * `true` si el usuario tiene permiso de recálculo * (`commercial.core.supplier-invoices.modify_withholdings`). Gatea Recalcular. */ canRecalculate: boolean; /** * Endpoint GET para cargar la lista TF3 (BRECHA G1/GAP-1 — el BE aún la expone * como stub 501). Si se omite, la grilla solo se puebla con `initialWithholdings` * y con las respuestas de las mutaciones. */ withholdingsEndpoint?: string; /** * Endpoint base de child: `/{id}/withholdings`. El widget añade `/{childId}` * para PUT/DELETE y `/recalculate` para el recálculo. POST va a la base. */ withholdingsBaseEndpoint: string; /** Cliente HTTP inyectado para las operaciones REST. */ httpRequest: WithholdingsHttpRequest; /** Loaders de catálogo para el modal Agregar (opcional — ver {@link WithholdingsCatalogs}). */ catalogs?: WithholdingsCatalogs; /** * Datos iniciales (opcional). Útil cuando la carga proviene de la sección * FactBox (`dataSource: 'adapter'`) en vez de un GET dedicado. */ initialWithholdings?: WithholdingDto[]; /** Formateador de montos. @default `formatAmount` de `useMasterDocumentFormatters` (idioma activo, 2 decimales). */ formatAmount?: (value: number) => string; /** Clases CSS adicionales para el contenedor raíz. */ className?: string; } //# sourceMappingURL=types.d.ts.map