@fiado/type-kit 3.491.0 → 3.493.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 (70) hide show
  1. package/_test_/unit/loanCredit/installmentPaidEvent.test.ts +17 -0
  2. package/_test_/unit/retailCommission/commissionPayout.test.ts +104 -0
  3. package/_test_/unit/retailCommission/commissionRent.test.ts +33 -0
  4. package/_test_/unit/retailCommission/commissionRules.test.ts +249 -0
  5. package/_test_/unit/retailCommission/commissionSimulation.test.ts +43 -0
  6. package/_test_/unit/retailCommission/myCommissions.test.ts +29 -0
  7. package/_test_/unit/retailWizard/creditPromotionBonusContract.test.ts +10 -0
  8. package/_test_/unit/retailWizard/ventaSagaMessages.test.ts +108 -11
  9. package/bin/loanCredit/dtos/InstallmentPaidEvent.d.ts +18 -0
  10. package/bin/loanCredit/dtos/InstallmentPaidEvent.js +5 -0
  11. package/bin/loanCredit/index.d.ts +1 -0
  12. package/bin/loanCredit/index.js +1 -0
  13. package/bin/retailCommission/dtos/CommissionAccrual.d.ts +36 -0
  14. package/bin/retailCommission/dtos/CommissionApi.d.ts +241 -2
  15. package/bin/retailCommission/dtos/CommissionCalcTrace.d.ts +10 -0
  16. package/bin/retailCommission/dtos/CommissionCouponAccrual.d.ts +31 -0
  17. package/bin/retailCommission/dtos/CommissionCouponAccrual.js +2 -0
  18. package/bin/retailCommission/dtos/CommissionPayout.d.ts +84 -0
  19. package/bin/retailCommission/dtos/CommissionRule.d.ts +119 -0
  20. package/bin/retailCommission/dtos/CommissionRule.js +2 -0
  21. package/bin/retailCommission/enums/CommissionAggregateByEnum.d.ts +14 -0
  22. package/bin/retailCommission/enums/CommissionAggregateByEnum.js +18 -0
  23. package/bin/retailCommission/enums/CommissionBonusModeEnum.d.ts +10 -0
  24. package/bin/retailCommission/enums/CommissionBonusModeEnum.js +14 -0
  25. package/bin/retailCommission/enums/CommissionCalcStepEnum.d.ts +3 -1
  26. package/bin/retailCommission/enums/CommissionCalcStepEnum.js +2 -0
  27. package/bin/retailCommission/enums/CommissionMetricEnum.d.ts +14 -0
  28. package/bin/retailCommission/enums/CommissionMetricEnum.js +18 -0
  29. package/bin/retailCommission/enums/CommissionOperatorEnum.d.ts +15 -0
  30. package/bin/retailCommission/enums/CommissionOperatorEnum.js +19 -0
  31. package/bin/retailCommission/enums/CommissionRuleStatusEnum.d.ts +16 -0
  32. package/bin/retailCommission/enums/CommissionRuleStatusEnum.js +20 -0
  33. package/bin/retailCommission/enums/CommissionSeriesByEnum.d.ts +14 -0
  34. package/bin/retailCommission/enums/CommissionSeriesByEnum.js +18 -0
  35. package/bin/retailCommission/enums/CommissionSimulationSkipEnum.d.ts +14 -0
  36. package/bin/retailCommission/enums/CommissionSimulationSkipEnum.js +18 -0
  37. package/bin/retailCommission/enums/CommissionWindowEnum.d.ts +12 -0
  38. package/bin/retailCommission/enums/CommissionWindowEnum.js +16 -0
  39. package/bin/retailCommission/index.d.ts +10 -0
  40. package/bin/retailCommission/index.js +10 -0
  41. package/bin/retailWizard/dtos/WizardCreditPromotionBonus.d.ts +3 -0
  42. package/bin/retailWizard/enums/RetailCommissionInboundMessageTypeEnum.d.ts +5 -0
  43. package/bin/retailWizard/enums/RetailCommissionInboundMessageTypeEnum.js +9 -0
  44. package/bin/retailWizard/events/RetailCommissionInboundMessage.d.ts +27 -1
  45. package/bin/retailWizard/events/RetailCommissionInboundMessage.js +70 -1
  46. package/bin/retailWizard/index.d.ts +1 -0
  47. package/bin/retailWizard/index.js +1 -0
  48. package/package.json +1 -1
  49. package/src/loanCredit/dtos/InstallmentPaidEvent.ts +20 -0
  50. package/src/loanCredit/index.ts +1 -0
  51. package/src/retailCommission/dtos/CommissionAccrual.ts +38 -0
  52. package/src/retailCommission/dtos/CommissionApi.ts +276 -2
  53. package/src/retailCommission/dtos/CommissionCalcTrace.ts +7 -0
  54. package/src/retailCommission/dtos/CommissionCouponAccrual.ts +33 -0
  55. package/src/retailCommission/dtos/CommissionPayout.ts +91 -0
  56. package/src/retailCommission/dtos/CommissionRule.ts +132 -0
  57. package/src/retailCommission/enums/CommissionAggregateByEnum.ts +14 -0
  58. package/src/retailCommission/enums/CommissionBonusModeEnum.ts +10 -0
  59. package/src/retailCommission/enums/CommissionCalcStepEnum.ts +2 -0
  60. package/src/retailCommission/enums/CommissionMetricEnum.ts +14 -0
  61. package/src/retailCommission/enums/CommissionOperatorEnum.ts +15 -0
  62. package/src/retailCommission/enums/CommissionRuleStatusEnum.ts +16 -0
  63. package/src/retailCommission/enums/CommissionSeriesByEnum.ts +14 -0
  64. package/src/retailCommission/enums/CommissionSimulationSkipEnum.ts +14 -0
  65. package/src/retailCommission/enums/CommissionWindowEnum.ts +12 -0
  66. package/src/retailCommission/index.ts +10 -0
  67. package/src/retailWizard/dtos/WizardCreditPromotionBonus.ts +3 -0
  68. package/src/retailWizard/enums/RetailCommissionInboundMessageTypeEnum.ts +5 -0
  69. package/src/retailWizard/events/RetailCommissionInboundMessage.ts +75 -2
  70. package/src/retailWizard/index.ts +1 -0
