@fiado/type-kit 3.477.0 → 3.479.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/_test_/unit/retailPromotions/constants.test.ts +1 -1
- package/_test_/unit/retailPromotions/skuSalePromotions.test.ts +49 -0
- package/_test_/unit/retailWizard/promotionM2mRequests.test.ts +37 -0
- package/bin/retailPromotions/constants/retailPromotionsErrorHttpStatus.js +1 -0
- package/bin/retailPromotions/dtos/requests/SkuSalePromotionsQuery.d.ts +5 -0
- package/bin/retailPromotions/dtos/requests/SkuSalePromotionsQuery.js +30 -0
- package/bin/retailPromotions/dtos/responses/SkuSalePromotionsResponse.d.ts +6 -0
- package/bin/retailPromotions/dtos/responses/SkuSalePromotionsResponse.js +2 -0
- package/bin/retailPromotions/enums/RetailPromotionsErrorCodeEnum.d.ts +3 -1
- package/bin/retailPromotions/enums/RetailPromotionsErrorCodeEnum.js +2 -0
- package/bin/retailPromotions/index.d.ts +2 -0
- package/bin/retailPromotions/index.js +2 -0
- package/bin/retailWizard/dtos/requests/SetAnchorGiftsRequest.d.ts +3 -0
- package/bin/retailWizard/dtos/requests/SetAnchorGiftsRequest.js +18 -0
- package/package.json +1 -1
- package/src/retailPromotions/constants/retailPromotionsErrorHttpStatus.ts +1 -0
- package/src/retailPromotions/dtos/requests/SkuSalePromotionsQuery.ts +15 -0
- package/src/retailPromotions/dtos/responses/SkuSalePromotionsResponse.ts +7 -0
- package/src/retailPromotions/enums/RetailPromotionsErrorCodeEnum.ts +2 -0
- package/src/retailPromotions/index.ts +2 -0
- package/src/retailWizard/dtos/requests/SetAnchorGiftsRequest.ts +18 -0
|
@@ -43,7 +43,7 @@ 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(
|
|
46
|
+
expect(Object.keys(RetailPromotionsErrorCodeEnum)).toHaveLength(29);
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
it('promo de regalo y de venta mandadas en el campo equivocado son 422', () => {
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { plainToInstance } from 'class-transformer';
|
|
3
|
+
import { validate } from 'class-validator';
|
|
4
|
+
import {
|
|
5
|
+
RETAIL_PROMOTIONS_ERROR_HTTP_STATUS,
|
|
6
|
+
RetailPromotionsErrorCodeEnum,
|
|
7
|
+
SkuSalePromotionsQuery,
|
|
8
|
+
SkuSalePromotionsResponse,
|
|
9
|
+
} from '../../../src/retailPromotions/index';
|
|
10
|
+
|
|
11
|
+
const invalidProps = async (raw: Record<string, unknown>): Promise<string[]> => {
|
|
12
|
+
const errors = await validate(plainToInstance(SkuSalePromotionsQuery, raw) as object);
|
|
13
|
+
return errors.map((e) => e.property).sort();
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
describe('SkuSalePromotionsQuery', () => {
|
|
17
|
+
it('acepta sessionId y sku', async () => {
|
|
18
|
+
expect(await invalidProps({ sessionId: 'ses-1', sku: 'SKU-1' })).toEqual([]);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('exige ambos campos', async () => {
|
|
22
|
+
expect(await invalidProps({})).toEqual(['sessionId', 'sku']);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it.each([
|
|
26
|
+
['sessionId', { sessionId: '', sku: 'SKU-1' }],
|
|
27
|
+
['sku', { sessionId: 'ses-1', sku: '' }],
|
|
28
|
+
])('rechaza %s vacío', async (prop, raw) => {
|
|
29
|
+
expect(await invalidProps(raw)).toEqual([prop]);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('rechaza valores que no son texto', async () => {
|
|
33
|
+
expect(await invalidProps({ sessionId: 1, sku: ['SKU-1'] })).toEqual(['sessionId', 'sku']);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe('SkuSalePromotionsResponse', () => {
|
|
38
|
+
it('lleva el sku y sus promos evaluadas', () => {
|
|
39
|
+
const response: SkuSalePromotionsResponse = { sku: 'SKU-1', promotions: [] };
|
|
40
|
+
expect(response.promotions).toEqual([]);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('CATALOG_SKU_NOT_FOUND', () => {
|
|
45
|
+
it('es 404', () => {
|
|
46
|
+
expect(RetailPromotionsErrorCodeEnum.CATALOG_SKU_NOT_FOUND).toBe('CATALOG_SKU_NOT_FOUND');
|
|
47
|
+
expect(RETAIL_PROMOTIONS_ERROR_HTTP_STATUS.CATALOG_SKU_NOT_FOUND).toBe(404);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -83,6 +83,43 @@ describe('SetAnchorGiftsRequest', () => {
|
|
|
83
83
|
expect(errorsOf(SetAnchorGiftsRequest, { ...ok, items: [{ sku: '' }] })).toContain('items.0.sku'));
|
|
84
84
|
it('exige items como arreglo', () =>
|
|
85
85
|
expect(errorsOf(SetAnchorGiftsRequest, { promotionId: null, promotionVersion: null })).toContain('items'));
|
|
86
|
+
|
|
87
|
+
describe('promo por item', () => {
|
|
88
|
+
const own = { sku: 'CASE-1', promotionId: 'promo-2', promotionVersion: 3 };
|
|
89
|
+
|
|
90
|
+
it('acepta un item sin promo propia (usa la de la raíz)', () => {
|
|
91
|
+
const req = plainToInstance(SetAnchorGiftsRequest, ok);
|
|
92
|
+
expect(validateSync(req)).toEqual([]);
|
|
93
|
+
expect(req.items[0].promotionId).toBeUndefined();
|
|
94
|
+
expect(req.items[0].promotionVersion).toBeUndefined();
|
|
95
|
+
});
|
|
96
|
+
it('acepta un item con promotionId y promotionVersion', () =>
|
|
97
|
+
expect(errorsOf(SetAnchorGiftsRequest, { ...ok, items: [own] })).toEqual([]));
|
|
98
|
+
it('exige promotionVersion si el item trae solo promotionId', () =>
|
|
99
|
+
expect(errorsOf(SetAnchorGiftsRequest, { ...ok, items: [{ sku: 'CASE-1', promotionId: 'promo-2' }] })).toContain(
|
|
100
|
+
'items.0.promotionVersion',
|
|
101
|
+
));
|
|
102
|
+
it('exige promotionId si el item trae solo promotionVersion', () =>
|
|
103
|
+
expect(errorsOf(SetAnchorGiftsRequest, { ...ok, items: [{ sku: 'CASE-1', promotionVersion: 3 }] })).toContain(
|
|
104
|
+
'items.0.promotionId',
|
|
105
|
+
));
|
|
106
|
+
it('rechaza la versión 0 en el item', () =>
|
|
107
|
+
expect(errorsOf(SetAnchorGiftsRequest, { ...ok, items: [{ ...own, promotionVersion: 0 }] })).toContain(
|
|
108
|
+
'items.0.promotionVersion',
|
|
109
|
+
));
|
|
110
|
+
it('rechaza promotionId vacío en el item', () =>
|
|
111
|
+
expect(errorsOf(SetAnchorGiftsRequest, { ...ok, items: [{ ...own, promotionId: '' }] })).toContain(
|
|
112
|
+
'items.0.promotionId',
|
|
113
|
+
));
|
|
114
|
+
it('acepta dos items de la misma ancla con promos distintas', () => {
|
|
115
|
+
const req = plainToInstance(SetAnchorGiftsRequest, {
|
|
116
|
+
...ok,
|
|
117
|
+
items: [own, { sku: 'MICA-1', promotionId: 'promo-9', promotionVersion: 1 }],
|
|
118
|
+
});
|
|
119
|
+
expect(validateSync(req)).toEqual([]);
|
|
120
|
+
expect(req.items.map((i) => i.promotionId)).toEqual(['promo-2', 'promo-9']);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
86
123
|
});
|
|
87
124
|
|
|
88
125
|
describe('ApplySalePromotionRequest', () => {
|
|
@@ -32,4 +32,5 @@ exports.RETAIL_PROMOTIONS_ERROR_HTTP_STATUS = {
|
|
|
32
32
|
[RetailPromotionsErrorCodeEnum_1.RetailPromotionsErrorCodeEnum.PROMOTION_NOT_REVALIDATED]: 409,
|
|
33
33
|
[RetailPromotionsErrorCodeEnum_1.RetailPromotionsErrorCodeEnum.SALE_PROMOTION_HOLD_CONFLICT]: 409,
|
|
34
34
|
[RetailPromotionsErrorCodeEnum_1.RetailPromotionsErrorCodeEnum.INVALID_NEXT_TOKEN]: 400,
|
|
35
|
+
[RetailPromotionsErrorCodeEnum_1.RetailPromotionsErrorCodeEnum.CATALOG_SKU_NOT_FOUND]: 404,
|
|
35
36
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
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.SkuSalePromotionsQuery = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
/** Query de publicListSkuSalePromotions; precio, tienda y cliente salen de la sesión y del catálogo. */
|
|
16
|
+
class SkuSalePromotionsQuery {
|
|
17
|
+
}
|
|
18
|
+
exports.SkuSalePromotionsQuery = SkuSalePromotionsQuery;
|
|
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
|
+
], SkuSalePromotionsQuery.prototype, "sessionId", void 0);
|
|
25
|
+
__decorate([
|
|
26
|
+
(0, class_transformer_1.Expose)(),
|
|
27
|
+
(0, class_validator_1.IsString)(),
|
|
28
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
29
|
+
__metadata("design:type", String)
|
|
30
|
+
], SkuSalePromotionsQuery.prototype, "sku", void 0);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { EvaluatedSalePromotion } from './WizardSalePromotionResponses';
|
|
2
|
+
/** Promos que aplicarían si el SKU fuera la ancla de la sesión, con sus opciones de regalo. */
|
|
3
|
+
export interface SkuSalePromotionsResponse {
|
|
4
|
+
sku: string;
|
|
5
|
+
promotions: EvaluatedSalePromotion[];
|
|
6
|
+
}
|
|
@@ -40,5 +40,7 @@ export declare enum RetailPromotionsErrorCodeEnum {
|
|
|
40
40
|
/** Otra venta ya retiene la promo. */
|
|
41
41
|
SALE_PROMOTION_HOLD_CONFLICT = "SALE_PROMOTION_HOLD_CONFLICT",
|
|
42
42
|
/** El token de paginación no es válido. */
|
|
43
|
-
INVALID_NEXT_TOKEN = "INVALID_NEXT_TOKEN"
|
|
43
|
+
INVALID_NEXT_TOKEN = "INVALID_NEXT_TOKEN",
|
|
44
|
+
/** El SKU no existe en el catálogo. */
|
|
45
|
+
CATALOG_SKU_NOT_FOUND = "CATALOG_SKU_NOT_FOUND"
|
|
44
46
|
}
|
|
@@ -45,4 +45,6 @@ var RetailPromotionsErrorCodeEnum;
|
|
|
45
45
|
RetailPromotionsErrorCodeEnum["SALE_PROMOTION_HOLD_CONFLICT"] = "SALE_PROMOTION_HOLD_CONFLICT";
|
|
46
46
|
/** El token de paginación no es válido. */
|
|
47
47
|
RetailPromotionsErrorCodeEnum["INVALID_NEXT_TOKEN"] = "INVALID_NEXT_TOKEN";
|
|
48
|
+
/** El SKU no existe en el catálogo. */
|
|
49
|
+
RetailPromotionsErrorCodeEnum["CATALOG_SKU_NOT_FOUND"] = "CATALOG_SKU_NOT_FOUND";
|
|
48
50
|
})(RetailPromotionsErrorCodeEnum || (exports.RetailPromotionsErrorCodeEnum = RetailPromotionsErrorCodeEnum = {}));
|
|
@@ -45,6 +45,8 @@ export * from './dtos/requests/EvaluateSalePromotionsRequest';
|
|
|
45
45
|
export * from './dtos/requests/HoldGiftPromotionInput';
|
|
46
46
|
export * from './dtos/requests/HoldSalePromotionRequest';
|
|
47
47
|
export * from './dtos/requests/GetSaleCouponQuery';
|
|
48
|
+
export * from './dtos/requests/SkuSalePromotionsQuery';
|
|
48
49
|
export * from './dtos/responses/SalePromotionCrudResponses';
|
|
49
50
|
export * from './dtos/responses/DiscountCodeResponses';
|
|
50
51
|
export * from './dtos/responses/WizardSalePromotionResponses';
|
|
52
|
+
export * from './dtos/responses/SkuSalePromotionsResponse';
|
|
@@ -65,7 +65,9 @@ __exportStar(require("./dtos/requests/EvaluateSalePromotionsRequest"), exports);
|
|
|
65
65
|
__exportStar(require("./dtos/requests/HoldGiftPromotionInput"), exports);
|
|
66
66
|
__exportStar(require("./dtos/requests/HoldSalePromotionRequest"), exports);
|
|
67
67
|
__exportStar(require("./dtos/requests/GetSaleCouponQuery"), exports);
|
|
68
|
+
__exportStar(require("./dtos/requests/SkuSalePromotionsQuery"), exports);
|
|
68
69
|
// Response DTOs
|
|
69
70
|
__exportStar(require("./dtos/responses/SalePromotionCrudResponses"), exports);
|
|
70
71
|
__exportStar(require("./dtos/responses/DiscountCodeResponses"), exports);
|
|
71
72
|
__exportStar(require("./dtos/responses/WizardSalePromotionResponses"), exports);
|
|
73
|
+
__exportStar(require("./dtos/responses/SkuSalePromotionsResponse"), exports);
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/** Un regalo del conjunto que queda ligado al ancla. */
|
|
2
2
|
export declare class AnchorGiftItem {
|
|
3
3
|
sku: string;
|
|
4
|
+
/** Promo propia de esta línea GIFT; va junto con `promotionVersion` y, si falta, se usa la de la raíz. */
|
|
5
|
+
promotionId?: string;
|
|
6
|
+
promotionVersion?: number;
|
|
4
7
|
}
|
|
5
8
|
/**
|
|
6
9
|
* PUT /private/wizard/sessions/{id}/lines/{anchorLineId}/gifts (M2M de Promociones).
|
|
@@ -12,6 +12,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.SetAnchorGiftsRequest = exports.AnchorGiftItem = void 0;
|
|
13
13
|
const class_transformer_1 = require("class-transformer");
|
|
14
14
|
const class_validator_1 = require("class-validator");
|
|
15
|
+
/** Hay que validar la promo del item si vino cualquiera de sus dos campos. */
|
|
16
|
+
function hasOwnPromotion(o) {
|
|
17
|
+
return o.promotionId !== undefined || o.promotionVersion !== undefined;
|
|
18
|
+
}
|
|
15
19
|
/** Un regalo del conjunto que queda ligado al ancla. */
|
|
16
20
|
class AnchorGiftItem {
|
|
17
21
|
}
|
|
@@ -22,6 +26,20 @@ __decorate([
|
|
|
22
26
|
(0, class_validator_1.IsNotEmpty)(),
|
|
23
27
|
__metadata("design:type", String)
|
|
24
28
|
], AnchorGiftItem.prototype, "sku", void 0);
|
|
29
|
+
__decorate([
|
|
30
|
+
(0, class_transformer_1.Expose)(),
|
|
31
|
+
(0, class_validator_1.ValidateIf)(hasOwnPromotion),
|
|
32
|
+
(0, class_validator_1.IsString)(),
|
|
33
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
34
|
+
__metadata("design:type", String)
|
|
35
|
+
], AnchorGiftItem.prototype, "promotionId", void 0);
|
|
36
|
+
__decorate([
|
|
37
|
+
(0, class_transformer_1.Expose)(),
|
|
38
|
+
(0, class_validator_1.ValidateIf)(hasOwnPromotion),
|
|
39
|
+
(0, class_validator_1.IsInt)(),
|
|
40
|
+
(0, class_validator_1.Min)(1),
|
|
41
|
+
__metadata("design:type", Number)
|
|
42
|
+
], AnchorGiftItem.prototype, "promotionVersion", void 0);
|
|
25
43
|
/** Hay que validar el campo si hay regalos o si vino con valor. */
|
|
26
44
|
function mustValidate(o, value) {
|
|
27
45
|
return (Array.isArray(o.items) && o.items.length > 0) || (value !== null && value !== undefined);
|
package/package.json
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Expose } from 'class-transformer';
|
|
2
|
+
import { IsNotEmpty, IsString } from 'class-validator';
|
|
3
|
+
|
|
4
|
+
/** Query de publicListSkuSalePromotions; precio, tienda y cliente salen de la sesión y del catálogo. */
|
|
5
|
+
export class SkuSalePromotionsQuery {
|
|
6
|
+
@Expose()
|
|
7
|
+
@IsString()
|
|
8
|
+
@IsNotEmpty()
|
|
9
|
+
sessionId!: string;
|
|
10
|
+
|
|
11
|
+
@Expose()
|
|
12
|
+
@IsString()
|
|
13
|
+
@IsNotEmpty()
|
|
14
|
+
sku!: string;
|
|
15
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { EvaluatedSalePromotion } from './WizardSalePromotionResponses';
|
|
2
|
+
|
|
3
|
+
/** Promos que aplicarían si el SKU fuera la ancla de la sesión, con sus opciones de regalo. */
|
|
4
|
+
export interface SkuSalePromotionsResponse {
|
|
5
|
+
sku: string;
|
|
6
|
+
promotions: EvaluatedSalePromotion[];
|
|
7
|
+
}
|
|
@@ -41,4 +41,6 @@ export enum RetailPromotionsErrorCodeEnum {
|
|
|
41
41
|
SALE_PROMOTION_HOLD_CONFLICT = 'SALE_PROMOTION_HOLD_CONFLICT',
|
|
42
42
|
/** El token de paginación no es válido. */
|
|
43
43
|
INVALID_NEXT_TOKEN = 'INVALID_NEXT_TOKEN',
|
|
44
|
+
/** El SKU no existe en el catálogo. */
|
|
45
|
+
CATALOG_SKU_NOT_FOUND = 'CATALOG_SKU_NOT_FOUND',
|
|
44
46
|
}
|
|
@@ -52,8 +52,10 @@ export * from './dtos/requests/EvaluateSalePromotionsRequest';
|
|
|
52
52
|
export * from './dtos/requests/HoldGiftPromotionInput';
|
|
53
53
|
export * from './dtos/requests/HoldSalePromotionRequest';
|
|
54
54
|
export * from './dtos/requests/GetSaleCouponQuery';
|
|
55
|
+
export * from './dtos/requests/SkuSalePromotionsQuery';
|
|
55
56
|
|
|
56
57
|
// Response DTOs
|
|
57
58
|
export * from './dtos/responses/SalePromotionCrudResponses';
|
|
58
59
|
export * from './dtos/responses/DiscountCodeResponses';
|
|
59
60
|
export * from './dtos/responses/WizardSalePromotionResponses';
|
|
61
|
+
export * from './dtos/responses/SkuSalePromotionsResponse';
|
|
@@ -1,12 +1,30 @@
|
|
|
1
1
|
import { Expose, Type } from 'class-transformer';
|
|
2
2
|
import { IsArray, IsInt, IsNotEmpty, IsString, Min, ValidateIf, ValidateNested } from 'class-validator';
|
|
3
3
|
|
|
4
|
+
/** Hay que validar la promo del item si vino cualquiera de sus dos campos. */
|
|
5
|
+
function hasOwnPromotion(o: AnchorGiftItem): boolean {
|
|
6
|
+
return o.promotionId !== undefined || o.promotionVersion !== undefined;
|
|
7
|
+
}
|
|
8
|
+
|
|
4
9
|
/** Un regalo del conjunto que queda ligado al ancla. */
|
|
5
10
|
export class AnchorGiftItem {
|
|
6
11
|
@Expose()
|
|
7
12
|
@IsString()
|
|
8
13
|
@IsNotEmpty()
|
|
9
14
|
sku!: string;
|
|
15
|
+
|
|
16
|
+
/** Promo propia de esta línea GIFT; va junto con `promotionVersion` y, si falta, se usa la de la raíz. */
|
|
17
|
+
@Expose()
|
|
18
|
+
@ValidateIf(hasOwnPromotion)
|
|
19
|
+
@IsString()
|
|
20
|
+
@IsNotEmpty()
|
|
21
|
+
promotionId?: string;
|
|
22
|
+
|
|
23
|
+
@Expose()
|
|
24
|
+
@ValidateIf(hasOwnPromotion)
|
|
25
|
+
@IsInt()
|
|
26
|
+
@Min(1)
|
|
27
|
+
promotionVersion?: number;
|
|
10
28
|
}
|
|
11
29
|
|
|
12
30
|
/** Hay que validar el campo si hay regalos o si vino con valor. */
|