@fiado/type-kit 3.504.0 → 3.506.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 (45) 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/sellerTableShapes.test.ts +43 -0
  4. package/bin/retailCommission/dtos/CommissionAccrual.d.ts +1 -1
  5. package/bin/retailCommission/dtos/CommissionPayout.d.ts +4 -1
  6. package/bin/retailCommission/dtos/PrivateLatestClosedPayout.d.ts +24 -0
  7. package/bin/retailCommission/dtos/PrivateLatestClosedPayout.js +24 -0
  8. package/bin/retailCommission/enums/CommissionBonusModeEnum.d.ts +2 -2
  9. package/bin/retailCommission/enums/CommissionBonusModeEnum.js +2 -2
  10. package/bin/retailCommission/enums/CommissionMetricEnum.d.ts +1 -1
  11. package/bin/retailCommission/enums/CommissionMetricEnum.js +1 -1
  12. package/bin/retailCommission/index.d.ts +1 -0
  13. package/bin/retailCommission/index.js +1 -0
  14. package/bin/retailOrg/dtos/requests/PrivateGoalListQuery.d.ts +12 -0
  15. package/bin/retailOrg/dtos/requests/PrivateGoalListQuery.js +40 -0
  16. package/bin/retailOrg/dtos/requests/PrivateSellerListQuery.d.ts +2 -0
  17. package/bin/retailOrg/dtos/requests/PrivateSellerListQuery.js +6 -0
  18. package/bin/retailOrg/dtos/responses/PrivateGoalListResponse.d.ts +8 -0
  19. package/bin/retailOrg/dtos/responses/PrivateGoalListResponse.js +2 -0
  20. package/bin/retailOrg/dtos/validation/PrivateSellerListResponse.d.ts +2 -0
  21. package/bin/retailOrg/dtos/validation/StoreValidationDto.d.ts +2 -0
  22. package/bin/retailOrg/index.d.ts +2 -0
  23. package/bin/retailOrg/index.js +2 -0
  24. package/bin/retailWizard/dtos/responses/BackofficeSellerTableResponse.d.ts +57 -0
  25. package/bin/retailWizard/dtos/responses/BackofficeSellerTableResponse.js +2 -0
  26. package/bin/retailWizard/enums/SellerTableSourceStatusEnum.d.ts +5 -0
  27. package/bin/retailWizard/enums/SellerTableSourceStatusEnum.js +9 -0
  28. package/bin/retailWizard/index.d.ts +2 -0
  29. package/bin/retailWizard/index.js +2 -0
  30. package/package.json +1 -1
  31. package/src/retailCommission/dtos/CommissionAccrual.ts +1 -1
  32. package/src/retailCommission/dtos/CommissionPayout.ts +4 -1
  33. package/src/retailCommission/dtos/PrivateLatestClosedPayout.ts +33 -0
  34. package/src/retailCommission/enums/CommissionBonusModeEnum.ts +2 -2
  35. package/src/retailCommission/enums/CommissionMetricEnum.ts +1 -1
  36. package/src/retailCommission/index.ts +1 -0
  37. package/src/retailOrg/dtos/requests/PrivateGoalListQuery.ts +27 -0
  38. package/src/retailOrg/dtos/requests/PrivateSellerListQuery.ts +8 -2
  39. package/src/retailOrg/dtos/responses/PrivateGoalListResponse.ts +9 -0
  40. package/src/retailOrg/dtos/validation/PrivateSellerListResponse.ts +2 -0
  41. package/src/retailOrg/dtos/validation/StoreValidationDto.ts +2 -0
  42. package/src/retailOrg/index.ts +2 -0
  43. package/src/retailWizard/dtos/responses/BackofficeSellerTableResponse.ts +61 -0
  44. package/src/retailWizard/enums/SellerTableSourceStatusEnum.ts +5 -0
  45. package/src/retailWizard/index.ts +2 -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,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
