@fiado/type-kit 3.535.0 → 3.537.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 (62) hide show
  1. package/_test_/unit/loanCredit/creditLifecycleEnums.test.ts +2 -1
  2. package/_test_/unit/loanCredit/signLoanCreditRequest.test.ts +37 -0
  3. package/_test_/unit/messagesConnector/otpBinding.test.ts +43 -0
  4. package/_test_/unit/retailWizard/otherStoreSale.test.ts +54 -0
  5. package/_test_/unit/retailWizard/signatureSendOtpRequest.test.ts +25 -0
  6. package/bin/loanCredit/dtos/LoanContract.d.ts +5 -1
  7. package/bin/loanCredit/dtos/LoanContract.js +8 -1
  8. package/bin/loanCredit/dtos/LoanContractSignatureEvidence.d.ts +45 -0
  9. package/bin/loanCredit/dtos/LoanContractSignatureEvidence.js +2 -0
  10. package/bin/loanCredit/dtos/SignatureContext.d.ts +20 -0
  11. package/bin/loanCredit/dtos/SignatureContext.js +92 -0
  12. package/bin/loanCredit/dtos/requests/SignLoanCreditRequest.d.ts +6 -0
  13. package/bin/loanCredit/dtos/requests/SignLoanCreditRequest.js +8 -0
  14. package/bin/loanCredit/dtos/responses/LoanContractResponse.d.ts +3 -0
  15. package/bin/loanCredit/enums/ContractTypeEnum.d.ts +2 -0
  16. package/bin/loanCredit/enums/ContractTypeEnum.js +2 -0
  17. package/bin/loanCredit/index.d.ts +2 -0
  18. package/bin/loanCredit/index.js +2 -0
  19. package/bin/messagesConnector/constants/OtpBinding.d.ts +2 -0
  20. package/bin/messagesConnector/constants/OtpBinding.js +5 -0
  21. package/bin/messagesConnector/dtos/SendMessageRequest.d.ts +1 -0
  22. package/bin/messagesConnector/dtos/SendMessageRequest.js +7 -0
  23. package/bin/messagesConnector/dtos/VerifyOtpRequest.d.ts +2 -0
  24. package/bin/messagesConnector/dtos/VerifyOtpRequest.js +14 -0
  25. package/bin/messagesConnector/dtos/VerifyOtpResponse.d.ts +6 -0
  26. package/bin/messagesConnector/index.d.ts +1 -0
  27. package/bin/messagesConnector/index.js +1 -0
  28. package/bin/retailWizard/dtos/WizardSession.d.ts +5 -0
  29. package/bin/retailWizard/dtos/requests/CancelOtherStoreSaleRequest.d.ts +9 -0
  30. package/bin/retailWizard/dtos/requests/CancelOtherStoreSaleRequest.js +34 -0
  31. package/bin/retailWizard/dtos/requests/SignatureSendOtpRequest.d.ts +7 -0
  32. package/bin/retailWizard/dtos/requests/SignatureSendOtpRequest.js +26 -0
  33. package/bin/retailWizard/dtos/responses/ActiveSessionByPhoneResponse.d.ts +5 -0
  34. package/bin/retailWizard/dtos/responses/CancelOtherStoreSaleResponse.d.ts +7 -0
  35. package/bin/retailWizard/dtos/responses/CancelOtherStoreSaleResponse.js +2 -0
  36. package/bin/retailWizard/enums/MoneyAtStakeKindEnum.d.ts +9 -0
  37. package/bin/retailWizard/enums/MoneyAtStakeKindEnum.js +13 -0
  38. package/bin/retailWizard/enums/SystemCancelReasonEnum.d.ts +7 -2
  39. package/bin/retailWizard/enums/SystemCancelReasonEnum.js +6 -1
  40. package/bin/retailWizard/index.d.ts +4 -0
  41. package/bin/retailWizard/index.js +4 -0
  42. package/package.json +1 -1
  43. package/src/loanCredit/dtos/LoanContract.ts +10 -2
  44. package/src/loanCredit/dtos/LoanContractSignatureEvidence.ts +50 -0
  45. package/src/loanCredit/dtos/SignatureContext.ts +75 -0
  46. package/src/loanCredit/dtos/requests/SignLoanCreditRequest.ts +11 -0
  47. package/src/loanCredit/dtos/responses/LoanContractResponse.ts +3 -0
  48. package/src/loanCredit/enums/ContractTypeEnum.ts +2 -0
  49. package/src/loanCredit/index.ts +2 -0
  50. package/src/messagesConnector/constants/OtpBinding.ts +2 -0
  51. package/src/messagesConnector/dtos/SendMessageRequest.ts +5 -1
  52. package/src/messagesConnector/dtos/VerifyOtpRequest.ts +5 -1
  53. package/src/messagesConnector/dtos/VerifyOtpResponse.ts +6 -0
  54. package/src/messagesConnector/index.ts +1 -0
  55. package/src/retailWizard/dtos/WizardSession.ts +5 -0
  56. package/src/retailWizard/dtos/requests/CancelOtherStoreSaleRequest.ts +20 -0
  57. package/src/retailWizard/dtos/requests/SignatureSendOtpRequest.ts +12 -0
  58. package/src/retailWizard/dtos/responses/ActiveSessionByPhoneResponse.ts +5 -0
  59. package/src/retailWizard/dtos/responses/CancelOtherStoreSaleResponse.ts +7 -0
  60. package/src/retailWizard/enums/MoneyAtStakeKindEnum.ts +9 -0
  61. package/src/retailWizard/enums/SystemCancelReasonEnum.ts +6 -1
  62. package/src/retailWizard/index.ts +4 -0
