@fiado/api-invoker 5.143.0 → 5.144.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/platformRbac/api/PlatformRbacBusinessApi.d.ts +1 -1
- package/bin/platformRbac/api/PlatformRbacBusinessApi.js +1 -1
- package/bin/platformRbac/api/interfaces/IPlatformRbacBusinessApi.d.ts +1 -1
- package/bin/retailCatalog/api/RetailCatalogBusinessApi.d.ts +2 -2
- package/bin/retailCatalog/api/RetailCatalogBusinessApi.js +3 -1
- package/bin/retailCatalog/api/interfaces/IRetailCatalogBusinessApi.d.ts +8 -7
- package/bin/retailIntegration/api/RetailIntegrationConnectorApi.d.ts +5 -1
- package/bin/retailIntegration/api/RetailIntegrationConnectorApi.js +33 -7
- package/bin/retailIntegration/api/interfaces/IRetailIntegrationConnectorApi.d.ts +5 -1
- package/bin/retailOrg/api/RetailOrgBusinessApi.d.ts +5 -3
- package/bin/retailOrg/api/RetailOrgBusinessApi.js +13 -6
- package/bin/retailOrg/api/interfaces/IRetailOrgBusinessApi.d.ts +17 -3
- package/bin/retailOrg/api/interfaces/IRetailOrgBusinessApi.js +4 -1
- package/package.json +2 -2
- package/src/platformRbac/api/PlatformRbacBusinessApi.ts +1 -1
- package/src/platformRbac/api/interfaces/IPlatformRbacBusinessApi.ts +1 -1
- package/src/retailCatalog/api/RetailCatalogBusinessApi.ts +5 -3
- package/src/retailCatalog/api/interfaces/IRetailCatalogBusinessApi.ts +7 -6
- package/src/retailIntegration/api/RetailIntegrationConnectorApi.ts +53 -7
- package/src/retailIntegration/api/interfaces/IRetailIntegrationConnectorApi.ts +14 -0
- package/src/retailOrg/api/RetailOrgBusinessApi.ts +14 -4
- package/src/retailOrg/api/interfaces/IRetailOrgBusinessApi.ts +21 -1
|
@@ -39,7 +39,7 @@ export default class PlatformRbacBusinessApi implements IPlatformRbacBusinessApi
|
|
|
39
39
|
listLevelEntities(tenantId: string, level: PermissionScope, parentId?: string): Promise<APIGatewayProxyResultBody<ListLevelEntitiesResponse>>;
|
|
40
40
|
/** GET /internal/tenants/{tenantId}/levels/{level}/entities/{id} — detalle de un grupo. */
|
|
41
41
|
getLevelEntity(tenantId: string, level: PermissionScope, id: string): Promise<APIGatewayProxyResultBody<LevelEntityResponse>>;
|
|
42
|
-
/** PUT /internal/tenants/{tenantId}/levels/{level}/entities/{id} — renombra un grupo
|
|
42
|
+
/** PUT /internal/tenants/{tenantId}/levels/{level}/entities/{id} — renombra un grupo o lo mueve de padre con `parentId`. */
|
|
43
43
|
updateLevelEntity(tenantId: string, level: PermissionScope, id: string, input: UpdateLevelEntityRequest): Promise<APIGatewayProxyResultBody<LevelEntityResponse>>;
|
|
44
44
|
/** DELETE /internal/tenants/{tenantId}/levels/{level}/entities/{id} — borra un grupo. El `actedBy` viaja en el cuerpo. */
|
|
45
45
|
deleteLevelEntity(tenantId: string, level: PermissionScope, id: string, input: DeleteLevelEntityRequest): Promise<APIGatewayProxyResultBody<DeleteLevelEntityResponse>>;
|
|
@@ -111,7 +111,7 @@ let PlatformRbacBusinessApi = class PlatformRbacBusinessApi {
|
|
|
111
111
|
const url = `${this._levelEntitiesUrl(tenantId, level)}/${encodeURIComponent(id)}`;
|
|
112
112
|
return await this.httpRequest.get(url);
|
|
113
113
|
}
|
|
114
|
-
/** PUT /internal/tenants/{tenantId}/levels/{level}/entities/{id} — renombra un grupo
|
|
114
|
+
/** PUT /internal/tenants/{tenantId}/levels/{level}/entities/{id} — renombra un grupo o lo mueve de padre con `parentId`. */
|
|
115
115
|
async updateLevelEntity(tenantId, level, id, input) {
|
|
116
116
|
const url = `${this._levelEntitiesUrl(tenantId, level)}/${encodeURIComponent(id)}`;
|
|
117
117
|
return await this.httpRequest.put(url, input);
|
|
@@ -82,7 +82,7 @@ export interface IPlatformRbacBusinessApi {
|
|
|
82
82
|
listLevelEntities(tenantId: string, level: PermissionScope, parentId?: string): Promise<APIGatewayProxyResultBody<ListLevelEntitiesResponse>>;
|
|
83
83
|
/** GET /internal/tenants/{tenantId}/levels/{level}/entities/{id} — detalle de un grupo. */
|
|
84
84
|
getLevelEntity(tenantId: string, level: PermissionScope, id: string): Promise<APIGatewayProxyResultBody<LevelEntityResponse>>;
|
|
85
|
-
/** PUT /internal/tenants/{tenantId}/levels/{level}/entities/{id} — renombra un grupo
|
|
85
|
+
/** PUT /internal/tenants/{tenantId}/levels/{level}/entities/{id} — renombra un grupo o lo mueve de padre con `parentId`. */
|
|
86
86
|
updateLevelEntity(tenantId: string, level: PermissionScope, id: string, input: UpdateLevelEntityRequest): Promise<APIGatewayProxyResultBody<LevelEntityResponse>>;
|
|
87
87
|
/** DELETE /internal/tenants/{tenantId}/levels/{level}/entities/{id} — borra un grupo. El `actedBy` viaja en el cuerpo. */
|
|
88
88
|
deleteLevelEntity(tenantId: string, level: PermissionScope, id: string, input: DeleteLevelEntityRequest): Promise<APIGatewayProxyResultBody<DeleteLevelEntityResponse>>;
|
|
@@ -3,7 +3,7 @@ import { StandardResponse } from "@fiado/gateway-adapter";
|
|
|
3
3
|
import type { GetStoreStockCatalogResponse, HoldStockRequest, HoldStockResponse, InventoryLensQuery, InventoryLensResponse, ReleaseStockRequest, ReleaseStockResponse, RenewReservationsRequest, RenewReservationsResponse, ReserveStockRequest, ReserveStockResponse, ReturnStockRequest, ReturnStockResponse, SellStockRequest, SellStockResponse, SuggestPiecesQuery, SuggestPiecesResponse, SyncInventoryRequest, SyncInventoryResponse, ValidateProductResponse, StoreCatalogItem as StockCatalogItem } from "@fiado/type-kit/bin/retailCatalog/index.js";
|
|
4
4
|
import type { PaginatedResult } from "@fiado/type-kit/bin/retailOrg/index.js";
|
|
5
5
|
import type { ApplyInventoryEventRequest, ApplyInventoryEventResponse, ApplyProductEventRequest, ApplyProductEventResponse } from "@fiado/type-kit/bin/retailIntegration/index.js";
|
|
6
|
-
import { IRetailCatalogBusinessApi, ProductsByRetailersResponse, ReleaseReservationBody, ReserveInventoryBody, ReserveInventoryResult,
|
|
6
|
+
import { IRetailCatalogBusinessApi, ProductsByRetailersResponse, ReleaseReservationBody, ReserveInventoryBody, ReserveInventoryResult, SellInventoryInput, StoreCatalogItem } from "./interfaces/IRetailCatalogBusinessApi.js";
|
|
7
7
|
/**
|
|
8
8
|
* Publisher HTTP del lambda `retail-catalog-business` (SureKeep Fase 1, pista Retail) para sus
|
|
9
9
|
* endpoints privados del ciclo de venta del IMEI. Contrato y semántica completos →
|
|
@@ -26,7 +26,7 @@ export default class RetailCatalogBusinessApi implements IRetailCatalogBusinessA
|
|
|
26
26
|
validateProduct(retailerId: string, sku: string, issuer: string): Promise<StandardResponse<ValidateProductResponse>>;
|
|
27
27
|
getProductsByRetailers(retailerIds: string[], tenantId: string): Promise<StandardResponse<ProductsByRetailersResponse>>;
|
|
28
28
|
reserveInventory(imei: string, body: ReserveInventoryBody, issuer: string): Promise<StandardResponse<ReserveInventoryResult>>;
|
|
29
|
-
sellInventory(imei: string, body:
|
|
29
|
+
sellInventory(imei: string, body: SellInventoryInput, issuer: string): Promise<StandardResponse<void>>;
|
|
30
30
|
releaseInventory(imei: string, body: ReleaseReservationBody, issuer: string): Promise<StandardResponse<void>>;
|
|
31
31
|
returnInventory(imei: string, issuer: string): Promise<StandardResponse<void>>;
|
|
32
32
|
/** URL de una ruta de tienda con `tenantId` y los parámetros extra en query. */
|
|
@@ -60,7 +60,9 @@ let RetailCatalogBusinessApi = class RetailCatalogBusinessApi {
|
|
|
60
60
|
}
|
|
61
61
|
async sellInventory(imei, body, issuer) {
|
|
62
62
|
const url = `${this.baseUrl}/private/inventory/${encodeURIComponent(imei)}/sell`;
|
|
63
|
-
|
|
63
|
+
const { saleId, ...rest } = body;
|
|
64
|
+
const payload = saleId === undefined ? rest : { ...rest, saleId };
|
|
65
|
+
return await this.httpRequest.put(url, payload, this.tenantHeader(issuer));
|
|
64
66
|
}
|
|
65
67
|
async releaseInventory(imei, body, issuer) {
|
|
66
68
|
const url = `${this.baseUrl}/private/inventory/${encodeURIComponent(imei)}/release`;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { StandardResponse } from "@fiado/gateway-adapter";
|
|
2
|
-
import type { GetStoreStockCatalogResponse, HoldStockRequest, HoldStockResponse, InventoryLensQuery, InventoryLensResponse, MdmLockModeEnum, MdmProviderEnum, ReleaseStockRequest, ReleaseStockResponse, RenewReservationsRequest, RenewReservationsResponse, ReserveStockRequest, ReserveStockResponse, ReturnStockRequest, ReturnStockResponse, SellStockRequest, SellStockResponse, SuggestPiecesQuery, SuggestPiecesResponse, SyncInventoryRequest, StoreCatalogItem as StockCatalogItem, SyncInventoryResponse, ValidateProductResponse } from "@fiado/type-kit/bin/retailCatalog/index.js";
|
|
2
|
+
import type { GetStoreStockCatalogResponse, HoldStockRequest, HoldStockResponse, InventoryLensQuery, InventoryLensResponse, MdmLockModeEnum, MdmProviderEnum, ReleaseStockRequest, ReleaseStockResponse, RenewReservationsRequest, RenewReservationsResponse, ReserveStockRequest, ReserveStockResponse, ReturnStockRequest, ReturnStockResponse, SellStockRequest, SellStockResponse, SellInventoryRequest, SuggestPiecesQuery, SuggestPiecesResponse, SyncInventoryRequest, StoreCatalogItem as StockCatalogItem, SyncInventoryResponse, ValidateProductResponse } from "@fiado/type-kit/bin/retailCatalog/index.js";
|
|
3
3
|
import type { PaginatedResult } from "@fiado/type-kit/bin/retailOrg/index.js";
|
|
4
4
|
import type { ApplyInventoryEventRequest, ApplyInventoryEventResponse, ApplyProductEventRequest, ApplyProductEventResponse } from "@fiado/type-kit/bin/retailIntegration/index.js";
|
|
5
5
|
/**
|
|
@@ -93,11 +93,12 @@ export interface ReserveInventoryBody {
|
|
|
93
93
|
sku: string;
|
|
94
94
|
sessionId: string;
|
|
95
95
|
}
|
|
96
|
-
/** Body de PUT `/private/inventory/{imei}/sell` (
|
|
97
|
-
export
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
96
|
+
/** Body de PUT `/private/inventory/{imei}/sell`; `saleId` opcional mientras el wizard de main no lo mande (catalog lo exige en runtime). */
|
|
97
|
+
export type SellInventoryInput = Omit<SellInventoryRequest, 'saleId'> & {
|
|
98
|
+
saleId?: string;
|
|
99
|
+
};
|
|
100
|
+
/** Alias de `SellInventoryInput`; se conserva por compatibilidad con consumidores. */
|
|
101
|
+
export type SellInventoryBody = SellInventoryInput;
|
|
101
102
|
/** Body de PUT `/private/inventory/{imei}/release` (DEC-018 del destino: verifica titularidad de la sesión). */
|
|
102
103
|
export interface ReleaseReservationBody {
|
|
103
104
|
sessionId: string;
|
|
@@ -149,7 +150,7 @@ export interface IRetailCatalogBusinessApi {
|
|
|
149
150
|
/** PUT `/private/inventory/{imei}/reserve` — reserva atómica del IMEI para una sesión (AVAILABLE → RESERVED). */
|
|
150
151
|
reserveInventory(imei: string, body: ReserveInventoryBody, issuer: string): Promise<StandardResponse<ReserveInventoryResult>>;
|
|
151
152
|
/** PUT `/private/inventory/{imei}/sell` — vende el IMEI (RESERVED → SOLD). */
|
|
152
|
-
sellInventory(imei: string, body:
|
|
153
|
+
sellInventory(imei: string, body: SellInventoryInput, issuer: string): Promise<StandardResponse<void>>;
|
|
153
154
|
/** PUT `/private/inventory/{imei}/release` — libera la reserva (RESERVED → AVAILABLE, titularidad de la sesión). */
|
|
154
155
|
releaseInventory(imei: string, body: ReleaseReservationBody, issuer: string): Promise<StandardResponse<void>>;
|
|
155
156
|
/** PUT `/private/inventory/{imei}/return` — devuelve el IMEI vendido al stock (SOLD → AVAILABLE, sin body). */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { IHttpRequest } from "@fiado/http-client";
|
|
2
2
|
import { StandardResponse } from "@fiado/gateway-adapter";
|
|
3
|
-
import type { GetRetailInventoryRequest, GetRetailInventoryResponse, ListRetailCatalogRequest, ListRetailCatalogResponse, ListRetailStoresRequest, ListRetailStoresResponse, ListRetailUsersRequest, ListRetailUsersResponse, RegisterRetailSaleRequest, RegisterRetailSaleResponse, RetailSystemSale } from "@fiado/type-kit/bin/retailIntegration/index.js";
|
|
3
|
+
import type { CancelRetailSaleRequest, CancelRetailSaleResponse, CheckRetailInventoryRequest, CheckRetailInventoryResponse, GetRetailInventoryRequest, GetRetailInventoryResponse, ListRetailCatalogRequest, ListRetailCatalogResponse, ListRetailStoresRequest, ListRetailStoresResponse, ListRetailUsersRequest, ListRetailUsersResponse, RegisterRetailSaleRequest, RegisterRetailSaleResponse, RetailSystemSale, RetailTenantQuery } from "@fiado/type-kit/bin/retailIntegration/index.js";
|
|
4
4
|
import { IRetailIntegrationConnectorApi } from "./interfaces/IRetailIntegrationConnectorApi.js";
|
|
5
5
|
/** Publisher de la salida privada de `retail-integration-connector`. */
|
|
6
6
|
export default class RetailIntegrationConnectorApi implements IRetailIntegrationConnectorApi {
|
|
@@ -12,6 +12,10 @@ export default class RetailIntegrationConnectorApi implements IRetailIntegration
|
|
|
12
12
|
getRetailInventory(request: GetRetailInventoryRequest): Promise<StandardResponse<GetRetailInventoryResponse>>;
|
|
13
13
|
listRetailUsers(request: ListRetailUsersRequest): Promise<StandardResponse<ListRetailUsersResponse>>;
|
|
14
14
|
registerRetailSale(request: RegisterRetailSaleRequest, sale: RetailSystemSale): Promise<StandardResponse<RegisterRetailSaleResponse>>;
|
|
15
|
+
cancelRetailSale(query: RetailTenantQuery, cancellation: CancelRetailSaleRequest): Promise<StandardResponse<CancelRetailSaleResponse>>;
|
|
16
|
+
checkRetailInventory(request: CheckRetailInventoryRequest): Promise<StandardResponse<CheckRetailInventoryResponse>>;
|
|
15
17
|
private getWithTimeout;
|
|
18
|
+
private tenantQuery;
|
|
19
|
+
private listQuery;
|
|
16
20
|
private toQuery;
|
|
17
21
|
}
|
|
@@ -13,6 +13,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
13
13
|
import { inject, injectable } from "inversify";
|
|
14
14
|
/** Mayor que el Timeout de 10 s del connector, para no cortar una venta en vuelo. */
|
|
15
15
|
const RETAIL_INTEGRATION_CONNECTOR_TIMEOUT_MS = 12000;
|
|
16
|
+
/** Mayor que los 2.5 s del connector hacia el retailer; la consulta en vivo no debe frenar la venta. */
|
|
17
|
+
const RETAIL_LIVE_CHECK_TIMEOUT_MS = 3000;
|
|
16
18
|
/** Publisher de la salida privada de `retail-integration-connector`. */
|
|
17
19
|
let RetailIntegrationConnectorApi = class RetailIntegrationConnectorApi {
|
|
18
20
|
httpRequest;
|
|
@@ -22,42 +24,66 @@ let RetailIntegrationConnectorApi = class RetailIntegrationConnectorApi {
|
|
|
22
24
|
}
|
|
23
25
|
async listRetailStores(request) {
|
|
24
26
|
return await this.getWithTimeout("/private/retail/stores", {
|
|
25
|
-
|
|
27
|
+
...this.listQuery(request),
|
|
26
28
|
limit: request.limit,
|
|
27
29
|
nextToken: request.nextToken,
|
|
28
30
|
});
|
|
29
31
|
}
|
|
30
32
|
async listRetailCatalog(request) {
|
|
31
33
|
return await this.getWithTimeout("/private/retail/catalog", {
|
|
32
|
-
|
|
34
|
+
...this.listQuery(request),
|
|
33
35
|
limit: request.limit,
|
|
34
36
|
nextToken: request.nextToken,
|
|
35
37
|
});
|
|
36
38
|
}
|
|
37
39
|
async getRetailInventory(request) {
|
|
38
40
|
return await this.getWithTimeout("/private/retail/inventory", {
|
|
39
|
-
|
|
41
|
+
...this.tenantQuery(request),
|
|
40
42
|
storeId: request.storeId,
|
|
43
|
+
runId: request.runId,
|
|
41
44
|
});
|
|
42
45
|
}
|
|
43
46
|
async listRetailUsers(request) {
|
|
44
47
|
return await this.getWithTimeout("/private/retail/users", {
|
|
45
|
-
|
|
48
|
+
...this.tenantQuery(request),
|
|
46
49
|
storeId: request.storeId,
|
|
50
|
+
runId: request.runId,
|
|
47
51
|
limit: request.limit,
|
|
48
52
|
nextToken: request.nextToken,
|
|
49
53
|
});
|
|
50
54
|
}
|
|
51
55
|
async registerRetailSale(request, sale) {
|
|
52
|
-
const url = `${this.baseUrl}/private/retail/sales?${this.toQuery(
|
|
56
|
+
const url = `${this.baseUrl}/private/retail/sales?${this.toQuery(this.tenantQuery(request))}`;
|
|
53
57
|
return await this.httpRequest.post(url, sale, {}, undefined, false, {
|
|
54
58
|
timeout: RETAIL_INTEGRATION_CONNECTOR_TIMEOUT_MS,
|
|
55
59
|
});
|
|
56
60
|
}
|
|
61
|
+
async cancelRetailSale(query, cancellation) {
|
|
62
|
+
const url = `${this.baseUrl}/private/retail/sales/cancel?${this.toQuery(this.tenantQuery(query))}`;
|
|
63
|
+
return await this.httpRequest.post(url, cancellation, {}, undefined, false, {
|
|
64
|
+
timeout: RETAIL_INTEGRATION_CONNECTOR_TIMEOUT_MS,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
async checkRetailInventory(request) {
|
|
68
|
+
const fields = {
|
|
69
|
+
...this.tenantQuery(request),
|
|
70
|
+
storeId: request.storeId,
|
|
71
|
+
identifiers: request.identifiers.join(","),
|
|
72
|
+
sessionId: request.sessionId,
|
|
73
|
+
};
|
|
74
|
+
return await this.getWithTimeout("/private/retail/inventory/live-check", fields, RETAIL_LIVE_CHECK_TIMEOUT_MS);
|
|
75
|
+
}
|
|
57
76
|
// GET con timeout propio; nunca `enableTimeout`, que tomaría el timeout corto del consumidor.
|
|
58
|
-
async getWithTimeout(path, fields) {
|
|
77
|
+
async getWithTimeout(path, fields, timeout = RETAIL_INTEGRATION_CONNECTOR_TIMEOUT_MS) {
|
|
59
78
|
const url = `${this.baseUrl}${path}?${this.toQuery(fields)}`;
|
|
60
|
-
return await this.httpRequest.get(url, {}, {}, undefined, { timeout
|
|
79
|
+
return await this.httpRequest.get(url, {}, {}, undefined, { timeout }, false);
|
|
80
|
+
}
|
|
81
|
+
// El connector coteja tenantId y retailerId contra el secreto del tenant.
|
|
82
|
+
tenantQuery(query) {
|
|
83
|
+
return { tenantId: query.tenantId, retailerId: query.retailerId };
|
|
84
|
+
}
|
|
85
|
+
listQuery(query) {
|
|
86
|
+
return { ...this.tenantQuery(query), runId: query.runId };
|
|
61
87
|
}
|
|
62
88
|
toQuery(fields) {
|
|
63
89
|
const params = new URLSearchParams();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { StandardResponse } from "@fiado/gateway-adapter";
|
|
2
|
-
import type { GetRetailInventoryRequest, GetRetailInventoryResponse, ListRetailCatalogRequest, ListRetailCatalogResponse, ListRetailStoresRequest, ListRetailStoresResponse, ListRetailUsersRequest, ListRetailUsersResponse, RegisterRetailSaleRequest, RegisterRetailSaleResponse, RetailSystemSale } from "@fiado/type-kit/bin/retailIntegration/index.js";
|
|
2
|
+
import type { CancelRetailSaleRequest, CancelRetailSaleResponse, CheckRetailInventoryRequest, CheckRetailInventoryResponse, GetRetailInventoryRequest, GetRetailInventoryResponse, ListRetailCatalogRequest, ListRetailCatalogResponse, ListRetailStoresRequest, ListRetailStoresResponse, ListRetailUsersRequest, ListRetailUsersResponse, RegisterRetailSaleRequest, RegisterRetailSaleResponse, RetailSystemSale, RetailTenantQuery } from "@fiado/type-kit/bin/retailIntegration/index.js";
|
|
3
3
|
/**
|
|
4
4
|
* Salida privada de `retail-integration-connector` hacia el sistema del retailer del tenant.
|
|
5
5
|
* Env var del consumidor: `RETAIL_INTEGRATION_CONNECTOR_URL: '{{resolve:ssm:retail-integration-connector}}'`.
|
|
@@ -15,4 +15,8 @@ export interface IRetailIntegrationConnectorApi {
|
|
|
15
15
|
listRetailUsers(request: ListRetailUsersRequest): Promise<StandardResponse<ListRetailUsersResponse>>;
|
|
16
16
|
/** `POST /private/retail/sales` — registra la venta; ante timeout o 502, reintenta con el mismo `saleId`. */
|
|
17
17
|
registerRetailSale(request: RegisterRetailSaleRequest, sale: RetailSystemSale): Promise<StandardResponse<RegisterRetailSaleResponse>>;
|
|
18
|
+
/** `POST /private/retail/sales/cancel` — cancela la venta con el mismo `saleId` del registro; 12 s. */
|
|
19
|
+
cancelRetailSale(query: RetailTenantQuery, cancellation: CancelRetailSaleRequest): Promise<StandardResponse<CancelRetailSaleResponse>>;
|
|
20
|
+
/** `GET /private/retail/inventory/live-check` — qué identificadores lista hoy la tienda; 3 s. */
|
|
21
|
+
checkRetailInventory(request: CheckRetailInventoryRequest): Promise<StandardResponse<CheckRetailInventoryResponse>>;
|
|
18
22
|
}
|
|
@@ -2,7 +2,7 @@ import type { IHttpRequest } from "@fiado/http-client";
|
|
|
2
2
|
import { StandardResponse } from "@fiado/gateway-adapter";
|
|
3
3
|
import { RetailerValidationDto, StoreValidationDto, RetailUserValidationDto, CollectorValidationDto, PrivateSellerListResponse, PrivateGoalListResponse, GoalTargetTypeEnum, RetailUserStatusEnum, PrivateRetailUserWalletResponse } from "@fiado/type-kit/bin/retailOrg/index.js";
|
|
4
4
|
import type { ApplyRetailUserEventRequest, ApplyRetailUserEventResponse, ApplyStoreEventRequest, ApplyStoreEventResponse } from "@fiado/type-kit/bin/retailIntegration/index.js";
|
|
5
|
-
import { IRetailOrgBusinessApi, RetailerRosterStatusFilter, StoreRosterStatusFilter } from "./interfaces/IRetailOrgBusinessApi.js";
|
|
5
|
+
import { IRetailOrgBusinessApi, RetailOrgRequestOptions, RetailerRosterStatusFilter, StoreRosterStatusFilter } from "./interfaces/IRetailOrgBusinessApi.js";
|
|
6
6
|
/**
|
|
7
7
|
* Publisher HTTP del lambda `retail-org-business` (componente 04 SureKeep Fase 1) para sus 9
|
|
8
8
|
* endpoints privados de validación. Contrato y semántica completos → `IRetailOrgBusinessApi`.
|
|
@@ -27,8 +27,10 @@ export default class RetailOrgBusinessApi implements IRetailOrgBusinessApi {
|
|
|
27
27
|
* qué `status` SÍ tiene default y por qué acá el estado es el CRUDO, sin cascada del padre)
|
|
28
28
|
* → `IRetailOrgBusinessApi.listRetailers`.
|
|
29
29
|
*/
|
|
30
|
-
listRetailers(tenantId: string, status?: RetailerRosterStatusFilter): Promise<StandardResponse<RetailerValidationDto[]>>;
|
|
31
|
-
getRetailer(retailerId: string, tenantId: string): Promise<StandardResponse<RetailerValidationDto>>;
|
|
30
|
+
listRetailers(tenantId: string, status?: RetailerRosterStatusFilter, integrated?: boolean, options?: RetailOrgRequestOptions): Promise<StandardResponse<RetailerValidationDto[]>>;
|
|
31
|
+
getRetailer(retailerId: string, tenantId: string, options?: RetailOrgRequestOptions): Promise<StandardResponse<RetailerValidationDto>>;
|
|
32
|
+
/** Aplica el timeout solo si el caller lo pide; sin él, el GET queda igual que siempre. */
|
|
33
|
+
private getWithOptionalTimeout;
|
|
32
34
|
getRetailerByStore(storeId: string, tenantId: string): Promise<StandardResponse<RetailerValidationDto>>;
|
|
33
35
|
getStore(retailerId: string, storeId: string, tenantId: string): Promise<StandardResponse<StoreValidationDto>>;
|
|
34
36
|
/**
|
|
@@ -37,17 +37,24 @@ let RetailOrgBusinessApi = class RetailOrgBusinessApi {
|
|
|
37
37
|
* qué `status` SÍ tiene default y por qué acá el estado es el CRUDO, sin cascada del padre)
|
|
38
38
|
* → `IRetailOrgBusinessApi.listRetailers`.
|
|
39
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.
|
|
40
|
+
async listRetailers(tenantId, status, integrated, options) {
|
|
43
41
|
const query = new URLSearchParams({ tenantId });
|
|
44
42
|
if (status)
|
|
45
43
|
query.set("status", status);
|
|
46
|
-
|
|
44
|
+
if (integrated !== undefined)
|
|
45
|
+
query.set("integrated", String(integrated));
|
|
46
|
+
const url = `${this.baseUrl}/private/retailers?${query.toString()}`;
|
|
47
|
+
return await this.getWithOptionalTimeout(url, options);
|
|
47
48
|
}
|
|
48
|
-
async getRetailer(retailerId, tenantId) {
|
|
49
|
+
async getRetailer(retailerId, tenantId, options) {
|
|
49
50
|
const url = `${this.baseUrl}/private/retailers/${encodeURIComponent(retailerId)}?tenantId=${encodeURIComponent(tenantId)}`;
|
|
50
|
-
return await this.
|
|
51
|
+
return await this.getWithOptionalTimeout(url, options);
|
|
52
|
+
}
|
|
53
|
+
/** Aplica el timeout solo si el caller lo pide; sin él, el GET queda igual que siempre. */
|
|
54
|
+
async getWithOptionalTimeout(url, options) {
|
|
55
|
+
if (options?.timeoutMs === undefined)
|
|
56
|
+
return await this.httpRequest.get(url);
|
|
57
|
+
return await this.httpRequest.get(url, undefined, undefined, undefined, { timeout: options.timeoutMs });
|
|
51
58
|
}
|
|
52
59
|
async getRetailerByStore(storeId, tenantId) {
|
|
53
60
|
const url = `${this.baseUrl}/private/retailers/by-store/${encodeURIComponent(storeId)}?tenantId=${encodeURIComponent(tenantId)}`;
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { StandardResponse } from "@fiado/gateway-adapter";
|
|
2
2
|
import { RetailerValidationDto, StoreValidationDto, RetailUserValidationDto, CollectorValidationDto, PrivateSellerListResponse, PrivateGoalListResponse, GoalTargetTypeEnum, RetailUserStatusEnum, RetailerStatusEnum, StoreStatusEnum, PrivateRetailUserWalletResponse } from "@fiado/type-kit/bin/retailOrg/index.js";
|
|
3
3
|
import type { ApplyRetailUserEventRequest, ApplyRetailUserEventResponse, ApplyStoreEventRequest, ApplyStoreEventResponse } from "@fiado/type-kit/bin/retailIntegration/index.js";
|
|
4
|
+
/** Timeout que el connector y el wizard pasan a `getRetailer`: cabe en los 3 s por evento del connector. */
|
|
5
|
+
export declare const RETAIL_ORG_GET_RETAILER_TIMEOUT_MS = 1500;
|
|
6
|
+
/** Timeout que el connector pasa a `listRetailers`: el padrón trae el árbol completo del silo. */
|
|
7
|
+
export declare const RETAIL_ORG_LIST_RETAILERS_TIMEOUT_MS = 5000;
|
|
8
|
+
/** Opciones por llamada. Sin `timeoutMs` no se aplica timeout propio. */
|
|
9
|
+
export interface RetailOrgRequestOptions {
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
}
|
|
4
12
|
/**
|
|
5
13
|
* Filtro de `listStoresByRetailer`. `"ALL"` no es un estado de tienda: es la ausencia de filtro, y
|
|
6
14
|
* va en el MISMO parámetro que los estados porque los dos hablan del mismo eje — un segundo flag
|
|
@@ -87,17 +95,23 @@ export interface IRetailOrgBusinessApi {
|
|
|
87
95
|
* Devuelve `[]` si ningún retailer pasa el filtro. **No hay 404**: el silo siempre existe — lo
|
|
88
96
|
* garantiza el `tenantId`, que es lo que resolvió el contexto del tenant.
|
|
89
97
|
*
|
|
98
|
+
* `integrated = true` deja solo los retailers con la bandera de integración prendida; cada
|
|
99
|
+
* retailer trae `integrationSystem` e `integrationActivatedAt` cuando la tiene. Timeout opt-in vía
|
|
100
|
+
* `options.timeoutMs` (ver `RETAIL_ORG_LIST_RETAILERS_TIMEOUT_MS`).
|
|
101
|
+
*
|
|
90
102
|
* @throws `400 RETAILER_STATUS_FILTER_INVALID` si `status` no es del catálogo ·
|
|
91
103
|
* `400 UNKNOWN_TENANT` sin `tenantId`.
|
|
92
104
|
*/
|
|
93
|
-
listRetailers(tenantId: string, status?: RetailerRosterStatusFilter): Promise<StandardResponse<RetailerValidationDto[]>>;
|
|
105
|
+
listRetailers(tenantId: string, status?: RetailerRosterStatusFilter, integrated?: boolean, options?: RetailOrgRequestOptions): Promise<StandardResponse<RetailerValidationDto[]>>;
|
|
94
106
|
/**
|
|
95
107
|
* GET /private/retailers/{retailerId} — valida que el retailer exista y devuelve su shape mínimo
|
|
96
|
-
* (id, name, type, status, parentId). `status` ya viene con la cascada
|
|
108
|
+
* (id, name, type, status, parentId) y la bandera de integración. `status` ya viene con la cascada
|
|
109
|
+
* aplicada (estado efectivo). Timeout opt-in vía `options.timeoutMs` (ver
|
|
110
|
+
* `RETAIL_ORG_GET_RETAILER_TIMEOUT_MS`).
|
|
97
111
|
*
|
|
98
112
|
* @throws si el retailer no existe (`404 RETAILER_NOT_FOUND`).
|
|
99
113
|
*/
|
|
100
|
-
getRetailer(retailerId: string, tenantId: string): Promise<StandardResponse<RetailerValidationDto>>;
|
|
114
|
+
getRetailer(retailerId: string, tenantId: string, options?: RetailOrgRequestOptions): Promise<StandardResponse<RetailerValidationDto>>;
|
|
101
115
|
/**
|
|
102
116
|
* GET /private/retailers/by-store/{storeId} — resuelve el retailer DUEÑO de una tienda teniendo
|
|
103
117
|
* SOLO el `storeId`, sin conocer el retailer. Es el único privado que no va anidado, porque es el
|
|
@@ -1 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
/** Timeout que el connector y el wizard pasan a `getRetailer`: cabe en los 3 s por evento del connector. */
|
|
2
|
+
export const RETAIL_ORG_GET_RETAILER_TIMEOUT_MS = 1500;
|
|
3
|
+
/** Timeout que el connector pasa a `listRetailers`: el padrón trae el árbol completo del silo. */
|
|
4
|
+
export const RETAIL_ORG_LIST_RETAILERS_TIMEOUT_MS = 5000;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fiado/api-invoker",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.144.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",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@fiado/gateway-adapter": "^3.14.0",
|
|
35
35
|
"@fiado/http-client": "^2.0.1",
|
|
36
36
|
"@fiado/logger": "^1.1.3",
|
|
37
|
-
"@fiado/type-kit": "^3.
|
|
37
|
+
"@fiado/type-kit": "^3.579.0",
|
|
38
38
|
"dotenv": "^16.4.7"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
@@ -204,7 +204,7 @@ export default class PlatformRbacBusinessApi implements IPlatformRbacBusinessApi
|
|
|
204
204
|
return await this.httpRequest.get(url);
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
-
/** PUT /internal/tenants/{tenantId}/levels/{level}/entities/{id} — renombra un grupo
|
|
207
|
+
/** PUT /internal/tenants/{tenantId}/levels/{level}/entities/{id} — renombra un grupo o lo mueve de padre con `parentId`. */
|
|
208
208
|
async updateLevelEntity(
|
|
209
209
|
tenantId: string,
|
|
210
210
|
level: PermissionScope,
|
|
@@ -174,7 +174,7 @@ export interface IPlatformRbacBusinessApi {
|
|
|
174
174
|
id: string,
|
|
175
175
|
): Promise<APIGatewayProxyResultBody<LevelEntityResponse>>;
|
|
176
176
|
|
|
177
|
-
/** PUT /internal/tenants/{tenantId}/levels/{level}/entities/{id} — renombra un grupo
|
|
177
|
+
/** PUT /internal/tenants/{tenantId}/levels/{level}/entities/{id} — renombra un grupo o lo mueve de padre con `parentId`. */
|
|
178
178
|
updateLevelEntity(
|
|
179
179
|
tenantId: string,
|
|
180
180
|
level: PermissionScope,
|
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
ReserveInventoryBody,
|
|
42
42
|
ReserveInventoryResult,
|
|
43
43
|
RETAILER_PRODUCTS_BATCH_MAX,
|
|
44
|
-
|
|
44
|
+
SellInventoryInput,
|
|
45
45
|
StoreCatalogItem,
|
|
46
46
|
} from "./interfaces/IRetailCatalogBusinessApi.js";
|
|
47
47
|
|
|
@@ -114,9 +114,11 @@ export default class RetailCatalogBusinessApi implements IRetailCatalogBusinessA
|
|
|
114
114
|
return await this.httpRequest.put(url, body, this.tenantHeader(issuer));
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
async sellInventory(imei: string, body:
|
|
117
|
+
async sellInventory(imei: string, body: SellInventoryInput, issuer: string): Promise<StandardResponse<void>> {
|
|
118
118
|
const url = `${this.baseUrl}/private/inventory/${encodeURIComponent(imei)}/sell`;
|
|
119
|
-
|
|
119
|
+
const { saleId, ...rest } = body;
|
|
120
|
+
const payload = saleId === undefined ? rest : { ...rest, saleId };
|
|
121
|
+
return await this.httpRequest.put(url, payload, this.tenantHeader(issuer));
|
|
120
122
|
}
|
|
121
123
|
|
|
122
124
|
async releaseInventory(imei: string, body: ReleaseReservationBody, issuer: string): Promise<StandardResponse<void>> {
|
|
@@ -17,6 +17,7 @@ import type {
|
|
|
17
17
|
ReturnStockResponse,
|
|
18
18
|
SellStockRequest,
|
|
19
19
|
SellStockResponse,
|
|
20
|
+
SellInventoryRequest,
|
|
20
21
|
SuggestPiecesQuery,
|
|
21
22
|
SuggestPiecesResponse,
|
|
22
23
|
SyncInventoryRequest,
|
|
@@ -137,11 +138,11 @@ export interface ReserveInventoryBody {
|
|
|
137
138
|
sessionId: string;
|
|
138
139
|
}
|
|
139
140
|
|
|
140
|
-
/** Body de PUT `/private/inventory/{imei}/sell` (
|
|
141
|
-
export
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
141
|
+
/** Body de PUT `/private/inventory/{imei}/sell`; `saleId` opcional mientras el wizard de main no lo mande (catalog lo exige en runtime). */
|
|
142
|
+
export type SellInventoryInput = Omit<SellInventoryRequest, 'saleId'> & { saleId?: string };
|
|
143
|
+
|
|
144
|
+
/** Alias de `SellInventoryInput`; se conserva por compatibilidad con consumidores. */
|
|
145
|
+
export type SellInventoryBody = SellInventoryInput;
|
|
145
146
|
|
|
146
147
|
/** Body de PUT `/private/inventory/{imei}/release` (DEC-018 del destino: verifica titularidad de la sesión). */
|
|
147
148
|
export interface ReleaseReservationBody {
|
|
@@ -206,7 +207,7 @@ export interface IRetailCatalogBusinessApi {
|
|
|
206
207
|
reserveInventory(imei: string, body: ReserveInventoryBody, issuer: string): Promise<StandardResponse<ReserveInventoryResult>>;
|
|
207
208
|
|
|
208
209
|
/** PUT `/private/inventory/{imei}/sell` — vende el IMEI (RESERVED → SOLD). */
|
|
209
|
-
sellInventory(imei: string, body:
|
|
210
|
+
sellInventory(imei: string, body: SellInventoryInput, issuer: string): Promise<StandardResponse<void>>;
|
|
210
211
|
|
|
211
212
|
/** PUT `/private/inventory/{imei}/release` — libera la reserva (RESERVED → AVAILABLE, titularidad de la sesión). */
|
|
212
213
|
releaseInventory(imei: string, body: ReleaseReservationBody, issuer: string): Promise<StandardResponse<void>>;
|
|
@@ -2,6 +2,10 @@ import { inject, injectable } from "inversify";
|
|
|
2
2
|
import type { IHttpRequest } from "@fiado/http-client";
|
|
3
3
|
import { StandardResponse } from "@fiado/gateway-adapter";
|
|
4
4
|
import type {
|
|
5
|
+
CancelRetailSaleRequest,
|
|
6
|
+
CancelRetailSaleResponse,
|
|
7
|
+
CheckRetailInventoryRequest,
|
|
8
|
+
CheckRetailInventoryResponse,
|
|
5
9
|
GetRetailInventoryRequest,
|
|
6
10
|
GetRetailInventoryResponse,
|
|
7
11
|
ListRetailCatalogRequest,
|
|
@@ -12,13 +16,18 @@ import type {
|
|
|
12
16
|
ListRetailUsersResponse,
|
|
13
17
|
RegisterRetailSaleRequest,
|
|
14
18
|
RegisterRetailSaleResponse,
|
|
19
|
+
RetailListQuery,
|
|
15
20
|
RetailSystemSale,
|
|
21
|
+
RetailTenantQuery,
|
|
16
22
|
} from "@fiado/type-kit/bin/retailIntegration/index.js";
|
|
17
23
|
import { IRetailIntegrationConnectorApi } from "./interfaces/IRetailIntegrationConnectorApi.js";
|
|
18
24
|
|
|
19
25
|
/** Mayor que el Timeout de 10 s del connector, para no cortar una venta en vuelo. */
|
|
20
26
|
const RETAIL_INTEGRATION_CONNECTOR_TIMEOUT_MS = 12000;
|
|
21
27
|
|
|
28
|
+
/** Mayor que los 2.5 s del connector hacia el retailer; la consulta en vivo no debe frenar la venta. */
|
|
29
|
+
const RETAIL_LIVE_CHECK_TIMEOUT_MS = 3000;
|
|
30
|
+
|
|
22
31
|
type QueryFields = Record<string, string | number | undefined>;
|
|
23
32
|
|
|
24
33
|
/** Publisher de la salida privada de `retail-integration-connector`. */
|
|
@@ -30,7 +39,7 @@ export default class RetailIntegrationConnectorApi implements IRetailIntegration
|
|
|
30
39
|
|
|
31
40
|
async listRetailStores(request: ListRetailStoresRequest): Promise<StandardResponse<ListRetailStoresResponse>> {
|
|
32
41
|
return await this.getWithTimeout("/private/retail/stores", {
|
|
33
|
-
|
|
42
|
+
...this.listQuery(request),
|
|
34
43
|
limit: request.limit,
|
|
35
44
|
nextToken: request.nextToken,
|
|
36
45
|
});
|
|
@@ -38,7 +47,7 @@ export default class RetailIntegrationConnectorApi implements IRetailIntegration
|
|
|
38
47
|
|
|
39
48
|
async listRetailCatalog(request: ListRetailCatalogRequest): Promise<StandardResponse<ListRetailCatalogResponse>> {
|
|
40
49
|
return await this.getWithTimeout("/private/retail/catalog", {
|
|
41
|
-
|
|
50
|
+
...this.listQuery(request),
|
|
42
51
|
limit: request.limit,
|
|
43
52
|
nextToken: request.nextToken,
|
|
44
53
|
});
|
|
@@ -46,15 +55,17 @@ export default class RetailIntegrationConnectorApi implements IRetailIntegration
|
|
|
46
55
|
|
|
47
56
|
async getRetailInventory(request: GetRetailInventoryRequest): Promise<StandardResponse<GetRetailInventoryResponse>> {
|
|
48
57
|
return await this.getWithTimeout("/private/retail/inventory", {
|
|
49
|
-
|
|
58
|
+
...this.tenantQuery(request),
|
|
50
59
|
storeId: request.storeId,
|
|
60
|
+
runId: request.runId,
|
|
51
61
|
});
|
|
52
62
|
}
|
|
53
63
|
|
|
54
64
|
async listRetailUsers(request: ListRetailUsersRequest): Promise<StandardResponse<ListRetailUsersResponse>> {
|
|
55
65
|
return await this.getWithTimeout("/private/retail/users", {
|
|
56
|
-
|
|
66
|
+
...this.tenantQuery(request),
|
|
57
67
|
storeId: request.storeId,
|
|
68
|
+
runId: request.runId,
|
|
58
69
|
limit: request.limit,
|
|
59
70
|
nextToken: request.nextToken,
|
|
60
71
|
});
|
|
@@ -64,16 +75,51 @@ export default class RetailIntegrationConnectorApi implements IRetailIntegration
|
|
|
64
75
|
request: RegisterRetailSaleRequest,
|
|
65
76
|
sale: RetailSystemSale,
|
|
66
77
|
): Promise<StandardResponse<RegisterRetailSaleResponse>> {
|
|
67
|
-
const url = `${this.baseUrl}/private/retail/sales?${this.toQuery(
|
|
78
|
+
const url = `${this.baseUrl}/private/retail/sales?${this.toQuery(this.tenantQuery(request))}`;
|
|
68
79
|
return await this.httpRequest.post(url, sale, {}, undefined, false, {
|
|
69
80
|
timeout: RETAIL_INTEGRATION_CONNECTOR_TIMEOUT_MS,
|
|
70
81
|
});
|
|
71
82
|
}
|
|
72
83
|
|
|
84
|
+
async cancelRetailSale(
|
|
85
|
+
query: RetailTenantQuery,
|
|
86
|
+
cancellation: CancelRetailSaleRequest,
|
|
87
|
+
): Promise<StandardResponse<CancelRetailSaleResponse>> {
|
|
88
|
+
const url = `${this.baseUrl}/private/retail/sales/cancel?${this.toQuery(this.tenantQuery(query))}`;
|
|
89
|
+
return await this.httpRequest.post(url, cancellation, {}, undefined, false, {
|
|
90
|
+
timeout: RETAIL_INTEGRATION_CONNECTOR_TIMEOUT_MS,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async checkRetailInventory(
|
|
95
|
+
request: CheckRetailInventoryRequest,
|
|
96
|
+
): Promise<StandardResponse<CheckRetailInventoryResponse>> {
|
|
97
|
+
const fields = {
|
|
98
|
+
...this.tenantQuery(request),
|
|
99
|
+
storeId: request.storeId,
|
|
100
|
+
identifiers: request.identifiers.join(","),
|
|
101
|
+
sessionId: request.sessionId,
|
|
102
|
+
};
|
|
103
|
+
return await this.getWithTimeout("/private/retail/inventory/live-check", fields, RETAIL_LIVE_CHECK_TIMEOUT_MS);
|
|
104
|
+
}
|
|
105
|
+
|
|
73
106
|
// GET con timeout propio; nunca `enableTimeout`, que tomaría el timeout corto del consumidor.
|
|
74
|
-
private async getWithTimeout<T>(
|
|
107
|
+
private async getWithTimeout<T>(
|
|
108
|
+
path: string,
|
|
109
|
+
fields: QueryFields,
|
|
110
|
+
timeout = RETAIL_INTEGRATION_CONNECTOR_TIMEOUT_MS,
|
|
111
|
+
): Promise<StandardResponse<T>> {
|
|
75
112
|
const url = `${this.baseUrl}${path}?${this.toQuery(fields)}`;
|
|
76
|
-
return await this.httpRequest.get(url, {}, {}, undefined, { timeout
|
|
113
|
+
return await this.httpRequest.get(url, {}, {}, undefined, { timeout }, false);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// El connector coteja tenantId y retailerId contra el secreto del tenant.
|
|
117
|
+
private tenantQuery(query: RetailTenantQuery): QueryFields {
|
|
118
|
+
return { tenantId: query.tenantId, retailerId: query.retailerId };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private listQuery(query: RetailListQuery): QueryFields {
|
|
122
|
+
return { ...this.tenantQuery(query), runId: query.runId };
|
|
77
123
|
}
|
|
78
124
|
|
|
79
125
|
private toQuery(fields: QueryFields): string {
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { StandardResponse } from "@fiado/gateway-adapter";
|
|
2
2
|
import type {
|
|
3
|
+
CancelRetailSaleRequest,
|
|
4
|
+
CancelRetailSaleResponse,
|
|
5
|
+
CheckRetailInventoryRequest,
|
|
6
|
+
CheckRetailInventoryResponse,
|
|
3
7
|
GetRetailInventoryRequest,
|
|
4
8
|
GetRetailInventoryResponse,
|
|
5
9
|
ListRetailCatalogRequest,
|
|
@@ -11,6 +15,7 @@ import type {
|
|
|
11
15
|
RegisterRetailSaleRequest,
|
|
12
16
|
RegisterRetailSaleResponse,
|
|
13
17
|
RetailSystemSale,
|
|
18
|
+
RetailTenantQuery,
|
|
14
19
|
} from "@fiado/type-kit/bin/retailIntegration/index.js";
|
|
15
20
|
|
|
16
21
|
/**
|
|
@@ -35,4 +40,13 @@ export interface IRetailIntegrationConnectorApi {
|
|
|
35
40
|
request: RegisterRetailSaleRequest,
|
|
36
41
|
sale: RetailSystemSale,
|
|
37
42
|
): Promise<StandardResponse<RegisterRetailSaleResponse>>;
|
|
43
|
+
|
|
44
|
+
/** `POST /private/retail/sales/cancel` — cancela la venta con el mismo `saleId` del registro; 12 s. */
|
|
45
|
+
cancelRetailSale(
|
|
46
|
+
query: RetailTenantQuery,
|
|
47
|
+
cancellation: CancelRetailSaleRequest,
|
|
48
|
+
): Promise<StandardResponse<CancelRetailSaleResponse>>;
|
|
49
|
+
|
|
50
|
+
/** `GET /private/retail/inventory/live-check` — qué identificadores lista hoy la tienda; 3 s. */
|
|
51
|
+
checkRetailInventory(request: CheckRetailInventoryRequest): Promise<StandardResponse<CheckRetailInventoryResponse>>;
|
|
38
52
|
}
|
|
@@ -22,6 +22,7 @@ import type {
|
|
|
22
22
|
} from "@fiado/type-kit/bin/retailIntegration/index.js";
|
|
23
23
|
import {
|
|
24
24
|
IRetailOrgBusinessApi,
|
|
25
|
+
RetailOrgRequestOptions,
|
|
25
26
|
RetailerRosterStatusFilter,
|
|
26
27
|
StoreRosterStatusFilter,
|
|
27
28
|
} from "./interfaces/IRetailOrgBusinessApi.js";
|
|
@@ -55,20 +56,29 @@ export default class RetailOrgBusinessApi implements IRetailOrgBusinessApi {
|
|
|
55
56
|
async listRetailers(
|
|
56
57
|
tenantId: string,
|
|
57
58
|
status?: RetailerRosterStatusFilter,
|
|
59
|
+
integrated?: boolean,
|
|
60
|
+
options?: RetailOrgRequestOptions,
|
|
58
61
|
): Promise<StandardResponse<RetailerValidationDto[]>> {
|
|
59
|
-
// `URLSearchParams` en vez de concatenar: `status` es opcional y armar el `&status=` a mano
|
|
60
|
-
// deja un `&status=undefined` en cuanto alguien se distrae.
|
|
61
62
|
const query = new URLSearchParams({ tenantId });
|
|
62
63
|
if (status) query.set("status", status);
|
|
63
|
-
|
|
64
|
+
if (integrated !== undefined) query.set("integrated", String(integrated));
|
|
65
|
+
const url = `${this.baseUrl}/private/retailers?${query.toString()}`;
|
|
66
|
+
return await this.getWithOptionalTimeout(url, options);
|
|
64
67
|
}
|
|
65
68
|
|
|
66
69
|
async getRetailer(
|
|
67
70
|
retailerId: string,
|
|
68
71
|
tenantId: string,
|
|
72
|
+
options?: RetailOrgRequestOptions,
|
|
69
73
|
): Promise<StandardResponse<RetailerValidationDto>> {
|
|
70
74
|
const url = `${this.baseUrl}/private/retailers/${encodeURIComponent(retailerId)}?tenantId=${encodeURIComponent(tenantId)}`;
|
|
71
|
-
return await this.
|
|
75
|
+
return await this.getWithOptionalTimeout(url, options);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Aplica el timeout solo si el caller lo pide; sin él, el GET queda igual que siempre. */
|
|
79
|
+
private async getWithOptionalTimeout<T>(url: string, options?: RetailOrgRequestOptions): Promise<StandardResponse<T>> {
|
|
80
|
+
if (options?.timeoutMs === undefined) return await this.httpRequest.get(url);
|
|
81
|
+
return await this.httpRequest.get(url, undefined, undefined, undefined, { timeout: options.timeoutMs });
|
|
72
82
|
}
|
|
73
83
|
|
|
74
84
|
async getRetailerByStore(
|
|
@@ -19,6 +19,17 @@ import type {
|
|
|
19
19
|
ApplyStoreEventResponse,
|
|
20
20
|
} from "@fiado/type-kit/bin/retailIntegration/index.js";
|
|
21
21
|
|
|
22
|
+
/** Timeout que el connector y el wizard pasan a `getRetailer`: cabe en los 3 s por evento del connector. */
|
|
23
|
+
export const RETAIL_ORG_GET_RETAILER_TIMEOUT_MS = 1500;
|
|
24
|
+
|
|
25
|
+
/** Timeout que el connector pasa a `listRetailers`: el padrón trae el árbol completo del silo. */
|
|
26
|
+
export const RETAIL_ORG_LIST_RETAILERS_TIMEOUT_MS = 5000;
|
|
27
|
+
|
|
28
|
+
/** Opciones por llamada. Sin `timeoutMs` no se aplica timeout propio. */
|
|
29
|
+
export interface RetailOrgRequestOptions {
|
|
30
|
+
timeoutMs?: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
22
33
|
/**
|
|
23
34
|
* Filtro de `listStoresByRetailer`. `"ALL"` no es un estado de tienda: es la ausencia de filtro, y
|
|
24
35
|
* va en el MISMO parámetro que los estados porque los dos hablan del mismo eje — un segundo flag
|
|
@@ -107,23 +118,32 @@ export interface IRetailOrgBusinessApi {
|
|
|
107
118
|
* Devuelve `[]` si ningún retailer pasa el filtro. **No hay 404**: el silo siempre existe — lo
|
|
108
119
|
* garantiza el `tenantId`, que es lo que resolvió el contexto del tenant.
|
|
109
120
|
*
|
|
121
|
+
* `integrated = true` deja solo los retailers con la bandera de integración prendida; cada
|
|
122
|
+
* retailer trae `integrationSystem` e `integrationActivatedAt` cuando la tiene. Timeout opt-in vía
|
|
123
|
+
* `options.timeoutMs` (ver `RETAIL_ORG_LIST_RETAILERS_TIMEOUT_MS`).
|
|
124
|
+
*
|
|
110
125
|
* @throws `400 RETAILER_STATUS_FILTER_INVALID` si `status` no es del catálogo ·
|
|
111
126
|
* `400 UNKNOWN_TENANT` sin `tenantId`.
|
|
112
127
|
*/
|
|
113
128
|
listRetailers(
|
|
114
129
|
tenantId: string,
|
|
115
130
|
status?: RetailerRosterStatusFilter,
|
|
131
|
+
integrated?: boolean,
|
|
132
|
+
options?: RetailOrgRequestOptions,
|
|
116
133
|
): Promise<StandardResponse<RetailerValidationDto[]>>;
|
|
117
134
|
|
|
118
135
|
/**
|
|
119
136
|
* GET /private/retailers/{retailerId} — valida que el retailer exista y devuelve su shape mínimo
|
|
120
|
-
* (id, name, type, status, parentId). `status` ya viene con la cascada
|
|
137
|
+
* (id, name, type, status, parentId) y la bandera de integración. `status` ya viene con la cascada
|
|
138
|
+
* aplicada (estado efectivo). Timeout opt-in vía `options.timeoutMs` (ver
|
|
139
|
+
* `RETAIL_ORG_GET_RETAILER_TIMEOUT_MS`).
|
|
121
140
|
*
|
|
122
141
|
* @throws si el retailer no existe (`404 RETAILER_NOT_FOUND`).
|
|
123
142
|
*/
|
|
124
143
|
getRetailer(
|
|
125
144
|
retailerId: string,
|
|
126
145
|
tenantId: string,
|
|
146
|
+
options?: RetailOrgRequestOptions,
|
|
127
147
|
): Promise<StandardResponse<RetailerValidationDto>>;
|
|
128
148
|
|
|
129
149
|
/**
|