@fiado/type-kit 3.570.0 → 3.572.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/retailCustomer/customerReferralContract.test.ts +6 -0
- package/_test_/unit/retailCustomer/promotionBonusContract.test.ts +6 -2
- package/_test_/unit/retailPromotions/referralPromotion.test.ts +22 -0
- package/bin/retailCustomer/dtos/CustomerReferral.d.ts +2 -0
- package/bin/retailCustomer/dtos/CustomerReferral.js +6 -0
- package/bin/retailCustomer/dtos/requests/UpsertPromotionBonusRequest.js +1 -1
- package/bin/retailCustomer/dtos/responses/CustomerReferralResponses.d.ts +2 -0
- package/bin/retailCustomer/enums/BonusTypeEnum.d.ts +2 -1
- package/bin/retailCustomer/enums/BonusTypeEnum.js +1 -0
- package/bin/retailPromotions/dtos/ReferralPromotion.d.ts +4 -0
- package/bin/retailPromotions/dtos/requests/ReferralPromotionInput.d.ts +4 -0
- package/bin/retailPromotions/dtos/requests/ReferralPromotionInput.js +14 -0
- package/bin/retailPromotions/dtos/responses/LiveReferralPromotionsResponse.d.ts +4 -0
- package/package.json +1 -1
- package/src/retailCustomer/dtos/CustomerReferral.ts +7 -1
- package/src/retailCustomer/dtos/requests/UpsertPromotionBonusRequest.ts +1 -1
- package/src/retailCustomer/dtos/responses/CustomerReferralResponses.ts +2 -0
- package/src/retailCustomer/enums/BonusTypeEnum.ts +1 -0
- package/src/retailPromotions/dtos/ReferralPromotion.ts +4 -0
- package/src/retailPromotions/dtos/requests/ReferralPromotionInput.ts +14 -0
- package/src/retailPromotions/dtos/responses/LiveReferralPromotionsResponse.ts +4 -0
|
@@ -188,6 +188,11 @@ describe('CustomerReferral y respuestas', () => {
|
|
|
188
188
|
expect(errorsOf(CustomerReferral, { ...referral, source: 'WEB' })).toEqual(['source']);
|
|
189
189
|
});
|
|
190
190
|
|
|
191
|
+
it('acepta la marca de cliente existente al capturar, opcional', () => {
|
|
192
|
+
expect(errorsOf(CustomerReferral, { ...referral, existingCustomerAtCapture: true })).toEqual([]);
|
|
193
|
+
expect(errorsOf(CustomerReferral, { ...referral, existingCustomerAtCapture: 'sí' })).toEqual(['existingCustomerAtCapture']);
|
|
194
|
+
});
|
|
195
|
+
|
|
191
196
|
it('describe las respuestas de las rutas privadas', () => {
|
|
192
197
|
const created: CreateCustomerReferralsResponse = { referrals: [referral] };
|
|
193
198
|
const updated: UpdateCustomerReferralResponse = { referral };
|
|
@@ -200,6 +205,7 @@ describe('CustomerReferral y respuestas', () => {
|
|
|
200
205
|
referrerName: 'Juan Pérez',
|
|
201
206
|
source: ReferralSourceEnum.SALE,
|
|
202
207
|
capturedAt: '2026-10-21T10:00:00Z',
|
|
208
|
+
existingCustomerAtCapture: false,
|
|
203
209
|
},
|
|
204
210
|
],
|
|
205
211
|
};
|
|
@@ -6,8 +6,8 @@ import { BonusTypeEnum, UpsertPromotionBonusRequest } from '../../../src/retailC
|
|
|
6
6
|
import type { PromotionBonusEntryResponse } from '../../../src/retailCustomer/index';
|
|
7
7
|
|
|
8
8
|
describe('BonusTypeEnum', () => {
|
|
9
|
-
it('distingue la bienvenida
|
|
10
|
-
expect(Object.values(BonusTypeEnum)).toEqual(['WELCOME', 'CREDIT_PROMOTION', 'SALE_PROMOTION']);
|
|
9
|
+
it('distingue la bienvenida, las dos promociones y el premio de referido', () => {
|
|
10
|
+
expect(Object.values(BonusTypeEnum)).toEqual(['WELCOME', 'CREDIT_PROMOTION', 'SALE_PROMOTION', 'REFERRAL']);
|
|
11
11
|
});
|
|
12
12
|
|
|
13
13
|
it('sale por el index raíz', () => {
|
|
@@ -51,6 +51,10 @@ describe('UpsertPromotionBonusRequest', () => {
|
|
|
51
51
|
expect(errorsOf({ ...PENDING_SALE, bonusType: 'WELCOME' })).toContain('bonusType');
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
+
it('acepta el premio de referido con su rol y referido', () => {
|
|
55
|
+
expect(errorsOf({ ...PENDING_SALE, bonusType: 'REFERRAL', role: 'REFERRER', referralId: 'ref-1' })).toEqual([]);
|
|
56
|
+
});
|
|
57
|
+
|
|
54
58
|
it.each(['promotionId', 'sourceId', 'storeId', 'currency', 'idempotencyKey'])('rechaza %s vacío', (field) => {
|
|
55
59
|
expect(errorsOf({ ...PENDING_SALE, [field]: ' ' })).toContain(field);
|
|
56
60
|
});
|
|
@@ -124,6 +124,26 @@ describe('ReferralPromotionInput', () => {
|
|
|
124
124
|
expect(errorsOf(ReferralPromotionInput, bad)).toEqual(['minAmountCents', 'windowDays', 'maxRewardsPerReferrer']);
|
|
125
125
|
});
|
|
126
126
|
|
|
127
|
+
it('acepta sin límites por referido ni por recomendado (ausente = 1)', () => {
|
|
128
|
+
expect(errorsOf(ReferralPromotionInput, { ...REFERRAL, maxRewardsPerReferral: 3, maxReferredRewards: 2 })).toEqual([]);
|
|
129
|
+
expect(errorsOf(ReferralPromotionInput, { ...REFERRAL, maxRewardsPerReferral: null, maxReferredRewards: null })).toEqual([]);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('rechaza límites por referido y por recomendado en cero, negativos o decimales', () => {
|
|
133
|
+
expect(errorsOf(ReferralPromotionInput, { ...REFERRAL, maxRewardsPerReferral: 0, maxReferredRewards: 0 })).toEqual([
|
|
134
|
+
'maxRewardsPerReferral',
|
|
135
|
+
'maxReferredRewards',
|
|
136
|
+
]);
|
|
137
|
+
expect(errorsOf(ReferralPromotionInput, { ...REFERRAL, maxRewardsPerReferral: -2, maxReferredRewards: -1 })).toEqual([
|
|
138
|
+
'maxRewardsPerReferral',
|
|
139
|
+
'maxReferredRewards',
|
|
140
|
+
]);
|
|
141
|
+
expect(errorsOf(ReferralPromotionInput, { ...REFERRAL, maxRewardsPerReferral: 1.5, maxReferredRewards: 2.5 })).toEqual([
|
|
142
|
+
'maxRewardsPerReferral',
|
|
143
|
+
'maxReferredRewards',
|
|
144
|
+
]);
|
|
145
|
+
});
|
|
146
|
+
|
|
127
147
|
it('deja al lambda el mínimo de 2 en compra N y racha (INVALID_REFERRAL_TRIGGER)', () => {
|
|
128
148
|
const nth = { ...REFERRAL, trigger: 'NTH_PURCHASE', purchaseNumber: 1 };
|
|
129
149
|
expect(errorsOf(ReferralPromotionInput, nth)).toEqual([]);
|
|
@@ -162,6 +182,8 @@ describe('promo de referido en el CRUD de promos', () => {
|
|
|
162
182
|
minAmountCents: null,
|
|
163
183
|
windowDays: 60,
|
|
164
184
|
maxRewardsPerReferrer: null,
|
|
185
|
+
maxRewardsPerReferral: 2,
|
|
186
|
+
maxReferredRewards: 1,
|
|
165
187
|
referrerReward: {
|
|
166
188
|
type: ReferralRewardTypeEnum.FIXED_BONUS,
|
|
167
189
|
amountCents: 100_00,
|
|
@@ -18,6 +18,8 @@ export declare class CustomerReferral {
|
|
|
18
18
|
saleId: string | null;
|
|
19
19
|
/** Solo en `OPENING`. */
|
|
20
20
|
accountOpeningSessionId: string | null;
|
|
21
|
+
/** `true` si el teléfono ya era cliente de alguna cadena del tenant al capturarlo; no genera premios. */
|
|
22
|
+
existingCustomerAtCapture?: boolean;
|
|
21
23
|
createdBy: string;
|
|
22
24
|
updatedBy: string;
|
|
23
25
|
createdAt: string;
|
|
@@ -77,6 +77,12 @@ __decorate([
|
|
|
77
77
|
(0, class_validator_1.IsString)(),
|
|
78
78
|
__metadata("design:type", String)
|
|
79
79
|
], CustomerReferral.prototype, "accountOpeningSessionId", void 0);
|
|
80
|
+
__decorate([
|
|
81
|
+
(0, class_transformer_1.Expose)(),
|
|
82
|
+
(0, class_validator_1.IsOptional)(),
|
|
83
|
+
(0, class_validator_1.IsBoolean)(),
|
|
84
|
+
__metadata("design:type", Boolean)
|
|
85
|
+
], CustomerReferral.prototype, "existingCustomerAtCapture", void 0);
|
|
80
86
|
__decorate([
|
|
81
87
|
(0, class_transformer_1.Expose)(),
|
|
82
88
|
(0, class_validator_1.IsString)(),
|
|
@@ -18,7 +18,7 @@ const ReferralRoleEnum_1 = require("../../enums/ReferralRoleEnum");
|
|
|
18
18
|
const WelcomeBonusStatusEnum_1 = require("../../enums/WelcomeBonusStatusEnum");
|
|
19
19
|
/** Tope del motivo libre que el caller escribe en el asiento. */
|
|
20
20
|
const FREE_TEXT_MAX_LENGTH = 256;
|
|
21
|
-
const PROMOTION_BONUS_TYPES = [BonusTypeEnum_1.BonusTypeEnum.CREDIT_PROMOTION, BonusTypeEnum_1.BonusTypeEnum.SALE_PROMOTION];
|
|
21
|
+
const PROMOTION_BONUS_TYPES = [BonusTypeEnum_1.BonusTypeEnum.CREDIT_PROMOTION, BonusTypeEnum_1.BonusTypeEnum.SALE_PROMOTION, BonusTypeEnum_1.BonusTypeEnum.REFERRAL];
|
|
22
22
|
const STATUSES_REQUIRING_REASON = [
|
|
23
23
|
WelcomeBonusStatusEnum_1.WelcomeBonusStatusEnum.FAILED,
|
|
24
24
|
WelcomeBonusStatusEnum_1.WelcomeBonusStatusEnum.UNVERIFIED,
|
|
@@ -20,6 +20,8 @@ export interface ReferralByPhone {
|
|
|
20
20
|
referrerName: string;
|
|
21
21
|
source: ReferralSourceEnum;
|
|
22
22
|
capturedAt: string;
|
|
23
|
+
/** `true` si el teléfono ya era cliente al capturarlo; no genera premios. */
|
|
24
|
+
existingCustomerAtCapture?: boolean;
|
|
23
25
|
}
|
|
24
26
|
/** Respuesta de `privateGetReferralsByPhone`, del más antiguo al más reciente. */
|
|
25
27
|
export interface ReferralsByPhoneResponse {
|
|
@@ -7,4 +7,5 @@ var BonusTypeEnum;
|
|
|
7
7
|
BonusTypeEnum["WELCOME"] = "WELCOME";
|
|
8
8
|
BonusTypeEnum["CREDIT_PROMOTION"] = "CREDIT_PROMOTION";
|
|
9
9
|
BonusTypeEnum["SALE_PROMOTION"] = "SALE_PROMOTION";
|
|
10
|
+
BonusTypeEnum["REFERRAL"] = "REFERRAL";
|
|
10
11
|
})(BonusTypeEnum || (exports.BonusTypeEnum = BonusTypeEnum = {}));
|
|
@@ -27,6 +27,10 @@ export interface ReferralPromotionConfig {
|
|
|
27
27
|
/** Días desde la captura del referido. */
|
|
28
28
|
windowDays: number | null;
|
|
29
29
|
maxRewardsPerReferrer: number | null;
|
|
30
|
+
/** Veces que se paga a quien recomienda por cada referido; ausente o `null` = 1. */
|
|
31
|
+
maxRewardsPerReferral?: number | null;
|
|
32
|
+
/** Veces que se paga o aplica el premio al recomendado; ausente o `null` = 1. */
|
|
33
|
+
maxReferredRewards?: number | null;
|
|
30
34
|
referrerReward: ReferralReward;
|
|
31
35
|
/** `null` = el recomendado no gana nada. */
|
|
32
36
|
referredReward: ReferralReward | null;
|
|
@@ -19,6 +19,10 @@ export declare class ReferralPromotionInput {
|
|
|
19
19
|
minAmountCents?: number | null;
|
|
20
20
|
windowDays?: number | null;
|
|
21
21
|
maxRewardsPerReferrer?: number | null;
|
|
22
|
+
/** Veces que se paga a quien recomienda por cada referido; ausente = 1. */
|
|
23
|
+
maxRewardsPerReferral?: number | null;
|
|
24
|
+
/** Veces que se paga o aplica el premio al recomendado; ausente = 1. */
|
|
25
|
+
maxReferredRewards?: number | null;
|
|
22
26
|
referrerReward: ReferralRewardInput;
|
|
23
27
|
referredReward?: ReferralRewardInput | null;
|
|
24
28
|
}
|
|
@@ -103,6 +103,20 @@ __decorate([
|
|
|
103
103
|
(0, class_validator_1.Min)(1),
|
|
104
104
|
__metadata("design:type", Number)
|
|
105
105
|
], ReferralPromotionInput.prototype, "maxRewardsPerReferrer", void 0);
|
|
106
|
+
__decorate([
|
|
107
|
+
(0, class_transformer_1.Expose)(),
|
|
108
|
+
(0, class_validator_1.IsOptional)(),
|
|
109
|
+
(0, class_validator_1.IsInt)(),
|
|
110
|
+
(0, class_validator_1.Min)(1),
|
|
111
|
+
__metadata("design:type", Number)
|
|
112
|
+
], ReferralPromotionInput.prototype, "maxRewardsPerReferral", void 0);
|
|
113
|
+
__decorate([
|
|
114
|
+
(0, class_transformer_1.Expose)(),
|
|
115
|
+
(0, class_validator_1.IsOptional)(),
|
|
116
|
+
(0, class_validator_1.IsInt)(),
|
|
117
|
+
(0, class_validator_1.Min)(1),
|
|
118
|
+
__metadata("design:type", Number)
|
|
119
|
+
], ReferralPromotionInput.prototype, "maxReferredRewards", void 0);
|
|
106
120
|
__decorate([
|
|
107
121
|
(0, class_transformer_1.Expose)(),
|
|
108
122
|
(0, class_validator_1.IsDefined)(),
|
|
@@ -15,6 +15,10 @@ export interface LiveReferralPromotionItem {
|
|
|
15
15
|
installmentStreak: number | null;
|
|
16
16
|
/** Fin de vigencia; `null` = sin fecha de fin. */
|
|
17
17
|
validUntil: string | null;
|
|
18
|
+
/** Veces que se paga a quien recomienda por cada referido; ausente o `null` = 1. */
|
|
19
|
+
maxRewardsPerReferral?: number | null;
|
|
20
|
+
/** Veces que se paga o aplica el premio al recomendado; ausente o `null` = 1. */
|
|
21
|
+
maxReferredRewards?: number | null;
|
|
18
22
|
referrerReward: ReferralReward;
|
|
19
23
|
/** `null` = el recomendado no gana nada. */
|
|
20
24
|
referredReward: ReferralReward | null;
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Expose } from 'class-transformer';
|
|
2
|
-
import { IsEnum, IsISO8601, IsOptional, IsString } from 'class-validator';
|
|
2
|
+
import { IsBoolean, IsEnum, IsISO8601, IsOptional, IsString } from 'class-validator';
|
|
3
3
|
import { ReferralSourceEnum } from '../enums/ReferralSourceEnum';
|
|
4
4
|
|
|
5
5
|
/** Persona que un cliente recomienda (owner: retail-customer-business). Teléfono normalizado a 10 dígitos. */
|
|
@@ -59,6 +59,12 @@ export class CustomerReferral {
|
|
|
59
59
|
@IsString()
|
|
60
60
|
accountOpeningSessionId!: string | null;
|
|
61
61
|
|
|
62
|
+
/** `true` si el teléfono ya era cliente de alguna cadena del tenant al capturarlo; no genera premios. */
|
|
63
|
+
@Expose()
|
|
64
|
+
@IsOptional()
|
|
65
|
+
@IsBoolean()
|
|
66
|
+
existingCustomerAtCapture?: boolean;
|
|
67
|
+
|
|
62
68
|
@Expose()
|
|
63
69
|
@IsString()
|
|
64
70
|
createdBy!: string;
|
|
@@ -8,7 +8,7 @@ import { WelcomeBonusStatusEnum } from '../../enums/WelcomeBonusStatusEnum';
|
|
|
8
8
|
/** Tope del motivo libre que el caller escribe en el asiento. */
|
|
9
9
|
const FREE_TEXT_MAX_LENGTH = 256;
|
|
10
10
|
|
|
11
|
-
const PROMOTION_BONUS_TYPES = [BonusTypeEnum.CREDIT_PROMOTION, BonusTypeEnum.SALE_PROMOTION];
|
|
11
|
+
const PROMOTION_BONUS_TYPES = [BonusTypeEnum.CREDIT_PROMOTION, BonusTypeEnum.SALE_PROMOTION, BonusTypeEnum.REFERRAL];
|
|
12
12
|
|
|
13
13
|
const STATUSES_REQUIRING_REASON: WelcomeBonusStatusEnum[] = [
|
|
14
14
|
WelcomeBonusStatusEnum.FAILED,
|
|
@@ -24,6 +24,8 @@ export interface ReferralByPhone {
|
|
|
24
24
|
referrerName: string;
|
|
25
25
|
source: ReferralSourceEnum;
|
|
26
26
|
capturedAt: string;
|
|
27
|
+
/** `true` si el teléfono ya era cliente al capturarlo; no genera premios. */
|
|
28
|
+
existingCustomerAtCapture?: boolean;
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
/** Respuesta de `privateGetReferralsByPhone`, del más antiguo al más reciente. */
|
|
@@ -29,6 +29,10 @@ export interface ReferralPromotionConfig {
|
|
|
29
29
|
/** Días desde la captura del referido. */
|
|
30
30
|
windowDays: number | null;
|
|
31
31
|
maxRewardsPerReferrer: number | null;
|
|
32
|
+
/** Veces que se paga a quien recomienda por cada referido; ausente o `null` = 1. */
|
|
33
|
+
maxRewardsPerReferral?: number | null;
|
|
34
|
+
/** Veces que se paga o aplica el premio al recomendado; ausente o `null` = 1. */
|
|
35
|
+
maxReferredRewards?: number | null;
|
|
32
36
|
referrerReward: ReferralReward;
|
|
33
37
|
/** `null` = el recomendado no gana nada. */
|
|
34
38
|
referredReward: ReferralReward | null;
|
|
@@ -79,6 +79,20 @@ export class ReferralPromotionInput {
|
|
|
79
79
|
@Min(1)
|
|
80
80
|
maxRewardsPerReferrer?: number | null;
|
|
81
81
|
|
|
82
|
+
/** Veces que se paga a quien recomienda por cada referido; ausente = 1. */
|
|
83
|
+
@Expose()
|
|
84
|
+
@IsOptional()
|
|
85
|
+
@IsInt()
|
|
86
|
+
@Min(1)
|
|
87
|
+
maxRewardsPerReferral?: number | null;
|
|
88
|
+
|
|
89
|
+
/** Veces que se paga o aplica el premio al recomendado; ausente = 1. */
|
|
90
|
+
@Expose()
|
|
91
|
+
@IsOptional()
|
|
92
|
+
@IsInt()
|
|
93
|
+
@Min(1)
|
|
94
|
+
maxReferredRewards?: number | null;
|
|
95
|
+
|
|
82
96
|
@Expose()
|
|
83
97
|
@IsDefined()
|
|
84
98
|
@ValidateNested()
|
|
@@ -16,6 +16,10 @@ export interface LiveReferralPromotionItem {
|
|
|
16
16
|
installmentStreak: number | null;
|
|
17
17
|
/** Fin de vigencia; `null` = sin fecha de fin. */
|
|
18
18
|
validUntil: string | null;
|
|
19
|
+
/** Veces que se paga a quien recomienda por cada referido; ausente o `null` = 1. */
|
|
20
|
+
maxRewardsPerReferral?: number | null;
|
|
21
|
+
/** Veces que se paga o aplica el premio al recomendado; ausente o `null` = 1. */
|
|
22
|
+
maxReferredRewards?: number | null;
|
|
19
23
|
referrerReward: ReferralReward;
|
|
20
24
|
/** `null` = el recomendado no gana nada. */
|
|
21
25
|
referredReward: ReferralReward | null;
|