import type { ProductVariant } from './product-search'; export type LineItemKind = 'item' | 'section' | 'note'; export interface LineItem { /** Clave estable de UI (no se envía al backend). */ key: string; kind: LineItemKind; /** Id del producto/variante en el catálogo (kind=item). */ product_id?: string; sku?: string; description: string; quantity: number; unit_price: number; /** * Descuento. Porcentaje 0-100 salvo `discount_kind: 'amount'`, donde es importe. */ discount: number; /** `percent` (default, se omite al serializar) o `amount`. */ discount_kind?: 'percent' | 'amount'; /** Tasa de impuesto como fracción (0.16). Viene de la config fiscal de la org. */ tax_rate: number; /** Unidad de medida (pza, juego…). Solo se serializa si viene informada. */ unit?: string; /** Precio o costo de catálogo, para mostrarlo junto al precio editado. */ catalog_price?: number; /** Costo conocido. Aviso si el precio de venta queda por debajo. No se serializa. */ cost?: number; /** Tope de cantidad (NC: facturado − acreditado; devolución: vendido − devuelto). */ max_quantity?: number; /** * Id del renglón del documento origen («crear desde»). Viaja en la columna * `line_link_field` de la fuente para que el servidor descuente y valide lo * pendiente; un renglón libre no lo lleva. */ source_line_id?: string; technician_id?: string; lot?: string; dot?: string; /** Existencia disponible conocida (para la política de sobreventa). */ available?: number; /** * Campos de extensión del renglón que aportan OTROS addons (p. ej. * fiscal_mexico: `mx_clave_prod_serv`, `mx_clave_unidad`), copiados del * producto al elegirlo. Viajan en `fiscal_data` (la bolsa de ModelExtension * del host) — el SDK no conoce sus claves. */ extensions?: Record; /** * Valores que el catálogo escribió en el renglón la última vez que se * aplicó el producto (elegirlo, crearlo o editarlo desde la celda). Un campo * cuyo valor actual difiere de su foto es un override del usuario («dirty») * y una edición del producto no lo pisa. No se serializa. */ catalog?: LineCatalogSnapshot; /** * Valores nuevos del catálogo que NO se aplicaron porque el usuario ya * había cambiado ese campo a mano: la celda ofrece «aplicar». No se serializa. */ catalog_pending?: Partial>; } /** Campos del renglón que salen del producto y el usuario puede sobrescribir. */ export type CatalogLineField = 'description' | 'sku' | 'unit_price' | 'tax_rate' | 'unit'; export declare const CATALOG_LINE_FIELDS: readonly CatalogLineField[]; /** Foto de lo que el catálogo escribió en el renglón (por campo) y de qué producto/variante. */ export interface LineCatalogSnapshot { description?: string; sku?: string; unit_price?: number; tax_rate?: number; unit?: string; /** Id del producto del catálogo (el registro que se edita), aunque el renglón lleve una variante. */ product_ref?: string; /** Variante elegida: al refrescar se vuelve a aplicar la misma. */ variant?: ProductVariant; } /** Qué hacer si `quantity > available`. */ export type StockPolicy = 'allow' | 'warn' | 'block'; export interface LineItemsPolicy { /** Default `warn`. */ stockPolicy?: StockPolicy; /** Permite cantidades/precios negativos (notas de crédito). Default false. */ allowNegative?: boolean; /** Exige al menos un renglón `item`. Default true. */ requireItems?: boolean; /** Permite cantidad 0 (renglón de origen que no se acredita/devuelve). Default false. */ allowZeroQuantity?: boolean; } /** Clave de UI única en el proceso. */ export declare function newLineKey(): string; export declare function makeLine(partial?: Partial): LineItem; export interface LineAmounts { gross: number; discount: number; net: number; tax: number; total: number; } export declare function computeLine(l: Pick & { discount_kind?: LineItem['discount_kind']; }): LineAmounts; export interface LineItemsTotals { subtotal: number; discount: number; tax: number; total: number; /** Suma de cantidades de los renglones `item`. */ units: number; } export declare function computeTotals(lines: LineItem[]): LineItemsTotals; /** Impuesto agrupado por tasa, sumando el impuesto ya redondeado de cada renglón. */ export declare function taxBreakdown(lines: LineItem[]): Array<{ rate: number; base: number; tax: number; }>; export interface LineItemsValidation { /** Errores por celda `"<índice>."` (mismo formato que DynamicLineItems). */ errors: Record; /** Avisos no bloqueantes (sobreventa con política `warn`). */ warnings: Record; /** Error de documento (sin renglones). */ form?: string; valid: boolean; } export declare function validateLineItems(lines: LineItem[], policy?: LineItemsPolicy): LineItemsValidation; /** * Forma que se manda al backend: números reales (nunca `""`), sin claves de UI, * opcionales vacíos omitidos y `position` 1-based conservando el orden. */ export declare function serializeLineItems(lines: LineItem[], opts?: { sourceLineField?: string; }): Array>; /** Inversa de `serializeLineItems`: filas del API → líneas editables (defaults seguros). */ export declare function parseLineItems(rows: unknown): LineItem[]; //# sourceMappingURL=line-items.d.ts.map