@@ -6,8 +6,30 @@ import type {
6
6
  CommissionPlanSnapshot,
7
7
  CommissionQuota,
8
8
  } from './CommissionPlan';
9
- import type { CommissionAccrual, CommissionSaleInput } from './CommissionAccrual';
10
- import type { CommissionAdjustment, CommissionPayout, CommissionPayoutSeller } from './CommissionPayout';
9
+ import type { CommissionAccrual, CommissionAppliedBonus, CommissionSaleInput, CommissionSaleLine } from './CommissionAccrual';
10
+ import type {
11
+ CommissionAdjustment,
12
+ CommissionAppliedMultiplier,
13
+ CommissionAppliedThreshold,
14
+ CommissionPayout,
15
+ CommissionPayoutSeller,
16
+ CommissionSellerBreakdown,
17
+ } from './CommissionPayout';
18
+ import type {
19
+ CommissionPolicies,
20
+ CommissionRule,
21
+ CommissionRuleCondition,
22
+ CommissionRuleLevers,
23
+ CommissionRuleScope,
24
+ CommissionRuleSetSnapshot,
25
+ } from './CommissionRule';
26
+ import type { CommissionWindowEnum } from '../enums/CommissionWindowEnum';
27
+ import type { CommissionAggregateByEnum } from '../enums/CommissionAggregateByEnum';
28
+ import type { CommissionSeriesByEnum } from '../enums/CommissionSeriesByEnum';
29
+ import type { CommissionAccrualStatusEnum } from '../enums/CommissionAccrualStatusEnum';
30
+ import type { CommissionSimulationSkipEnum } from '../enums/CommissionSimulationSkipEnum';
31
+ import type { ProductCategoryEnum } from '../../retailCatalog/enums/ProductCategoryEnum';
32
+ import type { ProductTierEnum } from '../../retailCatalog/enums/ProductTierEnum';
11
33
 
12
34
  /**
13
35
  * Los contratos HTTP del motor de comisiones — uno por endpoint, sin reutilizar.
@@ -203,3 +225,255 @@ export interface ClosePayoutResponse {
203
225
 
204
226
  /** Lo que el simulador reconstruye desde el data lake para volver a correr el motor. */
205
227
  export type CommissionSimulationSale = CommissionSaleInput;
