@fiado/type-kit 3.546.0 → 3.548.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 (61) hide show
  1. package/_test_/unit/loanCredit/cancelLoanCreditRequest.test.ts +40 -0
  2. package/_test_/unit/loanOfferings/prepaymentMinimum.test.ts +40 -0
  3. package/_test_/unit/loanRetailAudit/loanRetailAuditContracts.test.ts +9 -0
  4. package/_test_/unit/retailWizard/saleCancellation.test.ts +25 -0
  5. package/bin/loanCredit/dtos/requests/CancelLoanCreditRequest.d.ts +7 -0
  6. package/bin/loanCredit/dtos/requests/CancelLoanCreditRequest.js +33 -0
  7. package/bin/loanCredit/dtos/responses/CreditCustomerListItem.d.ts +2 -0
  8. package/bin/loanCredit/dtos/responses/LoanBorrowerCreditItem.d.ts +2 -0
  9. package/bin/loanCredit/dtos/responses/LoanCreditDetail.d.ts +2 -0
  10. package/bin/loanCredit/dtos/responses/LoanCreditResponse.d.ts +2 -0
  11. package/bin/loanCredit/dtos/responses/LoanPrepaymentQuote.d.ts +3 -1
  12. package/bin/loanCredit/dtos/responses/SellerCreditRow.d.ts +2 -0
  13. package/bin/loanCredit/index.d.ts +1 -0
  14. package/bin/loanCredit/index.js +1 -0
  15. package/bin/loanOfferings/dtos/CreditPlan.d.ts +3 -0
  16. package/bin/loanOfferings/dtos/CreditPlan.js +8 -0
  17. package/bin/loanOfferings/dtos/PrepaymentMinimum.d.ts +12 -0
  18. package/bin/loanOfferings/dtos/PrepaymentMinimum.js +42 -0
  19. package/bin/loanOfferings/dtos/requests/CreateCreditPlanRequest.d.ts +3 -0
  20. package/bin/loanOfferings/dtos/requests/CreateCreditPlanRequest.js +8 -0
  21. package/bin/loanOfferings/dtos/requests/UpdateCreditPlanRequest.d.ts +3 -0
  22. package/bin/loanOfferings/dtos/requests/UpdateCreditPlanRequest.js +8 -0
  23. package/bin/loanOfferings/dtos/responses/CreditPlanResponse.d.ts +3 -0
  24. package/bin/loanOfferings/enums/PrepaymentMinimumModeEnum.d.ts +9 -0
  25. package/bin/loanOfferings/enums/PrepaymentMinimumModeEnum.js +13 -0
  26. package/bin/loanOfferings/index.d.ts +2 -0
  27. package/bin/loanOfferings/index.js +2 -0
  28. package/bin/loanRetailAudit/enums/RetailAuditEntityTypeEnum.d.ts +3 -1
  29. package/bin/loanRetailAudit/enums/RetailAuditEntityTypeEnum.js +2 -0
  30. package/bin/loanRetailAudit/events/AuditTrailRecordedV1.d.ts +1 -1
  31. package/bin/retailLoan/dtos/MyCreditSummary.d.ts +2 -0
  32. package/bin/retailWizard/dtos/Sale.d.ts +3 -0
  33. package/bin/retailWizard/dtos/SaleCancellation.d.ts +9 -0
  34. package/bin/retailWizard/dtos/SaleCancellation.js +2 -0
  35. package/bin/retailWizard/enums/SaleCancellationReasonEnum.d.ts +8 -0
  36. package/bin/retailWizard/enums/SaleCancellationReasonEnum.js +12 -0
  37. package/bin/retailWizard/index.d.ts +2 -0
  38. package/bin/retailWizard/index.js +2 -0
  39. package/package.json +1 -1
  40. package/src/loanCredit/dtos/requests/CancelLoanCreditRequest.ts +20 -0
  41. package/src/loanCredit/dtos/responses/CreditCustomerListItem.ts +2 -0
  42. package/src/loanCredit/dtos/responses/LoanBorrowerCreditItem.ts +2 -0
  43. package/src/loanCredit/dtos/responses/LoanCreditDetail.ts +2 -0
  44. package/src/loanCredit/dtos/responses/LoanCreditResponse.ts +2 -0
  45. package/src/loanCredit/dtos/responses/LoanPrepaymentQuote.ts +3 -1
  46. package/src/loanCredit/dtos/responses/SellerCreditRow.ts +2 -0
  47. package/src/loanCredit/index.ts +1 -0
  48. package/src/loanOfferings/dtos/CreditPlan.ts +10 -1
  49. package/src/loanOfferings/dtos/PrepaymentMinimum.ts +28 -0
  50. package/src/loanOfferings/dtos/requests/CreateCreditPlanRequest.ts +10 -1
  51. package/src/loanOfferings/dtos/requests/UpdateCreditPlanRequest.ts +10 -1
  52. package/src/loanOfferings/dtos/responses/CreditPlanResponse.ts +3 -0
  53. package/src/loanOfferings/enums/PrepaymentMinimumModeEnum.ts +9 -0
  54. package/src/loanOfferings/index.ts +2 -0
  55. package/src/loanRetailAudit/enums/RetailAuditEntityTypeEnum.ts +2 -0
  56. package/src/loanRetailAudit/events/AuditTrailRecordedV1.ts +1 -1
  57. package/src/retailLoan/dtos/MyCreditSummary.ts +2 -0
  58. package/src/retailWizard/dtos/Sale.ts +3 -0
  59. package/src/retailWizard/dtos/SaleCancellation.ts +10 -0
  60. package/src/retailWizard/enums/SaleCancellationReasonEnum.ts +8 -0
  61. package/src/retailWizard/index.ts +2 -0
