@fiado/type-kit 3.516.0 → 3.518.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/rewardsEligibility/backofficeBarrel.test.ts +17 -0
- package/_test_/unit/rewardsEligibility/campaignAndEventTypeDtos.test.ts +52 -0
- package/_test_/unit/rewardsEligibility/campaignConfigDecorators.test.ts +49 -0
- package/_test_/unit/rewardsEligibility/catalogDtos.test.ts +27 -0
- package/_test_/unit/rewardsEligibility/evaluationDtos.test.ts +53 -0
- package/_test_/unit/rewardsEligibility/events.test.ts +3 -3
- package/_test_/unit/rewardsEligibility/generateRulesRequest.test.ts +50 -0
- package/_test_/unit/rewardsEligibility/generateRulesResponse.test.ts +12 -0
- package/_test_/unit/rewardsEligibility/metricsDtos.test.ts +17 -0
- package/_test_/unit/rewardsEligibility/ruleCatalogRich.test.ts +18 -0
- package/_test_/unit/rewardsEligibility/rulesAiEnums.test.ts +15 -0
- package/_test_/unit/rewardsEligibility/runDtos.test.ts +36 -0
- package/bin/rewardsEligibility/constants/BackofficeLimits.d.ts +16 -0
- package/bin/rewardsEligibility/constants/BackofficeLimits.js +19 -0
- package/bin/rewardsEligibility/dtos/CampaignAlerts.js +20 -0
- package/bin/rewardsEligibility/dtos/CampaignQuota.d.ts +1 -1
- package/bin/rewardsEligibility/dtos/CampaignQuota.js +29 -0
- package/bin/rewardsEligibility/dtos/backoffice/ApproveRunRequest.d.ts +4 -0
- package/bin/rewardsEligibility/dtos/backoffice/ApproveRunRequest.js +27 -0
- package/bin/rewardsEligibility/dtos/backoffice/CampaignListResponse.d.ts +6 -0
- package/bin/rewardsEligibility/dtos/backoffice/CampaignListResponse.js +6 -0
- package/bin/rewardsEligibility/dtos/backoffice/CampaignRequest.d.ts +16 -0
- package/bin/rewardsEligibility/dtos/backoffice/CampaignRequest.js +72 -0
- package/bin/rewardsEligibility/dtos/backoffice/CampaignResponse.d.ts +23 -0
- package/bin/rewardsEligibility/dtos/backoffice/CampaignResponse.js +7 -0
- package/bin/rewardsEligibility/dtos/backoffice/CampaignStatusRequest.d.ts +5 -0
- package/bin/rewardsEligibility/dtos/backoffice/CampaignStatusRequest.js +24 -0
- package/bin/rewardsEligibility/dtos/backoffice/CampaignSummaryResponse.d.ts +28 -0
- package/bin/rewardsEligibility/dtos/backoffice/CampaignSummaryResponse.js +7 -0
- package/bin/rewardsEligibility/dtos/backoffice/CreateRunRequest.d.ts +11 -0
- package/bin/rewardsEligibility/dtos/backoffice/CreateRunRequest.js +45 -0
- package/bin/rewardsEligibility/dtos/backoffice/CreateRunResponse.d.ts +9 -0
- package/bin/rewardsEligibility/dtos/backoffice/CreateRunResponse.js +7 -0
- package/bin/rewardsEligibility/dtos/backoffice/EvaluationListResponse.d.ts +5 -0
- package/bin/rewardsEligibility/dtos/backoffice/EvaluationListResponse.js +6 -0
- package/bin/rewardsEligibility/dtos/backoffice/EvaluationRequest.d.ts +27 -0
- package/bin/rewardsEligibility/dtos/backoffice/EvaluationRequest.js +86 -0
- package/bin/rewardsEligibility/dtos/backoffice/EvaluationResponse.d.ts +26 -0
- package/bin/rewardsEligibility/dtos/backoffice/EvaluationResponse.js +6 -0
- package/bin/rewardsEligibility/dtos/backoffice/EvaluationStatusRequest.d.ts +5 -0
- package/bin/rewardsEligibility/dtos/backoffice/EvaluationStatusRequest.js +24 -0
- package/bin/rewardsEligibility/dtos/backoffice/EventTypeListResponse.d.ts +5 -0
- package/bin/rewardsEligibility/dtos/backoffice/EventTypeListResponse.js +6 -0
- package/bin/rewardsEligibility/dtos/backoffice/EventTypeRequest.d.ts +12 -0
- package/bin/rewardsEligibility/dtos/backoffice/EventTypeRequest.js +58 -0
- package/bin/rewardsEligibility/dtos/backoffice/EventTypeResponse.d.ts +12 -0
- package/bin/rewardsEligibility/dtos/backoffice/EventTypeResponse.js +6 -0
- package/bin/rewardsEligibility/dtos/backoffice/FailedConditionStatResponse.d.ts +8 -0
- package/bin/rewardsEligibility/dtos/backoffice/FailedConditionStatResponse.js +7 -0
- package/bin/rewardsEligibility/dtos/backoffice/GenerateRulesRequest.d.ts +17 -0
- package/bin/rewardsEligibility/dtos/backoffice/GenerateRulesRequest.js +44 -0
- package/bin/rewardsEligibility/dtos/backoffice/GenerateRulesResponse.d.ts +18 -0
- package/bin/rewardsEligibility/dtos/backoffice/GenerateRulesResponse.js +12 -0
- package/bin/rewardsEligibility/dtos/backoffice/InputTypeResponse.d.ts +6 -0
- package/bin/rewardsEligibility/dtos/backoffice/InputTypeResponse.js +7 -0
- package/bin/rewardsEligibility/dtos/backoffice/MetricsPointResponse.d.ts +14 -0
- package/bin/rewardsEligibility/dtos/backoffice/MetricsPointResponse.js +7 -0
- package/bin/rewardsEligibility/dtos/backoffice/MetricsQuery.d.ts +9 -0
- package/bin/rewardsEligibility/dtos/backoffice/MetricsQuery.js +7 -0
- package/bin/rewardsEligibility/dtos/backoffice/PopulationRunRequest.d.ts +5 -0
- package/bin/rewardsEligibility/dtos/backoffice/PopulationRunRequest.js +24 -0
- package/bin/rewardsEligibility/dtos/backoffice/PopulationSourceResponse.d.ts +11 -0
- package/bin/rewardsEligibility/dtos/backoffice/PopulationSourceResponse.js +7 -0
- package/bin/rewardsEligibility/dtos/backoffice/QuotaImpactResponse.d.ts +9 -0
- package/bin/rewardsEligibility/dtos/backoffice/QuotaImpactResponse.js +7 -0
- package/bin/rewardsEligibility/dtos/backoffice/QuotaUsageResponse.d.ts +10 -0
- package/bin/rewardsEligibility/dtos/backoffice/QuotaUsageResponse.js +7 -0
- package/bin/rewardsEligibility/dtos/backoffice/ResultTraceResponse.d.ts +34 -0
- package/bin/rewardsEligibility/dtos/backoffice/ResultTraceResponse.js +14 -0
- package/bin/rewardsEligibility/dtos/backoffice/RuleCatalogResponse.d.ts +33 -0
- package/bin/rewardsEligibility/dtos/backoffice/RuleCatalogResponse.js +13 -0
- package/bin/rewardsEligibility/dtos/backoffice/RulesChatTurn.d.ts +6 -0
- package/bin/rewardsEligibility/dtos/backoffice/RulesChatTurn.js +32 -0
- package/bin/rewardsEligibility/dtos/backoffice/RunListResponse.d.ts +5 -0
- package/bin/rewardsEligibility/dtos/backoffice/RunListResponse.js +6 -0
- package/bin/rewardsEligibility/dtos/backoffice/RunResponse.d.ts +24 -0
- package/bin/rewardsEligibility/dtos/backoffice/RunResponse.js +7 -0
- package/bin/rewardsEligibility/dtos/backoffice/RunResultListResponse.d.ts +5 -0
- package/bin/rewardsEligibility/dtos/backoffice/RunResultListResponse.js +6 -0
- package/bin/rewardsEligibility/dtos/backoffice/RunResultResponse.d.ts +22 -0
- package/bin/rewardsEligibility/dtos/backoffice/RunResultResponse.js +7 -0
- package/bin/rewardsEligibility/dtos/backoffice/SimulateRequest.d.ts +8 -0
- package/bin/rewardsEligibility/dtos/backoffice/SimulateRequest.js +40 -0
- package/bin/rewardsEligibility/dtos/backoffice/SimulateResponse.d.ts +11 -0
- package/bin/rewardsEligibility/dtos/backoffice/SimulateResponse.js +6 -0
- package/bin/rewardsEligibility/enums/MetricsDimensionEnum.d.ts +8 -0
- package/bin/rewardsEligibility/enums/MetricsDimensionEnum.js +12 -0
- package/bin/rewardsEligibility/enums/RewardsEligibilityErrorCodeEnum.d.ts +56 -1
- package/bin/rewardsEligibility/enums/RewardsEligibilityErrorCodeEnum.js +56 -0
- package/bin/rewardsEligibility/enums/RuleValueTypeEnum.d.ts +9 -0
- package/bin/rewardsEligibility/enums/RuleValueTypeEnum.js +13 -0
- package/bin/rewardsEligibility/enums/RulesChatRoleEnum.d.ts +5 -0
- package/bin/rewardsEligibility/enums/RulesChatRoleEnum.js +9 -0
- package/bin/rewardsEligibility/index.d.ts +38 -0
- package/bin/rewardsEligibility/index.js +39 -0
- package/package.json +1 -1
- package/src/rewardsEligibility/constants/BackofficeLimits.ts +16 -0
- package/src/rewardsEligibility/dtos/CampaignAlerts.ts +9 -0
- package/src/rewardsEligibility/dtos/CampaignQuota.ts +13 -1
- package/src/rewardsEligibility/dtos/backoffice/ApproveRunRequest.ts +13 -0
- package/src/rewardsEligibility/dtos/backoffice/CampaignListResponse.ts +7 -0
- package/src/rewardsEligibility/dtos/backoffice/CampaignRequest.ts +53 -0
- package/src/rewardsEligibility/dtos/backoffice/CampaignResponse.ts +24 -0
- package/src/rewardsEligibility/dtos/backoffice/CampaignStatusRequest.ts +10 -0
- package/src/rewardsEligibility/dtos/backoffice/CampaignSummaryResponse.ts +26 -0
- package/src/rewardsEligibility/dtos/backoffice/CreateRunRequest.ts +30 -0
- package/src/rewardsEligibility/dtos/backoffice/CreateRunResponse.ts +10 -0
- package/src/rewardsEligibility/dtos/backoffice/EvaluationListResponse.ts +6 -0
- package/src/rewardsEligibility/dtos/backoffice/EvaluationRequest.ts +69 -0
- package/src/rewardsEligibility/dtos/backoffice/EvaluationResponse.ts +25 -0
- package/src/rewardsEligibility/dtos/backoffice/EvaluationStatusRequest.ts +10 -0
- package/src/rewardsEligibility/dtos/backoffice/EventTypeListResponse.ts +6 -0
- package/src/rewardsEligibility/dtos/backoffice/EventTypeRequest.ts +41 -0
- package/src/rewardsEligibility/dtos/backoffice/EventTypeResponse.ts +13 -0
- package/src/rewardsEligibility/dtos/backoffice/FailedConditionStatResponse.ts +8 -0
- package/src/rewardsEligibility/dtos/backoffice/GenerateRulesRequest.ts +33 -0
- package/src/rewardsEligibility/dtos/backoffice/GenerateRulesResponse.ts +17 -0
- package/src/rewardsEligibility/dtos/backoffice/InputTypeResponse.ts +7 -0
- package/src/rewardsEligibility/dtos/backoffice/MetricsPointResponse.ts +14 -0
- package/src/rewardsEligibility/dtos/backoffice/MetricsQuery.ts +10 -0
- package/src/rewardsEligibility/dtos/backoffice/PopulationRunRequest.ts +11 -0
- package/src/rewardsEligibility/dtos/backoffice/PopulationSourceResponse.ts +12 -0
- package/src/rewardsEligibility/dtos/backoffice/QuotaImpactResponse.ts +9 -0
- package/src/rewardsEligibility/dtos/backoffice/QuotaUsageResponse.ts +11 -0
- package/src/rewardsEligibility/dtos/backoffice/ResultTraceResponse.ts +34 -0
- package/src/rewardsEligibility/dtos/backoffice/RuleCatalogResponse.ts +32 -0
- package/src/rewardsEligibility/dtos/backoffice/RulesChatTurn.ts +17 -0
- package/src/rewardsEligibility/dtos/backoffice/RunListResponse.ts +6 -0
- package/src/rewardsEligibility/dtos/backoffice/RunResponse.ts +25 -0
- package/src/rewardsEligibility/dtos/backoffice/RunResultListResponse.ts +6 -0
- package/src/rewardsEligibility/dtos/backoffice/RunResultResponse.ts +23 -0
- package/src/rewardsEligibility/dtos/backoffice/SimulateRequest.ts +25 -0
- package/src/rewardsEligibility/dtos/backoffice/SimulateResponse.ts +12 -0
- package/src/rewardsEligibility/enums/MetricsDimensionEnum.ts +8 -0
- package/src/rewardsEligibility/enums/RewardsEligibilityErrorCodeEnum.ts +57 -0
- package/src/rewardsEligibility/enums/RuleValueTypeEnum.ts +9 -0
- package/src/rewardsEligibility/enums/RulesChatRoleEnum.ts +5 -0
- package/src/rewardsEligibility/index.ts +40 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import * as kit from '../../../src/rewardsEligibility';
|
|
3
|
+
|
|
4
|
+
describe('barrel rewardsEligibility incluye el backoffice', () => {
|
|
5
|
+
it.each([
|
|
6
|
+
'CampaignRequest', 'CampaignStatusRequest', 'CampaignResponse', 'CampaignListResponse', 'QuotaUsageResponse', 'CampaignSummaryResponse',
|
|
7
|
+
'EventTypeRequest', 'EventTypeResponse', 'EventTypeListResponse', 'EvaluationRequest', 'EvaluationStatusRequest', 'EvaluationResponse',
|
|
8
|
+
'EvaluationListResponse', 'ResultTraceResponse', 'TraceGroupResponse', 'TraceConditionResponse', 'SimulateRequest', 'SimulateResponse',
|
|
9
|
+
'RuleCatalogResponse', 'RuleCatalogSourceResponse', 'RuleCatalogFieldResponse', 'PopulationSourceResponse', 'InputTypeResponse',
|
|
10
|
+
'CreateRunRequest', 'PopulationRunRequest', 'ApproveRunRequest', 'QuotaImpactResponse', 'RunResponse', 'RunListResponse',
|
|
11
|
+
'RunResultResponse', 'RunResultListResponse', 'CreateRunResponse', 'MetricsPointResponse', 'FailedConditionStatResponse', 'MetricsQuery',
|
|
12
|
+
'MetricsDimensionEnum', 'RuleValueTypeEnum', 'ELIGIBILITY_ID_PATTERN', 'EVENT_KEY_PATTERN', 'REQUEST_ID_PATTERN', 'MAX_QUOTAS_PER_CAMPAIGN',
|
|
13
|
+
'RulesChatRoleEnum', 'RulesChatTurn', 'GenerateRulesRequest', 'GenerateRulesResponse', 'RULES_CHAT_TURN_MAX_LENGTH', 'RULES_CHAT_MAX_TURNS_HARD',
|
|
14
|
+
])('exporta %s', (name) => {
|
|
15
|
+
expect((kit as Record<string, object | string | number | RegExp>)[name]).toBeDefined();
|
|
16
|
+
});
|
|
17
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { plainToInstance } from 'class-transformer';
|
|
3
|
+
import { validate } from 'class-validator';
|
|
4
|
+
import { CampaignRequest } from '../../../src/rewardsEligibility/dtos/backoffice/CampaignRequest';
|
|
5
|
+
import { CampaignStatusRequest } from '../../../src/rewardsEligibility/dtos/backoffice/CampaignStatusRequest';
|
|
6
|
+
import { EventTypeRequest } from '../../../src/rewardsEligibility/dtos/backoffice/EventTypeRequest';
|
|
7
|
+
|
|
8
|
+
const parse = <T extends object>(cls: new () => T, value: object): T => plainToInstance(cls, value, { excludeExtraneousValues: true });
|
|
9
|
+
const valid = {
|
|
10
|
+
id: 'referidos-q4', name: 'Referidos Q4', objective: 'Que cada venta traiga una cuenta nueva.',
|
|
11
|
+
startsAt: '2026-10-15', endsAt: '2026-12-31',
|
|
12
|
+
quotas: [{ id: 'primeros-500', limit: 500, period: 'TOTAL' }, { id: 'semanal', limit: 100, period: 'WEEK' }],
|
|
13
|
+
onExhausted: 'PAUSE_CAMPAIGN', alerts: { thresholds: [0.8, 1] },
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
describe('CampaignRequest', () => {
|
|
17
|
+
it('un cuerpo válido pasa y conserva los cupos anidados', async () => {
|
|
18
|
+
const request = parse(CampaignRequest, { ...valid, hack: true });
|
|
19
|
+
expect(await validate(request)).toEqual([]);
|
|
20
|
+
expect(request.quotas).toHaveLength(2);
|
|
21
|
+
expect(request.quotas[0]).toMatchObject({ id: 'primeros-500', limit: 500, period: 'TOTAL' });
|
|
22
|
+
expect(Object.keys(request)).not.toContain('hack');
|
|
23
|
+
});
|
|
24
|
+
it.each([
|
|
25
|
+
['id con #', { ...valid, id: 'a#b' }],
|
|
26
|
+
['fecha mal formada', { ...valid, startsAt: '15/10/2026' }],
|
|
27
|
+
['cupo inválido anidado', { ...valid, quotas: [{ id: 'x', limit: 0, period: 'TOTAL' }] }],
|
|
28
|
+
['más de 9 cupos', { ...valid, quotas: Array.from({ length: 10 }, (_, i) => ({ id: `q${i}`, limit: 1, period: 'TOTAL' })) }],
|
|
29
|
+
['onExhausted desconocido', { ...valid, onExhausted: 'DELETE' }],
|
|
30
|
+
['sin alerts', { ...valid, alerts: undefined }],
|
|
31
|
+
])('rechaza: %s', async (_name, value) => {
|
|
32
|
+
expect((await validate(parse(CampaignRequest, value))).length).toBeGreaterThan(0);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe('CampaignStatusRequest / EventTypeRequest', () => {
|
|
37
|
+
it('status válido e inválido', async () => {
|
|
38
|
+
expect(await validate(parse(CampaignStatusRequest, { status: 'PAUSED' }))).toEqual([]);
|
|
39
|
+
expect((await validate(parse(CampaignStatusRequest, { status: 'BORRAR' }))).length).toBeGreaterThan(0);
|
|
40
|
+
});
|
|
41
|
+
it('un tipo de evento válido conserva sus fields (objetos sin clase) y rechaza eventKey en minúsculas', async () => {
|
|
42
|
+
const body = {
|
|
43
|
+
eventKey: 'PHONE_SALES_CODE_REDEEMED', name: 'Canje', description: 'd', emitter: 'phone-sales', status: 'ACTIVE',
|
|
44
|
+
fields: [{ key: 'saleId', type: 'ENTITY_REF', label: 'Venta', required: true }],
|
|
45
|
+
};
|
|
46
|
+
const ok = parse(EventTypeRequest, body);
|
|
47
|
+
expect(await validate(ok)).toEqual([]);
|
|
48
|
+
expect(ok.fields[0]).toMatchObject({ key: 'saleId', type: 'ENTITY_REF', label: 'Venta', required: true });
|
|
49
|
+
expect((await validate(parse(EventTypeRequest, { ...body, eventKey: 'phone' }))).length).toBeGreaterThan(0);
|
|
50
|
+
expect((await validate(parse(EventTypeRequest, { ...body, fields: 'x' }))).length).toBeGreaterThan(0);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { plainToInstance } from 'class-transformer';
|
|
3
|
+
import { validate } from 'class-validator';
|
|
4
|
+
import { CampaignAlerts } from '../../../src/rewardsEligibility/dtos/CampaignAlerts';
|
|
5
|
+
import { CampaignQuota } from '../../../src/rewardsEligibility/dtos/CampaignQuota';
|
|
6
|
+
import { MetricsDimensionEnum } from '../../../src/rewardsEligibility/enums/MetricsDimensionEnum';
|
|
7
|
+
import { RewardsEligibilityErrorCodeEnum } from '../../../src/rewardsEligibility/enums/RewardsEligibilityErrorCodeEnum';
|
|
8
|
+
import { ELIGIBILITY_ID_PATTERN, EVENT_KEY_PATTERN, MAX_QUOTAS_PER_CAMPAIGN } from '../../../src/rewardsEligibility/constants/BackofficeLimits';
|
|
9
|
+
|
|
10
|
+
const parse = <T extends object>(cls: new () => T, value: object): T => plainToInstance(cls, value, { excludeExtraneousValues: true });
|
|
11
|
+
|
|
12
|
+
describe('CampaignQuota / CampaignAlerts validables', () => {
|
|
13
|
+
it('un cupo válido pasa y descarta campos extra', async () => {
|
|
14
|
+
const quota = parse(CampaignQuota, { id: 'primeros-500', limit: 500, period: 'TOTAL', extra: 1 });
|
|
15
|
+
expect(await validate(quota)).toEqual([]);
|
|
16
|
+
expect(Object.keys(quota).sort()).toEqual(['id', 'limit', 'period']);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it.each([
|
|
20
|
+
[{ id: 'con#almohadilla', limit: 5, period: 'TOTAL' }],
|
|
21
|
+
[{ id: 'ok', limit: 0, period: 'TOTAL' }],
|
|
22
|
+
[{ id: 'ok', limit: 1.5, period: 'TOTAL' }],
|
|
23
|
+
[{ id: 'ok', limit: 5, period: 'YEAR' }],
|
|
24
|
+
])('un cupo inválido falla: %j', async (value) => {
|
|
25
|
+
expect((await validate(parse(CampaignQuota, value))).length).toBeGreaterThan(0);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('umbrales de alerta: entre 0 y 1, hasta 5', async () => {
|
|
29
|
+
expect(await validate(parse(CampaignAlerts, { thresholds: [0.8, 1] }))).toEqual([]);
|
|
30
|
+
expect((await validate(parse(CampaignAlerts, { thresholds: [1.5] }))).length).toBeGreaterThan(0);
|
|
31
|
+
expect((await validate(parse(CampaignAlerts, { thresholds: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6] }))).length).toBeGreaterThan(0);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
describe('constantes y enums del backoffice', () => {
|
|
36
|
+
it('patrones de id', () => {
|
|
37
|
+
expect(ELIGIBILITY_ID_PATTERN.test('referidos-q4')).toBe(true);
|
|
38
|
+
expect(ELIGIBILITY_ID_PATTERN.test('a#b')).toBe(false);
|
|
39
|
+
expect(ELIGIBILITY_ID_PATTERN.test('A:b')).toBe(false);
|
|
40
|
+
expect(EVENT_KEY_PATTERN.test('PHONE_SALES_CODE_REDEEMED')).toBe(true);
|
|
41
|
+
expect(EVENT_KEY_PATTERN.test('phone')).toBe(false);
|
|
42
|
+
expect(MAX_QUOTAS_PER_CAMPAIGN).toBe(9);
|
|
43
|
+
});
|
|
44
|
+
it('dimensiones y códigos', () => {
|
|
45
|
+
expect(Object.values(MetricsDimensionEnum)).toEqual(['CAMPAIGN', 'EVALUATION', 'PACKAGE', 'TRIGGER', 'ALL']);
|
|
46
|
+
expect(RewardsEligibilityErrorCodeEnum.EVALUATION_INVALID).toBe('EVALUATION_INVALID');
|
|
47
|
+
expect(RewardsEligibilityErrorCodeEnum.INPUT_INVALID).toBe('INPUT_INVALID');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { RuleValueTypeEnum } from '../../../src/rewardsEligibility/enums/RuleValueTypeEnum';
|
|
2
|
+
import { InputFieldTypeEnum } from '../../../src/dynamicForm/enums/InputFieldTypeEnum';
|
|
3
|
+
import type { RuleCatalogResponse } from '../../../src/rewardsEligibility/dtos/backoffice/RuleCatalogResponse';
|
|
4
|
+
import type { PopulationSourceResponse } from '../../../src/rewardsEligibility/dtos/backoffice/PopulationSourceResponse';
|
|
5
|
+
import type { InputTypeResponse } from '../../../src/rewardsEligibility/dtos/backoffice/InputTypeResponse';
|
|
6
|
+
|
|
7
|
+
describe('DTOs de catálogos (forma)', () => {
|
|
8
|
+
it('un catálogo de reglas se puede armar con la forma pública', () => {
|
|
9
|
+
const catalog: RuleCatalogResponse = {
|
|
10
|
+
sources: [{
|
|
11
|
+
source: 'directory', label: 'Directorio', description: 'Datos del usuario',
|
|
12
|
+
fields: [{ field: 'accountAgeDays', label: 'Antigüedad', valueType: RuleValueTypeEnum.NUMBER, operators: ['GT', 'LTE'] }],
|
|
13
|
+
}],
|
|
14
|
+
operators: { GT: '>', LTE: '≤' },
|
|
15
|
+
};
|
|
16
|
+
expect(catalog.sources[0]?.fields[0]?.valueType).toBe('NUMBER');
|
|
17
|
+
});
|
|
18
|
+
it('una fuente de población y un tipo de input', () => {
|
|
19
|
+
const source: PopulationSourceResponse = {
|
|
20
|
+
source: 'TX_ACTIVE_IN_WINDOW', label: 'Con transacciones', description: 'd',
|
|
21
|
+
paramsSchema: [{ key: 'window', type: InputFieldTypeEnum.TEXT, label: 'Ventana', required: true }], provides: ['directoryId'],
|
|
22
|
+
};
|
|
23
|
+
const type: InputTypeResponse = { type: InputFieldTypeEnum.DIRECTORY, label: 'Usuario' };
|
|
24
|
+
expect(source.provides).toEqual(['directoryId']);
|
|
25
|
+
expect(type.type).toBe('DIRECTORY');
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { plainToInstance } from 'class-transformer';
|
|
3
|
+
import { validate } from 'class-validator';
|
|
4
|
+
import { EvaluationRequest } from '../../../src/rewardsEligibility/dtos/backoffice/EvaluationRequest';
|
|
5
|
+
import { EvaluationStatusRequest } from '../../../src/rewardsEligibility/dtos/backoffice/EvaluationStatusRequest';
|
|
6
|
+
import { SimulateRequest } from '../../../src/rewardsEligibility/dtos/backoffice/SimulateRequest';
|
|
7
|
+
|
|
8
|
+
const parse = <T extends object>(cls: new () => T, value: object): T => plainToInstance(cls, value, { excludeExtraneousValues: true });
|
|
9
|
+
const evaluation = {
|
|
10
|
+
id: 'phone-sales-referido', campaignId: 'referidos-q4', name: 'Premio', description: 'd',
|
|
11
|
+
inputs: [{ key: 'buyerDirectoryId', type: 'DIRECTORY', label: 'Comprador', required: true }],
|
|
12
|
+
rules: { match: 'ALL', groups: [{ match: 'ALL', conditions: [{ source: 'directory', subject: 'buyerDirectoryId', field: 'accountAgeDays', op: 'LTE', value: 7 }] }] },
|
|
13
|
+
beneficiaryInput: 'buyerDirectoryId',
|
|
14
|
+
reward: { packageId: 'paquete-referido', inputs: { topup: { accountNumberMatchesOperator: { const: true } } } },
|
|
15
|
+
grantPolicy: { mode: 'ONCE' },
|
|
16
|
+
triggers: [{ type: 'MANUAL', approval: 'AUTO' }],
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
describe('EvaluationRequest', () => {
|
|
20
|
+
it('válida: conserva rules, reward, grantPolicy y triggers anidados (objetos sin clase)', async () => {
|
|
21
|
+
const request = parse(EvaluationRequest, { ...evaluation, extra: 1 });
|
|
22
|
+
expect(await validate(request)).toEqual([]);
|
|
23
|
+
expect(request.rules).toEqual(evaluation.rules);
|
|
24
|
+
expect(request.reward).toEqual(evaluation.reward);
|
|
25
|
+
expect(request.grantPolicy).toEqual({ mode: 'ONCE' });
|
|
26
|
+
expect(request.triggers).toEqual(evaluation.triggers);
|
|
27
|
+
expect(Object.keys(request)).not.toContain('extra');
|
|
28
|
+
});
|
|
29
|
+
it.each([
|
|
30
|
+
['id con :', { ...evaluation, id: 'a:b' }],
|
|
31
|
+
['inputs no es arreglo', { ...evaluation, inputs: {} }],
|
|
32
|
+
['rules no es objeto', { ...evaluation, rules: 'x' }],
|
|
33
|
+
['triggers vacío', { ...evaluation, triggers: [] }],
|
|
34
|
+
['sin beneficiaryInput', { ...evaluation, beneficiaryInput: '' }],
|
|
35
|
+
])('rechaza: %s', async (_name, value) => {
|
|
36
|
+
expect((await validate(parse(EvaluationRequest, value))).length).toBeGreaterThan(0);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe('EvaluationStatusRequest / SimulateRequest', () => {
|
|
41
|
+
it('status', async () => {
|
|
42
|
+
expect(await validate(parse(EvaluationStatusRequest, { status: 'ACTIVE' }))).toEqual([]);
|
|
43
|
+
expect((await validate(parse(EvaluationStatusRequest, { status: 'ENDED' }))).length).toBeGreaterThan(0);
|
|
44
|
+
});
|
|
45
|
+
it('simulate: evaluationId o borrador, con inputs', async () => {
|
|
46
|
+
expect(await validate(parse(SimulateRequest, { evaluationId: 'phone-sales-referido', inputs: { buyerDirectoryId: 'd-1' } }))).toEqual([]);
|
|
47
|
+
const draft = parse(SimulateRequest, { evaluation, inputs: { buyerDirectoryId: 'd-1' } });
|
|
48
|
+
expect(await validate(draft)).toEqual([]);
|
|
49
|
+
expect(draft.evaluation?.id).toBe('phone-sales-referido');
|
|
50
|
+
expect((await validate(parse(SimulateRequest, { evaluationId: 'x', inputs: { a: { nested: true } } }))).length).toBeGreaterThan(0);
|
|
51
|
+
expect((await validate(parse(SimulateRequest, { evaluationId: 'x' }))).length).toBeGreaterThan(0);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -75,9 +75,9 @@ describe('enums de rewardsEligibility (valores que viajan por HTTP)', () => {
|
|
|
75
75
|
);
|
|
76
76
|
expect(Object.values(RunModeEnum).sort()).toEqual(['LIVE', 'SIMULATION']);
|
|
77
77
|
expect(Object.values(TriggerTypeEnum).sort()).toEqual(['CRON', 'EVENT', 'MANUAL']);
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
);
|
|
78
|
+
const codes = Object.values(RewardsEligibilityErrorCodeEnum);
|
|
79
|
+
expect(codes).toEqual(expect.arrayContaining(['EVENT_TYPE_NOT_FOUND', 'INPUT_INVALID', 'RUN_NOT_FOUND']));
|
|
80
|
+
expect(codes).toHaveLength(35);
|
|
81
81
|
});
|
|
82
82
|
});
|
|
83
83
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { plainToInstance } from 'class-transformer';
|
|
3
|
+
import { validate } from 'class-validator';
|
|
4
|
+
import { InputFieldTypeEnum } from '../../../src/dynamicForm/enums/InputFieldTypeEnum';
|
|
5
|
+
import { GenerateRulesRequest } from '../../../src/rewardsEligibility/dtos/backoffice/GenerateRulesRequest';
|
|
6
|
+
|
|
7
|
+
const parse = async (body: object) => {
|
|
8
|
+
const value = plainToInstance(GenerateRulesRequest, body, { excludeExtraneousValues: true });
|
|
9
|
+
return { value, errors: await validate(value) };
|
|
10
|
+
};
|
|
11
|
+
const input = { key: 'buyerDirectoryId', type: InputFieldTypeEnum.DIRECTORY, label: 'Comprador', required: true };
|
|
12
|
+
const turn = (content: string, role = 'user') => ({ role, content });
|
|
13
|
+
const valid = { history: [turn('cuentas de menos de 7 días')], inputs: [input] };
|
|
14
|
+
|
|
15
|
+
describe('GenerateRulesRequest', () => {
|
|
16
|
+
it('acepta un chat con reglas actuales y el contrato de entrada', async () => {
|
|
17
|
+
const { errors, value } = await parse({ ...valid, currentRules: { match: 'ALL', groups: [] } });
|
|
18
|
+
expect(errors).toEqual([]);
|
|
19
|
+
expect(value.history[0]?.content).toBe('cuentas de menos de 7 días');
|
|
20
|
+
expect(value.currentRules).toEqual({ match: 'ALL', groups: [] });
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('acepta historial vacío y contrato vacío (el lambda decide con AI_CHAT_HISTORY_EMPTY)', async () => {
|
|
24
|
+
expect((await parse({ history: [], inputs: [] })).errors).toEqual([]);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('rechaza un rol inventado', async () => {
|
|
28
|
+
expect((await parse({ ...valid, history: [turn('hola', 'system')] })).errors.length).toBeGreaterThan(0);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('rechaza un turno vacío y uno de más de 4000 caracteres', async () => {
|
|
32
|
+
expect((await parse({ ...valid, history: [turn('')] })).errors.length).toBeGreaterThan(0);
|
|
33
|
+
expect((await parse({ ...valid, history: [turn('x'.repeat(4001))] })).errors.length).toBeGreaterThan(0);
|
|
34
|
+
expect((await parse({ ...valid, history: [turn('x'.repeat(4000))] })).errors).toEqual([]);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('rechaza más de 50 turnos (tope de seguridad del DTO)', async () => {
|
|
38
|
+
expect((await parse({ ...valid, history: Array.from({ length: 51 }, () => turn('a')) })).errors.length).toBeGreaterThan(0);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('rechaza inputs que no es un arreglo y currentRules que no es un objeto', async () => {
|
|
42
|
+
expect((await parse({ ...valid, inputs: 'x' })).errors.length).toBeGreaterThan(0);
|
|
43
|
+
expect((await parse({ ...valid, currentRules: 'x' })).errors.length).toBeGreaterThan(0);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('descarta propiedades que no son del contrato', async () => {
|
|
47
|
+
const { value } = await parse({ ...valid, hack: true });
|
|
48
|
+
expect('hack' in value).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { GenerateRulesResponse } from '../../../src/rewardsEligibility/dtos/backoffice/GenerateRulesResponse';
|
|
2
|
+
|
|
3
|
+
describe('GenerateRulesResponse (forma pública)', () => {
|
|
4
|
+
it('las tres salidas posibles del chat se pueden armar con la forma pública', () => {
|
|
5
|
+
const ready: GenerateRulesResponse = { explanation: 'Cuentas de hasta 7 días.', rules: { match: 'ALL', groups: [] }, valid: true };
|
|
6
|
+
const question: GenerateRulesResponse = { explanation: '¿A qué grupo te refieres?', valid: true };
|
|
7
|
+
const failed: GenerateRulesResponse = { explanation: 'No pude.', valid: false, problems: ['rules.groups[0].conditions[0].field: campo desconocido'] };
|
|
8
|
+
expect(ready.rules).toBeDefined();
|
|
9
|
+
expect(question.rules).toBeUndefined();
|
|
10
|
+
expect(failed.problems).toHaveLength(1);
|
|
11
|
+
});
|
|
12
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { MetricsDimensionEnum } from '../../../src/rewardsEligibility/enums/MetricsDimensionEnum';
|
|
2
|
+
import type { FailedConditionStatResponse } from '../../../src/rewardsEligibility/dtos/backoffice/FailedConditionStatResponse';
|
|
3
|
+
import type { MetricsPointResponse } from '../../../src/rewardsEligibility/dtos/backoffice/MetricsPointResponse';
|
|
4
|
+
import type { MetricsQuery } from '../../../src/rewardsEligibility/dtos/backoffice/MetricsQuery';
|
|
5
|
+
|
|
6
|
+
describe('DTOs de métricas (forma)', () => {
|
|
7
|
+
it('un punto diario trae los 9 contadores del spec 5.7', () => {
|
|
8
|
+
const point: MetricsPointResponse = { date: '2026-10-08', evaluated: 3, match: 2, noMatch: 1, error: 0, alreadyGranted: 0, quotaExhausted: 0, excluded: 0, requested: 2, requestFailed: 0 };
|
|
9
|
+
expect(Object.keys(point)).toHaveLength(10);
|
|
10
|
+
});
|
|
11
|
+
it('ranking y query', () => {
|
|
12
|
+
const stat: FailedConditionStatResponse = { key: 'directory.accountAgeDays', label: 'Antigüedad de la cuenta', count: 7 };
|
|
13
|
+
const query: MetricsQuery = { dimension: MetricsDimensionEnum.CAMPAIGN, value: 'referidos-q4', from: '2026-10-01', to: '2026-10-08' };
|
|
14
|
+
expect(stat.count).toBe(7);
|
|
15
|
+
expect(query.dimension).toBe('CAMPAIGN');
|
|
16
|
+
});
|
|
17
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { RuleValueTypeEnum } from '../../../src/rewardsEligibility/enums/RuleValueTypeEnum';
|
|
2
|
+
import type { RuleCatalogFieldResponse } from '../../../src/rewardsEligibility/dtos/backoffice/RuleCatalogResponse';
|
|
3
|
+
|
|
4
|
+
describe('RuleCatalogFieldResponse enriquecido', () => {
|
|
5
|
+
it('un campo puede traer descripción, frases de ejemplo y descripción por opción', () => {
|
|
6
|
+
const field: RuleCatalogFieldResponse = {
|
|
7
|
+
field: 'status', label: 'Estado de la cuenta', valueType: RuleValueTypeEnum.STRING, operators: ['EQUALS'],
|
|
8
|
+
description: 'Estado operativo del directorio del usuario.',
|
|
9
|
+
examplePhrases: ['usuarios activos'],
|
|
10
|
+
options: [{ value: 'ACTIVE', label: 'ACTIVE', description: 'cuenta operativa' }],
|
|
11
|
+
};
|
|
12
|
+
expect(field.options?.[0]?.description).toBe('cuenta operativa');
|
|
13
|
+
});
|
|
14
|
+
it('sigue siendo válido sin los campos nuevos', () => {
|
|
15
|
+
const field: RuleCatalogFieldResponse = { field: 'x', label: 'x', valueType: RuleValueTypeEnum.NUMBER, operators: ['GT'] };
|
|
16
|
+
expect(field.description).toBeUndefined();
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { RewardsEligibilityErrorCodeEnum } from '../../../src/rewardsEligibility/enums/RewardsEligibilityErrorCodeEnum';
|
|
2
|
+
import { RulesChatRoleEnum } from '../../../src/rewardsEligibility/enums/RulesChatRoleEnum';
|
|
3
|
+
|
|
4
|
+
describe('enums de la generación de reglas con IA', () => {
|
|
5
|
+
it('los roles del chat son user y assistant (los mismos del prompt de benefits)', () => {
|
|
6
|
+
expect(Object.values(RulesChatRoleEnum)).toEqual(['user', 'assistant']);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it.each(['AI_CHAT_HISTORY_EMPTY', 'AI_CHAT_HISTORY_TOO_LONG', 'AI_GENERATION_FAILED', 'AI_RESPONSE_UNPARSEABLE', 'AI_GENERATION_TIMEOUT'] as const)(
|
|
10
|
+
'el código %s existe y su valor es su nombre',
|
|
11
|
+
(code) => {
|
|
12
|
+
expect(RewardsEligibilityErrorCodeEnum[code]).toBe(code);
|
|
13
|
+
},
|
|
14
|
+
);
|
|
15
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { plainToInstance } from 'class-transformer';
|
|
3
|
+
import { validate } from 'class-validator';
|
|
4
|
+
import { ApproveRunRequest } from '../../../src/rewardsEligibility/dtos/backoffice/ApproveRunRequest';
|
|
5
|
+
import { CreateRunRequest } from '../../../src/rewardsEligibility/dtos/backoffice/CreateRunRequest';
|
|
6
|
+
|
|
7
|
+
const parse = <T extends object>(cls: new () => T, value: object): T => plainToInstance(cls, value, { excludeExtraneousValues: true });
|
|
8
|
+
|
|
9
|
+
describe('CreateRunRequest', () => {
|
|
10
|
+
it('un sujeto: requestId, mode e inputs', async () => {
|
|
11
|
+
const request = parse(CreateRunRequest, { requestId: 'req-12345678', mode: 'LIVE', inputs: { buyerDirectoryId: 'd-1' }, x: 1 });
|
|
12
|
+
expect(await validate(request)).toEqual([]);
|
|
13
|
+
expect(request.inputs).toEqual({ buyerDirectoryId: 'd-1' });
|
|
14
|
+
});
|
|
15
|
+
it('población: params anidados se conservan', async () => {
|
|
16
|
+
const request = parse(CreateRunRequest, { requestId: 'req-12345678', mode: 'SIMULATION', population: { params: { window: '7d' } } });
|
|
17
|
+
expect(await validate(request)).toEqual([]);
|
|
18
|
+
expect(request.population?.params).toEqual({ window: '7d' });
|
|
19
|
+
});
|
|
20
|
+
it.each([
|
|
21
|
+
['requestId corto', { requestId: 'a', mode: 'LIVE', inputs: {} }],
|
|
22
|
+
['mode desconocido', { requestId: 'req-12345678', mode: 'DRY', inputs: {} }],
|
|
23
|
+
['inputs con objeto anidado', { requestId: 'req-12345678', mode: 'LIVE', inputs: { a: { b: { c: 1 } } } }],
|
|
24
|
+
])('rechaza: %s', async (_name, value) => {
|
|
25
|
+
expect((await validate(parse(CreateRunRequest, value))).length).toBeGreaterThan(0);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe('ApproveRunRequest', () => {
|
|
30
|
+
it('excludeSubjectKeys es opcional y acotado', async () => {
|
|
31
|
+
expect(await validate(parse(ApproveRunRequest, {}))).toEqual([]);
|
|
32
|
+
expect(await validate(parse(ApproveRunRequest, { excludeSubjectKeys: ['a1b2c3d4e5f60718'] }))).toEqual([]);
|
|
33
|
+
expect((await validate(parse(ApproveRunRequest, { excludeSubjectKeys: [5] }))).length).toBeGreaterThan(0);
|
|
34
|
+
expect((await validate(parse(ApproveRunRequest, { excludeSubjectKeys: Array.from({ length: 1001 }, () => 'a1b2c3d4e5f60718') }))).length).toBeGreaterThan(0);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Id de campaña, evaluación (minúsculas, dígitos y guion; 2 a 64; sin `#` ni `:` porque entran en llaves compuestas y en la idempotencyKey). */
|
|
2
|
+
export declare const ELIGIBILITY_ID_PATTERN: RegExp;
|
|
3
|
+
/** `eventKey` de un tipo de evento: MAYÚSCULAS con guion bajo (ej. `PHONE_SALES_CODE_REDEEMED`). */
|
|
4
|
+
export declare const EVENT_KEY_PATTERN: RegExp;
|
|
5
|
+
/** Fecha de vigencia de una campaña (UTC, inclusiva). */
|
|
6
|
+
export declare const DATE_PATTERN: RegExp;
|
|
7
|
+
/** Id de solicitud que genera el backoffice al abrir el formulario de una corrida manual (llave de idempotencia). */
|
|
8
|
+
export declare const REQUEST_ID_PATTERN: RegExp;
|
|
9
|
+
/** Cupos por campaña que caben junto a las reservas de una transacción (100 − 90 − registro del lote). */
|
|
10
|
+
export declare const MAX_QUOTAS_PER_CAMPAIGN = 9;
|
|
11
|
+
/** Tope de `limit` de los listados paginados. */
|
|
12
|
+
export declare const LIST_PAGE_MAX = 100;
|
|
13
|
+
/** Largo máximo del texto de un turno del chat que genera reglas. */
|
|
14
|
+
export declare const RULES_CHAT_TURN_MAX_LENGTH = 4000;
|
|
15
|
+
/** Tope de seguridad de turnos que acepta el DTO (el límite funcional, 10, lo aplica el lambda con `AI_CHAT_HISTORY_TOO_LONG`). */
|
|
16
|
+
export declare const RULES_CHAT_MAX_TURNS_HARD = 50;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RULES_CHAT_MAX_TURNS_HARD = exports.RULES_CHAT_TURN_MAX_LENGTH = exports.LIST_PAGE_MAX = exports.MAX_QUOTAS_PER_CAMPAIGN = exports.REQUEST_ID_PATTERN = exports.DATE_PATTERN = exports.EVENT_KEY_PATTERN = exports.ELIGIBILITY_ID_PATTERN = void 0;
|
|
4
|
+
/** Id de campaña, evaluación (minúsculas, dígitos y guion; 2 a 64; sin `#` ni `:` porque entran en llaves compuestas y en la idempotencyKey). */
|
|
5
|
+
exports.ELIGIBILITY_ID_PATTERN = /^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$/;
|
|
6
|
+
/** `eventKey` de un tipo de evento: MAYÚSCULAS con guion bajo (ej. `PHONE_SALES_CODE_REDEEMED`). */
|
|
7
|
+
exports.EVENT_KEY_PATTERN = /^[A-Z][A-Z0-9_]{2,63}$/;
|
|
8
|
+
/** Fecha de vigencia de una campaña (UTC, inclusiva). */
|
|
9
|
+
exports.DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
10
|
+
/** Id de solicitud que genera el backoffice al abrir el formulario de una corrida manual (llave de idempotencia). */
|
|
11
|
+
exports.REQUEST_ID_PATTERN = /^[A-Za-z0-9_-]{8,64}$/;
|
|
12
|
+
/** Cupos por campaña que caben junto a las reservas de una transacción (100 − 90 − registro del lote). */
|
|
13
|
+
exports.MAX_QUOTAS_PER_CAMPAIGN = 9;
|
|
14
|
+
/** Tope de `limit` de los listados paginados. */
|
|
15
|
+
exports.LIST_PAGE_MAX = 100;
|
|
16
|
+
/** Largo máximo del texto de un turno del chat que genera reglas. */
|
|
17
|
+
exports.RULES_CHAT_TURN_MAX_LENGTH = 4000;
|
|
18
|
+
/** Tope de seguridad de turnos que acepta el DTO (el límite funcional, 10, lo aplica el lambda con `AI_CHAT_HISTORY_TOO_LONG`). */
|
|
19
|
+
exports.RULES_CHAT_MAX_TURNS_HARD = 50;
|
|
@@ -1,7 +1,27 @@
|
|
|
1
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
|
+
};
|
|
2
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
12
|
exports.CampaignAlerts = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
4
15
|
/** Umbrales de consumo (0 a 1) que avisan a los operadores (spec B 5.6). */
|
|
5
16
|
class CampaignAlerts {
|
|
6
17
|
}
|
|
7
18
|
exports.CampaignAlerts = CampaignAlerts;
|
|
19
|
+
__decorate([
|
|
20
|
+
(0, class_transformer_1.Expose)(),
|
|
21
|
+
(0, class_validator_1.IsArray)(),
|
|
22
|
+
(0, class_validator_1.ArrayMaxSize)(5),
|
|
23
|
+
(0, class_validator_1.IsNumber)({}, { each: true }),
|
|
24
|
+
(0, class_validator_1.Min)(0.01, { each: true }),
|
|
25
|
+
(0, class_validator_1.Max)(1, { each: true }),
|
|
26
|
+
__metadata("design:type", Array)
|
|
27
|
+
], CampaignAlerts.prototype, "thresholds", void 0);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { QuotaPeriodEnum } from '../enums/QuotaPeriodEnum';
|
|
2
2
|
/** Un cupo de campania: cantidad maxima de premios (no dinero) en un periodo (spec B 5.6). */
|
|
3
3
|
export declare class CampaignQuota {
|
|
4
|
-
/** Unico dentro de la campania (ej. `primeros-500`). Entra en la llave del consumo (`{id}#{periodo}`)
|
|
4
|
+
/** Unico dentro de la campania (ej. `primeros-500`). Entra en la llave del consumo (`{id}#{periodo}`): sin `#`. */
|
|
5
5
|
id: string;
|
|
6
6
|
limit: number;
|
|
7
7
|
period: QuotaPeriodEnum;
|
|
@@ -1,7 +1,36 @@
|
|
|
1
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
|
+
};
|
|
2
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
12
|
exports.CampaignQuota = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
const QuotaPeriodEnum_1 = require("../enums/QuotaPeriodEnum");
|
|
4
16
|
/** Un cupo de campania: cantidad maxima de premios (no dinero) en un periodo (spec B 5.6). */
|
|
5
17
|
class CampaignQuota {
|
|
6
18
|
}
|
|
7
19
|
exports.CampaignQuota = CampaignQuota;
|
|
20
|
+
__decorate([
|
|
21
|
+
(0, class_transformer_1.Expose)(),
|
|
22
|
+
(0, class_validator_1.IsString)(),
|
|
23
|
+
(0, class_validator_1.Matches)(/^[a-z0-9][a-z0-9-]{0,62}$/),
|
|
24
|
+
__metadata("design:type", String)
|
|
25
|
+
], CampaignQuota.prototype, "id", void 0);
|
|
26
|
+
__decorate([
|
|
27
|
+
(0, class_transformer_1.Expose)(),
|
|
28
|
+
(0, class_validator_1.IsInt)(),
|
|
29
|
+
(0, class_validator_1.Min)(1),
|
|
30
|
+
__metadata("design:type", Number)
|
|
31
|
+
], CampaignQuota.prototype, "limit", void 0);
|
|
32
|
+
__decorate([
|
|
33
|
+
(0, class_transformer_1.Expose)(),
|
|
34
|
+
(0, class_validator_1.IsEnum)(QuotaPeriodEnum_1.QuotaPeriodEnum),
|
|
35
|
+
__metadata("design:type", String)
|
|
36
|
+
], CampaignQuota.prototype, "period", void 0);
|
|
@@ -0,0 +1,27 @@
|
|
|
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.ApproveRunRequest = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
/** `POST /runs/{id}/approve`: aprueba todo salvo los sujetos excluidos (`subjectKey`). */
|
|
16
|
+
class ApproveRunRequest {
|
|
17
|
+
}
|
|
18
|
+
exports.ApproveRunRequest = ApproveRunRequest;
|
|
19
|
+
__decorate([
|
|
20
|
+
(0, class_transformer_1.Expose)(),
|
|
21
|
+
(0, class_validator_1.IsOptional)(),
|
|
22
|
+
(0, class_validator_1.IsArray)(),
|
|
23
|
+
(0, class_validator_1.ArrayMaxSize)(1000),
|
|
24
|
+
(0, class_validator_1.IsString)({ each: true }),
|
|
25
|
+
(0, class_validator_1.Matches)(/^[A-Za-z0-9_-]{8,128}$/, { each: true }),
|
|
26
|
+
__metadata("design:type", Array)
|
|
27
|
+
], ApproveRunRequest.prototype, "excludeSubjectKeys", void 0);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { QuotaExhaustedActionEnum } from '../../enums/QuotaExhaustedActionEnum';
|
|
2
|
+
import { CampaignAlerts } from '../CampaignAlerts';
|
|
3
|
+
import { CampaignQuota } from '../CampaignQuota';
|
|
4
|
+
/** Crear (POST) o reemplazar (PUT) una campaña. `status`, `pausedReason` y las fechas de auditoría las pone el servidor (el estado cambia con `POST /campaigns/{id}/status`). */
|
|
5
|
+
export declare class CampaignRequest {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
/** Qué se quiere lograr (texto libre). */
|
|
9
|
+
objective: string;
|
|
10
|
+
/** `AAAA-MM-DD` (UTC, inclusiva). */
|
|
11
|
+
startsAt: string;
|
|
12
|
+
endsAt: string;
|
|
13
|
+
quotas: CampaignQuota[];
|
|
14
|
+
onExhausted: QuotaExhaustedActionEnum;
|
|
15
|
+
alerts: CampaignAlerts;
|
|
16
|
+
}
|