228
+
229
+ // ─────────────────────────────────────────────────────────────────────────────
230
+ // Reglas y políticas
231
+ // ─────────────────────────────────────────────────────────────────────────────
232
+
233
+ /** `GET /backoffice/commissions/plan` — el plan vigente con reglas. `null` mientras no se publica nada. */
234
+ export interface GetRuleSetResponse {
235
+ active: CommissionRuleSetSnapshot | null;
236
+ }
237
+
238
+ /** `GET /backoffice/commissions/rules` — la última versión de cada regla. */
239
+ export interface ListRulesResponse {
240
+ rules: CommissionRule[];
241
+ }
242
+
243
+ /** Lo que el editor manda al crear o guardar una regla. */
244
+ export interface CommissionRuleInput {
245
+ name: string;
246
+ description: string | null;
247
+ levers: CommissionRuleLevers;
248
+ scope: CommissionRuleScope;
249
+ condition: CommissionRuleCondition | null;
250
+ effectiveFrom: string;
251
+ effectiveTo: string | null;
252
+ priority: number;
253
+ replacesOthers: boolean;
254
+ }
255
+
256
+ /** `POST /backoffice/commissions/rules` — la regla nace en borrador. */
257
+ export type CreateRuleRequest = CommissionRuleInput;
258
+
259
+ /** `PUT /backoffice/commissions/rules/{ruleId}` — `expectedVersion` es la versión que el editor cargó. */
260
+ export interface UpdateRuleRequest extends CommissionRuleInput {
261
+ expectedVersion: number;
262
+ }
263
+
264
+ export interface RuleResponse {
265
+ rule: CommissionRule;
266
+ }
267
+
268
+ /** `POST /backoffice/commissions/rules/{ruleId}/publish | pause | resume | expire` */
269
+ export interface RuleActionRequest {
270
+ expectedVersion: number;
271
+ }
272
+
273
+ /** Las acciones que cambian el plan vigente devuelven la regla y el snapshot nuevo. */
274
+ export interface RuleActionResponse {
275
+ rule: CommissionRule;
276
+ snapshotId: string;
277
+ }
278
+
279
+ /** Un evento del historial de una regla. */
280
+ export interface CommissionRuleEvent {
281
+ at: string;
282
+ action: string;
283
+ performedBy: string;
284
+ version: number | null;
285
+ }
286
+
287
+ /** `GET /backoffice/commissions/rules/{ruleId}/history` — del más nuevo al más viejo. */
288
+ export interface RuleHistoryResponse {
289
+ events: CommissionRuleEvent[];
290
+ }
291
+
292
+ /** `GET /backoffice/commissions/policies` */
293
+ export interface GetPoliciesResponse {
294
+ policies: CommissionPolicies;
295
+ }
296
+
297
+ /** `PUT /backoffice/commissions/policies` — las dos políticas se guardan juntas. */
298
+ export interface UpdatePoliciesRequest {
299
+ clawback: { cancelacionDias: number; devolucionDias: number; npiM30Dias: number };
300
+ commissions: { multiplicadorMaxBps: number; ventanaDefault: CommissionWindowEnum };
301
+ }
302
+
303
+ export interface UpdatePoliciesResponse {
304
+ policies: CommissionPolicies;
305
+ snapshotId: string;
306
+ }
307
+
308
+ // ─────────────────────────────────────────────────────────────────────────────
309
+ // Corte vivo, agregados y series
310
+ // ─────────────────────────────────────────────────────────────────────────────
311
+
312
+ /** `GET /backoffice/commissions/live?periodId=` — el corte calculado al momento, sin escribir nada. */
313
+ export interface GetLivePayoutResponse {
314
+ periodId: string;
315
+ periodStart: string;
316
+ periodEnd: string;
317
+ status: CommissionPayoutStatusEnum;
318
+ sellers: CommissionSellerBreakdown[];
319
+ }
320
+
321
+ /** Una venta del vendedor en el corte, con sus bonos recalculados en orden. Sin datos del cliente. */
322
+ export interface CommissionLiveSale {
323
+ saleId: string;
324
+ soldAt: string;
325
+ storeId: string;
326
+ status: CommissionAccrualStatusEnum;
327
+ /** El snapshot con el que se devengó: es el que se usa para recalcularla. */
328
+ planSnapshotId: string;
329
+ lines: CommissionSaleLine[];
330
+ appliedBonuses: CommissionAppliedBonus[];
331
+ subtotalBonusCents: number;
332
+ }
333
+
334
+ /** `GET /backoffice/commissions/live/sellers/{sellerId}?periodId=` */
335
+ export interface GetLiveSellerResponse {
336
+ periodId: string;
337
+ seller: CommissionSellerBreakdown;
338
+ sales: CommissionLiveSale[];
339
+ }
340
+
341
+ /** Un renglón del agregado. `name` es el de la regla; tienda, SKU y vendedor los resuelve el front. */
342
+ export interface CommissionAggregateRow {
343
+ key: string;
344
+ name: string | null;
345
+ sellersCount: number;
346
+ salesCount: number;
347
+ unitsCount: number;
348
+ placementCents: number;
349
+ paidCents: number;
350
+ }
351
+
352
+ /** `GET /backoffice/commissions/payouts/aggregates?by=&from=&to=` — sobre los cortes cerrados del rango. */
353
+ export interface GetPayoutAggregatesResponse {
354
+ by: CommissionAggregateByEnum;
355
+ from: string;
356
+ to: string;
357
+ /** Los cortes cerrados que entraron. */
358
+ periodIds: string[];
359
+ rows: CommissionAggregateRow[];
360
+ totalPaidCents: number;
361
+ }
362
+
363
+ /** Un punto de la serie: un corte cerrado. */
364
+ export interface CommissionSeriesPoint {
365
+ periodId: string;
366
+ salesCount: number;
367
+ unitsCount: number;
368
+ placementCents: number;
369
+ paidCents: number;
370
+ }
371
+
372
+ /** `GET /backoffice/commissions/payouts/series?by=&id=&weeks=` — del corte más viejo al más nuevo. */
373
+ export interface GetPayoutSeriesResponse {
374
+ by: CommissionSeriesByEnum;
375
+ id: string;
376
+ points: CommissionSeriesPoint[];
377
+ }
378
+
379
+ // ─────────────────────────────────────────────────────────────────────────────
380
+ // Simulador de reglas
381
+ // ─────────────────────────────────────────────────────────────────────────────
382
+
383
+ /** El vendedor modelo: cómo va su semana. */
384
+ export interface CommissionSimulationProfile {
385
+ unitsInWeek: number;
386
+ placementCents: number;
387
+ distinctSkus: number;
388
+ }
389
+
390
+ /** El producto que vende en la simulación. */
391
+ export interface CommissionSimulationProduct {
392
+ sku: string;
393
+ category: ProductCategoryEnum | null;
394
+ tier: ProductTierEnum | null;
395
+ netCents: number;
396
+ }
397
+
398
+ /** `POST /backoffice/commissions/rules/simulate` */
399
+ export interface SimulateRulesRequest {
400
+ /** Reglas por id, en su última versión, como si estuvieran publicadas. Vacío = el plan vigente. */
401
+ ruleIds: string[];
402
+ profile: CommissionSimulationProfile;
403
+ product: CommissionSimulationProduct;
404
+ /** Con tienda se evalúa el alcance por tienda; sin ella, se ignora. */
405
+ storeId: string | null;
406
+ /** `YYYY-MM-DD`. `null` = hoy. */
407
+ date: string | null;
408
+ }
409
+
410
+ /** Lo que una regla de bono por venta pagaría en una posición, o por qué no. */
411
+ export interface CommissionSimulatedRule {
412
+ ruleId: string;
413
+ name: string;
414
+ amountCents: number;
415
+ skipped: CommissionSimulationSkipEnum | null;
416
+ }
417
+
418
+ export interface SimulateRulesResponse {
419
+ date: string;
420
+ /** La venta siguiente, en la posición `unitsInWeek + 1`. */
421
+ nextSale: { position: number; subtotalBonusCents: number; rules: CommissionSimulatedRule[] };
422
+ /** Las piezas de la semana, en las posiciones 1 a `unitsInWeek`. */
423
+ progression: Array<{ position: number; subtotalBonusCents: number; cumulativeBonusCents: number }>;
424
+ /** El corte de esa semana. */
425
+ week: {
426
+ subtotalBonusCents: number;
427
+ multiplierBps: number;
428
+ multiplierBeforeCapBps: number;
429
+ multipliers: CommissionAppliedMultiplier[];
430
+ thresholdBonusCents: number;
431
+ thresholds: CommissionAppliedThreshold[];
432
+ releasedCents: number;
433
+ };
434
+ }
435
+
436
+ // ─────────────────────────────────────────────────────────────────────────────
437
+ // Mis comisiones (Portal Vendedor)
438
+ // ─────────────────────────────────────────────────────────────────────────────
439
+
440
+ /** Una regla como la ve el vendedor: sin estado interno ni datos de auditoría. */
441
+ export interface CommissionRuleView {
442
+ ruleId: string;
443
+ name: string;
444
+ description: string | null;
445
+ levers: CommissionRuleLevers;
446
+ scope: CommissionRuleScope;
447
+ condition: CommissionRuleCondition | null;
448
+ effectiveFrom: string;
449
+ effectiveTo: string | null;
450
+ }
451
+
452
+ /** Lo pagado en varios cortes. */
453
+ export interface MyCommissionsTotals {
454
+ periodsCount: number;
455
+ salesCount: number;
456
+ unitsCount: number;
457
+ netCents: number;
458
+ }
459
+
460
+ /**
461
+ * `GET /commissions/me?weeks=` — las comisiones del vendedor que llama. El vendedor sale del token;
462
+ * no se puede pedir el de otro.
463
+ */
464
+ export interface GetMyCommissionsResponse {
465
+ seller: { sellerId: string; name: string | null; storeId: string | null };
466
+ period: { periodId: string; periodStart: string; periodEnd: string };
467
+ /** El corte en curso; `null` si todavía no tiene ventas, renta ni ajustes. */
468
+ week: CommissionSellerBreakdown | null;
469
+ /** Cortes cuya semana empieza en el mes de hoy: cerrados, el anterior aún sin cerrar y el en curso. */
470
+ month: MyCommissionsTotals;
471
+ /** Cortes cuya semana empieza en el año de hoy: cerrados, el anterior aún sin cerrar y el en curso. */
472
+ year: MyCommissionsTotals;
473
+ /** Los cortes cerrados de las últimas `weeks` semanas, del más viejo al más nuevo. `paidCents` es el neto. */
474
+ history: CommissionSeriesPoint[];
475
+ /** Las reglas vigentes hoy que pueden pagarle: las de corte, las sin tienda y las de su tienda o de donde vendió. */
476
+ rules: CommissionRuleView[];
477
+ /** Tope del multiplicador de la política; `null` sin política. */
478
+ multiplierCapBps: number | null;
479
+ }
@@ -59,6 +59,13 @@ export type CommissionCalcTraceEntry =
59
59
  label: string;
