feat(tagumedica): la serie por defecto de SAP queda elegida en las solicitudes de inmovilizar y liberar

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
GeorgeandClaude Sonnet 5.5 committed 2026-10-20 15:57:34 -05:00
1 parent 3eb3269561
commit 0d49129bcd
5 files changed
+22 -5

No files matched your search

@@ -43,6 +43,7 @@ describe('LoteTransferPage', () => {
await tick();
// catálogos de la solicitud (campos de usuario de SAP) y series
for (const alias of Object.keys(FIELDS)) ctrl.expectOne(`/api/sapdb/user-fields/OWTQ/${alias}`).flush(FIELDS[alias]);
ctrl.expectOne('/api/sl/SeriesService_GetDefaultSeries').flush({ Series: 7 });
ctrl.expectOne('/api/sl/SeriesService_GetDocumentSeries').flush({ value: [{ Series: 7, Name: 'TR-01', Locked: 'tNO' }, { Series: 8, Name: 'OLD', Locked: 'tYES' }] });
await tick();
}
@@ -71,6 +72,12 @@ describe('LoteTransferPage', () => {
expect(rowOf('302').textContent).toContain('Ya inmovilizado');
});
it('deja elegida la serie por defecto de SAP', async () => {
await search('2090456');
expect(page().form().series).toBe(7);
expect((el().querySelector('sbo-select-field select') as HTMLSelectElement).selectedOptions[0]?.textContent?.trim()).toBe('TR-01');
});
it('al marcar un almacén se precarga todo el stock y no se puede superar', async () => {
await search('2090456');
check('201');
@@ -109,7 +116,8 @@ describe('LoteTransferPage', () => {
{ ItemCode: 'A1', Quantity: 2, WarehouseCode: '302', FromWarehouseCode: '202', BatchNumbers: [{ BatchNumber: '2090456', Quantity: 2 }] },
],
});
expect(req.request.body).not.toHaveProperty('Series');
// la serie por defecto de SAP viaja elegida
expect(req.request.body).toHaveProperty('Series', 7);
req.flush({ DocEntry: 480, DocNum: 4123 });
await tick();
// vuelve a la búsqueda con el aviso de éxito
@@ -177,7 +177,7 @@ export class LoteTransferPage {
if (!rows.length) throw new Error(`No se encontró stock para el lote «${lot}»`);
if (this.config.pickFrom && !rows.some((r) => r.WarehouseCode === this.fromWarehouse())) throw new Error(`El lote «${lot}» no tiene stock en el almacén ${this.fromWarehouse()}`);
this.result.set({ lot, rows });
this.form.set(initialForm(this.config, todayIso()));
this.form.set(initialForm(this.config, todayIso(), this.defaultSeries.value() ?? null));
this.message.set(null);
} catch (e) {
this.message.set({ kind: 'err', text: e instanceof Error && !('status' in e) ? e.message : apiErrorMessage(e) });
@@ -226,6 +226,8 @@ export class LoteTransferPage {
protected readonly catalogs = resource({ loader: () => this.api.catalogs() });
protected readonly options = computed(() => this.catalogs.value() ?? { movimientoInventario: [], tipoOperacion: [], tipoDespacho: [], movimientoAlmacen: [] });
protected readonly series = resource({ loader: () => this.api.series().catch(() => []) });
/** La serie por defecto de SAP: queda elegida al buscar el lote (se puede cambiar o dejar en blanco). */
private readonly defaultSeries = resource({ loader: () => this.api.defaultSeries().catch(() => null) });
protected readonly problems = computed(() => {
const f = this.form();
@@ -70,6 +70,12 @@ export class LotesFlujoApi {
return res.value.filter((r) => r['Locked'] !== 'tYES').map((r) => ({ value: Number(r['Series']), label: String(r['Name'] ?? r['Series']) }));
}
/** La serie que SAP usa por defecto para las solicitudes de traslado, o `null` si no se pudo saber. */
async defaultSeries(): Promise<number | null> {
const res = await firstValueFrom(this.http.post<{ Series?: number }>(`${API_URL}/sl/SeriesService_GetDefaultSeries`, { DocumentTypeParams: { Document: OBJECT_TYPE } }));
return typeof res.Series === 'number' ? res.Series : null;
}
create(body: Row): Promise<Row> {
return this.master.create(RESOURCE, body);
}
@@ -49,6 +49,7 @@ describe('solicitud de inmovilización', () => {
it('parte de los valores por defecto del flujo', () => {
expect(initialForm(cfg, '2026-10-20')).toMatchObject({ toWarehouse: '302', movimientoAlmacen: '107', movimientoInventario: 'XTD', tipoOperacion: '11', tipoDespacho: 'N', series: null });
expect(initialForm(LOT_FLOWS.liberar, '2026-10-20')).toMatchObject({ toWarehouse: '201', movimientoAlmacen: '108' });
expect(initialForm(cfg, '2026-10-20', 7).series).toBe(7);
});
it('pide motivo, comentario y acción, al menos un almacén y un destino distinto del origen', () => {
@@ -77,10 +77,10 @@ export interface TransferForm {
accion: string;
}
/** Valores iniciales de la solicitud de un flujo. */
export const initialForm = (config: LotFlowConfig, today: string): TransferForm => ({
/** Valores iniciales de la solicitud de un flujo (`series`: la que SAP usa por defecto, si se conoce). */
export const initialForm = (config: LotFlowConfig, today: string, series: number | null = null): TransferForm => ({
docDate: today,
series: null,
series,
movimientoInventario: DEFAULT_MOVIMIENTO_INVENTARIO,
tipoOperacion: DEFAULT_TIPO_OPERACION,
tipoDespacho: DEFAULT_TIPO_DESPACHO,