@fiado/type-kit 3.571.0 → 3.573.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.
@@ -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 de las dos promociones', () => {
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
  });
@@ -56,3 +56,25 @@ describe('population DTOs', () => {
56
56
  expect(Object.keys(Rules.PopulationExecutionStatusEnum)).toEqual(['RUNNING', 'SUCCEEDED', 'FAILED', 'CANCELLED']);
57
57
  });
58
58
  });
59
+
60
+ describe('rutas de columna (SEGMENT_COLUMN_PATH_PATTERN)', () => {
61
+ const colCond = (column: string) => ({ kind: 'COLUMN', table: 'riskprofile', column, op: 'GT', value: 1 });
62
+ it.each(['score', 'riskfactors.income.value', 'a.b.c.d.e.f.g.h'])('column "%s" válida -> 0 errores', async (column) => {
63
+ expect(await errorsOf(Rules.SegmentColumnCondition, colCond(column))).toBe(0);
64
+ });
65
+ it.each(['a.b.c.d.e.f.g.h.i', 'Riskfactors.income', 'a..b', 'a.', '.a', 'a.1b', 'a-b.c'])('column "%s" inválida -> error', async (column) => {
66
+ expect(await errorsOf(Rules.SegmentColumnCondition, colCond(column))).toBeGreaterThan(0);
67
+ });
68
+ it('table con punto sigue inválida', async () => {
69
+ expect(await errorsOf(Rules.SegmentColumnCondition, { ...colCond('score'), table: 'a.b' })).toBeGreaterThan(0);
70
+ });
71
+ it('dateColumn anidada válida y SEGMENT_MAX_PATH_DEPTH = 8', async () => {
72
+ expect(await errorsOf(Rules.SegmentWindow, { dateColumn: 'riskfactors.income.evaluationat', days: 30 })).toBe(0);
73
+ expect(Rules.SEGMENT_MAX_PATH_DEPTH).toBe(8);
74
+ });
75
+ it('aggregate column anidada válida', async () => {
76
+ const agg = { kind: 'AGGREGATE', table: 'tx', fn: 'SUM', column: 'a.b.c', op: 'GT', value: 1 };
77
+ const errs = await validate(plainToInstance(Rules.SegmentAggregateCondition, agg, { excludeExtraneousValues: true }));
78
+ expect(errs.filter((e) => e.property === 'column')).toHaveLength(0);
79
+ });
80
+ });
@@ -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,
@@ -2,5 +2,6 @@
2
2
  export declare enum BonusTypeEnum {
3
3
  WELCOME = "WELCOME",
4
4
  CREDIT_PROMOTION = "CREDIT_PROMOTION",
5
- SALE_PROMOTION = "SALE_PROMOTION"
5
+ SALE_PROMOTION = "SALE_PROMOTION",
6
+ REFERRAL = "REFERRAL"
6
7
  }
@@ -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 = {}));
@@ -1,5 +1,8 @@
1
1
  /** Identificador SQL permitido para tabla/columna (A§4.3 paso 1): minusculas, digitos y guion bajo; nunca texto libre. */
2
2
  export declare const SEGMENT_IDENTIFIER_PATTERN: RegExp;
3
+ /** Ruta a una hoja de columna struct de Glue (`riskfactors.income.value`): segmentos separados por punto, maximo SEGMENT_MAX_PATH_DEPTH. Una columna plana es una ruta de 1 segmento. */
4
+ export declare const SEGMENT_COLUMN_PATH_PATTERN: RegExp;
5
+ export declare const SEGMENT_MAX_PATH_DEPTH = 8;
3
6
  export declare const SEGMENT_MAX_DAYS = 365;
4
7
  export declare const SEGMENT_MAX_PARAMS = 40;
5
8
  export declare const SEGMENT_MAX_AGGREGATES = 8;
@@ -1,8 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SEGMENT_MAX_AGGREGATES = exports.SEGMENT_MAX_PARAMS = exports.SEGMENT_MAX_DAYS = exports.SEGMENT_IDENTIFIER_PATTERN = void 0;
3
+ exports.SEGMENT_MAX_AGGREGATES = exports.SEGMENT_MAX_PARAMS = exports.SEGMENT_MAX_DAYS = exports.SEGMENT_MAX_PATH_DEPTH = exports.SEGMENT_COLUMN_PATH_PATTERN = exports.SEGMENT_IDENTIFIER_PATTERN = void 0;
4
4
  /** Identificador SQL permitido para tabla/columna (A§4.3 paso 1): minusculas, digitos y guion bajo; nunca texto libre. */
5
5
  exports.SEGMENT_IDENTIFIER_PATTERN = /^[a-z_][a-z0-9_]*$/;