60
60
  outputCents: number;
61
61
  detail: { sku: string; brand: string | null };
62
+ }
63
+ | {
64
+ /** Una regla con bono por venta sumó por una pieza. */
65
+ step: CommissionCalcStepEnum.BONUS_PER_SALE;
66
+ label: string;
67
+ outputCents: number;
68
+ detail: { ruleId: string; lineId: string; position: number };
62
69
  };
63
70
 
64
71
  export type CommissionCalcTrace = CommissionCalcTraceEntry[];
@@ -0,0 +1,33 @@
1
+ import type { CommissionAccrualStatusEnum } from '../enums/CommissionAccrualStatusEnum';
2
+ import type { CommissionBonusModeEnum } from '../enums/CommissionBonusModeEnum';
3
+
4
+ /** Lo que paga una regla de renta de cartera por una cuota cobrada. */
5
+ export interface CommissionCouponAppliedBonus {
6
+ ruleId: string;
7
+ name: string;
8
+ mode: CommissionBonusModeEnum;
9
+ amountCents: number;
10
+ }
11
+
12
+ /**
13
+ * La renta de cartera de una cuota pagada, en el corte de su pago.
14
+ * Clave `SELLER#<sellerId>` · `COUPON#<periodId>#<creditId>#<cuota>`: determinista, idempotente.
15
+ */
16
+ export interface CommissionCouponAccrual {
17
+ sellerId: string;
18
+ retailerId: string;
19
+ periodId: string;
20
+ creditId: string;
21
+ /** La venta que originó el crédito. */
22
+ saleId: string;
23
+ installmentNumber: number;
24
+ /** Lo pagado de la cuota (capital + interés + IVA). */
25
+ couponAmountCents: number;
26
+ paidAt: string;
27
+ /** El snapshot con que se evaluó: de ahí salen las condiciones al cerrar el corte. */
28
+ planSnapshotId: string;
29
+ bonuses: CommissionCouponAppliedBonus[];
30
+ subtotalCents: number;
31
+ status: CommissionAccrualStatusEnum;
32
+ createdAt: string;
33
+ }
@@ -50,6 +50,8 @@ export interface CommissionPayoutSeller {
50
50
  /** Al cerrar: si alcanzó su cuota. */
51
51
  quotaMet: boolean | null;
52
52
  quotaFactorBps: number | null;
53
+ /** El corte del vendedor calculado con reglas. Lo escribe el cierre. */
54
+ breakdown?: CommissionSellerBreakdown;
53
55
  }
