@fiado/type-kit 3.475.0 → 3.476.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 (30) hide show
  1. package/_test_/unit/retailCatalog/catalogDebt.test.ts +17 -0
  2. package/_test_/unit/retailPromotions/constants.test.ts +6 -1
  3. package/_test_/unit/retailPromotions/discountCodeAndWizardRequests.test.ts +32 -3
  4. package/_test_/unit/retailPromotions/evaluatedSalePromotion.test.ts +2 -0
  5. package/_test_/unit/retailPromotions/resolveSalePromotionKind.test.ts +46 -0
  6. package/bin/retailCatalog/dtos/responses/GetInventorySkuResponse.d.ts +2 -0
  7. package/bin/retailPromotions/constants/retailPromotionsErrorHttpStatus.js +1 -0
  8. package/bin/retailPromotions/dtos/requests/HoldGiftPromotionInput.d.ts +6 -0
  9. package/bin/retailPromotions/dtos/requests/HoldGiftPromotionInput.js +38 -0
  10. package/bin/retailPromotions/dtos/requests/HoldSalePromotionRequest.d.ts +14 -4
  11. package/bin/retailPromotions/dtos/requests/HoldSalePromotionRequest.js +12 -3
  12. package/bin/retailPromotions/dtos/responses/WizardSalePromotionResponses.d.ts +13 -2
  13. package/bin/retailPromotions/enums/RetailPromotionsErrorCodeEnum.d.ts +2 -0
  14. package/bin/retailPromotions/enums/RetailPromotionsErrorCodeEnum.js +2 -0
  15. package/bin/retailPromotions/enums/SalePromotionKindEnum.d.ts +8 -0
  16. package/bin/retailPromotions/enums/SalePromotionKindEnum.js +12 -0
  17. package/bin/retailPromotions/helpers/resolveSalePromotionKind.d.ts +4 -0
  18. package/bin/retailPromotions/helpers/resolveSalePromotionKind.js +10 -0
  19. package/bin/retailPromotions/index.d.ts +3 -0
  20. package/bin/retailPromotions/index.js +3 -0
  21. package/package.json +1 -1
  22. package/src/retailCatalog/dtos/responses/GetInventorySkuResponse.ts +2 -0
  23. package/src/retailPromotions/constants/retailPromotionsErrorHttpStatus.ts +1 -0
  24. package/src/retailPromotions/dtos/requests/HoldGiftPromotionInput.ts +22 -0
  25. package/src/retailPromotions/dtos/requests/HoldSalePromotionRequest.ts +22 -6
  26. package/src/retailPromotions/dtos/responses/WizardSalePromotionResponses.ts +14 -2
  27. package/src/retailPromotions/enums/RetailPromotionsErrorCodeEnum.ts +2 -0
  28. package/src/retailPromotions/enums/SalePromotionKindEnum.ts +8 -0
  29. package/src/retailPromotions/helpers/resolveSalePromotionKind.ts +8 -0
  30. package/src/retailPromotions/index.ts +3 -0
@@ -121,3 +121,20 @@ describe('InventoryMovementEntry — reason', () => {
121
121
  expect(base.reason).toBeUndefined();
122
122
  });
123
123
  });
124
+
125
+ describe('InventoryMovementEntry — movementId', () => {
126
+ it('expone el id del MOV# y sigue válido sin él', () => {
127
+ const base: InventoryMovementEntry = {
128
+ storeId: 'ST-1',
129
+ sku: 'PH-A15',
130
+ type: InventoryMovementTypeEnum.ADJUSTMENT,
131
+ qty: 1,
132
+ identifier: null,
133
+ occurredAt: '2026-09-28T10:00:00.000Z',
134
+ createdBy: 'user-1',
135
+ };
136
+ const withId: InventoryMovementEntry = { ...base, movementId: 'MOV#01J9ZK' };
137
+ expect(withId.movementId).toBe('MOV#01J9ZK');
138
+ expect(base.movementId).toBeUndefined();
139
+ });
140
+ });
@@ -43,7 +43,12 @@ describe('catálogo de errores', () => {
43
43
  expect(RETAIL_PROMOTIONS_ERROR_HTTP_STATUS.CODE_NOT_FOUND).toBe(404);
44
44
  expect(RETAIL_PROMOTIONS_ERROR_HTTP_STATUS.DISCOUNT_AFTER_QUOTE).toBe(409);
45
45
  expect(RETAIL_PROMOTIONS_ERROR_HTTP_STATUS.CODE_NOT_OWNED).toBe(422);
46
- expect(Object.keys(RetailPromotionsErrorCodeEnum)).toHaveLength(20);
46
+ expect(Object.keys(RetailPromotionsErrorCodeEnum)).toHaveLength(21);
47
+ });
48
+
49
+ it('promo de regalo y de venta mandadas en el campo equivocado son 422', () => {
50
+ expect(RetailPromotionsErrorCodeEnum.PROMOTION_KIND_MISMATCH).toBe('PROMOTION_KIND_MISMATCH');
51
+ expect(RETAIL_PROMOTIONS_ERROR_HTTP_STATUS.PROMOTION_KIND_MISMATCH).toBe(422);
47
52
  });
