feat(web): cada documento de ventas y compras puede elegir sus columnas de línea y su cabecera

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
GeorgeandClaude Sonnet 5.5 committed 2026-10-14 15:16:22 -05:00
1 parent c5368c7ad0
commit 1f212e2b30
5 files changed
+91 -14

No files matched your search

@@ -1,7 +1,7 @@
import type { GridColumn, GridLine } from '../../shared/grid/grid.types';
import type { VhLookup } from '../../shared/value-help/value-help.types';
import type { DocRecord, LinesSpec } from './document-model';
import { DOCUMENT_LINE_COLUMNS, lineColumnsFor, newDocumentLine, recalcLine, uomEntryOf } from './line-columns';
import { DOCUMENT_LINE_COLUMNS, lineColumnsFor, lineFieldsOf, newDocumentLine, recalcLine, uomEntryOf } from './line-columns';
/** Valores calculados o del socio que una fila de solo lectura puede mostrar. */
export type ComputedSource = 'docNum' | 'partnerName' | 'partnerTaxId' | 'subtotal' | 'tax' | 'total';
@@ -95,18 +95,24 @@ export const blankLine = (): GridLine => ({ ItemCode: '', ItemDescription: '', Q
/**
* Ventas y compras: socio, referencia, fechas; líneas con precio, descuento e impuesto; pie con
* comentarios, descuento y totales. `left` y `right` son los campos que esa pantalla agrega a la
* cabecera (por ejemplo `FIELDS.folio` en las facturas); sin ellos, la cabecera base.
* comentarios, descuento y totales. Es el punto de partida; cada pantalla ajusta lo suyo:
* - `left` y `right` agregan campos a la cabecera base (por ejemplo `FIELDS.folio` en las facturas);
* - `header` la reemplaza por completo;
* - `lineColumns` reemplaza las columnas de línea (elegidas de `LINE_COLUMNS`); lo que se envía a SAP
* por línea se deduce de ellas.
*/
export function marketingLayout(opts: {
partnerLabel: string;
taxResource: string;
left?: readonly HeaderField[];
right?: readonly HeaderField[];
header?: FieldColumns;
lineColumns?: readonly GridColumn[];
}): DocumentLayout {
const columns = lineColumnsFor(opts.taxResource, opts.lineColumns);
return {
lines: { key: 'DocumentLines', fields: ['ItemCode', 'ItemDescription', 'Quantity', 'WarehouseCode', 'Price', 'DiscountPercent', 'TaxCode'], base: true },
header: {
lines: { key: 'DocumentLines', fields: lineFieldsOf(columns), base: true },
header: opts.header ?? {
left: [
{ type: 'partner', key: 'CardCode', label: opts.partnerLabel, required: true, missing: `el ${opts.partnerLabel.toLowerCase()}` },
{ type: 'computed', label: 'Nombre', source: 'partnerName' },
@@ -125,7 +131,7 @@ export function marketingLayout(opts: {
{ type: 'computed', label: 'Total del documento', source: 'total' },
],
},
columns: lineColumnsFor(opts.taxResource),
columns,
newHeader: () => ({ DocDate: today(), DocDueDate: today(), DiscountPercent: 0 }),
newLine: newDocumentLine,
recalc: recalcLine,