@@ -0,0 +1,7 @@
1
+ /**
2
+ * POST /wizard/sessions/:id/signature/send-otp — firma FES tiempo 1 (paso 08). El cliente marcó
3
+ * "Acepto los términos del contrato de crédito": sin esa aceptación el wizard no manda el código.
4
+ */
5
+ export declare class SignatureSendOtpRequest {
6
+ termsAccepted: true;
7
+ }
@@ -0,0 +1,26 @@
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.SignatureSendOtpRequest = void 0;
13
+ const class_transformer_1 = require("class-transformer");
14
+ const class_validator_1 = require("class-validator");
15
+ /**
16
+ * POST /wizard/sessions/:id/signature/send-otp — firma FES tiempo 1 (paso 08). El cliente marcó
17
+ * "Acepto los términos del contrato de crédito": sin esa aceptación el wizard no manda el código.
18
+ */
19
+ class SignatureSendOtpRequest {
20
+ }
21
+ exports.SignatureSendOtpRequest = SignatureSendOtpRequest;
22
+ __decorate([
23
+ (0, class_transformer_1.Expose)(),
24
+ (0, class_validator_1.Equals)(true, { message: 'termsAccepted debe ser true: el cliente tiene que aceptar los términos' }),
25
+ __metadata("design:type", Boolean)
26
+ ], SignatureSendOtpRequest.prototype, "termsAccepted", void 0);
@@ -1,3 +1,4 @@
1
+ import type { MoneyAtStakeKindEnum } from '../../enums/MoneyAtStakeKindEnum';
1
2
  import type { WizardStateEnum } from '../../enums/WizardStateEnum';
2
3
  import type { WizardStepEnum } from '../../enums/WizardStepEnum';
3
4
  import type { WizardBlockedSummary } from '../WizardBlocked';
@@ -32,4 +33,8 @@ export interface ActiveSessionByPhoneResponse {
32
33
  exactUntil?: string | null;
33
34
  /** La venta movió dinero u originó crédito: siempre se retoma la misma. */
34
35
  moneyAtStake?: boolean;
36
+ /** Qué dinero retiene: SALE (folio, cobro o venta) o CREDIT_QUOTED (solo crédito cotizado); `null` = ninguno. */
37
+ moneyAtStakeKind?: MoneyAtStakeKindEnum | null;
38
+ /** Venta solo de contado (el cliente tiene una venta con dinero en otra sucursal). */
39
+ cashOnly?: boolean;
35
40
  }
