feat: módulo Finanzas (plan de cuentas y asientos contables con cancelación)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
GeorgeandClaude Sonnet 5.5 committed 2026-10-16 14:36:24 -05:00
1 parent c9d1a714c9
commit 8bbd05d07b
23 files changed
+708 -29

No files matched your search

@@ -27,12 +27,12 @@ export type HeaderField =
| { type: 'date'; key: string; label: string; required?: boolean; missing?: string }
| { type: 'number'; key: string; label: string; decimals?: number; readonly?: boolean }
/** Casilla: en SAP un campo `tYES` / `tNO`. */
| { type: 'checkbox'; key: string; label: string; readonly?: boolean }
| { type: 'checkbox'; key: string; label: string; readonly?: boolean; immutable?: boolean }
/** Campo de código con su ventana de selección (grupo, moneda, lista de precios…). */
| { type: 'lookup'; key: string; label: string; lookup: VhLookup; required?: boolean; missing?: string }
| { type: 'lookup'; key: string; label: string; lookup: VhLookup; required?: boolean; missing?: string; immutable?: boolean }
| { type: 'textarea'; key: string; label: string }
/** Lista de valores válidos (típico de un campo de usuario con valores válidos en SAP). */
| { type: 'select'; key: string; label: string; options: readonly { value: string | number; label: string }[]; required?: boolean; missing?: string }
| { type: 'select'; key: string; label: string; options: readonly { value: string | number; label: string }[]; required?: boolean; missing?: string; immutable?: boolean }
/** Abre la lista de almacenes. */
| { type: 'warehouse'; key: string; label: string; required?: boolean; missing?: string }
/** Código del socio de negocio (cliente o proveedor) con su lista; solo editable al crear. */
@@ -221,20 +221,18 @@ export function compact(record: DocRecord): DocRecord {
export type NavTarget = 'first' | 'prev' | 'next' | 'last';
/** Consulta de un solo documento para ir al primero / anterior / siguiente / último por `DocEntry`. */
export function navigationQuery(target: NavTarget, docEntry: number | null): { $filter?: string; $orderby: string } {
/** Consulta de un solo documento para ir al primero / anterior / siguiente / último por `DocEntry` (u otra clave numérica). */
export function navigationQuery(target: NavTarget, docEntry: number | null, key = 'DocEntry'): { $filter?: string; $orderby: string } {
const asc = `${key} asc`;
const desc = `${key} desc`;
switch (target) {
case 'first':
return { $orderby: 'DocEntry asc' };
return { $orderby: asc };
case 'last':
return { $orderby: 'DocEntry desc' };
return { $orderby: desc };
case 'prev':
return docEntry === null
? { $orderby: 'DocEntry desc' }
: { $filter: `DocEntry lt ${docEntry}`, $orderby: 'DocEntry desc' };
return docEntry === null ? { $orderby: desc } : { $filter: `${key} lt ${docEntry}`, $orderby: desc };
case 'next':
return docEntry === null
? { $orderby: 'DocEntry asc' }
: { $filter: `DocEntry gt ${docEntry}`, $orderby: 'DocEntry asc' };
return docEntry === null ? { $orderby: asc } : { $filter: `${key} gt ${docEntry}`, $orderby: asc };
}
}