@fiado/type-kit 3.505.0 → 3.507.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.
Files changed (39) hide show
  1. package/_test_/unit/retailCommission/latestClosedPayout.test.ts +29 -0
  2. package/_test_/unit/retailOrg/dtos/sellerTableSources.test.ts +62 -0
  3. package/_test_/unit/retailWizard/customerTableShapes.test.ts +36 -0
  4. package/_test_/unit/retailWizard/sellerTableShapes.test.ts +43 -0
  5. package/bin/retailCommission/dtos/PrivateLatestClosedPayout.d.ts +24 -0
  6. package/bin/retailCommission/dtos/PrivateLatestClosedPayout.js +24 -0
  7. package/bin/retailCommission/index.d.ts +1 -0
  8. package/bin/retailCommission/index.js +1 -0
  9. package/bin/retailOrg/dtos/requests/PrivateGoalListQuery.d.ts +12 -0
  10. package/bin/retailOrg/dtos/requests/PrivateGoalListQuery.js +40 -0
  11. package/bin/retailOrg/dtos/requests/PrivateSellerListQuery.d.ts +2 -0
  12. package/bin/retailOrg/dtos/requests/PrivateSellerListQuery.js +6 -0
  13. package/bin/retailOrg/dtos/responses/PrivateGoalListResponse.d.ts +8 -0
  14. package/bin/retailOrg/dtos/responses/PrivateGoalListResponse.js +2 -0
  15. package/bin/retailOrg/dtos/validation/PrivateSellerListResponse.d.ts +2 -0
  16. package/bin/retailOrg/dtos/validation/StoreValidationDto.d.ts +2 -0
  17. package/bin/retailOrg/index.d.ts +2 -0
  18. package/bin/retailOrg/index.js +2 -0
  19. package/bin/retailWizard/dtos/responses/BackofficeCustomerTableResponse.d.ts +38 -0
  20. package/bin/retailWizard/dtos/responses/BackofficeCustomerTableResponse.js +2 -0
  21. package/bin/retailWizard/dtos/responses/BackofficeSellerTableResponse.d.ts +57 -0
  22. package/bin/retailWizard/dtos/responses/BackofficeSellerTableResponse.js +2 -0
  23. package/bin/retailWizard/enums/SellerTableSourceStatusEnum.d.ts +5 -0
  24. package/bin/retailWizard/enums/SellerTableSourceStatusEnum.js +9 -0
  25. package/bin/retailWizard/index.d.ts +3 -0
  26. package/bin/retailWizard/index.js +3 -0
  27. package/package.json +1 -1
  28. package/src/retailCommission/dtos/PrivateLatestClosedPayout.ts +33 -0
  29. package/src/retailCommission/index.ts +1 -0
  30. package/src/retailOrg/dtos/requests/PrivateGoalListQuery.ts +27 -0
  31. package/src/retailOrg/dtos/requests/PrivateSellerListQuery.ts +8 -2
  32. package/src/retailOrg/dtos/responses/PrivateGoalListResponse.ts +9 -0
  33. package/src/retailOrg/dtos/validation/PrivateSellerListResponse.ts +2 -0
  34. package/src/retailOrg/dtos/validation/StoreValidationDto.ts +2 -0
  35. package/src/retailOrg/index.ts +2 -0
  36. package/src/retailWizard/dtos/responses/BackofficeCustomerTableResponse.ts +41 -0
  37. package/src/retailWizard/dtos/responses/BackofficeSellerTableResponse.ts +61 -0
  38. package/src/retailWizard/enums/SellerTableSourceStatusEnum.ts +5 -0
  39. package/src/retailWizard/index.ts +3 -0
