@fiado/type-kit 3.574.0 → 3.575.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 (66) hide show
  1. package/_test_/unit/rewardsEligibility/evaluationStrategyDtos.test.ts +93 -0
  2. package/_test_/unit/rewardsEligibility/segmentMessagesAndRunDtos.test.ts +2 -2
  3. package/_test_/unit/rules/evaluationDatalakeDtos.test.ts +144 -0
  4. package/bin/rewardsEligibility/constants/BatchLimits.d.ts +2 -0
  5. package/bin/rewardsEligibility/constants/BatchLimits.js +5 -0
  6. package/bin/rewardsEligibility/dtos/backoffice/CreateRunRequest.d.ts +2 -0
  7. package/bin/rewardsEligibility/dtos/backoffice/CreateRunRequest.js +7 -0
  8. package/bin/rewardsEligibility/dtos/backoffice/EvaluationRequest.d.ts +3 -0
  9. package/bin/rewardsEligibility/dtos/backoffice/EvaluationRequest.js +7 -0
  10. package/bin/rewardsEligibility/dtos/backoffice/EvaluationResponse.d.ts +3 -0
  11. package/bin/rewardsEligibility/dtos/backoffice/SimulateRequest.d.ts +2 -0
  12. package/bin/rewardsEligibility/dtos/backoffice/SimulateRequest.js +7 -0
  13. package/bin/rewardsEligibility/dtos/messages/EvaluateBatchMessage.d.ts +1 -1
  14. package/bin/rewardsEligibility/dtos/messages/EvaluateBatchMessage.js +3 -2
  15. package/bin/rewardsEligibility/index.d.ts +2 -0
  16. package/bin/rewardsEligibility/index.js +2 -0
  17. package/bin/rewardsEligibility/types/RewardInputRef.d.ts +9 -1
  18. package/bin/rewardsEligibility/validators/IsRewardInputs.d.ts +7 -0
  19. package/bin/rewardsEligibility/validators/IsRewardInputs.js +26 -0
  20. package/bin/rules/constants/RulesLimits.d.ts +6 -0
  21. package/bin/rules/constants/RulesLimits.js +7 -1
  22. package/bin/rules/dtos/EvaluateRulesRequest.d.ts +8 -0
  23. package/bin/rules/dtos/EvaluateRulesRequest.js +24 -0
  24. package/bin/rules/dtos/EvaluateRulesResponse.d.ts +3 -0
  25. package/bin/rules/dtos/ValidateRulesRequest.d.ts +5 -0
  26. package/bin/rules/dtos/ValidateRulesRequest.js +15 -0
  27. package/bin/rules/dtos/datalake/EvaluationExecutionRequest.d.ts +21 -0
  28. package/bin/rules/dtos/datalake/EvaluationExecutionRequest.js +83 -0
  29. package/bin/rules/dtos/datalake/EvaluationExecutionResponse.d.ts +6 -0
  30. package/bin/rules/dtos/datalake/EvaluationExecutionResponse.js +7 -0
  31. package/bin/rules/dtos/datalake/EvaluationExecutionResultsResponse.d.ts +11 -0
  32. package/bin/rules/dtos/datalake/EvaluationExecutionResultsResponse.js +7 -0
  33. package/bin/rules/dtos/datalake/EvaluationResultsRequest.d.ts +11 -0
  34. package/bin/rules/dtos/datalake/EvaluationResultsRequest.js +64 -0
  35. package/bin/rules/dtos/datalake/ReturnFieldsCatalogResponse.d.ts +17 -0
  36. package/bin/rules/dtos/datalake/ReturnFieldsCatalogResponse.js +10 -0
  37. package/bin/rules/dtos/population/SegmentTableSchemaResponse.d.ts +2 -0
  38. package/bin/rules/enums/EvaluationStrategyEnum.d.ts +5 -0
  39. package/bin/rules/enums/EvaluationStrategyEnum.js +9 -0
  40. package/bin/rules/enums/RulesErrorCodeEnum.d.ts +11 -1
  41. package/bin/rules/enums/RulesErrorCodeEnum.js +10 -0
  42. package/bin/rules/index.d.ts +6 -0
  43. package/bin/rules/index.js +7 -0
  44. package/package.json +1 -1
  45. package/src/rewardsEligibility/constants/BatchLimits.ts +2 -0
  46. package/src/rewardsEligibility/dtos/backoffice/CreateRunRequest.ts +7 -0
  47. package/src/rewardsEligibility/dtos/backoffice/EvaluationRequest.ts +8 -1
  48. package/src/rewardsEligibility/dtos/backoffice/EvaluationResponse.ts +3 -0
  49. package/src/rewardsEligibility/dtos/backoffice/SimulateRequest.ts +7 -0
  50. package/src/rewardsEligibility/dtos/messages/EvaluateBatchMessage.ts +3 -2
  51. package/src/rewardsEligibility/index.ts +2 -0
  52. package/src/rewardsEligibility/types/RewardInputRef.ts +6 -2
  53. package/src/rewardsEligibility/validators/IsRewardInputs.ts +16 -0
  54. package/src/rules/constants/RulesLimits.ts +6 -0
  55. package/src/rules/dtos/EvaluateRulesRequest.ts +26 -1
  56. package/src/rules/dtos/EvaluateRulesResponse.ts +3 -0
  57. package/src/rules/dtos/ValidateRulesRequest.ts +17 -2
  58. package/src/rules/dtos/datalake/EvaluationExecutionRequest.ts +73 -0
  59. package/src/rules/dtos/datalake/EvaluationExecutionResponse.ts +7 -0
  60. package/src/rules/dtos/datalake/EvaluationExecutionResultsResponse.ts +12 -0
  61. package/src/rules/dtos/datalake/EvaluationResultsRequest.ts +46 -0
  62. package/src/rules/dtos/datalake/ReturnFieldsCatalogResponse.ts +19 -0
  63. package/src/rules/dtos/population/SegmentTableSchemaResponse.ts +2 -0
  64. package/src/rules/enums/EvaluationStrategyEnum.ts +5 -0
  65. package/src/rules/enums/RulesErrorCodeEnum.ts +10 -0
  66. package/src/rules/index.ts +8 -0
