@fiado/type-kit 3.633.0 → 3.635.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 (43) hide show
  1. package/_test_/unit/retailIntegration/eventPayloadBounds.test.ts +2 -1
  2. package/_test_/unit/retailIntegration/eventPayloads.test.ts +12 -0
  3. package/_test_/unit/retailWizard/salePayments.test.ts +29 -0
  4. package/bin/retailCatalog/dtos/Product.d.ts +1 -0
  5. package/bin/retailCatalog/dtos/requests/BackofficeCreateProductRequest.d.ts +2 -1
  6. package/bin/retailCatalog/dtos/requests/BackofficeCreateProductRequest.js +6 -0
  7. package/bin/retailCatalog/dtos/requests/BackofficeUpdateProductRequest.d.ts +2 -1
  8. package/bin/retailCatalog/dtos/requests/BackofficeUpdateProductRequest.js +6 -0
  9. package/bin/retailCatalog/dtos/requests/CreateProductRequest.d.ts +1 -0
  10. package/bin/retailCatalog/dtos/requests/CreateProductRequest.js +5 -0
  11. package/bin/retailCatalog/dtos/requests/SyncInventoryRequest.d.ts +1 -0
  12. package/bin/retailCatalog/dtos/requests/SyncInventoryRequest.js +5 -0
  13. package/bin/retailCatalog/dtos/requests/UpdateProductRequest.d.ts +1 -0
  14. package/bin/retailCatalog/dtos/requests/UpdateProductRequest.js +5 -0
  15. package/bin/retailCatalog/dtos/responses/InventoryLensResponse.d.ts +1 -0
  16. package/bin/retailCatalog/dtos/responses/StoreCatalogItem.d.ts +2 -0
  17. package/bin/retailIntegration/dtos/ProductEventPayload.d.ts +2 -0
  18. package/bin/retailIntegration/dtos/ProductEventPayload.js +8 -0
  19. package/bin/retailIntegration/models/RetailSystemProduct.d.ts +2 -0
  20. package/bin/retailWizard/dtos/WizardLineProduct.d.ts +1 -0
  21. package/bin/retailWizard/dtos/WizardPayment.d.ts +4 -4
  22. package/bin/retailWizard/dtos/WizardPayment.js +1 -0
  23. package/bin/retailWizard/dtos/WizardProduct.d.ts +2 -0
  24. package/bin/retailWizard/dtos/requests/DownPaymentRequest.d.ts +1 -1
  25. package/bin/retailWizard/dtos/requests/DownPaymentRequest.js +1 -1
  26. package/bin/retailWizard/dtos/requests/RegisterPaymentRequest.d.ts +1 -1
  27. package/bin/retailWizard/dtos/requests/RegisterPaymentRequest.js +1 -1
  28. package/package.json +1 -1
  29. package/src/retailCatalog/dtos/Product.ts +1 -0
  30. package/src/retailCatalog/dtos/requests/BackofficeCreateProductRequest.ts +6 -1
  31. package/src/retailCatalog/dtos/requests/BackofficeUpdateProductRequest.ts +6 -1
  32. package/src/retailCatalog/dtos/requests/CreateProductRequest.ts +4 -0
  33. package/src/retailCatalog/dtos/requests/SyncInventoryRequest.ts +4 -0
  34. package/src/retailCatalog/dtos/requests/UpdateProductRequest.ts +4 -0
  35. package/src/retailCatalog/dtos/responses/InventoryLensResponse.ts +1 -0
  36. package/src/retailCatalog/dtos/responses/StoreCatalogItem.ts +2 -0
  37. package/src/retailIntegration/dtos/ProductEventPayload.ts +3 -0
  38. package/src/retailIntegration/models/RetailSystemProduct.ts +2 -0
  39. package/src/retailWizard/dtos/WizardLineProduct.ts +1 -0
  40. package/src/retailWizard/dtos/WizardPayment.ts +6 -5
  41. package/src/retailWizard/dtos/WizardProduct.ts +2 -0
  42. package/src/retailWizard/dtos/requests/DownPaymentRequest.ts +2 -2
  43. package/src/retailWizard/dtos/requests/RegisterPaymentRequest.ts +2 -2
