@fiado/api-invoker 5.96.0 → 5.98.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.
Files changed (41) hide show
  1. package/bin/index.d.ts +1 -0
  2. package/bin/index.js +1 -0
  3. package/bin/retailCatalog/api/RetailCatalogBusinessApi.d.ts +3 -1
  4. package/bin/retailCatalog/api/RetailCatalogBusinessApi.js +13 -0
  5. package/bin/retailCatalog/api/interfaces/IRetailCatalogBusinessApi.d.ts +9 -2
  6. package/bin/retailCatalog/index.d.ts +2 -0
  7. package/bin/retailCatalog/index.js +2 -0
  8. package/bin/retailCatalog/queue/RetailInventoryInboundPublisher.d.ts +6 -0
  9. package/bin/retailCatalog/queue/RetailInventoryInboundPublisher.js +31 -0
  10. package/bin/retailCatalog/queue/interfaces/IRetailInventoryInboundPublisher.d.ts +8 -0
  11. package/bin/retailCatalog/queue/interfaces/IRetailInventoryInboundPublisher.js +1 -0
  12. package/bin/retailPromotions/api/RetailPromotionsBusinessApi.d.ts +11 -0
  13. package/bin/retailPromotions/api/RetailPromotionsBusinessApi.js +33 -0
  14. package/bin/retailPromotions/api/interfaces/IRetailPromotionsBusinessApi.d.ts +9 -0
  15. package/bin/retailPromotions/api/interfaces/IRetailPromotionsBusinessApi.js +1 -0
  16. package/bin/retailPromotions/index.d.ts +2 -0
  17. package/bin/retailPromotions/index.js +2 -0
  18. package/bin/retailWizard/api/RetailWizardBusinessApi.d.ts +7 -1
  19. package/bin/retailWizard/api/RetailWizardBusinessApi.js +23 -1
  20. package/bin/retailWizard/api/interfaces/IRetailWizardBusinessApi.d.ts +18 -1
  21. package/bin/retailWizard/index.d.ts +2 -0
  22. package/bin/retailWizard/index.js +2 -0
  23. package/bin/retailWizard/queue/RetailPromotionInboundPublisher.d.ts +6 -0
  24. package/bin/retailWizard/queue/RetailPromotionInboundPublisher.js +31 -0
  25. package/bin/retailWizard/queue/interfaces/IRetailPromotionInboundPublisher.d.ts +8 -0
  26. package/bin/retailWizard/queue/interfaces/IRetailPromotionInboundPublisher.js +1 -0
  27. package/package.json +2 -2
  28. package/src/index.ts +1 -0
  29. package/src/retailCatalog/api/RetailCatalogBusinessApi.ts +25 -1
  30. package/src/retailCatalog/api/interfaces/IRetailCatalogBusinessApi.ts +18 -1
  31. package/src/retailCatalog/index.ts +2 -0
  32. package/src/retailCatalog/queue/RetailInventoryInboundPublisher.ts +25 -0
  33. package/src/retailCatalog/queue/interfaces/IRetailInventoryInboundPublisher.ts +9 -0
  34. package/src/retailPromotions/api/RetailPromotionsBusinessApi.ts +23 -0
  35. package/src/retailPromotions/api/interfaces/IRetailPromotionsBusinessApi.ts +15 -0
  36. package/src/retailPromotions/index.ts +2 -0
  37. package/src/retailWizard/api/RetailWizardBusinessApi.ts +53 -2
  38. package/src/retailWizard/api/interfaces/IRetailWizardBusinessApi.ts +46 -1
  39. package/src/retailWizard/index.ts +2 -0
  40. package/src/retailWizard/queue/RetailPromotionInboundPublisher.ts +25 -0
  41. package/src/retailWizard/queue/interfaces/IRetailPromotionInboundPublisher.ts +9 -0
package/bin/index.d.ts CHANGED
@@ -88,6 +88,7 @@ export * from "./retailCatalog/index.js";
88
88
  export * from "./retailCards/index.js";
89
89
  export * from "./retailNotifications/index.js";
90
90
  export * from "./retailWizard/index.js";
91
+ export * from "./retailPromotions/index.js";
91
92
  export * from "./shortlink/index.js";
92
93
  export * from "./loanConfig/index.js";
93
94
  export * from "./loanOfferings/index.js";
package/bin/index.js CHANGED
@@ -88,6 +88,7 @@ export * from "./retailCatalog/index.js";
88
88
  export * from "./retailCards/index.js";
89
89
  export * from "./retailNotifications/index.js";
90
90
  export * from "./retailWizard/index.js";
91
+ export * from "./retailPromotions/index.js";
91
92
  export * from "./shortlink/index.js";
92
93
  export * from "./loanConfig/index.js";
93
94
  export * from "./loanOfferings/index.js";
@@ -1,6 +1,6 @@
1
1
  import type { IHttpRequest } from "@fiado/http-client";
2
2
  import { StandardResponse } from "@fiado/gateway-adapter";
3
- import type { GetStoreStockCatalogResponse, ReleaseStockRequest, ReleaseStockResponse, RenewReservationsRequest, RenewReservationsResponse, ReserveStockRequest, ReserveStockResponse, ReturnStockRequest, ReturnStockResponse, SellStockRequest, SellStockResponse, SuggestPiecesQuery, SuggestPiecesResponse, SyncInventoryRequest, SyncInventoryResponse, ValidateProductResponse } from "@fiado/type-kit/bin/retailCatalog/index.js";
3
+ import type { GetStoreStockCatalogResponse, HoldStockRequest, HoldStockResponse, InventoryLensQuery, InventoryLensResponse, ReleaseStockRequest, ReleaseStockResponse, RenewReservationsRequest, RenewReservationsResponse, ReserveStockRequest, ReserveStockResponse, ReturnStockRequest, ReturnStockResponse, SellStockRequest, SellStockResponse, SuggestPiecesQuery, SuggestPiecesResponse, SyncInventoryRequest, SyncInventoryResponse, ValidateProductResponse } from "@fiado/type-kit/bin/retailCatalog/index.js";
4
4
  import { IRetailCatalogBusinessApi, ProductsByRetailersResponse, ReleaseReservationBody, ReserveInventoryBody, ReserveInventoryResult, SellInventoryBody, StoreCatalogItem } from "./interfaces/IRetailCatalogBusinessApi.js";