@@ -0,0 +1,93 @@
1
+ import 'reflect-metadata';
2
+ import { plainToInstance } from 'class-transformer';
3
+ import { validate } from 'class-validator';
4
+ import { EvaluationStrategyEnum } from '../../../src/rules';
5
+ import {
6
+ CreateRunRequest,
7
+ EVALUATE_BATCH_MAX_SUBJECTS,
8
+ EvaluateBatchMessage,
9
+ EvaluationRequest,
10
+ EvaluationResponse,
11
+ RewardInputRef,
12
+ SimulateRequest,
13
+ } from '../../../src/rewardsEligibility';
14
+ import { InputFieldTypeEnum } from '../../../src/dynamicForm/enums/InputFieldTypeEnum';
15
+
16
+ const parse = <T extends object>(cls: new () => T, value: object): T => plainToInstance(cls, value, { excludeExtraneousValues: true });
17
+
18
+ const evaluation = {
19
+ id: 'eval-1',
20
+ campaignId: 'camp-1',
21
+ name: 'Eval',
22
+ description: '',
23
+ inputs: [],
24
+ rules: {},
25
+ beneficiaryInput: 'user',
26
+ reward: {},
27
+ grantPolicy: {},
28
+ triggers: [{}],
29
+ };
30
+
31
+ describe('EvaluationRequest.evaluationStrategy', () => {
32
+ it('ausente valida igual que hoy', async () => {
33
+ expect(await validate(parse(EvaluationRequest, evaluation))).toEqual([]);
34
+ });
35
+ it('acepta LIVE y DATALAKE; rechaza otro', async () => {
36
+ const ok = parse(EvaluationRequest, { ...evaluation, evaluationStrategy: 'DATALAKE' });
37
+ expect(await validate(ok)).toEqual([]);
38
+ expect(ok.evaluationStrategy).toBe(EvaluationStrategyEnum.DATALAKE);
39
+ expect((await validate(parse(EvaluationRequest, { ...evaluation, evaluationStrategy: 'X' }))).length).toBe(1);
40
+ });
41
+ it('EvaluationResponse lleva evaluationStrategy opcional', () => {
42
+ const r: Pick<EvaluationResponse, 'evaluationStrategy'> = { evaluationStrategy: EvaluationStrategyEnum.LIVE };
43
+ expect(r.evaluationStrategy).toBe('LIVE');
44
+ });
45
+ });
46
+
47
+ describe('RewardInputRef', () => {
48
+ it('admite const, input y field con fallback y as', () => {
49
+ const refs: RewardInputRef[] = [
50
+ { const: 'x' },
51
+ { input: 'email' },
52
+ { field: 'directory:email' },
53
+ { field: 'credit-activity:overdueCount', fallback: 0, as: InputFieldTypeEnum.NUMBER },
54
+ ];
55
+ expect(refs).toHaveLength(4);
56
+ });
57
+ });
58
+
59
+ describe('EvaluateBatchMessage', () => {
60
+ const msg = (n: number) => ({
61
+ messageType: 'EVALUATE_BATCH',
62
+ runId: 'r',
63
+ batchId: 'b',
64
+ subjects: Array.from({ length: n }, (_v, i) => ({ subjectKey: `s-${i}`, inputs: {} })),
65
+ });
66
+ it('constante 1000', () => expect(EVALUATE_BATCH_MAX_SUBJECTS).toBe(1000));
67
+ it('1000 sujetos ok, 1001 error', async () => {
68
+ expect(await validate(parse(EvaluateBatchMessage, msg(1000)))).toEqual([]);
69
+ expect((await validate(parse(EvaluateBatchMessage, msg(1001)))).length).toBe(1);
70
+ });
71
+ });
72
+
73
+ describe.each([
74
+ ['CreateRunRequest', () => ({ requestId: 'req-12345678', mode: 'LIVE', inputs: {} }), CreateRunRequest],
75
+ ['SimulateRequest', () => ({ evaluationId: 'eval-1', inputs: {} }), SimulateRequest],
76
+ ] as const)('%s.rewardInputs', (_name, make, cls) => {
77
+ it('sin rewardInputs valida igual', async () => {
78
+ expect(await validate(parse(cls as new () => object, make()))).toEqual([]);
79
+ });
80
+ it('acepta dos niveles item → clave → valor', async () => {
81
+ const r = parse(cls as new () => object, { ...make(), rewardInputs: { item: { key: 'v', n: 3, b: true, d: { from: '1d', to: '2d' } } } });
82
+ expect(await validate(r)).toEqual([]);
83
+ });
84
+ it.each([
85
+ ['valor anidado', { item: { key: { a: { b: 1 } } } }],
86
+ ['un solo nivel', { item: 'v' }],
87
+ ['array', [1]],
88
+ ['nivel interno array', { item: ['x'] }],
89
+ ])('rechaza: %s', async (_n, value) => {
90
+ const r = parse(cls as new () => object, { ...make(), rewardInputs: value });
91
+ expect((await validate(r)).length).toBeGreaterThan(0);
92
+ });
93
+ });
@@ -17,12 +17,12 @@ describe('mensajes de la cola de elegibilidad', () => {
17
17
  expect(await ok(ReleaseTrancheMessage, { messageType: T.RELEASE_TRANCHE, seq: 3 })).toBe(true);
18
18
  expect(await ok(ReleaseTrancheMessage, { messageType: T.RELEASE_TRANCHE, seq: -1 })).toBe(false);
19
19
  });
