feat(web): documentos de ventas y compras con tipo Artículo / Servicio (columnas de línea, validación, guardado y copiado)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
68d2cfe6d0
commit
2e74bccd65
11 files changed
+260
-25
No files matched your search
@@ -198,6 +198,7 @@ describe('DocumentFormPage', () => {
|
||||
const req = ctrl.expectOne((r) => r.method === 'POST' && !r.url.includes('SeriesService'));
|
||||
expect(req.request.url).toBe('/api/sl/Orders');
|
||||
expect(req.request.body).toEqual({
|
||||
DocType: 'dDocument_Items',
|
||||
CardCode: 'C1',
|
||||
DocDate: page().header().DocDate,
|
||||
DocDueDate: page().header().DocDueDate,
|
||||
@@ -209,6 +210,58 @@ describe('DocumentFormPage', () => {
|
||||
expect(navigate).toHaveBeenCalledWith(['..', 99], expect.objectContaining({ state: { created: '1099' } }));
|
||||
});
|
||||
|
||||
describe('tipo Servicio', () => {
|
||||
const headers = () => [...el().querySelectorAll('.lines-head th, table.grid thead th')].map((t) => t.textContent?.trim());
|
||||
|
||||
it('un documento de servicio cambia las columnas: cuenta contable, descripción, impuesto y total, sin artículo ni cantidad', async () => {
|
||||
page().setHeader('DocType', 'dDocument_Service');
|
||||
await tick();
|
||||
const titles = headers();
|
||||
expect(titles).toEqual(expect.arrayContaining(['Cuenta contable', 'Descripción', 'Impuesto', 'Total']));
|
||||
expect(titles).not.toContain('Nº de artículo');
|
||||
expect(titles).not.toContain('Cantidad');
|
||||
});
|
||||
|
||||
it('crea el documento con DocType de servicio y líneas de cuenta y total', async () => {
|
||||
page().setHeader('DocType', 'dDocument_Service');
|
||||
page().setHeader('CardCode', 'P1');
|
||||
page().setLines([{ AccountCode: '_SYS1', ItemDescription: 'Alquiler', TaxCode: 'IGV', LineTotal: 100, ItemCode: '' }]);
|
||||
await tick();
|
||||
(el().querySelector('.actions .btn.main') as HTMLElement).click();
|
||||
await tick();
|
||||
const req = ctrl.expectOne((r) => r.method === 'POST' && !r.url.includes('SeriesService'));
|
||||
expect(req.request.body).toMatchObject({ DocType: 'dDocument_Service', CardCode: 'P1' });
|
||||
expect((req.request.body as { DocumentLines: unknown[] }).DocumentLines).toEqual([{ AccountCode: '_SYS1', ItemDescription: 'Alquiler', TaxCode: 'IGV', LineTotal: 100 }]);
|
||||
req.flush({ DocEntry: 7, DocNum: 1007 });
|
||||
await tick();
|
||||
});
|
||||
|
||||
it('exige cuenta contable y un total mayor que cero', async () => {
|
||||
page().setHeader('DocType', 'dDocument_Service');
|
||||
page().setHeader('CardCode', 'P1');
|
||||
page().setLines([{ ItemDescription: 'Sin cuenta', LineTotal: 10 }]);
|
||||
await tick();
|
||||
(el().querySelector('.actions .btn.main') as HTMLElement).click();
|
||||
await tick();
|
||||
ctrl.expectNone((r) => r.method === 'POST' && !r.url.includes('SeriesService'));
|
||||
expect(el().querySelector('.status')!.textContent).toContain('indique la cuenta contable');
|
||||
});
|
||||
|
||||
it('cambiar el tipo con líneas escritas pide permiso y, si se acepta, las descarta', async () => {
|
||||
page().setLines([{ ItemCode: 'A1', Quantity: 1, Price: 50, LineTotal: 50 }]);
|
||||
await tick();
|
||||
page().setHeader('DocType', 'dDocument_Service');
|
||||
await tick();
|
||||
expect(el().querySelector('.ask')!.textContent).toContain('descarta la línea escrita');
|
||||
expect(page().header().DocType).toBe('dDocument_Items'); // todavía no cambió
|
||||
(el().querySelector('.ask .btn.main') as HTMLElement).click();
|
||||
await tick();
|
||||
expect(page().header().DocType).toBe('dDocument_Service');
|
||||
expect(page().lines()).toEqual([]);
|
||||
expect(el().querySelector('.ask')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
it('muestra el error de SAP si rechaza el documento', async () => {
|
||||
page().setHeader('CardCode', 'C1');
|
||||
page().setLines([{ ItemCode: 'A1', Quantity: 1, Price: 50, LineTotal: 50 }]);
|
||||
|
||||
Reference in new issue
Block a user