5
5
  /**
6
6
  * Publisher HTTP del lambda `retail-catalog-business` (SureKeep Fase 1, pista Retail) para sus
@@ -32,9 +32,11 @@ export default class RetailCatalogBusinessApi implements IRetailCatalogBusinessA
32
32
  reserveStock(storeId: string, body: ReserveStockRequest, tenantId: string): Promise<StandardResponse<ReserveStockResponse>>;
33
33
  renewReservations(storeId: string, body: RenewReservationsRequest, tenantId: string): Promise<StandardResponse<RenewReservationsResponse>>;
34
34
  suggestPieces(storeId: string, query: SuggestPiecesQuery, tenantId: string): Promise<StandardResponse<SuggestPiecesResponse>>;
35
+ holdStock(storeId: string, body: HoldStockRequest, tenantId: string): Promise<StandardResponse<HoldStockResponse>>;
35
36
  sellStock(storeId: string, body: SellStockRequest, tenantId: string): Promise<StandardResponse<SellStockResponse>>;
36
37
  releaseStock(storeId: string, body: ReleaseStockRequest, tenantId: string): Promise<StandardResponse<ReleaseStockResponse>>;
37
38
  returnStock(storeId: string, body: ReturnStockRequest, tenantId: string): Promise<StandardResponse<ReturnStockResponse>>;
38
39
  syncInventory(retailerId: string, body: SyncInventoryRequest, tenantId: string): Promise<StandardResponse<SyncInventoryResponse>>;
39
40
  getStoreStockCatalog(storeId: string, tenantId: string): Promise<StandardResponse<GetStoreStockCatalogResponse>>;
41
+ getInventoryLens(tenantId: string, retailerId: string, query: InventoryLensQuery): Promise<StandardResponse<InventoryLensResponse>>;
40
42
  }
@@ -83,8 +83,13 @@ let RetailCatalogBusinessApi = class RetailCatalogBusinessApi {
83
83
  }
84
84
  async suggestPieces(storeId, query, tenantId) {
85
85
  const extra = { sku: query.sku, prefix: query.prefix };
86
+ if (query.sessionId)
87
+ extra.sessionId = query.sessionId;
86
88
  return await this.httpRequest.get(this.storeUrl(storeId, "pieces", tenantId, extra));
87
89
  }
90
+ async holdStock(storeId, body, tenantId) {
91
+ return await this.httpRequest.put(this.storeUrl(storeId, "holds", tenantId), body);
92
+ }
88
93
  async sellStock(storeId, body, tenantId) {
89
94
  return await this.httpRequest.put(this.storeUrl(storeId, "sales", tenantId), body);
90
95
  }
@@ -102,6 +107,14 @@ let RetailCatalogBusinessApi = class RetailCatalogBusinessApi {
102
107
  async getStoreStockCatalog(storeId, tenantId) {
103
108
  return await this.httpRequest.get(this.storeUrl(storeId, "stock-catalog", tenantId));
104
109
  }
110
+ async getInventoryLens(tenantId, retailerId, query) {
111
+ const params = new URLSearchParams({ tenantId, retailerId, filter: query.filter });
112
+ if (query.period)
113
+ params.set("period", query.period);
114
+ if (query.storeId)
115
+ params.set("storeId", query.storeId);
116
+ return await this.httpRequest.get(`${this.baseUrl}/private/inventory/lens?${params.toString()}`);
117
+ }
105
118
  };
106
119
  RetailCatalogBusinessApi = __decorate([
107
120
  injectable(),
@@ -1,5 +1,5 @@
1
1
  import { StandardResponse } from "@fiado/gateway-adapter";
2
- import type { GetStoreStockCatalogResponse, MdmLockModeEnum, MdmProviderEnum, ReleaseStockRequest, ReleaseStockResponse, RenewReservationsRequest, RenewReservationsResponse, ReserveStockRequest, ReserveStockResponse, ReturnStockRequest, ReturnStockResponse, SellStockRequest, SellStockResponse, SuggestPiecesQuery, SuggestPiecesResponse, SyncInventoryRequest, 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, SuggestPiecesQuery, SuggestPiecesResponse, SyncInventoryRequest, SyncInventoryResponse, ValidateProductResponse } from "@fiado/type-kit/bin/retailCatalog/index.js";
3
3
  /**
4
4
  * Contrato del publisher HTTP del lambda `retail-catalog-business` (SureKeep Fase 1, pista Retail)
5
5
  * para sus endpoints privados del ciclo de venta del IMEI, consumidos por el wizard F2.
@@ -156,8 +156,13 @@ export interface IRetailCatalogBusinessApi {
156
156
  reserveStock(storeId: string, body: ReserveStockRequest, tenantId: string): Promise<StandardResponse<ReserveStockResponse>>;
157
157
  /** PUT `/private/stores/{storeId}/reservations/renew` — extiende las reservas de las líneas. */
158
158
  renewReservations(storeId: string, body: RenewReservationsRequest, tenantId: string): Promise<StandardResponse<RenewReservationsResponse>>;
159
- /** GET `/private/stores/{storeId}/pieces` — piezas disponibles del SKU que empiezan con `prefix`. */
159
+ /**
160
+ * GET `/private/stores/{storeId}/pieces` — piezas disponibles del SKU que empiezan con `prefix`;
161
+ * con `sessionId` también trae las HELD de esa sesión.
162
+ */
160
163
  suggestPieces(storeId: string, query: SuggestPiecesQuery, tenantId: string): Promise<StandardResponse<SuggestPiecesResponse>>;
164
+ /** PUT `/private/stores/{storeId}/holds` — fija como HELD de la sesión las piezas de una línea (idempotente). */
165
+ holdStock(storeId: string, body: HoldStockRequest, tenantId: string): Promise<StandardResponse<HoldStockResponse>>;
161
166
  /** PUT `/private/stores/{storeId}/sales` — vende las líneas con sus identificadores en una transacción. */
162
167
  sellStock(storeId: string, body: SellStockRequest, tenantId: string): Promise<StandardResponse<SellStockResponse>>;
163
168
  /** PUT `/private/stores/{storeId}/reservations/release` — libera las reservas de las líneas. */