@@ -0,0 +1,40 @@
1
+ import 'reflect-metadata';
2
+ import { plainToInstance } from 'class-transformer';
3
+ import { validate } from 'class-validator';
4
+ import { CancelLoanCreditRequest } from '../../../src/loanCredit/index';
5
+ import type { LoanCreditResponse } from '../../../src/loanCredit/index';
6
+
7
+ const errorsOf = async (body: Record<string, unknown>): Promise<string[]> => {
8
+ const errors = await validate(plainToInstance(CancelLoanCreditRequest, body));
9
+ return errors.map((error) => error.property);
10
+ };
11
+
12
+ const VALID = { saleId: '01M5B1V5R2KZ90G8CNEA8TTC46', reason: 'El cliente se arrepintió' };
13
+
14
+ describe('CancelLoanCreditRequest', () => {
15
+ it('acepta la venta y el motivo', async () => {
16
+ expect(await errorsOf(VALID)).toEqual([]);
17
+ });
18
+
19
+ it('exige saleId y reason', async () => {
20
+ expect((await errorsOf({})).sort()).toEqual(['reason', 'saleId']);
21
+ });
22
+
23
+ it('rechaza saleId o reason vacíos', async () => {
24
+ expect(await errorsOf({ ...VALID, saleId: '' })).toEqual(['saleId']);
25
+ expect(await errorsOf({ ...VALID, reason: '' })).toEqual(['reason']);
26
+ });
27
+
28
+ it('rechaza un saleId con caracteres fuera de la referencia del hecho', async () => {
29
+ expect(await errorsOf({ ...VALID, saleId: 'SALE#123' })).toEqual(['saleId']);
30
+ });
31
+ });
32
+
33
+ describe('LoanCreditResponse.hasPayments', () => {
34
+ it('es opcional y booleano', () => {
35
+ const partial: Pick<LoanCreditResponse, 'hasPayments'> = {};
36
+ const withFlag: Pick<LoanCreditResponse, 'hasPayments'> = { hasPayments: true };
37
+ expect(partial.hasPayments).toBeUndefined();
38
+ expect(withFlag.hasPayments).toBe(true);
39
+ });
40
+ });
@@ -0,0 +1,40 @@
1
+ import 'reflect-metadata';
2
+ import { plainToInstance } from 'class-transformer';
3
+ import { validate } from 'class-validator';
4
+ import {
5
+ PrepaymentMinimum,
6
+ PrepaymentMinimumModeEnum,
7
+ UpdateCreditPlanRequest,
8
+ } from '../../../src/loanOfferings/index';
9
+
10
+ const errorsOf = async (prepaymentMinimum: Record<string, unknown>): Promise<string[]> => {
11
+ const dto = plainToInstance(UpdateCreditPlanRequest, { prepaymentMinimum }, { excludeExtraneousValues: true });
12
+ const errors = await validate(dto as object);
13
+ return errors.flatMap((error) => (error.children ?? []).map((child) => child.property).concat(error.children?.length ? [] : [error.property]));
14
+ };
15
+
16
+ describe('UpdateCreditPlanRequest.prepaymentMinimum', () => {
17
+ it('tipa el mínimo del abono y conserva sus campos', async () => {
18
+ const dto = plainToInstance(
19
+ UpdateCreditPlanRequest,
20
+ { prepaymentMinimum: { mode: 'PERCENT_OF_PERIOD_PAYMENT', periodPaymentPct: 0.5 } },
21
+ { excludeExtraneousValues: true },
22
+ );
23
+ expect(await validate(dto as object)).toHaveLength(0);
24
+ expect(dto.prepaymentMinimum).toBeInstanceOf(PrepaymentMinimum);
25
+ expect(dto.prepaymentMinimum?.periodPaymentPct).toBe(0.5);
26
+ });
27
+
28
+ it('acepta cualquier monto, porcentaje del pago del periodo y monto fijo', async () => {
29
+ expect(await errorsOf({ mode: PrepaymentMinimumModeEnum.ANY })).toEqual([]);
30
+ expect(await errorsOf({ mode: PrepaymentMinimumModeEnum.PERCENT_OF_PERIOD_PAYMENT, periodPaymentPct: 1 })).toEqual([]);
31
+ expect(await errorsOf({ mode: PrepaymentMinimumModeEnum.FIXED, amountCents: 10_000 })).toEqual([]);
32
+ });
33
+
34
+ it('rechaza un modo desconocido, un porcentaje fuera de (0, 1] y un monto menor a un centavo', async () => {
35
+ expect(await errorsOf({ mode: 'HALF' })).toContain('mode');
36
+ expect(await errorsOf({ mode: PrepaymentMinimumModeEnum.PERCENT_OF_PERIOD_PAYMENT, periodPaymentPct: 1.5 })).toContain('periodPaymentPct');
37
+ expect(await errorsOf({ mode: PrepaymentMinimumModeEnum.PERCENT_OF_PERIOD_PAYMENT, periodPaymentPct: 0 })).toContain('periodPaymentPct');
38
+ expect(await errorsOf({ mode: PrepaymentMinimumModeEnum.FIXED, amountCents: 0 })).toContain('amountCents');
39
+ });
40
+ });
@@ -123,6 +123,15 @@ describe('ListAuditTrailQuery', () => {
123
123
  });
124
124
 