@@ -0,0 +1,7 @@
1
+ /** Resultado de cancelar la venta de otra sucursal que retenía al cliente. SureKeep — pista Retail. */
2
+ export interface CancelOtherStoreSaleResponse {
3
+ /** Venta cancelada. */
4
+ sessionId: string;
5
+ /** Enganche cobrado que queda por reembolsar; `null` si no hubo cobro. */
6
+ refundPendingCents: number | null;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Qué dinero retiene la venta, para el texto de la ficha.
3
+ * SALE: hay folio, cobro o venta cerrada.
4
+ * CREDIT_QUOTED: solo hay un crédito cotizado (sin cobro).
5
+ */
6
+ export declare enum MoneyAtStakeKindEnum {
7
+ SALE = "SALE",
8
+ CREDIT_QUOTED = "CREDIT_QUOTED"
9
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MoneyAtStakeKindEnum = void 0;
4
+ /**
5
+ * Qué dinero retiene la venta, para el texto de la ficha.
6
+ * SALE: hay folio, cobro o venta cerrada.
7
+ * CREDIT_QUOTED: solo hay un crédito cotizado (sin cobro).
8
+ */
9
+ var MoneyAtStakeKindEnum;
10
+ (function (MoneyAtStakeKindEnum) {
11
+ MoneyAtStakeKindEnum["SALE"] = "SALE";
12
+ MoneyAtStakeKindEnum["CREDIT_QUOTED"] = "CREDIT_QUOTED";
13
+ })(MoneyAtStakeKindEnum || (exports.MoneyAtStakeKindEnum = MoneyAtStakeKindEnum = {}));
@@ -1,4 +1,9 @@
1
- /** `cancelReason` que escribe el sistema (no el vendedor). La saga cierra la venta cuyo crédito se descartó. */
1
+ /**
2
+ * `cancelReason` que escribe el sistema (no el vendedor).
3
+ * SWEEP_CREDIT_DISCARDED: la saga cierra la venta cuyo crédito se descartó.
4
+ * TAKEN_OVER_BY_OTHER_STORE: otra tienda tomó al cliente y la venta no tenía dinero en juego.
5
+ */
2
6
  export declare enum SystemCancelReasonEnum {
3
- SWEEP_CREDIT_DISCARDED = "SWEEP_CREDIT_DISCARDED"
7
+ SWEEP_CREDIT_DISCARDED = "SWEEP_CREDIT_DISCARDED",
8
+ TAKEN_OVER_BY_OTHER_STORE = "TAKEN_OVER_BY_OTHER_STORE"
4
9
  }
@@ -1,8 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SystemCancelReasonEnum = void 0;
4
- /** `cancelReason` que escribe el sistema (no el vendedor). La saga cierra la venta cuyo crédito se descartó. */
4
+ /**
5
+ * `cancelReason` que escribe el sistema (no el vendedor).
6
+ * SWEEP_CREDIT_DISCARDED: la saga cierra la venta cuyo crédito se descartó.
7
+ * TAKEN_OVER_BY_OTHER_STORE: otra tienda tomó al cliente y la venta no tenía dinero en juego.
8
+ */
5
9
  var SystemCancelReasonEnum;
6
10
  (function (SystemCancelReasonEnum) {
7
11
  SystemCancelReasonEnum["SWEEP_CREDIT_DISCARDED"] = "SWEEP_CREDIT_DISCARDED";
12
+ SystemCancelReasonEnum["TAKEN_OVER_BY_OTHER_STORE"] = "TAKEN_OVER_BY_OTHER_STORE";
8
13
  })(SystemCancelReasonEnum || (exports.SystemCancelReasonEnum = SystemCancelReasonEnum = {}));
@@ -19,6 +19,7 @@ export * from './enums/AccountStepStatusEnum';
19
19
  export * from './enums/ResumeReasonEnum';
20
20
  export * from './enums/ProspectResumeModeEnum';
21
21
  export * from './enums/SystemCancelReasonEnum';
22
+ export * from './enums/MoneyAtStakeKindEnum';
22
23
  export * from './enums/AppOnboardingStepEnum';
23
24
  export * from './enums/AppOnboardingStepStatusEnum';
24
25
  export * from './enums/BlockedReasonEnum';
@@ -58,6 +59,7 @@ export * from './dtos/Prospect';
58
59
  export * from './dtos/PaginatedResult';
59
60
  export * from './dtos/requests/StartSessionRequest';
60
61
  export * from './dtos/requests/CancelSessionRequest';
62
+ export * from './dtos/requests/CancelOtherStoreSaleRequest';
61
63
  export * from './dtos/requests/VerifyOtpRequest';
62
64
  export * from './dtos/requests/ResendOtpRequest';
63
65
  export * from './dtos/requests/SkipOtpRequest';
@@ -89,6 +91,7 @@ export * from './dtos/requests/CancelSaleRequest';
89
91
  export * from './dtos/requests/QuoteRequest';
90
92
  export * from './dtos/requests/DownPaymentRequest';
91
93
  export * from './dtos/requests/SignatureSignRequest';
94
+ export * from './dtos/requests/SignatureSendOtpRequest';
92
95
  export * from './dtos/requests/RegisterDeviceRequest';
93
96
  export * from './dtos/requests/CompleteSaleRequest';
94
97
  export * from './dtos/requests/SuggestIdentifiersQuery';
@@ -109,6 +112,7 @@ export * from './dtos/responses/RegisterDeviceResponse';
109
112
  export * from './dtos/responses/AccountStatusResponse';
110
113
  export * from './dtos/responses/ActiveSessionByPhoneResponse';
111
114
  export * from './dtos/responses/ProspectResumeResponse';
115
+ export * from './dtos/responses/CancelOtherStoreSaleResponse';
112
116
  export * from './dtos/responses/ProspectByPhoneResponse';
113
117
  export * from './dtos/responses/AppOnboardingResponse';
114
118
  export * from './enums/SaleFinancierEnum';
@@ -38,6 +38,7 @@ __exportStar(require("./enums/AccountStepStatusEnum"), exports);
38
38
  __exportStar(require("./enums/ResumeReasonEnum"), exports);
39
39
  __exportStar(require("./enums/ProspectResumeModeEnum"), exports);
40
40
  __exportStar(require("./enums/SystemCancelReasonEnum"), exports);
41
+ __exportStar(require("./enums/MoneyAtStakeKindEnum"), exports);
41
42
  __exportStar(require("./enums/AppOnboardingStepEnum"), exports);
42
43
  __exportStar(require("./enums/AppOnboardingStepStatusEnum"), exports);
43
44
  __exportStar(require("./enums/BlockedReasonEnum"), exports);
@@ -83,6 +84,7 @@ __exportStar(require("./dtos/PaginatedResult"), exports);
83
84
  // Request DTOs (input validado por endpoint)
84
85
  __exportStar(require("./dtos/requests/StartSessionRequest"), exports);
85
86
  __exportStar(require("./dtos/requests/CancelSessionRequest"), exports);
87
+ __exportStar(require("./dtos/requests/CancelOtherStoreSaleRequest"), exports);
86
88
  __exportStar(require("./dtos/requests/VerifyOtpRequest"), exports);
87
89
  __exportStar(require("./dtos/requests/ResendOtpRequest"), exports);
88
90
  __exportStar(require("./dtos/requests/SkipOtpRequest"), exports);
@@ -114,6 +116,7 @@ __exportStar(require("./dtos/requests/CancelSaleRequest"), exports);
114
116
  __exportStar(require("./dtos/requests/QuoteRequest"), exports);
115
117
  __exportStar(require("./dtos/requests/DownPaymentRequest"), exports);
116
118
  __exportStar(require("./dtos/requests/SignatureSignRequest"), exports);
119
+ __exportStar(require("./dtos/requests/SignatureSendOtpRequest"), exports);
117
120
  __exportStar(require("./dtos/requests/RegisterDeviceRequest"), exports);
118
121
  __exportStar(require("./dtos/requests/CompleteSaleRequest"), exports);
119
122
  __exportStar(require("./dtos/requests/SuggestIdentifiersQuery"), exports);
@@ -135,6 +138,7 @@ __exportStar(require("./dtos/responses/RegisterDeviceResponse"), exports);
135
138
  __exportStar(require("./dtos/responses/AccountStatusResponse"), exports);
136
139
  __exportStar(require("./dtos/responses/ActiveSessionByPhoneResponse"), exports);
137
140
  __exportStar(require("./dtos/responses/ProspectResumeResponse"), exports);
141
+ __exportStar(require("./dtos/responses/CancelOtherStoreSaleResponse"), exports);
138
142
  __exportStar(require("./dtos/responses/ProspectByPhoneResponse"), exports);
139
143
  __exportStar(require("./dtos/responses/AppOnboardingResponse"), exports);
140
144
  // ── F3 · Backoffice VentasLuga ────────────────────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fiado/type-kit",
3
- "version": "3.535.0",
3
+ "version": "3.537.0",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "types": "bin/index.d.ts",
@@ -1,11 +1,13 @@
1
1
  import { Expose } from 'class-transformer';
2
- import { IsBoolean, IsEnum, IsOptional, IsString, Matches } from 'class-validator';
2
+ import { IsBoolean, IsEnum, IsObject, IsOptional, IsString, Matches } from 'class-validator';
3
3
  import { regexIso8601 } from '../../helpers/constans/regex';
4
4
  import { ContractTypeEnum } from '../enums/ContractTypeEnum';
5
+ import type { LoanContractSignatureEvidence } from './LoanContractSignatureEvidence';
5
6
 
6
7
  /**
7
8
  * LoanContract — documento del contrato de crédito con firma FES (modelo-datos §5b ·
8
- * `<T>LoanContract_GT` · M2 §4.3-§4.4). Un registro por documento (3 por crédito — C4).
9
+ * `<T>LoanContract_GT` · M2 §4.3-§4.4). Un registro por documento: los 3 de la originación (C4), más la
10
+ * constancia de firma al firmar.
9
11
  *
10
12
  * Nace DRAFT en la originación (sin PDF); la firma FES genera el PDF, calcula su `sha256`,
11
13
  * verifica el OTP y sella con NOM-151. Conservación documental: 10 años (NOM-151).
@@ -58,6 +60,12 @@ export class LoanContract {
58
60
  @Matches(regexIso8601)
59
61
  signedAt?: string;
60
62
 
63
+ /** Evidencia de la firma con código (solo en documentos firmados). */
64
+ @Expose()
65
+ @IsOptional()
66
+ @IsObject()
67
+ signatureEvidence?: LoanContractSignatureEvidence;
68
+
61
69
  @Expose()
62
70
  @IsString()
63
71
  createdBy!: string;
@@ -0,0 +1,50 @@
1
+ /** El código de firma tal como lo validó messages-business. */
2
+ export interface SignatureEvidenceOtp {
3
+ /** Id del envío en messages-business (fila del log del código). */
4
+ messageLogId: string;
5
+ sentAt: string;
6
+ verifiedAt: string;
7
+ channel: 'SMS';
8
+ /** Teléfono destino enmascarado (`****1234`). */
9
+ destinationMasked?: string;
10
+ }
11
+
12
+ /** Envíos del código (con reenvíos) y validaciones fallidas antes de firmar. */
13
+ export interface SignatureEvidenceAttempts {
14
+ sends: number;
15
+ failedVerifications: number;
16
+ }
17
+
18
+ /** Aceptación de términos del tiempo 1, amarrada a la huella del contrato generado en esa llamada. */
19
+ export interface SignatureEvidenceAcceptance {
20
+ acceptedAt: string;
21
+ contractSha256: string;
22
+ ip: string;
23
+ userAgent?: string;
24
+ }
25
+
26
+ /** Desde dónde y quién envió el código al firmar (tiempo 2). */
27
+ export interface SignatureEvidenceSigning {
28
+ ip: string;
29
+ userAgent?: string;
30
+ sellerActorId: string;
31
+ }
32
+
33
+ /** Quién facilitó la firma en la tienda. */
34
+ export interface SignatureEvidenceFacilitator {
35
+ sellerId: string;
36
+ sellerActorId: string;
37
+ sellerName?: string;
38
+ storeId: string;
39
+ storeName?: string;
40
+ wizardSessionId: string;
41
+ }
42
+
43
+ /** Evidencia de la firma con código que queda en cada documento firmado. */
44
+ export interface LoanContractSignatureEvidence {
45
+ otp: SignatureEvidenceOtp;
46
+ attempts: SignatureEvidenceAttempts;
47
+ acceptance: SignatureEvidenceAcceptance;
48
+ signing: SignatureEvidenceSigning;
49
+ facilitator: SignatureEvidenceFacilitator;
50
+ }
@@ -0,0 +1,75 @@
1
+ import { Expose } from 'class-transformer';
2
+ import { IsBoolean, IsNotEmpty, IsOptional, IsString, MaxLength } from 'class-validator';
3
+
4
+ /** Largo máximo de un id operacional (vendedor, tienda, sesión). */
5
+ const ID_TEXT = 128;
6
+ /** Largo máximo de un nombre para mostrar. */
7
+ const NAME_TEXT = 300;
8
+ /** Una IPv6 mide 39 caracteres; se deja margen para el formato mapeado. */
9
+ const IP_TEXT = 64;
10
+ /** Los navegadores mandan User-Agent de 150 a 300 caracteres. */
11
+ const USER_AGENT_TEXT = 512;
12
+
13
+ /**
14
+ * Contexto de la firma que aporta el wizard en cada tiempo de `POST /private/credits/:creditId/sign`:
15
+ * quién facilita la firma (vendedor, tienda, sesión) y desde qué navegador. Es evidencia de la
16
+ * ceremonia: la IP y el navegador son del equipo de la tienda. Nunca se loguean.
17
+ */
18
+ export class SignatureContext {
19
+ /** IP de origen de la llamada, como la ve el API Gateway del wizard. */
20
+ @Expose()
21
+ @IsString()
22
+ @IsNotEmpty()
23
+ @MaxLength(IP_TEXT)
24
+ ip!: string;
25
+
26
+ @Expose()
27
+ @IsOptional()
28
+ @IsString()
29
+ @MaxLength(USER_AGENT_TEXT)
30
+ userAgent?: string;
31
+
32
+ /** Tiempo 1: el cliente marcó "Acepto los términos". El motor exige `true` para mandar el código. */
33
+ @Expose()
34
+ @IsOptional()
35
+ @IsBoolean()
36
+ termsAccepted?: boolean;
37
+
38
+ /** Usuario retail del vendedor. */
39
+ @Expose()
40
+ @IsString()
41
+ @IsNotEmpty()
42
+ @MaxLength(ID_TEXT)
43
+ sellerId!: string;
44
+
45
+ /** Cognito sub del vendedor: queda como actor de la firma. */
46
+ @Expose()
47
+ @IsString()
48
+ @IsNotEmpty()
49
+ @MaxLength(ID_TEXT)
50
+ sellerActorId!: string;
51
+
52
+ @Expose()
53
+ @IsOptional()
54
+ @IsString()
55
+ @MaxLength(NAME_TEXT)
56
+ sellerName?: string;
57
+
58
+ @Expose()
59
+ @IsString()
60
+ @IsNotEmpty()
61
+ @MaxLength(ID_TEXT)
62
+ storeId!: string;
63
+
64
+ @Expose()
65
+ @IsOptional()
66
+ @IsString()
67
+ @MaxLength(NAME_TEXT)
68
+ storeName?: string;
69
+
70
+ @Expose()
71
+ @IsString()
72
+ @IsNotEmpty()
73
+ @MaxLength(ID_TEXT)
74
+ wizardSessionId!: string;
75
+ }
@@ -1,6 +1,7 @@
1
1
  import { Expose, Type } from 'class-transformer';
2
2
  import { IsObject, IsOptional, IsString, Length, ValidateNested } from 'class-validator';
3
3
  import { LoanContractDetails } from '../LoanContractDetails';
4
+ import { SignatureContext } from '../SignatureContext';
4
5
 
5
6
  /**
6
7
  * Body de `POST /private/credits/:creditId/sign` (loan-credit-business — wizard paso 08, firma FES
@@ -64,4 +65,14 @@ export class SignLoanCreditRequest {
64
65
  @IsOptional()
65
66
  @IsString()
66
67
  otpDestination?: string;
68
+
69
+ /**
70
+ * Ambos tiempos: quién facilita la firma y desde qué navegador (evidencia de la ceremonia). En el
71
+ * tiempo 1 trae `termsAccepted: true`. El motor lo exige; la IP y el navegador nunca se loguean.
72
+ */
73
+ @Expose()
74
+ @IsOptional()
75
+ @ValidateNested()
76
+ @Type(() => SignatureContext)
77
+ signatureContext?: SignatureContext;
67
78
  }
@@ -1,4 +1,5 @@
1
1
  import { ContractTypeEnum } from '../../enums/ContractTypeEnum';
2
+ import type { LoanContractSignatureEvidence } from '../LoanContractSignatureEvidence';
2
3
 
3
4
  /**
4
5
  * Response de un documento del contrato (loan-credit-business). `signedAt` ausente = draft.
@@ -13,6 +14,8 @@ export interface LoanContractResponse {
13
14
  otpVerified: boolean;
14
15
  nom151Timestamp?: string;
15
16
  signedAt?: string;
17
+ /** Evidencia de la firma con código (solo en documentos firmados). */
18
+ signatureEvidence?: LoanContractSignatureEvidence;
16
19
  createdAt: string;
17
20
  updatedAt: string;
18
21
  }
