import { type LineItem } from './line-items'; import type { Allocation, AllocationIssue, OpenDocument } from '../primitives/allocation'; import type { ActionFieldDef, DocumentFormLines, DocumentFormSource, DocumentFormOpenDocuments, DocumentFormsManifest, DocumentFormType } from '../types'; export declare const EXTENSION_PREFIX = "fiscal_data."; export type EditorLinesConfig = DocumentFormLines & { field: string; }; /** true si el tipo se abre en el DocumentEditor (`layout: "editor"`). */ export declare function isEditorLayout(type: Pick | null | undefined): boolean; /** Paso de renglones efectivo del tipo (o undefined si no tiene). */ export declare function editorLinesConfig(type: DocumentFormType, forms: Pick): EditorLinesConfig | undefined; /** * Divulgación progresiva: ¿el campo va plegado en «Opciones fiscales»? * - campos de extensión (`fiscal_data.*`) que aportan otros addons (los que * el propio tipo declara obligatorios, p. ej. método y forma de pago de la * factura, se marcan esenciales en splitEditorFields); * - `section: "fiscal" | "advanced"`; * - catálogos opcionales que ya traen un default (método, serie, relación…): * el usuario no necesita tocarlos para guardar. * Lo obligatorio sin default, la contraparte y el monto siempre están a la vista. */ export declare function isAdvancedField(f: ActionFieldDef, essentialKeys?: ReadonlySet): boolean; export interface EditorFieldGroups { /** Campo que elige la contraparte (cliente/proveedor), si el tipo la declara. */ party?: ActionFieldDef; /** A la vista: lo esencial del encabezado. */ essential: ActionFieldDef[]; /** Plegados en «Opciones fiscales». */ advanced: ActionFieldDef[]; /** Notas largas (textarea): al final. */ notes: ActionFieldDef[]; } /** Reparte los campos del tipo (más los de extensión) en grupos de pantalla. */ export declare function splitEditorFields(fields: readonly ActionFieldDef[], opts?: { partyField?: string; essentialKeys?: readonly string[]; extensionFields?: readonly ActionFieldDef[]; }): EditorFieldGroups; /** * Etiqueta clara con el código como dato secundario: * `03 · Transferencia electrónica` → `Transferencia electrónica · 03`. * Solo reordena el patrón «CÓDIGO · texto»; cualquier otra etiqueta pasa igual. */ export declare function friendlyOptionLabel(label: string): string; /** El mismo campo con sus opciones en formato «texto · código». */ export declare function withFriendlyOptions(f: ActionFieldDef): ActionFieldDef; /** Opciones del select que aplican con los valores actuales (`options[].when`). */ export declare function gatedOptions(f: ActionFieldDef, values: Record): ActionFieldDef; /** * Selects con opciones condicionadas (`options[].when`, p. ej. forma de pago * «99» solo con método PPD): cuando el valor actual deja de aplicar —o está * vacío y solo queda una opción— devuelve el que toca. Una sola opción * permitida se elige sola; si hay varias, el default del campo si aplica; si * no, vacío. Sin cambios devuelve `{}`, así que aplicarlo converge. */ export declare function gatedOptionFixes(fields: readonly ActionFieldDef[], values: Record): Record; /** * Defaults del encabezado que salen de la contraparte: los campos de extensión * con la MISMA clave en ambos modelos (p. ej. `fiscal_data.uso_cfdi` de Customer * → `fiscal_data.uso_cfdi` del documento) y la moneda. * Solo llena lo que está vacío: nunca pisa lo que el usuario ya capturó. */ export declare function partyDefaults(party: Record | null, documentFieldKeys: readonly string[], current: Record): Record; /** Etiqueta y opciones de catálogo de un campo (de la metadata del modelo o del propio tipo). */ export interface FieldDisplayMeta { label?: string; options?: ReadonlyArray<{ value: unknown; label?: unknown; }>; } /** * Metadata de pantalla por clave a partir de listas de campos/columnas * (`/metadata/modal` → fields, `/metadata/table` → columns, campos del tipo). * La primera lista que trae etiqueta u opciones para una clave gana. */ export declare function fieldDisplayMeta(lists: ReadonlyArray | null | undefined>, translate?: (s: string) => string): Record; /** `tax_id` → «Tax id»: último recurso cuando ningún metadata etiqueta la columna. */ export declare function humanizeKey(key: string): string; /** * Valor de catálogo legible: `G03` con la opción «Gastos en general» → * «G03 · Gastos en general» (si la etiqueta ya trae el código, tal cual). */ export declare function formatOptionValue(value: unknown, options?: FieldDisplayMeta['options']): string; /** * Filas de la tarjeta de contraparte: resumen declarado + extensiones (máximo * `limit`). Etiqueta del campo (metadata / labels declarados, ya traducidos), * valores de catálogo con su texto y nunca claves crudas ni vacíos. */ export declare function partySummaryRows(party: Record | null, summary?: readonly string[], labels?: Record, limit?: number, meta?: Record): Array<{ key: string; label: string; value: string; }>; export interface CreditStatus { limit?: number; balance?: number; overdue?: number; available?: number; holdReason?: string; /** `ok` | `warn` (supera 80 % o hay vencido) | `block` (retenido o sin crédito disponible). */ level: 'ok' | 'warn' | 'block'; } export declare function creditStatus(party: Record | null, cols: { limit?: string; balance?: string; overdue?: string; hold_reason?: string; } | undefined, documentTotal: number): CreditStatus | null; /** * Renglones de un documento origen → LineItem. `map` traduce nombres * (`description: product_name`, `discount: discount_pct`). Si el origen trae * `tax_amount` y `subtotal` pero no la tasa, la deriva. `credit` (NC) topa la * cantidad en lo facturado (o en `max_quantity` si el origen la trae). * * Con `remaining_quantity` (lo sirve el host: cantidad − lo ya facturado o * devuelto) la cantidad sugerida y el tope son lo pendiente y los renglones ya * cubiertos se omiten; un descuento en importe se prorratea a lo pendiente (un * porcentaje no cambia). Cada línea guarda `source_line_id` para el vínculo. */ export declare function linesFromSource(rows: unknown, map?: Record, opts?: { kind?: DocumentFormLines['kind']; discountMode?: DocumentFormLines['discount_mode']; defaultTaxRate?: number; }): LineItem[]; /** El editor ocupa toda la pantalla: documentos comerciales con renglones (factura, cotización, pedido, OC). */ export declare function isFullscreenEditor(type: DocumentFormType, forms: Pick): boolean; /** Cuántos renglones del origen se cargaron y cuántos se omitieron por estar ya cubiertos. */ export declare function sourceLoadSummary(rows: unknown): { loaded: number; covered: number; }; /** Fuente que precarga desde lo pendiente servido por el host (no desde la relación cruda). */ export declare function sourceTracksRemaining(src: Pick): boolean; /** Opción ya resuelta de un selector de la cabecera que el editor llenó por código. */ export interface SeedLabel { value: string; label: string; } /** Nombre visible de un registro: la columna declarada por el campo, luego folio/nombre. */ export declare function recordLabel(rec: Record | null | undefined, preferred?: string): string | undefined; /** * Etiquetas de lo que «Cargar desde…» escribe en la cabecera, para que el * selector muestre el nombre y no el UUID sin abrirse: * - `header` (`customer_id ← customer_id`): el objeto hermano `{value,label}` * que el host sirve junto a la FK (`customer`); * - `link_field`: el propio documento origen, con su folio. */ export declare function sourceHeaderSeeds(src: Pick, rec: Record, id: string, fields?: readonly ActionFieldDef[]): Record; /** * Registro para `renderField` con las etiquetas sembradas como objeto hermano * (`customer_id` → `customer: {value,label}`), el mismo contrato que sirve el * host en una fila. Conserva el registro desde el que se abrió. */ export declare function seedRecord(seeds: Record, record?: Record): Record | undefined; export interface EditorIssue { field?: string; severity: 'error' | 'warning'; message: string; } /** Revisión local (instantánea) de los renglones. Sin ruido: solo lo que hay que mirar. */ export declare function localIssues(lines: LineItem[], opts?: { requireLines?: boolean; requireTax?: boolean; }): EditorIssue[]; /** Documento abierto (fila de /data) → OpenDocument para PaymentAllocator. */ export declare function toOpenDocuments(rows: unknown, cfg: DocumentFormOpenDocuments, currency: string): OpenDocument[]; /** Monto actual de cada documento, para pasar a modo manual sin perder lo repartido. */ export declare function manualFromAllocations(allocations: readonly Allocation[]): Record; /** Renglones del payload: solo los dos campos que declara la acción (`invoice_id`, `amount`). */ export declare function allocationPayload(allocations: readonly Allocation[], cfg: DocumentFormOpenDocuments): Array>; /** * Campo del encabezado con el monto recibido: `amount` si existe; si no, el * primer campo numérico/moneda. Convención documentada (el schema no lo nombra). */ export declare function allocationAmountField(fields: readonly ActionFieldDef[]): string | undefined; /** AllocationIssue → mensaje en español claro (con el número del documento). */ export declare function allocationIssueMessages(issues: readonly AllocationIssue[], docs: readonly OpenDocument[]): EditorIssue[]; /** Días de atraso de un documento abierto (0 si no está vencido o no tiene vencimiento). */ export declare function overdueDays(doc: Pick, today?: Date): number; //# sourceMappingURL=document-editor-model.d.ts.map