@fiado/type-kit 3.412.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.
@@ -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
+ });
@@ -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,5 @@
1
+ /**
2
+ * Mismo tope que el lote de `loan-credit-business`, el único caller del endpoint.
3
+ * Si aquí fuera más chico, un lote que ese endpoint ya aceptó se caería con 400 al llegar a mensajería.
4
+ */
5
+ export declare const MDM_NOTIFY_MAX_BATCH = 500;
@@ -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,5 @@
1
+ import { MdmNotifyResponse } from './MdmNotifyResponse';
2
+ /** Response de `POST /private/messages/mdm-notify`. Un resultado por ítem enviado. */
3
+ export declare class MdmNotifyBatchResponse {
4
+ results: MdmNotifyResponse[];
5
+ }
@@ -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;
@@ -20,3 +20,8 @@ export * from './dtos/TemplateMessageUpdateRequest';
20
20
  export * from './dtos/TemplateMessageResponse';
21
21
  export * from './dtos/TemplateMessageListResponse';
22
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';
@@ -36,3 +36,8 @@ __exportStar(require("./dtos/TemplateMessageUpdateRequest"), exports);
36
36
  __exportStar(require("./dtos/TemplateMessageResponse"), exports);
37
37
  __exportStar(require("./dtos/TemplateMessageListResponse"), exports);
38
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fiado/type-kit",
3
- "version": "3.412.0",
3
+ "version": "3.413.0",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "types": "bin/index.d.ts",
@@ -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,6 @@
1
+ import { MdmNotifyResponse } from './MdmNotifyResponse';
2
+
3
+ /** Response de `POST /private/messages/mdm-notify`. Un resultado por ítem enviado. */
4
+ export class MdmNotifyBatchResponse {
5
+ results!: MdmNotifyResponse[];
6
+ }
@@ -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
+ }
@@ -20,3 +20,8 @@ export * from './dtos/TemplateMessageUpdateRequest';
20
20
  export * from './dtos/TemplateMessageResponse';
21
21
  export * from './dtos/TemplateMessageListResponse';
22
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';