@fiado/type-kit 3.584.0 → 3.585.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/UpdateTenantUserEmailRequest.test.ts +24 -0
- package/_test_/unit/platformRbac/enums/__snapshots__/permissionBits.test.ts.snap +2 -1
- package/_test_/unit/platformRbac/enums/apiUserPermission.test.ts +3 -2
- package/_test_/unit/platformRbac/enums/retailIntegrationPermission.test.ts +13 -0
- package/_test_/unit/retailIntegration/reconciliationContracts.test.ts +3 -3
- package/_test_/unit/retailIntegration/retailMovementsContracts.test.ts +109 -0
- package/_test_/unit/retailIntegration/retailSystemResponses.test.ts +120 -0
- package/bin/platformRbac/dtos/CreateTenantUserRequest.d.ts +2 -1
- package/bin/platformRbac/dtos/CreateTenantUserRequest.js +2 -1
- package/bin/platformRbac/dtos/UpdateTenantUserEmailRequest.d.ts +5 -0
- package/bin/platformRbac/dtos/UpdateTenantUserEmailRequest.js +30 -0
- package/bin/platformRbac/enums/Permission.d.ts +2 -1
- package/bin/platformRbac/enums/Permission.js +3 -0
- package/bin/platformRbac/index.d.ts +1 -0
- package/bin/platformRbac/index.js +1 -0
- package/bin/retailIntegration/constants/retailIntegrationLimits.d.ts +11 -0
- package/bin/retailIntegration/constants/retailIntegrationLimits.js +12 -1
- package/bin/retailIntegration/dtos/CheckRetailInventoryRequest.d.ts +4 -1
- package/bin/retailIntegration/dtos/CheckRetailInventoryRequest.js +4 -1
- package/bin/retailIntegration/dtos/GetRetailInventoryRequest.d.ts +3 -3
- package/bin/retailIntegration/dtos/GetRetailInventoryRequest.js +3 -3
- package/bin/retailIntegration/dtos/ListRetailInventoryMovementsRequest.d.ts +6 -0
- package/bin/retailIntegration/dtos/ListRetailInventoryMovementsRequest.js +29 -0
- package/bin/retailIntegration/dtos/ReconciliationPageMessage.d.ts +6 -0
- package/bin/retailIntegration/dtos/ReconciliationPageMessage.js +20 -0
- package/bin/retailIntegration/dtos/RetailOutboundResponses.d.ts +10 -2
- package/bin/retailIntegration/dtos/RetailSystemResponses.d.ts +41 -0
- package/bin/retailIntegration/dtos/RetailSystemResponses.js +136 -0
- package/bin/retailIntegration/enums/ReconciliationEntityEnum.d.ts +2 -1
- package/bin/retailIntegration/enums/ReconciliationEntityEnum.js +1 -0
- package/bin/retailIntegration/enums/ReconciliationTriggerEnum.d.ts +4 -2
- package/bin/retailIntegration/enums/ReconciliationTriggerEnum.js +3 -1
- package/bin/retailIntegration/index.d.ts +3 -0
- package/bin/retailIntegration/index.js +3 -0
- package/bin/retailIntegration/models/RetailPageMeta.d.ts +3 -1
- package/bin/retailIntegration/models/RetailSystemInventory.d.ts +9 -1
- package/bin/retailIntegration/validators/IsMovementsRangeValid.d.ts +6 -0
- package/bin/retailIntegration/validators/IsMovementsRangeValid.js +28 -0
- package/package.json +1 -1
- package/src/platformRbac/dtos/CreateTenantUserRequest.ts +2 -1
- package/src/platformRbac/dtos/UpdateTenantUserEmailRequest.ts +12 -0
- package/src/platformRbac/enums/Permission.ts +3 -0
- package/src/platformRbac/index.ts +1 -0
- package/src/retailIntegration/constants/retailIntegrationLimits.ts +16 -0
- package/src/retailIntegration/dtos/CheckRetailInventoryRequest.ts +4 -1
- package/src/retailIntegration/dtos/GetRetailInventoryRequest.ts +3 -3
- package/src/retailIntegration/dtos/ListRetailInventoryMovementsRequest.ts +14 -0
- package/src/retailIntegration/dtos/ReconciliationPageMessage.ts +21 -1
- package/src/retailIntegration/dtos/RetailOutboundResponses.ts +11 -2
- package/src/retailIntegration/dtos/RetailSystemResponses.ts +75 -0
- package/src/retailIntegration/enums/ReconciliationEntityEnum.ts +1 -0
- package/src/retailIntegration/enums/ReconciliationTriggerEnum.ts +3 -1
- package/src/retailIntegration/index.ts +3 -0
- package/src/retailIntegration/models/RetailPageMeta.ts +3 -1
- package/src/retailIntegration/models/RetailSystemInventory.ts +10 -1
- package/src/retailIntegration/validators/IsMovementsRangeValid.ts +17 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { plainToInstance } from 'class-transformer';
|
|
3
|
+
import { validateSync } from 'class-validator';
|
|
4
|
+
import { UpdateTenantUserEmailRequest } from '../../../../src/platformRbac';
|
|
5
|
+
|
|
6
|
+
function propsWithErrors(payload: object): string[] {
|
|
7
|
+
return validateSync(plainToInstance(UpdateTenantUserEmailRequest, payload)).map((e) => e.property);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
describe('UpdateTenantUserEmailRequest', () => {
|
|
11
|
+
it('normaliza el correo a minúsculas sin espacios', () => {
|
|
12
|
+
const dto = plainToInstance(UpdateTenantUserEmailRequest, { email: ' Ana.Perez@Example.COM ', actedBy: 'retail-org-business' });
|
|
13
|
+
expect(dto.email).toBe('ana.perez@example.com');
|
|
14
|
+
expect(validateSync(dto)).toEqual([]);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it.each([undefined, '', 'no-es-correo', 42])('rechaza email=%p', (email) => {
|
|
18
|
+
expect(propsWithErrors({ email, actedBy: 'retail-org-business' })).toEqual(['email']);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it.each([undefined, '', 7])('rechaza actedBy=%p', (actedBy) => {
|
|
22
|
+
expect(propsWithErrors({ email: 'ana@example.com', actedBy })).toEqual(['actedBy']);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
|
2
2
|
|
|
3
|
-
exports[`PERMISSION_BIT_ORDER PERMS_VERSION es número estable 1`] = `
|
|
3
|
+
exports[`PERMISSION_BIT_ORDER PERMS_VERSION es número estable 1`] = `1071810597`;
|
|
4
4
|
|
|
5
5
|
exports[`PERMISSION_BIT_ORDER append-only: snapshot del ORDEN COMPLETO (rompe ante cualquier reorden/inserción) 1`] = `
|
|
6
6
|
[
|
|
@@ -96,5 +96,6 @@ exports[`PERMISSION_BIT_ORDER append-only: snapshot del ORDEN COMPLETO (rompe an
|
|
|
96
96
|
"platform.integration.key.revoke",
|
|
97
97
|
"tenant.integration.diagnostic",
|
|
98
98
|
"tenant.api_user.manage",
|
|
99
|
+
"platform.retail_integration.activate",
|
|
99
100
|
]
|
|
100
101
|
`;
|
|
@@ -5,7 +5,8 @@ describe('Permiso de administración de usuarios de API', () => {
|
|
|
5
5
|
expect(Permission.TENANT_API_USER_MANAGE).toBe('tenant.api_user.manage');
|
|
6
6
|
});
|
|
7
7
|
|
|
8
|
-
it('
|
|
9
|
-
|
|
8
|
+
it('conserva su bit después de las integraciones M2M (append-only)', () => {
|
|
9
|
+
const index = PERMISSION_BIT_ORDER.indexOf(Permission.TENANT_API_USER_MANAGE);
|
|
10
|
+
expect(PERMISSION_BIT_ORDER[index - 1]).toBe(Permission.TENANT_INTEGRATION_DIAGNOSTIC);
|
|
10
11
|
});
|
|
11
12
|
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Permission, PERMISSION_BIT_ORDER } from '../../../../src/platformRbac/enums/Permission';
|
|
2
|
+
|
|
3
|
+
describe('Permiso de activación de la integración retail', () => {
|
|
4
|
+
it('existe con la llave platform.retail_integration.activate (scope PLATFORM)', () => {
|
|
5
|
+
expect(Permission.PLATFORM_RETAIL_INTEGRATION_ACTIVATE).toBe('platform.retail_integration.activate');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
it('va al FINAL del orden de bits, justo después de tenant.api_user.manage', () => {
|
|
9
|
+
const last = PERMISSION_BIT_ORDER.length - 1;
|
|
10
|
+
expect(PERMISSION_BIT_ORDER[last]).toBe(Permission.PLATFORM_RETAIL_INTEGRATION_ACTIVATE);
|
|
11
|
+
expect(PERMISSION_BIT_ORDER[last - 1]).toBe(Permission.TENANT_API_USER_MANAGE);
|
|
12
|
+
});
|
|
13
|
+
});
|
|
@@ -20,8 +20,8 @@ function propsWithErrors<T extends object>(cls: ClassConstructor<T>, payload: ob
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
describe('enums de la revisión', () => {
|
|
23
|
-
it('ReconciliationEntityEnum trae las
|
|
24
|
-
expect(Object.values(ReconciliationEntityEnum)).toEqual(['STORES', 'USERS', 'CATALOG', 'INVENTORY']);
|
|
23
|
+
it('ReconciliationEntityEnum trae las cinco entidades', () => {
|
|
24
|
+
expect(Object.values(ReconciliationEntityEnum)).toEqual(['STORES', 'USERS', 'CATALOG', 'INVENTORY', 'MOVEMENTS']);
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
it('ReconciliationRunStatusEnum trae los cuatro estados de la corrida', () => {
|
|
@@ -29,7 +29,7 @@ describe('enums de la revisión', () => {
|
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
it('ReconciliationTriggerEnum distingue el reloj del botón', () => {
|
|
32
|
-
expect(Object.values(ReconciliationTriggerEnum)).toEqual(['SCHEDULED', 'MANUAL', 'ACTIVATION']);
|
|
32
|
+
expect(Object.values(ReconciliationTriggerEnum)).toEqual(['SCHEDULED', 'MANUAL', 'ACTIVATION', 'DISCREPANCY', 'DAILY']);
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
it('InactiveReasonEnum distingue la baja de la revisión de la del evento', () => {
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { plainToInstance, type ClassConstructor } from 'class-transformer';
|
|
3
|
+
import { validateSync } from 'class-validator';
|
|
4
|
+
import {
|
|
5
|
+
GetRetailInventoryRequest,
|
|
6
|
+
type GetRetailInventoryResponse,
|
|
7
|
+
ListRetailInventoryMovementsRequest,
|
|
8
|
+
type ListRetailInventoryMovementsResponse,
|
|
9
|
+
ReconciliationEntityEnum,
|
|
10
|
+
ReconciliationPageMessage,
|
|
11
|
+
ReconciliationTriggerEnum,
|
|
12
|
+
} from '../../../src/retailIntegration';
|
|
13
|
+
|
|
14
|
+
function propsWithErrors<T extends object>(cls: ClassConstructor<T>, payload: object): string[] {
|
|
15
|
+
return validateSync(plainToInstance(cls, payload)).map((e) => e.property);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const tenant = { tenantId: 'surekeep', retailerId: 'ret-1' };
|
|
19
|
+
|
|
20
|
+
describe('ListRetailInventoryMovementsRequest', () => {
|
|
21
|
+
const valid = { ...tenant, from: '2026-08-17T19:55:00Z', to: '2026-08-17T21:00:00Z' };
|
|
22
|
+
|
|
23
|
+
it('acepta el rango con y sin paginación', () => {
|
|
24
|
+
expect(propsWithErrors(ListRetailInventoryMovementsRequest, valid)).toEqual([]);
|
|
25
|
+
expect(propsWithErrors(ListRetailInventoryMovementsRequest, { ...valid, limit: '200', nextToken: 'abc', runId: 'run-1' })).toEqual([]);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('acepta un rango de 7 días exactos', () => {
|
|
29
|
+
expect(propsWithErrors(ListRetailInventoryMovementsRequest, { ...tenant, from: '2026-08-10T00:00:00Z', to: '2026-08-17T00:00:00Z' })).toEqual([]);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it.each([
|
|
33
|
+
['to igual a from', '2026-08-17T20:00:00Z', '2026-08-17T20:00:00Z'],
|
|
34
|
+
['to antes de from', '2026-08-17T20:00:00Z', '2026-08-17T19:00:00Z'],
|
|
35
|
+
['más de 7 días', '2026-08-10T00:00:00Z', '2026-08-17T00:00:01Z'],
|
|
36
|
+
])('rechaza %s', (_label, from, to) => {
|
|
37
|
+
expect(propsWithErrors(ListRetailInventoryMovementsRequest, { ...tenant, from, to })).toEqual(['to']);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it.each(['from', 'to'])('rechaza sin %s o con fecha sin zona', (field) => {
|
|
41
|
+
const payload: Record<string, unknown> = { ...valid };
|
|
42
|
+
delete payload[field];
|
|
43
|
+
expect(propsWithErrors(ListRetailInventoryMovementsRequest, payload)).toContain(field);
|
|
44
|
+
expect(propsWithErrors(ListRetailInventoryMovementsRequest, { ...valid, [field]: '2026-08-17T20:00:00' })).toContain(field);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it.each(['0', '201'])('rechaza limit=%p', (limit) => {
|
|
48
|
+
expect(propsWithErrors(ListRetailInventoryMovementsRequest, { ...valid, limit })).toEqual(['limit']);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('la respuesta trae items y meta de página', () => {
|
|
52
|
+
const response: ListRetailInventoryMovementsResponse = {
|
|
53
|
+
items: [
|
|
54
|
+
{
|
|
55
|
+
eventId: 'evt-1',
|
|
56
|
+
eventType: 'InventoryMovementV1',
|
|
57
|
+
occurredAt: '2026-08-17T20:32:07Z',
|
|
58
|
+
payload: { movementType: 'SALE', storeId: '12', targetStoreId: null, pieces: [], stock: [] },
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
meta: { count: 1, nextToken: null },
|
|
62
|
+
};
|
|
63
|
+
expect(response.meta.nextToken).toBeNull();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('GetRetailInventoryRequest paginado', () => {
|
|
68
|
+
it('acepta limit y nextToken opcionales', () => {
|
|
69
|
+
expect(propsWithErrors(GetRetailInventoryRequest, { ...tenant, storeId: '12', limit: '50', nextToken: 'abc' })).toEqual([]);
|
|
70
|
+
expect(propsWithErrors(GetRetailInventoryRequest, { ...tenant, storeId: '12', limit: '0' })).toEqual(['limit']);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('la respuesta admite meta.count y meta.nextToken', () => {
|
|
74
|
+
const response: GetRetailInventoryResponse = {
|
|
75
|
+
pieces: [],
|
|
76
|
+
stock: [],
|
|
77
|
+
meta: { storeId: '12', generatedAt: '2026-08-17T15:00:00Z', count: 0, nextToken: null },
|
|
78
|
+
};
|
|
79
|
+
expect(response.meta.count).toBe(0);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe('enums de revisión para movimientos', () => {
|
|
84
|
+
it('ReconciliationEntityEnum suma MOVEMENTS', () => {
|
|
85
|
+
expect(ReconciliationEntityEnum.MOVEMENTS).toBe('MOVEMENTS');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('ReconciliationTriggerEnum suma DISCREPANCY y DAILY', () => {
|
|
89
|
+
expect(ReconciliationTriggerEnum.DISCREPANCY).toBe('DISCREPANCY');
|
|
90
|
+
expect(ReconciliationTriggerEnum.DAILY).toBe('DAILY');
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe('ReconciliationPageMessage con cursor y rango', () => {
|
|
95
|
+
const base = { ...tenant, runId: 'run-1', pageIndex: 0 };
|
|
96
|
+
|
|
97
|
+
it('acepta nextToken en inventario y from/to en movimientos', () => {
|
|
98
|
+
expect(propsWithErrors(ReconciliationPageMessage, { ...base, entity: 'INVENTORY', storeId: '12', nextToken: 'abc' })).toEqual([]);
|
|
99
|
+
expect(
|
|
100
|
+
propsWithErrors(ReconciliationPageMessage, { ...base, entity: 'MOVEMENTS', from: '2026-08-17T19:55:00Z', to: '2026-08-17T21:00:00Z' }),
|
|
101
|
+
).toEqual([]);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('rechaza nextToken vacío y fechas sin zona', () => {
|
|
105
|
+
expect(propsWithErrors(ReconciliationPageMessage, { ...base, entity: 'INVENTORY', nextToken: '' })).toEqual(['nextToken']);
|
|
106
|
+
expect(propsWithErrors(ReconciliationPageMessage, { ...base, entity: 'MOVEMENTS', from: '2026-08-17' })).toEqual(['from']);
|
|
107
|
+
expect(propsWithErrors(ReconciliationPageMessage, { ...base, entity: 'MOVEMENTS', to: 'ayer' })).toEqual(['to']);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { plainToInstance, type ClassConstructor } from 'class-transformer';
|
|
3
|
+
import { validateSync, type ValidationError } from 'class-validator';
|
|
4
|
+
import {
|
|
5
|
+
RetailSystemErrorBody,
|
|
6
|
+
RetailSystemInventoryResponse,
|
|
7
|
+
RetailSystemMovementsResponse,
|
|
8
|
+
RetailSystemPageMeta,
|
|
9
|
+
RetailSystemPageResponse,
|
|
10
|
+
RetailSystemSaleResponse,
|
|
11
|
+
} from '../../../src/retailIntegration';
|
|
12
|
+
|
|
13
|
+
function errorPaths(errors: ValidationError[], prefix = ''): string[] {
|
|
14
|
+
return errors.flatMap((error) => {
|
|
15
|
+
const path = prefix ? `${prefix}.${error.property}` : error.property;
|
|
16
|
+
return error.children?.length ? errorPaths(error.children, path) : [path];
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function pathsWithErrors<T extends object>(cls: ClassConstructor<T>, payload: object): string[] {
|
|
21
|
+
return errorPaths(validateSync(plainToInstance(cls, payload)));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const movement = {
|
|
25
|
+
eventId: 'evt_01J8ZE5M8Y2Q4R7T1V3W6X8Z1C',
|
|
26
|
+
eventType: 'InventoryMovementV1',
|
|
27
|
+
occurredAt: '2026-08-17T20:32:07Z',
|
|
28
|
+
payload: { movementType: 'SALE', storeId: '12', targetStoreId: null, pieces: [], stock: [] },
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
describe('RetailSystemPageMeta', () => {
|
|
32
|
+
it('acepta la última página y una intermedia', () => {
|
|
33
|
+
expect(pathsWithErrors(RetailSystemPageMeta, { count: 0, nextToken: null })).toEqual([]);
|
|
34
|
+
expect(pathsWithErrors(RetailSystemPageMeta, { count: 200, nextToken: 'eyJpZCI6MTQwMH0' })).toEqual([]);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it.each([-1, 1.5, '3', undefined])('rechaza count=%p', (count) => {
|
|
38
|
+
expect(pathsWithErrors(RetailSystemPageMeta, { count, nextToken: null })).toEqual(['count']);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it.each([undefined, 7, 'x'.repeat(2049)])('rechaza nextToken=%p', (nextToken) => {
|
|
42
|
+
expect(pathsWithErrors(RetailSystemPageMeta, { count: 1, nextToken })).toEqual(['nextToken']);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe('RetailSystemPageResponse', () => {
|
|
47
|
+
it('acepta data con renglones crudos', () => {
|
|
48
|
+
expect(pathsWithErrors(RetailSystemPageResponse, { data: [{ any: 'row' }], meta: { count: 1, nextToken: null } })).toEqual([]);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('rechaza data que no es arreglo y meta inválida', () => {
|
|
52
|
+
expect(pathsWithErrors(RetailSystemPageResponse, { data: {}, meta: { count: 1, nextToken: null } })).toEqual(['data']);
|
|
53
|
+
expect(pathsWithErrors(RetailSystemPageResponse, { data: [], meta: { count: -1, nextToken: null } })).toEqual(['meta.count']);
|
|
54
|
+
expect(pathsWithErrors(RetailSystemPageResponse, { data: [] })).toEqual(['meta']);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe('RetailSystemInventoryResponse', () => {
|
|
59
|
+
const valid = {
|
|
60
|
+
data: { pieces: [{ sku: 'SAM-A17' }], stock: [] },
|
|
61
|
+
meta: { storeId: '12', generatedAt: '2026-08-17T15:00:00Z', count: 1, nextToken: null },
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
it('acepta una página del inventario', () => {
|
|
65
|
+
expect(pathsWithErrors(RetailSystemInventoryResponse, valid)).toEqual([]);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('rechaza pieces o stock que no son arreglo', () => {
|
|
69
|
+
expect(pathsWithErrors(RetailSystemInventoryResponse, { ...valid, data: { pieces: null, stock: [] } })).toEqual(['data.pieces']);
|
|
70
|
+
expect(pathsWithErrors(RetailSystemInventoryResponse, { ...valid, data: { pieces: [] } })).toEqual(['data.stock']);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it.each([
|
|
74
|
+
['storeId', 'tienda/12'],
|
|
75
|
+
['generatedAt', '2026-08-17 15:00'],
|
|
76
|
+
['count', -2],
|
|
77
|
+
['nextToken', ''.padEnd(2049, 'a')],
|
|
78
|
+
])('rechaza meta.%s inválido', (field, value) => {
|
|
79
|
+
expect(pathsWithErrors(RetailSystemInventoryResponse, { ...valid, meta: { ...valid.meta, [field]: value } })).toEqual([`meta.${field}`]);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe('RetailSystemSaleResponse', () => {
|
|
84
|
+
it.each(['58812', 'SALE-12_a.b:c', 'a/b#ñ'])('acepta externalSaleId=%p', (externalSaleId) => {
|
|
85
|
+
expect(pathsWithErrors(RetailSystemSaleResponse, { externalSaleId })).toEqual([]);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it.each(['', 'con espacio', ' 58812', 'x'.repeat(65), 58812, undefined])('rechaza externalSaleId=%p', (externalSaleId) => {
|
|
89
|
+
expect(pathsWithErrors(RetailSystemSaleResponse, { externalSaleId })).toEqual(['externalSaleId']);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
describe('RetailSystemErrorBody', () => {
|
|
94
|
+
it('acepta el error con y sin lineIndex', () => {
|
|
95
|
+
expect(pathsWithErrors(RetailSystemErrorBody, { code: 'IDENTIFIER_NOT_AVAILABLE', msg: 'texto', lineIndex: 1 })).toEqual([]);
|
|
96
|
+
expect(pathsWithErrors(RetailSystemErrorBody, { code: 'VALIDATION_ERROR' })).toEqual([]);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('rechaza code ausente o largo y lineIndex fuera de rango', () => {
|
|
100
|
+
expect(pathsWithErrors(RetailSystemErrorBody, {})).toEqual(['code']);
|
|
101
|
+
expect(pathsWithErrors(RetailSystemErrorBody, { code: 'X'.repeat(65) })).toEqual(['code']);
|
|
102
|
+
expect(pathsWithErrors(RetailSystemErrorBody, { code: 'X', lineIndex: 1000 })).toEqual(['lineIndex']);
|
|
103
|
+
expect(pathsWithErrors(RetailSystemErrorBody, { code: 'X', lineIndex: -1 })).toEqual(['lineIndex']);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
describe('RetailSystemMovementsResponse', () => {
|
|
108
|
+
it('acepta movimientos con el sobre del webhook', () => {
|
|
109
|
+
expect(pathsWithErrors(RetailSystemMovementsResponse, { data: [movement], meta: { count: 1, nextToken: null } })).toEqual([]);
|
|
110
|
+
expect(pathsWithErrors(RetailSystemMovementsResponse, { data: [], meta: { count: 0, nextToken: null } })).toEqual([]);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('rechaza un movimiento con sobre inválido', () => {
|
|
114
|
+
const bad = { ...movement, eventType: 'StoreUpsertedV1', occurredAt: '2026-08-17' };
|
|
115
|
+
expect(pathsWithErrors(RetailSystemMovementsResponse, { data: [bad], meta: { count: 1, nextToken: null } }).sort()).toEqual([
|
|
116
|
+
'data.0.eventType',
|
|
117
|
+
'data.0.occurredAt',
|
|
118
|
+
]);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
@@ -6,7 +6,8 @@ import { PermissionScope } from '../enums/PermissionScope';
|
|
|
6
6
|
* Consumido por el alta de usuario orquestada de SureKeep F1 (retail-org → RBAC → RetailUser) vía api-invoker.
|
|
7
7
|
* - Usuario provisionado en estado INVITED (mitiga orphan si el paso siguiente en retail-org falla).
|
|
8
8
|
* - Idempotente por identidad Cognito.
|
|
9
|
-
* - `roleId`/`scope`/`scopeRef`: todos o ninguno; sin rol
|
|
9
|
+
* - `roleId`/`scope`/`scopeRef`: todos o ninguno; sin rol exige `suppressInvitation: true`
|
|
10
|
+
* y la invitación queda pendiente (`invitationPending`) hasta asignar el primer rol.
|
|
10
11
|
* - `createdBy` = cognitoSub del admin real (audit + grantedBy del assignment).
|
|
11
12
|
* - `customFields` = valores de los campos personalizados del tenant; si el correo ya tiene usuario, se fusionan.
|
|
12
13
|
*/
|
|
@@ -23,7 +23,8 @@ const hasAnyGrantField = (o) => o.roleId !== undefined || o.scope !== undefined
|
|
|
23
23
|
* Consumido por el alta de usuario orquestada de SureKeep F1 (retail-org → RBAC → RetailUser) vía api-invoker.
|
|
24
24
|
* - Usuario provisionado en estado INVITED (mitiga orphan si el paso siguiente en retail-org falla).
|
|
25
25
|
* - Idempotente por identidad Cognito.
|
|
26
|
-
* - `roleId`/`scope`/`scopeRef`: todos o ninguno; sin rol
|
|
26
|
+
* - `roleId`/`scope`/`scopeRef`: todos o ninguno; sin rol exige `suppressInvitation: true`
|
|
27
|
+
* y la invitación queda pendiente (`invitationPending`) hasta asignar el primer rol.
|
|
27
28
|
* - `createdBy` = cognitoSub del admin real (audit + grantedBy del assignment).
|
|
28
29
|
* - `customFields` = valores de los campos personalizados del tenant; si el correo ya tiene usuario, se fusionan.
|
|
29
30
|
*/
|
|
@@ -0,0 +1,30 @@
|
|
|
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.UpdateTenantUserEmailRequest = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
/** Body M2M que cambia el correo de un usuario del tenant; el correo se guarda en minúsculas. */
|
|
16
|
+
class UpdateTenantUserEmailRequest {
|
|
17
|
+
}
|
|
18
|
+
exports.UpdateTenantUserEmailRequest = UpdateTenantUserEmailRequest;
|
|
19
|
+
__decorate([
|
|
20
|
+
(0, class_transformer_1.Expose)(),
|
|
21
|
+
(0, class_transformer_1.Transform)(({ value }) => (typeof value === 'string' ? value.trim().toLowerCase() : value)),
|
|
22
|
+
(0, class_validator_1.IsEmail)(),
|
|
23
|
+
__metadata("design:type", String)
|
|
24
|
+
], UpdateTenantUserEmailRequest.prototype, "email", void 0);
|
|
25
|
+
__decorate([
|
|
26
|
+
(0, class_transformer_1.Expose)(),
|
|
27
|
+
(0, class_validator_1.IsString)(),
|
|
28
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
29
|
+
__metadata("design:type", String)
|
|
30
|
+
], UpdateTenantUserEmailRequest.prototype, "actedBy", void 0);
|
|
@@ -120,7 +120,8 @@ export declare enum Permission {
|
|
|
120
120
|
PLATFORM_INTEGRATION_KEY_ISSUE = "platform.integration.key.issue",
|
|
121
121
|
PLATFORM_INTEGRATION_KEY_REVOKE = "platform.integration.key.revoke",
|
|
122
122
|
TENANT_INTEGRATION_DIAGNOSTIC = "tenant.integration.diagnostic",
|
|
123
|
-
TENANT_API_USER_MANAGE = "tenant.api_user.manage"
|
|
123
|
+
TENANT_API_USER_MANAGE = "tenant.api_user.manage",
|
|
124
|
+
PLATFORM_RETAIL_INTEGRATION_ACTIVATE = "platform.retail_integration.activate"
|
|
124
125
|
}
|
|
125
126
|
/**
|
|
126
127
|
* Orden CANÓNICO y APPEND-ONLY de los permisos para el bitset del token.
|
|
@@ -166,6 +166,8 @@ var Permission;
|
|
|
166
166
|
Permission["TENANT_INTEGRATION_DIAGNOSTIC"] = "tenant.integration.diagnostic";
|
|
167
167
|
// Alta, rotación de secreto y edición de IPs de usuarios de API; se exige además de tenant.user.create.
|
|
168
168
|
Permission["TENANT_API_USER_MANAGE"] = "tenant.api_user.manage";
|
|
169
|
+
// Activa la integración de un retailer externo (Zentral); scope PLATFORM.
|
|
170
|
+
Permission["PLATFORM_RETAIL_INTEGRATION_ACTIVATE"] = "platform.retail_integration.activate";
|
|
169
171
|
})(Permission || (exports.Permission = Permission = {}));
|
|
170
172
|
/**
|
|
171
173
|
* Orden CANÓNICO y APPEND-ONLY de los permisos para el bitset del token.
|
|
@@ -286,6 +288,7 @@ exports.PERMISSION_BIT_ORDER = [
|
|
|
286
288
|
Permission.PLATFORM_INTEGRATION_KEY_REVOKE,
|
|
287
289
|
Permission.TENANT_INTEGRATION_DIAGNOSTIC,
|
|
288
290
|
Permission.TENANT_API_USER_MANAGE,
|
|
291
|
+
Permission.PLATFORM_RETAIL_INTEGRATION_ACTIVATE,
|
|
289
292
|
];
|
|
290
293
|
function djb2(input) {
|
|
291
294
|
let h = 5381;
|
|
@@ -73,6 +73,7 @@ export type { ListTenantUsersResponse } from './dtos/ListTenantUsersResponse';
|
|
|
73
73
|
export type { TenantUserListItemResponse } from './dtos/TenantUserListItemResponse';
|
|
74
74
|
export type { GetTenantUserResponse } from './dtos/GetTenantUserResponse';
|
|
75
75
|
export * from './dtos/UpdateTenantUserRequest';
|
|
76
|
+
export * from './dtos/UpdateTenantUserEmailRequest';
|
|
76
77
|
export * from './dtos/DeleteTenantUserRequest';
|
|
77
78
|
export * from './dtos/DisableTenantUserRequest';
|
|
78
79
|
export * from './dtos/EnableTenantUserRequest';
|
|
@@ -120,6 +120,7 @@ __exportStar(require("./dtos/UpdateIntegrationRequest"), exports);
|
|
|
120
120
|
__exportStar(require("./dtos/UpdateLevelEntityRequest"), exports);
|
|
121
121
|
__exportStar(require("./dtos/DeleteLevelEntityRequest"), exports);
|
|
122
122
|
__exportStar(require("./dtos/UpdateTenantUserRequest"), exports);
|
|
123
|
+
__exportStar(require("./dtos/UpdateTenantUserEmailRequest"), exports);
|
|
123
124
|
__exportStar(require("./dtos/DeleteTenantUserRequest"), exports);
|
|
124
125
|
__exportStar(require("./dtos/DisableTenantUserRequest"), exports);
|
|
125
126
|
__exportStar(require("./dtos/EnableTenantUserRequest"), exports);
|
|
@@ -34,3 +34,14 @@ export declare const RETAIL_EVENT_STOCK_MAX = 200;
|
|
|
34
34
|
export declare const RETAIL_ELIGIBLE_FINANCIERS_MAX = 50;
|
|
35
35
|
/** Decimal de los eventos del retailer: hasta 12 enteros y dos decimales, nunca negativo. */
|
|
36
36
|
export declare const RETAIL_EVENT_DECIMAL_PATTERN: RegExp;
|
|
37
|
+
/** Tope del `nextToken` opaco que devuelve Zentral. */
|
|
38
|
+
export declare const RETAIL_NEXT_TOKEN_MAX_LENGTH = 2048;
|
|
39
|
+
/** Id que asigna Zentral, como `externalSaleId`: no vacío, sin espacios y de a lo más 64. */
|
|
40
|
+
export declare const RETAIL_EXTERNAL_ID_PATTERN: RegExp;
|
|
41
|
+
/** Tope del `code` en el cuerpo de error de Zentral. */
|
|
42
|
+
export declare const RETAIL_ERROR_CODE_MAX_LENGTH = 64;
|
|
43
|
+
/** Rango de `lineIndex` en un error de línea de venta. */
|
|
44
|
+
export declare const RETAIL_LINE_INDEX_MIN = 0;
|
|
45
|
+
export declare const RETAIL_LINE_INDEX_MAX = 999;
|
|
46
|
+
/** Rango máximo de `GET /inventory/movements`: 7 días en milisegundos. */
|
|
47
|
+
export declare const RETAIL_MOVEMENTS_RANGE_MAX_MS: number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RETAIL_EVENT_DECIMAL_PATTERN = exports.RETAIL_ELIGIBLE_FINANCIERS_MAX = exports.RETAIL_EVENT_STOCK_MAX = exports.RETAIL_LONG_TEXT_MAX_LENGTH = exports.RETAIL_SHORT_TEXT_MAX_LENGTH = exports.RETAIL_ID_TEXT_MAX_LENGTH = exports.RETAIL_EVENT_PIECES_MAX = exports.RETAIL_LIVE_CHECK_IDENTIFIERS_MAX = exports.RETAIL_DECIMAL_PATTERN = exports.RETAIL_SKU_PATTERN = exports.RETAIL_ZIP_CODE_MAX_LENGTH = exports.RETAIL_ZIP_CODE_MIN_LENGTH = exports.RETAIL_STORE_CODE_MAX_LENGTH = exports.RETAIL_ZONE_ID_PATTERN = exports.RETAIL_ENTITY_ID_PATTERN = exports.RETAIL_TENANT_ID_PATTERN = exports.RETAIL_LIST_LIMIT_MAX = exports.RETAIL_LIST_LIMIT_MIN = exports.RETAIL_EVENT_ID_MAX_LENGTH = void 0;
|
|
3
|
+
exports.RETAIL_MOVEMENTS_RANGE_MAX_MS = exports.RETAIL_LINE_INDEX_MAX = exports.RETAIL_LINE_INDEX_MIN = exports.RETAIL_ERROR_CODE_MAX_LENGTH = exports.RETAIL_EXTERNAL_ID_PATTERN = exports.RETAIL_NEXT_TOKEN_MAX_LENGTH = exports.RETAIL_EVENT_DECIMAL_PATTERN = exports.RETAIL_ELIGIBLE_FINANCIERS_MAX = exports.RETAIL_EVENT_STOCK_MAX = exports.RETAIL_LONG_TEXT_MAX_LENGTH = exports.RETAIL_SHORT_TEXT_MAX_LENGTH = exports.RETAIL_ID_TEXT_MAX_LENGTH = exports.RETAIL_EVENT_PIECES_MAX = exports.RETAIL_LIVE_CHECK_IDENTIFIERS_MAX = exports.RETAIL_DECIMAL_PATTERN = exports.RETAIL_SKU_PATTERN = exports.RETAIL_ZIP_CODE_MAX_LENGTH = exports.RETAIL_ZIP_CODE_MIN_LENGTH = exports.RETAIL_STORE_CODE_MAX_LENGTH = exports.RETAIL_ZONE_ID_PATTERN = exports.RETAIL_ENTITY_ID_PATTERN = exports.RETAIL_TENANT_ID_PATTERN = exports.RETAIL_LIST_LIMIT_MAX = exports.RETAIL_LIST_LIMIT_MIN = exports.RETAIL_EVENT_ID_MAX_LENGTH = void 0;
|
|
4
4
|
/** Tope de `eventId`: el límite seguro de una llave de DynamoDB. */
|
|
5
5
|
exports.RETAIL_EVENT_ID_MAX_LENGTH = 1024;
|
|
6
6
|
/** Rango de `limit` en las listas paginadas del retailer. */
|
|
@@ -37,3 +37,14 @@ exports.RETAIL_EVENT_STOCK_MAX = 200;
|
|
|
37
37
|
exports.RETAIL_ELIGIBLE_FINANCIERS_MAX = 50;
|
|
38
38
|
/** Decimal de los eventos del retailer: hasta 12 enteros y dos decimales, nunca negativo. */
|
|
39
39
|
exports.RETAIL_EVENT_DECIMAL_PATTERN = /^\d{1,12}\.\d{2}$/;
|
|
40
|
+
/** Tope del `nextToken` opaco que devuelve Zentral. */
|
|
41
|
+
exports.RETAIL_NEXT_TOKEN_MAX_LENGTH = 2048;
|
|
42
|
+
/** Id que asigna Zentral, como `externalSaleId`: no vacío, sin espacios y de a lo más 64. */
|
|
43
|
+
exports.RETAIL_EXTERNAL_ID_PATTERN = /^\S{1,64}$/;
|
|
44
|
+
/** Tope del `code` en el cuerpo de error de Zentral. */
|
|
45
|
+
exports.RETAIL_ERROR_CODE_MAX_LENGTH = 64;
|
|
46
|
+
/** Rango de `lineIndex` en un error de línea de venta. */
|
|
47
|
+
exports.RETAIL_LINE_INDEX_MIN = 0;
|
|
48
|
+
exports.RETAIL_LINE_INDEX_MAX = 999;
|
|
49
|
+
/** Rango máximo de `GET /inventory/movements`: 7 días en milisegundos. */
|
|
50
|
+
exports.RETAIL_MOVEMENTS_RANGE_MAX_MS = 7 * 24 * 60 * 60 * 1000;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { RetailTenantQuery } from './RetailTenantQuery';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Query de `GET /private/retail/inventory/live-check`; `identifiers` llega como csv.
|
|
4
|
+
* @deprecated el live-check se va a quitar; el inventario se toma de movimientos y de la lectura diaria.
|
|
5
|
+
*/
|
|
3
6
|
export declare class CheckRetailInventoryRequest extends RetailTenantQuery {
|
|
4
7
|
storeId: string;
|
|
5
8
|
identifiers: string[];
|
|
@@ -18,7 +18,10 @@ const RetailTenantQuery_1 = require("./RetailTenantQuery");
|
|
|
18
18
|
function csvToArray({ value }) {
|
|
19
19
|
return typeof value === 'string' ? value.split(',').map((item) => item.trim()) : value;
|
|
20
20
|
}
|
|
21
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* Query de `GET /private/retail/inventory/live-check`; `identifiers` llega como csv.
|
|
23
|
+
* @deprecated el live-check se va a quitar; el inventario se toma de movimientos y de la lectura diaria.
|
|
24
|
+
*/
|
|
22
25
|
class CheckRetailInventoryRequest extends RetailTenantQuery_1.RetailTenantQuery {
|
|
23
26
|
}
|
|
24
27
|
exports.CheckRetailInventoryRequest = CheckRetailInventoryRequest;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
/** Query de `GET /private/retail/inventory`; el inventario es por tienda y
|
|
3
|
-
export declare class GetRetailInventoryRequest extends
|
|
1
|
+
import { RetailPagedQuery } from './RetailPagedQuery';
|
|
2
|
+
/** Query de `GET /private/retail/inventory`; el inventario es por tienda y pagina con `limit`/`nextToken`. */
|
|
3
|
+
export declare class GetRetailInventoryRequest extends RetailPagedQuery {
|
|
4
4
|
storeId: string;
|
|
5
5
|
}
|
|
@@ -11,9 +11,9 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.GetRetailInventoryRequest = void 0;
|
|
13
13
|
const class_validator_1 = require("class-validator");
|
|
14
|
-
const
|
|
15
|
-
/** Query de `GET /private/retail/inventory`; el inventario es por tienda y
|
|
16
|
-
class GetRetailInventoryRequest extends
|
|
14
|
+
const RetailPagedQuery_1 = require("./RetailPagedQuery");
|
|
15
|
+
/** Query de `GET /private/retail/inventory`; el inventario es por tienda y pagina con `limit`/`nextToken`. */
|
|
16
|
+
class GetRetailInventoryRequest extends RetailPagedQuery_1.RetailPagedQuery {
|
|
17
17
|
}
|
|
18
18
|
exports.GetRetailInventoryRequest = GetRetailInventoryRequest;
|
|
19
19
|
__decorate([
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { RetailPagedQuery } from './RetailPagedQuery';
|
|
2
|
+
/** Query de `GET /private/retail/inventory/movements`: rango `[from, to)` de a lo más 7 días. */
|
|
3
|
+
export declare class ListRetailInventoryMovementsRequest extends RetailPagedQuery {
|
|
4
|
+
from: string;
|
|
5
|
+
to: string;
|
|
6
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
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.ListRetailInventoryMovementsRequest = void 0;
|
|
13
|
+
const class_validator_1 = require("class-validator");
|
|
14
|
+
const IsIsoDateTimeWithZone_1 = require("../validators/IsIsoDateTimeWithZone");
|
|
15
|
+
const IsMovementsRangeValid_1 = require("../validators/IsMovementsRangeValid");
|
|
16
|
+
const RetailPagedQuery_1 = require("./RetailPagedQuery");
|
|
17
|
+
/** Query de `GET /private/retail/inventory/movements`: rango `[from, to)` de a lo más 7 días. */
|
|
18
|
+
class ListRetailInventoryMovementsRequest extends RetailPagedQuery_1.RetailPagedQuery {
|
|
19
|
+
}
|
|
20
|
+
exports.ListRetailInventoryMovementsRequest = ListRetailInventoryMovementsRequest;
|
|
21
|
+
__decorate([
|
|
22
|
+
(0, class_validator_1.Validate)(IsIsoDateTimeWithZone_1.IsIsoDateTimeWithZone),
|
|
23
|
+
__metadata("design:type", String)
|
|
24
|
+
], ListRetailInventoryMovementsRequest.prototype, "from", void 0);
|
|
25
|
+
__decorate([
|
|
26
|
+
(0, class_validator_1.Validate)(IsIsoDateTimeWithZone_1.IsIsoDateTimeWithZone),
|
|
27
|
+
(0, class_validator_1.Validate)(IsMovementsRangeValid_1.IsMovementsRangeValid),
|
|
28
|
+
__metadata("design:type", String)
|
|
29
|
+
], ListRetailInventoryMovementsRequest.prototype, "to", void 0);
|
|
@@ -12,4 +12,10 @@ export declare class ReconciliationPageMessage {
|
|
|
12
12
|
storeId?: string;
|
|
13
13
|
/** Veces que el mensaje ya se re-encoló. */
|
|
14
14
|
requeueCount?: number;
|
|
15
|
+
/** Cursor de Zentral para la siguiente página del inventario de la tienda. */
|
|
16
|
+
nextToken?: string;
|
|
17
|
+
/** Inicio del rango de movimientos, incluido. */
|
|
18
|
+
from?: string;
|
|
19
|
+
/** Fin del rango de movimientos, excluido. */
|
|
20
|
+
to?: string;
|
|
15
21
|
}
|
|
@@ -13,6 +13,7 @@ exports.ReconciliationPageMessage = void 0;
|
|
|
13
13
|
const class_transformer_1 = require("class-transformer");
|
|
14
14
|
const class_validator_1 = require("class-validator");
|
|
15
15
|
const ReconciliationEntityEnum_1 = require("../enums/ReconciliationEntityEnum");
|
|
16
|
+
const IsIsoDateTimeWithZone_1 = require("../validators/IsIsoDateTimeWithZone");
|
|
16
17
|
/** Mensaje de la cola de revisión: una página, o una tienda completa en inventario. */
|
|
17
18
|
class ReconciliationPageMessage {
|
|
18
19
|
}
|
|
@@ -60,3 +61,22 @@ __decorate([
|
|
|
60
61
|
(0, class_validator_1.Min)(0),
|
|
61
62
|
__metadata("design:type", Number)
|
|
62
63
|
], ReconciliationPageMessage.prototype, "requeueCount", void 0);
|
|
64
|
+
__decorate([
|
|
65
|
+
(0, class_transformer_1.Expose)(),
|
|
66
|
+
(0, class_validator_1.IsOptional)(),
|
|
67
|
+
(0, class_validator_1.IsString)(),
|
|
68
|
+
(0, class_validator_1.Matches)(/\S/),
|
|
69
|
+
__metadata("design:type", String)
|
|
70
|
+
], ReconciliationPageMessage.prototype, "nextToken", void 0);
|
|
71
|
+
__decorate([
|
|
72
|
+
(0, class_transformer_1.Expose)(),
|
|
73
|
+
(0, class_validator_1.IsOptional)(),
|
|
74
|
+
(0, class_validator_1.Validate)(IsIsoDateTimeWithZone_1.IsIsoDateTimeWithZone),
|
|
75
|
+
__metadata("design:type", String)
|
|
76
|
+
], ReconciliationPageMessage.prototype, "from", void 0);
|
|
77
|
+
__decorate([
|
|
78
|
+
(0, class_transformer_1.Expose)(),
|
|
79
|
+
(0, class_validator_1.IsOptional)(),
|
|
80
|
+
(0, class_validator_1.Validate)(IsIsoDateTimeWithZone_1.IsIsoDateTimeWithZone),
|
|
81
|
+
__metadata("design:type", String)
|
|
82
|
+
], ReconciliationPageMessage.prototype, "to", void 0);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RetailInventoryMeta, RetailPageMeta } from '../models/RetailPageMeta';
|
|
2
|
-
import { RetailSystemPiece, RetailSystemStock } from '../models/RetailSystemInventory';
|
|
2
|
+
import { RetailSystemInventoryMovement, RetailSystemPiece, RetailSystemStock } from '../models/RetailSystemInventory';
|
|
3
3
|
import { RetailSystemProduct } from '../models/RetailSystemProduct';
|
|
4
4
|
import { RetailSystemStore } from '../models/RetailSystemStore';
|
|
5
5
|
import { RetailSystemUser } from '../models/RetailSystemUser';
|
|
@@ -19,6 +19,11 @@ export interface GetRetailInventoryResponse {
|
|
|
19
19
|
stock: RetailSystemStock[];
|
|
20
20
|
meta: RetailInventoryMeta;
|
|
21
21
|
}
|
|
22
|
+
/** `data` de `GET /private/retail/inventory/movements`. */
|
|
23
|
+
export interface ListRetailInventoryMovementsResponse {
|
|
24
|
+
items: RetailSystemInventoryMovement[];
|
|
25
|
+
meta: RetailPageMeta;
|
|
26
|
+
}
|
|
22
27
|
/** `data` de `GET /private/retail/users`. */
|
|
23
28
|
export interface ListRetailUsersResponse {
|
|
24
29
|
items: RetailSystemUser[];
|
|
@@ -32,7 +37,10 @@ export interface RegisterRetailSaleResponse {
|
|
|
32
37
|
export interface CancelRetailSaleResponse {
|
|
33
38
|
saleId: string;
|
|
34
39
|
}
|
|
35
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* `data` de `GET /private/retail/inventory/live-check`: los identificadores que el retailer lista en la tienda.
|
|
42
|
+
* @deprecated el live-check se va a quitar; el inventario se toma de movimientos y de la lectura diaria.
|
|
43
|
+
*/
|
|
36
44
|
export interface CheckRetailInventoryResponse {
|
|
37
45
|
listed: string[];
|
|
38
46
|
generatedAt: string;
|