@@ -103,7 +103,7 @@ describe('RetailUserEventPayload: topes', () => {
103
103
  describe('ProductEventPayload: topes', () => {
104
104
  it('acepta textos, financieras y montos justo en su tope', async () => {
105
105
  const atMax = {
106
- ...product, externalId: text(ID), brand: text(SHORT), model: text(SHORT), color: text(SHORT), capacity: text(SHORT), description: text(LONG),
106
+ ...product, externalId: text(ID), brand: text(SHORT), model: text(SHORT), color: text(SHORT), capacity: text(SHORT), ram: text(SHORT), description: text(LONG),
107
107
  price: { ...price, basePrice: '999999999999.99', listPrice: '999999999999.99' },
108
108
  eligibleFinanciers: ['SUREKEEP', 'PAYJOY', 'CREDIYA', 'LESPAGO', 'INNOVA'],
109
109
  };
@@ -116,6 +116,7 @@ describe('ProductEventPayload: topes', () => {
116
116
  ['model', { model: text(SHORT + 1) }],
117
117
  ['color', { color: text(SHORT + 1) }],
118
118
  ['capacity', { capacity: text(SHORT + 1) }],
119
+ ['ram', { ram: text(SHORT + 1) }],
119
120
  ['description', { description: text(LONG + 1) }],
120
121
  ['price.basePrice', { price: { ...price, basePrice: '1000000000000.00' } }],
121
122
  ['price.listPrice', { price: { ...price, listPrice: '1000000000000.00' } }],
@@ -123,6 +123,18 @@ describe('ProductEventPayload', () => {
123
123
  expect(dto.eligibleFinanciers).toEqual(['PAYJOY']);
124
124
  });
125
125
 
126
+ it('acepta ram ausente, null o texto, y al transformar ausente queda null', async () => {
127
+ expect(await errorsOf(ProductEventPayload, product)).toEqual([]);
128
+ expect(await errorsOf(ProductEventPayload, { ...product, ram: null })).toEqual([]);
129
+ expect(await errorsOf(ProductEventPayload, { ...product, ram: '8 GB' })).toEqual([]);
130
+ expect(plainToInstance(ProductEventPayload, product).ram).toBeNull();
131
+ expect(plainToInstance(ProductEventPayload, { ...product, ram: '8 GB' }).ram).toBe('8 GB');
132
+ });
133
+
134
+ it('rechaza ram que no es texto', async () => {
135
+ expect(await errorsOf(ProductEventPayload, { ...product, ram: 8 })).toEqual(['ram']);
136
+ });
137
+
126
138
  it('la gama de la integración trae los mismos valores que la de catálogo', () => {
127
139
  expect(Object.values(RetailProductTierEnum)).toEqual(Object.values(ProductTierEnum));
128
140
  });
@@ -105,6 +105,35 @@ describe('payments en RegisterPaymentRequest', () => {
105
105
  });
106
106
  });
107
107
 
108
+ describe('cobro de $0', () => {
109
+ it.each([
110
+ ['RegisterPaymentRequest', RegisterPaymentRequest],
111
+ ['DownPaymentRequest', DownPaymentRequest],
112
+ ])('%s de $0 no exige method ni payments', (_name, cls) => {
113
+ expect(errorsOf(cls as new () => object, { amountCents: 0 })).toEqual([]);
114
+ });
115
+
116
+ it.each([
117
+ ['RegisterPaymentRequest', RegisterPaymentRequest],
118
+ ['DownPaymentRequest', DownPaymentRequest],
119
+ ])('%s de $0 con method lo sigue validando', (_name, cls) => {
120
+ expect(errorsOf(cls as new () => object, { amountCents: 0, method: CASH })).toEqual([]);
121
+ expect(errorsOf(cls as new () => object, { amountCents: 0, method: 'CHEQUE' })).toEqual(['method']);
122
+ });
123
+
124
+ it.each([
125
+ ['RegisterPaymentRequest', RegisterPaymentRequest],
126
+ ['DownPaymentRequest', DownPaymentRequest],
127
+ ])('%s con monto mayor a cero sin payments sigue exigiendo method', (_name, cls) => {
128
+ expect(errorsOf(cls as new () => object, { amountCents: 100 })).toEqual(['method']);
129
+ });
130
+
131
+ it('WizardPayment de $0 guarda method y payments en null', () => {
132
+ expect(errorsOf(WizardPayment, { method: null, amountCents: 0, payments: null, paidAt: '2026-11-03T10:00:00.000Z' })).toEqual([]);
133
+ expect(errorsOf(WizardPayment, { method: 'CHEQUE', amountCents: 0, paidAt: '2026-11-03T10:00:00.000Z' })).toEqual(['method']);
134
+ });
135
+ });
136
+
108
137
  describe('payments en los demás contratos', () => {
109
138
  it('DownPaymentRequest acepta solo payments y valida la suma', () => {
110
139
  expect(errorsOf(DownPaymentRequest, { amountCents: 15000, payments: [cash, wire] })).toEqual([]);
@@ -20,6 +20,7 @@ export declare class Product {
20
20
  brand: string;
21
21
  model: string;
22
22
  capacity: string;
23
+ ram: string | null;
23
24
  color: string;
24
25
  description: string;
25
26
  specs: Record<string, unknown> | null;
@@ -18,7 +18,8 @@ export declare class BackofficeCreateProductRequest {
18
18
  tier?: ProductTierEnum;
19
19
  brand?: string;
20
20
  model?: string;
21
- capacity?: string;
21
+ capacity?: string | null;
22
+ ram?: string | null;
22
23
  color?: string;
23
24
  description?: string;
24
25
  imageUrl?: string;
@@ -74,6 +74,12 @@ __decorate([
74
74
  (0, class_validator_1.IsString)(),
75
75
  __metadata("design:type", String)
76
76
  ], BackofficeCreateProductRequest.prototype, "capacity", void 0);
77
+ __decorate([
78
+ (0, class_validator_1.IsOptional)(),
79
+ (0, class_validator_1.Matches)(/\S/),
80
+ (0, class_validator_1.IsString)(),
81
+ __metadata("design:type", String)
82
+ ], BackofficeCreateProductRequest.prototype, "ram", void 0);
77
83
  __decorate([
78
84
  (0, class_validator_1.IsOptional)(),
79
85
  (0, class_validator_1.Matches)(/\S/),
@@ -16,7 +16,8 @@ export declare class BackofficeUpdateProductRequest {
16
16
  tier?: ProductTierEnum;
17
17
  brand?: string;
18
18
  model?: string;
19
- capacity?: string;
19
+ capacity?: string | null;
20
+ ram?: string | null;
20
21
  color?: string;
21
22
  description?: string;
22
23
  imageUrl?: string;
@@ -75,6 +75,12 @@ __decorate([
75
75
  (0, class_validator_1.IsString)(),
76
76
  __metadata("design:type", String)
77
77
  ], BackofficeUpdateProductRequest.prototype, "capacity", void 0);
78
+ __decorate([
79
+ (0, class_validator_1.IsOptional)(),
80
+ (0, class_validator_1.Matches)(/\S/),
81
+ (0, class_validator_1.IsString)(),
82
+ __metadata("design:type", String)
83
+ ], BackofficeUpdateProductRequest.prototype, "ram", void 0);
78
84
  __decorate([
79
85
  (0, class_validator_1.IsOptional)(),
80
86
  (0, class_validator_1.Matches)(/\S/),
@@ -11,6 +11,7 @@ export declare class CreateProductRequest {
11
11
  brand: string;
12
12
  model: string;
13
13
  capacity: string;
14
+ ram?: string | null;
14
15
  color: string;
15
16
  description: string;
16
17
  specs?: Record<string, unknown> | null;
@@ -46,6 +46,11 @@ __decorate([
46
46
  (0, class_validator_1.IsString)(),
47
47
  __metadata("design:type", String)
48
48
  ], CreateProductRequest.prototype, "capacity", void 0);
49
+ __decorate([
50
+ (0, class_validator_1.IsOptional)(),
51
+ (0, class_validator_1.IsString)(),
52
+ __metadata("design:type", String)
53
+ ], CreateProductRequest.prototype, "ram", void 0);
49
54
  __decorate([
50
55
  (0, class_validator_1.IsString)(),
51
56
  __metadata("design:type", String)
@@ -27,6 +27,7 @@ export declare class SyncProduct {
27
27
  brand?: string;
28
28
  model?: string;
29
29
  capacity?: string;
30
+ ram?: string | null;
30
31
  color?: string;
31
32
  description?: string;
32
33
  imageUrl?: string | null;
@@ -101,6 +101,11 @@ __decorate([
101
101
  (0, class_validator_1.IsString)(),
102
102
  __metadata("design:type", String)
103
103
  ], SyncProduct.prototype, "capacity", void 0);
104
+ __decorate([
105
+ (0, class_validator_1.IsOptional)(),
106
+ (0, class_validator_1.IsString)(),
107
+ __metadata("design:type", String)
108
+ ], SyncProduct.prototype, "ram", void 0);
104
109
  __decorate([
105
110
  (0, class_validator_1.IsOptional)(),
106
111
  (0, class_validator_1.IsString)(),
@@ -10,6 +10,7 @@ export declare class UpdateProductRequest {
10
10
  brand?: string;
11
11
  model?: string;
12
12
  capacity?: string;
13
+ ram?: string | null;
13
14
  color?: string;
14
15
  description?: string;
15
16
  specs?: Record<string, unknown> | null;
@@ -42,6 +42,11 @@ __decorate([
42
42
  (0, class_validator_1.IsString)(),
43
43
  __metadata("design:type", String)
44
44
  ], UpdateProductRequest.prototype, "capacity", void 0);
45
+ __decorate([
46
+ (0, class_validator_1.IsOptional)(),
47
+ (0, class_validator_1.IsString)(),
48
+ __metadata("design:type", String)
49
+ ], UpdateProductRequest.prototype, "ram", void 0);
45
50
  __decorate([
46
51
  (0, class_validator_1.IsOptional)(),
47
52
  (0, class_validator_1.IsString)(),
@@ -36,6 +36,7 @@ export interface InventoryLensSkuItem {
36
36
  brand: string;
37
37
  model: string;
38
38
  capacity: string;
39
+ ram: string | null;
39
40
  storeId: string;
40
41
  /** Unidades `AVAILABLE` de este SKU en esta tienda. */
41
42
  stock: number;
@@ -23,6 +23,8 @@ export interface StoreCatalogItem {
23
23
  brand: string;
24
24
  model: string;
25
25
  capacity: string;
26
+ /** RAM del equipo; `capacity` es la ROM. */
27
+ ram: string | null;
26
28
  color: string;
27
29
  imageUrl: string | null;
28
30
  tier: ProductTierEnum | null;
@@ -13,6 +13,8 @@ export declare class ProductEventPayload implements RetailSystemProduct {
13
13
  model: string;
14
14
  color: string | null;
15
15
  capacity: string | null;
16
+ /** RAM del equipo. Opcional en el evento: ausente se vuelve `null`. */
17
+ ram: string | null;
16
18
  description: string | null;
17
19
  category: RetailProductCategory;
18
20
  trackingMode: RetailTrackingMode;
@@ -75,6 +75,14 @@ __decorate([
75
75
  (0, class_validator_1.MaxLength)(retailIntegrationLimits_1.RETAIL_SHORT_TEXT_MAX_LENGTH),
76
76
  __metadata("design:type", String)
77
77
  ], ProductEventPayload.prototype, "capacity", void 0);
78
+ __decorate([
79
+ (0, class_transformer_1.Expose)(),
80
+ (0, class_transformer_1.Transform)(({ value }) => value ?? null),
81
+ (0, class_validator_1.IsOptional)(),
82
+ (0, class_validator_1.IsString)(),
83
+ (0, class_validator_1.MaxLength)(retailIntegrationLimits_1.RETAIL_SHORT_TEXT_MAX_LENGTH),
84
+ __metadata("design:type", String)
85
+ ], ProductEventPayload.prototype, "ram", void 0);
78
86
  __decorate([
79
87
  (0, class_validator_1.ValidateIf)(payloadValidators_1.isNullOrValidated),
80
88
  (0, class_validator_1.IsString)(),
@@ -21,6 +21,8 @@ export interface RetailSystemProduct {
21
21
  model: string;
22
22
  color: string | null;
23
23
  capacity: string | null;
24
+ /** RAM del equipo; `capacity` es la ROM. */
25
+ ram?: string | null;
24
26
  description: string | null;
25
27
  category: RetailProductCategory;
26
28
  trackingMode: RetailTrackingMode;
@@ -7,6 +7,7 @@ export interface WizardLineProduct {
7
7
  brand: string;
8
8
  model: string;
9
9
  capacity: string | null;
10
+ ram?: string | null;
10
11
  color: string | null;
11
12
  imageUrl: string | null;
12
13
  /** `null` = Sin gama. */
@@ -2,12 +2,12 @@ import { SalePaymentMethodEnum } from '../enums/SalePaymentMethodEnum';
2
2
  import { SalePayment } from './SalePayment';
3
3
  /** Registro del pago de contado dentro de la sesión (`WizardSession.payment`). SureKeep Fase 2 — pista Retail. */
4
4
  export declare class WizardPayment {
5
- /** @deprecated Usa `payments`; con varios pagos lleva el método del primero. */
6
- method: SalePaymentMethodEnum;
5
+ /** @deprecated Usa `payments`; con varios pagos lleva el método del primero. `null` en un cobro de $0. */
6
+ method: SalePaymentMethodEnum | null;
7
7
  amountCents: number;
8
8
  /** @deprecated Usa `payments`; es el comprobante como texto JSON. */
9
9
  detail?: string;
10
- /** Pagos del cobro (1 a 3); ausente en sesiones anteriores al campo. */
11
- payments?: SalePayment[];
10
+ /** Pagos del cobro (1 a 3); `null` en un cobro de $0, ausente en sesiones anteriores al campo. */
11
+ payments?: SalePayment[] | null;
12
12
  paidAt: string;
13
13
  }
@@ -21,6 +21,7 @@ class WizardPayment {
21
21
  exports.WizardPayment = WizardPayment;
22
22
  __decorate([
23
23
  (0, class_transformer_1.Expose)(),
24
+ (0, class_validator_1.ValidateIf)((o) => o.method != null),
24
25
  (0, class_validator_1.IsEnum)(SalePaymentMethodEnum_1.SalePaymentMethodEnum),
25
26
  __metadata("design:type", String)
26
27
  ], WizardPayment.prototype, "method", void 0);
@@ -31,6 +31,8 @@ export interface WizardProduct {
31
31
  brand: string;
32
32
  model: string;
33
33
  capacity: string;
34
+ /** RAM del equipo; `capacity` es la ROM. */
35
+ ram?: string | null;
34
36
  color: string;
35
37
  imageUrl: string | null;
36
38
  /** Gama del equipo (`PREMIUM` / `HIGH` / `MID` …). La define el catálogo, no el wizard. */
@@ -11,7 +11,7 @@ import { SalePayment } from '../SalePayment';
11
11
  * SureKeep Fase 2 — pista SOFOM.
12
12
  */
13
13
  export declare class DownPaymentRequest {
14
- /** @deprecated Usa `payments`; obligatorio solo si `payments` no viene. */
14
+ /** @deprecated Usa `payments`; obligatorio solo si `payments` no viene y el monto es mayor a cero. */
15
15
  method?: SalePaymentMethodEnum;
16
16
  amountCents: number;
17
17
  /** @deprecated Usa el comprobante de cada elemento de `payments`. */
@@ -29,7 +29,7 @@ class DownPaymentRequest {
29
29
  exports.DownPaymentRequest = DownPaymentRequest;
30
30
  __decorate([
31
31
  (0, class_transformer_1.Expose)(),
32
- (0, class_validator_1.ValidateIf)((o) => o.payments == null || o.method !== undefined),
32
+ (0, class_validator_1.ValidateIf)((o) => o.method !== undefined || (o.payments == null && o.amountCents !== 0)),
33
33
  (0, class_validator_1.IsEnum)(SalePaymentMethodEnum_1.SalePaymentMethodEnum),
34
34
  __metadata("design:type", String)
35
35
  ], DownPaymentRequest.prototype, "method", void 0);
@@ -7,7 +7,7 @@ import { SalePayment } from '../SalePayment';
7
7
  * (D11) ANTES del registro; el folio no viaja en el body (lo posee el server). SureKeep Fase 2 — pista Retail.
8
8
  */
9
9
  export declare class RegisterPaymentRequest {
10
- /** @deprecated Usa `payments`; obligatorio solo si `payments` no viene. */
10
+ /** @deprecated Usa `payments`; obligatorio solo si `payments` no viene y el monto es mayor a cero. */
11
11
  method?: SalePaymentMethodEnum;
12
12
  amountCents: number;
13
13
  /** @deprecated Usa el comprobante de cada elemento de `payments`. */
@@ -25,7 +25,7 @@ class RegisterPaymentRequest {
25
25
  exports.RegisterPaymentRequest = RegisterPaymentRequest;
26
26
  __decorate([
27
27
  (0, class_transformer_1.Expose)(),
28
- (0, class_validator_1.ValidateIf)((o) => o.payments == null || o.method !== undefined),
28
+ (0, class_validator_1.ValidateIf)((o) => o.method !== undefined || (o.payments == null && o.amountCents !== 0)),
29
29
  (0, class_validator_1.IsEnum)(SalePaymentMethodEnum_1.SalePaymentMethodEnum),
30
30
  __metadata("design:type", String)
31
31
  ], RegisterPaymentRequest.prototype, "method", void 0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fiado/type-kit",
3
- "version": "3.633.0",
3
+ "version": "3.635.0",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "types": "bin/index.d.ts",
@@ -21,6 +21,7 @@ export class Product {
21
21
  brand!: string;
22
22
  model!: string;
23
23
  capacity!: string;
24
+ ram!: string | null;
24
25
  color!: string;
25
26
  description!: string;
26
27
  specs!: Record<string, unknown> | null;
@@ -52,7 +52,12 @@ export class BackofficeCreateProductRequest {
52
52
  @IsOptional()
53
53
  @Matches(/\S/)
54
54
  @IsString()
55
- capacity?: string;
55
+ capacity?: string | null;
56
+
57
+ @IsOptional()
58
+ @Matches(/\S/)
59
+ @IsString()
60
+ ram?: string | null;
56
61
 
57
62
  @IsOptional()
58
63
  @Matches(/\S/)
@@ -53,7 +53,12 @@ export class BackofficeUpdateProductRequest {
53
53
  @IsOptional()
54
54
  @Matches(/\S/)
55
55
  @IsString()
56
- capacity?: string;
56
+ capacity?: string | null;
57
+
58
+ @IsOptional()
59
+ @Matches(/\S/)
60
+ @IsString()
61
+ ram?: string | null;
57
62
 
58
63
  @IsOptional()
59
64
  @Matches(/\S/)
@@ -40,6 +40,10 @@ export class CreateProductRequest {
40
40
  @IsString()
41
41
  capacity!: string;
42
42
 
43
+ @IsOptional()
44
+ @IsString()
45
+ ram?: string | null;
46
+
43
47
  @IsString()
44
48
  color!: string;
45
49
 
@@ -88,6 +88,10 @@ export class SyncProduct {
88
88
  @IsString()
89
89
  capacity?: string;
90
90
 
91
+ @IsOptional()
92
+ @IsString()
93
+ ram?: string | null;
94
+
91
95
  @IsOptional()
92
96
  @IsString()
93
97
  color?: string;
@@ -35,6 +35,10 @@ export class UpdateProductRequest {
35
35
  @IsString()
36
36
  capacity?: string;
37
37
 
38
+ @IsOptional()
39
+ @IsString()
40
+ ram?: string | null;
41
+
38
42
  @IsOptional()
39
43
  @IsString()
40
44
  color?: string;
@@ -38,6 +38,7 @@ export interface InventoryLensSkuItem {
38
38
  brand: string;
39
39
  model: string;
40
40
  capacity: string;
41
+ ram: string | null;
41
42
  storeId: string;
42
43
 
43
44
  /** Unidades `AVAILABLE` de este SKU en esta tienda. */
@@ -25,6 +25,8 @@ export interface StoreCatalogItem {
25
25
  brand: string;
26
26
  model: string;
27
27
  capacity: string;
28
+ /** RAM del equipo; `capacity` es la ROM. */
29
+ ram: string | null;
28
30
  color: string;
29
31
  imageUrl: string | null;
30
32
  tier: ProductTierEnum | null;
@@ -47,6 +47,9 @@ export class ProductEventPayload implements RetailSystemProduct {
47
47
  @IsString() @Matches(/\S/) @MaxLength(RETAIL_SHORT_TEXT_MAX_LENGTH) model!: string;
48
48
  @ValidateIf(isNullOrValidated) @IsString() @MaxLength(RETAIL_SHORT_TEXT_MAX_LENGTH) color!: string | null;
49
49
  @ValidateIf(isNullOrValidated) @IsString() @MaxLength(RETAIL_SHORT_TEXT_MAX_LENGTH) capacity!: string | null;
50
+ /** RAM del equipo. Opcional en el evento: ausente se vuelve `null`. */
51
+ @Expose() @Transform(({ value }) => value ?? null)
52
+ @IsOptional() @IsString() @MaxLength(RETAIL_SHORT_TEXT_MAX_LENGTH) ram!: string | null;
50
53
  @ValidateIf(isNullOrValidated) @IsString() @MaxLength(RETAIL_LONG_TEXT_MAX_LENGTH) description!: string | null;
51
54
  @IsIn(Object.values(RetailProductCategoryEnum)) category!: RetailProductCategory;
52
55
  @IsIn(Object.values(RetailTrackingModeEnum)) trackingMode!: RetailTrackingMode;
@@ -33,6 +33,8 @@ export interface RetailSystemProduct {
33
33
  model: string;
34
34
  color: string | null;
35
35
  capacity: string | null;
36
+ /** RAM del equipo; `capacity` es la ROM. */
37
+ ram?: string | null;
36
38
  description: string | null;
37
39
  category: RetailProductCategory;
38
40
  trackingMode: RetailTrackingMode;
@@ -8,6 +8,7 @@ export interface WizardLineProduct {
8
8
  brand: string;
9
9
  model: string;
10
10
  capacity: string | null;
11
+ ram?: string | null;
11
12
  color: string | null;
12
13
  imageUrl: string | null;
13
14
  /** `null` = Sin gama. */
@@ -1,5 +1,5 @@
1
1
  import { Expose } from 'class-transformer';
2
- import { IsEnum, IsInt, IsOptional, IsString, Matches, Min } from 'class-validator';
2
+ import { IsEnum, IsInt, IsOptional, IsString, Matches, Min, ValidateIf } from 'class-validator';
3
3
  import { regexIso8601 } from '../../helpers/constans/regex';
4
4
  import { SalePaymentMethodEnum } from '../enums/SalePaymentMethodEnum';
5
5
  import { IsSalePaymentList } from '../validators/IsSalePaymentList';
@@ -7,10 +7,11 @@ import { SalePayment } from './SalePayment';
7
7
 
8
8
  /** Registro del pago de contado dentro de la sesión (`WizardSession.payment`). SureKeep Fase 2 — pista Retail. */
9
9
  export class WizardPayment {
10
- /** @deprecated Usa `payments`; con varios pagos lleva el método del primero. */
10
+ /** @deprecated Usa `payments`; con varios pagos lleva el método del primero. `null` en un cobro de $0. */
11
11
  @Expose()
12
+ @ValidateIf((o: { method?: unknown }) => o.method != null)
12
13
  @IsEnum(SalePaymentMethodEnum)
13
- method!: SalePaymentMethodEnum;
14
+ method!: SalePaymentMethodEnum | null;
14
15
 
15
16
  @Expose()
16
17
  @IsInt()
@@ -23,11 +24,11 @@ export class WizardPayment {
23
24
  @IsString()
24
25
  detail?: string;
25
26
 
26
- /** Pagos del cobro (1 a 3); ausente en sesiones anteriores al campo. */
27
+ /** Pagos del cobro (1 a 3); `null` en un cobro de $0, ausente en sesiones anteriores al campo. */
27
28
  @Expose()
28
29
  @IsOptional()
29
30
  @IsSalePaymentList()
30
- payments?: SalePayment[];
31
+ payments?: SalePayment[] | null;
31
32
 
32
33
  @Expose()
33
34
  @IsString()
@@ -32,6 +32,8 @@ export interface WizardProduct {
32
32
  brand: string;
33
33
  model: string;
34
34
  capacity: string;
35
+ /** RAM del equipo; `capacity` es la ROM. */
36
+ ram?: string | null;
35
37
  color: string;
36
38
  imageUrl: string | null;
37
39
  /** Gama del equipo (`PREMIUM` / `HIGH` / `MID` …). La define el catálogo, no el wizard. */
@@ -15,9 +15,9 @@ import { IsSalePaymentList } from '../../validators/IsSalePaymentList';
15
15
  * SureKeep Fase 2 — pista SOFOM.
16
16
  */
17
17
  export class DownPaymentRequest {
18
- /** @deprecated Usa `payments`; obligatorio solo si `payments` no viene. */
18
+ /** @deprecated Usa `payments`; obligatorio solo si `payments` no viene y el monto es mayor a cero. */
19
19
  @Expose()
20
- @ValidateIf((o: { payments?: unknown; method?: unknown }) => o.payments == null || o.method !== undefined)
20
+ @ValidateIf((o: { payments?: unknown; method?: unknown; amountCents?: unknown }) => o.method !== undefined || (o.payments == null && o.amountCents !== 0))
21
21
  @IsEnum(SalePaymentMethodEnum)
22
22
  method?: SalePaymentMethodEnum;
23
23
 
@@ -11,9 +11,9 @@ import { IsSalePaymentList } from '../../validators/IsSalePaymentList';
11
11
  * (D11) ANTES del registro; el folio no viaja en el body (lo posee el server). SureKeep Fase 2 — pista Retail.
12
12
  */
13
13
  export class RegisterPaymentRequest {
14
- /** @deprecated Usa `payments`; obligatorio solo si `payments` no viene. */
14
+ /** @deprecated Usa `payments`; obligatorio solo si `payments` no viene y el monto es mayor a cero. */
15
15
  @Expose()
16
- @ValidateIf((o: { payments?: unknown; method?: unknown }) => o.payments == null || o.method !== undefined)
16
+ @ValidateIf((o: { payments?: unknown; method?: unknown; amountCents?: unknown }) => o.method !== undefined || (o.payments == null && o.amountCents !== 0))
17
17
  @IsEnum(SalePaymentMethodEnum)
18
18
  method?: SalePaymentMethodEnum;
19
19