6
+ /** Ruta a una hoja de columna struct de Glue (`riskfactors.income.value`): segmentos separados por punto, maximo SEGMENT_MAX_PATH_DEPTH. Una columna plana es una ruta de 1 segmento. */
7
+ exports.SEGMENT_COLUMN_PATH_PATTERN = /^[a-z_][a-z0-9_]*(\.[a-z_][a-z0-9_]*){0,7}$/;
8
+ exports.SEGMENT_MAX_PATH_DEPTH = 8;
6
9
  exports.SEGMENT_MAX_DAYS = 365;
7
10
  exports.SEGMENT_MAX_PARAMS = 40;
8
11
  exports.SEGMENT_MAX_AGGREGATES = 8;
@@ -40,7 +40,7 @@ __decorate([
40
40
  __decorate([
41
41
  (0, class_transformer_1.Expose)(),
42
42
  (0, class_validator_1.IsOptional)(),
43
- (0, class_validator_1.Matches)(SegmentLimits_1.SEGMENT_IDENTIFIER_PATTERN),
43
+ (0, class_validator_1.Matches)(SegmentLimits_1.SEGMENT_COLUMN_PATH_PATTERN),
44
44
  __metadata("design:type", String)
45
45
  ], SegmentAggregateCondition.prototype, "column", void 0);
46
46
  __decorate([
@@ -31,7 +31,7 @@ __decorate([
31
31
  ], SegmentColumnCondition.prototype, "table", void 0);
32
32
  __decorate([
33
33
  (0, class_transformer_1.Expose)(),
34
- (0, class_validator_1.Matches)(SegmentLimits_1.SEGMENT_IDENTIFIER_PATTERN),
34
+ (0, class_validator_1.Matches)(SegmentLimits_1.SEGMENT_COLUMN_PATH_PATTERN),
35
35
  __metadata("design:type", String)
36
36
  ], SegmentColumnCondition.prototype, "column", void 0);
37
37
  __decorate([
@@ -1,6 +1,8 @@
1
1
  import { SegmentOperatorEnum } from '../../enums/SegmentOperatorEnum';
2
2
  export declare class SegmentColumnSchemaResponse {
3
3
  name: string;
4
+ /** Columna raiz de Glue cuando `name` es una ruta a una hoja de struct (agrupa en la UI). */
5
+ root?: string;
4
6
  type: string;
5
7
  isDate: boolean;
6
8
  operators: SegmentOperatorEnum[];
@@ -19,7 +19,7 @@ class SegmentWindow {
19
19
  exports.SegmentWindow = SegmentWindow;
20
20
  __decorate([
21
21
  (0, class_transformer_1.Expose)(),
22
- (0, class_validator_1.Matches)(SegmentLimits_1.SEGMENT_IDENTIFIER_PATTERN),
22
+ (0, class_validator_1.Matches)(SegmentLimits_1.SEGMENT_COLUMN_PATH_PATTERN),
23
23
  __metadata("design:type", String)
24
24
  ], SegmentWindow.prototype, "dateColumn", void 0);
25
25
  __decorate([
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fiado/type-kit",
3
- "version": "3.571.0",
3
+ "version": "3.573.0",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "types": "bin/index.d.ts",
@@ -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,
@@ -3,4 +3,5 @@ export enum BonusTypeEnum {
3
3
  WELCOME = 'WELCOME',
4
4
  CREDIT_PROMOTION = 'CREDIT_PROMOTION',
5
5
  SALE_PROMOTION = 'SALE_PROMOTION',
6
+ REFERRAL = 'REFERRAL',
6
7
  }
@@ -1,5 +1,8 @@
1
1
  /** Identificador SQL permitido para tabla/columna (A§4.3 paso 1): minusculas, digitos y guion bajo; nunca texto libre. */
2
2
  export const SEGMENT_IDENTIFIER_PATTERN = /^[a-z_][a-z0-9_]*$/;
3
+ /** Ruta a una hoja de columna struct de Glue (`riskfactors.income.value`): segmentos separados por punto, maximo SEGMENT_MAX_PATH_DEPTH. Una columna plana es una ruta de 1 segmento. */
4
+ export const SEGMENT_COLUMN_PATH_PATTERN = /^[a-z_][a-z0-9_]*(\.[a-z_][a-z0-9_]*){0,7}$/;
5
+ export const SEGMENT_MAX_PATH_DEPTH = 8;
3
6
  export const SEGMENT_MAX_DAYS = 365;
4
7
  export const SEGMENT_MAX_PARAMS = 40;
5
8
  export const SEGMENT_MAX_AGGREGATES = 8;
@@ -1,6 +1,6 @@
1
1
  import { Expose, Type } from 'class-transformer';
2
2
  import { ArrayMaxSize, Equals, IsArray, IsEnum, IsNumber, IsOptional, Matches, ValidateNested } from 'class-validator';
3
- import { SEGMENT_IDENTIFIER_PATTERN } from '../../constants/SegmentLimits';
3
+ import { SEGMENT_COLUMN_PATH_PATTERN, SEGMENT_IDENTIFIER_PATTERN } from '../../constants/SegmentLimits';
4
4
  import { SegmentAggregateFnEnum } from '../../enums/SegmentAggregateFnEnum';
5
5
  import { SegmentConditionKindEnum } from '../../enums/SegmentConditionKindEnum';
6
6
  import { SegmentOperatorEnum } from '../../enums/SegmentOperatorEnum';
@@ -13,7 +13,7 @@ export class SegmentAggregateCondition {
13
13
  @Expose() @Matches(SEGMENT_IDENTIFIER_PATTERN) table: string;
14
14
  @Expose() @IsEnum(SegmentAggregateFnEnum) fn: SegmentAggregateFnEnum;
15
15
  /** Solo SUM. */
16
- @Expose() @IsOptional() @Matches(SEGMENT_IDENTIFIER_PATTERN) column?: string;
16
+ @Expose() @IsOptional() @Matches(SEGMENT_COLUMN_PATH_PATTERN) column?: string;
17
17
  /** COUNT y SUM; EXISTS no lleva. */
18
18
  @Expose() @IsOptional() @IsEnum(SegmentOperatorEnum) op?: SegmentOperatorEnum;
19
19
  @Expose() @IsOptional() @IsNumber() value?: number;
@@ -1,7 +1,7 @@
1
1
  import { Expose } from 'class-transformer';
2
2
  import { Equals, IsEnum, IsOptional, Matches } from 'class-validator';
3
3
  import { JsonValue } from '../../../common';
4
- import { SEGMENT_IDENTIFIER_PATTERN } from '../../constants/SegmentLimits';
4
+ import { SEGMENT_COLUMN_PATH_PATTERN, SEGMENT_IDENTIFIER_PATTERN } from '../../constants/SegmentLimits';
5
5
  import { SegmentConditionKindEnum } from '../../enums/SegmentConditionKindEnum';
6
6
  import { SegmentOperatorEnum } from '../../enums/SegmentOperatorEnum';
7
7
 
@@ -9,7 +9,7 @@ import { SegmentOperatorEnum } from '../../enums/SegmentOperatorEnum';
9
9
  export class SegmentColumnCondition {
10
10
  @Expose() @Equals(SegmentConditionKindEnum.COLUMN) kind: SegmentConditionKindEnum.COLUMN;
11
11
  @Expose() @Matches(SEGMENT_IDENTIFIER_PATTERN) table: string;
12
- @Expose() @Matches(SEGMENT_IDENTIFIER_PATTERN) column: string;
12
+ @Expose() @Matches(SEGMENT_COLUMN_PATH_PATTERN) column: string;
13
13
  @Expose() @IsEnum(SegmentOperatorEnum) op: SegmentOperatorEnum;
14
14
  @Expose() @IsOptional() value?: JsonValue;
15
15
  }
@@ -2,6 +2,8 @@ import { SegmentOperatorEnum } from '../../enums/SegmentOperatorEnum';
2
2
 
3
3
  export class SegmentColumnSchemaResponse {
4
4
  name: string;
5
+ /** Columna raiz de Glue cuando `name` es una ruta a una hoja de struct (agrupa en la UI). */
6
+ root?: string;
5
7
  type: string;
6
8
  isDate: boolean;
7
9
  operators: SegmentOperatorEnum[];
@@ -1,9 +1,9 @@
1
1
  import { Expose } from 'class-transformer';
2
2
  import { IsInt, Matches, Max, Min } from 'class-validator';
3
- import { SEGMENT_IDENTIFIER_PATTERN, SEGMENT_MAX_DAYS } from '../../constants/SegmentLimits';
3
+ import { SEGMENT_COLUMN_PATH_PATTERN, SEGMENT_MAX_DAYS } from '../../constants/SegmentLimits';
4
4
 
5
5
  /** Ventana relativa [referenceAt - days, referenceAt) sobre una columna de fecha (A§4.1). */
6
6
  export class SegmentWindow {
7
- @Expose() @Matches(SEGMENT_IDENTIFIER_PATTERN) dateColumn: string;
7
+ @Expose() @Matches(SEGMENT_COLUMN_PATH_PATTERN) dateColumn: string;
8
8
  @Expose() @IsInt() @Min(1) @Max(SEGMENT_MAX_DAYS) days: number;
9
9
  }