@fiado/type-kit 3.636.0 → 3.638.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.
- package/_test_/unit/emailVerification/dtos/internal/EmailOwnersByEmailRequest.test.ts +29 -0
- package/_test_/unit/retailWizard/salePayments.test.ts +43 -35
- package/bin/emailVerification/dtos/internal/EmailOwnersByEmailRequest.d.ts +6 -0
- package/bin/emailVerification/dtos/internal/EmailOwnersByEmailRequest.js +25 -0
- package/bin/emailVerification/index.d.ts +1 -0
- package/bin/emailVerification/index.js +1 -0
- package/bin/retailCommission/dtos/CommissionApi.d.ts +63 -0
- package/bin/retailWizard/dtos/SalePayment.d.ts +4 -1
- package/bin/retailWizard/dtos/SalePayment.js +8 -14
- package/bin/retailWizard/dtos/StoredSalePayment.d.ts +13 -0
- package/bin/retailWizard/dtos/StoredSalePayment.js +59 -0
- package/bin/retailWizard/dtos/requests/CreateAccessorySaleRequest.d.ts +1 -1
- package/bin/retailWizard/dtos/requests/CreateAccessorySaleRequest.js +2 -2
- package/bin/retailWizard/dtos/requests/DownPaymentRequest.d.ts +1 -1
- package/bin/retailWizard/dtos/requests/DownPaymentRequest.js +2 -2
- package/bin/retailWizard/dtos/requests/RegisterPaymentRequest.d.ts +1 -1
- package/bin/retailWizard/dtos/requests/RegisterPaymentRequest.js +2 -2
- package/bin/retailWizard/index.d.ts +2 -0
- package/bin/retailWizard/index.js +2 -0
- package/bin/retailWizard/validators/IsSalePaymentInputList.d.ts +2 -0
- package/bin/retailWizard/validators/IsSalePaymentInputList.js +11 -0
- package/bin/retailWizard/validators/IsSalePaymentList.d.ts +1 -1
- package/bin/retailWizard/validators/IsSalePaymentList.js +3 -3
- package/package.json +1 -1
- package/src/emailVerification/dtos/internal/EmailOwnersByEmailRequest.ts +11 -0
- package/src/emailVerification/index.ts +1 -0
- package/src/retailCommission/dtos/CommissionApi.ts +25 -0
- package/src/retailWizard/dtos/SalePayment.ts +9 -20
- package/src/retailWizard/dtos/StoredSalePayment.ts +46 -0
- package/src/retailWizard/dtos/requests/CreateAccessorySaleRequest.ts +3 -3
- package/src/retailWizard/dtos/requests/DownPaymentRequest.ts +3 -3
- package/src/retailWizard/dtos/requests/RegisterPaymentRequest.ts +3 -3
- package/src/retailWizard/index.ts +2 -0
- package/src/retailWizard/validators/IsSalePaymentInputList.ts +9 -0
- package/src/retailWizard/validators/IsSalePaymentList.ts +3 -3
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { plainToInstance } from 'class-transformer';
|
|
3
|
+
import { validate } from 'class-validator';
|
|
4
|
+
import { EmailOwnersByEmailRequest } from '../../../../../src/emailVerification/dtos/internal/EmailOwnersByEmailRequest';
|
|
5
|
+
import * as emailVerification from '../../../../../src/emailVerification';
|
|
6
|
+
|
|
7
|
+
describe('EmailOwnersByEmailRequest', () => {
|
|
8
|
+
it('valida happy path (0 errores)', async () => {
|
|
9
|
+
const dto = plainToInstance(EmailOwnersByEmailRequest, { email: 'persona@ejemplo.com' });
|
|
10
|
+
const errors = await validate(dto);
|
|
11
|
+
expect(errors).toEqual([]);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('falla si email no es un correo válido', async () => {
|
|
15
|
+
const dto = plainToInstance(EmailOwnersByEmailRequest, { email: 'no-es-correo' });
|
|
16
|
+
const errors = await validate(dto);
|
|
17
|
+
expect(errors.some(e => e.property === 'email')).toBe(true);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('falla si falta email', async () => {
|
|
21
|
+
const dto = plainToInstance(EmailOwnersByEmailRequest, {});
|
|
22
|
+
const errors = await validate(dto);
|
|
23
|
+
expect(errors.some(e => e.property === 'email')).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('se exporta desde el barrel de emailVerification', () => {
|
|
27
|
+
expect(emailVerification.EmailOwnersByEmailRequest).toBe(EmailOwnersByEmailRequest);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -3,6 +3,7 @@ import { plainToInstance } from 'class-transformer';
|
|
|
3
3
|
import { validateSync, type ValidationError } from 'class-validator';
|
|
4
4
|
import { SalePayment } from '../../../src/retailWizard/dtos/SalePayment';
|
|
5
5
|
import { WizardPayment } from '../../../src/retailWizard/dtos/WizardPayment';
|
|
6
|
+
import { StoredSalePayment } from '../../../src/retailWizard/dtos/StoredSalePayment';
|
|
6
7
|
import { RegisterPaymentRequest } from '../../../src/retailWizard/dtos/requests/RegisterPaymentRequest';
|
|
7
8
|
import { DownPaymentRequest } from '../../../src/retailWizard/dtos/requests/DownPaymentRequest';
|
|
8
9
|
import { CreateAccessorySaleRequest } from '../../../src/retailWizard/dtos/requests/CreateAccessorySaleRequest';
|
|
@@ -28,17 +29,32 @@ const cash = { method: CASH, amountCents: 10000, cashConfirmedInRegister: true }
|
|
|
28
29
|
const card = { method: CARD, amountCents: 5000, cardLast4: '4242', authCode: 'A1B2C3' };
|
|
29
30
|
const wire = { method: WIRE, amountCents: 5000, speiTrackingKey: 'MBAN01002610', senderClabe: '012180001234567897' };
|
|
30
31
|
|
|
31
|
-
describe('SalePayment', () => {
|
|
32
|
+
describe('SalePayment (forma del request)', () => {
|
|
33
|
+
it('acepta cualquier monto entero y comprobante en texto, sin revisar formato ni medio', () => {
|
|
34
|
+
expect(errorsOf(SalePayment, { method: CARD, amountCents: 0, cardLast4: '1', authCode: ' ' })).toEqual([]);
|
|
35
|
+
expect(errorsOf(SalePayment, { method: CASH, amountCents: -5, speiTrackingKey: 'MBAN-01' })).toEqual([]);
|
|
36
|
+
expect(errorsOf(SalePayment, { method: WIRE, amountCents: 1, senderClabe: null, cashConfirmedInRegister: null })).toEqual([]);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('rechaza lo que no tiene la forma', () => {
|
|
40
|
+
expect(errorsOf(SalePayment, { method: 'FIADO', amountCents: 1 })).toEqual(['method']);
|
|
41
|
+
expect(errorsOf(SalePayment, { method: CASH, amountCents: 1.5 })).toEqual(['amountCents']);
|
|
42
|
+
expect(errorsOf(SalePayment, { method: CARD, amountCents: 1, cardLast4: 4242 })).toEqual(['cardLast4']);
|
|
43
|
+
expect(errorsOf(SalePayment, { method: CASH, amountCents: 1, cashConfirmedInRegister: 'yes' })).toEqual(['cashConfirmedInRegister']);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('StoredSalePayment (cobro ya registrado)', () => {
|
|
32
48
|
it('acepta cada medio con comprobante', () => {
|
|
33
|
-
expect(errorsOf(
|
|
34
|
-
expect(errorsOf(
|
|
35
|
-
expect(errorsOf(
|
|
49
|
+
expect(errorsOf(StoredSalePayment, cash)).toEqual([]);
|
|
50
|
+
expect(errorsOf(StoredSalePayment, card)).toEqual([]);
|
|
51
|
+
expect(errorsOf(StoredSalePayment, wire)).toEqual([]);
|
|
36
52
|
});
|
|
37
53
|
|
|
38
54
|
it('acepta tarjeta y SPEI sin comprobante, ausente o en null', () => {
|
|
39
|
-
expect(errorsOf(
|
|
40
|
-
expect(errorsOf(
|
|
41
|
-
expect(errorsOf(
|
|
55
|
+
expect(errorsOf(StoredSalePayment, { method: CARD, amountCents: 5000 })).toEqual([]);
|
|
56
|
+
expect(errorsOf(StoredSalePayment, { method: WIRE, amountCents: 5000, speiTrackingKey: null, senderClabe: null })).toEqual([]);
|
|
57
|
+
expect(errorsOf(StoredSalePayment, { method: CASH, amountCents: 5000, cashConfirmedInRegister: null })).toEqual([]);
|
|
42
58
|
});
|
|
43
59
|
|
|
44
60
|
it.each([
|
|
@@ -49,7 +65,7 @@ describe('SalePayment', () => {
|
|
|
49
65
|
['senderClabe', { ...wire, senderClabe: '0121' }],
|
|
50
66
|
['cashConfirmedInRegister', { ...cash, cashConfirmedInRegister: 'yes' }],
|
|
51
67
|
])('rechaza %s con formato inválido', (field, payload) => {
|
|
52
|
-
expect(errorsOf(
|
|
68
|
+
expect(errorsOf(StoredSalePayment, payload)).toEqual([field]);
|
|
53
69
|
});
|
|
54
70
|
|
|
55
71
|
it.each([
|
|
@@ -57,13 +73,13 @@ describe('SalePayment', () => {
|
|
|
57
73
|
['speiTrackingKey', { ...card, speiTrackingKey: 'MBAN01' }],
|
|
58
74
|
['cashConfirmedInRegister', { ...wire, cashConfirmedInRegister: true }],
|
|
59
75
|
])('rechaza %s en un medio que no le corresponde', (field, payload) => {
|
|
60
|
-
expect(errorsOf(
|
|
76
|
+
expect(errorsOf(StoredSalePayment, payload)).toEqual([field]);
|
|
61
77
|
});
|
|
62
78
|
|
|
63
79
|
it('rechaza un medio fuera del enum y un monto no positivo', () => {
|
|
64
|
-
expect(errorsOf(
|
|
65
|
-
expect(errorsOf(
|
|
66
|
-
expect(errorsOf(
|
|
80
|
+
expect(errorsOf(StoredSalePayment, { method: 'FIADO', amountCents: 100 })).toEqual(['method']);
|
|
81
|
+
expect(errorsOf(StoredSalePayment, { ...cash, amountCents: 0 })).toEqual(['amountCents']);
|
|
82
|
+
expect(errorsOf(StoredSalePayment, { ...cash, amountCents: 10.5 })).toEqual(['amountCents']);
|
|
67
83
|
});
|
|
68
84
|
});
|
|
69
85
|
|
|
@@ -72,10 +88,6 @@ describe('payments en RegisterPaymentRequest', () => {
|
|
|
72
88
|
expect(errorsOf(RegisterPaymentRequest, { amountCents: 20000, payments: [cash, card, wire] })).toEqual([]);
|
|
73
89
|
});
|
|
74
90
|
|
|
75
|
-
it('acepta tarjeta repetida', () => {
|
|
76
|
-
expect(errorsOf(RegisterPaymentRequest, { amountCents: 20000, payments: [cash, card, card] })).toEqual([]);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
91
|
it('sigue aceptando el formato viejo', () => {
|
|
80
92
|
expect(errorsOf(RegisterPaymentRequest, { method: CASH, amountCents: 20000, detail: { cashConfirmedInRegister: true } })).toEqual([]);
|
|
81
93
|
});
|
|
@@ -84,24 +96,17 @@ describe('payments en RegisterPaymentRequest', () => {
|
|
|
84
96
|
expect(errorsOf(RegisterPaymentRequest, { amountCents: 20000 })).toEqual(['method']);
|
|
85
97
|
});
|
|
86
98
|
|
|
87
|
-
it('
|
|
88
|
-
expect(errorsOf(RegisterPaymentRequest, { amountCents: 20000, payments: [cash, cash] })).toEqual([
|
|
89
|
-
expect(errorsOf(RegisterPaymentRequest, { amountCents:
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
expect(errorsOf(RegisterPaymentRequest, { amountCents: 25000, payments: [cash, card, card, wire] })).toEqual(['payments']);
|
|
94
|
-
expect(errorsOf(RegisterPaymentRequest, { amountCents: 0, payments: [] })).toEqual(['payments']);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('rechaza que la suma no cuadre con amountCents', () => {
|
|
98
|
-
expect(errorsOf(RegisterPaymentRequest, { amountCents: 20001, payments: [cash, card, wire] })).toEqual(['payments']);
|
|
99
|
+
it('deja pasar las reglas de negocio para que el dominio responda con su code', () => {
|
|
100
|
+
expect(errorsOf(RegisterPaymentRequest, { amountCents: 20000, payments: [cash, cash] })).toEqual([]);
|
|
101
|
+
expect(errorsOf(RegisterPaymentRequest, { amountCents: 25000, payments: [cash, card, card, wire] })).toEqual([]);
|
|
102
|
+
expect(errorsOf(RegisterPaymentRequest, { amountCents: 0, payments: [] })).toEqual([]);
|
|
103
|
+
expect(errorsOf(RegisterPaymentRequest, { amountCents: 20001, payments: [cash, card, wire] })).toEqual([]);
|
|
104
|
+
expect(errorsOf(RegisterPaymentRequest, { amountCents: 15000, payments: [cash, { ...card, cardLast4: '1' }] })).toEqual([]);
|
|
99
105
|
});
|
|
100
106
|
|
|
101
|
-
it('reporta el campo
|
|
102
|
-
expect(errorsOf(RegisterPaymentRequest, { amountCents:
|
|
103
|
-
|
|
104
|
-
]);
|
|
107
|
+
it('rechaza lo que no tiene la forma y reporta el campo', () => {
|
|
108
|
+
expect(errorsOf(RegisterPaymentRequest, { amountCents: 1, payments: 'CASH' })).toEqual(['payments']);
|
|
109
|
+
expect(errorsOf(RegisterPaymentRequest, { amountCents: 1, payments: [{ ...card, method: 'FIADO' }] })).toEqual(['payments.0.method']);
|
|
105
110
|
});
|
|
106
111
|
});
|
|
107
112
|
|
|
@@ -135,16 +140,18 @@ describe('cobro de $0', () => {
|
|
|
135
140
|
});
|
|
136
141
|
|
|
137
142
|
describe('payments en los demás contratos', () => {
|
|
138
|
-
it('DownPaymentRequest acepta solo payments y
|
|
143
|
+
it('DownPaymentRequest acepta solo payments y deja la suma al dominio', () => {
|
|
139
144
|
expect(errorsOf(DownPaymentRequest, { amountCents: 15000, payments: [cash, wire] })).toEqual([]);
|
|
140
|
-
expect(errorsOf(DownPaymentRequest, { amountCents: 1, payments: [cash, wire] })).toEqual([
|
|
145
|
+
expect(errorsOf(DownPaymentRequest, { amountCents: 1, payments: [cash, wire] })).toEqual([]);
|
|
146
|
+
expect(errorsOf(DownPaymentRequest, { amountCents: 1, payments: [{ ...wire, amountCents: 'x' }] })).toEqual(['payments.0.amountCents']);
|
|
141
147
|
});
|
|
142
148
|
|
|
143
149
|
it('CreateAccessorySaleRequest acepta solo payments y ya no exige paymentDetail', () => {
|
|
144
150
|
const lines = [{ sku: 'ACC-1', qty: 1 }];
|
|
145
151
|
expect(errorsOf(CreateAccessorySaleRequest, { lines, amountCents: 15000, payments: [cash, card] })).toEqual([]);
|
|
146
152
|
expect(errorsOf(CreateAccessorySaleRequest, { lines, amountCents: 15000 })).toEqual(['paymentMethod']);
|
|
147
|
-
expect(errorsOf(CreateAccessorySaleRequest, { lines, amountCents: 20000, payments: [cash, cash] })).toEqual([
|
|
153
|
+
expect(errorsOf(CreateAccessorySaleRequest, { lines, amountCents: 20000, payments: [cash, cash] })).toEqual([]);
|
|
154
|
+
expect(errorsOf(CreateAccessorySaleRequest, { lines, amountCents: 1, payments: [{ ...card, authCode: 7 }] })).toEqual(['payments.0.authCode']);
|
|
148
155
|
});
|
|
149
156
|
|
|
150
157
|
it('WizardPayment guarda payments tipados', () => {
|
|
@@ -152,6 +159,7 @@ describe('payments en los demás contratos', () => {
|
|
|
152
159
|
expect(errorsOf(WizardPayment, { ...base, payments: [cash, card] })).toEqual([]);
|
|
153
160
|
expect(errorsOf(WizardPayment, base)).toEqual([]);
|
|
154
161
|
expect(errorsOf(WizardPayment, { ...base, payments: [cash, cash] })).toEqual(['payments']);
|
|
162
|
+
expect(errorsOf(WizardPayment, { ...base, payments: [{ ...card, cardLast4: '1' }] })).toEqual(['payments.0.cardLast4']);
|
|
155
163
|
});
|
|
156
164
|
|
|
157
165
|
it('RetailPromotionInboundMessage acepta paymentMethods y rechaza valores fuera del enum', () => {
|
|
@@ -0,0 +1,25 @@
|
|
|
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.EmailOwnersByEmailRequest = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
/**
|
|
16
|
+
* Request interno (api-invoker) para buscar qué directorios tienen un correo.
|
|
17
|
+
*/
|
|
18
|
+
class EmailOwnersByEmailRequest {
|
|
19
|
+
}
|
|
20
|
+
exports.EmailOwnersByEmailRequest = EmailOwnersByEmailRequest;
|
|
21
|
+
__decorate([
|
|
22
|
+
(0, class_transformer_1.Expose)(),
|
|
23
|
+
(0, class_validator_1.IsEmail)(),
|
|
24
|
+
__metadata("design:type", String)
|
|
25
|
+
], EmailOwnersByEmailRequest.prototype, "email", void 0);
|
|
@@ -24,3 +24,4 @@ export * from './dtos/internal/EmailsByDirectoryRequest';
|
|
|
24
24
|
export * from './dtos/internal/EmailsByDirectoryResponse';
|
|
25
25
|
export * from './dtos/internal/EmailStartByDirectoryRequest';
|
|
26
26
|
export * from './dtos/internal/EmailStartByDirectoryResponse';
|
|
27
|
+
export * from './dtos/internal/EmailOwnersByEmailRequest';
|
|
@@ -40,3 +40,4 @@ __exportStar(require("./dtos/internal/EmailsByDirectoryRequest"), exports);
|
|
|
40
40
|
__exportStar(require("./dtos/internal/EmailsByDirectoryResponse"), exports);
|
|
41
41
|
__exportStar(require("./dtos/internal/EmailStartByDirectoryRequest"), exports);
|
|
42
42
|
__exportStar(require("./dtos/internal/EmailStartByDirectoryResponse"), exports);
|
|
43
|
+
__exportStar(require("./dtos/internal/EmailOwnersByEmailRequest"), exports);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CommissionPlanStatusEnum } from '../enums/CommissionPlanStatusEnum';
|
|
2
|
+
import type { CommissionRuleStatusEnum } from '../enums/CommissionRuleStatusEnum';
|
|
2
3
|
import type { CommissionPayoutStatusEnum } from '../enums/CommissionPayoutStatusEnum';
|
|
3
4
|
import type { CommissionAddOn, CommissionCategory, CommissionPlanSnapshot, CommissionQuota } from './CommissionPlan';
|
|
4
5
|
import type { CommissionAccrual, CommissionAppliedBonus, CommissionSaleInput, CommissionSaleLine } from './CommissionAccrual';
|
|
@@ -227,12 +228,74 @@ export interface RuleActionResponse {
|
|
|
227
228
|
rule: CommissionRule;
|
|
228
229
|
snapshotId: string;
|
|
229
230
|
}
|
|
231
|
+
/** Un campo de la regla que cambió de una versión a la siguiente, con su valor antes y después. */
|
|
232
|
+
export type CommissionRuleChange = {
|
|
233
|
+
field: 'name';
|
|
234
|
+
before: string;
|
|
235
|
+
after: string;
|
|
236
|
+
} | {
|
|
237
|
+
field: 'description';
|
|
238
|
+
before: string | null;
|
|
239
|
+
after: string | null;
|
|
240
|
+
} | {
|
|
241
|
+
field: 'levers';
|
|
242
|
+
before: CommissionRuleLevers;
|
|
243
|
+
after: CommissionRuleLevers;
|
|
244
|
+
} | {
|
|
245
|
+
field: 'scope';
|
|
246
|
+
before: CommissionRuleScope;
|
|
247
|
+
after: CommissionRuleScope;
|
|
248
|
+
} | {
|
|
249
|
+
field: 'condition';
|
|
250
|
+
before: CommissionRuleCondition | null;
|
|
251
|
+
after: CommissionRuleCondition | null;
|
|
252
|
+
} | {
|
|
253
|
+
field: 'effectiveFrom';
|
|
254
|
+
before: string;
|
|
255
|
+
after: string;
|
|
256
|
+
} | {
|
|
257
|
+
field: 'effectiveTo';
|
|
258
|
+
before: string | null;
|
|
259
|
+
after: string | null;
|
|
260
|
+
} | {
|
|
261
|
+
field: 'priority';
|
|
262
|
+
before: number;
|
|
263
|
+
after: number;
|
|
264
|
+
} | {
|
|
265
|
+
field: 'replacesOthers';
|
|
266
|
+
before: boolean;
|
|
267
|
+
after: boolean;
|
|
268
|
+
} | {
|
|
269
|
+
field: 'countBy';
|
|
270
|
+
before: CommissionCountByEnum;
|
|
271
|
+
after: CommissionCountByEnum;
|
|
272
|
+
} | {
|
|
273
|
+
field: 'payTiming';
|
|
274
|
+
before: CommissionPayTimingEnum;
|
|
275
|
+
after: CommissionPayTimingEnum;
|
|
276
|
+
} | {
|
|
277
|
+
field: 'onSaleAdvanceBps';
|
|
278
|
+
before: number | null;
|
|
279
|
+
after: number | null;
|
|
280
|
+
};
|
|
230
281
|
/** Un evento del historial de una regla. */
|
|
231
282
|
export interface CommissionRuleEvent {
|
|
232
283
|
at: string;
|
|
233
284
|
action: string;
|
|
234
285
|
performedBy: string;
|
|
235
286
|
version: number | null;
|
|
287
|
+
/**
|
|
288
|
+
* Solo en ediciones: lo que cambió respecto a la versión anterior; vacío si no cambió ningún campo.
|
|
289
|
+
* Ausente si no hay versión anterior con qué comparar, y en motores anteriores.
|
|
290
|
+
*/
|
|
291
|
+
changes?: CommissionRuleChange[];
|
|
292
|
+
/** Junto a `changes`: si la versión editada cuenta piezas o ventas, para leer sus palancas y su condición. */
|
|
293
|
+
countBy?: CommissionCountByEnum;
|
|
294
|
+
/** El estado que tenía la regla y el que le dejó el evento; `null` si no lo cambió o no se sabe. Ausente en motores anteriores. */
|
|
295
|
+
statusChange?: {
|
|
296
|
+
from: CommissionRuleStatusEnum;
|
|
297
|
+
to: CommissionRuleStatusEnum;
|
|
298
|
+
} | null;
|
|
236
299
|
}
|
|
237
300
|
/** `GET /backoffice/commissions/rules/{ruleId}/history` — del más nuevo al más viejo. */
|
|
238
301
|
export interface RuleHistoryResponse {
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { SalePaymentMethodEnum } from '../enums/SalePaymentMethodEnum';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Un pago del cobro tal como llega en un request: solo la forma. Tope, uso único, suma, monto
|
|
4
|
+
* positivo y formato del comprobante los valida el dominio con su code.
|
|
5
|
+
*/
|
|
3
6
|
export declare class SalePayment {
|
|
4
7
|
method: SalePaymentMethodEnum;
|
|
5
8
|
amountCents: number;
|
|
@@ -12,12 +12,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.SalePayment = void 0;
|
|
13
13
|
const class_transformer_1 = require("class-transformer");
|
|
14
14
|
const class_validator_1 = require("class-validator");
|
|
15
|
-
const retailIntegrationLimits_1 = require("../../retailIntegration/constants/retailIntegrationLimits");
|
|
16
15
|
const SalePaymentMethodEnum_1 = require("../enums/SalePaymentMethodEnum");
|
|
17
|
-
const OnlyForPaymentMethodConstraint_1 = require("../validators/OnlyForPaymentMethodConstraint");
|
|
18
|
-
const { CASH, CARD, WIRE } = SalePaymentMethodEnum_1.SalePaymentMethodEnum;
|
|
19
16
|
const hasValue = (field) => (o) => o[field] != null;
|
|
20
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* Un pago del cobro tal como llega en un request: solo la forma. Tope, uso único, suma, monto
|
|
19
|
+
* positivo y formato del comprobante los valida el dominio con su code.
|
|
20
|
+
*/
|
|
21
21
|
class SalePayment {
|
|
22
22
|
}
|
|
23
23
|
exports.SalePayment = SalePayment;
|
|
@@ -29,41 +29,35 @@ __decorate([
|
|
|
29
29
|
__decorate([
|
|
30
30
|
(0, class_transformer_1.Expose)(),
|
|
31
31
|
(0, class_validator_1.IsInt)(),
|
|
32
|
-
(0, class_validator_1.Min)(1),
|
|
33
32
|
__metadata("design:type", Number)
|
|
34
33
|
], SalePayment.prototype, "amountCents", void 0);
|
|
35
34
|
__decorate([
|
|
36
35
|
(0, class_transformer_1.Expose)(),
|
|
37
36
|
(0, class_validator_1.ValidateIf)(hasValue('cashConfirmedInRegister')),
|
|
38
37
|
(0, class_validator_1.IsBoolean)(),
|
|
39
|
-
(0, class_validator_1.Validate)(OnlyForPaymentMethodConstraint_1.OnlyForPaymentMethodConstraint, [CASH]),
|
|
40
38
|
__metadata("design:type", Boolean)
|
|
41
39
|
], SalePayment.prototype, "cashConfirmedInRegister", void 0);
|
|
42
40
|
__decorate([
|
|
43
41
|
(0, class_transformer_1.Expose)(),
|
|
44
42
|
(0, class_validator_1.ValidateIf)(hasValue('cardLast4')),
|
|
45
|
-
(0, class_validator_1.
|
|
46
|
-
(0, class_validator_1.Validate)(OnlyForPaymentMethodConstraint_1.OnlyForPaymentMethodConstraint, [CARD]),
|
|
43
|
+
(0, class_validator_1.IsString)(),
|
|
47
44
|
__metadata("design:type", String)
|
|
48
45
|
], SalePayment.prototype, "cardLast4", void 0);
|
|
49
46
|
__decorate([
|
|
50
47
|
(0, class_transformer_1.Expose)(),
|
|
51
48
|
(0, class_validator_1.ValidateIf)(hasValue('authCode')),
|
|
52
|
-
(0, class_validator_1.
|
|
53
|
-
(0, class_validator_1.Validate)(OnlyForPaymentMethodConstraint_1.OnlyForPaymentMethodConstraint, [CARD]),
|
|
49
|
+
(0, class_validator_1.IsString)(),
|
|
54
50
|
__metadata("design:type", String)
|
|
55
51
|
], SalePayment.prototype, "authCode", void 0);
|
|
56
52
|
__decorate([
|
|
57
53
|
(0, class_transformer_1.Expose)(),
|
|
58
54
|
(0, class_validator_1.ValidateIf)(hasValue('speiTrackingKey')),
|
|
59
|
-
(0, class_validator_1.
|
|
60
|
-
(0, class_validator_1.Validate)(OnlyForPaymentMethodConstraint_1.OnlyForPaymentMethodConstraint, [WIRE]),
|
|
55
|
+
(0, class_validator_1.IsString)(),
|
|
61
56
|
__metadata("design:type", String)
|
|
62
57
|
], SalePayment.prototype, "speiTrackingKey", void 0);
|
|
63
58
|
__decorate([
|
|
64
59
|
(0, class_transformer_1.Expose)(),
|
|
65
60
|
(0, class_validator_1.ValidateIf)(hasValue('senderClabe')),
|
|
66
|
-
(0, class_validator_1.
|
|
67
|
-
(0, class_validator_1.Validate)(OnlyForPaymentMethodConstraint_1.OnlyForPaymentMethodConstraint, [WIRE]),
|
|
61
|
+
(0, class_validator_1.IsString)(),
|
|
68
62
|
__metadata("design:type", String)
|
|
69
63
|
], SalePayment.prototype, "senderClabe", void 0);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SalePayment } from './SalePayment';
|
|
2
|
+
/**
|
|
3
|
+
* Pago ya registrado (cobro de la sesión): monto positivo y comprobante con formato, solo en su medio.
|
|
4
|
+
* Repite las reglas de forma porque class-validator descarta las del padre en la propiedad que se redeclara.
|
|
5
|
+
*/
|
|
6
|
+
export declare class StoredSalePayment extends SalePayment {
|
|
7
|
+
amountCents: number;
|
|
8
|
+
cashConfirmedInRegister?: boolean | null;
|
|
9
|
+
cardLast4?: string | null;
|
|
10
|
+
authCode?: string | null;
|
|
11
|
+
speiTrackingKey?: string | null;
|
|
12
|
+
senderClabe?: string | null;
|
|
13
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
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.StoredSalePayment = void 0;
|
|
13
|
+
const class_validator_1 = require("class-validator");
|
|
14
|
+
const retailIntegrationLimits_1 = require("../../retailIntegration/constants/retailIntegrationLimits");
|
|
15
|
+
const SalePaymentMethodEnum_1 = require("../enums/SalePaymentMethodEnum");
|
|
16
|
+
const OnlyForPaymentMethodConstraint_1 = require("../validators/OnlyForPaymentMethodConstraint");
|
|
17
|
+
const SalePayment_1 = require("./SalePayment");
|
|
18
|
+
const { CASH, CARD, WIRE } = SalePaymentMethodEnum_1.SalePaymentMethodEnum;
|
|
19
|
+
/**
|
|
20
|
+
* Pago ya registrado (cobro de la sesión): monto positivo y comprobante con formato, solo en su medio.
|
|
21
|
+
* Repite las reglas de forma porque class-validator descarta las del padre en la propiedad que se redeclara.
|
|
22
|
+
*/
|
|
23
|
+
class StoredSalePayment extends SalePayment_1.SalePayment {
|
|
24
|
+
}
|
|
25
|
+
exports.StoredSalePayment = StoredSalePayment;
|
|
26
|
+
__decorate([
|
|
27
|
+
(0, class_validator_1.IsInt)(),
|
|
28
|
+
(0, class_validator_1.Min)(1),
|
|
29
|
+
__metadata("design:type", Number)
|
|
30
|
+
], StoredSalePayment.prototype, "amountCents", void 0);
|
|
31
|
+
__decorate([
|
|
32
|
+
(0, class_validator_1.IsBoolean)(),
|
|
33
|
+
(0, class_validator_1.Validate)(OnlyForPaymentMethodConstraint_1.OnlyForPaymentMethodConstraint, [CASH]),
|
|
34
|
+
__metadata("design:type", Boolean)
|
|
35
|
+
], StoredSalePayment.prototype, "cashConfirmedInRegister", void 0);
|
|
36
|
+
__decorate([
|
|
37
|
+
(0, class_validator_1.IsString)(),
|
|
38
|
+
(0, class_validator_1.Matches)(retailIntegrationLimits_1.RETAIL_CARD_LAST4_PATTERN),
|
|
39
|
+
(0, class_validator_1.Validate)(OnlyForPaymentMethodConstraint_1.OnlyForPaymentMethodConstraint, [CARD]),
|
|
40
|
+
__metadata("design:type", String)
|
|
41
|
+
], StoredSalePayment.prototype, "cardLast4", void 0);
|
|
42
|
+
__decorate([
|
|
43
|
+
(0, class_validator_1.IsString)(),
|
|
44
|
+
(0, class_validator_1.Matches)(retailIntegrationLimits_1.RETAIL_SALE_ID_TEXT_PATTERN),
|
|
45
|
+
(0, class_validator_1.Validate)(OnlyForPaymentMethodConstraint_1.OnlyForPaymentMethodConstraint, [CARD]),
|
|
46
|
+
__metadata("design:type", String)
|
|
47
|
+
], StoredSalePayment.prototype, "authCode", void 0);
|
|
48
|
+
__decorate([
|
|
49
|
+
(0, class_validator_1.IsString)(),
|
|
50
|
+
(0, class_validator_1.Matches)(retailIntegrationLimits_1.RETAIL_SPEI_TRACKING_KEY_PATTERN),
|
|
51
|
+
(0, class_validator_1.Validate)(OnlyForPaymentMethodConstraint_1.OnlyForPaymentMethodConstraint, [WIRE]),
|
|
52
|
+
__metadata("design:type", String)
|
|
53
|
+
], StoredSalePayment.prototype, "speiTrackingKey", void 0);
|
|
54
|
+
__decorate([
|
|
55
|
+
(0, class_validator_1.IsString)(),
|
|
56
|
+
(0, class_validator_1.Matches)(retailIntegrationLimits_1.RETAIL_CLABE_PATTERN),
|
|
57
|
+
(0, class_validator_1.Validate)(OnlyForPaymentMethodConstraint_1.OnlyForPaymentMethodConstraint, [WIRE]),
|
|
58
|
+
__metadata("design:type", String)
|
|
59
|
+
], StoredSalePayment.prototype, "senderClabe", void 0);
|
|
@@ -13,6 +13,6 @@ export declare class CreateAccessorySaleRequest {
|
|
|
13
13
|
amountCents: number;
|
|
14
14
|
/** @deprecated Usa el comprobante de cada elemento de `payments`. */
|
|
15
15
|
paymentDetail?: SalePaymentDetail;
|
|
16
|
-
/** Pagos del cobro
|
|
16
|
+
/** Pagos del cobro; si viene, manda sobre `paymentMethod` y `paymentDetail`. */
|
|
17
17
|
payments?: SalePayment[];
|
|
18
18
|
}
|
|
@@ -15,7 +15,7 @@ const class_validator_1 = require("class-validator");
|
|
|
15
15
|
const SalePaymentMethodEnum_1 = require("../../enums/SalePaymentMethodEnum");
|
|
16
16
|
const SalePaymentDetail_1 = require("../SalePaymentDetail");
|
|
17
17
|
const AccessorySaleLine_1 = require("../AccessorySaleLine");
|
|
18
|
-
const
|
|
18
|
+
const IsSalePaymentInputList_1 = require("../../validators/IsSalePaymentInputList");
|
|
19
19
|
/**
|
|
20
20
|
* POST /wizard/accessory-sales — cierra la venta de mostrador, sin cliente.
|
|
21
21
|
* `amountCents` es lo cobrado en caja: iguala la suma del catálogo y la de `payments`.
|
|
@@ -54,6 +54,6 @@ __decorate([
|
|
|
54
54
|
__decorate([
|
|
55
55
|
(0, class_transformer_1.Expose)(),
|
|
56
56
|
(0, class_validator_1.IsOptional)(),
|
|
57
|
-
(0,
|
|
57
|
+
(0, IsSalePaymentInputList_1.IsSalePaymentInputList)(),
|
|
58
58
|
__metadata("design:type", Array)
|
|
59
59
|
], CreateAccessorySaleRequest.prototype, "payments", void 0);
|
|
@@ -16,6 +16,6 @@ export declare class DownPaymentRequest {
|
|
|
16
16
|
amountCents: number;
|
|
17
17
|
/** @deprecated Usa el comprobante de cada elemento de `payments`. */
|
|
18
18
|
detail?: SalePaymentDetail;
|
|
19
|
-
/** Pagos del cobro
|
|
19
|
+
/** Pagos del cobro; si viene, manda sobre `method` y `detail`. */
|
|
20
20
|
payments?: SalePayment[];
|
|
21
21
|
}
|
|
@@ -14,7 +14,7 @@ const class_transformer_1 = require("class-transformer");
|
|
|
14
14
|
const class_validator_1 = require("class-validator");
|
|
15
15
|
const SalePaymentMethodEnum_1 = require("../../enums/SalePaymentMethodEnum");
|
|
16
16
|
const SalePaymentDetail_1 = require("../SalePaymentDetail");
|
|
17
|
-
const
|
|
17
|
+
const IsSalePaymentInputList_1 = require("../../validators/IsSalePaymentInputList");
|
|
18
18
|
/**
|
|
19
19
|
* POST /wizard/sessions/:id/down-payment — cobro del ENGANCHE de la venta a crédito (paso 07,
|
|
20
20
|
* pista SOFOM). Endpoint propio, separado del cobro de contado (`/payment`): acá la regla dura es
|
|
@@ -49,6 +49,6 @@ __decorate([
|
|
|
49
49
|
__decorate([
|
|
50
50
|
(0, class_transformer_1.Expose)(),
|
|
51
51
|
(0, class_validator_1.IsOptional)(),
|
|
52
|
-
(0,
|
|
52
|
+
(0, IsSalePaymentInputList_1.IsSalePaymentInputList)(),
|
|
53
53
|
__metadata("design:type", Array)
|
|
54
54
|
], DownPaymentRequest.prototype, "payments", void 0);
|
|
@@ -12,6 +12,6 @@ export declare class RegisterPaymentRequest {
|
|
|
12
12
|
amountCents: number;
|
|
13
13
|
/** @deprecated Usa el comprobante de cada elemento de `payments`. */
|
|
14
14
|
detail?: SalePaymentDetail;
|
|
15
|
-
/** Pagos del cobro
|
|
15
|
+
/** Pagos del cobro; si viene, manda sobre `method` y `detail`. */
|
|
16
16
|
payments?: SalePayment[];
|
|
17
17
|
}
|
|
@@ -14,7 +14,7 @@ const class_transformer_1 = require("class-transformer");
|
|
|
14
14
|
const class_validator_1 = require("class-validator");
|
|
15
15
|
const SalePaymentMethodEnum_1 = require("../../enums/SalePaymentMethodEnum");
|
|
16
16
|
const SalePaymentDetail_1 = require("../SalePaymentDetail");
|
|
17
|
-
const
|
|
17
|
+
const IsSalePaymentInputList_1 = require("../../validators/IsSalePaymentInputList");
|
|
18
18
|
/**
|
|
19
19
|
* POST /wizard/sessions/:id/payment — registra el cobro de contado (idempotente por sesión). Regla
|
|
20
20
|
* dura: `amountCents == cashPrice` de la reserva. `POST /payment/folio` genera el folio server-side
|
|
@@ -45,6 +45,6 @@ __decorate([
|
|
|
45
45
|
__decorate([
|
|
46
46
|
(0, class_transformer_1.Expose)(),
|
|
47
47
|
(0, class_validator_1.IsOptional)(),
|
|
48
|
-
(0,
|
|
48
|
+
(0, IsSalePaymentInputList_1.IsSalePaymentInputList)(),
|
|
49
49
|
__metadata("design:type", Array)
|
|
50
50
|
], RegisterPaymentRequest.prototype, "payments", void 0);
|
|
@@ -41,6 +41,8 @@ export * from './dtos/WizardWelcome';
|
|
|
41
41
|
export * from './dtos/WizardCreditPromotionBonus';
|
|
42
42
|
export * from './dtos/SalePaymentDetail';
|
|
43
43
|
export * from './dtos/SalePayment';
|
|
44
|
+
export * from './dtos/StoredSalePayment';
|
|
45
|
+
export * from './validators/IsSalePaymentInputList';
|
|
44
46
|
export * from './validators/IsSalePaymentList';
|
|
45
47
|
export * from './validators/OnlyForPaymentMethodConstraint';
|
|
46
48
|
export * from './validators/PaymentsHaveSingleUseMethodsConstraint';
|
|
@@ -61,6 +61,8 @@ __exportStar(require("./dtos/WizardWelcome"), exports);
|
|
|
61
61
|
__exportStar(require("./dtos/WizardCreditPromotionBonus"), exports);
|
|
62
62
|
__exportStar(require("./dtos/SalePaymentDetail"), exports);
|
|
63
63
|
__exportStar(require("./dtos/SalePayment"), exports);
|
|
64
|
+
__exportStar(require("./dtos/StoredSalePayment"), exports);
|
|
65
|
+
__exportStar(require("./validators/IsSalePaymentInputList"), exports);
|
|
64
66
|
__exportStar(require("./validators/IsSalePaymentList"), exports);
|
|
65
67
|
__exportStar(require("./validators/OnlyForPaymentMethodConstraint"), exports);
|
|
66
68
|
__exportStar(require("./validators/PaymentsHaveSingleUseMethodsConstraint"), exports);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IsSalePaymentInputList = IsSalePaymentInputList;
|
|
4
|
+
const class_transformer_1 = require("class-transformer");
|
|
5
|
+
const class_validator_1 = require("class-validator");
|
|
6
|
+
const SalePayment_1 = require("../dtos/SalePayment");
|
|
7
|
+
/** Forma de `payments` en un request: arreglo de pagos bien tipados. Las reglas de negocio las valida el dominio. */
|
|
8
|
+
function IsSalePaymentInputList() {
|
|
9
|
+
const decorators = [(0, class_validator_1.IsArray)(), (0, class_validator_1.ValidateNested)({ each: true }), (0, class_transformer_1.Type)(() => SalePayment_1.SalePayment)];
|
|
10
|
+
return (target, propertyKey) => decorators.forEach((decorate) => decorate(target, propertyKey));
|
|
11
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/** Reglas de `payments
|
|
1
|
+
/** Reglas de `payments` ya registrados (cobro de la sesión): 1 a 3 pagos válidos, efectivo y SPEI una vez, y la suma igual a `amountCents`. */
|
|
2
2
|
export declare function IsSalePaymentList(): PropertyDecorator;
|
|
@@ -4,17 +4,17 @@ exports.IsSalePaymentList = IsSalePaymentList;
|
|
|
4
4
|
const class_transformer_1 = require("class-transformer");
|
|
5
5
|
const class_validator_1 = require("class-validator");
|
|
6
6
|
const retailWizardValidation_1 = require("../constants/retailWizardValidation");
|
|
7
|
-
const
|
|
7
|
+
const StoredSalePayment_1 = require("../dtos/StoredSalePayment");
|
|
8
8
|
const PaymentsHaveSingleUseMethodsConstraint_1 = require("./PaymentsHaveSingleUseMethodsConstraint");
|
|
9
9
|
const PaymentsMatchAmountCentsConstraint_1 = require("./PaymentsMatchAmountCentsConstraint");
|
|
10
|
-
/** Reglas de `payments
|
|
10
|
+
/** Reglas de `payments` ya registrados (cobro de la sesión): 1 a 3 pagos válidos, efectivo y SPEI una vez, y la suma igual a `amountCents`. */
|
|
11
11
|
function IsSalePaymentList() {
|
|
12
12
|
const decorators = [
|
|
13
13
|
(0, class_validator_1.IsArray)(),
|
|
14
14
|
(0, class_validator_1.ArrayMinSize)(1),
|
|
15
15
|
(0, class_validator_1.ArrayMaxSize)(retailWizardValidation_1.MAX_SALE_PAYMENTS),
|
|
16
16
|
(0, class_validator_1.ValidateNested)({ each: true }),
|
|
17
|
-
(0, class_transformer_1.Type)(() =>
|
|
17
|
+
(0, class_transformer_1.Type)(() => StoredSalePayment_1.StoredSalePayment),
|
|
18
18
|
(0, class_validator_1.Validate)(PaymentsHaveSingleUseMethodsConstraint_1.PaymentsHaveSingleUseMethodsConstraint),
|
|
19
19
|
(0, class_validator_1.Validate)(PaymentsMatchAmountCentsConstraint_1.PaymentsMatchAmountCentsConstraint),
|
|
20
20
|
];
|
package/package.json
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Expose } from 'class-transformer';
|
|
2
|
+
import { IsEmail } from 'class-validator';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Request interno (api-invoker) para buscar qué directorios tienen un correo.
|
|
6
|
+
*/
|
|
7
|
+
export class EmailOwnersByEmailRequest {
|
|
8
|
+
@Expose()
|
|
9
|
+
@IsEmail()
|
|
10
|
+
email!: string;
|
|
11
|
+
}
|
|
@@ -24,3 +24,4 @@ export * from './dtos/internal/EmailsByDirectoryRequest';
|
|
|
24
24
|
export * from './dtos/internal/EmailsByDirectoryResponse';
|
|
25
25
|
export * from './dtos/internal/EmailStartByDirectoryRequest';
|
|
26
26
|
export * from './dtos/internal/EmailStartByDirectoryResponse';
|
|
27
|
+
export * from './dtos/internal/EmailOwnersByEmailRequest';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CommissionPlanStatusEnum } from '../enums/CommissionPlanStatusEnum';
|
|
2
|
+
import type { CommissionRuleStatusEnum } from '../enums/CommissionRuleStatusEnum';
|
|
2
3
|
import type { CommissionPayoutStatusEnum } from '../enums/CommissionPayoutStatusEnum';
|
|
3
4
|
import type {
|
|
4
5
|
CommissionAddOn,
|
|
@@ -295,12 +296,36 @@ export interface RuleActionResponse {
|
|
|
295
296
|
snapshotId: string;
|
|
296
297
|
}
|
|
297
298
|
|
|
299
|
+
/** Un campo de la regla que cambió de una versión a la siguiente, con su valor antes y después. */
|
|
300
|
+
export type CommissionRuleChange =
|
|
301
|
+
| { field: 'name'; before: string; after: string }
|
|
302
|
+
| { field: 'description'; before: string | null; after: string | null }
|
|
303
|
+
| { field: 'levers'; before: CommissionRuleLevers; after: CommissionRuleLevers }
|
|
304
|
+
| { field: 'scope'; before: CommissionRuleScope; after: CommissionRuleScope }
|
|
305
|
+
| { field: 'condition'; before: CommissionRuleCondition | null; after: CommissionRuleCondition | null }
|
|
306
|
+
| { field: 'effectiveFrom'; before: string; after: string }
|
|
307
|
+
| { field: 'effectiveTo'; before: string | null; after: string | null }
|
|
308
|
+
| { field: 'priority'; before: number; after: number }
|
|
309
|
+
| { field: 'replacesOthers'; before: boolean; after: boolean }
|
|
310
|
+
| { field: 'countBy'; before: CommissionCountByEnum; after: CommissionCountByEnum }
|
|
311
|
+
| { field: 'payTiming'; before: CommissionPayTimingEnum; after: CommissionPayTimingEnum }
|
|
312
|
+
| { field: 'onSaleAdvanceBps'; before: number | null; after: number | null };
|
|
313
|
+
|
|
298
314
|
/** Un evento del historial de una regla. */
|
|
299
315
|
export interface CommissionRuleEvent {
|
|
300
316
|
at: string;
|
|
301
317
|
action: string;
|
|
302
318
|
performedBy: string;
|
|
303
319
|
version: number | null;
|
|
320
|
+
/**
|
|
321
|
+
* Solo en ediciones: lo que cambió respecto a la versión anterior; vacío si no cambió ningún campo.
|
|
322
|
+
* Ausente si no hay versión anterior con qué comparar, y en motores anteriores.
|
|
323
|
+
*/
|
|
324
|
+
changes?: CommissionRuleChange[];
|
|
325
|
+
/** Junto a `changes`: si la versión editada cuenta piezas o ventas, para leer sus palancas y su condición. */
|
|
326
|
+
countBy?: CommissionCountByEnum;
|
|
327
|
+
/** El estado que tenía la regla y el que le dejó el evento; `null` si no lo cambió o no se sabe. Ausente en motores anteriores. */
|
|
328
|
+
statusChange?: { from: CommissionRuleStatusEnum; to: CommissionRuleStatusEnum } | null;
|
|
304
329
|
}
|
|
305
330
|
|
|
306
331
|
/** `GET /backoffice/commissions/rules/{ruleId}/history` — del más nuevo al más viejo. */
|
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
import { Expose } from 'class-transformer';
|
|
2
|
-
import { IsBoolean, IsEnum, IsInt,
|
|
3
|
-
import {
|
|
4
|
-
RETAIL_CARD_LAST4_PATTERN,
|
|
5
|
-
RETAIL_CLABE_PATTERN,
|
|
6
|
-
RETAIL_SALE_ID_TEXT_PATTERN,
|
|
7
|
-
RETAIL_SPEI_TRACKING_KEY_PATTERN,
|
|
8
|
-
} from '../../retailIntegration/constants/retailIntegrationLimits';
|
|
2
|
+
import { IsBoolean, IsEnum, IsInt, IsString, ValidateIf } from 'class-validator';
|
|
9
3
|
import { SalePaymentMethodEnum } from '../enums/SalePaymentMethodEnum';
|
|
10
|
-
import { OnlyForPaymentMethodConstraint } from '../validators/OnlyForPaymentMethodConstraint';
|
|
11
4
|
|
|
12
|
-
const { CASH, CARD, WIRE } = SalePaymentMethodEnum;
|
|
13
5
|
const hasValue = (field: keyof SalePayment) => (o: SalePayment) => o[field] != null;
|
|
14
6
|
|
|
15
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* Un pago del cobro tal como llega en un request: solo la forma. Tope, uso único, suma, monto
|
|
9
|
+
* positivo y formato del comprobante los valida el dominio con su code.
|
|
10
|
+
*/
|
|
16
11
|
export class SalePayment {
|
|
17
12
|
@Expose()
|
|
18
13
|
@IsEnum(SalePaymentMethodEnum)
|
|
@@ -20,36 +15,30 @@ export class SalePayment {
|
|
|
20
15
|
|
|
21
16
|
@Expose()
|
|
22
17
|
@IsInt()
|
|
23
|
-
@Min(1)
|
|
24
18
|
amountCents!: number;
|
|
25
19
|
|
|
26
20
|
@Expose()
|
|
27
21
|
@ValidateIf(hasValue('cashConfirmedInRegister'))
|
|
28
22
|
@IsBoolean()
|
|
29
|
-
@Validate(OnlyForPaymentMethodConstraint, [CASH])
|
|
30
23
|
cashConfirmedInRegister?: boolean | null;
|
|
31
24
|
|
|
32
25
|
@Expose()
|
|
33
26
|
@ValidateIf(hasValue('cardLast4'))
|
|
34
|
-
@
|
|
35
|
-
@Validate(OnlyForPaymentMethodConstraint, [CARD])
|
|
27
|
+
@IsString()
|
|
36
28
|
cardLast4?: string | null;
|
|
37
29
|
|
|
38
30
|
@Expose()
|
|
39
31
|
@ValidateIf(hasValue('authCode'))
|
|
40
|
-
@
|
|
41
|
-
@Validate(OnlyForPaymentMethodConstraint, [CARD])
|
|
32
|
+
@IsString()
|
|
42
33
|
authCode?: string | null;
|
|
43
34
|
|
|
44
35
|
@Expose()
|
|
45
36
|
@ValidateIf(hasValue('speiTrackingKey'))
|
|
46
|
-
@
|
|
47
|
-
@Validate(OnlyForPaymentMethodConstraint, [WIRE])
|
|
37
|
+
@IsString()
|
|
48
38
|
speiTrackingKey?: string | null;
|
|
49
39
|
|
|
50
40
|
@Expose()
|
|
51
41
|
@ValidateIf(hasValue('senderClabe'))
|
|
52
|
-
@
|
|
53
|
-
@Validate(OnlyForPaymentMethodConstraint, [WIRE])
|
|
42
|
+
@IsString()
|
|
54
43
|
senderClabe?: string | null;
|
|
55
44
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { IsBoolean, IsInt, IsString, Min, Matches, Validate } from 'class-validator';
|
|
2
|
+
import {
|
|
3
|
+
RETAIL_CARD_LAST4_PATTERN,
|
|
4
|
+
RETAIL_CLABE_PATTERN,
|
|
5
|
+
RETAIL_SALE_ID_TEXT_PATTERN,
|
|
6
|
+
RETAIL_SPEI_TRACKING_KEY_PATTERN,
|
|
7
|
+
} from '../../retailIntegration/constants/retailIntegrationLimits';
|
|
8
|
+
import { SalePaymentMethodEnum } from '../enums/SalePaymentMethodEnum';
|
|
9
|
+
import { OnlyForPaymentMethodConstraint } from '../validators/OnlyForPaymentMethodConstraint';
|
|
10
|
+
import { SalePayment } from './SalePayment';
|
|
11
|
+
|
|
12
|
+
const { CASH, CARD, WIRE } = SalePaymentMethodEnum;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Pago ya registrado (cobro de la sesión): monto positivo y comprobante con formato, solo en su medio.
|
|
16
|
+
* Repite las reglas de forma porque class-validator descarta las del padre en la propiedad que se redeclara.
|
|
17
|
+
*/
|
|
18
|
+
export class StoredSalePayment extends SalePayment {
|
|
19
|
+
@IsInt()
|
|
20
|
+
@Min(1)
|
|
21
|
+
declare amountCents: number;
|
|
22
|
+
|
|
23
|
+
@IsBoolean()
|
|
24
|
+
@Validate(OnlyForPaymentMethodConstraint, [CASH])
|
|
25
|
+
declare cashConfirmedInRegister?: boolean | null;
|
|
26
|
+
|
|
27
|
+
@IsString()
|
|
28
|
+
@Matches(RETAIL_CARD_LAST4_PATTERN)
|
|
29
|
+
@Validate(OnlyForPaymentMethodConstraint, [CARD])
|
|
30
|
+
declare cardLast4?: string | null;
|
|
31
|
+
|
|
32
|
+
@IsString()
|
|
33
|
+
@Matches(RETAIL_SALE_ID_TEXT_PATTERN)
|
|
34
|
+
@Validate(OnlyForPaymentMethodConstraint, [CARD])
|
|
35
|
+
declare authCode?: string | null;
|
|
36
|
+
|
|
37
|
+
@IsString()
|
|
38
|
+
@Matches(RETAIL_SPEI_TRACKING_KEY_PATTERN)
|
|
39
|
+
@Validate(OnlyForPaymentMethodConstraint, [WIRE])
|
|
40
|
+
declare speiTrackingKey?: string | null;
|
|
41
|
+
|
|
42
|
+
@IsString()
|
|
43
|
+
@Matches(RETAIL_CLABE_PATTERN)
|
|
44
|
+
@Validate(OnlyForPaymentMethodConstraint, [WIRE])
|
|
45
|
+
declare senderClabe?: string | null;
|
|
46
|
+
}
|
|
@@ -14,7 +14,7 @@ import { SalePaymentMethodEnum } from '../../enums/SalePaymentMethodEnum';
|
|
|
14
14
|
import { SalePaymentDetail } from '../SalePaymentDetail';
|
|
15
15
|
import { AccessorySaleLine } from '../AccessorySaleLine';
|
|
16
16
|
import { SalePayment } from '../SalePayment';
|
|
17
|
-
import {
|
|
17
|
+
import { IsSalePaymentInputList } from '../../validators/IsSalePaymentInputList';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* POST /wizard/accessory-sales — cierra la venta de mostrador, sin cliente.
|
|
@@ -47,9 +47,9 @@ export class CreateAccessorySaleRequest {
|
|
|
47
47
|
@Type(() => SalePaymentDetail)
|
|
48
48
|
paymentDetail?: SalePaymentDetail;
|
|
49
49
|
|
|
50
|
-
/** Pagos del cobro
|
|
50
|
+
/** Pagos del cobro; si viene, manda sobre `paymentMethod` y `paymentDetail`. */
|
|
51
51
|
@Expose()
|
|
52
52
|
@IsOptional()
|
|
53
|
-
@
|
|
53
|
+
@IsSalePaymentInputList()
|
|
54
54
|
payments?: SalePayment[];
|
|
55
55
|
}
|
|
@@ -3,7 +3,7 @@ import { IsEnum, IsInt, IsOptional, Min, ValidateIf, ValidateNested } from 'clas
|
|
|
3
3
|
import { SalePaymentMethodEnum } from '../../enums/SalePaymentMethodEnum';
|
|
4
4
|
import { SalePaymentDetail } from '../SalePaymentDetail';
|
|
5
5
|
import { SalePayment } from '../SalePayment';
|
|
6
|
-
import {
|
|
6
|
+
import { IsSalePaymentInputList } from '../../validators/IsSalePaymentInputList';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* POST /wizard/sessions/:id/down-payment — cobro del ENGANCHE de la venta a crédito (paso 07,
|
|
@@ -33,9 +33,9 @@ export class DownPaymentRequest {
|
|
|
33
33
|
@ValidateNested()
|
|
34
34
|
detail?: SalePaymentDetail;
|
|
35
35
|
|
|
36
|
-
/** Pagos del cobro
|
|
36
|
+
/** Pagos del cobro; si viene, manda sobre `method` y `detail`. */
|
|
37
37
|
@Expose()
|
|
38
38
|
@IsOptional()
|
|
39
|
-
@
|
|
39
|
+
@IsSalePaymentInputList()
|
|
40
40
|
payments?: SalePayment[];
|
|
41
41
|
}
|
|
@@ -3,7 +3,7 @@ import { IsEnum, IsInt, IsOptional, ValidateIf, ValidateNested, Min } from 'clas
|
|
|
3
3
|
import { SalePaymentMethodEnum } from '../../enums/SalePaymentMethodEnum';
|
|
4
4
|
import { SalePaymentDetail } from '../SalePaymentDetail';
|
|
5
5
|
import { SalePayment } from '../SalePayment';
|
|
6
|
-
import {
|
|
6
|
+
import { IsSalePaymentInputList } from '../../validators/IsSalePaymentInputList';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* POST /wizard/sessions/:id/payment — registra el cobro de contado (idempotente por sesión). Regla
|
|
@@ -29,9 +29,9 @@ export class RegisterPaymentRequest {
|
|
|
29
29
|
@ValidateNested()
|
|
30
30
|
detail?: SalePaymentDetail;
|
|
31
31
|
|
|
32
|
-
/** Pagos del cobro
|
|
32
|
+
/** Pagos del cobro; si viene, manda sobre `method` y `detail`. */
|
|
33
33
|
@Expose()
|
|
34
34
|
@IsOptional()
|
|
35
|
-
@
|
|
35
|
+
@IsSalePaymentInputList()
|
|
36
36
|
payments?: SalePayment[];
|
|
37
37
|
}
|
|
@@ -46,6 +46,8 @@ export * from './dtos/WizardWelcome';
|
|
|
46
46
|
export * from './dtos/WizardCreditPromotionBonus';
|
|
47
47
|
export * from './dtos/SalePaymentDetail';
|
|
48
48
|
export * from './dtos/SalePayment';
|
|
49
|
+
export * from './dtos/StoredSalePayment';
|
|
50
|
+
export * from './validators/IsSalePaymentInputList';
|
|
49
51
|
export * from './validators/IsSalePaymentList';
|
|
50
52
|
export * from './validators/OnlyForPaymentMethodConstraint';
|
|
51
53
|
export * from './validators/PaymentsHaveSingleUseMethodsConstraint';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Type } from 'class-transformer';
|
|
2
|
+
import { IsArray, ValidateNested } from 'class-validator';
|
|
3
|
+
import { SalePayment } from '../dtos/SalePayment';
|
|
4
|
+
|
|
5
|
+
/** Forma de `payments` en un request: arreglo de pagos bien tipados. Las reglas de negocio las valida el dominio. */
|
|
6
|
+
export function IsSalePaymentInputList(): PropertyDecorator {
|
|
7
|
+
const decorators: PropertyDecorator[] = [IsArray(), ValidateNested({ each: true }), Type(() => SalePayment)];
|
|
8
|
+
return (target, propertyKey) => decorators.forEach((decorate) => decorate(target, propertyKey));
|
|
9
|
+
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { Type } from 'class-transformer';
|
|
2
2
|
import { ArrayMaxSize, ArrayMinSize, IsArray, Validate, ValidateNested } from 'class-validator';
|
|
3
3
|
import { MAX_SALE_PAYMENTS } from '../constants/retailWizardValidation';
|
|
4
|
-
import {
|
|
4
|
+
import { StoredSalePayment } from '../dtos/StoredSalePayment';
|
|
5
5
|
import { PaymentsHaveSingleUseMethodsConstraint } from './PaymentsHaveSingleUseMethodsConstraint';
|
|
6
6
|
import { PaymentsMatchAmountCentsConstraint } from './PaymentsMatchAmountCentsConstraint';
|
|
7
7
|
|
|
8
|
-
/** Reglas de `payments
|
|
8
|
+
/** Reglas de `payments` ya registrados (cobro de la sesión): 1 a 3 pagos válidos, efectivo y SPEI una vez, y la suma igual a `amountCents`. */
|
|
9
9
|
export function IsSalePaymentList(): PropertyDecorator {
|
|
10
10
|
const decorators: PropertyDecorator[] = [
|
|
11
11
|
IsArray(),
|
|
12
12
|
ArrayMinSize(1),
|
|
13
13
|
ArrayMaxSize(MAX_SALE_PAYMENTS),
|
|
14
14
|
ValidateNested({ each: true }),
|
|
15
|
-
Type(() =>
|
|
15
|
+
Type(() => StoredSalePayment),
|
|
16
16
|
Validate(PaymentsHaveSingleUseMethodsConstraint),
|
|
17
17
|
Validate(PaymentsMatchAmountCentsConstraint),
|
|
18
18
|
];
|