+ });
@@ -107,7 +107,7 @@ export interface CommissionAppliedBonus {
107
107
  name: string;
108
108
  lineId: string;
109
109
  sku: string;
110
- /** Posición de la pieza en el contador de la regla dentro del periodo. */
110
+ /** Posición de la pieza (o de la venta, si la regla cuenta ventas) en el contador de la regla dentro del periodo. */
111
111
  position: number;
112
112
  mode: CommissionBonusModeEnum;
113
113
  amountCents: number;
@@ -1,4 +1,5 @@
1
1
  import type { CommissionPayoutStatusEnum } from '../enums/CommissionPayoutStatusEnum';
2
+ import type { CommissionCountByEnum } from '../enums/CommissionCountByEnum';
2
3
  /**
3
4
  * El corte semanal y todo lo que cuelga de él.
4
5
  * SureKeep Fase 3 — pista Retail.
@@ -77,8 +78,10 @@ export interface CommissionAdjustment {
77
78
  export interface CommissionRuleContribution {
78
79
  ruleId: string;
79
80
  name: string;
80
- /** Piezas que pagaron esta regla. */
81
+ /** Piezas que pagaron esta regla; ventas, si la regla cuenta ventas. */
81
82
  unitsCount: number;
83
+ /** Si la regla cuenta piezas o ventas. Ausente = `PIECE`. */
84
+ countBy?: CommissionCountByEnum;
82
85
  bonusCents: number;
83
86
  /** Su parte del multiplicador, en proporción a su bono. */
84
87
  multiplierShareCents: number;
@@ -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);
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Cómo se calcula un bono.
3
3
  *
4
- * FIXED - Monto fijo en centavos por pieza.
5
- * PERCENT - Puntos base sobre el precio neto de la pieza (10000 = 100%).
4
+ * FIXED - Monto fijo en centavos por pieza, o por venta si la regla cuenta ventas.
5
+ * PERCENT - Puntos base sobre el precio neto de la pieza, o de las piezas de la venta en el alcance si la regla cuenta ventas (10000 = 100%).
6
6
  */