54
56
 
55
57
  /**
@@ -74,3 +76,92 @@ export interface CommissionAdjustment {
74
76
  author: string;
75
77
  createdAt: string;
76
78
  }
79
+
80
+ /** Lo que una regla de bono por venta aportó al corte del vendedor. */
81
+ export interface CommissionRuleContribution {
82
+ ruleId: string;
83
+ name: string;
84
+ /** Piezas que pagaron esta regla. */
85
+ unitsCount: number;
86
+ bonusCents: number;
87
+ /** Su parte del multiplicador, en proporción a su bono. */
88
+ multiplierShareCents: number;
89
+ }
90
+
91
+ /** Un multiplicador que disparó en el corte. */
92
+ export interface CommissionAppliedMultiplier {
93
+ ruleId: string;
94
+ name: string;
95
+ factorBps: number;
96
+ }
97
+
98
+ /** Un bono por umbral que disparó en el corte. */
99
+ export interface CommissionAppliedThreshold {
100
+ ruleId: string;
101
+ name: string;
102
+ amountCents: number;
103
+ }
104
+
105
+ /** Lo vendido y lo pagado del vendedor en una tienda. Lo pagado no incluye umbrales. */
106
+ export interface CommissionStoreContribution {
107
+ storeId: string;
108
+ salesCount: number;
109
+ unitsCount: number;
110
+ placementCents: number;
111
+ paidCents: number;
112
+ }
113
+
114
+ /** Lo vendido y lo pagado del vendedor por un SKU. Lo pagado no incluye umbrales. */
115
+ export interface CommissionSkuContribution {
116
+ sku: string;
117
+ unitsCount: number;
118
+ placementCents: number;
119
+ paidCents: number;
120
+ }
121
+
122
+ /** La renta de cartera que pagó una regla en el corte. */
123
+ export interface CommissionAppliedRent {
124
+ ruleId: string;
125
+ name: string;
126
+ /** Cuotas cobradas que pagaron esta regla. */
127
+ couponsCount: number;
128
+ amountCents: number;
129
+ }
130
+
131
+ /**
132
+ * El corte de un vendedor calculado con las reglas.
133
+ *
134
+ * liberado = round(subtotal × multiplicador) + umbral + renta · neto = liberado + ajustes.
135
+ */
136
+ export interface CommissionSellerBreakdown {
137
+ sellerId: string;
138
+ /** Ventas del periodo sin las revertidas. */
139
+ salesCount: number;
140
+ /** Piezas de esas ventas: lo que cuentan las reglas. */
141
+ unitsCount: number;
142
+ /** Suma del precio neto de las piezas. */
143
+ placementCents: number;
144
+ subtotalBonusCents: number;
145
+ /** Multiplicador aplicado, ya con el tope. 10000 = ×1. */
146
+ multiplierBps: number;
147
+ multiplierBeforeCapBps: number;
148
+ multipliers: CommissionAppliedMultiplier[];
149
+ thresholdBonusCents: number;
150
+ thresholds: CommissionAppliedThreshold[];
151
+ portfolioRentCents: number;
152
+ releasedCents: number;
153
+ /** Ajustes del vendedor en el periodo: manuales, ventas tardías y reversas. */
154
+ adjustmentsCents: number;
155
+ /** Reversas de ventas de cortes ya cerrados, en positivo. Ya están dentro de `adjustmentsCents`. */
156
+ clawbackCents: number;
157
+ netCents: number;
158
+ byRule: CommissionRuleContribution[];
159
+ byStore: CommissionStoreContribution[];
160
+ bySku: CommissionSkuContribution[];
161
+ /** La renta por regla; suma `portfolioRentCents`. Ausente en cortes de antes de la renta. */
162
+ rentByRule?: CommissionAppliedRent[];
163
+ /** NPI M30 del vendedor con que se evaluaron las condiciones, en bps. `null` sin créditos que contar. */
164
+ npiM30Bps?: number | null;
165
+ /** Créditos que contaron para el NPI. */
166
+ npiSample?: number;
167
+ }
@@ -0,0 +1,132 @@
1
+ import type { ProductCategoryEnum } from '../../retailCatalog/enums/ProductCategoryEnum';
2
+ import type { ProductTierEnum } from '../../retailCatalog/enums/ProductTierEnum';
3
+ import type { CommissionBonusModeEnum } from '../enums/CommissionBonusModeEnum';
4
+ import type { CommissionMetricEnum } from '../enums/CommissionMetricEnum';
5
+ import type { CommissionOperatorEnum } from '../enums/CommissionOperatorEnum';
6
+ import type { CommissionRuleStatusEnum } from '../enums/CommissionRuleStatusEnum';
7
+ import type { CommissionWindowEnum } from '../enums/CommissionWindowEnum';
8
+
9
+ /**
10
+ * Reglas de comisión de VentasLuga: cada regla es independiente y se apila con las demás.
11
+ *
12
+ * Montos en centavos (`*Cents`); porcentajes y factores en puntos base (`*Bps`, 10000 = 100% = ×1).
13
+ */
14
+
15
+ /** Bono por pieza vendida: monto fijo (`FIXED`, centavos) o porcentaje de su precio neto (`PERCENT`, bps). */
16
+ export interface CommissionBonusPerSale {
17
+ mode: CommissionBonusModeEnum;
18
+ value: number;
19
+ }
20
+
21
+ /** Monto fijo, una vez por corte, cuando se cumple la condición. */
22
+ export interface CommissionThresholdBonus {
23
+ amountCents: number;
24
+ }
25
+
26
+ /** Multiplica el subtotal de bonos por venta del corte. */
27
+ export interface CommissionMultiplier {
28
+ factorBps: number;
29
+ }
30
+
31
+ /** Renta de cartera: un bono por cada cupón que el cliente paga. */
32
+ export interface CommissionCouponBonus {
33
+ mode: CommissionBonusModeEnum;
34
+ value: number;
35
+ }
36
+
37
+ /** Las palancas de una regla. Una regla publicable trae al menos una. */
38
+ export interface CommissionRuleLevers {
39
+ bonoPorVenta: CommissionBonusPerSale | null;
40
+ bonoUmbral: CommissionThresholdBonus | null;
41
+ multiplicador: CommissionMultiplier | null;
42
+ bonoPorCuponPagado: CommissionCouponBonus | null;
43
+ }
44
+
45
+ /** A qué piezas aplica la regla. Una lista vacía es "todas". */
46
+ export interface CommissionRuleScope {
47
+ tipos: ProductCategoryEnum[];
48
+ gamas: ProductTierEnum[];
49
+ skus: string[];
50
+ tiendas: string[];
51
+ }
52
+
53
+ /**
54
+ * Condición para que la regla dispare.
55
+ *
56
+ * `value` es un número, `[min, max]` con `BETWEEN` o la lista con `IN`. `minSample` solo aplica a
57
+ * `NPI_M30_VENDEDOR`: sin esa muestra la condición no dispara.
58
+ */
59
+ export interface CommissionRuleCondition {
60
+ metric: CommissionMetricEnum;
61
+ operator: CommissionOperatorEnum;
62
+ value: number | number[];
63
+ minSample: number | null;
64
+ }
65
+
66
+ /** Una regla de comisión, en su última versión. */
67
+ export interface CommissionRule {
68
+ ruleId: string;
69
+ retailerId: string;
70
+ name: string;
71
+ description: string | null;
72
+ status: CommissionRuleStatusEnum;
73
+ levers: CommissionRuleLevers;
74
+ scope: CommissionRuleScope;
75
+ condition: CommissionRuleCondition | null;
76
+ /** `YYYY-MM-DD`, inclusive. */
77
+ effectiveFrom: string;
78
+ /** `YYYY-MM-DD`, inclusive. `null` = permanente. */
79
+ effectiveTo: string | null;
80
+ /** Desempata multiplicadores exclusivos: gana la mayor. */
81
+ priority: number;
82
+ /** Solo con multiplicador: si dispara, es el único multiplicador del corte. */
83
+ replacesOthers: boolean;
84
+ /** Sube en cada guardado. */
85
+ version: number;
86
+ /** La versión que está en el plan vigente. `null` si nunca se publicó. */
87
+ publishedVersion: number | null;
88
+ publishedBy: string | null;
89
+ publishedAt: string | null;
90
+ createdBy: string;
91
+ updatedBy: string;
92
+ createdAt: string;
93
+ updatedAt: string;
94
+ }
95
+
96
+ /** Ventanas del clawback, en días. */
97
+ export interface CommissionPolicyClawback {
98
+ cancelacionDias: number;
99
+ devolucionDias: number;
100
+ npiM30Dias: number;
101
+ editedBy: string;
102
+ editedAt: string;
103
+ }
104
+
105
+ /** Política de comisiones de la cadena. */
106
+ export interface CommissionPolicyCommissions {
107
+ /** Tope del multiplicador acumulado del corte. 25000 = ×2.5. */
108
+ multiplicadorMaxBps: number;
109
+ ventanaDefault: CommissionWindowEnum;
110
+ editedBy: string;
111
+ editedAt: string;
112
+ }
113
+
114
+ /** Políticas de la cadena. Cada una es `null` mientras la cadena no la guarda. */
115
+ export interface CommissionPolicies {
116
+ clawback: CommissionPolicyClawback | null;
117
+ commissions: CommissionPolicyCommissions | null;
118
+ }
119
+
120
+ /**
121
+ * El plan vigente: las reglas publicadas y las políticas, congeladas en un snapshot inmutable.
122
+ * Cada devengo apunta al snapshot con que se calculó.
123
+ */
124
+ export interface CommissionRuleSetSnapshot {
125
+ retailerId: string;
126
+ snapshotId: string;
127
+ rules: CommissionRule[];
128
+ policies: CommissionPolicies;
129
+ changeNote: string;
130
+ publishedBy: string;
131
+ publishedAt: string;
132
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Por qué se agrega lo pagado en los cortes cerrados.
3
+ *
4
+ * RULE - Por regla: bonos por venta con su parte del multiplicador, y umbrales.
5
+ * STORE - Por tienda donde se vendió.
6
+ * SKU - Por producto.
7
+ * SELLER - Por vendedor: su neto.
8
+ */
9
+ export enum CommissionAggregateByEnum {
10
+ RULE = 'RULE',
11
+ STORE = 'STORE',
12
+ SKU = 'SKU',
13
+ SELLER = 'SELLER',
14
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Cómo se calcula un bono.
3
+ *
4
+ * FIXED - Monto fijo en centavos por pieza.
5
+ * PERCENT - Puntos base sobre el precio neto de la pieza (10000 = 100%).
6
+ */
7
+ export enum CommissionBonusModeEnum {
8
+ FIXED = 'FIXED',
9
+ PERCENT = 'PERCENT',
10
+ }
@@ -10,6 +10,7 @@
10
10
  * QUOTA - Se resolvió la cuota (binaria o escalonada). Ocurre al CERRAR, no al devengar.
11
11
  * ADJUSTMENT - Un ajuste manual del corte.
12
12
  * NO_CATEGORY - El SKU no matcheó ninguna categoría del plan: devenga 0 y queda visible.
13
+ * BONUS_PER_SALE - Una regla con bono por venta sumó por una pieza de la venta.
13
14
  *
14
15
  * SureKeep Fase 3 — pista Retail. Motor de comisiones de VentasLuga.
15
16
  */
@@ -20,4 +21,5 @@ export enum CommissionCalcStepEnum {
20
21
  QUOTA = 'QUOTA',
21
22
  ADJUSTMENT = 'ADJUSTMENT',
22
23
  NO_CATEGORY = 'NO_CATEGORY',
24
+ BONUS_PER_SALE = 'BONUS_PER_SALE',
23
25
  }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Métricas de la condición de una regla.
3
+ *
4
+ * POSICION_VENTA_EN_PERIODO - Lugar de la pieza entre las del vendedor en el periodo que caen en el alcance de la regla.
5
+ * COLOCACION_PERIODO - Suma del precio neto de todo lo que el vendedor vendió en el periodo, en centavos.
6
+ * NPI_M30_VENDEDOR - Proporción de créditos del vendedor con primer impago a 30 días, en bps. Viene del crédito.
7
+ * SKUS_DISTINTOS_PERIODO - Cuántos SKUs distintos vendió el vendedor en el periodo.
8
+ */
9
+ export enum CommissionMetricEnum {
10
+ POSICION_VENTA_EN_PERIODO = 'POSICION_VENTA_EN_PERIODO',
11
+ COLOCACION_PERIODO = 'COLOCACION_PERIODO',
12
+ NPI_M30_VENDEDOR = 'NPI_M30_VENDEDOR',
13
+ SKUS_DISTINTOS_PERIODO = 'SKUS_DISTINTOS_PERIODO',
14
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Operadores de la condición de una regla.
3
+ *
4
+ * GTE, LTE, LT, GT - Contra un número.
5
+ * BETWEEN - Contra `[min, max]`, ambos inclusive.
6
+ * IN - Contra una lista de valores.
7
+ */
8
+ export enum CommissionOperatorEnum {
9
+ GTE = 'GTE',
10
+ LTE = 'LTE',
11
+ LT = 'LT',
12
+ GT = 'GT',
13
+ BETWEEN = 'BETWEEN',
14
+ IN = 'IN',
15
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Estado de una regla de comisión.
3
+ *
4
+ * DRAFT - Borrador: nunca se publicó y no está en el plan vigente.
5
+ * SCHEDULED - Publicada, con vigencia que todavía no empieza.
6
+ * ACTIVE - Publicada y vigente.
7
+ * PAUSED - Publicada y pausada: sale del plan vigente hasta reanudarla.
8
+ * EXPIRED - Vencida por fecha o con "Vencer ahora". No vuelve a aplicar.
9
+ */
10
+ export enum CommissionRuleStatusEnum {
11
+ DRAFT = 'DRAFT',
12
+ SCHEDULED = 'SCHEDULED',
13
+ ACTIVE = 'ACTIVE',
14
+ PAUSED = 'PAUSED',
15
+ EXPIRED = 'EXPIRED',
16
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * De qué se arma una serie por periodo.
3
+ *
4
+ * SELLER - Un vendedor.
5
+ * RULE - Una regla.
6
+ * STORE - Una tienda.
7
+ * SKU - Un producto.
8
+ */
9
+ export enum CommissionSeriesByEnum {
10
+ SELLER = 'SELLER',
11
+ RULE = 'RULE',
12
+ STORE = 'STORE',
13
+ SKU = 'SKU',
14
+ }