@@ -168,4 +173,6 @@ export interface IRetailCatalogBusinessApi {
168
173
  syncInventory(retailerId: string, body: SyncInventoryRequest, tenantId: string): Promise<StandardResponse<SyncInventoryResponse>>;
169
174
  /** GET `/private/stores/{storeId}/stock-catalog` — catálogo vendible de la tienda, una fila por SKU. */
170
175
  getStoreStockCatalog(storeId: string, tenantId: string): Promise<StandardResponse<GetStoreStockCatalogResponse>>;
176
+ /** GET `/private/inventory/lens` — lente de inventario del retailer; `period` y `storeId` solo aplican a `filter=list`. */
177
+ getInventoryLens(tenantId: string, retailerId: string, query: InventoryLensQuery): Promise<StandardResponse<InventoryLensResponse>>;
171
178
  }
@@ -1,2 +1,4 @@
1
1
  export * from "./api/interfaces/IRetailCatalogBusinessApi.js";
2
2
  export { default as RetailCatalogBusinessApi } from "./api/RetailCatalogBusinessApi.js";
3
+ export * from "./queue/interfaces/IRetailInventoryInboundPublisher.js";
4
+ export * from "./queue/RetailInventoryInboundPublisher.js";
@@ -1,2 +1,4 @@
1
1
  export * from "./api/interfaces/IRetailCatalogBusinessApi.js";
2
2
  export { default as RetailCatalogBusinessApi } from "./api/RetailCatalogBusinessApi.js";
3
+ export * from "./queue/interfaces/IRetailInventoryInboundPublisher.js";
4
+ export * from "./queue/RetailInventoryInboundPublisher.js";
@@ -0,0 +1,6 @@
1
+ import type { InventoryInboundMessage } from "@fiado/type-kit/bin/retailCatalog/index.js";
2
+ import { IRetailInventoryInboundPublisher } from "./interfaces/IRetailInventoryInboundPublisher.js";
3
+ export declare class RetailInventoryInboundPublisher implements IRetailInventoryInboundPublisher {
4
+ private readonly RETAIL_INVENTORY_INBOUND_QUEUE_URL;
5
+ publish(message: InventoryInboundMessage): Promise<void>;
6
+ }
@@ -0,0 +1,31 @@
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
+ import { SendMessageCommand, SQSClient } from "@aws-sdk/client-sqs";
8
+ import { injectable } from "inversify";
9
+ let RetailInventoryInboundPublisher = class RetailInventoryInboundPublisher {
10
+ RETAIL_INVENTORY_INBOUND_QUEUE_URL = process.env.RETAIL_INVENTORY_INBOUND_QUEUE_URL;
11
+ async publish(message) {
12
+ try {
13
+ const client = new SQSClient();
14
+ // Cola estándar: sin MessageGroupId; el consumidor deduplica por sesión y venta.
15
+ const sendMessageRequest = {
16
+ QueueUrl: this.RETAIL_INVENTORY_INBOUND_QUEUE_URL,
17
+ MessageBody: JSON.stringify(message),
18
+ };
19
+ const command = new SendMessageCommand(sendMessageRequest);
20
+ await client.send(command);
21
+ }
22
+ catch (error) {
23
+ const errorMessage = error instanceof Error ? error.message : String(error);
24
+ throw new Error(`Error publishing message to RetailInventoryInboundQueue: ${errorMessage}`);
25
+ }
26
+ }
27
+ };
28
+ RetailInventoryInboundPublisher = __decorate([
29
+ injectable()
30
+ ], RetailInventoryInboundPublisher);
31
+ export { RetailInventoryInboundPublisher };
@@ -0,0 +1,8 @@
1
+ import type { InventoryInboundMessage } from "@fiado/type-kit/bin/retailCatalog/index.js";
2
+ /**
3
+ * Publisher hacia `RetailInventoryInboundQueue` (SALE_APPLIED | RETURN), que consume `retail-catalog-business`.
4
+ * Env var requerida en el productor: `RETAIL_INVENTORY_INBOUND_QUEUE_URL`.
5
+ */
6
+ export interface IRetailInventoryInboundPublisher {
7
+ publish(message: InventoryInboundMessage): Promise<void>;
8
+ }
@@ -0,0 +1,11 @@
1
+ import type { IHttpRequest } from "@fiado/http-client";
2
+ import { StandardResponse } from "@fiado/gateway-adapter";
3
+ import type { PrivateReleaseSalePromotionResponse } from "@fiado/type-kit/bin/retailPromotions/index.js";
4
+ import { IRetailPromotionsBusinessApi } from "./interfaces/IRetailPromotionsBusinessApi.js";
5
+ /** Publisher HTTP de los privados de `retail-promotions-business`. Contrato -> `IRetailPromotionsBusinessApi`. */
6
+ export default class RetailPromotionsBusinessApi implements IRetailPromotionsBusinessApi {
7
+ private httpRequest;
8
+ private readonly baseUrl;
9
+ constructor(httpRequest: IHttpRequest);
10
+ releaseSalePromotion(tenantId: string, sessionId: string): Promise<StandardResponse<PrivateReleaseSalePromotionResponse>>;
11
+ }
@@ -0,0 +1,33 @@
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
+ /** Publisher HTTP de los privados de `retail-promotions-business`. Contrato -> `IRetailPromotionsBusinessApi`. */
15
+ let RetailPromotionsBusinessApi = class RetailPromotionsBusinessApi {
16
+ httpRequest;
17
+ // El buildspec publica la URL en SSM con "/" final; se normaliza para no armar "//private".
18
+ baseUrl = (process.env.RETAIL_PROMOTIONS_BUSINESS_URL || "").replace(/\/+$/, "");
19
+ constructor(httpRequest) {
20
+ this.httpRequest = httpRequest;
21
+ }
22
+ async releaseSalePromotion(tenantId, sessionId) {
23
+ const query = new URLSearchParams({ tenantId });
24
+ const url = `${this.baseUrl}/private/sessions/${encodeURIComponent(sessionId)}/sale-promotion?${query.toString()}`;
25
+ return await this.httpRequest.delete(url);
26
+ }
27
+ };
28
+ RetailPromotionsBusinessApi = __decorate([
29
+ injectable(),
30
+ __param(0, inject("IHttpRequest")),
31
+ __metadata("design:paramtypes", [Object])
32
+ ], RetailPromotionsBusinessApi);
33
+ export default RetailPromotionsBusinessApi;
@@ -0,0 +1,9 @@
1
+ import { StandardResponse } from "@fiado/gateway-adapter";
2
+ import type { PrivateReleaseSalePromotionResponse } from "@fiado/type-kit/bin/retailPromotions/index.js";
3
+ export interface IRetailPromotionsBusinessApi {
4
+ /**
5
+ * `DELETE /private/sessions/{sessionId}/sale-promotion`: suelta el apartado de la promo de venta.
6
+ * Lo llama el wizard al cancelar. Es idempotente: `released: false` si no había apartado.
7
+ */
8
+ releaseSalePromotion(tenantId: string, sessionId: string): Promise<StandardResponse<PrivateReleaseSalePromotionResponse>>;
9
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./api/interfaces/IRetailPromotionsBusinessApi.js";
2
+ export { default as RetailPromotionsBusinessApi } from "./api/RetailPromotionsBusinessApi.js";
@@ -0,0 +1,2 @@
1
+ export * from "./api/interfaces/IRetailPromotionsBusinessApi.js";
2
+ export { default as RetailPromotionsBusinessApi } from "./api/RetailPromotionsBusinessApi.js";
@@ -1,6 +1,6 @@
1
1
  import type { IHttpRequest } from "@fiado/http-client";
2
2
  import { StandardResponse } from "@fiado/gateway-adapter";
3
- import { WizardSessionLookupResponse } from "@fiado/type-kit/bin/retailWizard/index.js";
3
+ import type { ApplyLinePromotionRequest, ApplySalePromotionRequest, PrivateWizardSessionResponse, SetAnchorGiftsRequest, SetAnchorGiftsResponse, WizardSessionLookupResponse } from "@fiado/type-kit/bin/retailWizard/index.js";
4
4
  import { IRetailWizardBusinessApi } from "./interfaces/IRetailWizardBusinessApi.js";
5
5
  /**
6
6
  * Publisher HTTP del lambda `retail-wizard-business` (componente 05 SureKeep Fase 2) para sus
@@ -20,4 +20,10 @@ export default class RetailWizardBusinessApi implements IRetailWizardBusinessApi
20
20
  * estados, el techo de 100 y lo que NO devuelve) -> `IRetailWizardBusinessApi`.
21
21
  */
22
22
  getWizardSessionsByIds(wizardSessionIds: string[], tenantId: string): Promise<StandardResponse<WizardSessionLookupResponse>>;
23
+ applyLinePromotion(sessionId: string, lineId: string, body: ApplyLinePromotionRequest, tenantId: string): Promise<void>;
24
+ setAnchorGifts(sessionId: string, anchorLineId: string, body: SetAnchorGiftsRequest, tenantId: string): Promise<StandardResponse<SetAnchorGiftsResponse>>;
25
+ applySalePromotion(sessionId: string, body: ApplySalePromotionRequest, tenantId: string): Promise<void>;
26
+ getPrivateWizardSession(sessionId: string, tenantId: string): Promise<StandardResponse<PrivateWizardSessionResponse>>;
27
+ /** URL de `/private/wizard/sessions/{id}[/subPath]` con `tenantId` en query. */
28
+ private sessionUrl;
23
29
  }
