@fiado/api-invoker 5.40.0 → 5.41.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.
@@ -1,9 +1,9 @@
1
1
  import type { IHttpRequest } from "@fiado/http-client";
2
2
  import { StandardResponse } from "@fiado/gateway-adapter";
3
3
  import { RetailerValidationDto, StoreValidationDto, RetailUserValidationDto, CollectorValidationDto, PrivateSellerListResponse, RetailUserStatusEnum } from "@fiado/type-kit/bin/retailOrg/index.js";
4
- import { IRetailOrgBusinessApi, StoreRosterStatusFilter } from "./interfaces/IRetailOrgBusinessApi.js";
4
+ import { IRetailOrgBusinessApi, RetailerRosterStatusFilter, StoreRosterStatusFilter } from "./interfaces/IRetailOrgBusinessApi.js";
5
5
  /**
6
- * Publisher HTTP del lambda `retail-org-business` (componente 04 SureKeep Fase 1) para sus 8
6
+ * Publisher HTTP del lambda `retail-org-business` (componente 04 SureKeep Fase 1) para sus 9
7
7
  * endpoints privados de validación. Contrato y semántica completos → `IRetailOrgBusinessApi`.
8
8
  *
9
9
  * Los paths y el `?tenantId=` fueron verificados contra dev (200 + negativos 400/404) el
@@ -20,6 +20,13 @@ export default class RetailOrgBusinessApi implements IRetailOrgBusinessApi {
20
20
  private httpRequest;
21
21
  private readonly baseUrl;
22
22
  constructor(httpRequest: IHttpRequest);
23
+ /**
24
+ * El padrón de retailers del SILO — lo consume la pantalla de analítica del Portal Admin, que
25
+ * agrega ventas de todo el silo y no de una cadena. Contrato y semántica completos (incluido por
26
+ * qué `status` SÍ tiene default y por qué acá el estado es el CRUDO, sin cascada del padre)
27
+ * → `IRetailOrgBusinessApi.listRetailers`.
28
+ */
29
+ listRetailers(tenantId: string, status?: RetailerRosterStatusFilter): Promise<StandardResponse<RetailerValidationDto[]>>;
23
30
  getRetailer(retailerId: string, tenantId: string): Promise<StandardResponse<RetailerValidationDto>>;
24
31
  getRetailerByStore(storeId: string, tenantId: string): Promise<StandardResponse<RetailerValidationDto>>;
25
32
  getStore(retailerId: string, storeId: string, tenantId: string): Promise<StandardResponse<StoreValidationDto>>;
@@ -12,7 +12,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
12
  };
13
13
  import { inject, injectable } from "inversify";
