@fiado/type-kit 3.73.0 → 3.75.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/platformRbac/dtos/CreateTenantRequest.test.ts +14 -0
- package/_test_/unit/platformRbac/tenantTypes.test.ts +22 -2
- package/bin/platformRbac/dtos/CreateTenantRequest.d.ts +3 -0
- package/bin/platformRbac/dtos/CreateTenantRequest.js +7 -0
- package/bin/platformRbac/enums/PermissionScope.d.ts +5 -3
- package/bin/platformRbac/enums/PermissionScope.js +4 -2
- package/bin/platformRbac/tenantTypes.d.ts +2 -1
- package/bin/platformRbac/tenantTypes.js +7 -0
- package/bin/riskProfile/dtos/private/ClientFinancialHistoryResponse.d.ts +19 -0
- package/bin/riskProfile/dtos/private/ClientFinancialHistoryResponse.js +72 -0
- package/bin/riskProfile/dtos/private/CreateClientFinancialHistoryRequest.d.ts +18 -0
- package/bin/riskProfile/dtos/private/CreateClientFinancialHistoryRequest.js +67 -0
- package/bin/riskProfile/dtos/private/ListClientFinancialHistoryResponse.d.ts +9 -0
- package/bin/riskProfile/dtos/private/ListClientFinancialHistoryResponse.js +28 -0
- package/bin/riskProfile/index.d.ts +3 -0
- package/bin/riskProfile/index.js +3 -0
- package/package.json +1 -1
- package/src/platformRbac/dtos/CreateTenantRequest.ts +3 -0
- package/src/platformRbac/enums/PermissionScope.ts +4 -2
- package/src/platformRbac/tenantTypes.ts +7 -0
- package/src/riskProfile/dtos/private/ClientFinancialHistoryResponse.ts +21 -0
- package/src/riskProfile/dtos/private/CreateClientFinancialHistoryRequest.ts +53 -0
- package/src/riskProfile/dtos/private/ListClientFinancialHistoryResponse.ts +11 -0
- package/src/riskProfile/index.ts +3 -0
|
@@ -2,6 +2,7 @@ import 'reflect-metadata';
|
|
|
2
2
|
import { plainToInstance } from 'class-transformer';
|
|
3
3
|
import { validate } from 'class-validator';
|
|
4
4
|
import { CreateTenantRequest } from '../../../../src/platformRbac/dtos/CreateTenantRequest';
|
|
5
|
+
import { TenantType } from '../../../../src/platformRbac/tenantTypes';
|
|
5
6
|
|
|
6
7
|
describe('CreateTenantRequest', () => {
|
|
7
8
|
const valid = {
|
|
@@ -53,6 +54,19 @@ describe('CreateTenantRequest', () => {
|
|
|
53
54
|
expect(errors.some(e => e.property === 'passwordMinLength')).toBe(true);
|
|
54
55
|
});
|
|
55
56
|
|
|
57
|
+
it('valida con tenantType opcional = agents', async () => {
|
|
58
|
+
const dto = plainToInstance(CreateTenantRequest, { ...valid, tenantType: 'agents' });
|
|
59
|
+
const errors = await validate(dto);
|
|
60
|
+
expect(errors).toEqual([]);
|
|
61
|
+
expect(dto.tenantType).toBe(TenantType.AGENTS);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('falla si tenantType no es un TenantType válido', async () => {
|
|
65
|
+
const dto = plainToInstance(CreateTenantRequest, { ...valid, tenantType: 'inexistente' });
|
|
66
|
+
const errors = await validate(dto);
|
|
67
|
+
expect(errors.some(e => e.property === 'tenantType')).toBe(true);
|
|
68
|
+
});
|
|
69
|
+
|
|
56
70
|
it('NO expone temporaryPassword en el request (campo del response, no del body)', () => {
|
|
57
71
|
// El request NO debe llevar temporaryPassword (es solo del response, fallback out-of-band F-11).
|
|
58
72
|
// Con excludeExtraneousValues solo sobreviven las props @Expose() del DTO → el contrato lo excluye.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TenantType, levelsOf, tableSuffixForLevel, scopeRankOrder } from '../../../src/platformRbac/tenantTypes';
|
|
1
|
+
import { TenantType, TENANT_TYPES, levelsOf, tableSuffixForLevel, scopeRankOrder } from '../../../src/platformRbac/tenantTypes';
|
|
2
2
|
import { PermissionScope } from '../../../src/platformRbac/enums/PermissionScope';
|
|
3
3
|
|
|
4
4
|
describe('tenantTypes', () => {
|
|
@@ -6,12 +6,13 @@ describe('tenantTypes', () => {
|
|
|
6
6
|
expect(levelsOf(TenantType.RETAIL)).toEqual([PermissionScope.RETAILER, PermissionScope.STORE]);
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
-
it('scopeRankOrder = [PLATFORM, TENANT, RETAILER, STORE] (retail
|
|
9
|
+
it('scopeRankOrder = [PLATFORM, TENANT, RETAILER, STORE, GROUP] (retail + agents)', () => {
|
|
10
10
|
expect(scopeRankOrder()).toEqual([
|
|
11
11
|
PermissionScope.PLATFORM,
|
|
12
12
|
PermissionScope.TENANT,
|
|
13
13
|
PermissionScope.RETAILER,
|
|
14
14
|
PermissionScope.STORE,
|
|
15
|
+
PermissionScope.GROUP,
|
|
15
16
|
]);
|
|
16
17
|
});
|
|
17
18
|
|
|
@@ -29,4 +30,23 @@ describe('tenantTypes', () => {
|
|
|
29
30
|
const order = scopeRankOrder();
|
|
30
31
|
expect(new Set(order).size).toBe(order.length);
|
|
31
32
|
});
|
|
33
|
+
|
|
34
|
+
it('agents define un único nivel GROUP debajo de TENANT', () => {
|
|
35
|
+
expect(levelsOf(TenantType.AGENTS)).toEqual([PermissionScope.GROUP]);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('agents mapea GROUP a su sufijo de tabla SharedGroup', () => {
|
|
39
|
+
expect(TENANT_TYPES[TenantType.AGENTS].tableSuffix).toEqual({ [PermissionScope.GROUP]: 'SharedGroup' });
|
|
40
|
+
expect(tableSuffixForLevel(TenantType.AGENTS, PermissionScope.GROUP)).toBe('SharedGroup');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('scopeRankOrder incluye GROUP al final (vía los levels de agents, después de los de retail)', () => {
|
|
44
|
+
expect(scopeRankOrder()).toEqual([
|
|
45
|
+
PermissionScope.PLATFORM,
|
|
46
|
+
PermissionScope.TENANT,
|
|
47
|
+
PermissionScope.RETAILER,
|
|
48
|
+
PermissionScope.STORE,
|
|
49
|
+
PermissionScope.GROUP,
|
|
50
|
+
]);
|
|
51
|
+
});
|
|
32
52
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { TokenValidationMode } from '../enums/TokenValidationMode';
|
|
2
|
+
import { TenantType } from '../tenantTypes';
|
|
2
3
|
/**
|
|
3
4
|
* Input del POST backoffice de creación de tenant (F-11 — onboarding de tenant en SureKeep).
|
|
4
5
|
* Consumido por el controller `backofficeCreateTenant` del platform-rbac-business y, a futuro,
|
|
@@ -16,4 +17,6 @@ export declare class CreateTenantRequest {
|
|
|
16
17
|
mfaRequired?: boolean;
|
|
17
18
|
passwordMinLength?: number;
|
|
18
19
|
tokenValidationMode?: TokenValidationMode;
|
|
20
|
+
/** Tipo de tenant a crear. Si se omite, el onboarding aplica su default (hoy: retail). */
|
|
21
|
+
tenantType?: TenantType;
|
|
19
22
|
}
|
|
@@ -13,6 +13,7 @@ exports.CreateTenantRequest = void 0;
|
|
|
13
13
|
const class_transformer_1 = require("class-transformer");
|
|
14
14
|
const class_validator_1 = require("class-validator");
|
|
15
15
|
const TokenValidationMode_1 = require("../enums/TokenValidationMode");
|
|
16
|
+
const tenantTypes_1 = require("../tenantTypes");
|
|
16
17
|
/**
|
|
17
18
|
* Input del POST backoffice de creación de tenant (F-11 — onboarding de tenant en SureKeep).
|
|
18
19
|
* Consumido por el controller `backofficeCreateTenant` del platform-rbac-business y, a futuro,
|
|
@@ -73,3 +74,9 @@ __decorate([
|
|
|
73
74
|
(0, class_validator_1.IsEnum)(TokenValidationMode_1.TokenValidationMode),
|
|
74
75
|
__metadata("design:type", String)
|
|
75
76
|
], CreateTenantRequest.prototype, "tokenValidationMode", void 0);
|
|
77
|
+
__decorate([
|
|
78
|
+
(0, class_transformer_1.Expose)(),
|
|
79
|
+
(0, class_validator_1.IsOptional)(),
|
|
80
|
+
(0, class_validator_1.IsEnum)(tenantTypes_1.TenantType),
|
|
81
|
+
__metadata("design:type", String)
|
|
82
|
+
], CreateTenantRequest.prototype, "tenantType", void 0);
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Jerarquía: PLATFORM > TENANT > RETAILER > STORE.
|
|
3
|
-
*
|
|
2
|
+
* Jerarquía retail: PLATFORM > TENANT > RETAILER > STORE.
|
|
3
|
+
* Jerarquía agents: PLATFORM > TENANT > GROUP.
|
|
4
|
+
* Componente 01 spec.
|
|
4
5
|
*/
|
|
5
6
|
export declare enum PermissionScope {
|
|
6
7
|
PLATFORM = "PLATFORM",
|
|
7
8
|
TENANT = "TENANT",
|
|
8
9
|
RETAILER = "RETAILER",
|
|
9
|
-
STORE = "STORE"
|
|
10
|
+
STORE = "STORE",
|
|
11
|
+
GROUP = "GROUP"
|
|
10
12
|
}
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PermissionScope = void 0;
|
|
4
4
|
/**
|
|
5
|
-
* Jerarquía: PLATFORM > TENANT > RETAILER > STORE.
|
|
6
|
-
*
|
|
5
|
+
* Jerarquía retail: PLATFORM > TENANT > RETAILER > STORE.
|
|
6
|
+
* Jerarquía agents: PLATFORM > TENANT > GROUP.
|
|
7
|
+
* Componente 01 spec.
|
|
7
8
|
*/
|
|
8
9
|
var PermissionScope;
|
|
9
10
|
(function (PermissionScope) {
|
|
@@ -11,4 +12,5 @@ var PermissionScope;
|
|
|
11
12
|
PermissionScope["TENANT"] = "TENANT";
|
|
12
13
|
PermissionScope["RETAILER"] = "RETAILER";
|
|
13
14
|
PermissionScope["STORE"] = "STORE";
|
|
15
|
+
PermissionScope["GROUP"] = "GROUP";
|
|
14
16
|
})(PermissionScope || (exports.PermissionScope = PermissionScope = {}));
|
|
@@ -4,7 +4,8 @@ import { PermissionScope } from './enums/PermissionScope';
|
|
|
4
4
|
* jerarquía de niveles DEBAJO de TENANT (data-driven). Hoy solo existe `retail`.
|
|
5
5
|
*/
|
|
6
6
|
export declare enum TenantType {
|
|
7
|
-
RETAIL = "retail"
|
|
7
|
+
RETAIL = "retail",
|
|
8
|
+
AGENTS = "agents"
|
|
8
9
|
}
|
|
9
10
|
interface TenantTypeDef {
|
|
10
11
|
displayName: string;
|
|
@@ -12,6 +12,7 @@ const PermissionScope_1 = require("./enums/PermissionScope");
|
|
|
12
12
|
var TenantType;
|
|
13
13
|
(function (TenantType) {
|
|
14
14
|
TenantType["RETAIL"] = "retail";
|
|
15
|
+
TenantType["AGENTS"] = "agents";
|
|
15
16
|
})(TenantType || (exports.TenantType = TenantType = {}));
|
|
16
17
|
exports.TENANT_TYPES = {
|
|
17
18
|
[TenantType.RETAIL]: {
|
|
@@ -22,6 +23,12 @@ exports.TENANT_TYPES = {
|
|
|
22
23
|
[PermissionScope_1.PermissionScope.STORE]: 'SharedStore',
|
|
23
24
|
},
|
|
24
25
|
},
|
|
26
|
+
// Fiado Agents — un único nivel GROUP debajo de TENANT.
|
|
27
|
+
[TenantType.AGENTS]: {
|
|
28
|
+
displayName: 'Agents',
|
|
29
|
+
levels: [PermissionScope_1.PermissionScope.GROUP],
|
|
30
|
+
tableSuffix: { [PermissionScope_1.PermissionScope.GROUP]: 'SharedGroup' },
|
|
31
|
+
},
|
|
25
32
|
};
|
|
26
33
|
function levelsOf(type) {
|
|
27
34
|
return exports.TENANT_TYPES[type].levels;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Item del historial financiero del perfil (tabla `ClientFinancialHistory_GT`).
|
|
3
|
+
* Shape que consume el Dashboard para reconstruir la timeline del perfil.
|
|
4
|
+
*/
|
|
5
|
+
export declare class ClientFinancialHistoryResponse {
|
|
6
|
+
directoryId: string;
|
|
7
|
+
sk: string;
|
|
8
|
+
eventId: string;
|
|
9
|
+
eventType: string;
|
|
10
|
+
field: string;
|
|
11
|
+
before?: number | null;
|
|
12
|
+
after?: number | null;
|
|
13
|
+
triggeredBy: string;
|
|
14
|
+
createdBy: string;
|
|
15
|
+
updatedBy?: string;
|
|
16
|
+
reason?: string;
|
|
17
|
+
tenantId: string;
|
|
18
|
+
createdAt: number;
|
|
19
|
+
}
|
|
@@ -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.ClientFinancialHistoryResponse = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
/**
|
|
15
|
+
* Item del historial financiero del perfil (tabla `ClientFinancialHistory_GT`).
|
|
16
|
+
* Shape que consume el Dashboard para reconstruir la timeline del perfil.
|
|
17
|
+
*/
|
|
18
|
+
class ClientFinancialHistoryResponse {
|
|
19
|
+
}
|
|
20
|
+
exports.ClientFinancialHistoryResponse = ClientFinancialHistoryResponse;
|
|
21
|
+
__decorate([
|
|
22
|
+
(0, class_transformer_1.Expose)(),
|
|
23
|
+
__metadata("design:type", String)
|
|
24
|
+
], ClientFinancialHistoryResponse.prototype, "directoryId", void 0);
|
|
25
|
+
__decorate([
|
|
26
|
+
(0, class_transformer_1.Expose)(),
|
|
27
|
+
__metadata("design:type", String)
|
|
28
|
+
], ClientFinancialHistoryResponse.prototype, "sk", void 0);
|
|
29
|
+
__decorate([
|
|
30
|
+
(0, class_transformer_1.Expose)(),
|
|
31
|
+
__metadata("design:type", String)
|
|
32
|
+
], ClientFinancialHistoryResponse.prototype, "eventId", void 0);
|
|
33
|
+
__decorate([
|
|
34
|
+
(0, class_transformer_1.Expose)(),
|
|
35
|
+
__metadata("design:type", String)
|
|
36
|
+
], ClientFinancialHistoryResponse.prototype, "eventType", void 0);
|
|
37
|
+
__decorate([
|
|
38
|
+
(0, class_transformer_1.Expose)(),
|
|
39
|
+
__metadata("design:type", String)
|
|
40
|
+
], ClientFinancialHistoryResponse.prototype, "field", void 0);
|
|
41
|
+
__decorate([
|
|
42
|
+
(0, class_transformer_1.Expose)(),
|
|
43
|
+
__metadata("design:type", Number)
|
|
44
|
+
], ClientFinancialHistoryResponse.prototype, "before", void 0);
|
|
45
|
+
__decorate([
|
|
46
|
+
(0, class_transformer_1.Expose)(),
|
|
47
|
+
__metadata("design:type", Number)
|
|
48
|
+
], ClientFinancialHistoryResponse.prototype, "after", void 0);
|
|
49
|
+
__decorate([
|
|
50
|
+
(0, class_transformer_1.Expose)(),
|
|
51
|
+
__metadata("design:type", String)
|
|
52
|
+
], ClientFinancialHistoryResponse.prototype, "triggeredBy", void 0);
|
|
53
|
+
__decorate([
|
|
54
|
+
(0, class_transformer_1.Expose)(),
|
|
55
|
+
__metadata("design:type", String)
|
|
56
|
+
], ClientFinancialHistoryResponse.prototype, "createdBy", void 0);
|
|
57
|
+
__decorate([
|
|
58
|
+
(0, class_transformer_1.Expose)(),
|
|
59
|
+
__metadata("design:type", String)
|
|
60
|
+
], ClientFinancialHistoryResponse.prototype, "updatedBy", void 0);
|
|
61
|
+
__decorate([
|
|
62
|
+
(0, class_transformer_1.Expose)(),
|
|
63
|
+
__metadata("design:type", String)
|
|
64
|
+
], ClientFinancialHistoryResponse.prototype, "reason", void 0);
|
|
65
|
+
__decorate([
|
|
66
|
+
(0, class_transformer_1.Expose)(),
|
|
67
|
+
__metadata("design:type", String)
|
|
68
|
+
], ClientFinancialHistoryResponse.prototype, "tenantId", void 0);
|
|
69
|
+
__decorate([
|
|
70
|
+
(0, class_transformer_1.Expose)(),
|
|
71
|
+
__metadata("design:type", Number)
|
|
72
|
+
], ClientFinancialHistoryResponse.prototype, "createdAt", void 0);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request para registrar un cambio en el historial financiero del perfil
|
|
3
|
+
* (tabla `ClientFinancialHistory_GT`). Audit log append-only — BO-03,
|
|
4
|
+
* Manual de Cumplimiento sec. 8.25 / Art. 24 (retención 10 años).
|
|
5
|
+
*
|
|
6
|
+
* El caller manda SOLO el cambio de negocio. El servidor deriva los campos
|
|
7
|
+
* meta/audit (`sk`, `eventId`, `eventType`, `triggeredBy`, `createdAt`), de
|
|
8
|
+
* modo que nadie pueda falsificar el timestamp ni el origen.
|
|
9
|
+
*/
|
|
10
|
+
export declare class CreateClientFinancialHistoryRequest {
|
|
11
|
+
directoryId: string;
|
|
12
|
+
field: string;
|
|
13
|
+
before?: number | null;
|
|
14
|
+
after: number | null;
|
|
15
|
+
email: string;
|
|
16
|
+
tenantId: string;
|
|
17
|
+
reason?: string;
|
|
18
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
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.CreateClientFinancialHistoryRequest = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
/**
|
|
16
|
+
* Request para registrar un cambio en el historial financiero del perfil
|
|
17
|
+
* (tabla `ClientFinancialHistory_GT`). Audit log append-only — BO-03,
|
|
18
|
+
* Manual de Cumplimiento sec. 8.25 / Art. 24 (retención 10 años).
|
|
19
|
+
*
|
|
20
|
+
* El caller manda SOLO el cambio de negocio. El servidor deriva los campos
|
|
21
|
+
* meta/audit (`sk`, `eventId`, `eventType`, `triggeredBy`, `createdAt`), de
|
|
22
|
+
* modo que nadie pueda falsificar el timestamp ni el origen.
|
|
23
|
+
*/
|
|
24
|
+
class CreateClientFinancialHistoryRequest {
|
|
25
|
+
}
|
|
26
|
+
exports.CreateClientFinancialHistoryRequest = CreateClientFinancialHistoryRequest;
|
|
27
|
+
__decorate([
|
|
28
|
+
(0, class_transformer_1.Expose)(),
|
|
29
|
+
(0, class_validator_1.IsString)(),
|
|
30
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
31
|
+
__metadata("design:type", String)
|
|
32
|
+
], CreateClientFinancialHistoryRequest.prototype, "directoryId", void 0);
|
|
33
|
+
__decorate([
|
|
34
|
+
(0, class_transformer_1.Expose)(),
|
|
35
|
+
(0, class_validator_1.IsString)(),
|
|
36
|
+
(0, class_validator_1.IsIn)(["declaredMonthlyIncome", "manualRiskLevel", "customHighAmount", "customMonthlyIncrease"]),
|
|
37
|
+
__metadata("design:type", String)
|
|
38
|
+
], CreateClientFinancialHistoryRequest.prototype, "field", void 0);
|
|
39
|
+
__decorate([
|
|
40
|
+
(0, class_transformer_1.Expose)(),
|
|
41
|
+
(0, class_validator_1.IsOptional)(),
|
|
42
|
+
(0, class_validator_1.IsNumber)(),
|
|
43
|
+
__metadata("design:type", Number)
|
|
44
|
+
], CreateClientFinancialHistoryRequest.prototype, "before", void 0);
|
|
45
|
+
__decorate([
|
|
46
|
+
(0, class_transformer_1.Expose)(),
|
|
47
|
+
(0, class_validator_1.ValidateIf)((o) => o.after !== null),
|
|
48
|
+
(0, class_validator_1.IsNumber)(),
|
|
49
|
+
__metadata("design:type", Number)
|
|
50
|
+
], CreateClientFinancialHistoryRequest.prototype, "after", void 0);
|
|
51
|
+
__decorate([
|
|
52
|
+
(0, class_transformer_1.Expose)(),
|
|
53
|
+
(0, class_validator_1.IsEmail)({}, { message: "email debe ser un correo válido" }),
|
|
54
|
+
__metadata("design:type", String)
|
|
55
|
+
], CreateClientFinancialHistoryRequest.prototype, "email", void 0);
|
|
56
|
+
__decorate([
|
|
57
|
+
(0, class_transformer_1.Expose)(),
|
|
58
|
+
(0, class_validator_1.IsString)(),
|
|
59
|
+
(0, class_validator_1.IsIn)(["PAGOCONFIADO", "FIADOSA"]),
|
|
60
|
+
__metadata("design:type", String)
|
|
61
|
+
], CreateClientFinancialHistoryRequest.prototype, "tenantId", void 0);
|
|
62
|
+
__decorate([
|
|
63
|
+
(0, class_transformer_1.Expose)(),
|
|
64
|
+
(0, class_validator_1.IsString)(),
|
|
65
|
+
(0, class_validator_1.IsOptional)(),
|
|
66
|
+
__metadata("design:type", String)
|
|
67
|
+
], CreateClientFinancialHistoryRequest.prototype, "reason", void 0);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ClientFinancialHistoryResponse } from "./ClientFinancialHistoryResponse";
|
|
2
|
+
/**
|
|
3
|
+
* Respuesta paginada del listado por `directoryId`. `continuationToken` es el
|
|
4
|
+
* base64 del `ExclusiveStartKey` de DynamoDB; `null` cuando no hay más páginas.
|
|
5
|
+
*/
|
|
6
|
+
export declare class ListClientFinancialHistoryResponse {
|
|
7
|
+
items: ClientFinancialHistoryResponse[];
|
|
8
|
+
continuationToken?: string | null;
|
|
9
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
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.ListClientFinancialHistoryResponse = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
/**
|
|
15
|
+
* Respuesta paginada del listado por `directoryId`. `continuationToken` es el
|
|
16
|
+
* base64 del `ExclusiveStartKey` de DynamoDB; `null` cuando no hay más páginas.
|
|
17
|
+
*/
|
|
18
|
+
class ListClientFinancialHistoryResponse {
|
|
19
|
+
}
|
|
20
|
+
exports.ListClientFinancialHistoryResponse = ListClientFinancialHistoryResponse;
|
|
21
|
+
__decorate([
|
|
22
|
+
(0, class_transformer_1.Expose)(),
|
|
23
|
+
__metadata("design:type", Array)
|
|
24
|
+
], ListClientFinancialHistoryResponse.prototype, "items", void 0);
|
|
25
|
+
__decorate([
|
|
26
|
+
(0, class_transformer_1.Expose)(),
|
|
27
|
+
__metadata("design:type", String)
|
|
28
|
+
], ListClientFinancialHistoryResponse.prototype, "continuationToken", void 0);
|
|
@@ -37,3 +37,6 @@ export * from './dtos/private/SetCustomAlarmRequest';
|
|
|
37
37
|
export * from './dtos/private/SetCustomAlarmResponse';
|
|
38
38
|
export * from './dtos/private/SetDeclaredIncomeRequest';
|
|
39
39
|
export * from './dtos/private/SetDeclaredIncomeResponse';
|
|
40
|
+
export * from './dtos/private/CreateClientFinancialHistoryRequest';
|
|
41
|
+
export * from './dtos/private/ClientFinancialHistoryResponse';
|
|
42
|
+
export * from './dtos/private/ListClientFinancialHistoryResponse';
|
package/bin/riskProfile/index.js
CHANGED
|
@@ -55,3 +55,6 @@ __exportStar(require("./dtos/private/SetCustomAlarmRequest"), exports);
|
|
|
55
55
|
__exportStar(require("./dtos/private/SetCustomAlarmResponse"), exports);
|
|
56
56
|
__exportStar(require("./dtos/private/SetDeclaredIncomeRequest"), exports);
|
|
57
57
|
__exportStar(require("./dtos/private/SetDeclaredIncomeResponse"), exports);
|
|
58
|
+
__exportStar(require("./dtos/private/CreateClientFinancialHistoryRequest"), exports);
|
|
59
|
+
__exportStar(require("./dtos/private/ClientFinancialHistoryResponse"), exports);
|
|
60
|
+
__exportStar(require("./dtos/private/ListClientFinancialHistoryResponse"), exports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Expose } from 'class-transformer';
|
|
2
2
|
import { IsBoolean, IsEmail, IsEnum, IsInt, IsOptional, IsString, Matches, Min } from 'class-validator';
|
|
3
3
|
import { TokenValidationMode } from '../enums/TokenValidationMode';
|
|
4
|
+
import { TenantType } from '../tenantTypes';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Input del POST backoffice de creación de tenant (F-11 — onboarding de tenant en SureKeep).
|
|
@@ -19,4 +20,6 @@ export class CreateTenantRequest {
|
|
|
19
20
|
@Expose() @IsOptional() @IsBoolean() mfaRequired?: boolean;
|
|
20
21
|
@Expose() @IsOptional() @IsInt() @Min(8) passwordMinLength?: number;
|
|
21
22
|
@Expose() @IsOptional() @IsEnum(TokenValidationMode) tokenValidationMode?: TokenValidationMode;
|
|
23
|
+
/** Tipo de tenant a crear. Si se omite, el onboarding aplica su default (hoy: retail). */
|
|
24
|
+
@Expose() @IsOptional() @IsEnum(TenantType) tenantType?: TenantType;
|
|
22
25
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Jerarquía: PLATFORM > TENANT > RETAILER > STORE.
|
|
3
|
-
*
|
|
2
|
+
* Jerarquía retail: PLATFORM > TENANT > RETAILER > STORE.
|
|
3
|
+
* Jerarquía agents: PLATFORM > TENANT > GROUP.
|
|
4
|
+
* Componente 01 spec.
|
|
4
5
|
*/
|
|
5
6
|
export enum PermissionScope {
|
|
6
7
|
PLATFORM = 'PLATFORM',
|
|
7
8
|
TENANT = 'TENANT',
|
|
8
9
|
RETAILER = 'RETAILER',
|
|
9
10
|
STORE = 'STORE',
|
|
11
|
+
GROUP = 'GROUP',
|
|
10
12
|
}
|
|
@@ -6,6 +6,7 @@ import { PermissionScope } from './enums/PermissionScope';
|
|
|
6
6
|
*/
|
|
7
7
|
export enum TenantType {
|
|
8
8
|
RETAIL = 'retail',
|
|
9
|
+
AGENTS = 'agents',
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
interface TenantTypeDef {
|
|
@@ -25,6 +26,12 @@ export const TENANT_TYPES: Record<TenantType, TenantTypeDef> = {
|
|
|
25
26
|
[PermissionScope.STORE]: 'SharedStore',
|
|
26
27
|
},
|
|
27
28
|
},
|
|
29
|
+
// Fiado Agents — un único nivel GROUP debajo de TENANT.
|
|
30
|
+
[TenantType.AGENTS]: {
|
|
31
|
+
displayName: 'Agents',
|
|
32
|
+
levels: [PermissionScope.GROUP],
|
|
33
|
+
tableSuffix: { [PermissionScope.GROUP]: 'SharedGroup' },
|
|
34
|
+
},
|
|
28
35
|
};
|
|
29
36
|
|
|
30
37
|
export function levelsOf(type: TenantType): PermissionScope[] {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Expose } from "class-transformer";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Item del historial financiero del perfil (tabla `ClientFinancialHistory_GT`).
|
|
5
|
+
* Shape que consume el Dashboard para reconstruir la timeline del perfil.
|
|
6
|
+
*/
|
|
7
|
+
export class ClientFinancialHistoryResponse {
|
|
8
|
+
@Expose() directoryId!: string;
|
|
9
|
+
@Expose() sk!: string;
|
|
10
|
+
@Expose() eventId!: string;
|
|
11
|
+
@Expose() eventType!: string;
|
|
12
|
+
@Expose() field!: string;
|
|
13
|
+
@Expose() before?: number | null;
|
|
14
|
+
@Expose() after?: number | null;
|
|
15
|
+
@Expose() triggeredBy!: string;
|
|
16
|
+
@Expose() createdBy!: string;
|
|
17
|
+
@Expose() updatedBy?: string;
|
|
18
|
+
@Expose() reason?: string;
|
|
19
|
+
@Expose() tenantId!: string;
|
|
20
|
+
@Expose() createdAt!: number;
|
|
21
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Expose } from "class-transformer";
|
|
2
|
+
import { IsEmail, IsIn, IsNotEmpty, IsNumber, IsOptional, IsString, ValidateIf } from "class-validator";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Request para registrar un cambio en el historial financiero del perfil
|
|
6
|
+
* (tabla `ClientFinancialHistory_GT`). Audit log append-only — BO-03,
|
|
7
|
+
* Manual de Cumplimiento sec. 8.25 / Art. 24 (retención 10 años).
|
|
8
|
+
*
|
|
9
|
+
* El caller manda SOLO el cambio de negocio. El servidor deriva los campos
|
|
10
|
+
* meta/audit (`sk`, `eventId`, `eventType`, `triggeredBy`, `createdAt`), de
|
|
11
|
+
* modo que nadie pueda falsificar el timestamp ni el origen.
|
|
12
|
+
*/
|
|
13
|
+
export class CreateClientFinancialHistoryRequest {
|
|
14
|
+
|
|
15
|
+
@Expose()
|
|
16
|
+
@IsString()
|
|
17
|
+
@IsNotEmpty()
|
|
18
|
+
directoryId!: string;
|
|
19
|
+
|
|
20
|
+
// Campo que cambió. Enum acotado a los 4 factores declarados del MVP (§3.2).
|
|
21
|
+
@Expose()
|
|
22
|
+
@IsString()
|
|
23
|
+
@IsIn(["declaredMonthlyIncome", "manualRiskLevel", "customHighAmount", "customMonthlyIncrease"])
|
|
24
|
+
field!: string;
|
|
25
|
+
|
|
26
|
+
// Valor anterior: number, o null/omitido en alta (sin valor previo).
|
|
27
|
+
@Expose()
|
|
28
|
+
@IsOptional()
|
|
29
|
+
@IsNumber()
|
|
30
|
+
before?: number | null;
|
|
31
|
+
|
|
32
|
+
// Valor nuevo: number, o null si es remoción de alarma custom (se audita).
|
|
33
|
+
// ValidateIf fuerza presencia (undefined falla) pero permite null.
|
|
34
|
+
@Expose()
|
|
35
|
+
@ValidateIf((o) => o.after !== null)
|
|
36
|
+
@IsNumber()
|
|
37
|
+
after!: number | null;
|
|
38
|
+
|
|
39
|
+
// Email del OC que hizo el cambio → se persiste como `createdBy`.
|
|
40
|
+
@Expose()
|
|
41
|
+
@IsEmail({}, { message: "email debe ser un correo válido" })
|
|
42
|
+
email!: string;
|
|
43
|
+
|
|
44
|
+
@Expose()
|
|
45
|
+
@IsString()
|
|
46
|
+
@IsIn(["PAGOCONFIADO", "FIADOSA"])
|
|
47
|
+
tenantId!: string;
|
|
48
|
+
|
|
49
|
+
@Expose()
|
|
50
|
+
@IsString()
|
|
51
|
+
@IsOptional()
|
|
52
|
+
reason?: string;
|
|
53
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Expose } from "class-transformer";
|
|
2
|
+
import { ClientFinancialHistoryResponse } from "./ClientFinancialHistoryResponse";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Respuesta paginada del listado por `directoryId`. `continuationToken` es el
|
|
6
|
+
* base64 del `ExclusiveStartKey` de DynamoDB; `null` cuando no hay más páginas.
|
|
7
|
+
*/
|
|
8
|
+
export class ListClientFinancialHistoryResponse {
|
|
9
|
+
@Expose() items!: ClientFinancialHistoryResponse[];
|
|
10
|
+
@Expose() continuationToken?: string | null;
|
|
11
|
+
}
|
package/src/riskProfile/index.ts
CHANGED
|
@@ -42,4 +42,7 @@ export * from './dtos/private/SetCustomAlarmRequest';
|
|
|
42
42
|
export * from './dtos/private/SetCustomAlarmResponse';
|
|
43
43
|
export * from './dtos/private/SetDeclaredIncomeRequest';
|
|
44
44
|
export * from './dtos/private/SetDeclaredIncomeResponse';
|
|
45
|
+
export * from './dtos/private/CreateClientFinancialHistoryRequest';
|
|
46
|
+
export * from './dtos/private/ClientFinancialHistoryResponse';
|
|
47
|
+
export * from './dtos/private/ListClientFinancialHistoryResponse';
|
|
45
48
|
|