125
125
  describe('catálogos', () => {
126
+ it('incluye PROSPECT y RETAIL_CUSTOMER del wizard y los acepta en el evento', () => {
127
+ for (const entityType of ['PROSPECT', 'RETAIL_CUSTOMER']) {
128
+ expect(AUDIT_TRAIL_ENTITY_TYPES).toContain(entityType);
129
+ expect(errorsOf(AuditTrailRecordedV1, { ...validEvent, entityType })).toEqual([]);
130
+ }
131
+ expect(RetailAuditEntityTypeEnum.PROSPECT).toBe('PROSPECT');
132
+ expect(RetailAuditEntityTypeEnum.RETAIL_CUSTOMER).toBe('RETAIL_CUSTOMER');
133
+ });
134
+
126
135
  it('AUDIT_TRAIL_ENTITY_TYPES une Loan y Retail sin repetidos', () => {
127
136
  const all = [...Object.values(LoanAuditEntityTypeEnum), ...Object.values(RetailAuditEntityTypeEnum)];
128
137
  expect([...AUDIT_TRAIL_ENTITY_TYPES].sort()).toEqual([...all].sort());
@@ -0,0 +1,25 @@
1
+ import 'reflect-metadata';
2
+ import { SaleCancellationReasonEnum } from '../../../src/retailWizard/index';
3
+ import type { Sale, SaleCancellation } from '../../../src/retailWizard/index';
4
+
5
+ describe('SaleCancellation', () => {
6
+ it('cataloga los cinco motivos por los que no se puede cancelar', () => {
7
+ expect(Object.values(SaleCancellationReasonEnum).sort()).toEqual([
8
+ 'CANCEL_WINDOW_EXPIRED',
9
+ 'CREDIT_HAS_PAYMENTS',
10
+ 'CREDIT_NOT_CANCELLABLE',
11
+ 'IMEI_NOT_RETURNABLE',
12
+ 'SALE_ALREADY_CANCELLED',
13
+ ]);
14
+ });
15
+
16
+ it('viaja opcional en la venta', () => {
17
+ const cancellation: SaleCancellation = {
18
+ allowed: false,
19
+ reason: SaleCancellationReasonEnum.CREDIT_HAS_PAYMENTS,
20
+ windowEndsAt: '2026-10-26T00:00:00.000Z',
21
+ };
22
+ const sale: Pick<Sale, 'cancellation'> = { cancellation };
23
+ expect(sale.cancellation?.allowed).toBe(false);
24
+ });
25
+ });
@@ -0,0 +1,7 @@
1
+ /** Body de `POST /private/credits/:creditId/cancel` (loan-credit-business): la venta que se cancela. */
2
+ export declare class CancelLoanCreditRequest {
3
+ /** Venta que origina la cancelación; es la referencia del aviso al cliente. */
4
+ saleId: string;
5
+ /** Motivo de la cancelación; va a la auditoría del crédito y no se loguea. */
6
+ reason: string;
7
+ }
@@ -0,0 +1,33 @@
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.CancelLoanCreditRequest = void 0;
13
+ const class_transformer_1 = require("class-transformer");
14
+ const class_validator_1 = require("class-validator");
15
+ /** Body de `POST /private/credits/:creditId/cancel` (loan-credit-business): la venta que se cancela. */
16
+ class CancelLoanCreditRequest {
17
+ }
18
+ exports.CancelLoanCreditRequest = CancelLoanCreditRequest;
19
+ __decorate([
20
+ (0, class_transformer_1.Expose)(),
21
+ (0, class_validator_1.IsString)(),
22
+ (0, class_validator_1.IsNotEmpty)(),
23
+ (0, class_validator_1.MaxLength)(120),
24
+ (0, class_validator_1.Matches)(/^[A-Za-z0-9._:-]+$/),
25
+ __metadata("design:type", String)
26
+ ], CancelLoanCreditRequest.prototype, "saleId", void 0);
27
+ __decorate([
28
+ (0, class_transformer_1.Expose)(),
29
+ (0, class_validator_1.IsString)(),
30
+ (0, class_validator_1.IsNotEmpty)(),
31
+ (0, class_validator_1.MaxLength)(500),
32
+ __metadata("design:type", String)
33
+ ], CancelLoanCreditRequest.prototype, "reason", void 0);
@@ -25,6 +25,8 @@ export interface CreditCustomerCredit {
25
25
  settledCreditsCount: number | null;
26
26
  writtenOffCreditsCount: number | null;
27
27
  outstandingBalanceCents: number | null;
28
+ /** Deuda total de sus créditos vivos: capital, interés e IVA que faltan de las cuotas abiertas. `null` = no aplica. */
29
+ totalDebtCents?: number | null;
28
30
  arrearsDays: number | null;
29
31
  lastPaymentAt: string | null;
30
32
  /** Ausente en créditos sin pago desde que existe el campo: el front cae a `lastPaymentAt`. */
@@ -9,6 +9,8 @@ export interface LoanBorrowerCreditItem extends LoanCreditResponse {
9
9
  paidInstallments: number;
10
10
  /** `null` = no aplica (el crédito se canceló o caducó); `0` = ya no debe nada. */
11
11
  outstandingBalanceCents: number | null;
12
+ /** Deuda total: capital, interés e IVA que faltan de las cuotas abiertas (PENDING u OVERDUE). `null` = no aplica. */
13
+ totalDebtCents?: number | null;
12
14
  /** Días desde el vencimiento impago más viejo; `0` al día; `null` si no hay atraso que medir. */
13
15
  overdueDays: number | null;
14
16
  /** Suma del TOTAL de las cuotas vencidas impagas. Sigue a `overdueDays` en `null`/`0`. */
@@ -13,6 +13,8 @@ export interface LoanCreditDetail extends LoanCreditResponse {
13
13
  financier: SaleFinancierEnum;
14
14
  paidInstallments: number;
15
15
  outstandingBalanceCents: number | null;
16
+ /** Deuda total: capital, interés e IVA que faltan de las cuotas abiertas (PENDING u OVERDUE). `null` = no aplica. */
17
+ totalDebtCents?: number | null;
16
18
  overdueDays: number | null;
17
19
  overdueAmountCents: number | null;
18
20
  /** Cuotas vencidas impagas. `0` = nada vencido; `null` acompaña a `overdueDays` en null. */
@@ -51,6 +51,8 @@ export interface LoanCreditResponse {
51
51
  effectiveTerms?: EffectiveTermsSnapshot | null;
52
52
  activatedAt?: string;
53
53
  voluntaryCancelDeadline?: string;
54
+ /** Si ya se abonó alguna cuota (el enganche no cuenta); solo lo traen la lectura y la cancelación privadas. */
55
+ hasPayments?: boolean;
54
56
  firstDueDate?: string;
55
57
  lastDueDate?: string;
56
58
  createdBy: string;
@@ -3,8 +3,10 @@ export interface LoanPrepaymentQuote {
3
3
  creditId: string;
4
4
  /** Saldo insoluto que se le informa al cliente. */
5
5
  outstandingCapitalCents: number;
6
- /** Pago del periodo: el mínimo del abono. */
6
+ /** Pago del periodo. */
7
7
  periodPaymentCents: number;
8
+ /** Mínimo del abono según el plan del crédito; con mínimo `ANY`, 1 centavo. */
9
+ minAmountCents?: number;
8
10
  /** Monto de liquidación anticipada: el techo del abono. */
9
11
  settlementAmountCents: number;
10
12
  }
@@ -17,6 +17,8 @@ export interface SellerCreditRow {
17
17
  summaryUnavailable: boolean;
18
18
  paidInstallments: number | null;
19
19
  outstandingBalanceCents: number | null;
20
+ /** Deuda total: capital, interés e IVA que faltan de las cuotas abiertas (PENDING u OVERDUE). `null` = no aplica. */
21
+ totalDebtCents?: number | null;
20
22
  overdueDays: number | null;
21
23
  overdueAmountCents: number | null;
22
24
  /** Primera cuota que todavía se debe; `null` si ya no debe nada o si el plan no se leyó. */
@@ -117,6 +117,7 @@ export * from './dtos/WriteOffConfirmations';
117
117
  export * from './dtos/requests/BackofficeSettleCreditRequest';
118
118
  export * from './dtos/requests/BackofficeListWriteOffCandidatesRequest';
119
119
  export * from './dtos/requests/BackofficeWriteOffCreditRequest';
120
+ export * from './dtos/requests/CancelLoanCreditRequest';
120
121
  export * from './dtos/requests/BackofficeCollectWrittenOffCreditRequest';
121
122
  export * from './dtos/requests/BackofficeProposeRestructureRequest';
122
123
  export * from './dtos/requests/BackofficeApproveRestructureRequest';
@@ -159,6 +159,7 @@ __exportStar(require("./dtos/WriteOffConfirmations"), exports);
159
159
  __exportStar(require("./dtos/requests/BackofficeSettleCreditRequest"), exports);
160
160
  __exportStar(require("./dtos/requests/BackofficeListWriteOffCandidatesRequest"), exports);
161
161
  __exportStar(require("./dtos/requests/BackofficeWriteOffCreditRequest"), exports);
162
+ __exportStar(require("./dtos/requests/CancelLoanCreditRequest"), exports);
162
163
  __exportStar(require("./dtos/requests/BackofficeCollectWrittenOffCreditRequest"), exports);
163
164
  __exportStar(require("./dtos/requests/BackofficeProposeRestructureRequest"), exports);
164
165
  __exportStar(require("./dtos/requests/BackofficeApproveRestructureRequest"), exports);
@@ -2,6 +2,7 @@ import { CreditPlanLevelEnum } from '../enums/CreditPlanLevelEnum';
2
2
  import { CreditPlanStatusEnum } from '../enums/CreditPlanStatusEnum';
3
3
  import { ProductTierEnum } from '../enums/ProductTierEnum';
4
4
  import { SaleTypeEnum } from '../enums/SaleTypeEnum';
5
+ import { PrepaymentMinimum } from './PrepaymentMinimum';
5
6
  /**
6
7
  * CreditPlan — plan de crédito del catálogo SOFOM SureKeep (modelo-datos §6.1 · M6 §4).
7
8
  * Entidad completa del dominio `loan-offerings-business` (SureKeep Fase 1 — pista Loan).
@@ -49,4 +50,6 @@ export declare class CreditPlan {
49
50
  updatedBy: string;
50
51
  createdAt: string;
51
52
  updatedAt: string;
53
+ /** Mínimo del abono a capital; ausente = `ANY` (cualquier monto). */
54
+ prepaymentMinimum?: PrepaymentMinimum;
52
55
  }
@@ -17,6 +17,7 @@ const CreditPlanLevelEnum_1 = require("../enums/CreditPlanLevelEnum");
17
17
  const CreditPlanStatusEnum_1 = require("../enums/CreditPlanStatusEnum");
18
18
  const ProductTierEnum_1 = require("../enums/ProductTierEnum");
19
19
  const SaleTypeEnum_1 = require("../enums/SaleTypeEnum");
20
+ const PrepaymentMinimum_1 = require("./PrepaymentMinimum");
20
21
  /**
21
22
  * CreditPlan — plan de crédito del catálogo SOFOM SureKeep (modelo-datos §6.1 · M6 §4).
22
23
  * Entidad completa del dominio `loan-offerings-business` (SureKeep Fase 1 — pista Loan).
@@ -182,3 +183,10 @@ __decorate([
182
183
  (0, class_validator_1.Matches)(regex_1.regexIso8601, { message: 'updatedAt debe ser una fecha ISO 8601' }),
183
184
  __metadata("design:type", String)
184
185
  ], CreditPlan.prototype, "updatedAt", void 0);
186
+ __decorate([
187
+ (0, class_transformer_1.Expose)(),
188
+ (0, class_validator_1.IsOptional)(),
189
+ (0, class_validator_1.ValidateNested)(),
190
+ (0, class_transformer_1.Type)(() => PrepaymentMinimum_1.PrepaymentMinimum),
191
+ __metadata("design:type", PrepaymentMinimum_1.PrepaymentMinimum)
192
+ ], CreditPlan.prototype, "prepaymentMinimum", void 0);
@@ -0,0 +1,12 @@
1
+ import { PrepaymentMinimumModeEnum } from '../enums/PrepaymentMinimumModeEnum';
2
+ /**
3
+ * Mínimo del abono a capital de un plan. El máximo no depende del plan: es lo que falta para liquidar.
4
+ * Sin este campo en el plan, el mínimo es `ANY`.
5
+ */
6
+ export declare class PrepaymentMinimum {
7
+ mode: PrepaymentMinimumModeEnum;
8
+ /** Sólo `PERCENT_OF_PERIOD_PAYMENT`: decimal sobre 1 del pago del periodo (`0.5` = 50 %). */
9
+ periodPaymentPct?: number | null;
10
+ /** Sólo `FIXED`: monto mínimo en cents. */
11
+ amountCents?: number | null;
12
+ }
@@ -0,0 +1,42 @@
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.PrepaymentMinimum = void 0;
13
+ const class_transformer_1 = require("class-transformer");
14
+ const class_validator_1 = require("class-validator");
15
+ const PrepaymentMinimumModeEnum_1 = require("../enums/PrepaymentMinimumModeEnum");
16
+ /**
17
+ * Mínimo del abono a capital de un plan. El máximo no depende del plan: es lo que falta para liquidar.
18
+ * Sin este campo en el plan, el mínimo es `ANY`.
19
+ */
20
+ class PrepaymentMinimum {
21
+ }
22
+ exports.PrepaymentMinimum = PrepaymentMinimum;
23
+ __decorate([
24
+ (0, class_transformer_1.Expose)(),
25
+ (0, class_validator_1.IsEnum)(PrepaymentMinimumModeEnum_1.PrepaymentMinimumModeEnum),
26
+ __metadata("design:type", String)
27
+ ], PrepaymentMinimum.prototype, "mode", void 0);
28
+ __decorate([
29
+ (0, class_transformer_1.Expose)(),
30
+ (0, class_validator_1.IsOptional)(),
31
+ (0, class_validator_1.IsNumber)(),
32
+ (0, class_validator_1.Min)(0.0001),
33
+ (0, class_validator_1.Max)(1),
34
+ __metadata("design:type", Number)
35
+ ], PrepaymentMinimum.prototype, "periodPaymentPct", void 0);
36
+ __decorate([
37
+ (0, class_transformer_1.Expose)(),
38
+ (0, class_validator_1.IsOptional)(),
39
+ (0, class_validator_1.IsInt)(),
40
+ (0, class_validator_1.Min)(1),
41
+ __metadata("design:type", Number)
42
+ ], PrepaymentMinimum.prototype, "amountCents", void 0);
@@ -1,6 +1,7 @@
1
1
  import { CreditPlanLevelEnum } from '../../enums/CreditPlanLevelEnum';
2
2
  import { ProductTierEnum } from '../../enums/ProductTierEnum';
3
3
  import { SaleTypeEnum } from '../../enums/SaleTypeEnum';
4
+ import { PrepaymentMinimum } from '../PrepaymentMinimum';
4
5
  /**
5
6
  * Body de POST /credit-plans — alta de un plan (SureKeep Fase 1 — pista Loan).
6
7
  * Campos server-assigned (`planId`, `version`, `ivaOnInterest`=0.16, `status`, auditoría) NO viajan
@@ -24,4 +25,6 @@ export declare class CreateCreditPlanRequest {
24
25
  maxSciScore?: number | null;
25
26
  validFrom?: string | null;
26
27
  validUntil?: string | null;
28
+ /** Mínimo del abono a capital; ausente = sin cambios (en el alta: `ANY`). */
29
+ prepaymentMinimum?: PrepaymentMinimum;
27
30
  }
@@ -15,6 +15,7 @@ const class_validator_1 = require("class-validator");
15
15
  const CreditPlanLevelEnum_1 = require("../../enums/CreditPlanLevelEnum");
16
16
  const ProductTierEnum_1 = require("../../enums/ProductTierEnum");
17
17
  const SaleTypeEnum_1 = require("../../enums/SaleTypeEnum");
18
+ const PrepaymentMinimum_1 = require("../PrepaymentMinimum");
18
19
  /**
19
20
  * Body de POST /credit-plans — alta de un plan (SureKeep Fase 1 — pista Loan).
20
21
  * Campos server-assigned (`planId`, `version`, `ivaOnInterest`=0.16, `status`, auditoría) NO viajan
@@ -135,3 +136,10 @@ __decorate([
135
136
  (0, class_validator_1.IsString)(),
136
137
  __metadata("design:type", String)
137
138
  ], CreateCreditPlanRequest.prototype, "validUntil", void 0);
139
+ __decorate([
140
+ (0, class_transformer_1.Expose)(),
141
+ (0, class_validator_1.IsOptional)(),
142
+ (0, class_validator_1.ValidateNested)(),
143
+ (0, class_transformer_1.Type)(() => PrepaymentMinimum_1.PrepaymentMinimum),
144
+ __metadata("design:type", PrepaymentMinimum_1.PrepaymentMinimum)
145
+ ], CreateCreditPlanRequest.prototype, "prepaymentMinimum", void 0);
@@ -1,5 +1,6 @@
1
1
  import { ProductTierEnum } from '../../enums/ProductTierEnum';
2
2
  import { SaleTypeEnum } from '../../enums/SaleTypeEnum';
3
+ import { PrepaymentMinimum } from '../PrepaymentMinimum';
3
4
  /**
4
5
  * Body de PUT /credit-plans/:planId — edición parcial de parámetros del plan (todos opcionales).
5
6
  * En F1 el PUT puede editar `min/maxSciScore` por-plan (DEC-004); el guard atómico anti-huecos
@@ -22,4 +23,6 @@ export declare class UpdateCreditPlanRequest {
22
23
  maxSciScore?: number | null;
23
24
  validFrom?: string | null;
24
25
  validUntil?: string | null;
26
+ /** Mínimo del abono a capital; ausente = sin cambios (en el alta: `ANY`). */
27
+ prepaymentMinimum?: PrepaymentMinimum;
25
28
  }
@@ -14,6 +14,7 @@ const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
15
  const ProductTierEnum_1 = require("../../enums/ProductTierEnum");
16
16
  const SaleTypeEnum_1 = require("../../enums/SaleTypeEnum");
17
+ const PrepaymentMinimum_1 = require("../PrepaymentMinimum");
17
18
  /**
18
19
  * Body de PUT /credit-plans/:planId — edición parcial de parámetros del plan (todos opcionales).
19
20
  * En F1 el PUT puede editar `min/maxSciScore` por-plan (DEC-004); el guard atómico anti-huecos
@@ -132,3 +133,10 @@ __decorate([
132
133
  (0, class_validator_1.IsString)(),
133
134
  __metadata("design:type", String)
134
135
  ], UpdateCreditPlanRequest.prototype, "validUntil", void 0);
136
+ __decorate([
137
+ (0, class_transformer_1.Expose)(),
138
+ (0, class_validator_1.IsOptional)(),
139
+ (0, class_validator_1.ValidateNested)(),
140
+ (0, class_transformer_1.Type)(() => PrepaymentMinimum_1.PrepaymentMinimum),
141
+ __metadata("design:type", PrepaymentMinimum_1.PrepaymentMinimum)
142
+ ], UpdateCreditPlanRequest.prototype, "prepaymentMinimum", void 0);
@@ -2,6 +2,7 @@ import { CreditPlanLevelEnum } from '../../enums/CreditPlanLevelEnum';
2
2
  import { CreditPlanStatusEnum } from '../../enums/CreditPlanStatusEnum';
3
3
  import { ProductTierEnum } from '../../enums/ProductTierEnum';
4
4
  import { SaleTypeEnum } from '../../enums/SaleTypeEnum';
5
+ import { PrepaymentMinimum } from '../PrepaymentMinimum';
5
6
  /**
6
7
  * Shape de salida de un plan de crédito (GET / POST / PUT de /credit-plans).
7
8
  * Montos en cents; porcentajes y TNA en decimal.
@@ -32,4 +33,6 @@ export interface CreditPlanResponse {
32
33
  updatedBy: string;
33
34
  createdAt: string;
34
35
  updatedAt: string;
36
+ /** Mínimo del abono a capital; ausente = `ANY` (cualquier monto). */
37
+ prepaymentMinimum?: PrepaymentMinimum;
35
38
  }
@@ -0,0 +1,9 @@
1
+ /** Cómo se fija el mínimo del abono a capital de un plan. */
2
+ export declare enum PrepaymentMinimumModeEnum {
3
+ /** Sin mínimo: el cliente abona el monto que quiera. */
4
+ ANY = "ANY",
5
+ /** Un porcentaje del pago del periodo (`periodPaymentPct`). */
6
+ PERCENT_OF_PERIOD_PAYMENT = "PERCENT_OF_PERIOD_PAYMENT",
7
+ /** Un monto fijo (`amountCents`). */
8
+ FIXED = "FIXED"
9
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PrepaymentMinimumModeEnum = void 0;
4
+ /** Cómo se fija el mínimo del abono a capital de un plan. */
5
+ var PrepaymentMinimumModeEnum;
6
+ (function (PrepaymentMinimumModeEnum) {
7
+ /** Sin mínimo: el cliente abona el monto que quiera. */
8
+ PrepaymentMinimumModeEnum["ANY"] = "ANY";
9
+ /** Un porcentaje del pago del periodo (`periodPaymentPct`). */
10
+ PrepaymentMinimumModeEnum["PERCENT_OF_PERIOD_PAYMENT"] = "PERCENT_OF_PERIOD_PAYMENT";
11
+ /** Un monto fijo (`amountCents`). */
12
+ PrepaymentMinimumModeEnum["FIXED"] = "FIXED";
13
+ })(PrepaymentMinimumModeEnum || (exports.PrepaymentMinimumModeEnum = PrepaymentMinimumModeEnum = {}));
@@ -15,7 +15,9 @@ export * from './enums/StorePolicyPhaseEnum';
15
15
  export * from './enums/SegmentStatusEnum';
16
16
  export * from './enums/SegmentColorSlotEnum';
17
17
  export * from './enums/SegmentFilterIdEnum';
18
+ export * from './enums/PrepaymentMinimumModeEnum';
18
19
  export * from './dtos/CreditPlan';
20
+ export * from './dtos/PrepaymentMinimum';
19
21
  export * from './dtos/Financier';
20
22
  export * from './dtos/RetailerCreditPlan';
21
23
  export * from './dtos/PromotionEffect';
@@ -32,8 +32,10 @@ __exportStar(require("./enums/StorePolicyPhaseEnum"), exports);
32
32
  __exportStar(require("./enums/SegmentStatusEnum"), exports);
33
33
  __exportStar(require("./enums/SegmentColorSlotEnum"), exports);
34
34
  __exportStar(require("./enums/SegmentFilterIdEnum"), exports);
35
+ __exportStar(require("./enums/PrepaymentMinimumModeEnum"), exports);
35
36
  // Entity DTOs
36
37
  __exportStar(require("./dtos/CreditPlan"), exports);
38
+ __exportStar(require("./dtos/PrepaymentMinimum"), exports);
37
39
  __exportStar(require("./dtos/Financier"), exports);
38
40
  __exportStar(require("./dtos/RetailerCreditPlan"), exports);
39
41
  __exportStar(require("./dtos/PromotionEffect"), exports);
@@ -13,5 +13,7 @@ export declare enum RetailAuditEntityTypeEnum {
13
13
  COMMISSION_PAYOUT = "COMMISSION_PAYOUT",
14
14
  COMMISSION_ADJUSTMENT = "COMMISSION_ADJUSTMENT",
15
15
  COMMISSION_RULE = "COMMISSION_RULE",
16
- COMMISSION_POLICY = "COMMISSION_POLICY"
16
+ COMMISSION_POLICY = "COMMISSION_POLICY",
17
+ PROSPECT = "PROSPECT",
18
+ RETAIL_CUSTOMER = "RETAIL_CUSTOMER"
17
19
  }
@@ -18,4 +18,6 @@ var RetailAuditEntityTypeEnum;
18
18
  RetailAuditEntityTypeEnum["COMMISSION_ADJUSTMENT"] = "COMMISSION_ADJUSTMENT";
19
19
  RetailAuditEntityTypeEnum["COMMISSION_RULE"] = "COMMISSION_RULE";
20
20
  RetailAuditEntityTypeEnum["COMMISSION_POLICY"] = "COMMISSION_POLICY";
21
+ RetailAuditEntityTypeEnum["PROSPECT"] = "PROSPECT";
22
+ RetailAuditEntityTypeEnum["RETAIL_CUSTOMER"] = "RETAIL_CUSTOMER";
21
23
  })(RetailAuditEntityTypeEnum || (exports.RetailAuditEntityTypeEnum = RetailAuditEntityTypeEnum = {}));
@@ -10,7 +10,7 @@ export declare class AuditTrailRecordedV1 {
10
10
  action: AuditTrailActionEnum;
11
11
  changes: AuditTrailChange[];
12
12
  context: AuditTrailContextEntry[];
13
- /** userId del actor, o `system` si lo disparó un proceso interno. */
13
+ /** userId del actor; nunca `system`: sin usuario va el nombre del lambda que lo disparó. */
14
14
  performedBy: string;
15
15
  sourceLambda: string;
16
16
  occurredAt: string;
@@ -25,5 +25,7 @@ export interface MyCreditSummary {
25
25
  totalInstallments: number;
26
26
  paidInstallments: number;
27
27
  remainingBalance: number | null;
28
+ /** Deuda total en pesos: capital, interés e IVA que faltan de las cuotas abiertas. `null` = no aplica. */
29
+ totalDebt?: number | null;
28
30
  overdue?: MyOverdue;
29
31
  }
@@ -7,6 +7,7 @@ import type { CentralSyncStatusEnum } from '../enums/CentralSyncStatusEnum';
7
7
  import type { SalePaymentDetail } from './SalePaymentDetail';
8
8
  import type { SaleLine } from './SaleLine';
9
9
  import type { SalePromotionRef } from '../../retailPromotions/dtos/SalePromotionRef';
10
+ import type { SaleCancellation } from './SaleCancellation';
10
11
  /**
11
12
  * Venta (modelo-datos §3). pk `SALE#<saleId>` · sk `META` · 4 GSIs (`retailerId-soldAt-index`,
12
13
  * `storeId-soldAt-index`, `seller-soldAt-index`, `customerId-soldAt-index`). Unicidad de folio vía
@@ -65,6 +66,8 @@ export interface Sale {
65
66
  cancelledAt: string | null;
66
67
  /** Reason OBLIGATORIO en cancelación (AuditTrail) — flujo C. */
67
68
  cancelReason: string | null;
69
+ /** Si la venta se puede cancelar hoy y, si no, por qué; solo lo trae el detalle del backoffice. */
70
+ cancellation?: SaleCancellation;
68
71
  /**
69
72
  * SNAPSHOT de identidad y contexto, congelado al cerrar la venta. NO se refresca: una venta es la
70
73
  * fotografía de un hecho, no la caché de un perfil. Si el cliente corrige su nombre, la venta
@@ -0,0 +1,9 @@
1
+ import type { SaleCancellationReasonEnum } from '../enums/SaleCancellationReasonEnum';
2
+ /** Si la venta se puede cancelar hoy; el backend valida igual al cancelar. */
3
+ export interface SaleCancellation {
4
+ allowed: boolean;
5
+ /** Ausente cuando `allowed` es true. */
6
+ reason?: SaleCancellationReasonEnum;
7
+ /** Fin de la ventana de cancelación voluntaria, ISO-8601. */
8
+ windowEndsAt?: string;
9
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,8 @@
1
+ /** Por qué una venta no se puede cancelar; coincide con el `code` que respondería la cancelación. */
2
+ export declare enum SaleCancellationReasonEnum {
3
+ SALE_ALREADY_CANCELLED = "SALE_ALREADY_CANCELLED",
4
+ IMEI_NOT_RETURNABLE = "IMEI_NOT_RETURNABLE",
5
+ CANCEL_WINDOW_EXPIRED = "CANCEL_WINDOW_EXPIRED",
6
+ CREDIT_HAS_PAYMENTS = "CREDIT_HAS_PAYMENTS",
7
+ CREDIT_NOT_CANCELLABLE = "CREDIT_NOT_CANCELLABLE"
8
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SaleCancellationReasonEnum = void 0;
4
+ /** Por qué una venta no se puede cancelar; coincide con el `code` que respondería la cancelación. */
5
+ var SaleCancellationReasonEnum;
6
+ (function (SaleCancellationReasonEnum) {
7
+ SaleCancellationReasonEnum["SALE_ALREADY_CANCELLED"] = "SALE_ALREADY_CANCELLED";
8
+ SaleCancellationReasonEnum["IMEI_NOT_RETURNABLE"] = "IMEI_NOT_RETURNABLE";
9
+ SaleCancellationReasonEnum["CANCEL_WINDOW_EXPIRED"] = "CANCEL_WINDOW_EXPIRED";
10
+ SaleCancellationReasonEnum["CREDIT_HAS_PAYMENTS"] = "CREDIT_HAS_PAYMENTS";
11
+ SaleCancellationReasonEnum["CREDIT_NOT_CANCELLABLE"] = "CREDIT_NOT_CANCELLABLE";
12
+ })(SaleCancellationReasonEnum || (exports.SaleCancellationReasonEnum = SaleCancellationReasonEnum = {}));
@@ -57,6 +57,8 @@ export * from './dtos/AccessorySaleLine';
57
57
  export * from './dtos/WizardSession';
58
58
  export * from './dtos/OtpVerification';
59
59
  export * from './dtos/Sale';
60
+ export * from './dtos/SaleCancellation';
61
+ export * from './enums/SaleCancellationReasonEnum';
60
62
  export * from './dtos/Prospect';
61
63
  export * from './dtos/PaginatedResult';
62
64
  export * from './dtos/requests/StartSessionRequest';
@@ -80,6 +80,8 @@ __exportStar(require("./dtos/AccessorySaleLine"), exports);
80
80
  __exportStar(require("./dtos/WizardSession"), exports);
81
81
  __exportStar(require("./dtos/OtpVerification"), exports);
82
82
  __exportStar(require("./dtos/Sale"), exports);
83
+ __exportStar(require("./dtos/SaleCancellation"), exports);
84
+ __exportStar(require("./enums/SaleCancellationReasonEnum"), exports);
83
85
  __exportStar(require("./dtos/Prospect"), exports);
84
86
  // Paginación genérica
85
87
  __exportStar(require("./dtos/PaginatedResult"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fiado/type-kit",
3
- "version": "3.546.0",
3
+ "version": "3.548.0",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "types": "bin/index.d.ts",
@@ -0,0 +1,20 @@
1
+ import { Expose } from 'class-transformer';
2
+ import { IsNotEmpty, IsString, Matches, MaxLength } from 'class-validator';
3
+
4
+ /** Body de `POST /private/credits/:creditId/cancel` (loan-credit-business): la venta que se cancela. */
5
+ export class CancelLoanCreditRequest {
6
+ /** Venta que origina la cancelación; es la referencia del aviso al cliente. */
7
+ @Expose()
8
+ @IsString()
9
+ @IsNotEmpty()
10
+ @MaxLength(120)
11
+ @Matches(/^[A-Za-z0-9._:-]+$/)
12
+ saleId!: string;
13
+
14
+ /** Motivo de la cancelación; va a la auditoría del crédito y no se loguea. */
15
+ @Expose()
16
+ @IsString()
17
+ @IsNotEmpty()
18
+ @MaxLength(500)
19
+ reason!: string;
20
+ }
@@ -28,6 +28,8 @@ export interface CreditCustomerCredit {
28
28
  settledCreditsCount: number | null;
29
29
  writtenOffCreditsCount: number | null;
30
30
  outstandingBalanceCents: number | null;
31
+ /** Deuda total de sus créditos vivos: capital, interés e IVA que faltan de las cuotas abiertas. `null` = no aplica. */
32
+ totalDebtCents?: number | null;
31
33
  arrearsDays: number | null;
32
34
  lastPaymentAt: string | null;
33
35
  /** Ausente en créditos sin pago desde que existe el campo: el front cae a `lastPaymentAt`. */
@@ -10,6 +10,8 @@ export interface LoanBorrowerCreditItem extends LoanCreditResponse {
10
10
  paidInstallments: number;
11
11
  /** `null` = no aplica (el crédito se canceló o caducó); `0` = ya no debe nada. */
12
12
  outstandingBalanceCents: number | null;
13
+ /** Deuda total: capital, interés e IVA que faltan de las cuotas abiertas (PENDING u OVERDUE). `null` = no aplica. */
14
+ totalDebtCents?: number | null;
13
15
  /** Días desde el vencimiento impago más viejo; `0` al día; `null` si no hay atraso que medir. */
14
16
  overdueDays: number | null;
15
17
  /** Suma del TOTAL de las cuotas vencidas impagas. Sigue a `overdueDays` en `null`/`0`. */
@@ -14,6 +14,8 @@ export interface LoanCreditDetail extends LoanCreditResponse {
14
14
  financier: SaleFinancierEnum;
15
15
  paidInstallments: number;
16
16
  outstandingBalanceCents: number | null;
17
+ /** Deuda total: capital, interés e IVA que faltan de las cuotas abiertas (PENDING u OVERDUE). `null` = no aplica. */
18
+ totalDebtCents?: number | null;
17
19
  overdueDays: number | null;
18
20
  overdueAmountCents: number | null;
19
21
  /** Cuotas vencidas impagas. `0` = nada vencido; `null` acompaña a `overdueDays` en null. */
@@ -52,6 +52,8 @@ export interface LoanCreditResponse {
52
52
  effectiveTerms?: EffectiveTermsSnapshot | null;
53
53
  activatedAt?: string;
54
54
  voluntaryCancelDeadline?: string;
55
+ /** Si ya se abonó alguna cuota (el enganche no cuenta); solo lo traen la lectura y la cancelación privadas. */
56
+ hasPayments?: boolean;
55
57
  firstDueDate?: string;
56
58
  lastDueDate?: string;
57
59
  createdBy: string;
@@ -3,8 +3,10 @@ export interface LoanPrepaymentQuote {
3
3
  creditId: string;
4
4
  /** Saldo insoluto que se le informa al cliente. */
5
5
  outstandingCapitalCents: number;
6
- /** Pago del periodo: el mínimo del abono. */
6
+ /** Pago del periodo. */
7
7
  periodPaymentCents: number;
8
+ /** Mínimo del abono según el plan del crédito; con mínimo `ANY`, 1 centavo. */
9
+ minAmountCents?: number;
8
10
  /** Monto de liquidación anticipada: el techo del abono. */
9
11
  settlementAmountCents: number;
10
12
  }
@@ -18,6 +18,8 @@ export interface SellerCreditRow {
18
18
  summaryUnavailable: boolean;
19
19
  paidInstallments: number | null;
20
20
  outstandingBalanceCents: number | null;
21
+ /** Deuda total: capital, interés e IVA que faltan de las cuotas abiertas (PENDING u OVERDUE). `null` = no aplica. */
22
+ totalDebtCents?: number | null;
21
23
  overdueDays: number | null;
22
24
  overdueAmountCents: number | null;
23
25
  /** Primera cuota que todavía se debe; `null` si ya no debe nada o si el plan no se leyó. */
@@ -141,6 +141,7 @@ export * from './dtos/WriteOffConfirmations';
141
141
  export * from './dtos/requests/BackofficeSettleCreditRequest';
142
142
  export * from './dtos/requests/BackofficeListWriteOffCandidatesRequest';
143
143
  export * from './dtos/requests/BackofficeWriteOffCreditRequest';
144
+ export * from './dtos/requests/CancelLoanCreditRequest';
144
145
  export * from './dtos/requests/BackofficeCollectWrittenOffCreditRequest';
145
146
  export * from './dtos/requests/BackofficeProposeRestructureRequest';
146
147
  export * from './dtos/requests/BackofficeApproveRestructureRequest';
@@ -1,4 +1,4 @@
1
- import { Expose } from 'class-transformer';
1
+ import { Expose, Type } from 'class-transformer';
2
2
  import {
3
3
  ArrayNotEmpty,
4
4
  IsArray,
@@ -11,12 +11,14 @@ import {
11
11
  Matches,
12
12
  Max,
13
13
  Min,
14
+ ValidateNested,
14
15
  } from 'class-validator';
15
16
  import { regexIso8601 } from '../../helpers/constans/regex';
16
17
  import { CreditPlanLevelEnum } from '../enums/CreditPlanLevelEnum';
17
18
  import { CreditPlanStatusEnum } from '../enums/CreditPlanStatusEnum';
18
19
  import { ProductTierEnum } from '../enums/ProductTierEnum';
19
20
  import { SaleTypeEnum } from '../enums/SaleTypeEnum';
21
+ import { PrepaymentMinimum } from './PrepaymentMinimum';
20
22
 
21
23
  /**
22
24
  * CreditPlan — plan de crédito del catálogo SOFOM SureKeep (modelo-datos §6.1 · M6 §4).
@@ -168,4 +170,11 @@ export class CreditPlan {
168
170
  @IsString()
169
171
  @Matches(regexIso8601, { message: 'updatedAt debe ser una fecha ISO 8601' })
170
172
  updatedAt!: string;
173
+
174
+ /** Mínimo del abono a capital; ausente = `ANY` (cualquier monto). */
175
+ @Expose()
176
+ @IsOptional()
177
+ @ValidateNested()
178
+ @Type(() => PrepaymentMinimum)
179
+ prepaymentMinimum?: PrepaymentMinimum;
171
180
  }
@@ -0,0 +1,28 @@
1
+ import { Expose } from 'class-transformer';
2
+ import { IsEnum, IsInt, IsNumber, IsOptional, Max, Min } from 'class-validator';
3
+ import { PrepaymentMinimumModeEnum } from '../enums/PrepaymentMinimumModeEnum';
4
+
5
+ /**
6
+ * Mínimo del abono a capital de un plan. El máximo no depende del plan: es lo que falta para liquidar.
7
+ * Sin este campo en el plan, el mínimo es `ANY`.
8
+ */
9
+ export class PrepaymentMinimum {
10
+ @Expose()
11
+ @IsEnum(PrepaymentMinimumModeEnum)
12
+ mode!: PrepaymentMinimumModeEnum;
13
+
14
+ /** Sólo `PERCENT_OF_PERIOD_PAYMENT`: decimal sobre 1 del pago del periodo (`0.5` = 50 %). */
15
+ @Expose()
16
+ @IsOptional()
17
+ @IsNumber()
18
+ @Min(0.0001)
19
+ @Max(1)
20
+ periodPaymentPct?: number | null;
21
+
22
+ /** Sólo `FIXED`: monto mínimo en cents. */
23
+ @Expose()
24
+ @IsOptional()
25
+ @IsInt()
26
+ @Min(1)
27
+ amountCents?: number | null;
28
+ }
@@ -1,4 +1,4 @@
1
- import { Expose } from 'class-transformer';
1
+ import { Expose, Type } from 'class-transformer';
2
2
  import {
3
3
  ArrayNotEmpty,
4
4
  IsArray,
@@ -10,10 +10,12 @@ import {
10
10
  IsString,
11
11
  Max,
12
12
  Min,
13
+ ValidateNested,
13
14
  } from 'class-validator';
14
15
  import { CreditPlanLevelEnum } from '../../enums/CreditPlanLevelEnum';
15
16
  import { ProductTierEnum } from '../../enums/ProductTierEnum';
16
17
  import { SaleTypeEnum } from '../../enums/SaleTypeEnum';
18
+ import { PrepaymentMinimum } from '../PrepaymentMinimum';
17
19
 
18
20
  /**
19
21
  * Body de POST /credit-plans — alta de un plan (SureKeep Fase 1 — pista Loan).
@@ -115,4 +117,11 @@ export class CreateCreditPlanRequest {
115
117
  @IsOptional()
116
118
  @IsString()
117
119
  validUntil?: string | null;
120
+
121
+ /** Mínimo del abono a capital; ausente = sin cambios (en el alta: `ANY`). */
122
+ @Expose()
123
+ @IsOptional()
124
+ @ValidateNested()
125
+ @Type(() => PrepaymentMinimum)
126
+ prepaymentMinimum?: PrepaymentMinimum;
118
127
  }
@@ -1,4 +1,4 @@
1
- import { Expose } from 'class-transformer';
1
+ import { Expose, Type } from 'class-transformer';
2
2
  import {
3
3
  ArrayNotEmpty,
4
4
  IsArray,
@@ -10,9 +10,11 @@ import {
10
10
  IsString,
11
11
  Max,
12
12
  Min,
13
+ ValidateNested,
13
14
  } from 'class-validator';
14
15
  import { ProductTierEnum } from '../../enums/ProductTierEnum';
15
16
  import { SaleTypeEnum } from '../../enums/SaleTypeEnum';
17
+ import { PrepaymentMinimum } from '../PrepaymentMinimum';
16
18
 
17
19
  /**
18
20
  * Body de PUT /credit-plans/:planId — edición parcial de parámetros del plan (todos opcionales).
@@ -114,4 +116,11 @@ export class UpdateCreditPlanRequest {
114
116
  @IsOptional()
115
117
  @IsString()
116
118
  validUntil?: string | null;
119
+
120
+ /** Mínimo del abono a capital; ausente = sin cambios (en el alta: `ANY`). */
121
+ @Expose()
122
+ @IsOptional()
123
+ @ValidateNested()
124
+ @Type(() => PrepaymentMinimum)
125
+ prepaymentMinimum?: PrepaymentMinimum;
117
126
  }
@@ -2,6 +2,7 @@ import { CreditPlanLevelEnum } from '../../enums/CreditPlanLevelEnum';
2
2
  import { CreditPlanStatusEnum } from '../../enums/CreditPlanStatusEnum';
3
3
  import { ProductTierEnum } from '../../enums/ProductTierEnum';
4
4
  import { SaleTypeEnum } from '../../enums/SaleTypeEnum';
5
+ import { PrepaymentMinimum } from '../PrepaymentMinimum';
5
6
 
6
7
  /**
7
8
  * Shape de salida de un plan de crédito (GET / POST / PUT de /credit-plans).
@@ -33,4 +34,6 @@ export interface CreditPlanResponse {
33
34
  updatedBy: string;
34
35
  createdAt: string;
35
36
  updatedAt: string;
37
+ /** Mínimo del abono a capital; ausente = `ANY` (cualquier monto). */
38
+ prepaymentMinimum?: PrepaymentMinimum;
36
39
  }
@@ -0,0 +1,9 @@
1
+ /** Cómo se fija el mínimo del abono a capital de un plan. */
2
+ export enum PrepaymentMinimumModeEnum {
3
+ /** Sin mínimo: el cliente abona el monto que quiera. */
4
+ ANY = 'ANY',
5
+ /** Un porcentaje del pago del periodo (`periodPaymentPct`). */
6
+ PERCENT_OF_PERIOD_PAYMENT = 'PERCENT_OF_PERIOD_PAYMENT',
7
+ /** Un monto fijo (`amountCents`). */
8
+ FIXED = 'FIXED',
9
+ }
@@ -16,9 +16,11 @@ export * from './enums/StorePolicyPhaseEnum';
16
16
  export * from './enums/SegmentStatusEnum';
17
17
  export * from './enums/SegmentColorSlotEnum';
18
18
  export * from './enums/SegmentFilterIdEnum';
19
+ export * from './enums/PrepaymentMinimumModeEnum';
19
20
 
20
21
  // Entity DTOs
21
22
  export * from './dtos/CreditPlan';
23
+ export * from './dtos/PrepaymentMinimum';
22
24
  export * from './dtos/Financier';
23
25
  export * from './dtos/RetailerCreditPlan';
24
26
  export * from './dtos/PromotionEffect';
@@ -14,4 +14,6 @@ export enum RetailAuditEntityTypeEnum {
14
14
  COMMISSION_ADJUSTMENT = 'COMMISSION_ADJUSTMENT',
15
15
  COMMISSION_RULE = 'COMMISSION_RULE',
16
16
  COMMISSION_POLICY = 'COMMISSION_POLICY',
17
+ PROSPECT = 'PROSPECT',
18
+ RETAIL_CUSTOMER = 'RETAIL_CUSTOMER',
17
19
  }
@@ -37,7 +37,7 @@ export class AuditTrailRecordedV1 {
37
37
  @Type(() => AuditTrailContextEntry)
38
38
  context!: AuditTrailContextEntry[];
39
39
 
40
- /** userId del actor, o `system` si lo disparó un proceso interno. */
40
+ /** userId del actor; nunca `system`: sin usuario va el nombre del lambda que lo disparó. */
41
41
  @Expose()
42
42
  @IsString()
43
43
  @IsNotEmpty()
@@ -28,5 +28,7 @@ export interface MyCreditSummary {
28
28
  totalInstallments: number;
29
29
  paidInstallments: number;
30
30
  remainingBalance: number | null;
31
+ /** Deuda total en pesos: capital, interés e IVA que faltan de las cuotas abiertas. `null` = no aplica. */
32
+ totalDebt?: number | null;
31
33
  overdue?: MyOverdue;
32
34
  }
@@ -7,6 +7,7 @@ import type { CentralSyncStatusEnum } from '../enums/CentralSyncStatusEnum';
7
7
  import type { SalePaymentDetail } from './SalePaymentDetail';
8
8
  import type { SaleLine } from './SaleLine';
9
9
  import type { SalePromotionRef } from '../../retailPromotions/dtos/SalePromotionRef';
10
+ import type { SaleCancellation } from './SaleCancellation';
10
11
 
11
12
  /**
12
13
  * Venta (modelo-datos §3). pk `SALE#<saleId>` · sk `META` · 4 GSIs (`retailerId-soldAt-index`,
@@ -66,6 +67,8 @@ export interface Sale {
66
67
  cancelledAt: string | null;
67
68
  /** Reason OBLIGATORIO en cancelación (AuditTrail) — flujo C. */
68
69
  cancelReason: string | null;
70
+ /** Si la venta se puede cancelar hoy y, si no, por qué; solo lo trae el detalle del backoffice. */
71
+ cancellation?: SaleCancellation;
69
72
  /**
70
73
  * SNAPSHOT de identidad y contexto, congelado al cerrar la venta. NO se refresca: una venta es la
71
74
  * fotografía de un hecho, no la caché de un perfil. Si el cliente corrige su nombre, la venta
@@ -0,0 +1,10 @@
1
+ import type { SaleCancellationReasonEnum } from '../enums/SaleCancellationReasonEnum';
2
+
3
+ /** Si la venta se puede cancelar hoy; el backend valida igual al cancelar. */
4
+ export interface SaleCancellation {
5
+ allowed: boolean;
6
+ /** Ausente cuando `allowed` es true. */
7
+ reason?: SaleCancellationReasonEnum;
8
+ /** Fin de la ventana de cancelación voluntaria, ISO-8601. */
9
+ windowEndsAt?: string;
10
+ }
@@ -0,0 +1,8 @@
1
+ /** Por qué una venta no se puede cancelar; coincide con el `code` que respondería la cancelación. */
2
+ export enum SaleCancellationReasonEnum {
3
+ SALE_ALREADY_CANCELLED = 'SALE_ALREADY_CANCELLED',
4
+ IMEI_NOT_RETURNABLE = 'IMEI_NOT_RETURNABLE',
5
+ CANCEL_WINDOW_EXPIRED = 'CANCEL_WINDOW_EXPIRED',
6
+ CREDIT_HAS_PAYMENTS = 'CREDIT_HAS_PAYMENTS',
7
+ CREDIT_NOT_CANCELLABLE = 'CREDIT_NOT_CANCELLABLE',
8
+ }
@@ -64,6 +64,8 @@ export * from './dtos/AccessorySaleLine';
64
64
  export * from './dtos/WizardSession';
65
65
  export * from './dtos/OtpVerification';
66
66
  export * from './dtos/Sale';
67
+ export * from './dtos/SaleCancellation';
68
+ export * from './enums/SaleCancellationReasonEnum';
67
69
  export * from './dtos/Prospect';
68
70
 
69
71
  // Paginación genérica