14
14
  /**
15
- * Publisher HTTP del lambda `retail-org-business` (componente 04 SureKeep Fase 1) para sus 8
15
+ * Publisher HTTP del lambda `retail-org-business` (componente 04 SureKeep Fase 1) para sus 9
16
16
  * endpoints privados de validación. Contrato y semántica completos → `IRetailOrgBusinessApi`.
17
17
  *
18
18
  * Los paths y el `?tenantId=` fueron verificados contra dev (200 + negativos 400/404) el
@@ -31,6 +31,20 @@ let RetailOrgBusinessApi = class RetailOrgBusinessApi {
31
31
  constructor(httpRequest) {
32
32
  this.httpRequest = httpRequest;
33
33
  }
34
+ /**
35
+ * El padrón de retailers del SILO — lo consume la pantalla de analítica del Portal Admin, que
36
+ * agrega ventas de todo el silo y no de una cadena. Contrato y semántica completos (incluido por
37
+ * qué `status` SÍ tiene default y por qué acá el estado es el CRUDO, sin cascada del padre)
38
+ * → `IRetailOrgBusinessApi.listRetailers`.
39
+ */
40
+ async listRetailers(tenantId, status) {
41
+ // `URLSearchParams` en vez de concatenar: `status` es opcional y armar el `&status=` a mano
42
+ // deja un `&status=undefined` en cuanto alguien se distrae.
43
+ const query = new URLSearchParams({ tenantId });
44
+ if (status)
45
+ query.set("status", status);
46
+ return await this.httpRequest.get(`${this.baseUrl}/private/retailers?${query.toString()}`);
47
+ }
34
48
  async getRetailer(retailerId, tenantId) {
35
49
  const url = `${this.baseUrl}/private/retailers/${encodeURIComponent(retailerId)}?tenantId=${encodeURIComponent(tenantId)}`;
36
50
  return await this.httpRequest.get(url);
@@ -1,14 +1,16 @@
1
1
  import { StandardResponse } from "@fiado/gateway-adapter";
2
- import { RetailerValidationDto, StoreValidationDto, RetailUserValidationDto, CollectorValidationDto, PrivateSellerListResponse, RetailUserStatusEnum, StoreStatusEnum } from "@fiado/type-kit/bin/retailOrg/index.js";
2
+ import { RetailerValidationDto, StoreValidationDto, RetailUserValidationDto, CollectorValidationDto, PrivateSellerListResponse, RetailUserStatusEnum, RetailerStatusEnum, StoreStatusEnum } from "@fiado/type-kit/bin/retailOrg/index.js";
3
3
  /**
4
4
  * Filtro de `listStoresByRetailer`. `"ALL"` no es un estado de tienda: es la ausencia de filtro, y
5
5
  * va en el MISMO parámetro que los estados porque los dos hablan del mismo eje — un segundo flag
6
6
  * tipo `includeInactive` admitiría combinaciones sin sentido que alguien tendría que resolver.
7
7
  */
8
8
  export type StoreRosterStatusFilter = StoreStatusEnum | "ALL";
9
+ /** Filtro de `listRetailers`. Mismo criterio que `StoreRosterStatusFilter`, un nivel más arriba. */
10
+ export type RetailerRosterStatusFilter = RetailerStatusEnum | "ALL";
9
11
  /**
10
12
  * Contrato del publisher HTTP del lambda `retail-org-business` (componente 04 SureKeep Fase 1)
11
- * para sus 8 endpoints privados de VALIDACIÓN (service-to-service, VPC-only).
13
+ * para sus 9 endpoints privados de VALIDACIÓN (service-to-service, VPC-only).
12
14
  *
13
15
  * Consumidores previstos (regla R5 — cruces entre lambdas son SOLO lecturas de validación;
14
16
  * ningún lambda escribe en tabla ajena):
@@ -51,6 +53,43 @@ export type StoreRosterStatusFilter = StoreStatusEnum | "ALL";
51
53
  * Convención CLAUDE.md global: SSM key = nombre del lambda owner de la URL.
52
54
  */
53
55
  export interface IRetailOrgBusinessApi {
56
+ /**
57
+ * `GET /private/retailers` — el **padrón de retailers del SILO**.
58
+ *
59
+ * ── 🔴 Por qué este método existe ────────────────────────────────────────────────────────────
60
+ * Lo consume la pantalla de analítica del Portal Admin, que agrega ventas de TODO el silo y no
61
+ * de una cadena. Para eso necesita saber **qué retailers existen**, y ningún otro privado lo
62
+ * dice: `getRetailer` resuelve UNO por id, `getRetailerByStore` el dueño de una tienda, y el
63
+ * resto baja un nivel. El único que lista cadenas, `publicListRetailers`, va detrás del
64
+ * `W4Authorizer` (token de usuario, no invocable entre lambdas), pagina, y devuelve el registro
65
+ * completo con RFC y datos de contacto.
66
+ *
67
+ * Es el hermano de `listStoresByRetailer` un nivel más arriba: aquel da las tiendas de UNA
68
+ * cadena, este da las cadenas. Sin `retailerId` en la firma: el recurso es el silo entero, que
69
+ * ya lo determina el `tenantId`.
70
+ *
71
+ * Devuelve el mismo `RetailerValidationDto` que `getRetailer` — `retailerId`, `name`, `type`,
72
+ * `status`, `parentId` — **sin ningún campo PII**. Trae el árbol COMPLETO (cadenas raíz +
73
+ * subdistribuidores + franquicias, a cualquier profundidad): una venta cuelga de una tienda que
74
+ * pertenece a un retailer de cualquier nivel, así que quedarse en las raíces perdería ventas.
75
+ *
76
+ * ⚠️ El `status` es el CRUDO de la fila, NO uno efectivo — a diferencia de `getStore` y
77
+ * `listStoresByRetailer`, donde sí viene la cascada del padre aplicada. En retail-org un
78
+ * retailer no hereda el estado de su padre en ninguna lectura: un subdistribuidor `ACTIVE` de
79
+ * una cadena `SUSPENDED` sale como `ACTIVE`. Si eso importa, cruza el `parentId`.
80
+ *
81
+ * ── ⚠️ `status` SÍ tiene default, igual que `listStoresByRetailer` ───────────────────────────
82
+ * Omitirlo devuelve **solo los `ACTIVE`**. Pasa `"ALL"` para el padrón completo. El default vive
83
+ * en el lambda, no acá: mandarlo implícito desde el publisher partiría la decisión en dos
84
+ * lugares que alguien tendría que mantener sincronizados.
85
+ *
86
+ * Devuelve `[]` si ningún retailer pasa el filtro. **No hay 404**: el silo siempre existe — lo
87
+ * garantiza el `tenantId`, que es lo que resolvió el contexto del tenant.
88
+ *
89
+ * @throws `400 RETAILER_STATUS_FILTER_INVALID` si `status` no es del catálogo ·
90
+ * `400 UNKNOWN_TENANT` sin `tenantId`.
91
+ */
92
+ listRetailers(tenantId: string, status?: RetailerRosterStatusFilter): Promise<StandardResponse<RetailerValidationDto[]>>;
54
93
  /**
55
94
  * GET /private/retailers/{retailerId} — valida que el retailer exista y devuelve su shape mínimo
56
95
  * (id, name, type, status, parentId). `status` ya viene con la cascada aplicada (estado efectivo).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fiado/api-invoker",
3
- "version": "5.40.0",
3
+ "version": "5.41.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",
@@ -11,11 +11,12 @@ import {
11
11
  } from "@fiado/type-kit/bin/retailOrg/index.js";
12
12
  import {
13
13
  IRetailOrgBusinessApi,
14
+ RetailerRosterStatusFilter,
14
15
  StoreRosterStatusFilter,
15
16
  } from "./interfaces/IRetailOrgBusinessApi.js";
16
17
 
17
18
  /**
18
- * Publisher HTTP del lambda `retail-org-business` (componente 04 SureKeep Fase 1) para sus 8
19
+ * Publisher HTTP del lambda `retail-org-business` (componente 04 SureKeep Fase 1) para sus 9
19
20
  * endpoints privados de validación. Contrato y semántica completos → `IRetailOrgBusinessApi`.
20
21
  *
21
22
  * Los paths y el `?tenantId=` fueron verificados contra dev (200 + negativos 400/404) el
@@ -34,6 +35,23 @@ export default class RetailOrgBusinessApi implements IRetailOrgBusinessApi {
34
35
 
35
36
  constructor(@inject("IHttpRequest") private httpRequest: IHttpRequest) {}
36
37
 
38
+ /**
39
+ * El padrón de retailers del SILO — lo consume la pantalla de analítica del Portal Admin, que
40
+ * agrega ventas de todo el silo y no de una cadena. Contrato y semántica completos (incluido por
41
+ * qué `status` SÍ tiene default y por qué acá el estado es el CRUDO, sin cascada del padre)
42
+ * → `IRetailOrgBusinessApi.listRetailers`.
43
+ */
44
+ async listRetailers(
45
+ tenantId: string,
46
+ status?: RetailerRosterStatusFilter,
47
+ ): Promise<StandardResponse<RetailerValidationDto[]>> {
48
+ // `URLSearchParams` en vez de concatenar: `status` es opcional y armar el `&status=` a mano
49
+ // deja un `&status=undefined` en cuanto alguien se distrae.
50
+ const query = new URLSearchParams({ tenantId });
51
+ if (status) query.set("status", status);
52
+ return await this.httpRequest.get(`${this.baseUrl}/private/retailers?${query.toString()}`);
53
+ }
54
+
37
55
  async getRetailer(
38
56
  retailerId: string,
39
57
  tenantId: string,
@@ -6,6 +6,7 @@ import {
6
6
  CollectorValidationDto,
7
7
  PrivateSellerListResponse,
8
8
  RetailUserStatusEnum,
9
+ RetailerStatusEnum,
9
10
  StoreStatusEnum,
10
11
  } from "@fiado/type-kit/bin/retailOrg/index.js";
11
12
 
@@ -16,9 +17,12 @@ import {
16
17
  */
17
18
  export type StoreRosterStatusFilter = StoreStatusEnum | "ALL";
18
19
 
20
+ /** Filtro de `listRetailers`. Mismo criterio que `StoreRosterStatusFilter`, un nivel más arriba. */
21
+ export type RetailerRosterStatusFilter = RetailerStatusEnum | "ALL";
22
+
19
23
  /**
20
24
  * Contrato del publisher HTTP del lambda `retail-org-business` (componente 04 SureKeep Fase 1)
21
- * para sus 8 endpoints privados de VALIDACIÓN (service-to-service, VPC-only).
25
+ * para sus 9 endpoints privados de VALIDACIÓN (service-to-service, VPC-only).
22
26
  *
23
27
  * Consumidores previstos (regla R5 — cruces entre lambdas son SOLO lecturas de validación;
24
28
  * ningún lambda escribe en tabla ajena):
@@ -61,6 +65,47 @@ export type StoreRosterStatusFilter = StoreStatusEnum | "ALL";
61
65
  * Convención CLAUDE.md global: SSM key = nombre del lambda owner de la URL.
62
66
  */
63
67
  export interface IRetailOrgBusinessApi {
68
+ /**
69
+ * `GET /private/retailers` — el **padrón de retailers del SILO**.
70
+ *
71
+ * ── 🔴 Por qué este método existe ────────────────────────────────────────────────────────────
72
+ * Lo consume la pantalla de analítica del Portal Admin, que agrega ventas de TODO el silo y no
73
+ * de una cadena. Para eso necesita saber **qué retailers existen**, y ningún otro privado lo
74
+ * dice: `getRetailer` resuelve UNO por id, `getRetailerByStore` el dueño de una tienda, y el
75
+ * resto baja un nivel. El único que lista cadenas, `publicListRetailers`, va detrás del
76
+ * `W4Authorizer` (token de usuario, no invocable entre lambdas), pagina, y devuelve el registro
77
+ * completo con RFC y datos de contacto.
78
+ *
79
+ * Es el hermano de `listStoresByRetailer` un nivel más arriba: aquel da las tiendas de UNA
80
+ * cadena, este da las cadenas. Sin `retailerId` en la firma: el recurso es el silo entero, que
81
+ * ya lo determina el `tenantId`.
82
+ *
83
+ * Devuelve el mismo `RetailerValidationDto` que `getRetailer` — `retailerId`, `name`, `type`,
84
+ * `status`, `parentId` — **sin ningún campo PII**. Trae el árbol COMPLETO (cadenas raíz +
85
+ * subdistribuidores + franquicias, a cualquier profundidad): una venta cuelga de una tienda que
86
+ * pertenece a un retailer de cualquier nivel, así que quedarse en las raíces perdería ventas.
87
+ *
88
+ * ⚠️ El `status` es el CRUDO de la fila, NO uno efectivo — a diferencia de `getStore` y
89
+ * `listStoresByRetailer`, donde sí viene la cascada del padre aplicada. En retail-org un
90
+ * retailer no hereda el estado de su padre en ninguna lectura: un subdistribuidor `ACTIVE` de
91
+ * una cadena `SUSPENDED` sale como `ACTIVE`. Si eso importa, cruza el `parentId`.
92
+ *
93
+ * ── ⚠️ `status` SÍ tiene default, igual que `listStoresByRetailer` ───────────────────────────
94
+ * Omitirlo devuelve **solo los `ACTIVE`**. Pasa `"ALL"` para el padrón completo. El default vive
95
+ * en el lambda, no acá: mandarlo implícito desde el publisher partiría la decisión en dos
96
+ * lugares que alguien tendría que mantener sincronizados.
97
+ *
98
+ * Devuelve `[]` si ningún retailer pasa el filtro. **No hay 404**: el silo siempre existe — lo
99
+ * garantiza el `tenantId`, que es lo que resolvió el contexto del tenant.
100
+ *
101
+ * @throws `400 RETAILER_STATUS_FILTER_INVALID` si `status` no es del catálogo ·
102
+ * `400 UNKNOWN_TENANT` sin `tenantId`.
103
+ */
104
+ listRetailers(
105
+ tenantId: string,
106
+ status?: RetailerRosterStatusFilter,
107
+ ): Promise<StandardResponse<RetailerValidationDto[]>>;
108
+
64
109
  /**
65
110
  * GET /private/retailers/{retailerId} — valida que el retailer exista y devuelve su shape mínimo
66
111
  * (id, name, type, status, parentId). `status` ya viene con la cascada aplicada (estado efectivo).