@fiado/type-kit 3.338.0 → 3.340.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.
@@ -10,12 +10,25 @@ import { LoanDeviceManualUnlockRequest } from '../../../../src/loanCredit/dtos/r
10
10
  import { LoanDeviceLockReasonEnum } from '../../../../src/loanCredit/enums/LoanDeviceLockReasonEnum';
11
11
  import { LOAN_DEVICE_MAX_BATCH } from '../../../../src/loanCredit/constants/LoanDeviceBatchLimits';
12
12
 
13
- const CREDIT_ID = '5f7c8a90-1234-4abc-9def-0123456789ab';
14
- const OTHER_CREDIT_ID = '5f7c8a90-1234-4abc-9def-0123456789ac';
13
+ /** ULIDs reales del motor: así es como `LoanCreditService` genera los creditId. */
14
+ const CREDIT_ID = '01M0B5D7FQA3T06K4REEVPRM33';
15
+ const OTHER_CREDIT_ID = '01M0AQFQ69DD6R9SBM9Q4Q6BXV';
16
+
17
+ /** Un UUID bien formado: era lo que el contrato exigía y hoy tiene que ser rechazado. */
18
+ const A_UUID = '5f7c8a90-1234-4abc-9def-0123456789ab';
19
+
20
+ const ULID_ALPHABET = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
15
21
 
16
22
  /** Genera un creditId válido y distinto por índice, para armar lotes grandes. */
17
- const creditIdAt = (index: number): string =>
18
- `5f7c8a90-1234-4abc-9def-${index.toString(16).padStart(12, '0')}`;
23
+ const creditIdAt = (index: number): string => {
24
+ let suffix = '';
25
+ let rest = index;
26
+ for (let i = 0; i < 5; i++) {
27
+ suffix = ULID_ALPHABET[rest % 32] + suffix;
28
+ rest = Math.floor(rest / 32);
29
+ }
30
+ return `01M0B5D7FQA3T06K4REEV${suffix}`;
31
+ };
19
32
 
20
33
  /** True si el error de `property` trae ese constraint puntual (no solo "algo falló"). */
21
34
  const hasConstraint = (errors: ValidationError[], property: string, constraint: string): boolean =>
@@ -206,10 +219,10 @@ describe('LoanDeviceManualUnlockRequest', () => {
206
219
  expect(errors).toEqual([]);
207
220
  });
208
221
 
