@fiado/type-kit 3.516.0 → 3.517.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 +16 -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/metricsDtos.test.ts +17 -0
- package/_test_/unit/rewardsEligibility/runDtos.test.ts +36 -0
- package/bin/rewardsEligibility/constants/BackofficeLimits.d.ts +12 -0
- package/bin/rewardsEligibility/constants/BackofficeLimits.js +15 -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/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 +28 -0
- package/bin/rewardsEligibility/dtos/backoffice/RuleCatalogResponse.js +13 -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 +46 -1
- package/bin/rewardsEligibility/enums/RewardsEligibilityErrorCodeEnum.js +46 -0
- package/bin/rewardsEligibility/enums/RuleValueTypeEnum.d.ts +9 -0
- package/bin/rewardsEligibility/enums/RuleValueTypeEnum.js +13 -0
- package/bin/rewardsEligibility/index.d.ts +34 -0
- package/bin/rewardsEligibility/index.js +35 -0
- package/package.json +1 -1
- package/src/rewardsEligibility/constants/BackofficeLimits.ts +12 -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/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 +28 -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 +47 -0
- package/src/rewardsEligibility/enums/RuleValueTypeEnum.ts +9 -0
- package/src/rewardsEligibility/index.ts +36 -0
|
@@ -0,0 +1,16 @@
|
|
|
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
|
+
])('exporta %s', (name) => {
|
|
14
|
+
expect((kit as Record<string, object | string | number | RegExp>)[name]).toBeDefined();
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -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(30);
|
|
81
81
|
});
|
|
82
82
|
});
|
|
83
83
|
|
|
@@ -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,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,12 @@
|
|
|
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;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
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;
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
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.CampaignRequest = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
const BackofficeLimits_1 = require("../../constants/BackofficeLimits");
|
|
16
|
+
const QuotaExhaustedActionEnum_1 = require("../../enums/QuotaExhaustedActionEnum");
|
|
17
|
+
const CampaignAlerts_1 = require("../CampaignAlerts");
|
|
18
|
+
const CampaignQuota_1 = require("../CampaignQuota");
|
|
19
|
+
/** 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`). */
|
|
20
|
+
class CampaignRequest {
|
|
21
|
+
}
|
|
22
|
+
exports.CampaignRequest = CampaignRequest;
|
|
23
|
+
__decorate([
|
|
24
|
+
(0, class_transformer_1.Expose)(),
|
|
25
|
+
(0, class_validator_1.IsString)(),
|
|
26
|
+
(0, class_validator_1.Matches)(BackofficeLimits_1.ELIGIBILITY_ID_PATTERN),
|
|
27
|
+
__metadata("design:type", String)
|
|
28
|
+
], CampaignRequest.prototype, "id", void 0);
|
|
29
|
+
__decorate([
|
|
30
|
+
(0, class_transformer_1.Expose)(),
|
|
31
|
+
(0, class_validator_1.IsString)(),
|
|
32
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
33
|
+
(0, class_validator_1.MaxLength)(120),
|
|
34
|
+
__metadata("design:type", String)
|
|
35
|
+
], CampaignRequest.prototype, "name", void 0);
|
|
36
|
+
__decorate([
|
|
37
|
+
(0, class_transformer_1.Expose)(),
|
|
38
|
+
(0, class_validator_1.IsString)(),
|
|
39
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
40
|
+
(0, class_validator_1.MaxLength)(500),
|
|
41
|
+
__metadata("design:type", String)
|
|
42
|
+
], CampaignRequest.prototype, "objective", void 0);
|
|
43
|
+
__decorate([
|
|
44
|
+
(0, class_transformer_1.Expose)(),
|
|
45
|
+
(0, class_validator_1.Matches)(BackofficeLimits_1.DATE_PATTERN),
|
|
46
|
+
__metadata("design:type", String)
|
|
47
|
+
], CampaignRequest.prototype, "startsAt", void 0);
|
|
48
|
+
__decorate([
|
|
49
|
+
(0, class_transformer_1.Expose)(),
|
|
50
|
+
(0, class_validator_1.Matches)(BackofficeLimits_1.DATE_PATTERN),
|
|
51
|
+
__metadata("design:type", String)
|
|
52
|
+
], CampaignRequest.prototype, "endsAt", void 0);
|
|
53
|
+
__decorate([
|
|
54
|
+
(0, class_transformer_1.Expose)(),
|
|
55
|
+
(0, class_validator_1.IsArray)(),
|
|
56
|
+
(0, class_validator_1.ArrayMaxSize)(BackofficeLimits_1.MAX_QUOTAS_PER_CAMPAIGN),
|
|
57
|
+
(0, class_validator_1.ValidateNested)({ each: true }),
|
|
58
|
+
(0, class_transformer_1.Type)(() => CampaignQuota_1.CampaignQuota),
|
|
59
|
+
__metadata("design:type", Array)
|
|
60
|
+
], CampaignRequest.prototype, "quotas", void 0);
|
|
61
|
+
__decorate([
|
|
62
|
+
(0, class_transformer_1.Expose)(),
|
|
63
|
+
(0, class_validator_1.IsEnum)(QuotaExhaustedActionEnum_1.QuotaExhaustedActionEnum),
|
|
64
|
+
__metadata("design:type", String)
|
|
65
|
+
], CampaignRequest.prototype, "onExhausted", void 0);
|
|
66
|
+
__decorate([
|
|
67
|
+
(0, class_transformer_1.Expose)(),
|
|
68
|
+
(0, class_validator_1.IsDefined)(),
|
|
69
|
+
(0, class_validator_1.ValidateNested)(),
|
|
70
|
+
(0, class_transformer_1.Type)(() => CampaignAlerts_1.CampaignAlerts),
|
|
71
|
+
__metadata("design:type", CampaignAlerts_1.CampaignAlerts)
|
|
72
|
+
], CampaignRequest.prototype, "alerts", void 0);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CampaignPausedReasonEnum } from '../../enums/CampaignPausedReasonEnum';
|
|
2
|
+
import { CampaignStatusEnum } from '../../enums/CampaignStatusEnum';
|
|
3
|
+
import { QuotaExhaustedActionEnum } from '../../enums/QuotaExhaustedActionEnum';
|
|
4
|
+
import { CampaignAlerts } from '../CampaignAlerts';
|
|
5
|
+
import { CampaignQuota } from '../CampaignQuota';
|
|
6
|
+
/** Una campaña (spec B 5.6). */
|
|
7
|
+
export declare class CampaignResponse {
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
objective: string;
|
|
11
|
+
status: CampaignStatusEnum;
|
|
12
|
+
/** Solo si `status` es `PAUSED`. */
|
|
13
|
+
pausedReason?: CampaignPausedReasonEnum;
|
|
14
|
+
startsAt: string;
|
|
15
|
+
endsAt: string;
|
|
16
|
+
quotas: CampaignQuota[];
|
|
17
|
+
onExhausted: QuotaExhaustedActionEnum;
|
|
18
|
+
alerts: CampaignAlerts;
|
|
19
|
+
/** Epoch en milisegundos. */
|
|
20
|
+
createdAt: number;
|
|
21
|
+
updatedAt: number;
|
|
22
|
+
updatedBy: string;
|
|
23
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
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.CampaignStatusRequest = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
const CampaignStatusEnum_1 = require("../../enums/CampaignStatusEnum");
|
|
16
|
+
/** Cuerpo de `POST /campaigns/{id}/status`: activar, pausar, terminar o archivar. */
|
|
17
|
+
class CampaignStatusRequest {
|
|
18
|
+
}
|
|
19
|
+
exports.CampaignStatusRequest = CampaignStatusRequest;
|
|
20
|
+
__decorate([
|
|
21
|
+
(0, class_transformer_1.Expose)(),
|
|
22
|
+
(0, class_validator_1.IsEnum)(CampaignStatusEnum_1.CampaignStatusEnum),
|
|
23
|
+
__metadata("design:type", String)
|
|
24
|
+
], CampaignStatusRequest.prototype, "status", void 0);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { CampaignPausedReasonEnum } from '../../enums/CampaignPausedReasonEnum';
|
|
2
|
+
import { CampaignStatusEnum } from '../../enums/CampaignStatusEnum';
|
|
3
|
+
/** Fila de la tabla ejecutiva `GET /campaigns/summary` (spec 10.1). */
|
|
4
|
+
export declare class CampaignSummaryResponse {
|
|
5
|
+
campaignId: string;
|
|
6
|
+
name: string;
|
|
7
|
+
status: CampaignStatusEnum;
|
|
8
|
+
pausedReason?: CampaignPausedReasonEnum;
|
|
9
|
+
startsAt: string;
|
|
10
|
+
endsAt: string;
|
|
11
|
+
evaluated: number;
|
|
12
|
+
matched: number;
|
|
13
|
+
requested: number;
|
|
14
|
+
quotaExhausted: number;
|
|
15
|
+
/** Cupo más restrictivo, de 0 a 1 (0 si la campaña no tiene cupos). */
|
|
16
|
+
quotaUsed: number;
|
|
17
|
+
/** Ritmo diario de pedidos de los últimos 7 días (para proyectar el agotamiento). */
|
|
18
|
+
dailyRate: number;
|
|
19
|
+
/** `AAAA-MM-DD` estimada en que se agota el cupo más restrictivo al ritmo actual; ausente si no aplica. */
|
|
20
|
+
projectedExhaustionDate?: string;
|
|
21
|
+
/** Valor entregado: lo calcula rewards por `campaignId`; este lambda no lo informa. */
|
|
22
|
+
value?: {
|
|
23
|
+
amount: number;
|
|
24
|
+
currency: string;
|
|
25
|
+
}[];
|
|
26
|
+
/** Entregados de verdad según rewards; este lambda no lo informa. */
|
|
27
|
+
granted?: number;
|
|
28
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CampaignSummaryResponse = void 0;
|
|
4
|
+
/** Fila de la tabla ejecutiva `GET /campaigns/summary` (spec 10.1). */
|
|
5
|
+
class CampaignSummaryResponse {
|
|
6
|
+
}
|
|
7
|
+
exports.CampaignSummaryResponse = CampaignSummaryResponse;
|