feat(api): proxy del Service Layer con registro de recursos
El frontend envía parámetros OData y cuerpo; el backend valida y ejecuta. - GET lista/por clave, POST y PATCH sobre /api/sl/:recurso, solo para recursos registrados (ventas, compras, inventario y maestros estándar); EmployeesInfo no se registra nunca (contiene U_WEB_PASS). - Permisos de menú por recurso (lectura/escritura); catálogos de consulta abiertos a cualquier sesión. Evaluador de patrones compartible (/inventario/* ya no habilita /inventario-x). - Parámetros OData validados con lista cerrada, $top máx. 500, $expand solo si el recurso lo declara, claves validadas y escapadas por tipo, cabeceras B1S-* con lista blanca. $inlinecount y B1S-PageSize automáticos. - configureApp() compartido entre main.ts y e2e (prefijo y límite de 5 mb). - Verificado contra SAP real: los 27 recursos existen; listado con total, filtro, paginación y claves. InventoryRequests no existe en el SL: se registra InventoryTransferRequests. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
73fffee2f7
commit
c0990ca83e
15 files changed
+683
-6
No files matched your search
@@ -0,0 +1,63 @@
|
||||
import { Body, Controller, Get, Headers, HttpCode, Param, Patch, Post, Query, Req } from '@nestjs/common';
|
||||
import type { AuthenticatedRequest } from '../auth/auth.types.js';
|
||||
import { ZodValidationPipe } from '../common/zod-validation.pipe.js';
|
||||
import {
|
||||
type GetQuery,
|
||||
type ListQuery,
|
||||
bodySchema,
|
||||
getQuerySchema,
|
||||
listQuerySchema,
|
||||
pickSlHeaders,
|
||||
} from './sl-request.js';
|
||||
import { SlProxyService } from './sl-proxy.service.js';
|
||||
|
||||
type Body = Record<string, unknown>;
|
||||
type IncomingHeaders = Record<string, string | string[] | undefined>;
|
||||
|
||||
/** Proxy del Service Layer: `/api/sl/<Recurso>[/<clave>]` con parámetros OData del frontend. */
|
||||
@Controller('sl')
|
||||
export class SlProxyController {
|
||||
constructor(private readonly proxy: SlProxyService) {}
|
||||
|
||||
@Get(':resource')
|
||||
list(
|
||||
@Req() req: AuthenticatedRequest,
|
||||
@Param('resource') resource: string,
|
||||
@Query(new ZodValidationPipe(listQuerySchema)) query: ListQuery,
|
||||
@Headers() headers: IncomingHeaders,
|
||||
) {
|
||||
return this.proxy.list(req.user, resource, query, pickSlHeaders(headers, 'GET'));
|
||||
}
|
||||
|
||||
@Get(':resource/:key')
|
||||
get(
|
||||
@Req() req: AuthenticatedRequest,
|
||||
@Param('resource') resource: string,
|
||||
@Param('key') key: string,
|
||||
@Query(new ZodValidationPipe(getQuerySchema)) query: GetQuery,
|
||||
) {
|
||||
return this.proxy.get(req.user, resource, key, query);
|
||||
}
|
||||
|
||||
@Post(':resource')
|
||||
create(
|
||||
@Req() req: AuthenticatedRequest,
|
||||
@Param('resource') resource: string,
|
||||
@Body(new ZodValidationPipe(bodySchema)) body: Body,
|
||||
@Headers() headers: IncomingHeaders,
|
||||
) {
|
||||
return this.proxy.create(req.user, resource, body, pickSlHeaders(headers, 'POST'));
|
||||
}
|
||||
|
||||
@Patch(':resource/:key')
|
||||
@HttpCode(204)
|
||||
async update(
|
||||
@Req() req: AuthenticatedRequest,
|
||||
@Param('resource') resource: string,
|
||||
@Param('key') key: string,
|
||||
@Body(new ZodValidationPipe(bodySchema)) body: Body,
|
||||
@Headers() headers: IncomingHeaders,
|
||||
): Promise<void> {
|
||||
await this.proxy.update(req.user, resource, key, body, pickSlHeaders(headers, 'PATCH'));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user