@fiado/api-invoker 5.60.0 → 5.62.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/loanOfferings/api/LoanOfferingsBusinessApi.d.ts +1 -1
- package/bin/loanOfferings/api/LoanOfferingsBusinessApi.js +6 -2
- package/bin/loanOfferings/api/interfaces/ILoanOfferingsBusinessApi.d.ts +4 -1
- package/bin/retailCatalog/api/RetailCatalogBusinessApi.d.ts +2 -1
- package/bin/retailCatalog/api/RetailCatalogBusinessApi.js +10 -1
- package/bin/retailCatalog/api/interfaces/IRetailCatalogBusinessApi.d.ts +50 -0
- package/bin/retailCatalog/api/interfaces/IRetailCatalogBusinessApi.js +2 -0
- package/package.json +1 -1
- package/src/loanOfferings/api/LoanOfferingsBusinessApi.ts +5 -1
- package/src/loanOfferings/api/interfaces/ILoanOfferingsBusinessApi.ts +5 -0
- package/src/retailCatalog/api/RetailCatalogBusinessApi.ts +18 -0
- package/src/retailCatalog/api/interfaces/IRetailCatalogBusinessApi.ts +58 -0
|
@@ -23,7 +23,7 @@ export default class LoanOfferingsBusinessApi implements ILoanOfferingsBusinessA
|
|
|
23
23
|
listActiveFinanciers(tenantId: string): Promise<StandardResponse<FinancierResponse[]>>;
|
|
24
24
|
simulate(planId: string, input: SimulateCreditPlanRequest, tenantId: string): Promise<StandardResponse<SimulationResultResponse>>;
|
|
25
25
|
consumePromotion(promotionId: string, input: ConsumePromotionRequest, tenantId: string): Promise<StandardResponse<ConsumePromotionResponse>>;
|
|
26
|
-
listPromotedSkus(storeId: string, tenantId: string): Promise<StandardResponse<PromotedSkusResponse>>;
|
|
26
|
+
listPromotedSkus(storeId: string, tenantId: string, level?: CreditPlanLevelEnum, segmentId?: string): Promise<StandardResponse<PromotedSkusResponse>>;
|
|
27
27
|
resolveCustomerSegments(input: ResolveCustomerSegmentsRequest, tenantId: string): Promise<StandardResponse<ResolveCustomerSegmentsResponse>>;
|
|
28
28
|
reservePromotionBonus(promotionId: string, input: ReservePromotionBonusRequest, tenantId: string): Promise<StandardResponse<ReservePromotionBonusResponse>>;
|
|
29
29
|
settlePromotionBonus(promotionId: string, input: SettlePromotionBonusRequest, tenantId: string): Promise<StandardResponse<PromotionBonusResponse>>;
|
|
@@ -50,8 +50,12 @@ let LoanOfferingsBusinessApi = class LoanOfferingsBusinessApi {
|
|
|
50
50
|
const url = `${this.baseUrl}/private/promotions/${encodeURIComponent(promotionId)}/consume?tenantId=${encodeURIComponent(tenantId)}`;
|
|
51
51
|
return await this.httpRequest.post(url, input);
|
|
52
52
|
}
|
|
53
|
-
async listPromotedSkus(storeId, tenantId) {
|
|
54
|
-
|
|
53
|
+
async listPromotedSkus(storeId, tenantId, level, segmentId) {
|
|
54
|
+
let url = `${this.baseUrl}/private/promotions/promoted-skus?storeId=${encodeURIComponent(storeId)}&tenantId=${encodeURIComponent(tenantId)}`;
|
|
55
|
+
if (level)
|
|
56
|
+
url += `&level=${encodeURIComponent(level)}`;
|
|
57
|
+
if (segmentId)
|
|
58
|
+
url += `&segmentId=${encodeURIComponent(segmentId)}`;
|
|
55
59
|
return await this.httpRequest.get(url);
|
|
56
60
|
}
|
|
57
61
|
async resolveCustomerSegments(input, tenantId) {
|
|
@@ -81,8 +81,11 @@ export interface ILoanOfferingsBusinessApi {
|
|
|
81
81
|
* El filtrado vive en el lambda, no acá: solo entran las promociones que alcanzan a CUALQUIER
|
|
82
82
|
* nivel (el catálogo se pinta antes del score) y las que ACOTAN por SKU (una general marcaría
|
|
83
83
|
* el catálogo entero). El caller no puede aflojar ese criterio.
|
|
84
|
+
*
|
|
85
|
+
* `level`/`segmentId` son opcionales, mismo criterio que {@link listSkuPromotions}: si no
|
|
86
|
+
* vienen, el lambda destino descarta las promociones que acotan por esa dimensión.
|
|
84
87
|
*/
|
|
85
|
-
listPromotedSkus(storeId: string, tenantId: string): Promise<StandardResponse<PromotedSkusResponse>>;
|
|
88
|
+
listPromotedSkus(storeId: string, tenantId: string, level?: CreditPlanLevelEnum, segmentId?: string): Promise<StandardResponse<PromotedSkusResponse>>;
|
|
86
89
|
/**
|
|
87
90
|
* POST /private/segments/resolve — los segmentos a los que pertenece el cliente HOY, evaluados
|
|
88
91
|
* en línea contra los hechos que manda el caller. No hay segmento persistido en el cliente.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { IHttpRequest } from "@fiado/http-client";
|
|
2
2
|
import { StandardResponse } from "@fiado/gateway-adapter";
|
|
3
|
-
import { ImeiProductLookupResponse, IRetailCatalogBusinessApi, ReleaseReservationBody, ReserveInventoryBody, ReserveInventoryResult, SellInventoryBody, StoreCatalogItem } from "./interfaces/IRetailCatalogBusinessApi.js";
|
|
3
|
+
import { ImeiProductLookupResponse, IRetailCatalogBusinessApi, ProductsByRetailersResponse, ReleaseReservationBody, ReserveInventoryBody, ReserveInventoryResult, SellInventoryBody, StoreCatalogItem } from "./interfaces/IRetailCatalogBusinessApi.js";
|
|
4
4
|
/**
|
|
5
5
|
* Publisher HTTP del lambda `retail-catalog-business` (SureKeep Fase 1, pista Retail) para sus
|
|
6
6
|
* endpoints privados del ciclo de venta del IMEI. Contrato y semántica completos →
|
|
@@ -21,6 +21,7 @@ export default class RetailCatalogBusinessApi implements IRetailCatalogBusinessA
|
|
|
21
21
|
private tenantHeader;
|
|
22
22
|
getStoreCatalog(storeId: string, issuer: string): Promise<StandardResponse<StoreCatalogItem[]>>;
|
|
23
23
|
getProductsByImei(imeis: string[], tenantId: string): Promise<StandardResponse<ImeiProductLookupResponse>>;
|
|
24
|
+
getProductsByRetailers(retailerIds: string[], tenantId: string): Promise<StandardResponse<ProductsByRetailersResponse>>;
|
|
24
25
|
reserveInventory(imei: string, body: ReserveInventoryBody, issuer: string): Promise<StandardResponse<ReserveInventoryResult>>;
|
|
25
26
|
sellInventory(imei: string, body: SellInventoryBody, issuer: string): Promise<StandardResponse<void>>;
|
|
26
27
|
releaseInventory(imei: string, body: ReleaseReservationBody, issuer: string): Promise<StandardResponse<void>>;
|
|
@@ -11,7 +11,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
11
11
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
12
|
};
|
|
13
13
|
import { inject, injectable } from "inversify";
|
|
14
|
-
import { IMEI_PRODUCT_BATCH_MAX, } from "./interfaces/IRetailCatalogBusinessApi.js";
|
|
14
|
+
import { IMEI_PRODUCT_BATCH_MAX, RETAILER_PRODUCTS_BATCH_MAX, } from "./interfaces/IRetailCatalogBusinessApi.js";
|
|
15
15
|
/** Header por el que el destino resuelve el silo (issuer Cognito forwardeado por el caller). */
|
|
16
16
|
const TENANT_ISSUER_HEADER = "x-tenant-issuer";
|
|
17
17
|
/**
|
|
@@ -51,6 +51,15 @@ let RetailCatalogBusinessApi = class RetailCatalogBusinessApi {
|
|
|
51
51
|
const query = new URLSearchParams({ imeis: imeis.join(","), tenantId });
|
|
52
52
|
return await this.httpRequest.get(`${this.baseUrl}/private/products/by-imei?${query.toString()}`);
|
|
53
53
|
}
|
|
54
|
+
async getProductsByRetailers(retailerIds, tenantId) {
|
|
55
|
+
// Se corta aquí: mandar un lote que el destino va a rechazar solo gasta un round-trip.
|
|
56
|
+
if (retailerIds.length > RETAILER_PRODUCTS_BATCH_MAX) {
|
|
57
|
+
throw new Error(`El lote admite hasta ${RETAILER_PRODUCTS_BATCH_MAX} cadenas y llegaron ${retailerIds.length}`);
|
|
58
|
+
}
|
|
59
|
+
const query = new URLSearchParams({ tenantId });
|
|
60
|
+
const body = { retailerIds };
|
|
61
|
+
return await this.httpRequest.post(`${this.baseUrl}/private/products/by-retailers?${query.toString()}`, body);
|
|
62
|
+
}
|
|
54
63
|
async reserveInventory(imei, body, issuer) {
|
|
55
64
|
const url = `${this.baseUrl}/private/inventory/${encodeURIComponent(imei)}/reserve`;
|
|
56
65
|
return await this.httpRequest.put(url, body, this.tenantHeader(issuer));
|
|
@@ -80,6 +80,30 @@ export interface ImeiProductLookupEntry {
|
|
|
80
80
|
export interface ImeiProductLookupResponse {
|
|
81
81
|
items: ImeiProductLookupEntry[];
|
|
82
82
|
}
|
|
83
|
+
/** Techo de cadenas por request del lote cadena->catálogo. Lo declara y lo honra el destino. */
|
|
84
|
+
export declare const RETAILER_PRODUCTS_BATCH_MAX = 100;
|
|
85
|
+
/** Body de POST `/private/products/by-retailers`. */
|
|
86
|
+
export interface ProductsByRetailersBody {
|
|
87
|
+
retailerIds: string[];
|
|
88
|
+
}
|
|
89
|
+
/** Un producto vendible de una cadena (espeja `RetailerProductItem` del destino). */
|
|
90
|
+
export interface RetailerProductItem {
|
|
91
|
+
/** Cadena a la que pertenece el producto; es la llave con la que el caller agrupa. */
|
|
92
|
+
retailerId: string;
|
|
93
|
+
sku: string;
|
|
94
|
+
/** Marca comercial (p. ej. "Samsung"). */
|
|
95
|
+
brand: string;
|
|
96
|
+
/** Modelo (p. ej. "A54"). */
|
|
97
|
+
model: string;
|
|
98
|
+
}
|
|
99
|
+
/** Respuesta del lote cadena->catálogo: los productos de TODAS las cadenas pedidas, en una lista plana. */
|
|
100
|
+
export interface ProductsByRetailersResponse {
|
|
101
|
+
items: RetailerProductItem[];
|
|
102
|
+
/** Cuántos productos trae `items`. */
|
|
103
|
+
count: number;
|
|
104
|
+
/** `true` si el destino recortó el resultado; pide las cadenas en lotes más chicos. */
|
|
105
|
+
truncated: boolean;
|
|
106
|
+
}
|
|
83
107
|
/** Resultado de la reserva (espeja `ReserveInventoryResponse` del destino). */
|
|
84
108
|
export interface ReserveInventoryResult {
|
|
85
109
|
reservationExpiresAt: string;
|
|
@@ -125,6 +149,32 @@ export interface IRetailCatalogBusinessApi {
|
|
|
125
149
|
* `400 IMEI_BATCH_REQUIRED` si `imeis` viene vacío · `400 UNKNOWN_TENANT` sin `tenantId`.
|
|
126
150
|
*/
|
|
127
151
|
getProductsByImei(imeis: string[], tenantId: string): Promise<StandardResponse<ImeiProductLookupResponse>>;
|
|
152
|
+
/**
|
|
153
|
+
* POST `/private/products/by-retailers?tenantId=` — catálogo de productos de VARIAS cadenas en
|
|
154
|
+
* una sola llamada, para el consumidor que arma su vista con N cadenas y no quiere N requests.
|
|
155
|
+
*
|
|
156
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
157
|
+
* ⚠️ El tenant va por `?tenantId=`, NO por el header `x-tenant-issuer` del resto de este publisher.
|
|
158
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
159
|
+
* Es obligatorio. El destino entra por `TenantContextService.withContextByTenantId`, igual que
|
|
160
|
+
* `getProductsByImei`.
|
|
161
|
+
*
|
|
162
|
+
* ── El contrato del lote ────────────────────────────────────────────────────────────────────
|
|
163
|
+
* `retailerIds` no puede venir vacío, sin repetidos y con un techo de
|
|
164
|
+
* `RETAILER_PRODUCTS_BATCH_MAX` cadenas; el caller parte los lotes mayores. La respuesta es una
|
|
165
|
+
* lista PLANA de productos con su `retailerId` — el caller agrupa. Una cadena sin catálogo
|
|
166
|
+
* simplemente no aporta ítems.
|
|
167
|
+
*
|
|
168
|
+
* O el lote sale completo o no sale: si falla la lectura de al menos una cadena el destino
|
|
169
|
+
* responde `INTERNAL_ERROR`. Nunca recibes una lista parcial.
|
|
170
|
+
*
|
|
171
|
+
* @throws Error si el lote supera el techo (se corta aquí, sin salir a la red) ·
|
|
172
|
+
* `400 VALIDATION_ERROR` body vacío, con repetidos, con no-strings o de más de 100 ids ·
|
|
173
|
+
* `400 UNKNOWN_TENANT` falta o no se reconoce el `tenantId` ·
|
|
174
|
+
* `500 TENANT_ASSUME_ROLE_FAILED` fallo de infra del silo ·
|
|
175
|
+
* `500 INTERNAL_ERROR` no se pudo leer alguna cadena.
|
|
176
|
+
*/
|
|
177
|
+
getProductsByRetailers(retailerIds: string[], tenantId: string): Promise<StandardResponse<ProductsByRetailersResponse>>;
|
|
128
178
|
/** PUT `/private/inventory/{imei}/reserve` — reserva atómica del IMEI para una sesión (AVAILABLE → RESERVED). */
|
|
129
179
|
reserveInventory(imei: string, body: ReserveInventoryBody, issuer: string): Promise<StandardResponse<ReserveInventoryResult>>;
|
|
130
180
|
/** PUT `/private/inventory/{imei}/sell` — vende el IMEI (RESERVED → SOLD). */
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
/** Techo de IMEIs por request del lote IMEI->producto. Lo declara y lo honra el destino. */
|
|
2
2
|
export const IMEI_PRODUCT_BATCH_MAX = 100;
|
|
3
|
+
/** Techo de cadenas por request del lote cadena->catálogo. Lo declara y lo honra el destino. */
|
|
4
|
+
export const RETAILER_PRODUCTS_BATCH_MAX = 100;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fiado/api-invoker",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.62.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",
|
|
@@ -84,8 +84,12 @@ export default class LoanOfferingsBusinessApi implements ILoanOfferingsBusinessA
|
|
|
84
84
|
async listPromotedSkus(
|
|
85
85
|
storeId: string,
|
|
86
86
|
tenantId: string,
|
|
87
|
+
level?: CreditPlanLevelEnum,
|
|
88
|
+
segmentId?: string,
|
|
87
89
|
): Promise<StandardResponse<PromotedSkusResponse>> {
|
|
88
|
-
|
|
90
|
+
let url = `${this.baseUrl}/private/promotions/promoted-skus?storeId=${encodeURIComponent(storeId)}&tenantId=${encodeURIComponent(tenantId)}`;
|
|
91
|
+
if (level) url += `&level=${encodeURIComponent(level)}`;
|
|
92
|
+
if (segmentId) url += `&segmentId=${encodeURIComponent(segmentId)}`;
|
|
89
93
|
return await this.httpRequest.get(url);
|
|
90
94
|
}
|
|
91
95
|
|
|
@@ -120,10 +120,15 @@ export interface ILoanOfferingsBusinessApi {
|
|
|
120
120
|
* El filtrado vive en el lambda, no acá: solo entran las promociones que alcanzan a CUALQUIER
|
|
121
121
|
* nivel (el catálogo se pinta antes del score) y las que ACOTAN por SKU (una general marcaría
|
|
122
122
|
* el catálogo entero). El caller no puede aflojar ese criterio.
|
|
123
|
+
*
|
|
124
|
+
* `level`/`segmentId` son opcionales, mismo criterio que {@link listSkuPromotions}: si no
|
|
125
|
+
* vienen, el lambda destino descarta las promociones que acotan por esa dimensión.
|
|
123
126
|
*/
|
|
124
127
|
listPromotedSkus(
|
|
125
128
|
storeId: string,
|
|
126
129
|
tenantId: string,
|
|
130
|
+
level?: CreditPlanLevelEnum,
|
|
131
|
+
segmentId?: string,
|
|
127
132
|
): Promise<StandardResponse<PromotedSkusResponse>>;
|
|
128
133
|
|
|
129
134
|
/**
|
|
@@ -5,9 +5,12 @@ import {
|
|
|
5
5
|
IMEI_PRODUCT_BATCH_MAX,
|
|
6
6
|
ImeiProductLookupResponse,
|
|
7
7
|
IRetailCatalogBusinessApi,
|
|
8
|
+
ProductsByRetailersBody,
|
|
9
|
+
ProductsByRetailersResponse,
|
|
8
10
|
ReleaseReservationBody,
|
|
9
11
|
ReserveInventoryBody,
|
|
10
12
|
ReserveInventoryResult,
|
|
13
|
+
RETAILER_PRODUCTS_BATCH_MAX,
|
|
11
14
|
SellInventoryBody,
|
|
12
15
|
StoreCatalogItem,
|
|
13
16
|
} from "./interfaces/IRetailCatalogBusinessApi.js";
|
|
@@ -58,6 +61,21 @@ export default class RetailCatalogBusinessApi implements IRetailCatalogBusinessA
|
|
|
58
61
|
return await this.httpRequest.get(`${this.baseUrl}/private/products/by-imei?${query.toString()}`);
|
|
59
62
|
}
|
|
60
63
|
|
|
64
|
+
async getProductsByRetailers(
|
|
65
|
+
retailerIds: string[],
|
|
66
|
+
tenantId: string,
|
|
67
|
+
): Promise<StandardResponse<ProductsByRetailersResponse>> {
|
|
68
|
+
// Se corta aquí: mandar un lote que el destino va a rechazar solo gasta un round-trip.
|
|
69
|
+
if (retailerIds.length > RETAILER_PRODUCTS_BATCH_MAX) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`El lote admite hasta ${RETAILER_PRODUCTS_BATCH_MAX} cadenas y llegaron ${retailerIds.length}`,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
const query = new URLSearchParams({ tenantId });
|
|
75
|
+
const body: ProductsByRetailersBody = { retailerIds };
|
|
76
|
+
return await this.httpRequest.post(`${this.baseUrl}/private/products/by-retailers?${query.toString()}`, body);
|
|
77
|
+
}
|
|
78
|
+
|
|
61
79
|
async reserveInventory(
|
|
62
80
|
imei: string,
|
|
63
81
|
body: ReserveInventoryBody,
|
|
@@ -93,6 +93,34 @@ export interface ImeiProductLookupResponse {
|
|
|
93
93
|
items: ImeiProductLookupEntry[];
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
/** Techo de cadenas por request del lote cadena->catálogo. Lo declara y lo honra el destino. */
|
|
97
|
+
export const RETAILER_PRODUCTS_BATCH_MAX = 100;
|
|
98
|
+
|
|
99
|
+
/** Body de POST `/private/products/by-retailers`. */
|
|
100
|
+
export interface ProductsByRetailersBody {
|
|
101
|
+
retailerIds: string[];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Un producto vendible de una cadena (espeja `RetailerProductItem` del destino). */
|
|
105
|
+
export interface RetailerProductItem {
|
|
106
|
+
/** Cadena a la que pertenece el producto; es la llave con la que el caller agrupa. */
|
|
107
|
+
retailerId: string;
|
|
108
|
+
sku: string;
|
|
109
|
+
/** Marca comercial (p. ej. "Samsung"). */
|
|
110
|
+
brand: string;
|
|
111
|
+
/** Modelo (p. ej. "A54"). */
|
|
112
|
+
model: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Respuesta del lote cadena->catálogo: los productos de TODAS las cadenas pedidas, en una lista plana. */
|
|
116
|
+
export interface ProductsByRetailersResponse {
|
|
117
|
+
items: RetailerProductItem[];
|
|
118
|
+
/** Cuántos productos trae `items`. */
|
|
119
|
+
count: number;
|
|
120
|
+
/** `true` si el destino recortó el resultado; pide las cadenas en lotes más chicos. */
|
|
121
|
+
truncated: boolean;
|
|
122
|
+
}
|
|
123
|
+
|
|
96
124
|
/** Resultado de la reserva (espeja `ReserveInventoryResponse` del destino). */
|
|
97
125
|
export interface ReserveInventoryResult {
|
|
98
126
|
reservationExpiresAt: string;
|
|
@@ -144,6 +172,36 @@ export interface IRetailCatalogBusinessApi {
|
|
|
144
172
|
*/
|
|
145
173
|
getProductsByImei(imeis: string[], tenantId: string): Promise<StandardResponse<ImeiProductLookupResponse>>;
|
|
146
174
|
|
|
175
|
+
/**
|
|
176
|
+
* POST `/private/products/by-retailers?tenantId=` — catálogo de productos de VARIAS cadenas en
|
|
177
|
+
* una sola llamada, para el consumidor que arma su vista con N cadenas y no quiere N requests.
|
|
178
|
+
*
|
|
179
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
180
|
+
* ⚠️ El tenant va por `?tenantId=`, NO por el header `x-tenant-issuer` del resto de este publisher.
|
|
181
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
182
|
+
* Es obligatorio. El destino entra por `TenantContextService.withContextByTenantId`, igual que
|
|
183
|
+
* `getProductsByImei`.
|
|
184
|
+
*
|
|
185
|
+
* ── El contrato del lote ────────────────────────────────────────────────────────────────────
|
|
186
|
+
* `retailerIds` no puede venir vacío, sin repetidos y con un techo de
|
|
187
|
+
* `RETAILER_PRODUCTS_BATCH_MAX` cadenas; el caller parte los lotes mayores. La respuesta es una
|
|
188
|
+
* lista PLANA de productos con su `retailerId` — el caller agrupa. Una cadena sin catálogo
|
|
189
|
+
* simplemente no aporta ítems.
|
|
190
|
+
*
|
|
191
|
+
* O el lote sale completo o no sale: si falla la lectura de al menos una cadena el destino
|
|
192
|
+
* responde `INTERNAL_ERROR`. Nunca recibes una lista parcial.
|
|
193
|
+
*
|
|
194
|
+
* @throws Error si el lote supera el techo (se corta aquí, sin salir a la red) ·
|
|
195
|
+
* `400 VALIDATION_ERROR` body vacío, con repetidos, con no-strings o de más de 100 ids ·
|
|
196
|
+
* `400 UNKNOWN_TENANT` falta o no se reconoce el `tenantId` ·
|
|
197
|
+
* `500 TENANT_ASSUME_ROLE_FAILED` fallo de infra del silo ·
|
|
198
|
+
* `500 INTERNAL_ERROR` no se pudo leer alguna cadena.
|
|
199
|
+
*/
|
|
200
|
+
getProductsByRetailers(
|
|
201
|
+
retailerIds: string[],
|
|
202
|
+
tenantId: string,
|
|
203
|
+
): Promise<StandardResponse<ProductsByRetailersResponse>>;
|
|
204
|
+
|
|
147
205
|
/** PUT `/private/inventory/{imei}/reserve` — reserva atómica del IMEI para una sesión (AVAILABLE → RESERVED). */
|
|
148
206
|
reserveInventory(imei: string, body: ReserveInventoryBody, issuer: string): Promise<StandardResponse<ReserveInventoryResult>>;
|
|
149
207
|
|