@@ -6,6 +6,8 @@ export enum ContractTypeEnum {
6
6
  CREDIT = 'CREDIT',
7
7
  PROMISSORY_NOTE = 'PROMISSORY_NOTE',
8
8
  SIC_AUTHORIZATION = 'SIC_AUTHORIZATION',
9
+ /** Constancia de firma electrónica: la evidencia de la firma con código, en PDF. */
10
+ SIGNATURE_EVIDENCE = 'SIGNATURE_EVIDENCE',
9
11
  RESTRUCTURE_ADDENDUM = 'RESTRUCTURE_ADDENDUM',
10
12
  ADVANCE_AUTHORIZATION = 'ADVANCE_AUTHORIZATION',
11
13
  SETTLEMENT_CERTIFICATE = 'SETTLEMENT_CERTIFICATE',
@@ -13,6 +13,8 @@ export * from './dtos/LoanInstallment';
13
13
  export * from './dtos/InstallmentPaidEvent';
14
14
  export * from './dtos/LoanContract';
15
15
  export * from './dtos/LoanContractDetails';
16
+ export * from './dtos/SignatureContext';
17
+ export * from './dtos/LoanContractSignatureEvidence';
16
18
  export * from './dtos/ActivationChecklist';
17
19
  export * from './dtos/AppliedPromotionSnapshot';
18
20
  export * from './dtos/AppliedStorePolicySnapshot';
@@ -0,0 +1,2 @@
1
+ /** Huella SHA-256 en hexadecimal, tal como la calcula pdf-render sobre el PDF. */
2
+ export const OTP_DOCUMENT_HASH_PATTERN = /^[a-f0-9]{64}$/;
@@ -1,6 +1,7 @@
1
1
  import { Expose } from 'class-transformer';
2
- import { IsEnum, IsNotEmpty, IsObject, IsOptional, IsString, IsUUID } from 'class-validator';
2
+ import { IsEnum, IsNotEmpty, IsObject, IsOptional, IsString, IsUUID, Matches } from 'class-validator';
3
3
  import { DeliveryChannelEnum } from '../../messaging';
4
+ import { OTP_DOCUMENT_HASH_PATTERN } from '../constants/OtpBinding';
4
5
  import { OtpMessagePurposeEnum } from '../enums/OtpMessagePurposeEnum';
5
6
 
6
7
  export class SendMessageRequest {
@@ -28,6 +29,9 @@ export class SendMessageRequest {
28
29
  @Expose() @IsOptional() @IsObject() options?: Record<string, unknown>;
29
30
  @Expose() @IsOptional() @IsUUID() referenceMessageId?: string;
30
31
  @Expose() @IsOptional() @IsString() transactionNumber?: string;
32
+ // Huella del documento que firma el código (CONTRACT_SIGNATURE_OTP). Junto con `transactionNumber`
33
+ // amarra el código a ese documento: messages solo lo valida contra la misma pareja.
34
+ @Expose() @IsOptional() @Matches(OTP_DOCUMENT_HASH_PATTERN) documentHash?: string;
31
35
  @Expose() @IsOptional() @IsEnum(OtpMessagePurposeEnum) purpose?: OtpMessagePurposeEnum;
32
36
  // Tenant emisor: decide plantilla e identidad de envío. Sin él messages-business cae a FIADO.
33
37
  @Expose() @IsOptional() @IsString() @IsNotEmpty() tenantId?: string;
@@ -1,5 +1,6 @@
1
1
  import { Expose } from 'class-transformer';
2
- import { IsEnum, IsNotEmpty, IsOptional, IsString } from 'class-validator';
2
+ import { IsEnum, IsNotEmpty, IsOptional, IsString, Matches } from 'class-validator';
3
+ import { OTP_DOCUMENT_HASH_PATTERN } from '../constants/OtpBinding';
3
4
  import { OtpMessagePurposeEnum } from '../enums/OtpMessagePurposeEnum';
4
5
 
5
6
  export class VerifyOtpRequest {
@@ -11,4 +12,7 @@ export class VerifyOtpRequest {
11
12
  @Expose() @IsString() @IsNotEmpty() typeOfDirectoryId!: string;
12
13
  @Expose() @IsString() @IsNotEmpty() message!: string;
13
14
  @Expose() @IsOptional() @IsEnum(OtpMessagePurposeEnum) purpose?: OtpMessagePurposeEnum;
15
+ // Amarre del código de firma: si vienen, la fila tiene que traer los mismos o el código no sirve.
16
+ @Expose() @IsOptional() @IsString() @IsNotEmpty() transactionNumber?: string;
17
+ @Expose() @IsOptional() @Matches(OTP_DOCUMENT_HASH_PATTERN) documentHash?: string;
14
18
  }
@@ -2,4 +2,10 @@ export class VerifyOtpResponse {
2
2
  verified!: boolean;
3
3
  directoryId!: string;
4
4
  typeOfDirectoryId!: string;
5
+ /** Id del envío (fila del log) que se validó. */
6
+ logId?: string;
7
+ /** Cuándo se mandó el código (ISO 8601). */
8
+ sentAt?: string;
9
+ /** Cuándo se validó (ISO 8601). */
10
+ verifiedAt?: string;
5
11
  }
@@ -2,6 +2,7 @@ export * from './enums/DeliveryChannelExtendedEnum';
2
2
  export * from './enums/NotificationOriginEnum';
3
3
  export * from './enums/MessagingSlotEnum';
4
4
  export * from './enums/OtpMessagePurposeEnum';
5
+ export * from './constants/OtpBinding';
5
6
  export * from './validators/IsStringValueRecord';
6
7
  export * from './dtos/NotificationQueueMessageRequestV2';
7
8
  export * from './dtos/SendMessageRequest';
@@ -155,6 +155,11 @@ export interface WizardSession {
155
155
  /** Prospecto vinculado (si la sesión se reanudó desde un prospecto): se cierra al cerrar la venta (D-prospecto). */
156
156
  prospectId: string | null;
157
157
  cancelReason: string | null;
158
+ /**
159
+ * Venta solo de contado: el cliente tiene una venta con dinero en juego en otra sucursal.
160
+ * Crédito y derivación se rechazan con `CREDIT_IN_PROGRESS_OTHER_STORE`. Ausente = venta completa.
161
+ */
162
+ cashOnly?: boolean;
158
163
  /** TTL DDB ~24h de inactividad (D14). */
159
164
  ttlEpoch: number;
160
165
  createdBy: string;
@@ -0,0 +1,20 @@
1
+ import { Expose } from 'class-transformer';
2
+ import { IsString, MaxLength, MinLength } from 'class-validator';
3
+
4
+ /**
5
+ * POST /wizard/phone-holder/cancel y /backoffice/phone-holder/cancel — el encargado de tienda o el
6
+ * Admin VL cancela la venta viva de otra sucursal que retiene al cliente. SureKeep — pista Retail.
7
+ */
8
+ export class CancelOtherStoreSaleRequest {
9
+ /** Teléfono del cliente: la venta ajena no se expone, así que es la única llave. */
10
+ @Expose()
11
+ @IsString()
12
+ @MaxLength(20)
13
+ phone!: string;
14
+
15
+ @Expose()
16
+ @IsString()
17
+ @MinLength(10)
18
+ @MaxLength(200)
19
+ reason!: string;
20
+ }
@@ -0,0 +1,12 @@
1
+ import { Expose } from 'class-transformer';
2
+ import { Equals } from 'class-validator';
3
+
4
+ /**
5
+ * POST /wizard/sessions/:id/signature/send-otp — firma FES tiempo 1 (paso 08). El cliente marcó
6
+ * "Acepto los términos del contrato de crédito": sin esa aceptación el wizard no manda el código.
7
+ */
8
+ export class SignatureSendOtpRequest {
9
+ @Expose()
10
+ @Equals(true, { message: 'termsAccepted debe ser true: el cliente tiene que aceptar los términos' })
11
+ termsAccepted!: true;
12
+ }
@@ -1,3 +1,4 @@
1
+ import type { MoneyAtStakeKindEnum } from '../../enums/MoneyAtStakeKindEnum';
1
2
  import type { WizardStateEnum } from '../../enums/WizardStateEnum';
2
3
  import type { WizardStepEnum } from '../../enums/WizardStepEnum';
3
4
  import type { WizardBlockedSummary } from '../WizardBlocked';
@@ -33,4 +34,8 @@ export interface ActiveSessionByPhoneResponse {
33
34
  exactUntil?: string | null;
34
35
  /** La venta movió dinero u originó crédito: siempre se retoma la misma. */
35
36
  moneyAtStake?: boolean;
37
+ /** Qué dinero retiene: SALE (folio, cobro o venta) o CREDIT_QUOTED (solo crédito cotizado); `null` = ninguno. */
38
+ moneyAtStakeKind?: MoneyAtStakeKindEnum | null;
39
+ /** Venta solo de contado (el cliente tiene una venta con dinero en otra sucursal). */
40
+ cashOnly?: boolean;
36
41
  }
@@ -0,0 +1,7 @@
1
+ /** Resultado de cancelar la venta de otra sucursal que retenía al cliente. SureKeep — pista Retail. */
2
+ export interface CancelOtherStoreSaleResponse {
3
+ /** Venta cancelada. */
4
+ sessionId: string;
5
+ /** Enganche cobrado que queda por reembolsar; `null` si no hubo cobro. */
6
+ refundPendingCents: number | null;
7
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Qué dinero retiene la venta, para el texto de la ficha.
3
+ * SALE: hay folio, cobro o venta cerrada.
4
+ * CREDIT_QUOTED: solo hay un crédito cotizado (sin cobro).
5
+ */
6
+ export enum MoneyAtStakeKindEnum {
7
+ SALE = 'SALE',
8
+ CREDIT_QUOTED = 'CREDIT_QUOTED',
9
+ }
@@ -1,4 +1,9 @@
1
- /** `cancelReason` que escribe el sistema (no el vendedor). La saga cierra la venta cuyo crédito se descartó. */
1
+ /**
2
+ * `cancelReason` que escribe el sistema (no el vendedor).
3
+ * SWEEP_CREDIT_DISCARDED: la saga cierra la venta cuyo crédito se descartó.
4
+ * TAKEN_OVER_BY_OTHER_STORE: otra tienda tomó al cliente y la venta no tenía dinero en juego.
5
+ */
2
6
  export enum SystemCancelReasonEnum {
3
7
  SWEEP_CREDIT_DISCARDED = 'SWEEP_CREDIT_DISCARDED',
8
+ TAKEN_OVER_BY_OTHER_STORE = 'TAKEN_OVER_BY_OTHER_STORE',
4
9
  }
@@ -22,6 +22,7 @@ export * from './enums/AccountStepStatusEnum';
22
22
  export * from './enums/ResumeReasonEnum';
23
23
  export * from './enums/ProspectResumeModeEnum';
24
24
  export * from './enums/SystemCancelReasonEnum';
25
+ export * from './enums/MoneyAtStakeKindEnum';
25
26
  export * from './enums/AppOnboardingStepEnum';
26
27
  export * from './enums/AppOnboardingStepStatusEnum';
27
28
  export * from './enums/BlockedReasonEnum';
@@ -69,6 +70,7 @@ export * from './dtos/PaginatedResult';
69
70
  // Request DTOs (input validado por endpoint)
70
71
  export * from './dtos/requests/StartSessionRequest';
71
72
  export * from './dtos/requests/CancelSessionRequest';
73
+ export * from './dtos/requests/CancelOtherStoreSaleRequest';
72
74
  export * from './dtos/requests/VerifyOtpRequest';
73
75
  export * from './dtos/requests/ResendOtpRequest';
74
76
  export * from './dtos/requests/SkipOtpRequest';
@@ -100,6 +102,7 @@ export * from './dtos/requests/CancelSaleRequest';
100
102
  export * from './dtos/requests/QuoteRequest';
101
103
  export * from './dtos/requests/DownPaymentRequest';
102
104
  export * from './dtos/requests/SignatureSignRequest';
105
+ export * from './dtos/requests/SignatureSendOtpRequest';
103
106
  export * from './dtos/requests/RegisterDeviceRequest';
104
107
  export * from './dtos/requests/CompleteSaleRequest';
105
108
  export * from './dtos/requests/SuggestIdentifiersQuery';
@@ -122,6 +125,7 @@ export * from './dtos/responses/RegisterDeviceResponse';
122
125
  export * from './dtos/responses/AccountStatusResponse';
123
126
  export * from './dtos/responses/ActiveSessionByPhoneResponse';
124
127
  export * from './dtos/responses/ProspectResumeResponse';
128
+ export * from './dtos/responses/CancelOtherStoreSaleResponse';
125
129
  export * from './dtos/responses/ProspectByPhoneResponse';
126
130
  export * from './dtos/responses/AppOnboardingResponse';
127
131