feat(web): lotes y series en las líneas de entradas, salidas y transferencias de stock

Una ventana por línea con tabla editable; validación de suma de lotes y una serie por unidad.
Probado contra SBODemoCL: entrada de inventario 156 con SU01 y su lote.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
GeorgeandClaude Sonnet 5.5 committed 2026-10-16 12:25:01 -05:00
1 parent a5592fac76
commit abc1cc4ac6
16 files changed
+752 -10

No files matched your search

@@ -32,6 +32,7 @@ import { type ComputedSource, type HeaderField, PARTNER_COLUMNS, WAREHOUSE_LOOKU
import { type CopyOrigin, copyFromDocument, copySources, copyTargets } from './document-copy';
import { DOCUMENT_SCREENS, type DocumentScreen, docNum, documentStatus, menuLabel } from './document-screens';
import { OBJECT_TYPES } from './document-objects';
import { detailHint, validateLineDetails } from './line-details';
import { ITEMS_MULTI_ADD } from './line-columns';
const today = (): string => new Date().toISOString().slice(0, 10);
@@ -316,6 +317,7 @@ export class DocumentFormPage {
private readonly itemColumn = this.layout.columns.find((c) => c.key === 'ItemCode') ?? this.layout.columns[0];
protected readonly newLine = () => this.layout.newLine(this.header());
/** Recalcula la línea con la tasa de cada impuesto (precio con y sin impuesto, total). */
protected readonly detailHint = detailHint;
protected readonly recalc = this.layout.recalc ? (line: GridLine, key: string) => this.layout.recalc!(line, key, this.rates()) : undefined;
protected readonly multi: GridMultiAdd = {
...ITEMS_MULTI_ADD,
@@ -411,6 +413,7 @@ export class DocumentFormPage {
protected async save(): Promise<void> {
if (this.saving() || this.readOnly()) return;
const errors = validateLayout(this.header(), this.lines(), requiredHeaderOf(this.layout), this.layout.requiredLine);
if (this.layout.details?.length) errors.push(...validateLineDetails(this.lines()));
if (this.hasFolio && !/^\d*$/.test(text(this.header()['FolioNumber']).trim())) errors.push('El número de folio debe ser numérico.');
if (errors.length) {
this.message.set({ kind: 'err', text: errors[0] });