@@ -22,7 +22,8 @@ import { inject, injectable } from "inversify";
22
22
  */
23
23
  let RetailWizardBusinessApi = class RetailWizardBusinessApi {
24
24
  httpRequest;
25
- baseUrl = process.env.RETAIL_WIZARD_BUSINESS_URL || "";
25
+ // El buildspec publica la URL en SSM con "/" final; se normaliza para no armar "//private".
26
+ baseUrl = (process.env.RETAIL_WIZARD_BUSINESS_URL || "").replace(/\/+$/, "");
26
27
  constructor(httpRequest) {
27
28
  this.httpRequest = httpRequest;
28
29
  }
@@ -36,6 +37,27 @@ let RetailWizardBusinessApi = class RetailWizardBusinessApi {
36
37
  const query = new URLSearchParams({ ids: wizardSessionIds.join(","), tenantId });
37
38
  return await this.httpRequest.get(`${this.baseUrl}/private/wizard-sessions/batch?${query.toString()}`);
38
39
  }
40
+ async applyLinePromotion(sessionId, lineId, body, tenantId) {
41
+ // El 204 no trae cuerpo (http-client devuelve ""); los errores se propagan tal cual.
42
+ const path = `lines/${encodeURIComponent(lineId)}/promotion`;
43
+ await this.httpRequest.put(this.sessionUrl(sessionId, tenantId, path), body);
44
+ }
45
+ async setAnchorGifts(sessionId, anchorLineId, body, tenantId) {
46
+ const path = `lines/${encodeURIComponent(anchorLineId)}/gifts`;
47
+ return await this.httpRequest.put(this.sessionUrl(sessionId, tenantId, path), body);
48
+ }
49
+ async applySalePromotion(sessionId, body, tenantId) {
50
+ await this.httpRequest.put(this.sessionUrl(sessionId, tenantId, "sale-promotion"), body);
51
+ }
52
+ async getPrivateWizardSession(sessionId, tenantId) {
53
+ return await this.httpRequest.get(this.sessionUrl(sessionId, tenantId));
54
+ }
55
+ /** URL de `/private/wizard/sessions/{id}[/subPath]` con `tenantId` en query. */
56
+ sessionUrl(sessionId, tenantId, subPath) {
57
+ const base = `${this.baseUrl}/private/wizard/sessions/${encodeURIComponent(sessionId)}`;
58
+ const query = new URLSearchParams({ tenantId });
59
+ return `${subPath ? `${base}/${subPath}` : base}?${query.toString()}`;
60
+ }
39
61
  };