209
- it('falla si algún creditId no es UUID', async () => {
222
+ it('falla si algún creditId no es un ULID', async () => {
210
223
  const dto = plainToInstance(LoanDeviceManualUnlockRequest, {
211
224
  ...validUnlock,
212
- items: [{ creditId: 'no-es-uuid' }],
225
+ items: [{ creditId: A_UUID }],
213
226
  });
214
227
  const errors = await validate(dto);
215
228
  const itemsError = errors.find(e => e.property === 'items');
@@ -256,8 +269,8 @@ describe.each([
256
269
  expect(errors).toEqual([]);
257
270
  });
258
271
 
259
- it('falla si algún creditId no es UUID', async () => {
260
- const dto = plainToInstance(RequestClass, { creditIds: [CREDIT_ID, 'no-es-uuid'] });
272
+ it('falla si algún creditId no es un ULID', async () => {
273
+ const dto = plainToInstance(RequestClass, { creditIds: [CREDIT_ID, A_UUID] });
261
274
  const errors = await validate(dto);
262
275
  expect(errors.some(e => e.property === 'creditIds')).toBe(true);
263
276
  });
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Formato del identificador de crédito: ULID canónico de 26 chars en Crockford base32.
3
+ * El motor lo genera con `ulid()`, no con UUID — validar UUID rechaza todos los créditos reales.
4
+ */
5
+ export declare const CREDIT_ID_PATTERN: RegExp;
6
+ /** Mensaje único de los 6 endpoints de dispositivo, para que el caller no adivine el formato. */
7
+ export declare const CREDIT_ID_MESSAGE = "creditId debe ser un ULID de 26 caracteres";
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CREDIT_ID_MESSAGE = exports.CREDIT_ID_PATTERN = void 0;
4
+ /**
5
+ * Formato del identificador de crédito: ULID canónico de 26 chars en Crockford base32.
6
+ * El motor lo genera con `ulid()`, no con UUID — validar UUID rechaza todos los créditos reales.
7
+ */
8
+ exports.CREDIT_ID_PATTERN = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/;
9
+ /** Mensaje único de los 6 endpoints de dispositivo, para que el caller no adivine el formato. */
10
+ exports.CREDIT_ID_MESSAGE = 'creditId debe ser un ULID de 26 caracteres';
@@ -12,12 +12,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.LoanDeviceCreditRefItem = void 0;
13
13
  const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
+ const CreditIdPattern_1 = require("../constants/CreditIdPattern");
15
16
  /** Ítem que solo referencia un crédito, para las mutaciones que no necesitan más datos. */
16
17
  class LoanDeviceCreditRefItem {
17
18
  }
18
19
  exports.LoanDeviceCreditRefItem = LoanDeviceCreditRefItem;
19
20
  __decorate([
20
21
  (0, class_transformer_1.Expose)(),
21
- (0, class_validator_1.IsUUID)(),
22
+ (0, class_validator_1.Matches)(CreditIdPattern_1.CREDIT_ID_PATTERN, { message: CreditIdPattern_1.CREDIT_ID_MESSAGE }),
22
23
  __metadata("design:type", String)
23
24
  ], LoanDeviceCreditRefItem.prototype, "creditId", void 0);
@@ -13,6 +13,7 @@ exports.LoanDeviceEnrollItem = void 0;
13
13
  const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
15
  const SkuPattern_1 = require("../../retailCatalog/constants/SkuPattern");
16
+ const CreditIdPattern_1 = require("../constants/CreditIdPattern");
16
17
  /** Charset y largo del IMEI: exactamente 15 dígitos. */
17
18
  const IMEI_PATTERN = /^\d{15}$/;
18
19
  /** Plazo máximo del crédito en meses. */
@@ -23,7 +24,7 @@ class LoanDeviceEnrollItem {
23
24
  exports.LoanDeviceEnrollItem = LoanDeviceEnrollItem;
24
25
  __decorate([
25
26
  (0, class_transformer_1.Expose)(),
26
- (0, class_validator_1.IsUUID)(),
27
+ (0, class_validator_1.Matches)(CreditIdPattern_1.CREDIT_ID_PATTERN, { message: CreditIdPattern_1.CREDIT_ID_MESSAGE }),
27
28
  __metadata("design:type", String)
28
29
  ], LoanDeviceEnrollItem.prototype, "creditId", void 0);
29
30
  __decorate([
@@ -14,13 +14,14 @@ const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
15
  const LoanDeviceLockReasonEnum_1 = require("../enums/LoanDeviceLockReasonEnum");
16
16
  const DeviceLockScreenMessage_1 = require("../../mdm/dtos/DeviceLockScreenMessage");
17
+ const CreditIdPattern_1 = require("../constants/CreditIdPattern");
17
18
  /** Ítem de bloqueo manual: qué crédito se bloquea, por qué y con qué mensaje en pantalla. */
18
19
  class LoanDeviceManualLockItem {
19
20
  }
20
21
  exports.LoanDeviceManualLockItem = LoanDeviceManualLockItem;
21
22
  __decorate([
22
23
  (0, class_transformer_1.Expose)(),
23
- (0, class_validator_1.IsUUID)(),
24
+ (0, class_validator_1.Matches)(CreditIdPattern_1.CREDIT_ID_PATTERN, { message: CreditIdPattern_1.CREDIT_ID_MESSAGE }),
24
25
  __metadata("design:type", String)
25
26
  ], LoanDeviceManualLockItem.prototype, "creditId", void 0);
26
27
  __decorate([
@@ -13,6 +13,7 @@ exports.LoanDeviceEnrollStatusRequest = void 0;
13
13
  const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
15
  const LoanDeviceBatchLimits_1 = require("../../constants/LoanDeviceBatchLimits");
16
+ const CreditIdPattern_1 = require("../../constants/CreditIdPattern");
16
17
  /** Body de `POST /private/devices/enroll-status` (loan-credit-business). Consulta en lote. */
17
18
  class LoanDeviceEnrollStatusRequest {
18
19
  }
@@ -23,6 +24,6 @@ __decorate([
23
24
  (0, class_validator_1.ArrayNotEmpty)(),
24
25
  (0, class_validator_1.ArrayMaxSize)(LoanDeviceBatchLimits_1.LOAN_DEVICE_MAX_BATCH),
25
26
  (0, class_validator_1.ArrayUnique)(),
26
- (0, class_validator_1.IsUUID)(undefined, { each: true }),
27
+ (0, class_validator_1.Matches)(CreditIdPattern_1.CREDIT_ID_PATTERN, { each: true, message: CreditIdPattern_1.CREDIT_ID_MESSAGE }),
27
28
  __metadata("design:type", Array)
28
29
  ], LoanDeviceEnrollStatusRequest.prototype, "creditIds", void 0);
@@ -13,6 +13,7 @@ exports.LoanDeviceLastSeenRequest = void 0;
13
13
  const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
15
  const LoanDeviceBatchLimits_1 = require("../../constants/LoanDeviceBatchLimits");
16
+ const CreditIdPattern_1 = require("../../constants/CreditIdPattern");
16
17
  /** Body de `POST /private/devices/last-seen` (loan-credit-business). Consulta en lote. */
17
18
  class LoanDeviceLastSeenRequest {
18
19
  }
@@ -23,6 +24,6 @@ __decorate([
23
24
  (0, class_validator_1.ArrayNotEmpty)(),
24
25
  (0, class_validator_1.ArrayMaxSize)(LoanDeviceBatchLimits_1.LOAN_DEVICE_MAX_BATCH),
25
26
  (0, class_validator_1.ArrayUnique)(),
26
- (0, class_validator_1.IsUUID)(undefined, { each: true }),
27
+ (0, class_validator_1.Matches)(CreditIdPattern_1.CREDIT_ID_PATTERN, { each: true, message: CreditIdPattern_1.CREDIT_ID_MESSAGE }),
27
28
  __metadata("design:type", Array)
28
29
  ], LoanDeviceLastSeenRequest.prototype, "creditIds", void 0);
@@ -13,6 +13,7 @@ exports.LoanDeviceStatusRequest = void 0;
13
13
  const class_transformer_1 = require("class-transformer");
14
14
  const class_validator_1 = require("class-validator");
15
15
  const LoanDeviceBatchLimits_1 = require("../../constants/LoanDeviceBatchLimits");
16
+ const CreditIdPattern_1 = require("../../constants/CreditIdPattern");
16
17
  /** Body de `POST /private/devices/status` (loan-credit-business). Consulta en lote. */
17
18
  class LoanDeviceStatusRequest {
18
19
  }
@@ -23,6 +24,6 @@ __decorate([
23
24
  (0, class_validator_1.ArrayNotEmpty)(),
24
25
  (0, class_validator_1.ArrayMaxSize)(LoanDeviceBatchLimits_1.LOAN_DEVICE_MAX_BATCH),
25
26
  (0, class_validator_1.ArrayUnique)(),
26
- (0, class_validator_1.IsUUID)(undefined, { each: true }),
27
+ (0, class_validator_1.Matches)(CreditIdPattern_1.CREDIT_ID_PATTERN, { each: true, message: CreditIdPattern_1.CREDIT_ID_MESSAGE }),
27
28
  __metadata("design:type", Array)
28
29
  ], LoanDeviceStatusRequest.prototype, "creditIds", void 0);
@@ -3,7 +3,13 @@ import { CashInNetworkEnum } from '../enums/CashInNetworkEnum';
3
3
  import { CashInProviderEnum } from '../enums/CashInProviderEnum';
4
4
  import { EstablishmentBrandEnum } from '../enums/EstablishmentBrandEnum';
5
5
  /**
6
- * Establecimiento (punto de cash-in) servido desde el cache de HERE.
6
+ * Establecimiento (punto de cash-in).
7
+ *
8
+ * Es la forma ÚNICA con la que la app ve un punto de cash-in, sin importar de dónde salió:
9
+ * del cache de HERE (búsqueda por marca) o del directorio en vivo de un proveedor de fondeo.
10
+ * Quien decide la fuente es la config del lambda, y el cliente no se enfrenta a dos shapes:
11
+ * los campos que una fuente no puede llenar simplemente vienen ausentes.
12
+ *
7
13
  * Response DTO — sin decoradores de validación.
8
14
  */
9
15
  export declare class EstablishmentDto {
@@ -25,4 +31,22 @@ export declare class EstablishmentDto {
25
31
  country?: CountryId;
26
32
  /** Red Passport (OXXO/SUPERMERCADO/TIENDITA). En US no aplica. */
27
33
  network?: CashInNetworkEnum;
34
+ /**
35
+ * Comisión que el CLIENTE paga EN LA CAJA, encima de su depósito. No es la de Fiado.
36
+ *
37
+ * Va en la respuesta para que la app la muestre en el pin ANTES de mandar al cliente a
38
+ * la tienda: enterarse en el mostrador es la peor forma de enterarse.
39
+ */
40
+ cashInFrontFee?: number | null;
41
+ /** Tope por operación que acepta esa caja. Junto con la comisión, decide si el punto sirve. */
42
+ maxDepositAmount?: number | null;
43
+ /** Horario de atención en formato HH:mm, tal como lo informa el proveedor. */
44
+ openingTime?: string | null;
45
+ closingTime?: string | null;
46
+ /** Teléfono del punto. Muchos proveedores no lo informan. */
47
+ phone?: string | null;
48
+ /** Logo del comercio, para el pin o el carrusel. */
49
+ imageUrl?: string | null;
50
+ /** Imagen de ejemplo del código que el cajero escanea. */
51
+ sampleQr?: string | null;
28
52
  }
@@ -2,7 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EstablishmentDto = void 0;
4
4
  /**
5
- * Establecimiento (punto de cash-in) servido desde el cache de HERE.
5
+ * Establecimiento (punto de cash-in).
6
+ *
7
+ * Es la forma ÚNICA con la que la app ve un punto de cash-in, sin importar de dónde salió:
8
+ * del cache de HERE (búsqueda por marca) o del directorio en vivo de un proveedor de fondeo.
9
+ * Quien decide la fuente es la config del lambda, y el cliente no se enfrenta a dos shapes:
10
+ * los campos que una fuente no puede llenar simplemente vienen ausentes.
11
+ *
6
12
  * Response DTO — sin decoradores de validación.
7
13
  */
8
14
  class EstablishmentDto {
@@ -1,13 +1,16 @@
1
1
  import { EstablishmentDto } from './EstablishmentDto';
2
2
  import { OfficeDto } from '../../offices/dtos/OfficeDto';
3
- import { FundingStoreItem } from '../../walletFunding/dtos/FundingStoreItem';
4
3
  /**
5
4
  * Respuesta de la búsqueda unificada. Solo se incluyen los tipos pedidos en `types`.
5
+ *
6
+ * Un campo por tipo de lugar, y el campo NO cambia según de dónde salió el dato: si
7
+ * `cashInMx` se resuelve contra el cache de HERE o contra el directorio en vivo de un
8
+ * proveedor de fondeo, la app lee el mismo campo con el mismo shape. El ruteo es una
9
+ * decisión del lambda, no algo que el cliente tenga que interpretar.
6
10
  */
7
11
  export declare class GetNearbyPlacesResponse {
8
12
  cashInUs?: EstablishmentDto[];
9
13
  cashInMx?: EstablishmentDto[];
10
- cashInMxStores?: FundingStoreItem[];
11
14
  officeFiado?: OfficeDto[];
12
15
  storeFiado?: OfficeDto[];
13
16
  }
@@ -3,6 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GetNearbyPlacesResponse = void 0;
4
4
  /**
5
5
  * Respuesta de la búsqueda unificada. Solo se incluyen los tipos pedidos en `types`.
6
+ *
7
+ * Un campo por tipo de lugar, y el campo NO cambia según de dónde salió el dato: si
8
+ * `cashInMx` se resuelve contra el cache de HERE o contra el directorio en vivo de un
9
+ * proveedor de fondeo, la app lee el mismo campo con el mismo shape. El ruteo es una
10
+ * decisión del lambda, no algo que el cliente tenga que interpretar.
6
11
  */
7
12
  class GetNearbyPlacesResponse {
8
13
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fiado/type-kit",
3
- "version": "3.338.0",
3
+ "version": "3.340.0",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "types": "bin/index.d.ts",
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Formato del identificador de crédito: ULID canónico de 26 chars en Crockford base32.
3
+ * El motor lo genera con `ulid()`, no con UUID — validar UUID rechaza todos los créditos reales.
4
+ */
5
+ export const CREDIT_ID_PATTERN = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/;
6
+
7
+ /** Mensaje único de los 6 endpoints de dispositivo, para que el caller no adivine el formato. */
8
+ export const CREDIT_ID_MESSAGE = 'creditId debe ser un ULID de 26 caracteres';
@@ -1,9 +1,10 @@
1
1
  import { Expose } from 'class-transformer';
2
- import { IsUUID } from 'class-validator';
2
+ import { Matches } from 'class-validator';
3
+ import { CREDIT_ID_MESSAGE, CREDIT_ID_PATTERN } from '../constants/CreditIdPattern';
3
4
 
4
5
  /** Ítem que solo referencia un crédito, para las mutaciones que no necesitan más datos. */
5
6
  export class LoanDeviceCreditRefItem {
6
7
  @Expose()
7
- @IsUUID()
8
+ @Matches(CREDIT_ID_PATTERN, { message: CREDIT_ID_MESSAGE })
8
9
  creditId: string;
9
10
  }
@@ -1,6 +1,7 @@
1
1
  import { Expose } from 'class-transformer';
2
- import { IsISO8601, IsInt, IsNotEmpty, IsOptional, IsPositive, IsString, IsUUID, Matches, Max, MaxLength } from 'class-validator';
2
+ import { IsISO8601, IsInt, IsNotEmpty, IsOptional, IsPositive, IsString, Matches, Max, MaxLength } from 'class-validator';
3
3
  import { SKU_PATTERN } from '../../retailCatalog/constants/SkuPattern';
4
+ import { CREDIT_ID_MESSAGE, CREDIT_ID_PATTERN } from '../constants/CreditIdPattern';
4
5
 
5
6
  /** Charset y largo del IMEI: exactamente 15 dígitos. */
6
7
  const IMEI_PATTERN = /^\d{15}$/;
@@ -11,7 +12,7 @@ const MAX_TERM_MONTHS = 60;
11
12
  /** Ítem de enrolamiento: un crédito con el equipo que se va a enrolar en el MDM. */
12
13
  export class LoanDeviceEnrollItem {
13
14
  @Expose()
14
- @IsUUID()
15
+ @Matches(CREDIT_ID_PATTERN, { message: CREDIT_ID_MESSAGE })
15
16
  creditId: string;
16
17
 
17
18
  @Expose()
@@ -1,12 +1,13 @@
1
1
  import { Expose, Type } from 'class-transformer';
2
- import { IsEnum, IsOptional, IsUUID, ValidateNested } from 'class-validator';
2
+ import { IsEnum, IsOptional, Matches, ValidateNested } from 'class-validator';
3
3
  import { LoanDeviceLockReasonEnum } from '../enums/LoanDeviceLockReasonEnum';
4
4
  import { DeviceLockScreenMessage } from '../../mdm/dtos/DeviceLockScreenMessage';
5
+ import { CREDIT_ID_MESSAGE, CREDIT_ID_PATTERN } from '../constants/CreditIdPattern';
5
6
 
6
7
  /** Ítem de bloqueo manual: qué crédito se bloquea, por qué y con qué mensaje en pantalla. */
7
8
  export class LoanDeviceManualLockItem {
8
9
  @Expose()
9
- @IsUUID()
10
+ @Matches(CREDIT_ID_PATTERN, { message: CREDIT_ID_MESSAGE })
10
11
  creditId: string;
11
12
 
12
13
  @Expose()
@@ -1,6 +1,7 @@
1
1
  import { Expose } from 'class-transformer';
2
- import { ArrayMaxSize, ArrayNotEmpty, ArrayUnique, IsArray, IsUUID } from 'class-validator';
2
+ import { ArrayMaxSize, ArrayNotEmpty, ArrayUnique, IsArray, Matches } from 'class-validator';
3
3
  import { LOAN_DEVICE_MAX_BATCH } from '../../constants/LoanDeviceBatchLimits';
4
+ import { CREDIT_ID_MESSAGE, CREDIT_ID_PATTERN } from '../../constants/CreditIdPattern';
4
5
 
5
6
  /** Body de `POST /private/devices/enroll-status` (loan-credit-business). Consulta en lote. */
6
7
  export class LoanDeviceEnrollStatusRequest {
@@ -9,6 +10,6 @@ export class LoanDeviceEnrollStatusRequest {
9
10
  @ArrayNotEmpty()
10
11
  @ArrayMaxSize(LOAN_DEVICE_MAX_BATCH)
11
12
  @ArrayUnique()
12
- @IsUUID(undefined, { each: true })
13
+ @Matches(CREDIT_ID_PATTERN, { each: true, message: CREDIT_ID_MESSAGE })
13
14
  creditIds: string[];
14
15
  }
@@ -1,6 +1,7 @@
1
1
  import { Expose } from 'class-transformer';
2
- import { ArrayMaxSize, ArrayNotEmpty, ArrayUnique, IsArray, IsUUID } from 'class-validator';
2
+ import { ArrayMaxSize, ArrayNotEmpty, ArrayUnique, IsArray, Matches } from 'class-validator';
3
3
  import { LOAN_DEVICE_MAX_BATCH } from '../../constants/LoanDeviceBatchLimits';
4
+ import { CREDIT_ID_MESSAGE, CREDIT_ID_PATTERN } from '../../constants/CreditIdPattern';
4
5
 
5
6
  /** Body de `POST /private/devices/last-seen` (loan-credit-business). Consulta en lote. */
6
7
  export class LoanDeviceLastSeenRequest {
@@ -9,6 +10,6 @@ export class LoanDeviceLastSeenRequest {
9
10
  @ArrayNotEmpty()
10
11
  @ArrayMaxSize(LOAN_DEVICE_MAX_BATCH)
11
12
  @ArrayUnique()
12
- @IsUUID(undefined, { each: true })
13
+ @Matches(CREDIT_ID_PATTERN, { each: true, message: CREDIT_ID_MESSAGE })
13
14
  creditIds: string[];
14
15
  }
@@ -1,6 +1,7 @@
1
1
  import { Expose } from 'class-transformer';
2
- import { ArrayMaxSize, ArrayNotEmpty, ArrayUnique, IsArray, IsUUID } from 'class-validator';
2
+ import { ArrayMaxSize, ArrayNotEmpty, ArrayUnique, IsArray, Matches } from 'class-validator';
3
3
  import { LOAN_DEVICE_MAX_BATCH } from '../../constants/LoanDeviceBatchLimits';
4
+ import { CREDIT_ID_MESSAGE, CREDIT_ID_PATTERN } from '../../constants/CreditIdPattern';
4
5
 
5
6
  /** Body de `POST /private/devices/status` (loan-credit-business). Consulta en lote. */
6
7
  export class LoanDeviceStatusRequest {
@@ -9,6 +10,6 @@ export class LoanDeviceStatusRequest {
9
10
  @ArrayNotEmpty()
10
11
  @ArrayMaxSize(LOAN_DEVICE_MAX_BATCH)
11
12
  @ArrayUnique()
12
- @IsUUID(undefined, { each: true })
13
+ @Matches(CREDIT_ID_PATTERN, { each: true, message: CREDIT_ID_MESSAGE })
13
14
  creditIds: string[];
14
15
  }
@@ -4,7 +4,13 @@ import { CashInProviderEnum } from '../enums/CashInProviderEnum';
4
4
  import { EstablishmentBrandEnum } from '../enums/EstablishmentBrandEnum';
5
5
 
6
6
  /**
7
- * Establecimiento (punto de cash-in) servido desde el cache de HERE.
7
+ * Establecimiento (punto de cash-in).
8
+ *
9
+ * Es la forma ÚNICA con la que la app ve un punto de cash-in, sin importar de dónde salió:
10
+ * del cache de HERE (búsqueda por marca) o del directorio en vivo de un proveedor de fondeo.
11
+ * Quien decide la fuente es la config del lambda, y el cliente no se enfrenta a dos shapes:
12
+ * los campos que una fuente no puede llenar simplemente vienen ausentes.
13
+ *
8
14
  * Response DTO — sin decoradores de validación.
9
15
  */
10
16
  export class EstablishmentDto {
@@ -27,4 +33,29 @@ export class EstablishmentDto {
27
33
  country?: CountryId;
28
34
  /** Red Passport (OXXO/SUPERMERCADO/TIENDITA). En US no aplica. */
29
35
  network?: CashInNetworkEnum;
36
+
37
+ // ─────────────────────────────────────────────────────────────────────────
38
+ // Datos que sólo informa un directorio en vivo del proveedor (aditivos, opcionales).
39
+ // El cache de HERE no los tiene: HERE sabe dónde está una tienda, no qué cobra.
40
+ // `null` = el proveedor los expone pero no informó valor; ausente = la fuente ni los maneja.
41
+ // ─────────────────────────────────────────────────────────────────────────
42
+
43
+ /**
44
+ * Comisión que el CLIENTE paga EN LA CAJA, encima de su depósito. No es la de Fiado.
45
+ *
46
+ * Va en la respuesta para que la app la muestre en el pin ANTES de mandar al cliente a
47
+ * la tienda: enterarse en el mostrador es la peor forma de enterarse.
48
+ */
49
+ cashInFrontFee?: number | null;
50
+ /** Tope por operación que acepta esa caja. Junto con la comisión, decide si el punto sirve. */
51
+ maxDepositAmount?: number | null;
52
+ /** Horario de atención en formato HH:mm, tal como lo informa el proveedor. */
53
+ openingTime?: string | null;
54
+ closingTime?: string | null;
55
+ /** Teléfono del punto. Muchos proveedores no lo informan. */
56
+ phone?: string | null;
57
+ /** Logo del comercio, para el pin o el carrusel. */
58
+ imageUrl?: string | null;
59
+ /** Imagen de ejemplo del código que el cajero escanea. */
60
+ sampleQr?: string | null;
30
61
  }
@@ -1,14 +1,17 @@
1
1
  import { EstablishmentDto } from './EstablishmentDto';
2
2
  import { OfficeDto } from '../../offices/dtos/OfficeDto';
3
- import { FundingStoreItem } from '../../walletFunding/dtos/FundingStoreItem';
4
3
 
5
4
  /**
6
5
  * Respuesta de la búsqueda unificada. Solo se incluyen los tipos pedidos en `types`.
6
+ *
7
+ * Un campo por tipo de lugar, y el campo NO cambia según de dónde salió el dato: si
8
+ * `cashInMx` se resuelve contra el cache de HERE o contra el directorio en vivo de un
9
+ * proveedor de fondeo, la app lee el mismo campo con el mismo shape. El ruteo es una
10
+ * decisión del lambda, no algo que el cliente tenga que interpretar.
7
11
  */
8
12
  export class GetNearbyPlacesResponse {
9
13
  cashInUs?: EstablishmentDto[];
10
14
  cashInMx?: EstablishmentDto[];
11
- cashInMxStores?: FundingStoreItem[];
12
15
  officeFiado?: OfficeDto[];
13
16
  storeFiado?: OfficeDto[];
14
17
  }