20
- it('EVALUATE_BATCH: <= 100 sujetos, sin prefetchedFacts', async () => {
20
+ it('EVALUATE_BATCH: <= 1000 sujetos, sin prefetchedFacts', async () => {
21
21
  const subject = { subjectKey: 'd-1', inputs: { directoryId: 'd-1' } };
22
22
  const base = { messageType: T.EVALUATE_BATCH, runId: 'r-1', batchId: 'r-1#p0#b0' };
23
23
  expect(await ok(EvaluateBatchMessage, { ...base, subjects: [subject] })).toBe(true);
24
24
  expect(await ok(EvaluateBatchMessage, { ...base, subjects: [] })).toBe(false);
25
- expect(await ok(EvaluateBatchMessage, { ...base, subjects: Array.from({ length: 101 }, () => subject) })).toBe(false);
25
+ expect(await ok(EvaluateBatchMessage, { ...base, subjects: Array.from({ length: 1001 }, () => subject) })).toBe(false);
26
26
  const parsed = plainToInstance(EvaluateBatchMessage, { ...base, subjects: [{ ...subject, prefetchedFacts: { a: 1 } }] }, { excludeExtraneousValues: true });
27
27
  expect('prefetchedFacts' in parsed.subjects[0]).toBe(false);
28
28
  });
@@ -0,0 +1,144 @@
1
+ import 'reflect-metadata';
2
+ import { plainToInstance } from 'class-transformer';
3
+ import { validate } from 'class-validator';
4
+ import {
5
+ EvaluateRulesRequest,
6
+ EvaluationExecutionRequest,
7
+ EvaluationExecutionResponse,
8
+ EvaluationExecutionResultsResponse,
9
+ EvaluationResultsRequest,
10
+ EvaluationStrategyEnum,
11
+ PopulationExecutionStatusEnum,
12
+ RETURN_FIELD_ID_PATTERN,
13
+ RULES_MAX_RETURN_FIELDS,
14
+ RULES_MAX_SUBJECTS_PER_DATALAKE_CALL,
15
+ ReturnFieldsCatalogResponse,
16
+ RulesErrorCodeEnum,
17
+ RulesValueTypeEnum,
18
+ SegmentColumnSchemaResponse,
19
+ ValidateRulesRequest,
20
+ } from '../../../src/rules';
21
+
22
+ const parse = <T extends object>(cls: new () => T, value: object): T => plainToInstance(cls, value, { excludeExtraneousValues: true });
23
+ const KEY = 'k'.repeat(32);
24
+ const base = { items: ['directory:email'], subjects: [{ directoryId: 'd-1' }], rules: [{ id: 'r1', rule: { match: 'ALL', groups: [] } }] };
25
+ const validReturn = ['credit-activity:overdueCount', 'directoryuser.email', 'surekeeploanscievaluation.offer.termsweeks'];
26
+
27
+ describe('constantes y enums', () => {
28
+ it('exporta los valores del contrato', () => {
29
+ expect(EvaluationStrategyEnum).toEqual({ LIVE: 'LIVE', DATALAKE: 'DATALAKE' });
30
+ expect(RULES_MAX_SUBJECTS_PER_DATALAKE_CALL).toBe(1000);
31
+ expect(RULES_MAX_RETURN_FIELDS).toBe(20);
32
+ expect(RulesErrorCodeEnum.RULE_NOT_DATALAKE_COMPATIBLE).toBe('RULE_NOT_DATALAKE_COMPATIBLE');
33
+ expect(RulesErrorCodeEnum.DATALAKE_UNAVAILABLE).toBe('DATALAKE_UNAVAILABLE');
34
+ expect(RulesErrorCodeEnum.DATALAKE_EVALUATION_FAILED).toBe('DATALAKE_EVALUATION_FAILED');
35
+ expect(RulesErrorCodeEnum.DATALAKE_EVALUATION_TIMEOUT).toBe('DATALAKE_EVALUATION_TIMEOUT');
36
+ expect(RulesErrorCodeEnum.UNKNOWN_RETURN_FIELD).toBe('UNKNOWN_RETURN_FIELD');
37
+ });
38
+ it('RETURN_FIELD_ID_PATTERN', () => {
39
+ validReturn.forEach((id) => expect(RETURN_FIELD_ID_PATTERN.test(id)).toBe(true));
40
+ ['Credit:x', 'a', 'tabla.', 'x y', 'a:1x'].forEach((id) => expect(RETURN_FIELD_ID_PATTERN.test(id)).toBe(false));
41
+ });
42
+ });
43
+
44
+ describe('EvaluateRulesRequest / ValidateRulesRequest', () => {
45
+ it('sin campos nuevos sigue válido (compatibilidad)', async () => {
46
+ expect(await validate(parse(EvaluateRulesRequest, base))).toEqual([]);
47
+ });
48
+ it('acepta estrategia, returnFields válidos e inputContract', async () => {
49
+ const r = parse(EvaluateRulesRequest, { ...base, evaluationStrategy: 'DATALAKE', returnFields: validReturn, inputContract: [] });
50
+ expect(await validate(r)).toEqual([]);
51
+ expect(r.evaluationStrategy).toBe(EvaluationStrategyEnum.DATALAKE);
52
+ });
53
+ it('21 returnFields → error', async () => {
54
+ const ids = Array.from({ length: 21 }, (_v, i) => `directoryuser.c${i}`.replace(/\d/g, 'x') + '_a');
55
+ expect((await validate(parse(EvaluateRulesRequest, { ...base, returnFields: ids }))).length).toBe(1);
56
+ });
57
+ it.each(['Credit:x', 'a', 'tabla.', 'x y'])('returnField inválido %s', async (id) => {
58
+ expect((await validate(parse(EvaluateRulesRequest, { ...base, returnFields: [id] }))).length).toBe(1);
59
+ });
60
+ it('evaluationStrategy desconocida → error', async () => {
61
+ expect((await validate(parse(EvaluateRulesRequest, { ...base, evaluationStrategy: 'OTRO' }))).length).toBe(1);
62
+ });
63
+ it('inputContract de 31 campos → error', async () => {
64
+ const contract = Array.from({ length: 31 }, () => ({}));
65
+ expect((await validate(parse(EvaluateRulesRequest, { ...base, inputContract: contract }))).length).toBe(1);
66
+ });
67
+ it('ValidateRulesRequest acepta estrategia y returnFields', async () => {
68
+ const ok = parse(ValidateRulesRequest, { items: [], rule: {}, evaluationStrategy: 'LIVE', returnFields: validReturn });
69
+ expect(await validate(ok)).toEqual([]);
70
+ const bad = parse(ValidateRulesRequest, { items: [], rule: {}, evaluationStrategy: 'X', returnFields: ['a'] });
71
+ expect((await validate(bad)).length).toBe(2);
72
+ });
73
+ });
74
+
75
+ describe('EvaluationExecutionRequest', () => {
76
+ const exec = { items: ['directory:email'], subjects: [{ directoryId: 'd-1' }], rules: base.rules, referenceAt: '2026-10-22T10:00:00Z', idempotencyKey: KEY };
77
+ it('válido', async () => {
78
+ expect(await validate(parse(EvaluationExecutionRequest, exec))).toEqual([]);
79
+ });
80
+ it('idempotencyKey: 31 chars error, 32 ok, 129 error', async () => {
81
+ expect((await validate(parse(EvaluationExecutionRequest, { ...exec, idempotencyKey: 'k'.repeat(31) }))).length).toBe(1);
82
+ expect(await validate(parse(EvaluationExecutionRequest, { ...exec, idempotencyKey: KEY }))).toEqual([]);
83
+ expect((await validate(parse(EvaluationExecutionRequest, { ...exec, idempotencyKey: 'k'.repeat(129) }))).length).toBe(1);
84
+ });
85
+ it('referenceAt sin hora → error', async () => {
86
+ expect((await validate(parse(EvaluationExecutionRequest, { ...exec, referenceAt: '2026-10-22' }))).length).toBe(1);
87
+ });
88
+ it('sin rules y sin returnFields: el DTO lo acepta (la regla "rules o returnFields" la valida A10)', async () => {
89
+ const { rules: _rules, ...noRules } = exec;
90
+ expect(await validate(parse(EvaluationExecutionRequest, noRules))).toEqual([]);
91
+ });
92
+ it('modo solo campos con returnFields', async () => {
93
+ const { rules: _rules, ...noRules } = exec;
94
+ expect(await validate(parse(EvaluationExecutionRequest, { ...noRules, returnFields: validReturn }))).toEqual([]);
95
+ });
96
+ it('rules: 0 o más de 10 → error', async () => {
97
+ expect((await validate(parse(EvaluationExecutionRequest, { ...exec, rules: [] }))).length).toBe(1);
98
+ const eleven = Array.from({ length: 11 }, (_v, i) => ({ id: `r${i}`, rule: {} }));
99
+ expect((await validate(parse(EvaluationExecutionRequest, { ...exec, rules: eleven }))).length).toBe(1);
100
+ });
101
+ it('inputContract de 31 campos → error', async () => {
102
+ expect((await validate(parse(EvaluationExecutionRequest, { ...exec, inputContract: Array.from({ length: 31 }, () => ({})) }))).length).toBe(1);
103
+ });
104
+ it('sin sujetos o más de 1000 → error', async () => {
105
+ expect((await validate(parse(EvaluationExecutionRequest, { ...exec, subjects: [] }))).length).toBe(1);
106
+ const many = Array.from({ length: 1001 }, (_v, i) => ({ directoryId: `d-${i}` }));
107
+ expect((await validate(parse(EvaluationExecutionRequest, { ...exec, subjects: many }))).length).toBe(1);
108
+ const max = Array.from({ length: 1000 }, (_v, i) => ({ directoryId: `d-${i}` }));
109
+ expect(await validate(parse(EvaluationExecutionRequest, { ...exec, subjects: max }))).toEqual([]);
110
+ });
111
+ });
112
+
113
+ describe('EvaluationResultsRequest y respuestas', () => {
114
+ it('results request: nextToken y returnFields opcionales', async () => {
115
+ const r = parse(EvaluationResultsRequest, { items: [], rules: base.rules, returnFields: validReturn, nextToken: 't' });
116
+ expect(await validate(r)).toEqual([]);
117
+ expect((await validate(parse(EvaluationResultsRequest, { items: [], returnFields: ['a'] }))).length).toBe(1);
118
+ });
119
+ it('formas de respuesta (tipado)', () => {
120
+ const run: EvaluationExecutionResponse = { executionId: 'e', status: PopulationExecutionStatusEnum.RUNNING };
121
+ const res: EvaluationExecutionResultsResponse = {
122
+ executionId: 'e',
123
+ status: PopulationExecutionStatusEnum.FAILED,
124
+ results: [],
125
+ reason: RulesErrorCodeEnum.DATALAKE_EVALUATION_TIMEOUT,
126
+ };
127
+ const cat: ReturnFieldsCatalogResponse = {
128
+ available: true,
129
+ fields: [{ id: 'directory:email', source: 'directory', field: 'email', label: 'Correo', description: '', valueType: RulesValueTypeEnum.STRING, datalakeCompatible: true }],
130
+ };
131
+ expect(run.status).toBe('RUNNING');
132
+ expect(res.reason).toBe('DATALAKE_EVALUATION_TIMEOUT');
133
+ expect(cat.fields[0].id).toBe('directory:email');
134
+ });
135
+ });
136
+
137
+ describe('SegmentColumnSchemaResponse', () => {
138
+ it('inArray es opcional', () => {
139
+ const a: SegmentColumnSchemaResponse = { name: 'x', type: 'string', isDate: false, operators: [] };
140
+ const b: SegmentColumnSchemaResponse = { ...a, inArray: true };
141
+ expect(a.inArray).toBeUndefined();
142
+ expect(b.inArray).toBe(true);
143
+ });
144
+ });
@@ -0,0 +1,2 @@
1
+ /** Máximo de sujetos de un `EvaluateBatchMessage` (lote de una evaluación DATALAKE). */
2
+ export declare const EVALUATE_BATCH_MAX_SUBJECTS = 1000;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EVALUATE_BATCH_MAX_SUBJECTS = void 0;
4
+ /** Máximo de sujetos de un `EvaluateBatchMessage` (lote de una evaluación DATALAKE). */
5
+ exports.EVALUATE_BATCH_MAX_SUBJECTS = 1000;
@@ -8,4 +8,6 @@ export declare class CreateRunRequest {
8
8
  mode: RunModeEnum;
9
9
  inputs?: Record<string, DynamicFormValue>;
10
10
  population?: PopulationRunRequest;
11
+ /** Valores escritos por el operador para ESTA corrida: itemKey → inputKey → valor. */
12
+ rewardInputs?: Record<string, Record<string, DynamicFormValue>>;
11
13
  }
@@ -13,6 +13,7 @@ exports.CreateRunRequest = void 0;
13
13
  const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
15
  const IsDynamicFormValues_1 = require("../../../dynamicForm/validators/IsDynamicFormValues");
16
+ const IsRewardInputs_1 = require("../../validators/IsRewardInputs");
16
17
  const BackofficeLimits_1 = require("../../constants/BackofficeLimits");
17
18
  const RunModeEnum_1 = require("../../enums/RunModeEnum");
18
19
  const PopulationRunRequest_1 = require("./PopulationRunRequest");
@@ -45,3 +46,9 @@ __decorate([
45
46
  (0, class_transformer_1.Type)(() => PopulationRunRequest_1.PopulationRunRequest),
46
47
  __metadata("design:type", PopulationRunRequest_1.PopulationRunRequest)
47
48
  ], CreateRunRequest.prototype, "population", void 0);
49
+ __decorate([
50
+ (0, class_transformer_1.Expose)(),
51
+ (0, class_validator_1.IsOptional)(),
52
+ (0, class_validator_1.Validate)(IsRewardInputs_1.IsRewardInputs),
53
+ __metadata("design:type", Object)
54
+ ], CreateRunRequest.prototype, "rewardInputs", void 0);
@@ -1,4 +1,5 @@
1
1
  import { JsonValue } from '../../../common';
2
+ import { EvaluationStrategyEnum } from '../../../rules/enums/EvaluationStrategyEnum';
2
3
  import { InputField } from '../../../dynamicForm/dtos/InputField';
3
4
  import { EvaluationReward } from '../EvaluationReward';
4
5
  import { EvaluationTrigger } from '../EvaluationTrigger';
@@ -28,4 +29,6 @@ export declare class EvaluationRequest {
28
29
  populationSegmentId?: string;
29
30
  /** Llave del input `DIRECTORY` que recibe el `directoryid` de cada persona del segmento. */
30
31
  populationInputKey?: string;
32
+ /** Estrategia de evaluación de las corridas masivas; ausente = `LIVE`. */
33
+ evaluationStrategy?: EvaluationStrategyEnum;
31
34
  }
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.EvaluationRequest = void 0;
13
13
  const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
+ const EvaluationStrategyEnum_1 = require("../../../rules/enums/EvaluationStrategyEnum");
15
16
  const BackofficeLimits_1 = require("../../constants/BackofficeLimits");
16
17
  const EvaluationReward_1 = require("../EvaluationReward");
17
18
  const GrantPolicy_1 = require("../GrantPolicy");
@@ -98,3 +99,9 @@ __decorate([
98
99
  (0, class_validator_1.Matches)(BackofficeLimits_1.INPUT_KEY_PATTERN),
99
100
  __metadata("design:type", String)
100
101
  ], EvaluationRequest.prototype, "populationInputKey", void 0);
102
+ __decorate([
103
+ (0, class_transformer_1.Expose)(),
104
+ (0, class_validator_1.IsOptional)(),
105
+ (0, class_validator_1.IsEnum)(EvaluationStrategyEnum_1.EvaluationStrategyEnum),
106
+ __metadata("design:type", String)
107
+ ], EvaluationRequest.prototype, "evaluationStrategy", void 0);
@@ -1,4 +1,5 @@
1
1
  import { JsonValue } from '../../../common';
2
+ import { EvaluationStrategyEnum } from '../../../rules/enums/EvaluationStrategyEnum';
2
3
  import { InputField } from '../../../dynamicForm/dtos/InputField';
3
4
  import { EvaluationStatusEnum } from '../../enums/EvaluationStatusEnum';
4
5
  import { EvaluationReward } from '../EvaluationReward';
@@ -22,6 +23,8 @@ export declare class EvaluationResponse {
22
23
  triggers: EvaluationTrigger[];
23
24
  populationSegmentId?: string;
24
25
  populationInputKey?: string;
26
+ /** Ausente = `LIVE`. */
27
+ evaluationStrategy?: EvaluationStrategyEnum;
25
28
  createdAt: number;
26
29
  updatedAt: number;
27
30
  updatedBy: string;
@@ -5,4 +5,6 @@ export declare class SimulateRequest {
5
5
  evaluationId?: string;
6
6
  evaluation?: EvaluationRequest;
7
7
  inputs: Record<string, DynamicFormValue>;
8
+ /** Valores escritos por el operador para ESTA corrida: itemKey → inputKey → valor. */
9
+ rewardInputs?: Record<string, Record<string, DynamicFormValue>>;
8
10
  }
@@ -13,6 +13,7 @@ exports.SimulateRequest = void 0;
13
13
  const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
15
  const IsDynamicFormValues_1 = require("../../../dynamicForm/validators/IsDynamicFormValues");
16
+ const IsRewardInputs_1 = require("../../validators/IsRewardInputs");
16
17
  const BackofficeLimits_1 = require("../../constants/BackofficeLimits");
17
18
  const EvaluationRequest_1 = require("./EvaluationRequest");
18
19
  /** `POST /evaluations/simulate`: una evaluación GUARDADA (`evaluationId`) o un BORRADOR sin guardar (`evaluation`), más los inputs del sujeto. No persiste nada. Exactamente uno de los dos lo valida el lambda. */
@@ -38,3 +39,9 @@ __decorate([
38
39
  (0, class_validator_1.Validate)(IsDynamicFormValues_1.IsDynamicFormValues),
39
40
  __metadata("design:type", Object)
40
41
  ], SimulateRequest.prototype, "inputs", void 0);
42
+ __decorate([
43
+ (0, class_transformer_1.Expose)(),
44
+ (0, class_validator_1.IsOptional)(),
45
+ (0, class_validator_1.Validate)(IsRewardInputs_1.IsRewardInputs),
46
+ __metadata("design:type", Object)
47
+ ], SimulateRequest.prototype, "rewardInputs", void 0);
@@ -5,7 +5,7 @@ export declare class EvaluateBatchSubject {
5
5
  subjectKey: string;
6
6
  inputs: Record<string, DynamicFormValue>;
7
7
  }
8
- /** Lote de hasta 100 sujetos a evaluar en una corrida masiva. */
8
+ /** Lote de hasta 1000 sujetos a evaluar en una corrida masiva. */
9
9
  export declare class EvaluateBatchMessage {
10
10
  messageType: EligibilityMessageTypeEnum.EVALUATE_BATCH;
11
11
  runId: string;
@@ -13,6 +13,7 @@ exports.EvaluateBatchMessage = exports.EvaluateBatchSubject = void 0;
13
13
  const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
15
  const IsDynamicFormValues_1 = require("../../../dynamicForm/validators/IsDynamicFormValues");
16
+ const BatchLimits_1 = require("../../constants/BatchLimits");
16
17
  const EligibilityMessageTypeEnum_1 = require("../../enums/EligibilityMessageTypeEnum");
17
18
  /** Un sujeto del lote. No lleva hechos precargados: la evaluacion siempre es en vivo. */
18
19
  class EvaluateBatchSubject {
@@ -29,7 +30,7 @@ __decorate([
29
30
  (0, class_validator_1.Validate)(IsDynamicFormValues_1.IsDynamicFormValues),
30
31
  __metadata("design:type", Object)
31
32
  ], EvaluateBatchSubject.prototype, "inputs", void 0);
32
- /** Lote de hasta 100 sujetos a evaluar en una corrida masiva. */
33
+ /** Lote de hasta 1000 sujetos a evaluar en una corrida masiva. */
33
34
  class EvaluateBatchMessage {
34
35
  }
35
36
  exports.EvaluateBatchMessage = EvaluateBatchMessage;
@@ -54,7 +55,7 @@ __decorate([
54
55
  (0, class_transformer_1.Expose)(),
55
56
  (0, class_validator_1.IsArray)(),
56
57
  (0, class_validator_1.ArrayMinSize)(1),
57
- (0, class_validator_1.ArrayMaxSize)(100),
58
+ (0, class_validator_1.ArrayMaxSize)(BatchLimits_1.EVALUATE_BATCH_MAX_SUBJECTS),
58
59
  (0, class_validator_1.ValidateNested)({ each: true }),
59
60
  (0, class_transformer_1.Type)(() => EvaluateBatchSubject),
60
61
  __metadata("design:type", Array)
@@ -32,6 +32,8 @@ export * from './enums/MetricsDimensionEnum';
32
32
  export * from './enums/RuleValueTypeEnum';
33
33
  export * from './enums/RulesChatRoleEnum';
34
34
  export * from './constants/BackofficeLimits';
35
+ export * from './constants/BatchLimits';
36
+ export * from './validators/IsRewardInputs';
35
37
  export * from './dtos/backoffice/CampaignRequest';
36
38
  export * from './dtos/backoffice/CampaignStatusRequest';
37
39
  export * from './dtos/backoffice/CampaignResponse';
@@ -54,6 +54,8 @@ __exportStar(require("./enums/MetricsDimensionEnum"), exports);
54
54
  __exportStar(require("./enums/RuleValueTypeEnum"), exports);
55
55
  __exportStar(require("./enums/RulesChatRoleEnum"), exports);
56
56
  __exportStar(require("./constants/BackofficeLimits"), exports);
57
+ __exportStar(require("./constants/BatchLimits"), exports);
58
+ __exportStar(require("./validators/IsRewardInputs"), exports);
57
59
  __exportStar(require("./dtos/backoffice/CampaignRequest"), exports);
58
60
  __exportStar(require("./dtos/backoffice/CampaignStatusRequest"), exports);
59
61
  __exportStar(require("./dtos/backoffice/CampaignResponse"), exports);
@@ -1,7 +1,15 @@
1
+ import { InputFieldTypeEnum } from '../../dynamicForm/enums/InputFieldTypeEnum';
1
2
  import { DynamicFormValue } from '../../dynamicForm/types/DynamicFormValue';
2
- /** Valor de un input de `reward.inputs`: constante o tomado de un input de la evaluacion (spec B 5.1). */
3
+ /**
4
+ * Valor de un input de `reward.inputs`: constante, tomado de un input de la evaluacion (spec B 5.1)
5
+ * o de un campo del usuario leído del datalake (`field`). `as` lo fija el backend al guardar (tipo de la dependencia destino).
6
+ */
3
7
  export type RewardInputRef = {
4
8
  const: DynamicFormValue;
5
9
  } | {
6
10
  input: string;
11
+ } | {
12
+ field: string;
13
+ fallback?: DynamicFormValue;
14
+ as?: InputFieldTypeEnum;
7
15
  };
@@ -0,0 +1,7 @@
1
+ import { ValidationArguments, ValidatorConstraintInterface } from 'class-validator';
2
+ import { JsonValue } from '../../common/types/JsonValue';
3
+ /** Valida `itemKey → inputKey → DynamicFormValue` (dos niveles exactos). */
4
+ export declare class IsRewardInputs implements ValidatorConstraintInterface {
5
+ validate(value: JsonValue, _args: ValidationArguments): boolean;
6
+ defaultMessage(_args: ValidationArguments): string;
7
+ }
@@ -0,0 +1,26 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.IsRewardInputs = void 0;
10
+ const class_validator_1 = require("class-validator");
11
+ const isDynamicFormValue_1 = require("../../dynamicForm/helpers/isDynamicFormValue");
12
+ /** Valida `itemKey → inputKey → DynamicFormValue` (dos niveles exactos). */
13
+ let IsRewardInputs = class IsRewardInputs {
14
+ validate(value, _args) {
15
+ if (!(0, isDynamicFormValue_1.isPlainObject)(value))
16
+ return false;
17
+ return Object.values(value).every((inner) => (0, isDynamicFormValue_1.isPlainObject)(inner) && Object.values(inner).every(isDynamicFormValue_1.isDynamicFormValue));
18
+ }
19
+ defaultMessage(_args) {
20
+ return 'rewardInputs debe ser un mapa itemKey → inputKey → string | number | boolean | {from, to}';
21
+ }
22
+ };
23
+ exports.IsRewardInputs = IsRewardInputs;
24
+ exports.IsRewardInputs = IsRewardInputs = __decorate([
25
+ (0, class_validator_1.ValidatorConstraint)({ name: 'IsRewardInputs', async: false })
26
+ ], IsRewardInputs);
@@ -6,3 +6,9 @@ export declare const RULES_INPUT_SOURCE = "input";
6
6
  export declare const RULES_MAX_INPUT_CONTRACT = 30;
7
7
  /** Largo máximo (caracteres) del contenido de un turno del chat de `POST /generate`. */
8
8
  export declare const RULES_CHAT_TURN_MAX_LENGTH = 4000;
9
+ /** Máximo de sujetos por query asíncrona de evaluación DATALAKE (`POST /evaluate/executions`). */
10
+ export declare const RULES_MAX_SUBJECTS_PER_DATALAKE_CALL = 1000;
11
+ /** Máximo de `returnFields` por llamada. */
12
+ export declare const RULES_MAX_RETURN_FIELDS = 20;
13
+ /** Id de campo devuelto: `fuente:campo` (campo del catálogo) o `tabla.ruta.hoja` (hoja del esquema aplanado de Glue). */
14
+ export declare const RETURN_FIELD_ID_PATTERN: RegExp;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RULES_CHAT_TURN_MAX_LENGTH = exports.RULES_MAX_INPUT_CONTRACT = exports.RULES_INPUT_SOURCE = exports.RULES_MAX_SUBJECTS_PER_CALL = void 0;
3
+ exports.RETURN_FIELD_ID_PATTERN = exports.RULES_MAX_RETURN_FIELDS = exports.RULES_MAX_SUBJECTS_PER_DATALAKE_CALL = exports.RULES_CHAT_TURN_MAX_LENGTH = exports.RULES_MAX_INPUT_CONTRACT = exports.RULES_INPUT_SOURCE = exports.RULES_MAX_SUBJECTS_PER_CALL = void 0;
4
4
  /** Máximo de sujetos por llamada a `POST /evaluate` (si no, 400 `TOO_MANY_SUBJECTS`). */
5
5
  exports.RULES_MAX_SUBJECTS_PER_CALL = 100;
6
6
  /** Fuente especial: datos que el llamador manda en la llamada, no se resuelven ni se piden en `items`. */
@@ -9,3 +9,9 @@ exports.RULES_INPUT_SOURCE = 'input';
9
9
  exports.RULES_MAX_INPUT_CONTRACT = 30;
10
10
  /** Largo máximo (caracteres) del contenido de un turno del chat de `POST /generate`. */
11
11
  exports.RULES_CHAT_TURN_MAX_LENGTH = 4000;
12
+ /** Máximo de sujetos por query asíncrona de evaluación DATALAKE (`POST /evaluate/executions`). */
13
+ exports.RULES_MAX_SUBJECTS_PER_DATALAKE_CALL = 1000;
14
+ /** Máximo de `returnFields` por llamada. */
15
+ exports.RULES_MAX_RETURN_FIELDS = 20;
16
+ /** Id de campo devuelto: `fuente:campo` (campo del catálogo) o `tabla.ruta.hoja` (hoja del esquema aplanado de Glue). */
17
+ exports.RETURN_FIELD_ID_PATTERN = /^(?:[a-z][a-z0-9-]*:[A-Za-z][A-Za-z0-9_]*|[a-z_][a-z0-9_]*(?:\.[a-z_][a-z0-9_]*){1,8})$/;
@@ -1,5 +1,7 @@
1
1
  import { JsonValue } from '../../common';
2
+ import { InputField } from '../../dynamicForm/dtos/InputField';
2
3
  import { DynamicFormValue } from '../../dynamicForm/types/DynamicFormValue';
4
+ import { EvaluationStrategyEnum } from '../enums/EvaluationStrategyEnum';
3
5
  /** A quién se le evalúa la regla. */
4
6
  export declare class RulesEvaluationSubject {
5
7
  directoryId: string;
@@ -27,4 +29,10 @@ export declare class EvaluateRulesRequest {
27
29
  subjects: RulesEvaluationSubject[];
28
30
  /** Fecha ISO 8601; por defecto, el momento de la llamada. */
29
31
  referenceAt?: string;
32
+ /** Estrategia de evaluación; ausente = `LIVE`. */
33
+ evaluationStrategy?: EvaluationStrategyEnum;
34
+ /** Campos a devolver por sujeto (`fuente:campo` o `tabla.ruta.hoja`); máx. 20. Se leen del datalake. */
35
+ returnFields?: string[];
36
+ /** Contrato de la fuente `input` (tipos de las columnas `i_<llave>` en DATALAKE). */
37
+ inputContract?: InputField[];
30
38
  }
@@ -12,6 +12,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.EvaluateRulesRequest = exports.RuleToEvaluate = exports.RulesEvaluationSubject = void 0;
13
13
  const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
+ const RulesLimits_1 = require("../constants/RulesLimits");
16
+ const EvaluationStrategyEnum_1 = require("../enums/EvaluationStrategyEnum");
15
17
  /** A quién se le evalúa la regla. */
16
18
  class RulesEvaluationSubject {
17
19
  }
@@ -82,3 +84,25 @@ __decorate([
82
84
  (0, class_validator_1.IsISO8601)(),
83
85
  __metadata("design:type", String)
84
86
  ], EvaluateRulesRequest.prototype, "referenceAt", void 0);
87
+ __decorate([
88
+ (0, class_transformer_1.Expose)(),
89
+ (0, class_validator_1.IsOptional)(),
90
+ (0, class_validator_1.IsEnum)(EvaluationStrategyEnum_1.EvaluationStrategyEnum),
91
+ __metadata("design:type", String)
92
+ ], EvaluateRulesRequest.prototype, "evaluationStrategy", void 0);
93
+ __decorate([
94
+ (0, class_transformer_1.Expose)(),
95
+ (0, class_validator_1.IsOptional)(),
96
+ (0, class_validator_1.IsArray)(),
97
+ (0, class_validator_1.ArrayMaxSize)(RulesLimits_1.RULES_MAX_RETURN_FIELDS),
98
+ (0, class_validator_1.Matches)(RulesLimits_1.RETURN_FIELD_ID_PATTERN, { each: true }),
99
+ __metadata("design:type", Array)
100
+ ], EvaluateRulesRequest.prototype, "returnFields", void 0);
101
+ __decorate([
102
+ (0, class_transformer_1.Expose)(),
103
+ (0, class_validator_1.IsOptional)(),
104
+ (0, class_validator_1.IsArray)(),
105
+ (0, class_validator_1.ArrayMaxSize)(RulesLimits_1.RULES_MAX_INPUT_CONTRACT),
106
+ (0, class_validator_1.IsObject)({ each: true }),
107
+ __metadata("design:type", Array)
108
+ ], EvaluateRulesRequest.prototype, "inputContract", void 0);
@@ -1,3 +1,4 @@
1
+ import { JsonValue } from '../../common';
1
2
  import { RulesOutcomeEnum } from '../enums/RulesOutcomeEnum';
2
3
  import { RulesTraceResponse } from './RulesTraceResponse';
3
4
  /** Resultado de una regla para un sujeto. */
@@ -10,6 +11,8 @@ export declare class RuleEvaluationResult {
10
11
  trace?: RulesTraceResponse;
11
12
  /** Solo si `outcome` es `ERROR`. */
12
13
  errorMessage?: string;
14
+ /** Campos devueltos pedidos en `returnFields`: clave = id del campo; `null` = sin dato. */
15
+ returned?: Record<string, JsonValue>;
13
16
  }
14
17
  /** `POST /evaluate`: ordenado por regla y, dentro de cada regla, por `subjectIndex`. */
15
18
  export declare class EvaluateRulesResponse {
@@ -1,5 +1,6 @@
1
1
  import { JsonValue } from '../../common';
2
2
  import { InputField } from '../../dynamicForm/dtos/InputField';
3
+ import { EvaluationStrategyEnum } from '../enums/EvaluationStrategyEnum';
3
4
  /** `POST /validate`: valida una regla guardada contra el catálogo de los ítems indicados y el contrato de `input`. */
4
5
  export declare class ValidateRulesRequest {
5
6
  /** Quién llama (solo logs y métricas). */
@@ -12,4 +13,8 @@ export declare class ValidateRulesRequest {
12
13
  };
13
14
  /** Contrato de la fuente `input` (`InputField[]`, dominio `dynamicForm`). */
14
15
  inputContract?: InputField[];
16
+ /** Estrategia contra la que se valida; ausente = `LIVE`. */
17
+ evaluationStrategy?: EvaluationStrategyEnum;
18
+ /** Campos devueltos a validar (`fuente:campo` o `tabla.ruta.hoja`); máx. 20. */
19
+ returnFields?: string[];
15
20
  }
@@ -13,6 +13,7 @@ exports.ValidateRulesRequest = void 0;
13
13
  const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
15
  const RulesLimits_1 = require("../constants/RulesLimits");
16
+ const EvaluationStrategyEnum_1 = require("../enums/EvaluationStrategyEnum");
16
17
  /** `POST /validate`: valida una regla guardada contra el catálogo de los ítems indicados y el contrato de `input`. */
17
18
  class ValidateRulesRequest {
18
19
  }
@@ -42,3 +43,17 @@ __decorate([
42
43
  (0, class_validator_1.IsObject)({ each: true }),
43
44
  __metadata("design:type", Array)
44
45
  ], ValidateRulesRequest.prototype, "inputContract", void 0);
46
+ __decorate([
47
+ (0, class_transformer_1.Expose)(),
48
+ (0, class_validator_1.IsOptional)(),
49
+ (0, class_validator_1.IsEnum)(EvaluationStrategyEnum_1.EvaluationStrategyEnum),
50
+ __metadata("design:type", String)
51
+ ], ValidateRulesRequest.prototype, "evaluationStrategy", void 0);
52
+ __decorate([
53
+ (0, class_transformer_1.Expose)(),
54
+ (0, class_validator_1.IsOptional)(),
55
+ (0, class_validator_1.IsArray)(),
56
+ (0, class_validator_1.ArrayMaxSize)(RulesLimits_1.RULES_MAX_RETURN_FIELDS),
57
+ (0, class_validator_1.Matches)(RulesLimits_1.RETURN_FIELD_ID_PATTERN, { each: true }),
58
+ __metadata("design:type", Array)
59
+ ], ValidateRulesRequest.prototype, "returnFields", void 0);