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:
1 parent
3eb3269561
commit
0d49129bcd
5 files changed
+22
-5
No files matched your search
@@ -43,6 +43,7 @@ describe('LoteTransferPage', () => {
|
|||||||
await tick();
|
await tick();
|
||||||
// catálogos de la solicitud (campos de usuario de SAP) y series
|
// 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]);
|
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' }] });
|
ctrl.expectOne('/api/sl/SeriesService_GetDocumentSeries').flush({ value: [{ Series: 7, Name: 'TR-01', Locked: 'tNO' }, { Series: 8, Name: 'OLD', Locked: 'tYES' }] });
|
||||||
await tick();
|
await tick();
|
||||||
}
|
}
|
||||||
@@ -71,6 +72,12 @@ describe('LoteTransferPage', () => {
|
|||||||
expect(rowOf('302').textContent).toContain('Ya inmovilizado');
|
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 () => {
|
it('al marcar un almacén se precarga todo el stock y no se puede superar', async () => {
|
||||||
await search('2090456');
|
await search('2090456');
|
||||||
check('201');
|
check('201');
|
||||||
@@ -109,7 +116,8 @@ describe('LoteTransferPage', () => {
|
|||||||
{ ItemCode: 'A1', Quantity: 2, WarehouseCode: '302', FromWarehouseCode: '202', BatchNumbers: [{ BatchNumber: '2090456', Quantity: 2 }] },
|
{ 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 });
|
req.flush({ DocEntry: 480, DocNum: 4123 });
|
||||||
await tick();
|
await tick();
|
||||||
// vuelve a la búsqueda con el aviso de éxito
|
// 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 (!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()}`);
|
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.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);
|
this.message.set(null);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.message.set({ kind: 'err', text: e instanceof Error && !('status' in e) ? e.message : apiErrorMessage(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 catalogs = resource({ loader: () => this.api.catalogs() });
|
||||||
protected readonly options = computed(() => this.catalogs.value() ?? { movimientoInventario: [], tipoOperacion: [], tipoDespacho: [], movimientoAlmacen: [] });
|
protected readonly options = computed(() => this.catalogs.value() ?? { movimientoInventario: [], tipoOperacion: [], tipoDespacho: [], movimientoAlmacen: [] });
|
||||||
protected readonly series = resource({ loader: () => this.api.series().catch(() => []) });
|
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(() => {
|
protected readonly problems = computed(() => {
|
||||||
const f = this.form();
|
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']) }));
|
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> {
|
create(body: Row): Promise<Row> {
|
||||||
return this.master.create(RESOURCE, body);
|
return this.master.create(RESOURCE, body);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ describe('solicitud de inmovilización', () => {
|
|||||||
it('parte de los valores por defecto del flujo', () => {
|
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(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(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', () => {
|
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;
|
accion: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Valores iniciales de la solicitud de un flujo. */
|
/** 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): TransferForm => ({
|
export const initialForm = (config: LotFlowConfig, today: string, series: number | null = null): TransferForm => ({
|
||||||
docDate: today,
|
docDate: today,
|
||||||
series: null,
|
series,
|
||||||
movimientoInventario: DEFAULT_MOVIMIENTO_INVENTARIO,
|
movimientoInventario: DEFAULT_MOVIMIENTO_INVENTARIO,
|
||||||
tipoOperacion: DEFAULT_TIPO_OPERACION,
|
tipoOperacion: DEFAULT_TIPO_OPERACION,
|
||||||
tipoDespacho: DEFAULT_TIPO_DESPACHO,
|
tipoDespacho: DEFAULT_TIPO_DESPACHO,
|
||||||
|
|||||||
Reference in new issue
Block a user