48
53
 
49
54
  it('promo o cupón de venta inexistentes son 404; sesión sin retailer o tienda es 403', () => {
@@ -72,16 +72,45 @@ describe('piezas del wizard', () => {
72
72
  it('apartar acepta null como «Ninguna» y valida versión entera y SKUs de regalo', async () => {
73
73
  expect(await errorPaths(HoldSalePromotionRequest, { promotionId: null, discountCode: null })).toHaveLength(0);
74
74
  expect(
75
- await errorPaths(HoldSalePromotionRequest, { promotionId: 'p1', promotionVersion: 2, giftSkus: ['SKU-9'] }),
75
+ await errorPaths(HoldSalePromotionRequest, { promotionId: 'p1', promotionVersion: 2, saleGiftSkus: ['SKU-9'] }),
76
76
  ).toHaveLength(0);
77
77
  expect(
78
- await errorPaths(HoldSalePromotionRequest, { promotionId: 'p1', promotionVersion: '2', giftSkus: [1] }),
79
- ).toEqual(expect.arrayContaining(['promotionVersion', 'giftSkus']));
78
+ await errorPaths(HoldSalePromotionRequest, { promotionId: 'p1', promotionVersion: '2', saleGiftSkus: [1] }),
79
+ ).toEqual(expect.arrayContaining(['promotionVersion', 'saleGiftSkus']));
80
80
  });
81
81
 
82
82
  it('apartar pide versión cuando trae promo', async () => {
83
83
  expect(await errorPaths(HoldSalePromotionRequest, { promotionId: 'p1' })).toContain('promotionVersion');
84
84
  });
85
+
86
+ describe('gift (promo de regalo del teléfono)', () => {
87
+ const gift = { promotionId: 'g1', promotionVersion: 1, skus: ['SKU-1'] };
88
+
89
+ it('acepta la promo de regalo junto a la de venta, o null como sin regalo', async () => {
90
+ expect(
91
+ await errorPaths(HoldSalePromotionRequest, { gift, promotionId: 'p1', promotionVersion: 2 }),
92
+ ).toHaveLength(0);
93
+ expect(await errorPaths(HoldSalePromotionRequest, { gift, promotionId: null })).toHaveLength(0);
94
+ expect(await errorPaths(HoldSalePromotionRequest, { gift: null })).toHaveLength(0);
95
+ });
96
+
97
+ it('exige promotionId, versión desde 1 y al menos un sku no vacío', async () => {
98
+ const paths = await errorPaths(HoldSalePromotionRequest, {
99
+ gift: { promotionId: '', promotionVersion: 0, skus: [] },
100
+ });
101
+ expect(paths).toEqual(
102
+ expect.arrayContaining(['gift.promotionId', 'gift.promotionVersion', 'gift.skus']),
103
+ );
104
+ expect(await errorPaths(HoldSalePromotionRequest, { gift: { ...gift, skus: [''] } })).toContain('gift.skus');
105
+ expect(await errorPaths(HoldSalePromotionRequest, { gift: { ...gift, promotionVersion: 1.5 } })).toContain(
106
+ 'gift.promotionVersion',
107
+ );
108
+ });
109
+
110
+ it('rechaza un gift que no es objeto', async () => {
111
+ expect(await errorPaths(HoldSalePromotionRequest, { gift: 'g1' })).toContain('gift');
112
+ });
113
+ });
85
114
  });
86
115
 
87
116
  describe('GetSaleCouponQuery', () => {
@@ -2,11 +2,13 @@ import 'reflect-metadata';
2
2
  import {
3
3
  EvaluatedSalePromotion,
4
4
  RetailPromotionsErrorCodeEnum,
5
+ SalePromotionKindEnum,
5
6
  } from '../../../src/retailPromotions/index';
6
7
 
7
8
  const basePromotion: EvaluatedSalePromotion = {
8
9
  promotionId: 'promo-1',
9
10
  version: 1,
11
+ kind: SalePromotionKindEnum.SALE,
10
12
  name: 'Regalo',
11
13
  customerText: 'Llévate un regalo',
12
14
  levers: [],
@@ -0,0 +1,46 @@
1
+ import 'reflect-metadata';
2
+ import {
3
+ EvaluatedSalePromotion,
4
+ SalePromotionKindEnum,
5
+ SalePromotionLeverEnum,
6
+ resolveSalePromotionKind,
7
+ } from '../../../src/retailPromotions/index';
8
+
9
+ describe('resolveSalePromotionKind', () => {
10
+ it('devuelve GIFT cuando la única palanca es el regalo', () => {
11
+ expect(resolveSalePromotionKind([SalePromotionLeverEnum.GIFT])).toBe(SalePromotionKindEnum.GIFT);
12
+ });
13
+
14
+ it('devuelve SALE cuando el regalo viene con otras palancas', () => {
15
+ expect(
16
+ resolveSalePromotionKind([SalePromotionLeverEnum.GIFT, SalePromotionLeverEnum.DEVICE_DISCOUNT]),
17
+ ).toBe(SalePromotionKindEnum.SALE);
18
+ });
19
+
20
+ it('devuelve SALE cuando no hay regalo', () => {
21
+ expect(resolveSalePromotionKind([SalePromotionLeverEnum.COUPON])).toBe(SalePromotionKindEnum.SALE);
22
+ });
23
+
24
+ it('devuelve SALE sin palancas', () => {
25
+ expect(resolveSalePromotionKind([])).toBe(SalePromotionKindEnum.SALE);
26
+ });
27
+ });
28
+
29
+ describe('EvaluatedSalePromotion.kind', () => {
30
+ it('lleva el tipo de promo', () => {
31
+ const promotion: EvaluatedSalePromotion = {
32
+ promotionId: 'g1',
33
+ version: 1,
34
+ kind: SalePromotionKindEnum.GIFT,
35
+ name: 'Regalo',
36
+ customerText: 'Llévate un regalo',
37
+ levers: [SalePromotionLeverEnum.GIFT],
38
+ lines: [],
39
+ totalDiscountCents: 0,
40
+ giftOptions: [],
41
+ giftChooseCount: 1,
42
+ afterSale: [],
43
+ };
44
+ expect(promotion.kind).toBe(SalePromotionKindEnum.GIFT);
45
+ });
46
+ });
@@ -14,6 +14,8 @@ export interface InventoryMovementEntry {
14
14
  createdBy: string;
15
15
  /** Motivo guardado en el MOV#; ausente en los tipos que no llevan motivo. */
16
16
  reason?: InventoryMovementReasonEnum;
17
+ /** Id del MOV#, para ligar un ajuste con reversesMovementId. */
18
+ movementId?: string;
17
19
  }
18
20
  /** Pieza de una tienda; status AVAILABLE, SOLD o DAMAGED. */
19
21
  export interface InventoryPieceEntry {
@@ -22,6 +22,7 @@ exports.RETAIL_PROMOTIONS_ERROR_HTTP_STATUS = {
22
22
  [RetailPromotionsErrorCodeEnum_1.RetailPromotionsErrorCodeEnum.INVALID_DISCOUNT_CODE]: 422,
23
23
  [RetailPromotionsErrorCodeEnum_1.RetailPromotionsErrorCodeEnum.SALE_PROMOTION_NOT_FOUND]: 404,
24
24
  [RetailPromotionsErrorCodeEnum_1.RetailPromotionsErrorCodeEnum.SALE_COUPON_NOT_FOUND]: 404,
25
+ [RetailPromotionsErrorCodeEnum_1.RetailPromotionsErrorCodeEnum.PROMOTION_KIND_MISMATCH]: 422,
25
26
  [RetailPromotionsErrorCodeEnum_1.RetailPromotionsErrorCodeEnum.MISSING_RETAILER_SCOPE]: 403,
26
27
  [RetailPromotionsErrorCodeEnum_1.RetailPromotionsErrorCodeEnum.MISSING_STORE_SCOPE]: 403,
27
28
  };
@@ -0,0 +1,6 @@
1
+ /** Promo de regalo del teléfono dentro del apartado, con los regalos que eligió el cliente. */
2
+ export declare class HoldGiftPromotionInput {
3
+ promotionId: string;
4
+ promotionVersion: number;
5
+ skus: string[];
6
+ }
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.HoldGiftPromotionInput = void 0;
13
+ const class_transformer_1 = require("class-transformer");
14
+ const class_validator_1 = require("class-validator");
15
+ /** Promo de regalo del teléfono dentro del apartado, con los regalos que eligió el cliente. */
16
+ class HoldGiftPromotionInput {
17
+ }
18
+ exports.HoldGiftPromotionInput = HoldGiftPromotionInput;
19
+ __decorate([
20
+ (0, class_transformer_1.Expose)(),
21
+ (0, class_validator_1.IsString)(),
22
+ (0, class_validator_1.IsNotEmpty)(),
23
+ __metadata("design:type", String)
24
+ ], HoldGiftPromotionInput.prototype, "promotionId", void 0);
25
+ __decorate([
26
+ (0, class_transformer_1.Expose)(),
27
+ (0, class_validator_1.IsInt)(),
28
+ (0, class_validator_1.Min)(1),
29
+ __metadata("design:type", Number)
30
+ ], HoldGiftPromotionInput.prototype, "promotionVersion", void 0);
31
+ __decorate([
32
+ (0, class_transformer_1.Expose)(),
33
+ (0, class_validator_1.IsArray)(),
34
+ (0, class_validator_1.ArrayMinSize)(1),
35
+ (0, class_validator_1.IsString)({ each: true }),
36
+ (0, class_validator_1.IsNotEmpty)({ each: true }),
37
+ __metadata("design:type", Array)
38
+ ], HoldGiftPromotionInput.prototype, "skus", void 0);
@@ -1,11 +1,21 @@
1
+ import { HoldGiftPromotionInput } from './HoldGiftPromotionInput';
1
2
  /**
2
- * Body de publicHoldSalePromotion (PUT, `sessionId` en el path). `promotionId: null` = «Ninguna»;
3
- * un PUT distinto reemplaza el apartado anterior.
3
+ * Body de publicHoldSalePromotion (PUT, `sessionId` en el path): hasta una promo de regalo, una de venta
4
+ * y un código. `null` en cada una = sin ella; un PUT distinto reemplaza el apartado anterior.
4
5
  */
5
6
  export declare class HoldSalePromotionRequest {
7
+ /**
8
+ * Promo de regalo del teléfono (su única palanca es el regalo).
9
+ * El lambda rechaza con PROMOTION_KIND_MISMATCH una promo de venta mandada aquí.
10
+ */
11
+ gift?: HoldGiftPromotionInput | null;
12
+ /**
13
+ * Promo de venta; `null` = «Ninguna».
14
+ * El lambda rechaza con PROMOTION_KIND_MISMATCH una promo de solo regalo mandada aquí.
15
+ */
6
16
  promotionId?: string | null;
7
17
  promotionVersion?: number | null;
8
- /** Regalos elegidos por el cliente, si la promo trae regalo. */
9
- giftSkus?: string[] | null;
18
+ /** Regalo incluido en la promo de venta, solo si esa promo además trae otras palancas. */
19
+ saleGiftSkus?: string[] | null;
10
20
  discountCode?: string | null;
11
21
  }
@@ -12,13 +12,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.HoldSalePromotionRequest = void 0;
13
13
  const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
+ const HoldGiftPromotionInput_1 = require("./HoldGiftPromotionInput");
15
16
  /**
16
- * Body de publicHoldSalePromotion (PUT, `sessionId` en el path). `promotionId: null` = «Ninguna»;
17
- * un PUT distinto reemplaza el apartado anterior.
17
+ * Body de publicHoldSalePromotion (PUT, `sessionId` en el path): hasta una promo de regalo, una de venta
18
+ * y un código. `null` en cada una = sin ella; un PUT distinto reemplaza el apartado anterior.
18
19
  */
19
20
  class HoldSalePromotionRequest {
20
21
  }
21
22
  exports.HoldSalePromotionRequest = HoldSalePromotionRequest;
23
+ __decorate([
24
+ (0, class_transformer_1.Expose)(),
25
+ (0, class_validator_1.IsOptional)(),
26
+ (0, class_validator_1.IsObject)(),
27
+ (0, class_validator_1.ValidateNested)(),
28
+ (0, class_transformer_1.Type)(() => HoldGiftPromotionInput_1.HoldGiftPromotionInput),
29
+ __metadata("design:type", HoldGiftPromotionInput_1.HoldGiftPromotionInput)
30
+ ], HoldSalePromotionRequest.prototype, "gift", void 0);
22
31
  __decorate([
23
32
  (0, class_transformer_1.Expose)(),
24
33
  (0, class_validator_1.IsOptional)(),
@@ -38,7 +47,7 @@ __decorate([
38
47
  (0, class_validator_1.IsArray)(),
39
48
  (0, class_validator_1.IsString)({ each: true }),
40
49
  __metadata("design:type", Array)
41
- ], HoldSalePromotionRequest.prototype, "giftSkus", void 0);
50
+ ], HoldSalePromotionRequest.prototype, "saleGiftSkus", void 0);
42
51
  __decorate([
43
52
  (0, class_transformer_1.Expose)(),
44
53
  (0, class_validator_1.IsOptional)(),
@@ -4,6 +4,7 @@ import { EntitlementKindEnum } from '../../enums/EntitlementKindEnum';
4
4
  import { EntitlementStateEnum } from '../../enums/EntitlementStateEnum';
5
5
  import { RetailPromotionsErrorCodeEnum } from '../../enums/RetailPromotionsErrorCodeEnum';
6
6
  import { SaleCouponAvailabilityEnum } from '../../enums/SaleCouponAvailabilityEnum';
7
+ import { SalePromotionKindEnum } from '../../enums/SalePromotionKindEnum';
7
8
  import { SalePromotionLeverEnum } from '../../enums/SalePromotionLeverEnum';
8
9
  import { DiscountValue } from '../DiscountValue';
9
10
  import { LinePromotionDiscount } from '../LinePromotionDiscount';
@@ -38,6 +39,8 @@ export interface AfterSaleBenefit {
38
39
  export interface EvaluatedSalePromotion {
39
40
  promotionId: string;
40
41
  version: number;
42
+ /** GIFT = solo regalo, se aparta por separado en `gift`; SALE = promo de venta. */
43
+ kind: SalePromotionKindEnum;
41
44
  name: string;
42
45
  customerText: string;
43
46
  levers: SalePromotionLeverEnum[];
@@ -61,13 +64,21 @@ export interface EvaluateSalePromotionsResponse {
61
64
  promotions: EvaluatedSalePromotion[];
62
65
  discountCode: EvaluatedDiscountCode | null;
63
66
  }
64
- /** Lo que quedó apartado y escrito en la sesión. */
67
+ /** Promo de regalo del teléfono que quedó apartada. */
68
+ export interface HeldGiftPromotion {
69
+ promotionId: string;
70
+ promotionVersion: number;
71
+ skus: string[];
72
+ }
73
+ /** Lo que quedó apartado y escrito en la sesión: la promo de regalo, la de venta y el código. */
65
74
  export interface HoldSalePromotionResponse {
66
75
  sessionId: string;
76
+ gift: HeldGiftPromotion | null;
67
77
  promotionId: string | null;
68
78
  promotionVersion: number | null;
69
79
  discountCode: string | null;
70
- giftSkus: string[];
80
+ /** Regalo incluido en la promo de venta; vacío si no trae. */
81
+ saleGiftSkus: string[];
71
82
  lines: LinePromotionDiscount[];
72
83
  totalDiscountCents: number;
73
84
  }
@@ -22,6 +22,8 @@ export declare enum RetailPromotionsErrorCodeEnum {
22
22
  INVALID_DISCOUNT_CODE = "INVALID_DISCOUNT_CODE",
23
23
  SALE_PROMOTION_NOT_FOUND = "SALE_PROMOTION_NOT_FOUND",
24
24
  SALE_COUPON_NOT_FOUND = "SALE_COUPON_NOT_FOUND",
25
+ /** Promo de solo regalo mandada como promo de venta, o promo de venta mandada en `gift`. */
26
+ PROMOTION_KIND_MISMATCH = "PROMOTION_KIND_MISMATCH",
25
27
  /** La sesión no trae retailer: no se puede acotar la consulta. */
26
28
  MISSING_RETAILER_SCOPE = "MISSING_RETAILER_SCOPE",
27
29
  /** La sesión no trae tienda: no se puede acotar la consulta. */
@@ -26,6 +26,8 @@ var RetailPromotionsErrorCodeEnum;
26
26
  RetailPromotionsErrorCodeEnum["INVALID_DISCOUNT_CODE"] = "INVALID_DISCOUNT_CODE";
27
27
  RetailPromotionsErrorCodeEnum["SALE_PROMOTION_NOT_FOUND"] = "SALE_PROMOTION_NOT_FOUND";
28
28
  RetailPromotionsErrorCodeEnum["SALE_COUPON_NOT_FOUND"] = "SALE_COUPON_NOT_FOUND";
29
+ /** Promo de solo regalo mandada como promo de venta, o promo de venta mandada en `gift`. */
30
+ RetailPromotionsErrorCodeEnum["PROMOTION_KIND_MISMATCH"] = "PROMOTION_KIND_MISMATCH";
29
31
  /** La sesión no trae retailer: no se puede acotar la consulta. */
30
32
  RetailPromotionsErrorCodeEnum["MISSING_RETAILER_SCOPE"] = "MISSING_RETAILER_SCOPE";
31
33
  /** La sesión no trae tienda: no se puede acotar la consulta. */
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Tipo de promo en el apartado: GIFT solo trae regalo y va ligada al teléfono; SALE es cualquier otra.
3
+ * @enum {string}
4
+ */
5
+ export declare enum SalePromotionKindEnum {
6
+ GIFT = "GIFT",
7
+ SALE = "SALE"
8
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SalePromotionKindEnum = void 0;
4
+ /**
5
+ * Tipo de promo en el apartado: GIFT solo trae regalo y va ligada al teléfono; SALE es cualquier otra.
6
+ * @enum {string}
7
+ */
8
+ var SalePromotionKindEnum;
9
+ (function (SalePromotionKindEnum) {
10
+ SalePromotionKindEnum["GIFT"] = "GIFT";
11
+ SalePromotionKindEnum["SALE"] = "SALE";
12
+ })(SalePromotionKindEnum || (exports.SalePromotionKindEnum = SalePromotionKindEnum = {}));
@@ -0,0 +1,4 @@
1
+ import { SalePromotionKindEnum } from '../enums/SalePromotionKindEnum';
2
+ import { SalePromotionLeverEnum } from '../enums/SalePromotionLeverEnum';
3
+ /** GIFT si la única palanca de la promo es el regalo; SALE en cualquier otro caso. */
4
+ export declare function resolveSalePromotionKind(levers: readonly SalePromotionLeverEnum[]): SalePromotionKindEnum;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveSalePromotionKind = resolveSalePromotionKind;
4
+ const SalePromotionKindEnum_1 = require("../enums/SalePromotionKindEnum");
5
+ const SalePromotionLeverEnum_1 = require("../enums/SalePromotionLeverEnum");
6
+ /** GIFT si la única palanca de la promo es el regalo; SALE en cualquier otro caso. */
7
+ function resolveSalePromotionKind(levers) {
8
+ const onlyGift = levers.length > 0 && levers.every((lever) => lever === SalePromotionLeverEnum_1.SalePromotionLeverEnum.GIFT);
9
+ return onlyGift ? SalePromotionKindEnum_1.SalePromotionKindEnum.GIFT : SalePromotionKindEnum_1.SalePromotionKindEnum.SALE;
10
+ }
@@ -16,11 +16,13 @@ export * from './enums/EntitlementStateEnum';
16
16
  export * from './enums/EntitlementKindEnum';
17
17
  export * from './enums/SaleCouponAvailabilityEnum';
18
18
  export * from './enums/RetailPromotionsErrorCodeEnum';
19
+ export * from './enums/SalePromotionKindEnum';
19
20
  export * from './constants/retailPromotionsErrorHttpStatus';
20
21
  export * from './constants/salePromotionTransitions';
21
22
  export * from './constants/bonusPreMoney';
22
23
  export * from './helpers/resolveSalePromotionTransition';
23
24
  export * from './helpers/computeBudgetUsedBps';
25
+ export * from './helpers/resolveSalePromotionKind';
24
26
  export * from './dtos/DiscountValue';
25
27
  export * from './dtos/SalePromotionLevers';
26
28
  export * from './dtos/SalePromotion';
@@ -40,6 +42,7 @@ export * from './dtos/requests/ListDiscountCodesQuery';
40
42
  export * from './dtos/requests/ChangeDiscountCodeStatusRequest';
41
43
  export * from './dtos/requests/ListStoreSalePromotionsQuery';
42
44
  export * from './dtos/requests/EvaluateSalePromotionsRequest';
45
+ export * from './dtos/requests/HoldGiftPromotionInput';
43
46
  export * from './dtos/requests/HoldSalePromotionRequest';
44
47
  export * from './dtos/requests/GetSaleCouponQuery';
45
48
  export * from './dtos/responses/SalePromotionCrudResponses';
@@ -33,12 +33,14 @@ __exportStar(require("./enums/EntitlementStateEnum"), exports);
33
33
  __exportStar(require("./enums/EntitlementKindEnum"), exports);
34
34
  __exportStar(require("./enums/SaleCouponAvailabilityEnum"), exports);
35
35
  __exportStar(require("./enums/RetailPromotionsErrorCodeEnum"), exports);
36
+ __exportStar(require("./enums/SalePromotionKindEnum"), exports);
36
37
  // Constantes y helpers puros
37
38
  __exportStar(require("./constants/retailPromotionsErrorHttpStatus"), exports);
38
39
  __exportStar(require("./constants/salePromotionTransitions"), exports);
39
40
  __exportStar(require("./constants/bonusPreMoney"), exports);
40
41
  __exportStar(require("./helpers/resolveSalePromotionTransition"), exports);
41
42
  __exportStar(require("./helpers/computeBudgetUsedBps"), exports);
43
+ __exportStar(require("./helpers/resolveSalePromotionKind"), exports);
42
44
  // Entidades del dominio
43
45
  __exportStar(require("./dtos/DiscountValue"), exports);
44
46
  __exportStar(require("./dtos/SalePromotionLevers"), exports);
@@ -60,6 +62,7 @@ __exportStar(require("./dtos/requests/ListDiscountCodesQuery"), exports);
60
62
  __exportStar(require("./dtos/requests/ChangeDiscountCodeStatusRequest"), exports);
61
63
  __exportStar(require("./dtos/requests/ListStoreSalePromotionsQuery"), exports);
62
64
  __exportStar(require("./dtos/requests/EvaluateSalePromotionsRequest"), exports);
65
+ __exportStar(require("./dtos/requests/HoldGiftPromotionInput"), exports);
63
66
  __exportStar(require("./dtos/requests/HoldSalePromotionRequest"), exports);
64
67
  __exportStar(require("./dtos/requests/GetSaleCouponQuery"), exports);
65
68
  // Response DTOs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fiado/type-kit",
3
- "version": "3.475.0",
3
+ "version": "3.476.0",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "types": "bin/index.d.ts",
@@ -15,6 +15,8 @@ export interface InventoryMovementEntry {
15
15
  createdBy: string;
16
16
  /** Motivo guardado en el MOV#; ausente en los tipos que no llevan motivo. */
17
17
  reason?: InventoryMovementReasonEnum;
18
+ /** Id del MOV#, para ligar un ajuste con reversesMovementId. */
19
+ movementId?: string;
18
20
  }
19
21
 
20
22
  /** Pieza de una tienda; status AVAILABLE, SOLD o DAMAGED. */
@@ -20,6 +20,7 @@ export const RETAIL_PROMOTIONS_ERROR_HTTP_STATUS: Readonly<Record<C, 403 | 404 |
20
20
  [C.INVALID_DISCOUNT_CODE]: 422,
21
21
  [C.SALE_PROMOTION_NOT_FOUND]: 404,
22
22
  [C.SALE_COUPON_NOT_FOUND]: 404,
23
+ [C.PROMOTION_KIND_MISMATCH]: 422,
23
24
  [C.MISSING_RETAILER_SCOPE]: 403,
24
25
  [C.MISSING_STORE_SCOPE]: 403,
25
26
  };
@@ -0,0 +1,22 @@
1
+ import { Expose } from 'class-transformer';
2
+ import { ArrayMinSize, IsArray, IsInt, IsNotEmpty, IsString, Min } from 'class-validator';
3
+
4
+ /** Promo de regalo del teléfono dentro del apartado, con los regalos que eligió el cliente. */
5
+ export class HoldGiftPromotionInput {
6
+ @Expose()
7
+ @IsString()
8
+ @IsNotEmpty()
9
+ promotionId!: string;
10
+
11
+ @Expose()
12
+ @IsInt()
13
+ @Min(1)
14
+ promotionVersion!: number;
15
+
16
+ @Expose()
17
+ @IsArray()
18
+ @ArrayMinSize(1)
19
+ @IsString({ each: true })
20
+ @IsNotEmpty({ each: true })
21
+ skus!: string[];
22
+ }
@@ -1,11 +1,27 @@
1
- import { Expose } from 'class-transformer';
2
- import { IsArray, IsInt, IsNotEmpty, IsOptional, IsString, ValidateIf } from 'class-validator';
1
+ import { Expose, Type } from 'class-transformer';
2
+ import { IsArray, IsInt, IsNotEmpty, IsObject, IsOptional, IsString, ValidateIf, ValidateNested } from 'class-validator';
3
+ import { HoldGiftPromotionInput } from './HoldGiftPromotionInput';
3
4
 
4
5
  /**
5
- * Body de publicHoldSalePromotion (PUT, `sessionId` en el path). `promotionId: null` = «Ninguna»;
6
- * un PUT distinto reemplaza el apartado anterior.
6
+ * Body de publicHoldSalePromotion (PUT, `sessionId` en el path): hasta una promo de regalo, una de venta
7
+ * y un código. `null` en cada una = sin ella; un PUT distinto reemplaza el apartado anterior.
7
8
  */
8
9
  export class HoldSalePromotionRequest {
10
+ /**
11
+ * Promo de regalo del teléfono (su única palanca es el regalo).
12
+ * El lambda rechaza con PROMOTION_KIND_MISMATCH una promo de venta mandada aquí.
13
+ */
14
+ @Expose()
15
+ @IsOptional()
16
+ @IsObject()
17
+ @ValidateNested()
18
+ @Type(() => HoldGiftPromotionInput)
19
+ gift?: HoldGiftPromotionInput | null;
20
+
21
+ /**
22
+ * Promo de venta; `null` = «Ninguna».
23
+ * El lambda rechaza con PROMOTION_KIND_MISMATCH una promo de solo regalo mandada aquí.
24
+ */
9
25
  @Expose()
10
26
  @IsOptional()
11
27
  @IsString()
@@ -17,12 +33,12 @@ export class HoldSalePromotionRequest {
17
33
  @IsInt()
18
34
  promotionVersion?: number | null;
19
35
 
20
- /** Regalos elegidos por el cliente, si la promo trae regalo. */
36
+ /** Regalo incluido en la promo de venta, solo si esa promo además trae otras palancas. */
21
37
  @Expose()
22
38
  @IsOptional()
23
39
  @IsArray()
24
40
  @IsString({ each: true })
25
- giftSkus?: string[] | null;
41
+ saleGiftSkus?: string[] | null;
26
42
 
27
43
  @Expose()
28
44
  @IsOptional()
@@ -4,6 +4,7 @@ import { EntitlementKindEnum } from '../../enums/EntitlementKindEnum';
4
4
  import { EntitlementStateEnum } from '../../enums/EntitlementStateEnum';
5
5
  import { RetailPromotionsErrorCodeEnum } from '../../enums/RetailPromotionsErrorCodeEnum';
6
6
  import { SaleCouponAvailabilityEnum } from '../../enums/SaleCouponAvailabilityEnum';
7
+ import { SalePromotionKindEnum } from '../../enums/SalePromotionKindEnum';
7
8
  import { SalePromotionLeverEnum } from '../../enums/SalePromotionLeverEnum';
8
9
  import { DiscountValue } from '../DiscountValue';
9
10
  import { LinePromotionDiscount } from '../LinePromotionDiscount';
@@ -43,6 +44,8 @@ export interface AfterSaleBenefit {
43
44
  export interface EvaluatedSalePromotion {
44
45
  promotionId: string;
45
46
  version: number;
47
+ /** GIFT = solo regalo, se aparta por separado en `gift`; SALE = promo de venta. */
48
+ kind: SalePromotionKindEnum;
46
49
  name: string;
47
50
  customerText: string;
48
51
  levers: SalePromotionLeverEnum[];
@@ -69,13 +72,22 @@ export interface EvaluateSalePromotionsResponse {
69
72
  discountCode: EvaluatedDiscountCode | null;
70
73
  }
71
74
 
72
- /** Lo que quedó apartado y escrito en la sesión. */
75
+ /** Promo de regalo del teléfono que quedó apartada. */
76
+ export interface HeldGiftPromotion {
77
+ promotionId: string;
78
+ promotionVersion: number;
79
+ skus: string[];
80
+ }
81
+
82
+ /** Lo que quedó apartado y escrito en la sesión: la promo de regalo, la de venta y el código. */
73
83
  export interface HoldSalePromotionResponse {
74
84
  sessionId: string;
85
+ gift: HeldGiftPromotion | null;
75
86
  promotionId: string | null;
76
87
  promotionVersion: number | null;
77
88
  discountCode: string | null;
78
- giftSkus: string[];
89
+ /** Regalo incluido en la promo de venta; vacío si no trae. */
90
+ saleGiftSkus: string[];
79
91
  lines: LinePromotionDiscount[];
80
92
  totalDiscountCents: number;
81
93
  }
@@ -22,6 +22,8 @@ export enum RetailPromotionsErrorCodeEnum {
22
22
  INVALID_DISCOUNT_CODE = 'INVALID_DISCOUNT_CODE',
23
23
  SALE_PROMOTION_NOT_FOUND = 'SALE_PROMOTION_NOT_FOUND',
24
24
  SALE_COUPON_NOT_FOUND = 'SALE_COUPON_NOT_FOUND',
25
+ /** Promo de solo regalo mandada como promo de venta, o promo de venta mandada en `gift`. */
26
+ PROMOTION_KIND_MISMATCH = 'PROMOTION_KIND_MISMATCH',
25
27
  /** La sesión no trae retailer: no se puede acotar la consulta. */
26
28
  MISSING_RETAILER_SCOPE = 'MISSING_RETAILER_SCOPE',
27
29
  /** La sesión no trae tienda: no se puede acotar la consulta. */
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Tipo de promo en el apartado: GIFT solo trae regalo y va ligada al teléfono; SALE es cualquier otra.
3
+ * @enum {string}
4
+ */
5
+ export enum SalePromotionKindEnum {
6
+ GIFT = 'GIFT',
7
+ SALE = 'SALE',
8
+ }
@@ -0,0 +1,8 @@
1
+ import { SalePromotionKindEnum } from '../enums/SalePromotionKindEnum';
2
+ import { SalePromotionLeverEnum } from '../enums/SalePromotionLeverEnum';
3
+
4
+ /** GIFT si la única palanca de la promo es el regalo; SALE en cualquier otro caso. */
5
+ export function resolveSalePromotionKind(levers: readonly SalePromotionLeverEnum[]): SalePromotionKindEnum {
6
+ const onlyGift = levers.length > 0 && levers.every((lever) => lever === SalePromotionLeverEnum.GIFT);
7
+ return onlyGift ? SalePromotionKindEnum.GIFT : SalePromotionKindEnum.SALE;
8
+ }
@@ -17,6 +17,7 @@ export * from './enums/EntitlementStateEnum';
17
17
  export * from './enums/EntitlementKindEnum';
18
18
  export * from './enums/SaleCouponAvailabilityEnum';
19
19
  export * from './enums/RetailPromotionsErrorCodeEnum';
20
+ export * from './enums/SalePromotionKindEnum';
20
21
 
21
22
  // Constantes y helpers puros
22
23
  export * from './constants/retailPromotionsErrorHttpStatus';
@@ -24,6 +25,7 @@ export * from './constants/salePromotionTransitions';
24
25
  export * from './constants/bonusPreMoney';
25
26
  export * from './helpers/resolveSalePromotionTransition';
26
27
  export * from './helpers/computeBudgetUsedBps';
28
+ export * from './helpers/resolveSalePromotionKind';
27
29
 
28
30
  // Entidades del dominio
29
31
  export * from './dtos/DiscountValue';
@@ -47,6 +49,7 @@ export * from './dtos/requests/ListDiscountCodesQuery';
47
49
  export * from './dtos/requests/ChangeDiscountCodeStatusRequest';
48
50
  export * from './dtos/requests/ListStoreSalePromotionsQuery';
49
51
  export * from './dtos/requests/EvaluateSalePromotionsRequest';
52
+ export * from './dtos/requests/HoldGiftPromotionInput';
50
53
  export * from './dtos/requests/HoldSalePromotionRequest';
51
54
  export * from './dtos/requests/GetSaleCouponQuery';
52
55