40
62
  RetailWizardBusinessApi = __decorate([
41
63
  injectable(),
@@ -1,5 +1,5 @@
1
1
  import { StandardResponse } from "@fiado/gateway-adapter";
2
- import { WizardSessionLookupResponse } from "@fiado/type-kit/bin/retailWizard/index.js";
2
+ import type { ApplyLinePromotionRequest, ApplySalePromotionRequest, PrivateWizardSessionResponse, SetAnchorGiftsRequest, SetAnchorGiftsResponse, WizardSessionLookupResponse } from "@fiado/type-kit/bin/retailWizard/index.js";
3
3
  /**
4
4
  * Contrato del publisher HTTP del lambda `retail-wizard-business` (componente 05 SureKeep Fase 2)
5
5
  * para sus endpoints privados (service-to-service, VPC-only).
@@ -55,4 +55,21 @@ export interface IRetailWizardBusinessApi {
55
55
  * `400 UNKNOWN_TENANT` sin `tenantId`.
56
56
  */
57
57
  getWizardSessionsByIds(wizardSessionIds: string[], tenantId: string): Promise<StandardResponse<WizardSessionLookupResponse>>;
58
+ /**
59
+ * `PUT /private/wizard/sessions/{id}/lines/{lineId}/promotion` (M2M de Promociones). Reemplaza la
60
+ * promo de la línea por valor. Responde 204 sin body.
61
+ */
62
+ applyLinePromotion(sessionId: string, lineId: string, body: ApplyLinePromotionRequest, tenantId: string): Promise<void>;
63
+ /**
64
+ * `PUT /private/wizard/sessions/{id}/lines/{anchorLineId}/gifts` (M2M de Promociones). Deja
65
+ * exactamente esos regalos en el ancla; `items: []` suelta todos.
66
+ */
67
+ setAnchorGifts(sessionId: string, anchorLineId: string, body: SetAnchorGiftsRequest, tenantId: string): Promise<StandardResponse<SetAnchorGiftsResponse>>;
68
+ /**
69
+ * `PUT /private/wizard/sessions/{id}/sale-promotion` (M2M de Promociones). Ambos campos en `null`
70
+ * es «Ninguna». Responde 204 sin body.
71
+ */
72
+ applySalePromotion(sessionId: string, body: ApplySalePromotionRequest, tenantId: string): Promise<void>;
73
+ /** `GET /private/wizard/sessions/{id}`: la sesión como la lee Promociones (líneas, ancla, promo de venta). */
74
+ getPrivateWizardSession(sessionId: string, tenantId: string): Promise<StandardResponse<PrivateWizardSessionResponse>>;
58
75
  }
@@ -1,2 +1,4 @@
1
1
  export * from "./api/interfaces/IRetailWizardBusinessApi.js";
2
2
  export { default as RetailWizardBusinessApi } from "./api/RetailWizardBusinessApi.js";
3
+ export * from "./queue/interfaces/IRetailPromotionInboundPublisher.js";
4
+ export * from "./queue/RetailPromotionInboundPublisher.js";
@@ -1,2 +1,4 @@
1
1
  export * from "./api/interfaces/IRetailWizardBusinessApi.js";
2
2
  export { default as RetailWizardBusinessApi } from "./api/RetailWizardBusinessApi.js";
3
+ export * from "./queue/interfaces/IRetailPromotionInboundPublisher.js";
4
+ export * from "./queue/RetailPromotionInboundPublisher.js";
@@ -0,0 +1,6 @@
1
+ import type { RetailPromotionInboundMessage } from "@fiado/type-kit/bin/retailWizard/index.js";
2
+ import { IRetailPromotionInboundPublisher } from "./interfaces/IRetailPromotionInboundPublisher.js";
3
+ export declare class RetailPromotionInboundPublisher implements IRetailPromotionInboundPublisher {
4
+ private readonly RETAIL_PROMOTION_INBOUND_QUEUE_URL;
5
+ publish(message: RetailPromotionInboundMessage): Promise<void>;
6
+ }
@@ -0,0 +1,31 @@
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
+ import { SendMessageCommand, SQSClient } from "@aws-sdk/client-sqs";
8
+ import { injectable } from "inversify";
9
+ let RetailPromotionInboundPublisher = class RetailPromotionInboundPublisher {
10
+ RETAIL_PROMOTION_INBOUND_QUEUE_URL = process.env.RETAIL_PROMOTION_INBOUND_QUEUE_URL;
11
+ async publish(message) {
12
+ try {
13
+ const client = new SQSClient();
14
+ // Cola estándar: sin MessageGroupId; el consumidor deduplica por venta.
15
+ const sendMessageRequest = {
16
+ QueueUrl: this.RETAIL_PROMOTION_INBOUND_QUEUE_URL,
17
+ MessageBody: JSON.stringify(message),
18
+ };
19
+ const command = new SendMessageCommand(sendMessageRequest);
20
+ await client.send(command);
21
+ }
22
+ catch (error) {
23
+ const errorMessage = error instanceof Error ? error.message : String(error);
24
+ throw new Error(`Error publishing message to RetailPromotionInboundQueue: ${errorMessage}`);
25
+ }
26
+ }
27
+ };
28
+ RetailPromotionInboundPublisher = __decorate([
29
+ injectable()
30
+ ], RetailPromotionInboundPublisher);
31
+ export { RetailPromotionInboundPublisher };
@@ -0,0 +1,8 @@
1
+ import type { RetailPromotionInboundMessage } from "@fiado/type-kit/bin/retailWizard/index.js";
2
+ /**
3
+ * Publisher hacia `RetailPromotionInboundQueue` (SALE_CONFIRMED | SALE_CANCELLED), que consume `retail-promotions`.
4
+ * Env var requerida en el productor: `RETAIL_PROMOTION_INBOUND_QUEUE_URL`.
5
+ */
6
+ export interface IRetailPromotionInboundPublisher {
7
+ publish(message: RetailPromotionInboundMessage): Promise<void>;
8
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fiado/api-invoker",
3
- "version": "5.96.0",
3
+ "version": "5.98.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.9.0",
35
35
  "@fiado/http-client": "^2.0.1",
36
36
  "@fiado/logger": "^1.1.3",
37
- "@fiado/type-kit": "^3.468.0",
37
+ "@fiado/type-kit": "3.478.0",
38
38
  "dotenv": "^16.4.7"
39
39
  },
40
40
  "peerDependencies": {
package/src/index.ts CHANGED
@@ -88,6 +88,7 @@ export * from "./retailCatalog/index.js";
88
88
  export * from "./retailCards/index.js";
89
89
  export * from "./retailNotifications/index.js";
90
90
  export * from "./retailWizard/index.js";
91
+ export * from "./retailPromotions/index.js";
91
92
  export * from "./shortlink/index.js";
92
93
  export * from "./loanConfig/index.js";
93
94
  export * from "./loanOfferings/index.js";
@@ -3,6 +3,10 @@ import type { IHttpRequest } from "@fiado/http-client";
3
3
  import { StandardResponse } from "@fiado/gateway-adapter";
4
4
  import type {
5
5
  GetStoreStockCatalogResponse,
6
+ HoldStockRequest,
7
+ HoldStockResponse,
8
+ InventoryLensQuery,
9
+ InventoryLensResponse,
6
10
  ReleaseStockRequest,
7
11
  ReleaseStockResponse,
8
12
  RenewReservationsRequest,
@@ -142,10 +146,19 @@ export default class RetailCatalogBusinessApi implements IRetailCatalogBusinessA
142
146
  query: SuggestPiecesQuery,
143
147
  tenantId: string,
144
148
  ): Promise<StandardResponse<SuggestPiecesResponse>> {
145
- const extra = { sku: query.sku, prefix: query.prefix };
149
+ const extra: Record<string, string> = { sku: query.sku, prefix: query.prefix };
150
+ if (query.sessionId) extra.sessionId = query.sessionId;
146
151
  return await this.httpRequest.get(this.storeUrl(storeId, "pieces", tenantId, extra));
147
152
  }
148
153
 
154
+ async holdStock(
155
+ storeId: string,
156
+ body: HoldStockRequest,
157
+ tenantId: string,
158
+ ): Promise<StandardResponse<HoldStockResponse>> {
159
+ return await this.httpRequest.put(this.storeUrl(storeId, "holds", tenantId), body);
160
+ }
161
+
149
162
  async sellStock(
150
163
  storeId: string,
151
164
  body: SellStockRequest,
@@ -186,4 +199,15 @@ export default class RetailCatalogBusinessApi implements IRetailCatalogBusinessA
186
199
  ): Promise<StandardResponse<GetStoreStockCatalogResponse>> {
187
200
  return await this.httpRequest.get(this.storeUrl(storeId, "stock-catalog", tenantId));
188
201
  }
202
+
203
+ async getInventoryLens(
204
+ tenantId: string,
205
+ retailerId: string,
206
+ query: InventoryLensQuery,
207
+ ): Promise<StandardResponse<InventoryLensResponse>> {
208
+ const params = new URLSearchParams({ tenantId, retailerId, filter: query.filter });
209
+ if (query.period) params.set("period", query.period);
210
+ if (query.storeId) params.set("storeId", query.storeId);
211
+ return await this.httpRequest.get(`${this.baseUrl}/private/inventory/lens?${params.toString()}`);
212
+ }
189
213
  }
@@ -1,6 +1,10 @@
1
1
  import { StandardResponse } from "@fiado/gateway-adapter";
2
2
  import type {
3
3
  GetStoreStockCatalogResponse,
4
+ HoldStockRequest,
5
+ HoldStockResponse,
6
+ InventoryLensQuery,
7
+ InventoryLensResponse,
4
8
  MdmLockModeEnum,
5
9
  MdmProviderEnum,
6
10
  ReleaseStockRequest,
@@ -218,13 +222,19 @@ export interface IRetailCatalogBusinessApi {
218
222
  tenantId: string,
219
223
  ): Promise<StandardResponse<RenewReservationsResponse>>;
220
224
 
221
- /** GET `/private/stores/{storeId}/pieces` — piezas disponibles del SKU que empiezan con `prefix`. */
225
+ /**
226
+ * GET `/private/stores/{storeId}/pieces` — piezas disponibles del SKU que empiezan con `prefix`;
227
+ * con `sessionId` también trae las HELD de esa sesión.
228
+ */
222
229
  suggestPieces(
223
230
  storeId: string,
224
231
  query: SuggestPiecesQuery,
225
232
  tenantId: string,
226
233
  ): Promise<StandardResponse<SuggestPiecesResponse>>;
227
234
 
235
+ /** PUT `/private/stores/{storeId}/holds` — fija como HELD de la sesión las piezas de una línea (idempotente). */
236
+ holdStock(storeId: string, body: HoldStockRequest, tenantId: string): Promise<StandardResponse<HoldStockResponse>>;
237
+
228
238
  /** PUT `/private/stores/{storeId}/sales` — vende las líneas con sus identificadores en una transacción. */
229
239
  sellStock(storeId: string, body: SellStockRequest, tenantId: string): Promise<StandardResponse<SellStockResponse>>;
230
240
 
@@ -251,4 +261,11 @@ export interface IRetailCatalogBusinessApi {
251
261
 
252
262
  /** GET `/private/stores/{storeId}/stock-catalog` — catálogo vendible de la tienda, una fila por SKU. */
253
263
  getStoreStockCatalog(storeId: string, tenantId: string): Promise<StandardResponse<GetStoreStockCatalogResponse>>;
264
+
265
+ /** GET `/private/inventory/lens` — lente de inventario del retailer; `period` y `storeId` solo aplican a `filter=list`. */
266
+ getInventoryLens(
267
+ tenantId: string,
268
+ retailerId: string,
269
+ query: InventoryLensQuery,
270
+ ): Promise<StandardResponse<InventoryLensResponse>>;
254
271
  }
@@ -1,2 +1,4 @@
1
1
  export * from "./api/interfaces/IRetailCatalogBusinessApi.js";
2
2
  export { default as RetailCatalogBusinessApi } from "./api/RetailCatalogBusinessApi.js";
3
+ export * from "./queue/interfaces/IRetailInventoryInboundPublisher.js";
4
+ export * from "./queue/RetailInventoryInboundPublisher.js";
@@ -0,0 +1,25 @@
1
+ import { SendMessageCommand, SendMessageRequest, SQSClient } from "@aws-sdk/client-sqs";
2
+ import { injectable } from "inversify";
3
+ import type { InventoryInboundMessage } from "@fiado/type-kit/bin/retailCatalog/index.js";
4
+ import { IRetailInventoryInboundPublisher } from "./interfaces/IRetailInventoryInboundPublisher.js";
5
+
6
+ @injectable()
7
+ export class RetailInventoryInboundPublisher implements IRetailInventoryInboundPublisher {
8
+ private readonly RETAIL_INVENTORY_INBOUND_QUEUE_URL = process.env.RETAIL_INVENTORY_INBOUND_QUEUE_URL;
9
+
10
+ async publish(message: InventoryInboundMessage): Promise<void> {
11
+ try {
12
+ const client: SQSClient = new SQSClient();
13
+ // Cola estándar: sin MessageGroupId; el consumidor deduplica por sesión y venta.
14
+ const sendMessageRequest: SendMessageRequest = {
15
+ QueueUrl: this.RETAIL_INVENTORY_INBOUND_QUEUE_URL,
16
+ MessageBody: JSON.stringify(message),
17
+ };
18
+ const command: SendMessageCommand = new SendMessageCommand(sendMessageRequest);
19
+ await client.send(command);
20
+ } catch (error) {
21
+ const errorMessage = error instanceof Error ? error.message : String(error);
22
+ throw new Error(`Error publishing message to RetailInventoryInboundQueue: ${errorMessage}`);
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,9 @@
1
+ import type { InventoryInboundMessage } from "@fiado/type-kit/bin/retailCatalog/index.js";
2
+
3
+ /**
4
+ * Publisher hacia `RetailInventoryInboundQueue` (SALE_APPLIED | RETURN), que consume `retail-catalog-business`.
5
+ * Env var requerida en el productor: `RETAIL_INVENTORY_INBOUND_QUEUE_URL`.
6
+ */
7
+ export interface IRetailInventoryInboundPublisher {
8
+ publish(message: InventoryInboundMessage): Promise<void>;
9
+ }
@@ -0,0 +1,23 @@
1
+ import { inject, injectable } from "inversify";
2
+ import type { IHttpRequest } from "@fiado/http-client";
3
+ import { StandardResponse } from "@fiado/gateway-adapter";
4
+ import type { PrivateReleaseSalePromotionResponse } from "@fiado/type-kit/bin/retailPromotions/index.js";
5
+ import { IRetailPromotionsBusinessApi } from "./interfaces/IRetailPromotionsBusinessApi.js";
6
+
7
+ /** Publisher HTTP de los privados de `retail-promotions-business`. Contrato -> `IRetailPromotionsBusinessApi`. */
8
+ @injectable()
9
+ export default class RetailPromotionsBusinessApi implements IRetailPromotionsBusinessApi {
10
+ // El buildspec publica la URL en SSM con "/" final; se normaliza para no armar "//private".
11
+ private readonly baseUrl = (process.env.RETAIL_PROMOTIONS_BUSINESS_URL || "").replace(/\/+$/, "");
12
+
13
+ constructor(@inject("IHttpRequest") private httpRequest: IHttpRequest) {}
14
+
15
+ async releaseSalePromotion(
16
+ tenantId: string,
17
+ sessionId: string,
18
+ ): Promise<StandardResponse<PrivateReleaseSalePromotionResponse>> {
19
+ const query = new URLSearchParams({ tenantId });
20
+ const url = `${this.baseUrl}/private/sessions/${encodeURIComponent(sessionId)}/sale-promotion?${query.toString()}`;
21
+ return await this.httpRequest.delete(url);
22
+ }
23
+ }
@@ -0,0 +1,15 @@
1
+ import { StandardResponse } from "@fiado/gateway-adapter";
2
+ import type { PrivateReleaseSalePromotionResponse } from "@fiado/type-kit/bin/retailPromotions/index.js";
3
+
4
+ // Contrato de los privados de `retail-promotions-business`; el caller manda `tenantId` por query.
5
+ // El consumer necesita `RETAIL_PROMOTIONS_BUSINESS_URL` = `{{resolve:ssm:retail-promotions-business}}`.
6
+ export interface IRetailPromotionsBusinessApi {
7
+ /**
8
+ * `DELETE /private/sessions/{sessionId}/sale-promotion`: suelta el apartado de la promo de venta.
9
+ * Lo llama el wizard al cancelar. Es idempotente: `released: false` si no había apartado.
10
+ */
11
+ releaseSalePromotion(
12
+ tenantId: string,
13
+ sessionId: string,
14
+ ): Promise<StandardResponse<PrivateReleaseSalePromotionResponse>>;
15
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./api/interfaces/IRetailPromotionsBusinessApi.js";
2
+ export { default as RetailPromotionsBusinessApi } from "./api/RetailPromotionsBusinessApi.js";
@@ -1,7 +1,14 @@
1
1
  import { inject, injectable } from "inversify";
2
2
  import type { IHttpRequest } from "@fiado/http-client";
3
3
  import { StandardResponse } from "@fiado/gateway-adapter";
4
- import { WizardSessionLookupResponse } from "@fiado/type-kit/bin/retailWizard/index.js";
4
+ import type {
5
+ ApplyLinePromotionRequest,
6
+ ApplySalePromotionRequest,
7
+ PrivateWizardSessionResponse,
8
+ SetAnchorGiftsRequest,
9
+ SetAnchorGiftsResponse,
10
+ WizardSessionLookupResponse,
11
+ } from "@fiado/type-kit/bin/retailWizard/index.js";
5
12
  import { IRetailWizardBusinessApi } from "./interfaces/IRetailWizardBusinessApi.js";
6
13
 
7
14
  /**
@@ -15,7 +22,8 @@ import { IRetailWizardBusinessApi } from "./interfaces/IRetailWizardBusinessApi.
15
22
  */
16
23
  @injectable()
17
24
  export default class RetailWizardBusinessApi implements IRetailWizardBusinessApi {
18
- private readonly baseUrl = process.env.RETAIL_WIZARD_BUSINESS_URL || "";
25
+ // El buildspec publica la URL en SSM con "/" final; se normaliza para no armar "//private".
26
+ private readonly baseUrl = (process.env.RETAIL_WIZARD_BUSINESS_URL || "").replace(/\/+$/, "");
19
27
 
20
28
  constructor(@inject("IHttpRequest") private httpRequest: IHttpRequest) {}
21
29
 
@@ -32,4 +40,47 @@ export default class RetailWizardBusinessApi implements IRetailWizardBusinessApi
32
40
  const query = new URLSearchParams({ ids: wizardSessionIds.join(","), tenantId });
33
41
  return await this.httpRequest.get(`${this.baseUrl}/private/wizard-sessions/batch?${query.toString()}`);
34
42
  }
43
+
44
+ async applyLinePromotion(
45
+ sessionId: string,
46
+ lineId: string,
47
+ body: ApplyLinePromotionRequest,
48
+ tenantId: string,
49
+ ): Promise<void> {
50
+ // El 204 no trae cuerpo (http-client devuelve ""); los errores se propagan tal cual.
51
+ const path = `lines/${encodeURIComponent(lineId)}/promotion`;
52
+ await this.httpRequest.put(this.sessionUrl(sessionId, tenantId, path), body);
53
+ }
54
+
55
+ async setAnchorGifts(
56
+ sessionId: string,
57
+ anchorLineId: string,
58
+ body: SetAnchorGiftsRequest,
59
+ tenantId: string,
60
+ ): Promise<StandardResponse<SetAnchorGiftsResponse>> {
61
+ const path = `lines/${encodeURIComponent(anchorLineId)}/gifts`;
62
+ return await this.httpRequest.put(this.sessionUrl(sessionId, tenantId, path), body);
63
+ }
64
+
65
+ async applySalePromotion(
66
+ sessionId: string,
67
+ body: ApplySalePromotionRequest,
68
+ tenantId: string,
69
+ ): Promise<void> {
70
+ await this.httpRequest.put(this.sessionUrl(sessionId, tenantId, "sale-promotion"), body);
71
+ }
72
+
73
+ async getPrivateWizardSession(
74
+ sessionId: string,
75
+ tenantId: string,
76
+ ): Promise<StandardResponse<PrivateWizardSessionResponse>> {
77
+ return await this.httpRequest.get(this.sessionUrl(sessionId, tenantId));
78
+ }
79
+
80
+ /** URL de `/private/wizard/sessions/{id}[/subPath]` con `tenantId` en query. */
81
+ private sessionUrl(sessionId: string, tenantId: string, subPath?: string): string {
82
+ const base = `${this.baseUrl}/private/wizard/sessions/${encodeURIComponent(sessionId)}`;
83
+ const query = new URLSearchParams({ tenantId });
84
+ return `${subPath ? `${base}/${subPath}` : base}?${query.toString()}`;
85
+ }
35
86
  }
@@ -1,5 +1,12 @@
1
1
  import { StandardResponse } from "@fiado/gateway-adapter";
2
- import { WizardSessionLookupResponse } from "@fiado/type-kit/bin/retailWizard/index.js";
2
+ import type {
3
+ ApplyLinePromotionRequest,
4
+ ApplySalePromotionRequest,
5
+ PrivateWizardSessionResponse,
6
+ SetAnchorGiftsRequest,
7
+ SetAnchorGiftsResponse,
8
+ WizardSessionLookupResponse,
9
+ } from "@fiado/type-kit/bin/retailWizard/index.js";
3
10
 
4
11
  /**
5
12
  * Contrato del publisher HTTP del lambda `retail-wizard-business` (componente 05 SureKeep Fase 2)
@@ -59,4 +66,42 @@ export interface IRetailWizardBusinessApi {
59
66
  wizardSessionIds: string[],
60
67
  tenantId: string,
61
68
  ): Promise<StandardResponse<WizardSessionLookupResponse>>;
69
+
70
+ /**
71
+ * `PUT /private/wizard/sessions/{id}/lines/{lineId}/promotion` (M2M de Promociones). Reemplaza la
72
+ * promo de la línea por valor. Responde 204 sin body.
73
+ */
74
+ applyLinePromotion(
75
+ sessionId: string,
76
+ lineId: string,
77
+ body: ApplyLinePromotionRequest,
78
+ tenantId: string,
79
+ ): Promise<void>;
80
+
81
+ /**
82
+ * `PUT /private/wizard/sessions/{id}/lines/{anchorLineId}/gifts` (M2M de Promociones). Deja
83
+ * exactamente esos regalos en el ancla; `items: []` suelta todos.
84
+ */
85
+ setAnchorGifts(
86
+ sessionId: string,
87
+ anchorLineId: string,
88
+ body: SetAnchorGiftsRequest,
89
+ tenantId: string,
90
+ ): Promise<StandardResponse<SetAnchorGiftsResponse>>;
91
+
92
+ /**
93
+ * `PUT /private/wizard/sessions/{id}/sale-promotion` (M2M de Promociones). Ambos campos en `null`
94
+ * es «Ninguna». Responde 204 sin body.
95
+ */
96
+ applySalePromotion(
97
+ sessionId: string,
98
+ body: ApplySalePromotionRequest,
99
+ tenantId: string,
100
+ ): Promise<void>;
101
+
102
+ /** `GET /private/wizard/sessions/{id}`: la sesión como la lee Promociones (líneas, ancla, promo de venta). */
103
+ getPrivateWizardSession(
104
+ sessionId: string,
105
+ tenantId: string,
106
+ ): Promise<StandardResponse<PrivateWizardSessionResponse>>;
62
107
  }
@@ -1,2 +1,4 @@
1
1
  export * from "./api/interfaces/IRetailWizardBusinessApi.js";
2
2
  export { default as RetailWizardBusinessApi } from "./api/RetailWizardBusinessApi.js";
3
+ export * from "./queue/interfaces/IRetailPromotionInboundPublisher.js";
4
+ export * from "./queue/RetailPromotionInboundPublisher.js";
@@ -0,0 +1,25 @@
1
+ import { SendMessageCommand, SendMessageRequest, SQSClient } from "@aws-sdk/client-sqs";
2
+ import { injectable } from "inversify";
3
+ import type { RetailPromotionInboundMessage } from "@fiado/type-kit/bin/retailWizard/index.js";
4
+ import { IRetailPromotionInboundPublisher } from "./interfaces/IRetailPromotionInboundPublisher.js";
5
+
6
+ @injectable()
7
+ export class RetailPromotionInboundPublisher implements IRetailPromotionInboundPublisher {
8
+ private readonly RETAIL_PROMOTION_INBOUND_QUEUE_URL = process.env.RETAIL_PROMOTION_INBOUND_QUEUE_URL;
9
+
10
+ async publish(message: RetailPromotionInboundMessage): Promise<void> {
11
+ try {
12
+ const client: SQSClient = new SQSClient();
13
+ // Cola estándar: sin MessageGroupId; el consumidor deduplica por venta.
14
+ const sendMessageRequest: SendMessageRequest = {
15
+ QueueUrl: this.RETAIL_PROMOTION_INBOUND_QUEUE_URL,
16
+ MessageBody: JSON.stringify(message),
17
+ };
18
+ const command: SendMessageCommand = new SendMessageCommand(sendMessageRequest);
19
+ await client.send(command);
20
+ } catch (error) {
21
+ const errorMessage = error instanceof Error ? error.message : String(error);
22
+ throw new Error(`Error publishing message to RetailPromotionInboundQueue: ${errorMessage}`);
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,9 @@
1
+ import type { RetailPromotionInboundMessage } from "@fiado/type-kit/bin/retailWizard/index.js";
2
+
3
+ /**
4
+ * Publisher hacia `RetailPromotionInboundQueue` (SALE_CONFIRMED | SALE_CANCELLED), que consume `retail-promotions`.
5
+ * Env var requerida en el productor: `RETAIL_PROMOTION_INBOUND_QUEUE_URL`.
6
+ */
7
+ export interface IRetailPromotionInboundPublisher {
8
+ publish(message: RetailPromotionInboundMessage): Promise<void>;
9
+ }