7
7
  export declare enum CommissionBonusModeEnum {
8
8
  FIXED = "FIXED",
@@ -4,8 +4,8 @@ exports.CommissionBonusModeEnum = void 0;
4
4
  /**
5
5
  * Cómo se calcula un bono.
6
6
  *
7
- * FIXED - Monto fijo en centavos por pieza.
8
- * PERCENT - Puntos base sobre el precio neto de la pieza (10000 = 100%).
7
+ * FIXED - Monto fijo en centavos por pieza, o por venta si la regla cuenta ventas.
8
+ * PERCENT - Puntos base sobre el precio neto de la pieza, o de las piezas de la venta en el alcance si la regla cuenta ventas (10000 = 100%).
9
9
  */
10
10
  var CommissionBonusModeEnum;
11
11
  (function (CommissionBonusModeEnum) {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Métricas de la condición de una regla.
3
3
  *
4
- * POSICION_VENTA_EN_PERIODO - Lugar de la pieza entre las del vendedor en el periodo que caen en el alcance de la regla.
4
+ * POSICION_VENTA_EN_PERIODO - Lugar de la pieza (o de la venta, si la regla cuenta ventas) entre las del vendedor en el periodo que caen en el alcance de la regla.
5
5
  * COLOCACION_PERIODO - Suma del precio neto de todo lo que el vendedor vendió en el periodo, en centavos.
6
6
  * NPI_M30_VENDEDOR - Proporción de créditos del vendedor con primer impago a 30 días, en bps. Viene del crédito.
7
7
  * SKUS_DISTINTOS_PERIODO - Cuántos SKUs distintos vendió el vendedor en el periodo.
@@ -4,7 +4,7 @@ exports.CommissionMetricEnum = void 0;
4
4
  /**
5
5
  * Métricas de la condición de una regla.
6
6
  *
7
- * POSICION_VENTA_EN_PERIODO - Lugar de la pieza entre las del vendedor en el periodo que caen en el alcance de la regla.
7
+ * POSICION_VENTA_EN_PERIODO - Lugar de la pieza (o de la venta, si la regla cuenta ventas) entre las del vendedor en el periodo que caen en el alcance de la regla.
8
8
  * COLOCACION_PERIODO - Suma del precio neto de todo lo que el vendedor vendió en el periodo, en centavos.
9
9
  * NPI_M30_VENDEDOR - Proporción de créditos del vendedor con primer impago a 30 días, en bps. Viene del crédito.
10
10
  * SKUS_DISTINTOS_PERIODO - Cuántos SKUs distintos vendió el vendedor en el periodo.
@@ -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,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,8 @@ 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';
138
140
  export * from './events/SaleCompletedV1';
139
141
  export * from './events/SaleCancelledV1';
140
142
  export * from './events/SaleCompletedV2';
@@ -168,6 +168,8 @@ __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);
171
173
  // Contratos de eventos (PascalCase + sufijo V1)
172
174
  __exportStar(require("./events/SaleCompletedV1"), exports);
173
175
  __exportStar(require("./events/SaleCancelledV1"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fiado/type-kit",
3
- "version": "3.504.0",
3
+ "version": "3.506.0",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "types": "bin/index.d.ts",
@@ -112,7 +112,7 @@ export interface CommissionAppliedBonus {
112
112
  name: string;
113
113
  lineId: string;
114
114
  sku: string;
115
- /** Posición de la pieza en el contador de la regla dentro del periodo. */
115
+ /** Posición de la pieza (o de la venta, si la regla cuenta ventas) en el contador de la regla dentro del periodo. */
116
116
  position: number;
117
117
  mode: CommissionBonusModeEnum;
118
118
  amountCents: number;
@@ -1,4 +1,5 @@
1
1
  import type { CommissionPayoutStatusEnum } from '../enums/CommissionPayoutStatusEnum';
2
+ import type { CommissionCountByEnum } from '../enums/CommissionCountByEnum';
2
3
 
3
4
  /**
4
5
  * El corte semanal y todo lo que cuelga de él.
@@ -81,8 +82,10 @@ export interface CommissionAdjustment {
81
82
  export interface CommissionRuleContribution {
82
83
  ruleId: string;
83
84
  name: string;
84
- /** Piezas que pagaron esta regla. */
85
+ /** Piezas que pagaron esta regla; ventas, si la regla cuenta ventas. */
85
86
  unitsCount: number;
87
+ /** Si la regla cuenta piezas o ventas. Ausente = `PIECE`. */
88
+ countBy?: CommissionCountByEnum;
86
89
  bonusCents: number;
87
90
  /** Su parte del multiplicador, en proporción a su bono. */
88
91
  multiplierShareCents: number;
@@ -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
+ }
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Cómo se calcula un bono.
3
3
  *
4
- * FIXED - Monto fijo en centavos por pieza.
5
- * PERCENT - Puntos base sobre el precio neto de la pieza (10000 = 100%).
4
+ * FIXED - Monto fijo en centavos por pieza, o por venta si la regla cuenta ventas.
5
+ * PERCENT - Puntos base sobre el precio neto de la pieza, o de las piezas de la venta en el alcance si la regla cuenta ventas (10000 = 100%).
6
6
  */
7
7
  export enum CommissionBonusModeEnum {
8
8
  FIXED = 'FIXED',
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Métricas de la condición de una regla.
3
3
  *
4
- * POSICION_VENTA_EN_PERIODO - Lugar de la pieza entre las del vendedor en el periodo que caen en el alcance de la regla.
4
+ * POSICION_VENTA_EN_PERIODO - Lugar de la pieza (o de la venta, si la regla cuenta ventas) entre las del vendedor en el periodo que caen en el alcance de la regla.
5
5
  * COLOCACION_PERIODO - Suma del precio neto de todo lo que el vendedor vendió en el periodo, en centavos.
6
6
  * NPI_M30_VENDEDOR - Proporción de créditos del vendedor con primer impago a 30 días, en bps. Viene del crédito.
7
7
  * SKUS_DISTINTOS_PERIODO - Cuántos SKUs distintos vendió el vendedor en el periodo.
@@ -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,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,8 @@ 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';
163
165
 
164
166
  // Contratos de eventos (PascalCase + sufijo V1)
165
167
  export * from './events/SaleCompletedV1';