@@ -0,0 +1,29 @@
1
+ import 'reflect-metadata';
2
+ import { plainToInstance } from 'class-transformer';
3
+ import { validateSync } from 'class-validator';
4
+ import {
5
+ PrivateLatestClosedPayoutQuery,
6
+ type PrivateLatestClosedPayoutResponse,
7
+ } from '../../../src/retailCommission';
8
+
9
+ describe('PrivateLatestClosedPayoutQuery', () => {
10
+ const errorsOf = (payload: object) =>
11
+ validateSync(plainToInstance(PrivateLatestClosedPayoutQuery, payload, { excludeExtraneousValues: true })).map(
12
+ (e) => e.property,
13
+ );
14
+
15
+ it('acepta un retailerId', () => expect(errorsOf({ retailerId: 'r-1' })).toEqual([]));
16
+ it('exige el retailerId', () => expect(errorsOf({})).toContain('retailerId'));
17
+ });
18
+
19
+ describe('PrivateLatestClosedPayoutResponse', () => {
20
+ it('sin corte cerrado el periodo viaja en null', () => {
21
+ const empty: PrivateLatestClosedPayoutResponse = { retailerId: 'r-1', period: null, sellers: [] };
22
+ const closed: PrivateLatestClosedPayoutResponse = {
23
+ retailerId: 'r-1',
24
+ period: { periodId: '2026-09-28', from: '2026-09-28', to: '2026-10-04' },
25
+ sellers: [{ retailUserId: 'u-1', amountCents: 12000 }],
26
+ };
27
+ expect([empty.period, closed.sellers[0].amountCents]).toEqual([null, 12000]);
28
+ });
29
+ });
@@ -0,0 +1,62 @@
1
+ import 'reflect-metadata';
2
+ import { plainToInstance, type ClassConstructor } from 'class-transformer';
3
+ import { validateSync } from 'class-validator';
4
+ import {
5
+ GoalTargetTypeEnum,
6
+ PrivateGoalListQuery,
7
+ PrivateSellerListQuery,
8
+ type PrivateGoalListResponse,
9
+ type PrivateSellerDto,
10
+ type StoreValidationDto,
11
+ } from '../../../../src/retailOrg';
12
+
13
+ const RETAILER = '01J9ZQ0000000000000000000A';
14
+
15
+ function errorsOf<T extends object>(cls: ClassConstructor<T>, payload: object): string[] {
16
+ return validateSync(plainToInstance(cls, payload, { excludeExtraneousValues: true }) as object).map(
17
+ (e) => e.property,
18
+ );
19
+ }
20
+
21
+ describe('PrivateGoalListQuery', () => {
22
+ it('acepta retailer, periodo y tipo', () =>
23
+ expect(errorsOf(PrivateGoalListQuery, { retailerId: RETAILER, periodId: '2026-10', targetType: 'SELLER' })).toEqual([]));
24
+ it('acepta sin tipo', () => expect(errorsOf(PrivateGoalListQuery, { retailerId: RETAILER, periodId: '2026-10' })).toEqual([]));
25
+ it('rechaza un retailerId que no es ULID', () =>
26
+ expect(errorsOf(PrivateGoalListQuery, { retailerId: 'x', periodId: '2026-10' })).toContain('retailerId'));
27
+ it('rechaza el mes 13', () =>
28
+ expect(errorsOf(PrivateGoalListQuery, { retailerId: RETAILER, periodId: '2026-13' })).toContain('periodId'));
29
+ it('rechaza un tipo fuera del catálogo', () =>
30
+ expect(errorsOf(PrivateGoalListQuery, { retailerId: RETAILER, periodId: '2026-10', targetType: 'ZONE' })).toContain(
31
+ 'targetType',
32
+ ));
33
+ });
34
+
35
+ describe('PrivateSellerListQuery.includePhone', () => {
36
+ it('lee "true" como verdadero', () => {
37
+ const q = plainToInstance(PrivateSellerListQuery, { retailerId: RETAILER, includePhone: 'true' }, { excludeExtraneousValues: true });
38
+ expect(q.includePhone).toBe(true);
39
+ expect(validateSync(q)).toEqual([]);
40
+ });
41
+ it('sin el parámetro queda en falso', () => {
42
+ const q = plainToInstance(PrivateSellerListQuery, { retailerId: RETAILER }, { excludeExtraneousValues: true });
43
+ expect(q.includePhone).toBe(false);
44
+ });
45
+ });
46
+
47
+ describe('shapes de los privados del padrón', () => {
48
+ it('la tienda publica a su encargado y el vendedor su teléfono opcional', () => {
49
+ const store: StoreValidationDto = {
50
+ storeId: 's', retailerId: RETAILER, zoneId: null, zoneName: null, code: 'C', name: 'N', status: 'ACTIVE' as never,
51
+ managerRetailUserId: 'u-1',
52
+ };
53
+ const seller: PrivateSellerDto = {
54
+ sellerId: 'u-1', displayName: null, homeStoreId: 's', commissionTier: 'seller', status: 'ACTIVE' as never, phone: null,
55
+ };
56
+ const goals: PrivateGoalListResponse = {
57
+ retailerId: RETAILER, periodId: '2026-10',
58
+ goals: [{ targetId: 'u-1', targetType: GoalTargetTypeEnum.SELLER, monthCents: 3000, weekCents: 750, dayCents: 107 }],
59
+ };
60
+ expect([store.managerRetailUserId, seller.phone, goals.goals.length]).toEqual(['u-1', null, 1]);
61
+ });
62
+ });
@@ -0,0 +1,36 @@
1
+ import 'reflect-metadata';
2
+ import { ClientLevelEnum } from '../../../src/loanScoring/enums/ClientLevelEnum';
3
+ import {
4
+ SellerTableSourceStatusEnum,
5
+ type BackofficeCustomerTableResponse,
6
+ } from '../../../src/retailWizard';
7
+
8
+ describe('BackofficeCustomerTableResponse', () => {
9
+ it('declara las fuentes, el cursor y una fila completa', () => {
10
+ const response: BackofficeCustomerTableResponse = {
11
+ from: null,
12
+ to: '2026-10-07T18:00:00.000Z',
13
+ nextToken: 'abc',
14
+ sources: { sales: SellerTableSourceStatusEnum.OK, credit: SellerTableSourceStatusEnum.UNAVAILABLE },
15
+ items: [
16
+ {
17
+ retailCustomerId: 'RC-1',
18
+ name: 'Ana',
19
+ phone: null,
20
+ purchaseCount: 2,
21
+ totalSpentCents: 300_000,
22
+ averageTicketCents: 150_000,
23
+ firstPurchaseAt: '2026-09-01T18:00:00.000Z',
24
+ lastPurchaseAt: '2026-10-01T18:00:00.000Z',
25
+ lastStoreName: 'Centro',
26
+ favoriteStoreId: 'ST-1',
27
+ favoriteStoreName: 'Centro',
28
+ skLevel: ClientLevelEnum.GOLD,
29
+ activeCreditsCount: null,
30
+ },
31
+ ],
32
+ };
33
+ expect(response.items[0].skLevel).toBe('GOLD');
34
+ expect(response.sources.credit).toBe('UNAVAILABLE');
35
+ });
36
+ });
@@ -0,0 +1,43 @@
1
+ import 'reflect-metadata';
2
+ import {
3
+ SellerTableSourceStatusEnum,
4
+ type BackofficeSellerTableResponse,
5
+ } from '../../../src/retailWizard';
6
+
7
+ describe('BackofficeSellerTableResponse', () => {
8
+ it('declara las tres fuentes y una fila completa', () => {
9
+ const response: BackofficeSellerTableResponse = {
10
+ from: '2026-09-07T06:00:00.000Z',
11
+ to: '2026-10-07T05:59:59.999Z',
12
+ truncated: false,
13
+ sources: {
14
+ roster: SellerTableSourceStatusEnum.OK,
15
+ goals: SellerTableSourceStatusEnum.UNAVAILABLE,
16
+ commission: SellerTableSourceStatusEnum.OK,
17
+ },
18
+ commissionPeriod: { periodId: '2026-09-28', from: '2026-09-28', to: '2026-10-04' },
19
+ items: [
20
+ {
21
+ retailUserId: 'u-1',
22
+ name: 'Ana',
23
+ status: 'ACTIVE' as never,
24
+ phone: null,
25
+ storeId: null,
26
+ storeName: null,
27
+ zoneName: null,
28
+ isStoreAdmin: false,
29
+ salesCount: 0,
30
+ placedCents: 0,
31
+ averageTicketCents: null,
32
+ lastSaleAt: null,
33
+ weekOverWeekChangePct: null,
34
+ goalCents: null,
35
+ commissionCents: null,
36
+ npiM30Pct: null,
37
+ },
38
+ ],
39
+ };
40
+ expect(Object.values(SellerTableSourceStatusEnum)).toEqual(['OK', 'UNAVAILABLE']);
41
+ expect(response.items[0].npiM30Pct).toBeNull();
42
+ });
43
+ });
@@ -0,0 +1,24 @@
1
+ /** Query de `GET /private/retailers/{retailerId}/payouts/latest-closed`. */
2
+ export declare class PrivateLatestClosedPayoutQuery {
3
+ retailerId: string;
4
+ }
5
+ /** Lo que el corte le paga a un vendedor: liberado más ajustes, en centavos. */
6
+ export interface PrivateClosedPayoutSeller {
7
+ retailUserId: string;
8
+ amountCents: number;
9
+ }
10
+ /** El corte semanal; `from` y `to` son días locales `YYYY-MM-DD`, ambos incluidos. */
11
+ export interface PrivateClosedPayoutPeriod {
12
+ periodId: string;
13
+ from: string;
14
+ to: string;
15
+ }
16
+ /**
17
+ * Respuesta de `GET /private/retailers/{retailerId}/payouts/latest-closed`: el último corte semanal
18
+ * CERRADO de la cadena. Sin corte cerrado reciente, `period: null` y `sellers: []`.
19
+ */
20
+ export interface PrivateLatestClosedPayoutResponse {
21
+ retailerId: string;
22
+ period: PrivateClosedPayoutPeriod | null;
23
+ sellers: PrivateClosedPayoutSeller[];
24
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.PrivateLatestClosedPayoutQuery = void 0;
13
+ const class_transformer_1 = require("class-transformer");
14
+ const class_validator_1 = require("class-validator");
15
+ /** Query de `GET /private/retailers/{retailerId}/payouts/latest-closed`. */
16
+ class PrivateLatestClosedPayoutQuery {
17
+ }
18
+ exports.PrivateLatestClosedPayoutQuery = PrivateLatestClosedPayoutQuery;
19
+ __decorate([
20
+ (0, class_transformer_1.Expose)(),
21
+ (0, class_validator_1.IsString)(),
22
+ (0, class_validator_1.IsNotEmpty)(),
23
+ __metadata("design:type", String)
24
+ ], PrivateLatestClosedPayoutQuery.prototype, "retailerId", void 0);
@@ -27,3 +27,4 @@ export * from './dtos/CommissionCalcTrace';
27
27
  export * from './dtos/CommissionAccrual';
28
28
  export * from './dtos/CommissionPayout';
29
29
  export * from './dtos/CommissionApi';
30
+ export * from './dtos/PrivateLatestClosedPayout';
@@ -46,3 +46,4 @@ __exportStar(require("./dtos/CommissionAccrual"), exports);
46
46
  __exportStar(require("./dtos/CommissionPayout"), exports);
47
47
  // Contratos HTTP — uno por endpoint
48
48
  __exportStar(require("./dtos/CommissionApi"), exports);
49
+ __exportStar(require("./dtos/PrivateLatestClosedPayout"), exports);
@@ -0,0 +1,12 @@
1
+ import { GoalTargetTypeEnum } from '../../enums/GoalTargetTypeEnum';
2
+ /**
3
+ * Query de `GET /private/retailers/{retailerId}/goals` — las metas de un periodo, M2M.
4
+ * El `retailerId` llega en el path; la seguridad del privado es de red, no de identidad.
5
+ */
6
+ export declare class PrivateGoalListQuery {
7
+ retailerId: string;
8
+ /** Mes calendario `YYYY-MM` (mes 01-12). */
9
+ periodId: string;
10
+ /** Si falta, devuelve los dos tipos. */
11
+ targetType?: GoalTargetTypeEnum;
12
+ }
@@ -0,0 +1,40 @@
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.PrivateGoalListQuery = void 0;
13
+ const class_transformer_1 = require("class-transformer");
14
+ const class_validator_1 = require("class-validator");
15
+ const GoalTargetTypeEnum_1 = require("../../enums/GoalTargetTypeEnum");
16
+ /** ULID canónico: 26 chars Crockford base32, primer char 0-7. */
17
+ const ULID = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/;
18
+ /**
19
+ * Query de `GET /private/retailers/{retailerId}/goals` — las metas de un periodo, M2M.
20
+ * El `retailerId` llega en el path; la seguridad del privado es de red, no de identidad.
21
+ */
22
+ class PrivateGoalListQuery {
23
+ }
24
+ exports.PrivateGoalListQuery = PrivateGoalListQuery;
25
+ __decorate([
26
+ (0, class_transformer_1.Expose)(),
27
+ (0, class_validator_1.Matches)(ULID, { message: 'retailerId debe ser un ULID' }),
28
+ __metadata("design:type", String)
29
+ ], PrivateGoalListQuery.prototype, "retailerId", void 0);
30
+ __decorate([
31
+ (0, class_transformer_1.Expose)(),
32
+ (0, class_validator_1.Matches)(/^\d{4}-(0[1-9]|1[0-2])$/, { message: 'periodId debe tener formato YYYY-MM (mes 01-12)' }),
33
+ __metadata("design:type", String)
34
+ ], PrivateGoalListQuery.prototype, "periodId", void 0);
35
+ __decorate([
36
+ (0, class_transformer_1.Expose)(),
37
+ (0, class_validator_1.IsOptional)(),
38
+ (0, class_validator_1.IsEnum)(GoalTargetTypeEnum_1.GoalTargetTypeEnum),
39
+ __metadata("design:type", String)
40
+ ], PrivateGoalListQuery.prototype, "targetType", void 0);
@@ -24,4 +24,6 @@ export declare class PrivateSellerListQuery {
24
24
  * nunca omite el registro.
25
25
  */
26
26
  callerService?: string;
27
+ /** `true` agrega el teléfono de cada vendedor. Por defecto no viaja: es PII. */
28
+ includePhone?: boolean;
27
29
  }
@@ -43,3 +43,9 @@ __decorate([
43
43
  (0, class_validator_1.Matches)(/^[a-z0-9-]{1,64}$/, { message: 'callerService debe ser el nombre del lambda (kebab-case)' }),
44
44
  __metadata("design:type", String)
45
45
  ], PrivateSellerListQuery.prototype, "callerService", void 0);
46
+ __decorate([
47
+ (0, class_transformer_1.Expose)(),
48
+ (0, class_transformer_1.Transform)(({ value }) => value === true || value === 'true'),
49
+ (0, class_validator_1.IsBoolean)(),
50
+ __metadata("design:type", Boolean)
51
+ ], PrivateSellerListQuery.prototype, "includePhone", void 0);
@@ -0,0 +1,8 @@
1
+ import type { GoalListResponse } from './GoalListResponse';
2
+ /**
3
+ * Respuesta de `GET /private/retailers/{retailerId}/goals`: las metas del periodo con las tres cifras
4
+ * derivadas. Un periodo sin metas devuelve `goals: []`, no un 404.
5
+ */
6
+ export interface PrivateGoalListResponse extends GoalListResponse {
7
+ retailerId: string;
8
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -15,6 +15,8 @@ export interface PrivateSellerDto {
15
15
  homeStoreId: string | null;
16
16
  commissionTier: string;
17
17
  status: RetailUserStatusEnum;
18
+ /** Teléfono del vendedor. Solo viaja si se pidió `includePhone=true`; `null` si no lo tiene. */
19
+ phone?: string | null;
18
20
  }
19
21
  /**
20
22
  * Respuesta de `GET /private/sellers?retailerId=…` — el padrón de una cadena, para máquinas.
@@ -16,4 +16,6 @@ export interface StoreValidationDto {
16
16
  code: string;
17
17
  name: string;
18
18
  status: StoreStatusEnum;
19
+ /** Encargado de la tienda (`retailUserId`); `null` si no tiene. Ausente en lambdas viejos. */
20
+ managerRetailUserId?: string | null;
19
21
  }
@@ -37,10 +37,12 @@ export * from './dtos/requests/TransferRetailUserRequest';
37
37
  export * from './dtos/requests/GoalListQuery';
38
38
  export * from './dtos/requests/GoalUpsertRequest';
39
39
  export * from './dtos/requests/GoalPathParams';
40
+ export * from './dtos/requests/PrivateGoalListQuery';
40
41
  export * from './dtos/requests/KpiQuery';
41
42
  export * from './dtos/requests/PrivateSellerListQuery';
42
43
  export * from './dtos/responses/RetailerHierarchyResponse';
43
44
  export * from './dtos/responses/GoalListResponse';
44
45
  export * from './dtos/responses/GoalUpsertResponse';
46
+ export * from './dtos/responses/PrivateGoalListResponse';
45
47
  export * from './dtos/responses/StoreKpiResponse';
46
48
  export * from './dtos/responses/SellerKpiResponse';
@@ -59,11 +59,13 @@ __exportStar(require("./dtos/requests/TransferRetailUserRequest"), exports);
59
59
  __exportStar(require("./dtos/requests/GoalListQuery"), exports);
60
60
  __exportStar(require("./dtos/requests/GoalUpsertRequest"), exports);
61
61
  __exportStar(require("./dtos/requests/GoalPathParams"), exports);
62
+ __exportStar(require("./dtos/requests/PrivateGoalListQuery"), exports);
62
63
  __exportStar(require("./dtos/requests/KpiQuery"), exports);
63
64
  __exportStar(require("./dtos/requests/PrivateSellerListQuery"), exports);
64
65
  // Response DTOs
65
66
  __exportStar(require("./dtos/responses/RetailerHierarchyResponse"), exports);
66
67
  __exportStar(require("./dtos/responses/GoalListResponse"), exports);
67
68
  __exportStar(require("./dtos/responses/GoalUpsertResponse"), exports);
69
+ __exportStar(require("./dtos/responses/PrivateGoalListResponse"), exports);
68
70
  __exportStar(require("./dtos/responses/StoreKpiResponse"), exports);
69
71
  __exportStar(require("./dtos/responses/SellerKpiResponse"), exports);
@@ -0,0 +1,38 @@
1
+ import type { ClientLevelEnum } from '../../../loanScoring/enums/ClientLevelEnum';
2
+ import type { SellerTableSourceStatusEnum } from '../../enums/SellerTableSourceStatusEnum';
3
+ /** Una fila de la tabla de Clientes: compras en la cadena dentro de la ventana, sin canceladas, más su crédito SK. */
4
+ export interface CustomerTableRow {
5
+ retailCustomerId: string;
6
+ name: string | null;
7
+ phone: string | null;
8
+ purchaseCount: number;
9
+ /** Precio de lo comprado (en crédito, el precio del equipo, no el enganche). */
10
+ totalSpentCents: number;
11
+ averageTicketCents: number | null;
12
+ firstPurchaseAt: string;
13
+ lastPurchaseAt: string;
14
+ lastStoreName: string | null;
15
+ /** Tienda con más compras; en empate, la de la compra más reciente. */
16
+ favoriteStoreId: string | null;
17
+ favoriteStoreName: string | null;
18
+ /** `null` sin nivel o con el crédito sin leer. */
19
+ skLevel: ClientLevelEnum | null;
20
+ /** `null` con el crédito sin leer. */
21
+ activeCreditsCount: number | null;
22
+ }
23
+ /** Estado de cada fuente. Con el crédito `UNAVAILABLE` sus campos van en `null`, nunca en `0`. */
24
+ export interface CustomerTableSources {
25
+ sales: SellerTableSourceStatusEnum.OK;
26
+ credit: SellerTableSourceStatusEnum;
27
+ }
28
+ /**
29
+ * `GET /backoffice/customers/table?from&to&limit&nextToken&storeId&sellerId&value` — tabla de Clientes
30
+ * del Portal Admin VL, paginada por última compra descendente. `from` en `null` es «Todo».
31
+ */
32
+ export interface BackofficeCustomerTableResponse {
33
+ from: string | null;
34
+ to: string;
35
+ nextToken: string | null;
36
+ sources: CustomerTableSources;
37
+ items: CustomerTableRow[];
38
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,57 @@
1
+ import type { RetailUserStatusEnum } from '../../../retailOrg/enums/RetailUserStatusEnum';
2
+ import type { SellerTableSourceStatusEnum } from '../../enums/SellerTableSourceStatusEnum';
3
+ /** Una fila de la tabla de Vendedores: padrón + ventas de la ventana + meta + comisión. */
4
+ export interface SellerTableRow {
5
+ retailUserId: string;
6
+ /** `null` si ni el padrón ni las ventas traen nombre. */
7
+ name: string | null;
8
+ /** `null` solo si el vendedor vendió pero ya no está en el padrón. */
9
+ status: RetailUserStatusEnum | null;
10
+ phone: string | null;
11
+ storeId: string | null;
12
+ storeName: string | null;
13
+ zoneName: string | null;
14
+ /** Es el encargado (`managerRetailUserId`) de su tienda. */
15
+ isStoreAdmin: boolean;
16
+ /** Sin ventas en la ventana viaja `0`: el barrido es exhaustivo. */
17
+ salesCount: number;
18
+ placedCents: number;
19
+ averageTicketCents: number | null;
20
+ lastSaleAt: string | null;
21
+ /** Δ % contra la misma ventana 7 días antes; `null` si la ventana pasa de 7 días o no hubo base. */
22
+ weekOverWeekChangePct: number | null;
23
+ /**
24
+ * Meta mensual (`monthCents` del mes de `to`, hora de CDMX) escalada a los días de la ventana:
25
+ * `round(monthCents * días / 30)`. `null` sin meta, con metas caídas o con ventana > 90 días.
26
+ */
27
+ goalCents: number | null;
28
+ /** Lo que le pagó el último corte semanal CERRADO (`0` si no le pagó); `null` sin corte o con la fuente caída. */
29
+ commissionCents: number | null;
30
+ /** NPI M30: no lo calcula ningún lambda todavía. Siempre `null`. */
31
+ npiM30Pct: null;
32
+ }
33
+ /** Estado de cada fuente externa. Una fuente `UNAVAILABLE` deja sus campos en `null`, nunca en `0`. */
34
+ export interface SellerTableSources {
35
+ roster: SellerTableSourceStatusEnum;
36
+ goals: SellerTableSourceStatusEnum;
37
+ commission: SellerTableSourceStatusEnum;
38
+ }
39
+ /** Corte semanal del que sale `commissionCents`; días locales `YYYY-MM-DD`, ambos incluidos. */
40
+ export interface SellerTableCommissionPeriod {
41
+ periodId: string;
42
+ from: string;
43
+ to: string;
44
+ }
45
+ /**
46
+ * `GET /backoffice/sellers/table?from&to&value` — la tabla completa de Vendedores del Portal Admin
47
+ * VL, sin paginación. Incluye a los vendedores del padrón sin ventas y a los inactivos.
48
+ */
49
+ export interface BackofficeSellerTableResponse {
50
+ from: string;
51
+ to: string | null;
52
+ /** Las ventas de la ventana pasaron el tope de lectura: los números están recortados. */
53
+ truncated: boolean;
54
+ sources: SellerTableSources;
55
+ commissionPeriod: SellerTableCommissionPeriod | null;
56
+ items: SellerTableRow[];
57
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,5 @@
1
+ /** Si una fuente de la tabla de Vendedores contestó (`OK`) o falló (`UNAVAILABLE`). */
2
+ export declare enum SellerTableSourceStatusEnum {
3
+ OK = "OK",
4
+ UNAVAILABLE = "UNAVAILABLE"
5
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SellerTableSourceStatusEnum = void 0;
4
+ /** Si una fuente de la tabla de Vendedores contestó (`OK`) o falló (`UNAVAILABLE`). */
5
+ var SellerTableSourceStatusEnum;
6
+ (function (SellerTableSourceStatusEnum) {
7
+ SellerTableSourceStatusEnum["OK"] = "OK";
8
+ SellerTableSourceStatusEnum["UNAVAILABLE"] = "UNAVAILABLE";
9
+ })(SellerTableSourceStatusEnum || (exports.SellerTableSourceStatusEnum = SellerTableSourceStatusEnum = {}));
@@ -135,6 +135,9 @@ export * from './dtos/responses/BackofficeCustomersResponse';
135
135
  export * from './dtos/responses/BackofficeCustomerPurchasesResponse';
136
136
  export * from './dtos/responses/BackofficeStoreKpisResponse';
137
137
  export * from './dtos/responses/BackofficeSellerKpisResponse';
138
+ export * from './enums/SellerTableSourceStatusEnum';
139
+ export * from './dtos/responses/BackofficeSellerTableResponse';
140
+ export * from './dtos/responses/BackofficeCustomerTableResponse';
138
141
  export * from './events/SaleCompletedV1';
139
142
  export * from './events/SaleCancelledV1';
140
143
  export * from './events/SaleCompletedV2';
@@ -168,6 +168,9 @@ __exportStar(require("./dtos/responses/BackofficeCustomersResponse"), exports);
168
168
  __exportStar(require("./dtos/responses/BackofficeCustomerPurchasesResponse"), exports);
169
169
  __exportStar(require("./dtos/responses/BackofficeStoreKpisResponse"), exports);
170
170
  __exportStar(require("./dtos/responses/BackofficeSellerKpisResponse"), exports);
171
+ __exportStar(require("./enums/SellerTableSourceStatusEnum"), exports);
172
+ __exportStar(require("./dtos/responses/BackofficeSellerTableResponse"), exports);
173
+ __exportStar(require("./dtos/responses/BackofficeCustomerTableResponse"), exports);
171
174
  // Contratos de eventos (PascalCase + sufijo V1)
172
175
  __exportStar(require("./events/SaleCompletedV1"), exports);
173
176
  __exportStar(require("./events/SaleCancelledV1"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fiado/type-kit",
3
- "version": "3.505.0",
3
+ "version": "3.507.0",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "types": "bin/index.d.ts",
@@ -0,0 +1,33 @@
1
+ import { Expose } from 'class-transformer';
2
+ import { IsNotEmpty, IsString } from 'class-validator';
3
+
4
+ /** Query de `GET /private/retailers/{retailerId}/payouts/latest-closed`. */
5
+ export class PrivateLatestClosedPayoutQuery {
6
+ @Expose()
7
+ @IsString()
8
+ @IsNotEmpty()
9
+ retailerId!: string;
10
+ }
11
+
12
+ /** Lo que el corte le paga a un vendedor: liberado más ajustes, en centavos. */
13
+ export interface PrivateClosedPayoutSeller {
14
+ retailUserId: string;
15
+ amountCents: number;
16
+ }
17
+
18
+ /** El corte semanal; `from` y `to` son días locales `YYYY-MM-DD`, ambos incluidos. */
19
+ export interface PrivateClosedPayoutPeriod {
20
+ periodId: string;
21
+ from: string;
22
+ to: string;
23
+ }
24
+
25
+ /**
26
+ * Respuesta de `GET /private/retailers/{retailerId}/payouts/latest-closed`: el último corte semanal
27
+ * CERRADO de la cadena. Sin corte cerrado reciente, `period: null` y `sellers: []`.
28
+ */
29
+ export interface PrivateLatestClosedPayoutResponse {
30
+ retailerId: string;
31
+ period: PrivateClosedPayoutPeriod | null;
32
+ sellers: PrivateClosedPayoutSeller[];
33
+ }
@@ -32,3 +32,4 @@ export * from './dtos/CommissionPayout';
32
32
 
33
33
  // Contratos HTTP — uno por endpoint
34
34
  export * from './dtos/CommissionApi';
35
+ export * from './dtos/PrivateLatestClosedPayout';
@@ -0,0 +1,27 @@
1
+ import { Expose } from 'class-transformer';
2
+ import { IsEnum, IsOptional, Matches } from 'class-validator';
3
+ import { GoalTargetTypeEnum } from '../../enums/GoalTargetTypeEnum';
4
+
5
+ /** ULID canónico: 26 chars Crockford base32, primer char 0-7. */
6
+ const ULID = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/;
7
+
8
+ /**
9
+ * Query de `GET /private/retailers/{retailerId}/goals` — las metas de un periodo, M2M.
10
+ * El `retailerId` llega en el path; la seguridad del privado es de red, no de identidad.
11
+ */
12
+ export class PrivateGoalListQuery {
13
+ @Expose()
14
+ @Matches(ULID, { message: 'retailerId debe ser un ULID' })
15
+ retailerId!: string;
16
+
17
+ /** Mes calendario `YYYY-MM` (mes 01-12). */
18
+ @Expose()
19
+ @Matches(/^\d{4}-(0[1-9]|1[0-2])$/, { message: 'periodId debe tener formato YYYY-MM (mes 01-12)' })
20
+ periodId!: string;
21
+
22
+ /** Si falta, devuelve los dos tipos. */
23
+ @Expose()
24
+ @IsOptional()
25
+ @IsEnum(GoalTargetTypeEnum)
26
+ targetType?: GoalTargetTypeEnum;
27
+ }
@@ -1,5 +1,5 @@
1
- import { Expose } from 'class-transformer';
2
- import { IsEnum, IsOptional, Matches } from 'class-validator';
1
+ import { Expose, Transform } from 'class-transformer';
2
+ import { IsBoolean, IsEnum, IsOptional, Matches } from 'class-validator';
3
3
  import { RetailUserStatusEnum } from '../../enums/RetailUserStatusEnum';
4
4
 
5
5
  /** ULID canónico: 26 chars Crockford base32, primer char 0-7 (el timestamp cabe en 48 bits). */
@@ -40,4 +40,10 @@ export class PrivateSellerListQuery {
40
40
  @IsOptional()
41
41
  @Matches(/^[a-z0-9-]{1,64}$/, { message: 'callerService debe ser el nombre del lambda (kebab-case)' })
42
42
  callerService?: string;
43
+
44
+ /** `true` agrega el teléfono de cada vendedor. Por defecto no viaja: es PII. */
45
+ @Expose()
46
+ @Transform(({ value }) => value === true || value === 'true')
47
+ @IsBoolean()
48
+ includePhone?: boolean;
43
49
  }
@@ -0,0 +1,9 @@
1
+ import type { GoalListResponse } from './GoalListResponse';
2
+
3
+ /**
4
+ * Respuesta de `GET /private/retailers/{retailerId}/goals`: las metas del periodo con las tres cifras
5
+ * derivadas. Un periodo sin metas devuelve `goals: []`, no un 404.
6
+ */
7
+ export interface PrivateGoalListResponse extends GoalListResponse {
8
+ retailerId: string;
9
+ }
@@ -16,6 +16,8 @@ export interface PrivateSellerDto {
16
16
  homeStoreId: string | null;
17
17
  commissionTier: string;
18
18
  status: RetailUserStatusEnum;
19
+ /** Teléfono del vendedor. Solo viaja si se pidió `includePhone=true`; `null` si no lo tiene. */
20
+ phone?: string | null;
19
21
  }
20
22
 
21
23
  /**
@@ -17,4 +17,6 @@ export interface StoreValidationDto {
17
17
  code: string;
18
18
  name: string;
19
19
  status: StoreStatusEnum;
20
+ /** Encargado de la tienda (`retailUserId`); `null` si no tiene. Ausente en lambdas viejos. */
21
+ managerRetailUserId?: string | null;
20
22
  }
@@ -47,6 +47,7 @@ export * from './dtos/requests/TransferRetailUserRequest';
47
47
  export * from './dtos/requests/GoalListQuery';
48
48
  export * from './dtos/requests/GoalUpsertRequest';
49
49
  export * from './dtos/requests/GoalPathParams';
50
+ export * from './dtos/requests/PrivateGoalListQuery';
50
51
  export * from './dtos/requests/KpiQuery';
51
52
  export * from './dtos/requests/PrivateSellerListQuery';
52
53
 
@@ -54,5 +55,6 @@ export * from './dtos/requests/PrivateSellerListQuery';
54
55
  export * from './dtos/responses/RetailerHierarchyResponse';
55
56
  export * from './dtos/responses/GoalListResponse';
56
57
  export * from './dtos/responses/GoalUpsertResponse';
58
+ export * from './dtos/responses/PrivateGoalListResponse';
57
59
  export * from './dtos/responses/StoreKpiResponse';
58
60
  export * from './dtos/responses/SellerKpiResponse';
@@ -0,0 +1,41 @@
1
+ import type { ClientLevelEnum } from '../../../loanScoring/enums/ClientLevelEnum';
2
+ import type { SellerTableSourceStatusEnum } from '../../enums/SellerTableSourceStatusEnum';
3
+
4
+ /** Una fila de la tabla de Clientes: compras en la cadena dentro de la ventana, sin canceladas, más su crédito SK. */
5
+ export interface CustomerTableRow {
6
+ retailCustomerId: string;
7
+ name: string | null;
8
+ phone: string | null;
9
+ purchaseCount: number;
10
+ /** Precio de lo comprado (en crédito, el precio del equipo, no el enganche). */
11
+ totalSpentCents: number;
12
+ averageTicketCents: number | null;
13
+ firstPurchaseAt: string;
14
+ lastPurchaseAt: string;
15
+ lastStoreName: string | null;
16
+ /** Tienda con más compras; en empate, la de la compra más reciente. */
17
+ favoriteStoreId: string | null;
18
+ favoriteStoreName: string | null;
19
+ /** `null` sin nivel o con el crédito sin leer. */
20
+ skLevel: ClientLevelEnum | null;
21
+ /** `null` con el crédito sin leer. */
22
+ activeCreditsCount: number | null;
23
+ }
24
+
25
+ /** Estado de cada fuente. Con el crédito `UNAVAILABLE` sus campos van en `null`, nunca en `0`. */
26
+ export interface CustomerTableSources {
27
+ sales: SellerTableSourceStatusEnum.OK;
28
+ credit: SellerTableSourceStatusEnum;
29
+ }
30
+
31
+ /**
32
+ * `GET /backoffice/customers/table?from&to&limit&nextToken&storeId&sellerId&value` — tabla de Clientes
33
+ * del Portal Admin VL, paginada por última compra descendente. `from` en `null` es «Todo».
34
+ */
35
+ export interface BackofficeCustomerTableResponse {
36
+ from: string | null;
37
+ to: string;
38
+ nextToken: string | null;
39
+ sources: CustomerTableSources;
40
+ items: CustomerTableRow[];
41
+ }
@@ -0,0 +1,61 @@
1
+ import type { RetailUserStatusEnum } from '../../../retailOrg/enums/RetailUserStatusEnum';
2
+ import type { SellerTableSourceStatusEnum } from '../../enums/SellerTableSourceStatusEnum';
3
+
4
+ /** Una fila de la tabla de Vendedores: padrón + ventas de la ventana + meta + comisión. */
5
+ export interface SellerTableRow {
6
+ retailUserId: string;
7
+ /** `null` si ni el padrón ni las ventas traen nombre. */
8
+ name: string | null;
9
+ /** `null` solo si el vendedor vendió pero ya no está en el padrón. */
10
+ status: RetailUserStatusEnum | null;
11
+ phone: string | null;
12
+ storeId: string | null;
13
+ storeName: string | null;
14
+ zoneName: string | null;
15
+ /** Es el encargado (`managerRetailUserId`) de su tienda. */
16
+ isStoreAdmin: boolean;
17
+ /** Sin ventas en la ventana viaja `0`: el barrido es exhaustivo. */
18
+ salesCount: number;
19
+ placedCents: number;
20
+ averageTicketCents: number | null;
21
+ lastSaleAt: string | null;
22
+ /** Δ % contra la misma ventana 7 días antes; `null` si la ventana pasa de 7 días o no hubo base. */
23
+ weekOverWeekChangePct: number | null;
24
+ /**
25
+ * Meta mensual (`monthCents` del mes de `to`, hora de CDMX) escalada a los días de la ventana:
26
+ * `round(monthCents * días / 30)`. `null` sin meta, con metas caídas o con ventana > 90 días.
27
+ */
28
+ goalCents: number | null;
29
+ /** Lo que le pagó el último corte semanal CERRADO (`0` si no le pagó); `null` sin corte o con la fuente caída. */
30
+ commissionCents: number | null;
31
+ /** NPI M30: no lo calcula ningún lambda todavía. Siempre `null`. */
32
+ npiM30Pct: null;
33
+ }
34
+
35
+ /** Estado de cada fuente externa. Una fuente `UNAVAILABLE` deja sus campos en `null`, nunca en `0`. */
36
+ export interface SellerTableSources {
37
+ roster: SellerTableSourceStatusEnum;
38
+ goals: SellerTableSourceStatusEnum;
39
+ commission: SellerTableSourceStatusEnum;
40
+ }
41
+
42
+ /** Corte semanal del que sale `commissionCents`; días locales `YYYY-MM-DD`, ambos incluidos. */
43
+ export interface SellerTableCommissionPeriod {
44
+ periodId: string;
45
+ from: string;
46
+ to: string;
47
+ }
48
+
49
+ /**
50
+ * `GET /backoffice/sellers/table?from&to&value` — la tabla completa de Vendedores del Portal Admin
51
+ * VL, sin paginación. Incluye a los vendedores del padrón sin ventas y a los inactivos.
52
+ */
53
+ export interface BackofficeSellerTableResponse {
54
+ from: string;
55
+ to: string | null;
56
+ /** Las ventas de la ventana pasaron el tope de lectura: los números están recortados. */
57
+ truncated: boolean;
58
+ sources: SellerTableSources;
59
+ commissionPeriod: SellerTableCommissionPeriod | null;
60
+ items: SellerTableRow[];
61
+ }
@@ -0,0 +1,5 @@
1
+ /** Si una fuente de la tabla de Vendedores contestó (`OK`) o falló (`UNAVAILABLE`). */
2
+ export enum SellerTableSourceStatusEnum {
3
+ OK = 'OK',
4
+ UNAVAILABLE = 'UNAVAILABLE',
5
+ }
@@ -160,6 +160,9 @@ export * from './dtos/responses/BackofficeCustomersResponse';
160
160
  export * from './dtos/responses/BackofficeCustomerPurchasesResponse';
161
161
  export * from './dtos/responses/BackofficeStoreKpisResponse';
162
162
  export * from './dtos/responses/BackofficeSellerKpisResponse';
163
+ export * from './enums/SellerTableSourceStatusEnum';
164
+ export * from './dtos/responses/BackofficeSellerTableResponse';
165
+ export * from './dtos/responses/BackofficeCustomerTableResponse';
163
166
 
164
167
  // Contratos de eventos (PascalCase + sufijo V1)
165
168
  export * from './events/SaleCompletedV1';