@fiado/api-invoker 4.62.0 → 4.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/index.d.ts +1 -0
- package/bin/index.js +1 -0
- package/bin/loanConfig/api/LoanConfigBusinessApi.d.ts +27 -0
- package/bin/loanConfig/api/LoanConfigBusinessApi.js +52 -0
- package/bin/loanConfig/api/interfaces/ILoanConfigBusinessApi.d.ts +67 -0
- package/bin/loanConfig/api/interfaces/ILoanConfigBusinessApi.js +1 -0
- package/bin/loanConfig/index.d.ts +2 -0
- package/bin/loanConfig/index.js +2 -0
- package/bin/retailOrg/api/RetailOrgBusinessApi.d.ts +1 -0
- package/bin/retailOrg/api/RetailOrgBusinessApi.js +4 -0
- package/bin/retailOrg/api/interfaces/IRetailOrgBusinessApi.d.ts +12 -0
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/loanConfig/api/LoanConfigBusinessApi.ts +55 -0
- package/src/loanConfig/api/interfaces/ILoanConfigBusinessApi.ts +82 -0
- package/src/loanConfig/index.ts +2 -0
- package/src/retailOrg/api/RetailOrgBusinessApi.ts +8 -0
- package/src/retailOrg/api/interfaces/IRetailOrgBusinessApi.ts +16 -0
package/bin/index.d.ts
CHANGED
|
@@ -77,6 +77,7 @@ export * from "./milestone-business/index.js";
|
|
|
77
77
|
export * from "./cognitoBackofficeConnector/index.js";
|
|
78
78
|
export * from "./platformRbac/index.js";
|
|
79
79
|
export * from "./retailOrg/index.js";
|
|
80
|
+
export * from "./loanConfig/index.js";
|
|
80
81
|
export * from "./messages-business/index.js";
|
|
81
82
|
export * from "./totp-security/index.js";
|
|
82
83
|
export * from "./equality-connector/index.js";
|
package/bin/index.js
CHANGED
|
@@ -77,6 +77,7 @@ export * from "./milestone-business/index.js";
|
|
|
77
77
|
export * from "./cognitoBackofficeConnector/index.js";
|
|
78
78
|
export * from "./platformRbac/index.js";
|
|
79
79
|
export * from "./retailOrg/index.js";
|
|
80
|
+
export * from "./loanConfig/index.js";
|
|
80
81
|
export * from "./messages-business/index.js";
|
|
81
82
|
export * from "./totp-security/index.js";
|
|
82
83
|
export * from "./equality-connector/index.js";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { IHttpRequest } from "@fiado/http-client";
|
|
2
|
+
import { StandardResponse } from "@fiado/gateway-adapter";
|
|
3
|
+
import { BulkGetParametersResponse, ParameterKeyRef, ParameterResponse } from "@fiado/type-kit/bin/loanConfig/index.js";
|
|
4
|
+
import { ILoanConfigBusinessApi } from "./interfaces/ILoanConfigBusinessApi.js";
|
|
5
|
+
/**
|
|
6
|
+
* Publisher HTTP del lambda `loan-config-business` (componente 09 SureKeep Fase 1) para sus 3
|
|
7
|
+
* endpoints privados de lectura de parámetros. Contrato y semántica completos →
|
|
8
|
+
* `ILoanConfigBusinessApi` (tenantId obligatorio, cache 5 min del lado del consumer,
|
|
9
|
+
* `StandardResponse` → leer `result.data`).
|
|
10
|
+
*
|
|
11
|
+
* Env var requerida en el consumer: `LOAN_CONFIG_BUSINESS_URL`.
|
|
12
|
+
* El template.yml del consumer la setea con:
|
|
13
|
+
*
|
|
14
|
+
* LOAN_CONFIG_BUSINESS_URL: '{{resolve:ssm:loan-config-business}}'
|
|
15
|
+
*
|
|
16
|
+
* Convención CLAUDE.md global: SSM key = nombre del lambda owner de la URL.
|
|
17
|
+
*/
|
|
18
|
+
export default class LoanConfigBusinessApi implements ILoanConfigBusinessApi {
|
|
19
|
+
private httpRequest;
|
|
20
|
+
private readonly baseUrl;
|
|
21
|
+
constructor(httpRequest: IHttpRequest);
|
|
22
|
+
getParameter(paramType: string, key: string, tenantId: string): Promise<StandardResponse<ParameterResponse>>;
|
|
23
|
+
getParametersByType(paramType: string, tenantId: string): Promise<StandardResponse<{
|
|
24
|
+
parameters: ParameterResponse[];
|
|
25
|
+
}>>;
|
|
26
|
+
bulkGetParameters(items: ParameterKeyRef[], tenantId: string): Promise<StandardResponse<BulkGetParametersResponse>>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { inject, injectable } from "inversify";
|
|
14
|
+
/**
|
|
15
|
+
* Publisher HTTP del lambda `loan-config-business` (componente 09 SureKeep Fase 1) para sus 3
|
|
16
|
+
* endpoints privados de lectura de parámetros. Contrato y semántica completos →
|
|
17
|
+
* `ILoanConfigBusinessApi` (tenantId obligatorio, cache 5 min del lado del consumer,
|
|
18
|
+
* `StandardResponse` → leer `result.data`).
|
|
19
|
+
*
|
|
20
|
+
* Env var requerida en el consumer: `LOAN_CONFIG_BUSINESS_URL`.
|
|
21
|
+
* El template.yml del consumer la setea con:
|
|
22
|
+
*
|
|
23
|
+
* LOAN_CONFIG_BUSINESS_URL: '{{resolve:ssm:loan-config-business}}'
|
|
24
|
+
*
|
|
25
|
+
* Convención CLAUDE.md global: SSM key = nombre del lambda owner de la URL.
|
|
26
|
+
*/
|
|
27
|
+
let LoanConfigBusinessApi = class LoanConfigBusinessApi {
|
|
28
|
+
httpRequest;
|
|
29
|
+
// El buildspec publica la URL en SSM con "/" final — se normaliza para no armar "//private".
|
|
30
|
+
baseUrl = (process.env.LOAN_CONFIG_BUSINESS_URL || "").replace(/\/+$/, "");
|
|
31
|
+
constructor(httpRequest) {
|
|
32
|
+
this.httpRequest = httpRequest;
|
|
33
|
+
}
|
|
34
|
+
async getParameter(paramType, key, tenantId) {
|
|
35
|
+
const url = `${this.baseUrl}/private/parameters/${encodeURIComponent(paramType)}/${encodeURIComponent(key)}?tenantId=${encodeURIComponent(tenantId)}`;
|
|
36
|
+
return await this.httpRequest.get(url);
|
|
37
|
+
}
|
|
38
|
+
async getParametersByType(paramType, tenantId) {
|
|
39
|
+
const url = `${this.baseUrl}/private/parameters/by-type/${encodeURIComponent(paramType)}?tenantId=${encodeURIComponent(tenantId)}`;
|
|
40
|
+
return await this.httpRequest.get(url);
|
|
41
|
+
}
|
|
42
|
+
async bulkGetParameters(items, tenantId) {
|
|
43
|
+
const url = `${this.baseUrl}/private/parameters/bulk-get?tenantId=${encodeURIComponent(tenantId)}`;
|
|
44
|
+
return await this.httpRequest.post(url, { items });
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
LoanConfigBusinessApi = __decorate([
|
|
48
|
+
injectable(),
|
|
49
|
+
__param(0, inject("IHttpRequest")),
|
|
50
|
+
__metadata("design:paramtypes", [Object])
|
|
51
|
+
], LoanConfigBusinessApi);
|
|
52
|
+
export default LoanConfigBusinessApi;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { StandardResponse } from "@fiado/gateway-adapter";
|
|
2
|
+
import { BulkGetParametersResponse, ParameterKeyRef, ParameterResponse } from "@fiado/type-kit/bin/loanConfig/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Contrato del publisher HTTP del lambda `loan-config-business` (componente 09 SureKeep Fase 1)
|
|
5
|
+
* para sus 3 endpoints privados de LECTURA de parámetros operativos (service-to-service, VPC-only).
|
|
6
|
+
*
|
|
7
|
+
* loan-config es el "centro de configuración" del SOFOM: una tabla genérica de parámetros
|
|
8
|
+
* clave/valor discriminados por `paramType` (14 sub-tipos, M6_ADMIN §8). Consumidores previstos:
|
|
9
|
+
* - wizard de originación (F2) → WIZARD (OTP, KYC) · CREDIT (descarte, comisión)
|
|
10
|
+
* - motor de crédito (F3) → SCORING · CREDIT
|
|
11
|
+
* - cobranza / batch de mora → MORA_BLOCK · UNBLOCK · COLLECTIONS · NOTIFICATIONS
|
|
12
|
+
*
|
|
13
|
+
* ⏱️ El spec ordena cachear del lado del CONSUMER (~5 min en el warm container, configurable vía
|
|
14
|
+
* `CONFIG_CACHE_TTL_SECONDS`): los parámetros cambian poco y el hot path no debe pagar una llamada
|
|
15
|
+
* por lectura. `bulkGetParameters` es la forma eficiente de precargar el cache.
|
|
16
|
+
*
|
|
17
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
18
|
+
* `tenantId` es OBLIGATORIO en los 3 métodos — no es un detalle de firma.
|
|
19
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
20
|
+
* Los privados NO llevan token de usuario (`Feature.ANONIMUS`; la protección es la red VPC),
|
|
21
|
+
* así que el lambda destino no tiene `AuthContext.issuer` y NO puede inferir el silo. El caller
|
|
22
|
+
* declara el tenant explícito por query y `@fiado/tenant-context` asume el rol de ESE silo.
|
|
23
|
+
* Sin `tenantId` → `400 UNKNOWN_TENANT` (fail-closed). Nunca hay default: caer a un tenant por
|
|
24
|
+
* default sería fail-OPEN y podría devolver parámetros de otra SOFOM.
|
|
25
|
+
*
|
|
26
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
27
|
+
* ⚠️ Patrón de retorno: `StandardResponse<T>` — el consumer accede `result.data`, NO `result.body`.
|
|
28
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
29
|
+
* `@fiado/http-client` devuelve el body pelado (`response.data` de axios); los publishers viejos
|
|
30
|
+
* que tipan `{ statusCode, body }` son ficción del tipo (ver `IRetailOrgBusinessApi`, donde está
|
|
31
|
+
* documentado el 500 que costó descubrirlo). Los publishers nuevos dicen la verdad.
|
|
32
|
+
*
|
|
33
|
+
* Errores: el lambda destino lanza `DomainError` tipado → el publisher RECHAZA (no devuelve null).
|
|
34
|
+
* Cada consumer mapea a su propio error de dominio (ver `fiado-api-invoker § 6`):
|
|
35
|
+
* `404 PARAMETER_NOT_FOUND` (paramType+key inexistente)
|
|
36
|
+
* `400 UNKNOWN_TENANT` (tenantId ausente o desconocido)
|
|
37
|
+
*
|
|
38
|
+
* Env var requerida en el consumer: `LOAN_CONFIG_BUSINESS_URL`.
|
|
39
|
+
* El template.yml del consumer la setea con:
|
|
40
|
+
*
|
|
41
|
+
* LOAN_CONFIG_BUSINESS_URL: '{{resolve:ssm:loan-config-business}}'
|
|
42
|
+
*
|
|
43
|
+
* Convención CLAUDE.md global: SSM key = nombre del lambda owner de la URL.
|
|
44
|
+
*/
|
|
45
|
+
export interface ILoanConfigBusinessApi {
|
|
46
|
+
/**
|
|
47
|
+
* GET /private/parameters/{paramType}/{key} — un parámetro puntual. `data.effectiveValue` es el
|
|
48
|
+
* valor a usar (= `value`, o `defaultValue` cuando `value` es null/pendiente).
|
|
49
|
+
*
|
|
50
|
+
* @throws si el parámetro no existe (`404 PARAMETER_NOT_FOUND`).
|
|
51
|
+
*/
|
|
52
|
+
getParameter(paramType: string, key: string, tenantId: string): Promise<StandardResponse<ParameterResponse>>;
|
|
53
|
+
/**
|
|
54
|
+
* GET /private/parameters/by-type/{paramType} — todos los parámetros de una categoría (ej. toda
|
|
55
|
+
* la config de MORA_BLOCK de una vez). Devuelve `{ parameters: [] }` si la categoría está vacía
|
|
56
|
+
* (no 404): las 14 categorías del enum son válidas por definición.
|
|
57
|
+
*/
|
|
58
|
+
getParametersByType(paramType: string, tenantId: string): Promise<StandardResponse<{
|
|
59
|
+
parameters: ParameterResponse[];
|
|
60
|
+
}>>;
|
|
61
|
+
/**
|
|
62
|
+
* POST /private/parameters/bulk-get — el hot path: varios parámetros (de cualquier categoría) en
|
|
63
|
+
* UNA llamada. Los no existentes NO hacen fallar la llamada: vuelven en `data.notFound` y el
|
|
64
|
+
* consumer decide (típicamente: usar su default local o fallar tipado).
|
|
65
|
+
*/
|
|
66
|
+
bulkGetParameters(items: ParameterKeyRef[], tenantId: string): Promise<StandardResponse<BulkGetParametersResponse>>;
|
|
67
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -21,6 +21,7 @@ export default class RetailOrgBusinessApi implements IRetailOrgBusinessApi {
|
|
|
21
21
|
private readonly baseUrl;
|
|
22
22
|
constructor(httpRequest: IHttpRequest);
|
|
23
23
|
getRetailer(retailerId: string, tenantId: string): Promise<StandardResponse<RetailerValidationDto>>;
|
|
24
|
+
getRetailerByStore(storeId: string, tenantId: string): Promise<StandardResponse<RetailerValidationDto>>;
|
|
24
25
|
getStore(retailerId: string, storeId: string, tenantId: string): Promise<StandardResponse<StoreValidationDto>>;
|
|
25
26
|
getStoreUsers(retailerId: string, storeId: string, tenantId: string): Promise<StandardResponse<RetailUserValidationDto[]>>;
|
|
26
27
|
getUserByCognitoSub(cognitoSub: string, tenantId: string): Promise<StandardResponse<RetailUserValidationDto>>;
|
|
@@ -35,6 +35,10 @@ let RetailOrgBusinessApi = class RetailOrgBusinessApi {
|
|
|
35
35
|
const url = `${this.baseUrl}/private/retailers/${encodeURIComponent(retailerId)}?tenantId=${encodeURIComponent(tenantId)}`;
|
|
36
36
|
return await this.httpRequest.get(url);
|
|
37
37
|
}
|
|
38
|
+
async getRetailerByStore(storeId, tenantId) {
|
|
39
|
+
const url = `${this.baseUrl}/private/retailers/by-store/${encodeURIComponent(storeId)}?tenantId=${encodeURIComponent(tenantId)}`;
|
|
40
|
+
return await this.httpRequest.get(url);
|
|
41
|
+
}
|
|
38
42
|
async getStore(retailerId, storeId, tenantId) {
|
|
39
43
|
const url = `${this.baseUrl}/private/retailers/${encodeURIComponent(retailerId)}/stores/${encodeURIComponent(storeId)}?tenantId=${encodeURIComponent(tenantId)}`;
|
|
40
44
|
return await this.httpRequest.get(url);
|
|
@@ -51,6 +51,18 @@ export interface IRetailOrgBusinessApi {
|
|
|
51
51
|
* @throws si el retailer no existe (`404 RETAILER_NOT_FOUND`).
|
|
52
52
|
*/
|
|
53
53
|
getRetailer(retailerId: string, tenantId: string): Promise<StandardResponse<RetailerValidationDto>>;
|
|
54
|
+
/**
|
|
55
|
+
* GET /private/retailers/by-store/{storeId} — resuelve el retailer DUEÑO de una tienda teniendo
|
|
56
|
+
* SOLO el `storeId`, sin conocer el retailer. Es el único privado que no va anidado, porque es el
|
|
57
|
+
* único caso donde el caller no tiene el `retailerId` (spec comp. 04: "resolver retailerId desde
|
|
58
|
+
* storeId").
|
|
59
|
+
*
|
|
60
|
+
* Se apoya en el GSI `storeId-pk-index` de `RetailStore_GT`: sin él haría falta `Scan`, que el rol
|
|
61
|
+
* del tenant prohíbe. Si el índice no está deployado en el silo, este endpoint responde `500`.
|
|
62
|
+
*
|
|
63
|
+
* @throws si la tienda no existe (`404 STORE_NOT_FOUND`).
|
|
64
|
+
*/
|
|
65
|
+
getRetailerByStore(storeId: string, tenantId: string): Promise<StandardResponse<RetailerValidationDto>>;
|
|
54
66
|
/**
|
|
55
67
|
* GET /private/retailers/{retailerId}/stores/{storeId} — valida que la tienda exista Y pertenezca
|
|
56
68
|
* a ese retailer. El path es ANIDADO (no `/private/stores/{storeId}`): la tabla es
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fiado/api-invoker",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.64.0",
|
|
4
4
|
"description": "Sirve como un puente entre diferentes funciones lambda, facilitando la comunicación entre ellas a través de invocaciones http",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "bin/index.js",
|
package/src/index.ts
CHANGED
|
@@ -77,6 +77,7 @@ export * from "./milestone-business/index.js";
|
|
|
77
77
|
export * from "./cognitoBackofficeConnector/index.js";
|
|
78
78
|
export * from "./platformRbac/index.js";
|
|
79
79
|
export * from "./retailOrg/index.js";
|
|
80
|
+
export * from "./loanConfig/index.js";
|
|
80
81
|
export * from "./messages-business/index.js";
|
|
81
82
|
export * from "./totp-security/index.js";
|
|
82
83
|
export * from "./equality-connector/index.js";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { inject, injectable } from "inversify";
|
|
2
|
+
import type { IHttpRequest } from "@fiado/http-client";
|
|
3
|
+
import { StandardResponse } from "@fiado/gateway-adapter";
|
|
4
|
+
import {
|
|
5
|
+
BulkGetParametersResponse,
|
|
6
|
+
ParameterKeyRef,
|
|
7
|
+
ParameterResponse,
|
|
8
|
+
} from "@fiado/type-kit/bin/loanConfig/index.js";
|
|
9
|
+
import { ILoanConfigBusinessApi } from "./interfaces/ILoanConfigBusinessApi.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Publisher HTTP del lambda `loan-config-business` (componente 09 SureKeep Fase 1) para sus 3
|
|
13
|
+
* endpoints privados de lectura de parámetros. Contrato y semántica completos →
|
|
14
|
+
* `ILoanConfigBusinessApi` (tenantId obligatorio, cache 5 min del lado del consumer,
|
|
15
|
+
* `StandardResponse` → leer `result.data`).
|
|
16
|
+
*
|
|
17
|
+
* Env var requerida en el consumer: `LOAN_CONFIG_BUSINESS_URL`.
|
|
18
|
+
* El template.yml del consumer la setea con:
|
|
19
|
+
*
|
|
20
|
+
* LOAN_CONFIG_BUSINESS_URL: '{{resolve:ssm:loan-config-business}}'
|
|
21
|
+
*
|
|
22
|
+
* Convención CLAUDE.md global: SSM key = nombre del lambda owner de la URL.
|
|
23
|
+
*/
|
|
24
|
+
@injectable()
|
|
25
|
+
export default class LoanConfigBusinessApi implements ILoanConfigBusinessApi {
|
|
26
|
+
// El buildspec publica la URL en SSM con "/" final — se normaliza para no armar "//private".
|
|
27
|
+
private readonly baseUrl = (process.env.LOAN_CONFIG_BUSINESS_URL || "").replace(/\/+$/, "");
|
|
28
|
+
|
|
29
|
+
constructor(@inject("IHttpRequest") private httpRequest: IHttpRequest) {}
|
|
30
|
+
|
|
31
|
+
async getParameter(
|
|
32
|
+
paramType: string,
|
|
33
|
+
key: string,
|
|
34
|
+
tenantId: string,
|
|
35
|
+
): Promise<StandardResponse<ParameterResponse>> {
|
|
36
|
+
const url = `${this.baseUrl}/private/parameters/${encodeURIComponent(paramType)}/${encodeURIComponent(key)}?tenantId=${encodeURIComponent(tenantId)}`;
|
|
37
|
+
return await this.httpRequest.get(url);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async getParametersByType(
|
|
41
|
+
paramType: string,
|
|
42
|
+
tenantId: string,
|
|
43
|
+
): Promise<StandardResponse<{ parameters: ParameterResponse[] }>> {
|
|
44
|
+
const url = `${this.baseUrl}/private/parameters/by-type/${encodeURIComponent(paramType)}?tenantId=${encodeURIComponent(tenantId)}`;
|
|
45
|
+
return await this.httpRequest.get(url);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async bulkGetParameters(
|
|
49
|
+
items: ParameterKeyRef[],
|
|
50
|
+
tenantId: string,
|
|
51
|
+
): Promise<StandardResponse<BulkGetParametersResponse>> {
|
|
52
|
+
const url = `${this.baseUrl}/private/parameters/bulk-get?tenantId=${encodeURIComponent(tenantId)}`;
|
|
53
|
+
return await this.httpRequest.post(url, { items });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { StandardResponse } from "@fiado/gateway-adapter";
|
|
2
|
+
import {
|
|
3
|
+
BulkGetParametersResponse,
|
|
4
|
+
ParameterKeyRef,
|
|
5
|
+
ParameterResponse,
|
|
6
|
+
} from "@fiado/type-kit/bin/loanConfig/index.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Contrato del publisher HTTP del lambda `loan-config-business` (componente 09 SureKeep Fase 1)
|
|
10
|
+
* para sus 3 endpoints privados de LECTURA de parámetros operativos (service-to-service, VPC-only).
|
|
11
|
+
*
|
|
12
|
+
* loan-config es el "centro de configuración" del SOFOM: una tabla genérica de parámetros
|
|
13
|
+
* clave/valor discriminados por `paramType` (14 sub-tipos, M6_ADMIN §8). Consumidores previstos:
|
|
14
|
+
* - wizard de originación (F2) → WIZARD (OTP, KYC) · CREDIT (descarte, comisión)
|
|
15
|
+
* - motor de crédito (F3) → SCORING · CREDIT
|
|
16
|
+
* - cobranza / batch de mora → MORA_BLOCK · UNBLOCK · COLLECTIONS · NOTIFICATIONS
|
|
17
|
+
*
|
|
18
|
+
* ⏱️ El spec ordena cachear del lado del CONSUMER (~5 min en el warm container, configurable vía
|
|
19
|
+
* `CONFIG_CACHE_TTL_SECONDS`): los parámetros cambian poco y el hot path no debe pagar una llamada
|
|
20
|
+
* por lectura. `bulkGetParameters` es la forma eficiente de precargar el cache.
|
|
21
|
+
*
|
|
22
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
23
|
+
* `tenantId` es OBLIGATORIO en los 3 métodos — no es un detalle de firma.
|
|
24
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
25
|
+
* Los privados NO llevan token de usuario (`Feature.ANONIMUS`; la protección es la red VPC),
|
|
26
|
+
* así que el lambda destino no tiene `AuthContext.issuer` y NO puede inferir el silo. El caller
|
|
27
|
+
* declara el tenant explícito por query y `@fiado/tenant-context` asume el rol de ESE silo.
|
|
28
|
+
* Sin `tenantId` → `400 UNKNOWN_TENANT` (fail-closed). Nunca hay default: caer a un tenant por
|
|
29
|
+
* default sería fail-OPEN y podría devolver parámetros de otra SOFOM.
|
|
30
|
+
*
|
|
31
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
32
|
+
* ⚠️ Patrón de retorno: `StandardResponse<T>` — el consumer accede `result.data`, NO `result.body`.
|
|
33
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
34
|
+
* `@fiado/http-client` devuelve el body pelado (`response.data` de axios); los publishers viejos
|
|
35
|
+
* que tipan `{ statusCode, body }` son ficción del tipo (ver `IRetailOrgBusinessApi`, donde está
|
|
36
|
+
* documentado el 500 que costó descubrirlo). Los publishers nuevos dicen la verdad.
|
|
37
|
+
*
|
|
38
|
+
* Errores: el lambda destino lanza `DomainError` tipado → el publisher RECHAZA (no devuelve null).
|
|
39
|
+
* Cada consumer mapea a su propio error de dominio (ver `fiado-api-invoker § 6`):
|
|
40
|
+
* `404 PARAMETER_NOT_FOUND` (paramType+key inexistente)
|
|
41
|
+
* `400 UNKNOWN_TENANT` (tenantId ausente o desconocido)
|
|
42
|
+
*
|
|
43
|
+
* Env var requerida en el consumer: `LOAN_CONFIG_BUSINESS_URL`.
|
|
44
|
+
* El template.yml del consumer la setea con:
|
|
45
|
+
*
|
|
46
|
+
* LOAN_CONFIG_BUSINESS_URL: '{{resolve:ssm:loan-config-business}}'
|
|
47
|
+
*
|
|
48
|
+
* Convención CLAUDE.md global: SSM key = nombre del lambda owner de la URL.
|
|
49
|
+
*/
|
|
50
|
+
export interface ILoanConfigBusinessApi {
|
|
51
|
+
/**
|
|
52
|
+
* GET /private/parameters/{paramType}/{key} — un parámetro puntual. `data.effectiveValue` es el
|
|
53
|
+
* valor a usar (= `value`, o `defaultValue` cuando `value` es null/pendiente).
|
|
54
|
+
*
|
|
55
|
+
* @throws si el parámetro no existe (`404 PARAMETER_NOT_FOUND`).
|
|
56
|
+
*/
|
|
57
|
+
getParameter(
|
|
58
|
+
paramType: string,
|
|
59
|
+
key: string,
|
|
60
|
+
tenantId: string,
|
|
61
|
+
): Promise<StandardResponse<ParameterResponse>>;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* GET /private/parameters/by-type/{paramType} — todos los parámetros de una categoría (ej. toda
|
|
65
|
+
* la config de MORA_BLOCK de una vez). Devuelve `{ parameters: [] }` si la categoría está vacía
|
|
66
|
+
* (no 404): las 14 categorías del enum son válidas por definición.
|
|
67
|
+
*/
|
|
68
|
+
getParametersByType(
|
|
69
|
+
paramType: string,
|
|
70
|
+
tenantId: string,
|
|
71
|
+
): Promise<StandardResponse<{ parameters: ParameterResponse[] }>>;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* POST /private/parameters/bulk-get — el hot path: varios parámetros (de cualquier categoría) en
|
|
75
|
+
* UNA llamada. Los no existentes NO hacen fallar la llamada: vuelven en `data.notFound` y el
|
|
76
|
+
* consumer decide (típicamente: usar su default local o fallar tipado).
|
|
77
|
+
*/
|
|
78
|
+
bulkGetParameters(
|
|
79
|
+
items: ParameterKeyRef[],
|
|
80
|
+
tenantId: string,
|
|
81
|
+
): Promise<StandardResponse<BulkGetParametersResponse>>;
|
|
82
|
+
}
|
|
@@ -36,6 +36,14 @@ export default class RetailOrgBusinessApi implements IRetailOrgBusinessApi {
|
|
|
36
36
|
return await this.httpRequest.get(url);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
async getRetailerByStore(
|
|
40
|
+
storeId: string,
|
|
41
|
+
tenantId: string,
|
|
42
|
+
): Promise<StandardResponse<RetailerValidationDto>> {
|
|
43
|
+
const url = `${this.baseUrl}/private/retailers/by-store/${encodeURIComponent(storeId)}?tenantId=${encodeURIComponent(tenantId)}`;
|
|
44
|
+
return await this.httpRequest.get(url);
|
|
45
|
+
}
|
|
46
|
+
|
|
39
47
|
async getStore(
|
|
40
48
|
retailerId: string,
|
|
41
49
|
storeId: string,
|
|
@@ -60,6 +60,22 @@ export interface IRetailOrgBusinessApi {
|
|
|
60
60
|
tenantId: string,
|
|
61
61
|
): Promise<StandardResponse<RetailerValidationDto>>;
|
|
62
62
|
|
|
63
|
+
/**
|
|
64
|
+
* GET /private/retailers/by-store/{storeId} — resuelve el retailer DUEÑO de una tienda teniendo
|
|
65
|
+
* SOLO el `storeId`, sin conocer el retailer. Es el único privado que no va anidado, porque es el
|
|
66
|
+
* único caso donde el caller no tiene el `retailerId` (spec comp. 04: "resolver retailerId desde
|
|
67
|
+
* storeId").
|
|
68
|
+
*
|
|
69
|
+
* Se apoya en el GSI `storeId-pk-index` de `RetailStore_GT`: sin él haría falta `Scan`, que el rol
|
|
70
|
+
* del tenant prohíbe. Si el índice no está deployado en el silo, este endpoint responde `500`.
|
|
71
|
+
*
|
|
72
|
+
* @throws si la tienda no existe (`404 STORE_NOT_FOUND`).
|
|
73
|
+
*/
|
|
74
|
+
getRetailerByStore(
|
|
75
|
+
storeId: string,
|
|
76
|
+
tenantId: string,
|
|
77
|
+
): Promise<StandardResponse<RetailerValidationDto>>;
|
|
78
|
+
|
|
63
79
|
/**
|
|
64
80
|
* GET /private/retailers/{retailerId}/stores/{storeId} — valida que la tienda exista Y pertenezca
|
|
65
81
|
* a ese retailer. El path es ANIDADO (no `/private/stores/{storeId}`): la tabla es
|