@fiado/type-kit 3.411.0 → 3.413.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/loanCredit/dtos/listMessagingCandidates.test.ts +97 -0
- package/_test_/unit/mdm/dtos/mdmDeviceContract.test.ts +21 -0
- package/_test_/unit/messagesConnector/mdmNotifyContract.test.ts +162 -0
- package/_test_/unit/messagesConnector/messagingEnums.test.ts +37 -0
- package/bin/loanCredit/constants/MessagingCandidateLimits.d.ts +4 -0
- package/bin/loanCredit/constants/MessagingCandidateLimits.js +7 -0
- package/bin/loanCredit/constants/StoreDayPattern.d.ts +3 -0
- package/bin/loanCredit/constants/StoreDayPattern.js +6 -0
- package/bin/loanCredit/dtos/MessagingCandidateItem.d.ts +31 -0
- package/bin/loanCredit/dtos/MessagingCandidateItem.js +10 -0
- package/bin/loanCredit/dtos/requests/ListMessagingCandidatesRequest.d.ts +11 -0
- package/bin/loanCredit/dtos/requests/ListMessagingCandidatesRequest.js +47 -0
- package/bin/loanCredit/dtos/responses/ListMessagingCandidatesResponse.d.ts +7 -0
- package/bin/loanCredit/dtos/responses/ListMessagingCandidatesResponse.js +7 -0
- package/bin/loanCredit/index.d.ts +6 -0
- package/bin/loanCredit/index.js +10 -1
- package/bin/mdm/dtos/DeviceNotifyRequest.js +3 -0
- package/bin/messagesConnector/constants/MdmNotifyBatchLimits.d.ts +5 -0
- package/bin/messagesConnector/constants/MdmNotifyBatchLimits.js +9 -0
- package/bin/messagesConnector/dtos/MdmNotifyBatchResponse.d.ts +5 -0
- package/bin/messagesConnector/dtos/MdmNotifyBatchResponse.js +7 -0
- package/bin/messagesConnector/dtos/MdmNotifyItem.d.ts +22 -0
- package/bin/messagesConnector/dtos/MdmNotifyItem.js +65 -0
- package/bin/messagesConnector/dtos/MdmNotifyRequest.d.ts +10 -0
- package/bin/messagesConnector/dtos/MdmNotifyRequest.js +44 -0
- package/bin/messagesConnector/dtos/MdmNotifyResponse.d.ts +11 -0
- package/bin/messagesConnector/dtos/MdmNotifyResponse.js +7 -0
- package/bin/messagesConnector/enums/DeliveryChannelExtendedEnum.d.ts +3 -1
- package/bin/messagesConnector/enums/DeliveryChannelExtendedEnum.js +2 -0
- package/bin/messagesConnector/enums/MessagingSlotEnum.d.ts +9 -0
- package/bin/messagesConnector/enums/MessagingSlotEnum.js +13 -0
- package/bin/messagesConnector/index.d.ts +6 -0
- package/bin/messagesConnector/index.js +6 -0
- package/package.json +1 -1
- package/src/loanCredit/constants/MessagingCandidateLimits.ts +5 -0
- package/src/loanCredit/constants/StoreDayPattern.ts +4 -0
- package/src/loanCredit/dtos/MessagingCandidateItem.ts +40 -0
- package/src/loanCredit/dtos/requests/ListMessagingCandidatesRequest.ts +33 -0
- package/src/loanCredit/dtos/responses/ListMessagingCandidatesResponse.ts +9 -0
- package/src/loanCredit/index.ts +10 -0
- package/src/mdm/dtos/DeviceNotifyRequest.ts +4 -1
- package/src/messagesConnector/constants/MdmNotifyBatchLimits.ts +7 -0
- package/src/messagesConnector/dtos/MdmNotifyBatchResponse.ts +6 -0
- package/src/messagesConnector/dtos/MdmNotifyItem.ts +51 -0
- package/src/messagesConnector/dtos/MdmNotifyRequest.ts +31 -0
- package/src/messagesConnector/dtos/MdmNotifyResponse.ts +16 -0
- package/src/messagesConnector/enums/DeliveryChannelExtendedEnum.ts +2 -0
- package/src/messagesConnector/enums/MessagingSlotEnum.ts +9 -0
- package/src/messagesConnector/index.ts +6 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { plainToInstance } from 'class-transformer';
|
|
3
|
+
import { validate } from 'class-validator';
|
|
4
|
+
import { ListMessagingCandidatesRequest } from '../../../../src/loanCredit/dtos/requests/ListMessagingCandidatesRequest';
|
|
5
|
+
import { ListMessagingCandidatesResponse } from '../../../../src/loanCredit/dtos/responses/ListMessagingCandidatesResponse';
|
|
6
|
+
import { MessagingCandidateItem } from '../../../../src/loanCredit/dtos/MessagingCandidateItem';
|
|
7
|
+
import { MESSAGING_CANDIDATES_MAX_LIMIT } from '../../../../src/loanCredit/constants/MessagingCandidateLimits';
|
|
8
|
+
import { DeliveryChannelExtendedEnum, MessagingSlotEnum } from '../../../../src/messagesConnector/index';
|
|
9
|
+
import { MdmProviderEnum } from '../../../../src/mdm/enums/MdmProviderEnum';
|
|
10
|
+
|
|
11
|
+
const RUN_DATE = '2026-09-08';
|
|
12
|
+
|
|
13
|
+
/** `whitelist: true` es lo que corre el motor en `validateRequest`: sin decorador, la propiedad se borra. */
|
|
14
|
+
const validateWhitelisted = (body: object) => {
|
|
15
|
+
const dto = plainToInstance(ListMessagingCandidatesRequest, body);
|
|
16
|
+
return validate(dto, { whitelist: true, forbidNonWhitelisted: false }).then(errors => ({ dto, errors }));
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
describe('ListMessagingCandidatesRequest', () => {
|
|
20
|
+
it('acepta la primera página: sin cursor y sin limit', async () => {
|
|
21
|
+
const { dto, errors } = await validateWhitelisted({ slot: MessagingSlotEnum.MORNING, runDate: RUN_DATE });
|
|
22
|
+
|
|
23
|
+
expect(errors).toEqual([]);
|
|
24
|
+
expect(dto.cursor).toBeUndefined();
|
|
25
|
+
expect(dto.limit).toBeUndefined();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('convierte el limit que llega como texto', async () => {
|
|
29
|
+
const { dto, errors } = await validateWhitelisted({ slot: MessagingSlotEnum.EVENING, runDate: RUN_DATE, limit: '25' });
|
|
30
|
+
|
|
31
|
+
expect(errors).toEqual([]);
|
|
32
|
+
expect(dto.limit).toBe(25);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('rechaza un slot fuera del enum', async () => {
|
|
36
|
+
const { errors } = await validateWhitelisted({ slot: 'NIGHT', runDate: RUN_DATE });
|
|
37
|
+
|
|
38
|
+
expect(errors.some(error => error.property === 'slot')).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('rechaza un runDate con hora: el día de tienda no lleva reloj', async () => {
|
|
42
|
+
const { errors } = await validateWhitelisted({ slot: MessagingSlotEnum.MORNING, runDate: '2026-09-08T10:00:00Z' });
|
|
43
|
+
|
|
44
|
+
expect(errors.some(error => error.property === 'runDate')).toBe(true);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('rechaza un limit por encima del tope de página', async () => {
|
|
48
|
+
const { errors } = await validateWhitelisted({
|
|
49
|
+
slot: MessagingSlotEnum.AFTERNOON,
|
|
50
|
+
runDate: RUN_DATE,
|
|
51
|
+
limit: MESSAGING_CANDIDATES_MAX_LIMIT + 1,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
expect(errors.some(error => error.property === 'limit')).toBe(true);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe('MessagingCandidateItem', () => {
|
|
59
|
+
it('el candidato sin crédito conserva la persona', () => {
|
|
60
|
+
const item: MessagingCandidateItem = {
|
|
61
|
+
personId: '01JB2Z0N7Q9K3M5R8T1V4W6X7Y',
|
|
62
|
+
messageType: 'COLLECTION_NOTICE',
|
|
63
|
+
slot: MessagingSlotEnum.MORNING,
|
|
64
|
+
channel: DeliveryChannelExtendedEnum.SMS,
|
|
65
|
+
variables: { firstName: 'Ana', amount: '1,250.00' },
|
|
66
|
+
reference: 'collections#2026-09-08#MORNING#1',
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
expect(item.personId).toBeDefined();
|
|
70
|
+
expect(item.creditId).toBeUndefined();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('el candidato de MDM lleva IMEI y proveedor', () => {
|
|
74
|
+
const item: MessagingCandidateItem = {
|
|
75
|
+
personId: '01JB2Z0N7Q9K3M5R8T1V4W6X7Y',
|
|
76
|
+
creditId: 'CRD-01JB2Z0N7Q9K3M5R8T1V4W6X7Y',
|
|
77
|
+
messageType: 'COLLECTION_NOTICE',
|
|
78
|
+
slot: MessagingSlotEnum.EVENING,
|
|
79
|
+
channel: DeliveryChannelExtendedEnum.MDM,
|
|
80
|
+
variables: {},
|
|
81
|
+
reference: 'collections#2026-09-08#EVENING#7',
|
|
82
|
+
imei: '351756051523999',
|
|
83
|
+
mdmProvider: MdmProviderEnum.DATACULTR,
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
expect(item.channel).toBe('MDM');
|
|
87
|
+
expect(item.imei).toBe('351756051523999');
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe('ListMessagingCandidatesResponse', () => {
|
|
92
|
+
it('la última página cierra con nextCursor en null, no en undefined', () => {
|
|
93
|
+
const response: ListMessagingCandidatesResponse = { items: [], nextCursor: null };
|
|
94
|
+
|
|
95
|
+
expect(response.nextCursor).toBeNull();
|
|
96
|
+
});
|
|
97
|
+
});
|
|
@@ -148,6 +148,27 @@ describe('DeviceNotifyRequest — los tres textos son opcionales', () => {
|
|
|
148
148
|
});
|
|
149
149
|
});
|
|
150
150
|
|
|
151
|
+
describe('DeviceNotifyRequest — topes de longitud de los tres textos', () => {
|
|
152
|
+
/** Mismos números que `LoanDeviceNotifyItem`: las dos puntas del contrato dicen lo mismo. */
|
|
153
|
+
const limits = [
|
|
154
|
+
['notificationCode', 64],
|
|
155
|
+
['title', 128],
|
|
156
|
+
['content', 1024],
|
|
157
|
+
] as const;
|
|
158
|
+
|
|
159
|
+
it.each(limits)('acepta %s en el largo máximo', async (field, max) => {
|
|
160
|
+
const dto = plainToInstance(DeviceNotifyRequest, { ...validNotify, [field]: 'x'.repeat(max) });
|
|
161
|
+
const errors = await validate(dto);
|
|
162
|
+
expect(errors).toEqual([]);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it.each(limits)('falla si %s excede el largo máximo', async (field, max) => {
|
|
166
|
+
const dto = plainToInstance(DeviceNotifyRequest, { ...validNotify, [field]: 'x'.repeat(max + 1) });
|
|
167
|
+
const errors = await validate(dto);
|
|
168
|
+
expect(hasConstraint(errors, field, 'maxLength')).toBe(true);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
151
172
|
describe('MdmNoticeTypeEnum', () => {
|
|
152
173
|
it('expone los diez avisos del catálogo de cobranza', () => {
|
|
153
174
|
expect(Object.values(MdmNoticeTypeEnum)).toEqual([
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { plainToInstance } from 'class-transformer';
|
|
3
|
+
import { validate, ValidationError } from 'class-validator';
|
|
4
|
+
import { MdmNotifyItem } from '../../../src/messagesConnector/dtos/MdmNotifyItem';
|
|
5
|
+
import { MdmNotifyRequest } from '../../../src/messagesConnector/dtos/MdmNotifyRequest';
|
|
6
|
+
import * as MessagesConnectorBarrel from '../../../src/messagesConnector/index';
|
|
7
|
+
import { DeviceNotifyIntensityEnum } from '../../../src/mdm/enums/DeviceNotifyIntensityEnum';
|
|
8
|
+
import { MdmNoticeTypeEnum } from '../../../src/mdm/enums/MdmNoticeTypeEnum';
|
|
9
|
+
import { MdmOperationStatusEnum } from '../../../src/mdm/enums/MdmOperationStatusEnum';
|
|
10
|
+
import { MdmProviderEnum } from '../../../src/mdm/enums/MdmProviderEnum';
|
|
11
|
+
import { MDM_NOTIFY_MAX_BATCH } from '../../../src/messagesConnector/constants/MdmNotifyBatchLimits';
|
|
12
|
+
|
|
13
|
+
/** ULID real del motor: así genera los creditId `loan-credit-business`. */
|
|
14
|
+
const CREDIT_ID = '01M0B5D7FQA3T06K4REEVPRM33';
|
|
15
|
+
|
|
16
|
+
const validItem = {
|
|
17
|
+
imei: '351756051523999',
|
|
18
|
+
creditId: CREDIT_ID,
|
|
19
|
+
provider: MdmProviderEnum.TRUSTONIC,
|
|
20
|
+
noticeType: MdmNoticeTypeEnum.OVERDUE_1_DAY,
|
|
21
|
+
intensity: DeviceNotifyIntensityEnum.BANNER,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const validRequest = {
|
|
25
|
+
items: [validItem],
|
|
26
|
+
operationReference: 'mdm-notify-2026-09-08-0001',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/** True si el error de `property` trae ese constraint puntual (no solo "algo falló"). */
|
|
30
|
+
const hasConstraint = (errors: ValidationError[], property: string, constraint: string): boolean =>
|
|
31
|
+
errors.some((e) => e.property === property && Boolean(e.constraints?.[constraint]));
|
|
32
|
+
|
|
33
|
+
const validateRequest = async (payload: Record<string, unknown>): Promise<ValidationError[]> =>
|
|
34
|
+
validate(plainToInstance(MdmNotifyRequest, { ...validRequest, ...payload }));
|
|
35
|
+
|
|
36
|
+
const validateItem = async (payload: Record<string, unknown>): Promise<ValidationError[]> =>
|
|
37
|
+
validate(plainToInstance(MdmNotifyItem, { ...validItem, ...payload }));
|
|
38
|
+
|
|
39
|
+
describe('MdmNotifyItem', () => {
|
|
40
|
+
it('valida el ítem mínimo del endpoint', async () => {
|
|
41
|
+
expect(await validateItem({})).toEqual([]);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it.each(Object.values(MdmProviderEnum))('valida con provider %s', async (provider) => {
|
|
45
|
+
expect(await validateItem({ provider })).toEqual([]);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('falla si provider está fuera del enum', async () => {
|
|
49
|
+
expect(hasConstraint(await validateItem({ provider: 'AIRDROID' }), 'provider', 'isEnum')).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it.each(Object.values(MdmNoticeTypeEnum))('valida con noticeType %s', async (noticeType) => {
|
|
53
|
+
expect(await validateItem({ noticeType })).toEqual([]);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('falla si noticeType no viaja: el endpoint resuelve el catálogo, no hay otro camino', async () => {
|
|
57
|
+
const { noticeType: _omitted, ...rest } = validItem;
|
|
58
|
+
const errors = await validate(plainToInstance(MdmNotifyItem, rest));
|
|
59
|
+
expect(hasConstraint(errors, 'noticeType', 'isEnum')).toBe(true);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('falla si intensity no viaja', async () => {
|
|
63
|
+
const { intensity: _omitted, ...rest } = validItem;
|
|
64
|
+
const errors = await validate(plainToInstance(MdmNotifyItem, rest));
|
|
65
|
+
expect(hasConstraint(errors, 'intensity', 'isEnum')).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('falla si el imei viene vacío', async () => {
|
|
69
|
+
expect(hasConstraint(await validateItem({ imei: '' }), 'imei', 'isNotEmpty')).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('falla si el creditId no es un ULID', async () => {
|
|
73
|
+
expect(hasConstraint(await validateItem({ creditId: 'no-es-ulid' }), 'creditId', 'matches')).toBe(true);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('valida sin language ni country: caen al par por defecto', async () => {
|
|
77
|
+
const dto = plainToInstance(MdmNotifyItem, validItem);
|
|
78
|
+
expect(await validate(dto)).toEqual([]);
|
|
79
|
+
expect(dto.language).toBeUndefined();
|
|
80
|
+
expect(dto.country).toBeUndefined();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('valida con language y country explícitos', async () => {
|
|
84
|
+
expect(await validateItem({ language: 'es', country: 'MX' })).toEqual([]);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it.each(['language', 'country'] as const)('falla si %s viene vacío', async (field) => {
|
|
88
|
+
expect(hasConstraint(await validateItem({ [field]: '' }), field, 'isNotEmpty')).toBe(true);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe('MdmNotifyRequest', () => {
|
|
93
|
+
it('valida el sobre mínimo', async () => {
|
|
94
|
+
expect(await validateRequest({})).toEqual([]);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('valida sin tenantId: messages-business asume FIADO', async () => {
|
|
98
|
+
const dto = plainToInstance(MdmNotifyRequest, validRequest);
|
|
99
|
+
expect(await validate(dto)).toEqual([]);
|
|
100
|
+
expect(dto.tenantId).toBeUndefined();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('falla si items viene vacío', async () => {
|
|
104
|
+
expect(hasConstraint(await validateRequest({ items: [] }), 'items', 'arrayNotEmpty')).toBe(true);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('falla si items excede el tope del lote', async () => {
|
|
108
|
+
const items = Array.from({ length: MDM_NOTIFY_MAX_BATCH + 1 }, () => validItem);
|
|
109
|
+
expect(hasConstraint(await validateRequest({ items }), 'items', 'arrayMaxSize')).toBe(true);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('falla si dos ítems repiten el mismo imei: el resultado se devuelve por imei', async () => {
|
|
113
|
+
expect(hasConstraint(await validateRequest({ items: [validItem, validItem] }), 'items', 'arrayUnique')).toBe(true);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('valida en profundidad cada ítem', async () => {
|
|
117
|
+
const errors = await validateRequest({ items: [{ ...validItem, provider: 'AIRDROID' }] });
|
|
118
|
+
const children = errors.find((e) => e.property === 'items')?.children ?? [];
|
|
119
|
+
expect(hasConstraint(children[0]?.children ?? [], 'provider', 'isEnum')).toBe(true);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('materializa los ítems como MdmNotifyItem', async () => {
|
|
123
|
+
const dto = plainToInstance(MdmNotifyRequest, validRequest);
|
|
124
|
+
expect(dto.items[0]).toBeInstanceOf(MdmNotifyItem);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('falla si operationReference viene vacío', async () => {
|
|
128
|
+
expect(hasConstraint(await validateRequest({ operationReference: '' }), 'operationReference', 'isNotEmpty')).toBe(true);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('falla si operationReference excede el largo máximo', async () => {
|
|
132
|
+
const errors = await validateRequest({ operationReference: 'x'.repeat(65) });
|
|
133
|
+
expect(hasConstraint(errors, 'operationReference', 'maxLength')).toBe(true);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('falla si tenantId viene vacío: ausente cae a FIADO, pero "" no es un tenant', async () => {
|
|
137
|
+
expect(hasConstraint(await validateRequest({ tenantId: '' }), 'tenantId', 'isNotEmpty')).toBe(true);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('valida con tenantId explícito', async () => {
|
|
141
|
+
expect(await validateRequest({ tenantId: 'SUREKEEP' })).toEqual([]);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
describe('barrel de messagesConnector', () => {
|
|
146
|
+
it('exporta el par del endpoint de avisos MDM', () => {
|
|
147
|
+
expect(MessagesConnectorBarrel.MdmNotifyItem).toBe(MdmNotifyItem);
|
|
148
|
+
expect(MessagesConnectorBarrel.MdmNotifyRequest).toBe(MdmNotifyRequest);
|
|
149
|
+
expect(MessagesConnectorBarrel.MdmNotifyResponse).toBeDefined();
|
|
150
|
+
expect(MessagesConnectorBarrel.MdmNotifyBatchResponse).toBeDefined();
|
|
151
|
+
expect(MessagesConnectorBarrel.MDM_NOTIFY_MAX_BATCH).toBe(MDM_NOTIFY_MAX_BATCH);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('el resultado por imei se tipa contra el estado de operación de MDM', () => {
|
|
155
|
+
const result = new MessagesConnectorBarrel.MdmNotifyResponse();
|
|
156
|
+
result.imei = validItem.imei;
|
|
157
|
+
result.creditId = CREDIT_ID;
|
|
158
|
+
result.status = MdmOperationStatusEnum.SUCCESS;
|
|
159
|
+
result.sentAt = '2026-09-08T12:00:00.000Z';
|
|
160
|
+
expect(result.status).toBe(MdmOperationStatusEnum.SUCCESS);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { DeliveryChannelExtendedEnum, MessagingSlotEnum } from '../../../src/messagesConnector/index';
|
|
3
|
+
|
|
4
|
+
describe('DeliveryChannelExtendedEnum', () => {
|
|
5
|
+
it('incluye MDM junto a los tres canales que ya existían', () => {
|
|
6
|
+
expect(Object.values(DeliveryChannelExtendedEnum).sort()).toEqual([
|
|
7
|
+
'MAIL',
|
|
8
|
+
'MDM',
|
|
9
|
+
'PUSH_NOTIFICATION',
|
|
10
|
+
'SMS',
|
|
11
|
+
]);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('cada clave es igual a su valor', () => {
|
|
15
|
+
for (const [key, value] of Object.entries(DeliveryChannelExtendedEnum)) {
|
|
16
|
+
expect(key).toBe(value);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe('MessagingSlotEnum', () => {
|
|
22
|
+
it('tiene exactamente los tres momentos del contrato', () => {
|
|
23
|
+
expect(Object.values(MessagingSlotEnum).sort()).toEqual(['AFTERNOON', 'EVENING', 'MORNING']);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('cada clave es igual a su valor', () => {
|
|
27
|
+
for (const [key, value] of Object.entries(MessagingSlotEnum)) {
|
|
28
|
+
expect(key).toBe(value);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('ningún valor lleva la hora: la hora vive en la agenda del tenant', () => {
|
|
33
|
+
for (const value of Object.values(MessagingSlotEnum)) {
|
|
34
|
+
expect(value).not.toMatch(/\d/);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MESSAGING_CANDIDATES_DEFAULT_LIMIT = exports.MESSAGING_CANDIDATES_MAX_LIMIT = void 0;
|
|
4
|
+
/** Tope de candidatos por página. Una cartera grande no cabe en una sola llamada. */
|
|
5
|
+
exports.MESSAGING_CANDIDATES_MAX_LIMIT = 100;
|
|
6
|
+
/** Tamaño de página cuando el caller no manda `limit`. */
|
|
7
|
+
exports.MESSAGING_CANDIDATES_DEFAULT_LIMIT = 50;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.STORE_DAY_MESSAGE = exports.STORE_DAY_PATTERN = void 0;
|
|
4
|
+
/** Día de tienda en la zona horaria del tenant, sin hora: `YYYY-MM-DD`. */
|
|
5
|
+
exports.STORE_DAY_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
6
|
+
exports.STORE_DAY_MESSAGE = 'runDate debe ser un día de tienda en formato YYYY-MM-DD';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { DeliveryChannelExtendedEnum, MessagingSlotEnum } from '../../messagesConnector/index';
|
|
2
|
+
import { MdmProviderEnum } from '../../mdm/enums/MdmProviderEnum';
|
|
3
|
+
/**
|
|
4
|
+
* Un candidato a recibir un mensaje: a quién, qué momento le toca y por dónde sale.
|
|
5
|
+
* Mensajería no resuelve nada de dominio con este ítem: solo elige la plantilla y entrega.
|
|
6
|
+
*/
|
|
7
|
+
export declare class MessagingCandidateItem {
|
|
8
|
+
/** El destinatario es la PERSONA. Siempre viaja. */
|
|
9
|
+
personId: string;
|
|
10
|
+
/**
|
|
11
|
+
* El crédito es el motivo del mensaje, no a quién se le manda.
|
|
12
|
+
* Va vacío en los avisos que no cuelgan de un crédito.
|
|
13
|
+
*/
|
|
14
|
+
creditId?: string;
|
|
15
|
+
/** Momento del catálogo de plantillas — parte de la PK de `TemplateMessages_GT`. */
|
|
16
|
+
messageType: string;
|
|
17
|
+
/** Momento de la corrida que produjo este candidato. */
|
|
18
|
+
slot: MessagingSlotEnum;
|
|
19
|
+
channel: DeliveryChannelExtendedEnum;
|
|
20
|
+
/**
|
|
21
|
+
* Variables del texto YA RESUELTAS. Mensajería no sabe qué es un crédito:
|
|
22
|
+
* si aquí viajara un id para que ella lo resuelva, cada mensaje sería otra llamada entre lambdas.
|
|
23
|
+
*/
|
|
24
|
+
variables: Record<string, string>;
|
|
25
|
+
/** Referencia de rastreo del candidato; el consumidor la usa para deduplicar. */
|
|
26
|
+
reference: string;
|
|
27
|
+
/** IMEI del equipo. Solo viaja cuando `channel` es `MDM`. */
|
|
28
|
+
imei?: string;
|
|
29
|
+
/** Proveedor MDM del equipo. Solo viaja cuando `channel` es `MDM`. */
|
|
30
|
+
mdmProvider?: MdmProviderEnum;
|
|
31
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MessagingCandidateItem = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Un candidato a recibir un mensaje: a quién, qué momento le toca y por dónde sale.
|
|
6
|
+
* Mensajería no resuelve nada de dominio con este ítem: solo elige la plantilla y entrega.
|
|
7
|
+
*/
|
|
8
|
+
class MessagingCandidateItem {
|
|
9
|
+
}
|
|
10
|
+
exports.MessagingCandidateItem = MessagingCandidateItem;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { MessagingSlotEnum } from '../../../messagesConnector/index';
|
|
2
|
+
/** Body de `POST /private/messaging/candidates` (loan-credit-business). Pide una página de candidatos. */
|
|
3
|
+
export declare class ListMessagingCandidatesRequest {
|
|
4
|
+
/** Qué horario disparó la corrida. El nombre del momento, nunca la hora. */
|
|
5
|
+
slot: MessagingSlotEnum;
|
|
6
|
+
/** Día de tienda de la corrida. Lo manda el caller: el cupo no puede salir del reloj del lambda. */
|
|
7
|
+
runDate: string;
|
|
8
|
+
/** Cursor opaco de la página anterior. Ausente en la primera página. */
|
|
9
|
+
cursor?: string;
|
|
10
|
+
limit?: number;
|
|
11
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
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.ListMessagingCandidatesRequest = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
const index_1 = require("../../../messagesConnector/index");
|
|
16
|
+
const MessagingCandidateLimits_1 = require("../../constants/MessagingCandidateLimits");
|
|
17
|
+
const StoreDayPattern_1 = require("../../constants/StoreDayPattern");
|
|
18
|
+
/** Body de `POST /private/messaging/candidates` (loan-credit-business). Pide una página de candidatos. */
|
|
19
|
+
class ListMessagingCandidatesRequest {
|
|
20
|
+
}
|
|
21
|
+
exports.ListMessagingCandidatesRequest = ListMessagingCandidatesRequest;
|
|
22
|
+
__decorate([
|
|
23
|
+
(0, class_transformer_1.Expose)(),
|
|
24
|
+
(0, class_validator_1.IsEnum)(index_1.MessagingSlotEnum),
|
|
25
|
+
__metadata("design:type", String)
|
|
26
|
+
], ListMessagingCandidatesRequest.prototype, "slot", void 0);
|
|
27
|
+
__decorate([
|
|
28
|
+
(0, class_transformer_1.Expose)(),
|
|
29
|
+
(0, class_validator_1.Matches)(StoreDayPattern_1.STORE_DAY_PATTERN, { message: StoreDayPattern_1.STORE_DAY_MESSAGE }),
|
|
30
|
+
__metadata("design:type", String)
|
|
31
|
+
], ListMessagingCandidatesRequest.prototype, "runDate", void 0);
|
|
32
|
+
__decorate([
|
|
33
|
+
(0, class_transformer_1.Expose)(),
|
|
34
|
+
(0, class_validator_1.IsOptional)(),
|
|
35
|
+
(0, class_validator_1.IsString)(),
|
|
36
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
37
|
+
__metadata("design:type", String)
|
|
38
|
+
], ListMessagingCandidatesRequest.prototype, "cursor", void 0);
|
|
39
|
+
__decorate([
|
|
40
|
+
(0, class_transformer_1.Expose)(),
|
|
41
|
+
(0, class_validator_1.IsOptional)(),
|
|
42
|
+
(0, class_transformer_1.Type)(() => Number),
|
|
43
|
+
(0, class_validator_1.IsInt)(),
|
|
44
|
+
(0, class_validator_1.Min)(1),
|
|
45
|
+
(0, class_validator_1.Max)(MessagingCandidateLimits_1.MESSAGING_CANDIDATES_MAX_LIMIT),
|
|
46
|
+
__metadata("design:type", Number)
|
|
47
|
+
], ListMessagingCandidatesRequest.prototype, "limit", void 0);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { MessagingCandidateItem } from '../MessagingCandidateItem';
|
|
2
|
+
/** Response de `POST /private/messaging/candidates`. Una página de candidatos. */
|
|
3
|
+
export declare class ListMessagingCandidatesResponse {
|
|
4
|
+
items: MessagingCandidateItem[];
|
|
5
|
+
/** Cursor de la siguiente página. `null` significa que ya no queda nadie — nunca `undefined`. */
|
|
6
|
+
nextCursor: string | null;
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ListMessagingCandidatesResponse = void 0;
|
|
4
|
+
/** Response de `POST /private/messaging/candidates`. Una página de candidatos. */
|
|
5
|
+
class ListMessagingCandidatesResponse {
|
|
6
|
+
}
|
|
7
|
+
exports.ListMessagingCandidatesResponse = ListMessagingCandidatesResponse;
|
|
@@ -82,3 +82,9 @@ export * from './dtos/responses/LoanDeviceNotifyResponse';
|
|
|
82
82
|
export * from './dtos/responses/LoanDeviceReleaseResult';
|
|
83
83
|
export * from './dtos/responses/LoanDeviceReleaseResponse';
|
|
84
84
|
export * from './validators/IsFutureIso8601DateTime';
|
|
85
|
+
export { MessagingSlotEnum } from '../messagesConnector/enums/MessagingSlotEnum';
|
|
86
|
+
export * from './constants/MessagingCandidateLimits';
|
|
87
|
+
export * from './constants/StoreDayPattern';
|
|
88
|
+
export * from './dtos/MessagingCandidateItem';
|
|
89
|
+
export * from './dtos/requests/ListMessagingCandidatesRequest';
|
|
90
|
+
export * from './dtos/responses/ListMessagingCandidatesResponse';
|
package/bin/loanCredit/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.MdmLockModeEnum = exports.DeviceLockScreenMessage = exports.MdmError = exports.DeviceReleaseReasonEnum = exports.MdmNoticeTypeEnum = exports.DeviceNotifyIntensityEnum = exports.DeviceEnrollmentModeEnum = exports.MdmProviderEnum = exports.MdmOperationTypeEnum = exports.MdmDeviceStatusEnum = exports.MdmOperationStatusEnum = exports.ClientLevelEnum = void 0;
|
|
17
|
+
exports.MessagingSlotEnum = exports.MdmLockModeEnum = exports.DeviceLockScreenMessage = exports.MdmError = exports.DeviceReleaseReasonEnum = exports.MdmNoticeTypeEnum = exports.DeviceNotifyIntensityEnum = exports.DeviceEnrollmentModeEnum = exports.MdmProviderEnum = exports.MdmOperationTypeEnum = exports.MdmDeviceStatusEnum = exports.MdmOperationStatusEnum = exports.ClientLevelEnum = void 0;
|
|
18
18
|
// Enums
|
|
19
19
|
__exportStar(require("./enums/LoanCreditStatusEnum"), exports);
|
|
20
20
|
__exportStar(require("./enums/LoanInstallmentStatusEnum"), exports);
|
|
@@ -118,3 +118,12 @@ __exportStar(require("./dtos/responses/LoanDeviceNotifyResponse"), exports);
|
|
|
118
118
|
__exportStar(require("./dtos/responses/LoanDeviceReleaseResult"), exports);
|
|
119
119
|
__exportStar(require("./dtos/responses/LoanDeviceReleaseResponse"), exports);
|
|
120
120
|
__exportStar(require("./validators/IsFutureIso8601DateTime"), exports);
|
|
121
|
+
// Candidatos de mensajería — contrato de `POST /private/messaging/candidates`
|
|
122
|
+
// Re-export del enum canónico del momento (owner: messagesConnector — un solo origen de verdad).
|
|
123
|
+
var MessagingSlotEnum_1 = require("../messagesConnector/enums/MessagingSlotEnum");
|
|
124
|
+
Object.defineProperty(exports, "MessagingSlotEnum", { enumerable: true, get: function () { return MessagingSlotEnum_1.MessagingSlotEnum; } });
|
|
125
|
+
__exportStar(require("./constants/MessagingCandidateLimits"), exports);
|
|
126
|
+
__exportStar(require("./constants/StoreDayPattern"), exports);
|
|
127
|
+
__exportStar(require("./dtos/MessagingCandidateItem"), exports);
|
|
128
|
+
__exportStar(require("./dtos/requests/ListMessagingCandidatesRequest"), exports);
|
|
129
|
+
__exportStar(require("./dtos/responses/ListMessagingCandidatesResponse"), exports);
|
|
@@ -39,6 +39,7 @@ __decorate([
|
|
|
39
39
|
(0, class_validator_1.IsOptional)(),
|
|
40
40
|
(0, class_validator_1.IsString)(),
|
|
41
41
|
(0, class_validator_1.IsNotEmpty)(),
|
|
42
|
+
(0, class_validator_1.MaxLength)(64),
|
|
42
43
|
__metadata("design:type", String)
|
|
43
44
|
], DeviceNotifyRequest.prototype, "notificationCode", void 0);
|
|
44
45
|
__decorate([
|
|
@@ -46,6 +47,7 @@ __decorate([
|
|
|
46
47
|
(0, class_validator_1.IsOptional)(),
|
|
47
48
|
(0, class_validator_1.IsString)(),
|
|
48
49
|
(0, class_validator_1.IsNotEmpty)(),
|
|
50
|
+
(0, class_validator_1.MaxLength)(128),
|
|
49
51
|
__metadata("design:type", String)
|
|
50
52
|
], DeviceNotifyRequest.prototype, "title", void 0);
|
|
51
53
|
__decorate([
|
|
@@ -53,6 +55,7 @@ __decorate([
|
|
|
53
55
|
(0, class_validator_1.IsOptional)(),
|
|
54
56
|
(0, class_validator_1.IsString)(),
|
|
55
57
|
(0, class_validator_1.IsNotEmpty)(),
|
|
58
|
+
(0, class_validator_1.MaxLength)(1024),
|
|
56
59
|
__metadata("design:type", String)
|
|
57
60
|
], DeviceNotifyRequest.prototype, "content", void 0);
|
|
58
61
|
__decorate([
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MDM_NOTIFY_MAX_BATCH = void 0;
|
|
4
|
+
const LoanDeviceBatchLimits_1 = require("../../loanCredit/constants/LoanDeviceBatchLimits");
|
|
5
|
+
/**
|
|
6
|
+
* Mismo tope que el lote de `loan-credit-business`, el único caller del endpoint.
|
|
7
|
+
* Si aquí fuera más chico, un lote que ese endpoint ya aceptó se caería con 400 al llegar a mensajería.
|
|
8
|
+
*/
|
|
9
|
+
exports.MDM_NOTIFY_MAX_BATCH = LoanDeviceBatchLimits_1.LOAN_DEVICE_MAX_BATCH;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MdmNotifyBatchResponse = void 0;
|
|
4
|
+
/** Response de `POST /private/messages/mdm-notify`. Un resultado por ítem enviado. */
|
|
5
|
+
class MdmNotifyBatchResponse {
|
|
6
|
+
}
|
|
7
|
+
exports.MdmNotifyBatchResponse = MdmNotifyBatchResponse;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { DeviceNotifyIntensityEnum } from '../../mdm/enums/DeviceNotifyIntensityEnum';
|
|
2
|
+
import { MdmNoticeTypeEnum } from '../../mdm/enums/MdmNoticeTypeEnum';
|
|
3
|
+
import { MdmProviderEnum } from '../../mdm/enums/MdmProviderEnum';
|
|
4
|
+
/**
|
|
5
|
+
* Equipo al que se le avisa. El caller dice cuál es el aviso; el texto lo resuelve
|
|
6
|
+
* messages-business contra el catálogo, así que aquí no viajan `title` ni `content`.
|
|
7
|
+
*/
|
|
8
|
+
export declare class MdmNotifyItem {
|
|
9
|
+
imei: string;
|
|
10
|
+
creditId: string;
|
|
11
|
+
/** Proveedor MDM del equipo: messages-business agrupa por él y hace una llamada por grupo. */
|
|
12
|
+
provider: MdmProviderEnum;
|
|
13
|
+
/** Id agnóstico del aviso. Es obligatorio: resolverlo contra el catálogo es el punto del endpoint. */
|
|
14
|
+
noticeType: MdmNoticeTypeEnum;
|
|
15
|
+
intensity: DeviceNotifyIntensityEnum;
|
|
16
|
+
/**
|
|
17
|
+
* Idioma y país con los que se busca la plantilla del aviso.
|
|
18
|
+
* Ausentes, messages-business cae al par por defecto del tenant.
|
|
19
|
+
*/
|
|
20
|
+
language?: string;
|
|
21
|
+
country?: string;
|
|
22
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
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.MdmNotifyItem = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
const CreditIdPattern_1 = require("../../common/constants/CreditIdPattern");
|
|
16
|
+
const DeviceNotifyIntensityEnum_1 = require("../../mdm/enums/DeviceNotifyIntensityEnum");
|
|
17
|
+
const MdmNoticeTypeEnum_1 = require("../../mdm/enums/MdmNoticeTypeEnum");
|
|
18
|
+
const MdmProviderEnum_1 = require("../../mdm/enums/MdmProviderEnum");
|
|
19
|
+
/**
|
|
20
|
+
* Equipo al que se le avisa. El caller dice cuál es el aviso; el texto lo resuelve
|
|
21
|
+
* messages-business contra el catálogo, así que aquí no viajan `title` ni `content`.
|
|
22
|
+
*/
|
|
23
|
+
class MdmNotifyItem {
|
|
24
|
+
}
|
|
25
|
+
exports.MdmNotifyItem = MdmNotifyItem;
|
|
26
|
+
__decorate([
|
|
27
|
+
(0, class_transformer_1.Expose)(),
|
|
28
|
+
(0, class_validator_1.IsString)(),
|
|
29
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
30
|
+
__metadata("design:type", String)
|
|
31
|
+
], MdmNotifyItem.prototype, "imei", void 0);
|
|
32
|
+
__decorate([
|
|
33
|
+
(0, class_transformer_1.Expose)(),
|
|
34
|
+
(0, class_validator_1.Matches)(CreditIdPattern_1.CREDIT_ID_PATTERN, { message: CreditIdPattern_1.CREDIT_ID_MESSAGE }),
|
|
35
|
+
__metadata("design:type", String)
|
|
36
|
+
], MdmNotifyItem.prototype, "creditId", void 0);
|
|
37
|
+
__decorate([
|
|
38
|
+
(0, class_transformer_1.Expose)(),
|
|
39
|
+
(0, class_validator_1.IsEnum)(MdmProviderEnum_1.MdmProviderEnum),
|
|
40
|
+
__metadata("design:type", String)
|
|
41
|
+
], MdmNotifyItem.prototype, "provider", void 0);
|
|
42
|
+
__decorate([
|
|
43
|
+
(0, class_transformer_1.Expose)(),
|
|
44
|
+
(0, class_validator_1.IsEnum)(MdmNoticeTypeEnum_1.MdmNoticeTypeEnum),
|
|
45
|
+
__metadata("design:type", String)
|
|
46
|
+
], MdmNotifyItem.prototype, "noticeType", void 0);
|
|
47
|
+
__decorate([
|
|
48
|
+
(0, class_transformer_1.Expose)(),
|
|
49
|
+
(0, class_validator_1.IsEnum)(DeviceNotifyIntensityEnum_1.DeviceNotifyIntensityEnum),
|
|
50
|
+
__metadata("design:type", String)
|
|
51
|
+
], MdmNotifyItem.prototype, "intensity", void 0);
|
|
52
|
+
__decorate([
|
|
53
|
+
(0, class_transformer_1.Expose)(),
|
|
54
|
+
(0, class_validator_1.IsOptional)(),
|
|
55
|
+
(0, class_validator_1.IsString)(),
|
|
56
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
57
|
+
__metadata("design:type", String)
|
|
58
|
+
], MdmNotifyItem.prototype, "language", void 0);
|
|
59
|
+
__decorate([
|
|
60
|
+
(0, class_transformer_1.Expose)(),
|
|
61
|
+
(0, class_validator_1.IsOptional)(),
|
|
62
|
+
(0, class_validator_1.IsString)(),
|
|
63
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
64
|
+
__metadata("design:type", String)
|
|
65
|
+
], MdmNotifyItem.prototype, "country", void 0);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { MdmNotifyItem } from './MdmNotifyItem';
|
|
2
|
+
/** Body de `POST /private/messages/mdm-notify` (messages-business). Avisa en lote. */
|
|
3
|
+
export declare class MdmNotifyRequest {
|
|
4
|
+
/** Un resultado por imei, así que el imei repetido no tiene resultado que devolver. */
|
|
5
|
+
items: MdmNotifyItem[];
|
|
6
|
+
/** Tenant emisor del aviso. Si se omite, messages-business asume FIADO. */
|
|
7
|
+
tenantId?: string;
|
|
8
|
+
/** Referencia con la que el caller correlaciona este batch. */
|
|
9
|
+
operationReference: string;
|
|
10
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
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.MdmNotifyRequest = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
const MdmNotifyItem_1 = require("./MdmNotifyItem");
|
|
16
|
+
const MdmNotifyBatchLimits_1 = require("../constants/MdmNotifyBatchLimits");
|
|
17
|
+
/** Body de `POST /private/messages/mdm-notify` (messages-business). Avisa en lote. */
|
|
18
|
+
class MdmNotifyRequest {
|
|
19
|
+
}
|
|
20
|
+
exports.MdmNotifyRequest = MdmNotifyRequest;
|
|
21
|
+
__decorate([
|
|
22
|
+
(0, class_transformer_1.Expose)(),
|
|
23
|
+
(0, class_validator_1.IsArray)(),
|
|
24
|
+
(0, class_validator_1.ArrayNotEmpty)(),
|
|
25
|
+
(0, class_validator_1.ArrayMaxSize)(MdmNotifyBatchLimits_1.MDM_NOTIFY_MAX_BATCH),
|
|
26
|
+
(0, class_validator_1.ArrayUnique)((item) => item.imei),
|
|
27
|
+
(0, class_validator_1.ValidateNested)({ each: true }),
|
|
28
|
+
(0, class_transformer_1.Type)(() => MdmNotifyItem_1.MdmNotifyItem),
|
|
29
|
+
__metadata("design:type", Array)
|
|
30
|
+
], MdmNotifyRequest.prototype, "items", void 0);
|
|
31
|
+
__decorate([
|
|
32
|
+
(0, class_transformer_1.Expose)(),
|
|
33
|
+
(0, class_validator_1.IsOptional)(),
|
|
34
|
+
(0, class_validator_1.IsString)(),
|
|
35
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
36
|
+
__metadata("design:type", String)
|
|
37
|
+
], MdmNotifyRequest.prototype, "tenantId", void 0);
|
|
38
|
+
__decorate([
|
|
39
|
+
(0, class_transformer_1.Expose)(),
|
|
40
|
+
(0, class_validator_1.IsString)(),
|
|
41
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
42
|
+
(0, class_validator_1.MaxLength)(64),
|
|
43
|
+
__metadata("design:type", String)
|
|
44
|
+
], MdmNotifyRequest.prototype, "operationReference", void 0);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { MdmError } from '../../mdm/dtos/MdmError';
|
|
2
|
+
import { MdmOperationStatusEnum } from '../../mdm/enums/MdmOperationStatusEnum';
|
|
3
|
+
/** Resultado por equipo del aviso en lote. `error` solo viaja cuando el status es ERROR. */
|
|
4
|
+
export declare class MdmNotifyResponse {
|
|
5
|
+
imei: string;
|
|
6
|
+
creditId: string;
|
|
7
|
+
status: MdmOperationStatusEnum;
|
|
8
|
+
/** Momento en que el proveedor aceptó el aviso, en ISO-8601. */
|
|
9
|
+
sentAt?: string;
|
|
10
|
+
error?: MdmError;
|
|
11
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MdmNotifyResponse = void 0;
|
|
4
|
+
/** Resultado por equipo del aviso en lote. `error` solo viaja cuando el status es ERROR. */
|
|
5
|
+
class MdmNotifyResponse {
|
|
6
|
+
}
|
|
7
|
+
exports.MdmNotifyResponse = MdmNotifyResponse;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export declare enum DeliveryChannelExtendedEnum {
|
|
2
2
|
SMS = "SMS",
|
|
3
3
|
MAIL = "MAIL",
|
|
4
|
-
PUSH_NOTIFICATION = "PUSH_NOTIFICATION"
|
|
4
|
+
PUSH_NOTIFICATION = "PUSH_NOTIFICATION",
|
|
5
|
+
/** Aviso en la pantalla del equipo financiado. Se entrega por IMEI, no por teléfono ni correo. */
|
|
6
|
+
MDM = "MDM"
|
|
5
7
|
}
|
|
@@ -6,4 +6,6 @@ var DeliveryChannelExtendedEnum;
|
|
|
6
6
|
DeliveryChannelExtendedEnum["SMS"] = "SMS";
|
|
7
7
|
DeliveryChannelExtendedEnum["MAIL"] = "MAIL";
|
|
8
8
|
DeliveryChannelExtendedEnum["PUSH_NOTIFICATION"] = "PUSH_NOTIFICATION";
|
|
9
|
+
/** Aviso en la pantalla del equipo financiado. Se entrega por IMEI, no por teléfono ni correo. */
|
|
10
|
+
DeliveryChannelExtendedEnum["MDM"] = "MDM";
|
|
9
11
|
})(DeliveryChannelExtendedEnum || (exports.DeliveryChannelExtendedEnum = DeliveryChannelExtendedEnum = {}));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Momento del día en que corre una agenda de mensajería.
|
|
3
|
+
* Es el nombre del momento, nunca la hora: la hora vive en la agenda de cada tenant y cambia sin desplegar.
|
|
4
|
+
*/
|
|
5
|
+
export declare enum MessagingSlotEnum {
|
|
6
|
+
MORNING = "MORNING",
|
|
7
|
+
AFTERNOON = "AFTERNOON",
|
|
8
|
+
EVENING = "EVENING"
|
|
9
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MessagingSlotEnum = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Momento del día en que corre una agenda de mensajería.
|
|
6
|
+
* Es el nombre del momento, nunca la hora: la hora vive en la agenda de cada tenant y cambia sin desplegar.
|
|
7
|
+
*/
|
|
8
|
+
var MessagingSlotEnum;
|
|
9
|
+
(function (MessagingSlotEnum) {
|
|
10
|
+
MessagingSlotEnum["MORNING"] = "MORNING";
|
|
11
|
+
MessagingSlotEnum["AFTERNOON"] = "AFTERNOON";
|
|
12
|
+
MessagingSlotEnum["EVENING"] = "EVENING";
|
|
13
|
+
})(MessagingSlotEnum || (exports.MessagingSlotEnum = MessagingSlotEnum = {}));
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './enums/DeliveryChannelExtendedEnum';
|
|
2
2
|
export * from './enums/NotificationOriginEnum';
|
|
3
|
+
export * from './enums/MessagingSlotEnum';
|
|
3
4
|
export * from './validators/IsStringValueRecord';
|
|
4
5
|
export * from './dtos/NotificationQueueMessageRequestV2';
|
|
5
6
|
export * from './dtos/SendMessageRequest';
|
|
@@ -19,3 +20,8 @@ export * from './dtos/TemplateMessageUpdateRequest';
|
|
|
19
20
|
export * from './dtos/TemplateMessageResponse';
|
|
20
21
|
export * from './dtos/TemplateMessageListResponse';
|
|
21
22
|
export * from './dtos/TemplateMessageListFiltersRequest';
|
|
23
|
+
export * from './constants/MdmNotifyBatchLimits';
|
|
24
|
+
export * from './dtos/MdmNotifyItem';
|
|
25
|
+
export * from './dtos/MdmNotifyRequest';
|
|
26
|
+
export * from './dtos/MdmNotifyResponse';
|
|
27
|
+
export * from './dtos/MdmNotifyBatchResponse';
|
|
@@ -16,6 +16,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./enums/DeliveryChannelExtendedEnum"), exports);
|
|
18
18
|
__exportStar(require("./enums/NotificationOriginEnum"), exports);
|
|
19
|
+
__exportStar(require("./enums/MessagingSlotEnum"), exports);
|
|
19
20
|
__exportStar(require("./validators/IsStringValueRecord"), exports);
|
|
20
21
|
__exportStar(require("./dtos/NotificationQueueMessageRequestV2"), exports);
|
|
21
22
|
__exportStar(require("./dtos/SendMessageRequest"), exports);
|
|
@@ -35,3 +36,8 @@ __exportStar(require("./dtos/TemplateMessageUpdateRequest"), exports);
|
|
|
35
36
|
__exportStar(require("./dtos/TemplateMessageResponse"), exports);
|
|
36
37
|
__exportStar(require("./dtos/TemplateMessageListResponse"), exports);
|
|
37
38
|
__exportStar(require("./dtos/TemplateMessageListFiltersRequest"), exports);
|
|
39
|
+
__exportStar(require("./constants/MdmNotifyBatchLimits"), exports);
|
|
40
|
+
__exportStar(require("./dtos/MdmNotifyItem"), exports);
|
|
41
|
+
__exportStar(require("./dtos/MdmNotifyRequest"), exports);
|
|
42
|
+
__exportStar(require("./dtos/MdmNotifyResponse"), exports);
|
|
43
|
+
__exportStar(require("./dtos/MdmNotifyBatchResponse"), exports);
|
package/package.json
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { DeliveryChannelExtendedEnum, MessagingSlotEnum } from '../../messagesConnector/index';
|
|
2
|
+
import { MdmProviderEnum } from '../../mdm/enums/MdmProviderEnum';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Un candidato a recibir un mensaje: a quién, qué momento le toca y por dónde sale.
|
|
6
|
+
* Mensajería no resuelve nada de dominio con este ítem: solo elige la plantilla y entrega.
|
|
7
|
+
*/
|
|
8
|
+
export class MessagingCandidateItem {
|
|
9
|
+
/** El destinatario es la PERSONA. Siempre viaja. */
|
|
10
|
+
personId!: string;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* El crédito es el motivo del mensaje, no a quién se le manda.
|
|
14
|
+
* Va vacío en los avisos que no cuelgan de un crédito.
|
|
15
|
+
*/
|
|
16
|
+
creditId?: string;
|
|
17
|
+
|
|
18
|
+
/** Momento del catálogo de plantillas — parte de la PK de `TemplateMessages_GT`. */
|
|
19
|
+
messageType!: string;
|
|
20
|
+
|
|
21
|
+
/** Momento de la corrida que produjo este candidato. */
|
|
22
|
+
slot!: MessagingSlotEnum;
|
|
23
|
+
|
|
24
|
+
channel!: DeliveryChannelExtendedEnum;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Variables del texto YA RESUELTAS. Mensajería no sabe qué es un crédito:
|
|
28
|
+
* si aquí viajara un id para que ella lo resuelva, cada mensaje sería otra llamada entre lambdas.
|
|
29
|
+
*/
|
|
30
|
+
variables!: Record<string, string>;
|
|
31
|
+
|
|
32
|
+
/** Referencia de rastreo del candidato; el consumidor la usa para deduplicar. */
|
|
33
|
+
reference!: string;
|
|
34
|
+
|
|
35
|
+
/** IMEI del equipo. Solo viaja cuando `channel` es `MDM`. */
|
|
36
|
+
imei?: string;
|
|
37
|
+
|
|
38
|
+
/** Proveedor MDM del equipo. Solo viaja cuando `channel` es `MDM`. */
|
|
39
|
+
mdmProvider?: MdmProviderEnum;
|
|
40
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Expose, Type } from 'class-transformer';
|
|
2
|
+
import { IsEnum, IsInt, IsNotEmpty, IsOptional, IsString, Matches, Max, Min } from 'class-validator';
|
|
3
|
+
import { MessagingSlotEnum } from '../../../messagesConnector/index';
|
|
4
|
+
import { MESSAGING_CANDIDATES_MAX_LIMIT } from '../../constants/MessagingCandidateLimits';
|
|
5
|
+
import { STORE_DAY_MESSAGE, STORE_DAY_PATTERN } from '../../constants/StoreDayPattern';
|
|
6
|
+
|
|
7
|
+
/** Body de `POST /private/messaging/candidates` (loan-credit-business). Pide una página de candidatos. */
|
|
8
|
+
export class ListMessagingCandidatesRequest {
|
|
9
|
+
/** Qué horario disparó la corrida. El nombre del momento, nunca la hora. */
|
|
10
|
+
@Expose()
|
|
11
|
+
@IsEnum(MessagingSlotEnum)
|
|
12
|
+
slot!: MessagingSlotEnum;
|
|
13
|
+
|
|
14
|
+
/** Día de tienda de la corrida. Lo manda el caller: el cupo no puede salir del reloj del lambda. */
|
|
15
|
+
@Expose()
|
|
16
|
+
@Matches(STORE_DAY_PATTERN, { message: STORE_DAY_MESSAGE })
|
|
17
|
+
runDate!: string;
|
|
18
|
+
|
|
19
|
+
/** Cursor opaco de la página anterior. Ausente en la primera página. */
|
|
20
|
+
@Expose()
|
|
21
|
+
@IsOptional()
|
|
22
|
+
@IsString()
|
|
23
|
+
@IsNotEmpty()
|
|
24
|
+
cursor?: string;
|
|
25
|
+
|
|
26
|
+
@Expose()
|
|
27
|
+
@IsOptional()
|
|
28
|
+
@Type(() => Number)
|
|
29
|
+
@IsInt()
|
|
30
|
+
@Min(1)
|
|
31
|
+
@Max(MESSAGING_CANDIDATES_MAX_LIMIT)
|
|
32
|
+
limit?: number;
|
|
33
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { MessagingCandidateItem } from '../MessagingCandidateItem';
|
|
2
|
+
|
|
3
|
+
/** Response de `POST /private/messaging/candidates`. Una página de candidatos. */
|
|
4
|
+
export class ListMessagingCandidatesResponse {
|
|
5
|
+
items!: MessagingCandidateItem[];
|
|
6
|
+
|
|
7
|
+
/** Cursor de la siguiente página. `null` significa que ya no queda nadie — nunca `undefined`. */
|
|
8
|
+
nextCursor!: string | null;
|
|
9
|
+
}
|
package/src/loanCredit/index.ts
CHANGED
|
@@ -98,3 +98,13 @@ export * from './dtos/responses/LoanDeviceReleaseResult';
|
|
|
98
98
|
export * from './dtos/responses/LoanDeviceReleaseResponse';
|
|
99
99
|
|
|
100
100
|
export * from './validators/IsFutureIso8601DateTime';
|
|
101
|
+
|
|
102
|
+
// Candidatos de mensajería — contrato de `POST /private/messaging/candidates`
|
|
103
|
+
// Re-export del enum canónico del momento (owner: messagesConnector — un solo origen de verdad).
|
|
104
|
+
export { MessagingSlotEnum } from '../messagesConnector/enums/MessagingSlotEnum';
|
|
105
|
+
export * from './constants/MessagingCandidateLimits';
|
|
106
|
+
export * from './constants/StoreDayPattern';
|
|
107
|
+
export * from './dtos/MessagingCandidateItem';
|
|
108
|
+
export * from './dtos/requests/ListMessagingCandidatesRequest';
|
|
109
|
+
export * from './dtos/responses/ListMessagingCandidatesResponse';
|
|
110
|
+
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Expose } from "class-transformer";
|
|
2
|
-
import { IsString, IsNotEmpty, IsEnum, IsOptional } from "class-validator";
|
|
2
|
+
import { IsString, IsNotEmpty, IsEnum, IsOptional, MaxLength } from "class-validator";
|
|
3
3
|
import { DeviceNotifyIntensityEnum } from "../enums/DeviceNotifyIntensityEnum";
|
|
4
4
|
import { MdmNoticeTypeEnum } from "../enums/MdmNoticeTypeEnum";
|
|
5
5
|
|
|
@@ -27,6 +27,7 @@ export class DeviceNotifyRequest {
|
|
|
27
27
|
@IsOptional()
|
|
28
28
|
@IsString()
|
|
29
29
|
@IsNotEmpty()
|
|
30
|
+
@MaxLength(64)
|
|
30
31
|
notificationCode?: string;
|
|
31
32
|
|
|
32
33
|
/** Título crudo para Trustonic. Camino legacy: solo se lee si no viaja `noticeType`. */
|
|
@@ -34,6 +35,7 @@ export class DeviceNotifyRequest {
|
|
|
34
35
|
@IsOptional()
|
|
35
36
|
@IsString()
|
|
36
37
|
@IsNotEmpty()
|
|
38
|
+
@MaxLength(128)
|
|
37
39
|
title?: string;
|
|
38
40
|
|
|
39
41
|
/** Cuerpo crudo para Trustonic. Camino legacy: solo se lee si no viaja `noticeType`. */
|
|
@@ -41,6 +43,7 @@ export class DeviceNotifyRequest {
|
|
|
41
43
|
@IsOptional()
|
|
42
44
|
@IsString()
|
|
43
45
|
@IsNotEmpty()
|
|
46
|
+
@MaxLength(1024)
|
|
44
47
|
content?: string;
|
|
45
48
|
|
|
46
49
|
@Expose()
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { LOAN_DEVICE_MAX_BATCH } from '../../loanCredit/constants/LoanDeviceBatchLimits';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Mismo tope que el lote de `loan-credit-business`, el único caller del endpoint.
|
|
5
|
+
* Si aquí fuera más chico, un lote que ese endpoint ya aceptó se caería con 400 al llegar a mensajería.
|
|
6
|
+
*/
|
|
7
|
+
export const MDM_NOTIFY_MAX_BATCH = LOAN_DEVICE_MAX_BATCH;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Expose } from 'class-transformer';
|
|
2
|
+
import { IsEnum, IsNotEmpty, IsOptional, IsString, Matches } from 'class-validator';
|
|
3
|
+
import { CREDIT_ID_MESSAGE, CREDIT_ID_PATTERN } from '../../common/constants/CreditIdPattern';
|
|
4
|
+
import { DeviceNotifyIntensityEnum } from '../../mdm/enums/DeviceNotifyIntensityEnum';
|
|
5
|
+
import { MdmNoticeTypeEnum } from '../../mdm/enums/MdmNoticeTypeEnum';
|
|
6
|
+
import { MdmProviderEnum } from '../../mdm/enums/MdmProviderEnum';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Equipo al que se le avisa. El caller dice cuál es el aviso; el texto lo resuelve
|
|
10
|
+
* messages-business contra el catálogo, así que aquí no viajan `title` ni `content`.
|
|
11
|
+
*/
|
|
12
|
+
export class MdmNotifyItem {
|
|
13
|
+
@Expose()
|
|
14
|
+
@IsString()
|
|
15
|
+
@IsNotEmpty()
|
|
16
|
+
imei!: string;
|
|
17
|
+
|
|
18
|
+
@Expose()
|
|
19
|
+
@Matches(CREDIT_ID_PATTERN, { message: CREDIT_ID_MESSAGE })
|
|
20
|
+
creditId!: string;
|
|
21
|
+
|
|
22
|
+
/** Proveedor MDM del equipo: messages-business agrupa por él y hace una llamada por grupo. */
|
|
23
|
+
@Expose()
|
|
24
|
+
@IsEnum(MdmProviderEnum)
|
|
25
|
+
provider!: MdmProviderEnum;
|
|
26
|
+
|
|
27
|
+
/** Id agnóstico del aviso. Es obligatorio: resolverlo contra el catálogo es el punto del endpoint. */
|
|
28
|
+
@Expose()
|
|
29
|
+
@IsEnum(MdmNoticeTypeEnum)
|
|
30
|
+
noticeType!: MdmNoticeTypeEnum;
|
|
31
|
+
|
|
32
|
+
@Expose()
|
|
33
|
+
@IsEnum(DeviceNotifyIntensityEnum)
|
|
34
|
+
intensity!: DeviceNotifyIntensityEnum;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Idioma y país con los que se busca la plantilla del aviso.
|
|
38
|
+
* Ausentes, messages-business cae al par por defecto del tenant.
|
|
39
|
+
*/
|
|
40
|
+
@Expose()
|
|
41
|
+
@IsOptional()
|
|
42
|
+
@IsString()
|
|
43
|
+
@IsNotEmpty()
|
|
44
|
+
language?: string;
|
|
45
|
+
|
|
46
|
+
@Expose()
|
|
47
|
+
@IsOptional()
|
|
48
|
+
@IsString()
|
|
49
|
+
@IsNotEmpty()
|
|
50
|
+
country?: string;
|
|
51
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Expose, Type } from 'class-transformer';
|
|
2
|
+
import { ArrayMaxSize, ArrayNotEmpty, ArrayUnique, IsArray, IsNotEmpty, IsOptional, IsString, MaxLength, ValidateNested } from 'class-validator';
|
|
3
|
+
import { MdmNotifyItem } from './MdmNotifyItem';
|
|
4
|
+
import { MDM_NOTIFY_MAX_BATCH } from '../constants/MdmNotifyBatchLimits';
|
|
5
|
+
|
|
6
|
+
/** Body de `POST /private/messages/mdm-notify` (messages-business). Avisa en lote. */
|
|
7
|
+
export class MdmNotifyRequest {
|
|
8
|
+
/** Un resultado por imei, así que el imei repetido no tiene resultado que devolver. */
|
|
9
|
+
@Expose()
|
|
10
|
+
@IsArray()
|
|
11
|
+
@ArrayNotEmpty()
|
|
12
|
+
@ArrayMaxSize(MDM_NOTIFY_MAX_BATCH)
|
|
13
|
+
@ArrayUnique((item: MdmNotifyItem) => item.imei)
|
|
14
|
+
@ValidateNested({ each: true })
|
|
15
|
+
@Type(() => MdmNotifyItem)
|
|
16
|
+
items!: MdmNotifyItem[];
|
|
17
|
+
|
|
18
|
+
/** Tenant emisor del aviso. Si se omite, messages-business asume FIADO. */
|
|
19
|
+
@Expose()
|
|
20
|
+
@IsOptional()
|
|
21
|
+
@IsString()
|
|
22
|
+
@IsNotEmpty()
|
|
23
|
+
tenantId?: string;
|
|
24
|
+
|
|
25
|
+
/** Referencia con la que el caller correlaciona este batch. */
|
|
26
|
+
@Expose()
|
|
27
|
+
@IsString()
|
|
28
|
+
@IsNotEmpty()
|
|
29
|
+
@MaxLength(64)
|
|
30
|
+
operationReference!: string;
|
|
31
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { MdmError } from '../../mdm/dtos/MdmError';
|
|
2
|
+
import { MdmOperationStatusEnum } from '../../mdm/enums/MdmOperationStatusEnum';
|
|
3
|
+
|
|
4
|
+
/** Resultado por equipo del aviso en lote. `error` solo viaja cuando el status es ERROR. */
|
|
5
|
+
export class MdmNotifyResponse {
|
|
6
|
+
imei!: string;
|
|
7
|
+
|
|
8
|
+
creditId!: string;
|
|
9
|
+
|
|
10
|
+
status!: MdmOperationStatusEnum;
|
|
11
|
+
|
|
12
|
+
/** Momento en que el proveedor aceptó el aviso, en ISO-8601. */
|
|
13
|
+
sentAt?: string;
|
|
14
|
+
|
|
15
|
+
error?: MdmError;
|
|
16
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Momento del día en que corre una agenda de mensajería.
|
|
3
|
+
* Es el nombre del momento, nunca la hora: la hora vive en la agenda de cada tenant y cambia sin desplegar.
|
|
4
|
+
*/
|
|
5
|
+
export enum MessagingSlotEnum {
|
|
6
|
+
MORNING = 'MORNING',
|
|
7
|
+
AFTERNOON = 'AFTERNOON',
|
|
8
|
+
EVENING = 'EVENING',
|
|
9
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './enums/DeliveryChannelExtendedEnum';
|
|
2
2
|
export * from './enums/NotificationOriginEnum';
|
|
3
|
+
export * from './enums/MessagingSlotEnum';
|
|
3
4
|
export * from './validators/IsStringValueRecord';
|
|
4
5
|
export * from './dtos/NotificationQueueMessageRequestV2';
|
|
5
6
|
export * from './dtos/SendMessageRequest';
|
|
@@ -19,3 +20,8 @@ export * from './dtos/TemplateMessageUpdateRequest';
|
|
|
19
20
|
export * from './dtos/TemplateMessageResponse';
|
|
20
21
|
export * from './dtos/TemplateMessageListResponse';
|
|
21
22
|
export * from './dtos/TemplateMessageListFiltersRequest';
|
|
23
|
+
export * from './constants/MdmNotifyBatchLimits';
|
|
24
|
+
export * from './dtos/MdmNotifyItem';
|
|
25
|
+
export * from './dtos/MdmNotifyRequest';
|
|
26
|
+
export * from './dtos/MdmNotifyResponse';
|
|
27
|
+
export * from './dtos/MdmNotifyBatchResponse';
|