@fiado/type-kit 3.289.0 → 3.290.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/bin/benefitCenter/enums/BenefitFlowEnum.d.ts +11 -0
- package/bin/benefitCenter/enums/BenefitFlowEnum.js +15 -0
- package/bin/loanConfig/enums/ModifiableByRoleEnum.d.ts +11 -0
- package/bin/loanConfig/enums/ModifiableByRoleEnum.js +15 -0
- package/bin/places/dtos/CashInFeeDto.d.ts +17 -0
- package/bin/places/dtos/CashInFeeDto.js +12 -0
- package/bin/platformRbac/dtos/ResendOtpRequest.d.ts +22 -0
- package/bin/platformRbac/dtos/ResendOtpRequest.js +36 -0
- package/bin/platformRbac/dtos/ResendSelfRegisterOtpRequest.d.ts +11 -0
- package/bin/platformRbac/dtos/ResendSelfRegisterOtpRequest.js +36 -0
- package/bin/retailWizard/dtos/SaleLogEntry.d.ts +13 -0
- package/bin/retailWizard/dtos/responses/BackofficeSalesStatsResponse.d.ts +20 -4
- package/bin/retailWizard/dtos/responses/BackofficeSellerKpisResponse.d.ts +7 -0
- package/bin/retailWizard/dtos/responses/BackofficeStoreKpisResponse.d.ts +27 -0
- package/package.json +1 -1
- package/src/retailWizard/dtos/SaleLogEntry.ts +13 -0
- package/src/retailWizard/dtos/responses/BackofficeSalesStatsResponse.ts +20 -4
- package/src/retailWizard/dtos/responses/BackofficeSellerKpisResponse.ts +7 -0
- package/src/retailWizard/dtos/responses/BackofficeStoreKpisResponse.ts +27 -0
- package/bin/identity/enums/SelfieSourceEnum.d.ts +0 -10
- package/bin/identity/enums/SelfieSourceEnum.js +0 -14
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare enum BenefitFlowEnum {
|
|
2
|
+
TOPUPS = "TOPUPS",
|
|
3
|
+
BILL_PAYMENT = "BILL_PAYMENT",
|
|
4
|
+
CREDIT = "CREDIT",
|
|
5
|
+
INSURANCE = "INSURANCE",
|
|
6
|
+
DONATION = "DONATION",
|
|
7
|
+
PHARMACY = "PHARMACY",
|
|
8
|
+
REMITTANCE = "REMITTANCE",
|
|
9
|
+
/** Fondeo de wallet PCF con efectivo via provider externo (Equality/Passport, OpenPay, …) — spec 13. */
|
|
10
|
+
WALLET_FUNDING = "WALLET_FUNDING"
|
|
11
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BenefitFlowEnum = void 0;
|
|
4
|
+
var BenefitFlowEnum;
|
|
5
|
+
(function (BenefitFlowEnum) {
|
|
6
|
+
BenefitFlowEnum["TOPUPS"] = "TOPUPS";
|
|
7
|
+
BenefitFlowEnum["BILL_PAYMENT"] = "BILL_PAYMENT";
|
|
8
|
+
BenefitFlowEnum["CREDIT"] = "CREDIT";
|
|
9
|
+
BenefitFlowEnum["INSURANCE"] = "INSURANCE";
|
|
10
|
+
BenefitFlowEnum["DONATION"] = "DONATION";
|
|
11
|
+
BenefitFlowEnum["PHARMACY"] = "PHARMACY";
|
|
12
|
+
BenefitFlowEnum["REMITTANCE"] = "REMITTANCE";
|
|
13
|
+
/** Fondeo de wallet PCF con efectivo via provider externo (Equality/Passport, OpenPay, …) — spec 13. */
|
|
14
|
+
BenefitFlowEnum["WALLET_FUNDING"] = "WALLET_FUNDING";
|
|
15
|
+
})(BenefitFlowEnum || (exports.BenefitFlowEnum = BenefitFlowEnum = {}));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rol RBAC mínimo que puede modificar un parámetro (RBAC a nivel de parámetro, modelo-datos §8).
|
|
3
|
+
* `retailer_admin` = "Admin VentasLuga" de M6 §8. Valores = identificadores de rol de RBAC F0.
|
|
4
|
+
* TD-004: confirmar mapeo super_admin ↔ platform_super_admin con el naming real de F0.
|
|
5
|
+
* @enum {string}
|
|
6
|
+
*/
|
|
7
|
+
export declare enum ModifiableByRoleEnum {
|
|
8
|
+
SUPER_ADMIN = "super_admin",
|
|
9
|
+
SOFOM_ADMIN = "sofom_admin",
|
|
10
|
+
RETAILER_ADMIN = "retailer_admin"
|
|
11
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ModifiableByRoleEnum = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Rol RBAC mínimo que puede modificar un parámetro (RBAC a nivel de parámetro, modelo-datos §8).
|
|
6
|
+
* `retailer_admin` = "Admin VentasLuga" de M6 §8. Valores = identificadores de rol de RBAC F0.
|
|
7
|
+
* TD-004: confirmar mapeo super_admin ↔ platform_super_admin con el naming real de F0.
|
|
8
|
+
* @enum {string}
|
|
9
|
+
*/
|
|
10
|
+
var ModifiableByRoleEnum;
|
|
11
|
+
(function (ModifiableByRoleEnum) {
|
|
12
|
+
ModifiableByRoleEnum["SUPER_ADMIN"] = "super_admin";
|
|
13
|
+
ModifiableByRoleEnum["SOFOM_ADMIN"] = "sofom_admin";
|
|
14
|
+
ModifiableByRoleEnum["RETAILER_ADMIN"] = "retailer_admin";
|
|
15
|
+
})(ModifiableByRoleEnum || (exports.ModifiableByRoleEnum = ModifiableByRoleEnum = {}));
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CurrencyId } from '../../currency/enums/CurrencyId';
|
|
2
|
+
/**
|
|
3
|
+
* Comisión que cobra un punto de cash-in (lo que el lambda MUESTRA, no cobra).
|
|
4
|
+
* - GreenDot (US): representativo por cadena → `fixed` + `cap` (cada tienda cobra hasta el tope).
|
|
5
|
+
* - Passport (MX): por red → `fixed` + `percentage`.
|
|
6
|
+
* Response DTO — sin decoradores de validación.
|
|
7
|
+
*/
|
|
8
|
+
export declare class CashInFeeDto {
|
|
9
|
+
/** Comisión fija, en la moneda del país. */
|
|
10
|
+
fixed?: number;
|
|
11
|
+
/** Porcentaje del monto depositado (0–100). */
|
|
12
|
+
percentage?: number;
|
|
13
|
+
/** Tope máximo de comisión (GreenDot: el asociado cobra hasta este cap). */
|
|
14
|
+
cap?: number;
|
|
15
|
+
/** Moneda del fee: USD (GreenDot) | MXN (Passport). */
|
|
16
|
+
currency: CurrencyId;
|
|
17
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CashInFeeDto = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Comisión que cobra un punto de cash-in (lo que el lambda MUESTRA, no cobra).
|
|
6
|
+
* - GreenDot (US): representativo por cadena → `fixed` + `cap` (cada tienda cobra hasta el tope).
|
|
7
|
+
* - Passport (MX): por red → `fixed` + `percentage`.
|
|
8
|
+
* Response DTO — sin decoradores de validación.
|
|
9
|
+
*/
|
|
10
|
+
class CashInFeeDto {
|
|
11
|
+
}
|
|
12
|
+
exports.CashInFeeDto = CashInFeeDto;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { MfaMethodEnum } from '../enums/MfaMethodEnum';
|
|
2
|
+
/**
|
|
3
|
+
* Body del POST /auth/resend-otp (público, anónimo). DEC-RBAC-054.
|
|
4
|
+
* Reenvía el OTP del login re-disparando el challenge real CUSTOM_AUTH (EMAIL_OTP) para la
|
|
5
|
+
* identidad SIN password. `tenantId` obligatorio (DEC-064 — el picker ya lo resolvió, NO "solo email").
|
|
6
|
+
* El email se normaliza lowercase server-side. Postura anti-enumeración: respuesta 200 genérica
|
|
7
|
+
* siempre, sin filtrar existencia (ver AuthLoginManager.resendChallengeOtp).
|
|
8
|
+
*/
|
|
9
|
+
export declare class ResendOtpRequest {
|
|
10
|
+
email: string;
|
|
11
|
+
tenantId: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Respuesta del resend-otp. `session`/`mfaMethod` frescos del nuevo challenge CUSTOM_AUTH.
|
|
15
|
+
* Plain sin validators (no validamos lo que mandamos al cliente — fiado-validation-and-dtos § 7).
|
|
16
|
+
* Ambos opcionales: en los caminos de rechazo silencioso (anti-enumeración) o ramas sin CUSTOM_AUTH
|
|
17
|
+
* el server responde 200 genérico sin session ni método.
|
|
18
|
+
*/
|
|
19
|
+
export interface ResendOtpResponse {
|
|
20
|
+
session?: string;
|
|
21
|
+
mfaMethod?: MfaMethodEnum;
|
|
22
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
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.ResendOtpRequest = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
/**
|
|
16
|
+
* Body del POST /auth/resend-otp (público, anónimo). DEC-RBAC-054.
|
|
17
|
+
* Reenvía el OTP del login re-disparando el challenge real CUSTOM_AUTH (EMAIL_OTP) para la
|
|
18
|
+
* identidad SIN password. `tenantId` obligatorio (DEC-064 — el picker ya lo resolvió, NO "solo email").
|
|
19
|
+
* El email se normaliza lowercase server-side. Postura anti-enumeración: respuesta 200 genérica
|
|
20
|
+
* siempre, sin filtrar existencia (ver AuthLoginManager.resendChallengeOtp).
|
|
21
|
+
*/
|
|
22
|
+
class ResendOtpRequest {
|
|
23
|
+
}
|
|
24
|
+
exports.ResendOtpRequest = ResendOtpRequest;
|
|
25
|
+
__decorate([
|
|
26
|
+
(0, class_transformer_1.Expose)(),
|
|
27
|
+
(0, class_validator_1.IsEmail)(),
|
|
28
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
29
|
+
__metadata("design:type", String)
|
|
30
|
+
], ResendOtpRequest.prototype, "email", void 0);
|
|
31
|
+
__decorate([
|
|
32
|
+
(0, class_transformer_1.Expose)(),
|
|
33
|
+
(0, class_validator_1.IsString)(),
|
|
34
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
35
|
+
__metadata("design:type", String)
|
|
36
|
+
], ResendOtpRequest.prototype, "tenantId", void 0);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Body del POST /self-register/resend-otp (público, anónimo). DEC-RBAC-054.
|
|
3
|
+
* Re-envía el OTP del autoregistro (mecanismo messages-business, NO Cognito) tras validar un
|
|
4
|
+
* `pending` existente. Misma postura anti-enumeración del start. El email se normaliza lowercase
|
|
5
|
+
* server-side. DTO propio por endpoint (NO reusa SelfRegisterStartRequest, que exige roleId/scope/
|
|
6
|
+
* scopeRef, ni SelfRegisterVerifyOtpRequest, que exige otp).
|
|
7
|
+
*/
|
|
8
|
+
export declare class ResendSelfRegisterOtpRequest {
|
|
9
|
+
tenantId: string;
|
|
10
|
+
email: string;
|
|
11
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
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.ResendSelfRegisterOtpRequest = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
/**
|
|
16
|
+
* Body del POST /self-register/resend-otp (público, anónimo). DEC-RBAC-054.
|
|
17
|
+
* Re-envía el OTP del autoregistro (mecanismo messages-business, NO Cognito) tras validar un
|
|
18
|
+
* `pending` existente. Misma postura anti-enumeración del start. El email se normaliza lowercase
|
|
19
|
+
* server-side. DTO propio por endpoint (NO reusa SelfRegisterStartRequest, que exige roleId/scope/
|
|
20
|
+
* scopeRef, ni SelfRegisterVerifyOtpRequest, que exige otp).
|
|
21
|
+
*/
|
|
22
|
+
class ResendSelfRegisterOtpRequest {
|
|
23
|
+
}
|
|
24
|
+
exports.ResendSelfRegisterOtpRequest = ResendSelfRegisterOtpRequest;
|
|
25
|
+
__decorate([
|
|
26
|
+
(0, class_transformer_1.Expose)(),
|
|
27
|
+
(0, class_validator_1.IsString)(),
|
|
28
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
29
|
+
__metadata("design:type", String)
|
|
30
|
+
], ResendSelfRegisterOtpRequest.prototype, "tenantId", void 0);
|
|
31
|
+
__decorate([
|
|
32
|
+
(0, class_transformer_1.Expose)(),
|
|
33
|
+
(0, class_validator_1.IsEmail)(),
|
|
34
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
35
|
+
__metadata("design:type", String)
|
|
36
|
+
], ResendSelfRegisterOtpRequest.prototype, "email", void 0);
|
|
@@ -26,4 +26,17 @@ export interface SaleLogEntry {
|
|
|
26
26
|
/** Motivo, cuando la acción lo exige (cancelación, excepción aplicada). */
|
|
27
27
|
reason: string | null;
|
|
28
28
|
changes: SaleLogChange[];
|
|
29
|
+
/**
|
|
30
|
+
* Datos de la venta que la acción NO cambió y que se guardan para poder leer la entrada sin abrir
|
|
31
|
+
* otra pantalla (en un `SALE_CANCEL`: el tipo de venta, el monto, el enganche, el crédito).
|
|
32
|
+
*
|
|
33
|
+
* Va aparte de `changes` a propósito. Antes viajaba dentro de `new` y `changes` lo pintaba como un
|
|
34
|
+
* alta: la bitácora afirmaba que en la cancelación el tipo de venta había pasado «de nada a CASH».
|
|
35
|
+
* En una auditoría un cambio inventado es peor que un dato faltante.
|
|
36
|
+
*
|
|
37
|
+
* **El front lo pinta como contexto, NUNCA como «antes → después».** `null` cuando la acción no
|
|
38
|
+
* mandó contexto. Valores serializados a string igual que `changes`; y como `changes`, NUNCA
|
|
39
|
+
* lleva PII.
|
|
40
|
+
*/
|
|
41
|
+
context: Record<string, string | null> | null;
|
|
29
42
|
}
|
|
@@ -7,20 +7,36 @@
|
|
|
7
7
|
* contra el que el front ya mockeó la pantalla. Cambiarlas a inglés por consistencia rompería una
|
|
8
8
|
* pantalla ya construida sin ganar nada. Decisión de Andrés, 2026-08-03.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* **Las identidades del contrato** (las tres se cumplen siempre y están cubiertas por tests):
|
|
11
|
+
*
|
|
12
|
+
* - `contado` + `credito` + `sinProveedor` == `total`
|
|
13
|
+
* - `surekeep` + `externas` == `credito`
|
|
14
|
+
*
|
|
15
|
+
* `contado`, `credito` y `sinProveedor` particionan `total`; `surekeep` y `externas` particionan
|
|
16
|
+
* `credito`. Ninguna de las dos particiones se solapa (ver `helpers/saleFinancier`).
|
|
12
17
|
*/
|
|
13
18
|
export interface BackofficeSalesStatsResponse {
|
|
14
19
|
/** Ventas del retailer en la ventana consultada. */
|
|
15
20
|
total: number;
|
|
16
21
|
/** Subconjunto de `total` con `soldAt` en el día de hoy. */
|
|
17
22
|
hoy: number;
|
|
18
|
-
/** `type: CASH`. */
|
|
23
|
+
/** `type: CASH`. Efectivo de verdad — ver `sinProveedor`. */
|
|
19
24
|
contado: number;
|
|
20
|
-
/** `type: CREDIT
|
|
25
|
+
/** Derivadas con financiera CONOCIDA: `type: CREDIT`, o `EXTERNAL_REFERRAL` con proveedor. */
|
|
21
26
|
credito: number;
|
|
22
27
|
/** Financiadas por la SOFOM (`type: CREDIT`). */
|
|
23
28
|
surekeep: number;
|
|
24
29
|
/** Financiadas por un tercero (`EXTERNAL_REFERRAL` con proveedor). */
|
|
25
30
|
externas: number;
|
|
31
|
+
/**
|
|
32
|
+
* `type: EXTERNAL_REFERRAL` **sin** `externalProvider` — derivadas cuya financiera no quedó
|
|
33
|
+
* registrada. Es un DATO ROTO, no una forma de pago.
|
|
34
|
+
*
|
|
35
|
+
* Vive en su propia llave y NO en `contado` porque antes caía ahí y la pantalla las leía como
|
|
36
|
+
* EFECTIVO, que es la lectura más cara de equivocar. Tampoco entra en `credito`: `surekeep` +
|
|
37
|
+
* `externas` == `credito` y una venta sin financiera no pertenece a ninguna de las dos.
|
|
38
|
+
* Análisis ya las descartaba de su mix, y por eso Ventas y Análisis contaban distinto el mismo
|
|
39
|
+
* período. Un valor > 0 es una invitación a ir a corregir esas filas.
|
|
40
|
+
*/
|
|
41
|
+
sinProveedor: number;
|
|
26
42
|
}
|
|
@@ -22,6 +22,13 @@ export interface SellerKpiRow {
|
|
|
22
22
|
*
|
|
23
23
|
* Mismo criterio que A3: el eje es la venta, así que solo aparecen los vendedores que vendieron en
|
|
24
24
|
* la ventana. El roster completo vive en `retail-org-business`.
|
|
25
|
+
*
|
|
26
|
+
* ⚠️ **Sin la ★ de encargado de tienda** que pinta el mockup (`es_admin_tienda`). Ese flag es del
|
|
27
|
+
* padrón (`RetailUser_GT`, de `retail-org-business`), no del snapshot de la venta: la pantalla lo
|
|
28
|
+
* trae de ahí y lo une por `sellerRetailUserId`.
|
|
29
|
+
*
|
|
30
|
+
* ⚠️ Tampoco lleva variación contra la semana pasada — el mockup de Vendedores no la pinta, solo el
|
|
31
|
+
* de Tiendas (ver `StoreKpiRow.weekOverWeekChangePct`).
|
|
25
32
|
*/
|
|
26
33
|
export interface BackofficeSellerKpisResponse {
|
|
27
34
|
items: SellerKpiRow[];
|
|
@@ -15,6 +15,21 @@ export interface StoreKpiRow {
|
|
|
15
15
|
averageTicketCents: number | null;
|
|
16
16
|
/** ISO-8601 de la venta más reciente de la tienda en la ventana. `null` si no vendió. */
|
|
17
17
|
lastSaleAt: string | null;
|
|
18
|
+
/**
|
|
19
|
+
* Variación porcentual del volumen colocado contra la MISMA ventana corrida 7 días atrás, con un
|
|
20
|
+
* decimal. Es el chip `+12%` / `-8%` de la pantalla Tiendas.
|
|
21
|
+
*
|
|
22
|
+
* `null` en tres casos, todos «no sé» y ninguno «no cambió»:
|
|
23
|
+
* - la ventana pedida abarca **más de 7 días**, así que el baseline se solaparía con ella y el
|
|
24
|
+
* delta compararía un período contra sí mismo (con el default de 90 días, siempre);
|
|
25
|
+
* - la tienda no vendió nada esa semana — no se divide por cero;
|
|
26
|
+
* - los números vienen del data lake y no hay fila para esta tienda en el baseline.
|
|
27
|
+
*/
|
|
28
|
+
weekOverWeekChangePct: number | null;
|
|
29
|
+
/** Volumen colocado de la ventana de hace 7 días — el denominador del chip, explícito. */
|
|
30
|
+
baselineSameWeekdayCents: number | null;
|
|
31
|
+
/** Piezas de esa misma ventana. La pantalla las pinta debajo del chip («N piezas semana pasada»). */
|
|
32
|
+
baselineSameWeekdayUnits: number | null;
|
|
18
33
|
}
|
|
19
34
|
/**
|
|
20
35
|
* GET /backoffice/stores/kpis — la pantalla Tiendas del Admin VL (A3).
|
|
@@ -22,6 +37,18 @@ export interface StoreKpiRow {
|
|
|
22
37
|
*
|
|
23
38
|
* El eje es la VENTA: solo aparecen las tiendas que vendieron en la ventana. El roster completo
|
|
24
39
|
* (incluidas las que no vendieron) lo tiene `retail-org-business`; la pantalla los cruza.
|
|
40
|
+
*
|
|
41
|
+
* ⚠️ **Tres columnas del mockup NO salen de acá y no van a salir**, porque no están en el snapshot
|
|
42
|
+
* congelado de la venta sino en el padrón:
|
|
43
|
+
*
|
|
44
|
+
* | Columna | Dónde vive |
|
|
45
|
+
* |---|---|
|
|
46
|
+
* | código de tienda | `Store` — `retail-org-business` |
|
|
47
|
+
* | tipo propia / subdistribuidor | NO es un campo de `Store`: un subdistribuidor es un *retailer hijo*, así que sale de `GET /retailers/{retailerId}/hierarchy` |
|
|
48
|
+
* | vendedores activos | `RetailUser_GT` — `retail-org-business` |
|
|
49
|
+
*
|
|
50
|
+
* La pantalla las trae de ahí y las une por `storeId`. Devolverlas desde este endpoint obligaría al
|
|
51
|
+
* silo de ventas a consultar el padrón en cada lectura de tablero.
|
|
25
52
|
*/
|
|
26
53
|
export interface BackofficeStoreKpisResponse {
|
|
27
54
|
items: StoreKpiRow[];
|
package/package.json
CHANGED
|
@@ -27,4 +27,17 @@ export interface SaleLogEntry {
|
|
|
27
27
|
/** Motivo, cuando la acción lo exige (cancelación, excepción aplicada). */
|
|
28
28
|
reason: string | null;
|
|
29
29
|
changes: SaleLogChange[];
|
|
30
|
+
/**
|
|
31
|
+
* Datos de la venta que la acción NO cambió y que se guardan para poder leer la entrada sin abrir
|
|
32
|
+
* otra pantalla (en un `SALE_CANCEL`: el tipo de venta, el monto, el enganche, el crédito).
|
|
33
|
+
*
|
|
34
|
+
* Va aparte de `changes` a propósito. Antes viajaba dentro de `new` y `changes` lo pintaba como un
|
|
35
|
+
* alta: la bitácora afirmaba que en la cancelación el tipo de venta había pasado «de nada a CASH».
|
|
36
|
+
* En una auditoría un cambio inventado es peor que un dato faltante.
|
|
37
|
+
*
|
|
38
|
+
* **El front lo pinta como contexto, NUNCA como «antes → después».** `null` cuando la acción no
|
|
39
|
+
* mandó contexto. Valores serializados a string igual que `changes`; y como `changes`, NUNCA
|
|
40
|
+
* lleva PII.
|
|
41
|
+
*/
|
|
42
|
+
context: Record<string, string | null> | null;
|
|
30
43
|
}
|
|
@@ -7,20 +7,36 @@
|
|
|
7
7
|
* contra el que el front ya mockeó la pantalla. Cambiarlas a inglés por consistencia rompería una
|
|
8
8
|
* pantalla ya construida sin ganar nada. Decisión de Andrés, 2026-08-03.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* **Las identidades del contrato** (las tres se cumplen siempre y están cubiertas por tests):
|
|
11
|
+
*
|
|
12
|
+
* - `contado` + `credito` + `sinProveedor` == `total`
|
|
13
|
+
* - `surekeep` + `externas` == `credito`
|
|
14
|
+
*
|
|
15
|
+
* `contado`, `credito` y `sinProveedor` particionan `total`; `surekeep` y `externas` particionan
|
|
16
|
+
* `credito`. Ninguna de las dos particiones se solapa (ver `helpers/saleFinancier`).
|
|
12
17
|
*/
|
|
13
18
|
export interface BackofficeSalesStatsResponse {
|
|
14
19
|
/** Ventas del retailer en la ventana consultada. */
|
|
15
20
|
total: number;
|
|
16
21
|
/** Subconjunto de `total` con `soldAt` en el día de hoy. */
|
|
17
22
|
hoy: number;
|
|
18
|
-
/** `type: CASH`. */
|
|
23
|
+
/** `type: CASH`. Efectivo de verdad — ver `sinProveedor`. */
|
|
19
24
|
contado: number;
|
|
20
|
-
/** `type: CREDIT
|
|
25
|
+
/** Derivadas con financiera CONOCIDA: `type: CREDIT`, o `EXTERNAL_REFERRAL` con proveedor. */
|
|
21
26
|
credito: number;
|
|
22
27
|
/** Financiadas por la SOFOM (`type: CREDIT`). */
|
|
23
28
|
surekeep: number;
|
|
24
29
|
/** Financiadas por un tercero (`EXTERNAL_REFERRAL` con proveedor). */
|
|
25
30
|
externas: number;
|
|
31
|
+
/**
|
|
32
|
+
* `type: EXTERNAL_REFERRAL` **sin** `externalProvider` — derivadas cuya financiera no quedó
|
|
33
|
+
* registrada. Es un DATO ROTO, no una forma de pago.
|
|
34
|
+
*
|
|
35
|
+
* Vive en su propia llave y NO en `contado` porque antes caía ahí y la pantalla las leía como
|
|
36
|
+
* EFECTIVO, que es la lectura más cara de equivocar. Tampoco entra en `credito`: `surekeep` +
|
|
37
|
+
* `externas` == `credito` y una venta sin financiera no pertenece a ninguna de las dos.
|
|
38
|
+
* Análisis ya las descartaba de su mix, y por eso Ventas y Análisis contaban distinto el mismo
|
|
39
|
+
* período. Un valor > 0 es una invitación a ir a corregir esas filas.
|
|
40
|
+
*/
|
|
41
|
+
sinProveedor: number;
|
|
26
42
|
}
|
|
@@ -23,6 +23,13 @@ export interface SellerKpiRow {
|
|
|
23
23
|
*
|
|
24
24
|
* Mismo criterio que A3: el eje es la venta, así que solo aparecen los vendedores que vendieron en
|
|
25
25
|
* la ventana. El roster completo vive en `retail-org-business`.
|
|
26
|
+
*
|
|
27
|
+
* ⚠️ **Sin la ★ de encargado de tienda** que pinta el mockup (`es_admin_tienda`). Ese flag es del
|
|
28
|
+
* padrón (`RetailUser_GT`, de `retail-org-business`), no del snapshot de la venta: la pantalla lo
|
|
29
|
+
* trae de ahí y lo une por `sellerRetailUserId`.
|
|
30
|
+
*
|
|
31
|
+
* ⚠️ Tampoco lleva variación contra la semana pasada — el mockup de Vendedores no la pinta, solo el
|
|
32
|
+
* de Tiendas (ver `StoreKpiRow.weekOverWeekChangePct`).
|
|
26
33
|
*/
|
|
27
34
|
export interface BackofficeSellerKpisResponse {
|
|
28
35
|
items: SellerKpiRow[];
|
|
@@ -15,6 +15,21 @@ export interface StoreKpiRow {
|
|
|
15
15
|
averageTicketCents: number | null;
|
|
16
16
|
/** ISO-8601 de la venta más reciente de la tienda en la ventana. `null` si no vendió. */
|
|
17
17
|
lastSaleAt: string | null;
|
|
18
|
+
/**
|
|
19
|
+
* Variación porcentual del volumen colocado contra la MISMA ventana corrida 7 días atrás, con un
|
|
20
|
+
* decimal. Es el chip `+12%` / `-8%` de la pantalla Tiendas.
|
|
21
|
+
*
|
|
22
|
+
* `null` en tres casos, todos «no sé» y ninguno «no cambió»:
|
|
23
|
+
* - la ventana pedida abarca **más de 7 días**, así que el baseline se solaparía con ella y el
|
|
24
|
+
* delta compararía un período contra sí mismo (con el default de 90 días, siempre);
|
|
25
|
+
* - la tienda no vendió nada esa semana — no se divide por cero;
|
|
26
|
+
* - los números vienen del data lake y no hay fila para esta tienda en el baseline.
|
|
27
|
+
*/
|
|
28
|
+
weekOverWeekChangePct: number | null;
|
|
29
|
+
/** Volumen colocado de la ventana de hace 7 días — el denominador del chip, explícito. */
|
|
30
|
+
baselineSameWeekdayCents: number | null;
|
|
31
|
+
/** Piezas de esa misma ventana. La pantalla las pinta debajo del chip («N piezas semana pasada»). */
|
|
32
|
+
baselineSameWeekdayUnits: number | null;
|
|
18
33
|
}
|
|
19
34
|
|
|
20
35
|
/**
|
|
@@ -23,6 +38,18 @@ export interface StoreKpiRow {
|
|
|
23
38
|
*
|
|
24
39
|
* El eje es la VENTA: solo aparecen las tiendas que vendieron en la ventana. El roster completo
|
|
25
40
|
* (incluidas las que no vendieron) lo tiene `retail-org-business`; la pantalla los cruza.
|
|
41
|
+
*
|
|
42
|
+
* ⚠️ **Tres columnas del mockup NO salen de acá y no van a salir**, porque no están en el snapshot
|
|
43
|
+
* congelado de la venta sino en el padrón:
|
|
44
|
+
*
|
|
45
|
+
* | Columna | Dónde vive |
|
|
46
|
+
* |---|---|
|
|
47
|
+
* | código de tienda | `Store` — `retail-org-business` |
|
|
48
|
+
* | tipo propia / subdistribuidor | NO es un campo de `Store`: un subdistribuidor es un *retailer hijo*, así que sale de `GET /retailers/{retailerId}/hierarchy` |
|
|
49
|
+
* | vendedores activos | `RetailUser_GT` — `retail-org-business` |
|
|
50
|
+
*
|
|
51
|
+
* La pantalla las trae de ahí y las une por `storeId`. Devolverlas desde este endpoint obligaría al
|
|
52
|
+
* silo de ventas a consultar el padrón en cada lectura de tablero.
|
|
26
53
|
*/
|
|
27
54
|
export interface BackofficeStoreKpisResponse {
|
|
28
55
|
items: StoreKpiRow[];
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Con qué criterio se resolvió cuál archivo de S3 es la selfie del usuario.
|
|
3
|
-
* Le dice al consumidor qué tan confiable es el match antes de mandarla a un facematch.
|
|
4
|
-
*/
|
|
5
|
-
export declare enum SelfieSourceEnum {
|
|
6
|
-
/** Matcheó el verificationId de la verificación vigente en People. */
|
|
7
|
-
VERIFICATION = "VERIFICATION",
|
|
8
|
-
/** No hubo match por verificación: se tomó el archivo de selfie más reciente del bucket. */
|
|
9
|
-
LATEST = "LATEST"
|
|
10
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SelfieSourceEnum = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Con qué criterio se resolvió cuál archivo de S3 es la selfie del usuario.
|
|
6
|
-
* Le dice al consumidor qué tan confiable es el match antes de mandarla a un facematch.
|
|
7
|
-
*/
|
|
8
|
-
var SelfieSourceEnum;
|
|
9
|
-
(function (SelfieSourceEnum) {
|
|
10
|
-
/** Matcheó el verificationId de la verificación vigente en People. */
|
|
11
|
-
SelfieSourceEnum["VERIFICATION"] = "VERIFICATION";
|
|
12
|
-
/** No hubo match por verificación: se tomó el archivo de selfie más reciente del bucket. */
|
|
13
|
-
SelfieSourceEnum["LATEST"] = "LATEST";
|
|
14
|
-
})(SelfieSourceEnum || (exports.SelfieSourceEnum = SelfieSourceEnum = {}));
|