feat(web): lista de documentos con barra de filtros y búsqueda por columna
Cada pantalla de documento del menú abre primero la lista de los últimos documentos; desde ahí se crea uno (/nuevo) o se abre uno (/:docEntry). - sbo-list-view: título, botón de alta, barra de filtros, tabla y paginación (50 por página, más recientes primero). - sbo-filter-bar (como el FilterBar del mini-erp): búsqueda por la columna activa + filtros declarativos text / select (con valor por defecto) / multi (chips + lista de valores) / date (siempre rango [desde – hasta]), con Ir y Limpiar. Ir aplica búsqueda y filtros en una sola consulta. - Búsqueda numérica por igualdad (DocNum eq 314) con aviso si no es número; una columna con texto calculado (format) ya no es buscable por defecto. - Piezas compartidas con sbo-value-help, que se refactoriza sobre ellas: createSlList (estado de búsqueda/paginación), sbo-data-table, sbo-pager, sbo-search-bar. Insignias de estado (tone) y estilos de botón globales. - DOCUMENT_SCREENS: columnas y filtros de 17 documentos (ventas, compras, inventario) según los campos verificados en el Service Layer real (PurchaseRequests no tiene CardCode; StockTransfers no tiene estado). - Rutas generadas desde el registro: lista, nuevo y :docEntry bajo el permiso de la ruta de menú. El formulario es un marcador (paso 9). - Presupuesto: el aviso del bundle inicial sube a 300 kB; httpResource aporta ~18 kB al chunk compartido (278 kB, 78 kB comprimido). - Verificado en Chrome contra SAP real: 49 órdenes abiertas, 314 en total, rango de fechas, chips de monedas, búsqueda por número, navegación y botón atrás, tema oscuro; ofertas (4391), transferencias y entradas. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
68caf401a7
commit
598307960e
36 files changed
+2163
-359
No files matched your search
@@ -0,0 +1,37 @@
|
||||
import { MENU } from '@basic-erp/sap-types';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { routes } from './app.routes';
|
||||
import { permissionGuard } from './core/auth/guards';
|
||||
import { DOCUMENT_SCREENS } from './features/documents/document-screens';
|
||||
|
||||
const shell = routes.find((r) => r.path === '')!;
|
||||
const children = shell.children!;
|
||||
|
||||
describe('rutas', () => {
|
||||
it('cada pantalla del menú tiene su ruta protegida por permiso', () => {
|
||||
for (const item of MENU.flatMap((m) => m.items)) {
|
||||
const route = children.find((r) => r.path === item.path.slice(1));
|
||||
expect(route, item.path).toBeDefined();
|
||||
expect(route?.canActivate, item.path).toContain(permissionGuard);
|
||||
expect(route?.data?.['path'], item.path).toBe(item.path);
|
||||
}
|
||||
});
|
||||
|
||||
it('cada documento ofrece lista, "nuevo" y "ver/editar" bajo la ruta del menú', () => {
|
||||
for (const screen of DOCUMENT_SCREENS) {
|
||||
const route = children.find((r) => r.path === screen.path.slice(1))!;
|
||||
expect(route.children?.map((c) => c.path), screen.path).toEqual(['', 'nuevo', ':docEntry']);
|
||||
expect(route.data?.['screen']).toBe(screen);
|
||||
}
|
||||
});
|
||||
|
||||
it('las pantallas que no son documentos (maestros) siguen como "no disponible"', () => {
|
||||
const route = children.find((r) => r.path === 'socios/clientes')!;
|
||||
expect(route.children).toBeUndefined();
|
||||
expect(route.loadComponent).toBeDefined();
|
||||
});
|
||||
|
||||
it('las rutas desconocidas vuelven al inicio', () => {
|
||||
expect(routes.at(-1)).toMatchObject({ path: '**', redirectTo: '' });
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user