hvp-shared 13.12.0 → 13.14.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.
@@ -14,7 +14,7 @@ export declare enum MetricWeight {
14
14
  }
15
15
  export type MetricType = "indicator" | "support";
16
16
  export type MetricUnit = "currency" | "percent" | "number";
17
- export type MetricPillar = "P1" | "P2" | "P3";
17
+ export type MetricPillar = "P1" | "P2" | "P3" | "P4";
18
18
  export type MetricEndpoint = "growth" | "cooperation" | "fidelity" | "visits" | "others" | "operative" | "sales";
19
19
  export type MetricStatus = "implemented" | "proposed";
20
20
  export interface PerformanceMetricMeta {
@@ -39,3 +39,13 @@ export declare const PERFORMANCE_METRICS: Record<string, PerformanceMetricMeta>;
39
39
  export declare function performanceLabelsByEndpoint(endpoint: MetricEndpoint): Record<string, string>;
40
40
  /** Keys where a lower value is better, for a given endpoint. */
41
41
  export declare function performanceLowerIsBetter(endpoint: MetricEndpoint): Set<string>;
42
+ export interface MetricDetailView {
43
+ /** In-app route (HashRouter path under /dashboard). */
44
+ route: string;
45
+ /** Short Spanish name of the destination view. */
46
+ label: string;
47
+ }
48
+ /** metric key → its dedicated view (undefined if the metric has no own page). */
49
+ export declare const METRIC_DETAIL_VIEWS: Record<string, MetricDetailView>;
50
+ /** Convenience accessor: the dedicated view for a metric key, or undefined. */
51
+ export declare function metricDetailView(key: string): MetricDetailView | undefined;
@@ -9,9 +9,10 @@
9
9
  * 76 metrics · type {"indicator":38,"support":38} · weight {"critical":10,"important":17,"complementary":11} · status {"implemented":70,"proposed":6}
10
10
  */
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.PERFORMANCE_METRICS = exports.MetricWeight = void 0;
12
+ exports.METRIC_DETAIL_VIEWS = exports.PERFORMANCE_METRICS = exports.MetricWeight = void 0;
13
13
  exports.performanceLabelsByEndpoint = performanceLabelsByEndpoint;
14
14
  exports.performanceLowerIsBetter = performanceLowerIsBetter;
15
+ exports.metricDetailView = metricDetailView;
15
16
  var MetricWeight;
16
17
  (function (MetricWeight) {
17
18
  MetricWeight["CRITICAL"] = "critical";
@@ -21,7 +22,7 @@ var MetricWeight;
21
22
  exports.PERFORMANCE_METRICS = {
22
23
  "assistancesGiven": { key: "assistancesGiven", label: "Asistencias prestadas", type: "indicator", weight: MetricWeight.CRITICAL, unit: "number", endpoint: "cooperation", pillar: "P1", status: "implemented" },
23
24
  "mentorshipsAsMentor": { key: "mentorshipsAsMentor", label: "Mentorías como mentor", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "number", endpoint: "cooperation", pillar: "P1", status: "implemented" },
24
- "mentorshipsAsMentoree": { key: "mentorshipsAsMentoree", label: "Mentorías como mentoree", type: "indicator", weight: MetricWeight.COMPLEMENTARY, unit: "number", endpoint: "cooperation", pillar: "P1", status: "implemented" },
25
+ "mentorshipsAsMentoree": { key: "mentorshipsAsMentoree", label: "Mentorías como mentoree", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "number", endpoint: "cooperation", pillar: "P1", status: "implemented" },
25
26
  "allConsultations": { key: "allConsultations", label: "Consultas", type: "indicator", weight: MetricWeight.CRITICAL, unit: "number", endpoint: "growth", pillar: "P1", status: "implemented" },
26
27
  "allHospitalizations": { key: "allHospitalizations", label: "Hospitalizaciones y emergencias", type: "indicator", weight: MetricWeight.COMPLEMENTARY, unit: "number", endpoint: "growth", pillar: "P1", status: "implemented" },
27
28
  "allLabWork": { key: "allLabWork", label: "Laboratorio", type: "indicator", weight: MetricWeight.COMPLEMENTARY, unit: "number", endpoint: "growth", pillar: "P1", status: "implemented" },
@@ -30,7 +31,8 @@ exports.PERFORMANCE_METRICS = {
30
31
  "allSurgeryAssistances": { key: "allSurgeryAssistances", label: "Asistencias de cirugía", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "number", endpoint: "growth", pillar: "P1", status: "implemented" },
31
32
  "chemistryPanels": { key: "chemistryPanels", label: "Químicas sanguíneas", type: "support", unit: "number", endpoint: "growth", pillar: "P1", status: "implemented" },
32
33
  "commissionAmount": { key: "commissionAmount", label: "Monto de comisiones", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "currency", endpoint: "growth", pillar: "P1", status: "implemented" },
33
- "commissionCount": { key: "commissionCount", label: "Comisiones recibidas", type: "indicator", weight: MetricWeight.CRITICAL, unit: "number", endpoint: "growth", pillar: "P1", status: "implemented" },
34
+ "commissionCount": { key: "commissionCount", label: "Comisiones recibidas", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "number", endpoint: "growth", pillar: "P1", status: "implemented" },
35
+ "egoCommissions": { key: "egoCommissions", label: "Comisiones de Examen General de Orina (EGO)", type: "indicator", weight: MetricWeight.COMPLEMENTARY, unit: "number", endpoint: "growth", pillar: "P4", status: "implemented" },
34
36
  "complexSurgeries": { key: "complexSurgeries", label: "Cirugías complejas", type: "support", unit: "number", endpoint: "growth", pillar: "P1", status: "implemented" },
35
37
  "consultations": { key: "consultations", label: "Consultas generales", type: "support", unit: "number", endpoint: "growth", pillar: "P1", status: "implemented" },
36
38
  "dewormings": { key: "dewormings", label: "Desparasitaciones", type: "support", unit: "number", endpoint: "growth", pillar: "P1", status: "implemented" },
@@ -50,18 +52,18 @@ exports.PERFORMANCE_METRICS = {
50
52
  "matchedConsultations": { key: "matchedConsultations", label: "Consultas y vacunas comisionadas con visita registrada", type: "support", unit: "number", endpoint: "others", pillar: "P1", status: "implemented" },
51
53
  "matchRate": { key: "matchRate", label: "% de consultas y vacunas comisionadas con visita registrada", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "percent", endpoint: "others", pillar: "P1", status: "implemented" },
52
54
  "avgVisitLength": { key: "avgVisitLength", label: "Extensión promedio (caracteres)", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "number", endpoint: "visits", pillar: "P1", status: "implemented" },
53
- "visitCount": { key: "visitCount", label: "Visitas registradas", type: "indicator", weight: MetricWeight.CRITICAL, unit: "number", endpoint: "visits", pillar: "P1", status: "implemented" },
55
+ "visitCount": { key: "visitCount", label: "Visitas registradas", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "number", endpoint: "visits", pillar: "P1", status: "implemented" },
54
56
  "newClients": { key: "newClients", label: "Clientes nuevos", type: "indicator", weight: MetricWeight.COMPLEMENTARY, unit: "number", endpoint: "fidelity", pillar: "P2", status: "implemented" },
55
57
  "vetRequestedTotal": { key: "vetRequestedTotal", label: "Veterinario solicitado (total)", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "number", endpoint: "fidelity", pillar: "P2", status: "implemented" },
56
- "avgTicketOverall": { key: "avgTicketOverall", label: "Ticket promedio general", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "currency", endpoint: "sales", pillar: "P2", status: "proposed" },
57
- "consultations_avgTicket": { key: "consultations_avgTicket", label: "Consultas — prom. ticket", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "currency", endpoint: "sales", pillar: "P2", status: "implemented" },
58
+ "avgTicketOverall": { key: "avgTicketOverall", label: "Ticket promedio general", type: "indicator", weight: MetricWeight.COMPLEMENTARY, unit: "currency", endpoint: "sales", pillar: "P2", status: "implemented" },
59
+ "consultations_avgTicket": { key: "consultations_avgTicket", label: "Consultas — prom. ticket", type: "indicator", weight: MetricWeight.CRITICAL, unit: "currency", endpoint: "sales", pillar: "P2", status: "implemented" },
58
60
  "consultations_extraPct": { key: "consultations_extraPct", label: "Consultas — extra %", type: "indicator", weight: MetricWeight.COMPLEMENTARY, unit: "percent", endpoint: "sales", pillar: "P2", status: "implemented" },
59
61
  "consultations_tickets": { key: "consultations_tickets", label: "Consultas — tickets", type: "support", unit: "number", endpoint: "sales", pillar: "P2", status: "implemented" },
60
62
  "emergencies_avgTicket": { key: "emergencies_avgTicket", label: "Emergencias y hospitalizaciones — prom. ticket", type: "support", unit: "currency", endpoint: "sales", pillar: "P2", status: "implemented" },
61
63
  "emergencies_extraPct": { key: "emergencies_extraPct", label: "Emergencias y hospitalizaciones — extra %", type: "support", unit: "percent", endpoint: "sales", pillar: "P2", status: "implemented" },
62
64
  "emergencies_tickets": { key: "emergencies_tickets", label: "Emergencias y hospitalizaciones — tickets", type: "support", unit: "number", endpoint: "sales", pillar: "P2", status: "implemented" },
63
- "generatedRevenue": { key: "generatedRevenue", label: "Facturación generada", type: "indicator", weight: MetricWeight.CRITICAL, unit: "currency", endpoint: "sales", pillar: "P2", status: "proposed" },
64
- "pharmacyProductSales": { key: "pharmacyProductSales", label: "Venta de farmacia / productos", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "currency", endpoint: "sales", pillar: "P2", status: "proposed" },
65
+ "generatedRevenue": { key: "generatedRevenue", label: "Facturación generada", type: "indicator", weight: MetricWeight.CRITICAL, unit: "currency", endpoint: "sales", pillar: "P2", status: "implemented" },
66
+ "pharmacyProductSales": { key: "pharmacyProductSales", label: "Venta de farmacia / productos", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "currency", endpoint: "sales", pillar: "P2", status: "implemented" },
65
67
  "surgeries_avgTicket": { key: "surgeries_avgTicket", label: "Cirugías — prom. ticket", type: "support", unit: "currency", endpoint: "sales", pillar: "P2", status: "implemented" },
66
68
  "surgeries_extraPct": { key: "surgeries_extraPct", label: "Cirugías — extra %", type: "support", unit: "percent", endpoint: "sales", pillar: "P2", status: "implemented" },
67
69
  "surgeries_tickets": { key: "surgeries_tickets", label: "Cirugías — tickets", type: "support", unit: "number", endpoint: "sales", pillar: "P2", status: "implemented" },
@@ -77,24 +79,28 @@ exports.PERFORMANCE_METRICS = {
77
79
  "closingSuccessRate": { key: "closingSuccessRate", label: "% cierres bien hechos", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "percent", endpoint: "operative", pillar: "P3", status: "implemented" },
78
80
  "collectionsAmount": { key: "collectionsAmount", label: "Monto de cobros", type: "indicator", weight: MetricWeight.COMPLEMENTARY, unit: "currency", endpoint: "operative", pillar: "P3", status: "implemented" },
79
81
  "collectionsTickets": { key: "collectionsTickets", label: "Tickets cobrados", type: "support", unit: "number", endpoint: "operative", pillar: "P3", status: "implemented" },
80
- "cvGlobalPct": { key: "cvGlobalPct", label: "% Clientes Varios (monto total)", type: "indicator", weight: MetricWeight.COMPLEMENTARY, unit: "percent", lowerIsBetter: true, endpoint: "operative", pillar: "P3", status: "implemented" },
81
- "cvMedicalPct": { key: "cvMedicalPct", label: "% Clientes Varios (servicios médicos)", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "percent", lowerIsBetter: true, endpoint: "operative", pillar: "P3", status: "implemented" },
82
- "docsReadRate": { key: "docsReadRate", label: "% documentación interna leída", type: "indicator", weight: MetricWeight.CRITICAL, unit: "percent", endpoint: "operative", pillar: "P3", status: "proposed" },
82
+ "cvObligatoryPct": { key: "cvObligatoryPct", label: "% obligatorios a Clientes Varios", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "percent", lowerIsBetter: true, endpoint: "operative", pillar: "P3", status: "implemented" },
83
+ "duplicateClientsCreated": { key: "duplicateClientsCreated", label: "Clientes duplicados creados", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "number", lowerIsBetter: true, endpoint: "operative", pillar: "P3", status: "implemented" },
84
+ "cvGlobalPct": { key: "cvGlobalPct", label: "% por monto (>$500) a Clientes Varios", type: "support", unit: "percent", lowerIsBetter: true, endpoint: "operative", pillar: "P3", status: "implemented" },
85
+ "cvMedicalPct": { key: "cvMedicalPct", label: "% médicos/externos a Clientes Varios", type: "support", unit: "percent", lowerIsBetter: true, endpoint: "operative", pillar: "P3", status: "implemented" },
86
+ "docsReadRate": { key: "docsReadRate", label: "% documentación interna leída", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "percent", endpoint: "operative", pillar: "P3", status: "implemented" },
83
87
  "farCheckInRate": { key: "farCheckInRate", label: "% check-ins fuera", type: "indicator", weight: MetricWeight.COMPLEMENTARY, unit: "percent", lowerIsBetter: true, endpoint: "operative", pillar: "P3", status: "implemented" },
84
88
  "farCheckIns": { key: "farCheckIns", label: "Check-ins fuera de sucursal", type: "support", unit: "number", lowerIsBetter: true, endpoint: "operative", pillar: "P3", status: "implemented" },
85
- "goodSchedulingRate": { key: "goodSchedulingRate", label: "% agendas bien hechas", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "percent", endpoint: "operative", pillar: "P3", status: "proposed" },
86
- "internalLabRate": { key: "internalLabRate", label: "% químicas y hemogramas internos", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "percent", endpoint: "operative", pillar: "P3", status: "proposed" },
89
+ "goodSchedulingRate": { key: "goodSchedulingRate", label: "Calidad de agenda (puntaje prom.)", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "percent", endpoint: "operative", pillar: "P3", status: "implemented" },
90
+ "scheduledAppointments": { key: "scheduledAppointments", label: "Citas agendadas con nombre", type: "indicator", weight: MetricWeight.COMPLEMENTARY, unit: "number", endpoint: "operative", pillar: "P3", status: "implemented" },
91
+ "correctVisitTypeRate": { key: "correctVisitTypeRate", label: "% tipo de visita correcto", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "percent", endpoint: "visits", pillar: "P1", status: "implemented" },
92
+ "internalLabRate": { key: "internalLabRate", label: "% químicas y hemogramas internos", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "percent", endpoint: "operative", pillar: "P3", status: "implemented" },
87
93
  "invalidClosings": { key: "invalidClosings", label: "Cierres inválidos", type: "support", unit: "number", lowerIsBetter: true, endpoint: "operative", pillar: "P3", status: "implemented" },
88
94
  "lateCount": { key: "lateCount", label: "Retardos (>10 min)", type: "support", unit: "number", lowerIsBetter: true, endpoint: "operative", pillar: "P3", status: "implemented" },
89
95
  "lateRate": { key: "lateRate", label: "% retardos", type: "indicator", weight: MetricWeight.CRITICAL, unit: "percent", lowerIsBetter: true, endpoint: "operative", pillar: "P3", status: "implemented" },
90
96
  "memosRead": { key: "memosRead", label: "Memorandums leídos", type: "support", unit: "number", endpoint: "operative", pillar: "P3", status: "implemented" },
91
- "memosReadRate": { key: "memosReadRate", label: "% lectura de memorandums", type: "indicator", weight: MetricWeight.CRITICAL, unit: "percent", endpoint: "operative", pillar: "P3", status: "implemented" },
97
+ "memosReadRate": { key: "memosReadRate", label: "% lectura de memorandums", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "percent", endpoint: "operative", pillar: "P3", status: "implemented" },
92
98
  "salesAmount": { key: "salesAmount", label: "Monto de ventas", type: "indicator", weight: MetricWeight.COMPLEMENTARY, unit: "currency", endpoint: "operative", pillar: "P3", status: "implemented" },
93
99
  "salesCount": { key: "salesCount", label: "Tickets vendidos", type: "support", unit: "number", endpoint: "operative", pillar: "P3", status: "implemented" },
94
100
  "sellerMatchRate": { key: "sellerMatchRate", label: "% de cobros con el vendedor correcto", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "percent", endpoint: "operative", pillar: "P3", status: "implemented" },
95
101
  "verifiedTickets": { key: "verifiedTickets", label: "Tickets médicos verificados", type: "support", unit: "number", endpoint: "operative", pillar: "P3", status: "implemented" },
96
102
  "ownSaleConsultations": { key: "ownSaleConsultations", label: "Consultas y vacunas comisionadas en las que aparezco como vendedor", type: "support", unit: "number", endpoint: "others", pillar: "P3", status: "implemented" },
97
- "ownSaleRate": { key: "ownSaleRate", label: "% de consultas y vacunas comisionadas en las que aparezco como vendedor", type: "indicator", weight: MetricWeight.IMPORTANT, unit: "percent", endpoint: "others", pillar: "P3", status: "implemented" },
103
+ "ownSaleRate": { key: "ownSaleRate", label: "% de consultas y vacunas comisionadas en las que aparezco como vendedor", type: "indicator", weight: MetricWeight.COMPLEMENTARY, unit: "percent", endpoint: "others", pillar: "P3", status: "implemented" },
98
104
  };
99
105
  /** Labels for a given endpoint (replaces the per-endpoint *_METRIC_LABELS maps). */
100
106
  function performanceLabelsByEndpoint(endpoint) {
@@ -111,3 +117,78 @@ function performanceLowerIsBetter(endpoint) {
111
117
  .filter((m) => m.endpoint === endpoint && m.lowerIsBetter)
112
118
  .map((m) => m.key));
113
119
  }
120
+ const DETAIL_VIEW_GROUPS = [
121
+ {
122
+ view: { route: "/dashboard/commissions", label: "Comisiones" },
123
+ keys: [
124
+ "commissionAmount", "commissionCount", "totalServices", "allConsultations",
125
+ "allSurgeries", "allPreventive", "allSurgeryAssistances", "allHospitalizations",
126
+ "allLabWork", "assistancesGiven", "mentorshipsAsMentor", "mentorshipsAsMentoree",
127
+ "vetRequestedTotal", "newClients", "egoCommissions", "commissionConsultations",
128
+ "ownSaleConsultations", "chemistryPanels", "complexSurgeries", "consultations",
129
+ "dewormings", "diagnosticTests", "emergencies", "englishConsultations", "hemograms",
130
+ "hospitalizations", "revisions", "specialistConsultations", "specialistRevisions",
131
+ "surgeries", "surgeryAssistances", "vaccines",
132
+ ],
133
+ },
134
+ {
135
+ view: { route: "/dashboard/qvet/sync/visits", label: "Visitas clínicas" },
136
+ keys: ["visitCount", "avgVisitLength", "matchRate", "correctVisitTypeRate", "matchedConsultations"],
137
+ },
138
+ {
139
+ view: { route: "/dashboard/google-calendar/diagnose", label: "Diagnóstico de agenda" },
140
+ keys: ["goodSchedulingRate", "scheduledAppointments"],
141
+ },
142
+ {
143
+ view: { route: "/dashboard/attendance-records", label: "Asistencia" },
144
+ keys: ["absenceRate", "lateRate", "farCheckInRate", "absences", "attendanceCount", "lateCount", "farCheckIns"],
145
+ },
146
+ {
147
+ view: { route: "/dashboard/documentation/memos", label: "Memorandums" },
148
+ keys: ["memosReadRate", "memosRead"],
149
+ },
150
+ {
151
+ view: { route: "/dashboard/documentation/compliance", label: "Control de lectura" },
152
+ keys: ["docsReadRate"],
153
+ },
154
+ {
155
+ view: { route: "/dashboard/cash-reconciliation", label: "Reconciliación de caja" },
156
+ keys: ["closingSuccessRate", "closingsCount", "invalidClosings"],
157
+ },
158
+ {
159
+ view: { route: "/dashboard/cash-reconciliation", label: "Reconciliación de caja" },
160
+ keys: ["cashFlowValidRate", "cashFlowCount"],
161
+ },
162
+ {
163
+ view: { route: "/dashboard/qvet/sync/collections", label: "Ventas y cobros" },
164
+ keys: ["salesAmount", "collectionsAmount", "salesCount", "collectionsTickets", "ownSaleRate", "sellerMatchRate", "verifiedTickets"],
165
+ },
166
+ {
167
+ view: { route: "/dashboard/qvet/sync/sales", label: "Ventas QVET" },
168
+ keys: [
169
+ "generatedRevenue", "pharmacyProductSales", "avgTicketOverall",
170
+ "consultations_avgTicket", "consultations_extraPct", "consultations_tickets",
171
+ "surgeries_avgTicket", "surgeries_extraPct", "surgeries_tickets",
172
+ "vaccines_avgTicket", "vaccines_extraPct", "vaccines_tickets",
173
+ "emergencies_avgTicket", "emergencies_extraPct", "emergencies_tickets",
174
+ ],
175
+ },
176
+ {
177
+ view: { route: "/dashboard/audit/generic-clients", label: "Auditoría Clientes Varios" },
178
+ keys: ["cvObligatoryPct", "cvGlobalPct", "cvMedicalPct"],
179
+ },
180
+ {
181
+ view: { route: "/dashboard/audit/duplicates", label: "Auditoría duplicados" },
182
+ keys: ["duplicateClientsCreated"],
183
+ },
184
+ {
185
+ view: { route: "/dashboard/performance/lab", label: "Análisis de laboratorio" },
186
+ keys: ["internalLabRate"],
187
+ },
188
+ ];
189
+ /** metric key → its dedicated view (undefined if the metric has no own page). */
190
+ exports.METRIC_DETAIL_VIEWS = Object.fromEntries(DETAIL_VIEW_GROUPS.flatMap((g) => g.keys.map((k) => [k, g.view])));
191
+ /** Convenience accessor: the dedicated view for a metric key, or undefined. */
192
+ function metricDetailView(key) {
193
+ return exports.METRIC_DETAIL_VIEWS[key];
194
+ }
@@ -20,5 +20,8 @@ export declare const LEGAL_VACATIONS: {
20
20
  /**
21
21
  * TimeOffTypes that consume vacation balance.
22
22
  * Only these types count against a collaborator's vacation days.
23
+ *
24
+ * NOTE: TimeOffType.PaidLeave (Permiso con goce de sueldo) is intentionally
25
+ * EXCLUDED — a paid leave pays full salary but must NOT consume vacation days.
23
26
  */
24
27
  export declare const VACATION_CONSUMING_TYPES: readonly TimeOffType[];
@@ -87,6 +87,9 @@ exports.LEGAL_VACATIONS = {
87
87
  /**
88
88
  * TimeOffTypes that consume vacation balance.
89
89
  * Only these types count against a collaborator's vacation days.
90
+ *
91
+ * NOTE: TimeOffType.PaidLeave (Permiso con goce de sueldo) is intentionally
92
+ * EXCLUDED — a paid leave pays full salary but must NOT consume vacation days.
90
93
  */
91
94
  exports.VACATION_CONSUMING_TYPES = [
92
95
  time_off_enums_1.TimeOffType.Vacation,
@@ -19,7 +19,14 @@ export declare enum TimeOffType {
19
19
  AuthorizedUnjustifiedAbsence = "Falta injustificada autorizada",
20
20
  EarlyLeavePermission = "Permiso de salida anticipada",
21
21
  LatePermission = "Permiso de llegar tarde",
22
- CompensationShift = "Reposici\u00F3n de jornada"
22
+ CompensationShift = "Reposici\u00F3n de jornada",
23
+ /**
24
+ * Employer-paid authorized absence at full ordinary salary (paternity,
25
+ * marriage, bereavement, etc.). The specific motive goes in the request note.
26
+ * Pays full salary, NO discount, does NOT consume vacation balance, grants
27
+ * NO prima vacacional, and pays NO commission/average-income compensation.
28
+ */
29
+ PaidLeave = "Permiso con goce de sueldo"
23
30
  }
24
31
  /** Spanish display labels for TimeOffType */
25
32
  export declare const TIME_OFF_TYPE_LABELS: Record<TimeOffType, string>;
@@ -25,6 +25,13 @@ var TimeOffType;
25
25
  TimeOffType["EarlyLeavePermission"] = "Permiso de salida anticipada";
26
26
  TimeOffType["LatePermission"] = "Permiso de llegar tarde";
27
27
  TimeOffType["CompensationShift"] = "Reposici\u00F3n de jornada";
28
+ /**
29
+ * Employer-paid authorized absence at full ordinary salary (paternity,
30
+ * marriage, bereavement, etc.). The specific motive goes in the request note.
31
+ * Pays full salary, NO discount, does NOT consume vacation balance, grants
32
+ * NO prima vacacional, and pays NO commission/average-income compensation.
33
+ */
34
+ TimeOffType["PaidLeave"] = "Permiso con goce de sueldo";
28
35
  })(TimeOffType || (exports.TimeOffType = TimeOffType = {}));
29
36
  /** Spanish display labels for TimeOffType */
30
37
  exports.TIME_OFF_TYPE_LABELS = {
@@ -37,6 +44,7 @@ exports.TIME_OFF_TYPE_LABELS = {
37
44
  [TimeOffType.EarlyLeavePermission]: 'Permiso de salida anticipada',
38
45
  [TimeOffType.LatePermission]: 'Permiso de llegar tarde',
39
46
  [TimeOffType.CompensationShift]: 'Reposición de jornada',
47
+ [TimeOffType.PaidLeave]: 'Permiso con goce de sueldo',
40
48
  };
41
49
  /** Spanish display labels for TimeOffStatus */
42
50
  exports.TIME_OFF_STATUS_LABELS = {
@@ -27,6 +27,12 @@ export interface DuplicateClientInfo {
27
27
  visitCount: number;
28
28
  salesTotalAmount: number;
29
29
  petNames: string[];
30
+ /** QVET staff member who registered the client ("PERSONAL ALTA"). Null for old records QVET never recorded a creator for. */
31
+ createdByStaff: string | null;
32
+ /** When the client was created in QVET ("FECHA ALTA"), ISO 8601. */
33
+ createdAt: string | null;
34
+ /** When the client was deactivated ("FECHA BAJA"), ISO 8601. Null if still active. */
35
+ deactivatedAt: string | null;
30
36
  }
31
37
  /**
32
38
  * A group of 2+ clients detected as potential duplicates.
@@ -51,6 +57,17 @@ export interface DuplicateClientsSummary {
51
57
  lowConfidence: number;
52
58
  uniqueClientsInvolved: number;
53
59
  }
60
+ /**
61
+ * Per-staff alta summary for the selected period: how many clients each staff
62
+ * registered ("PERSONAL ALTA") and how many of those turned out to be duplicates
63
+ * (score >= 30). Includes staff with 0 duplicates so you can see who does it well.
64
+ * Only present when a period filter (createdFrom/createdTo) is applied.
65
+ */
66
+ export interface DuplicateAltaStaffSummary {
67
+ staff: string;
68
+ created: number;
69
+ duplicates: number;
70
+ }
54
71
  /**
55
72
  * Full response for duplicate client detection endpoint.
56
73
  *
@@ -59,6 +76,7 @@ export interface DuplicateClientsSummary {
59
76
  export interface DuplicateClientsResponse {
60
77
  summary: DuplicateClientsSummary;
61
78
  groups: DuplicateClientGroup[];
79
+ altasSummary?: DuplicateAltaStaffSummary[];
62
80
  }
63
81
  /**
64
82
  * Query parameters for filtering duplicate detection results.
@@ -68,4 +86,12 @@ export interface DuplicateClientsQueryParams {
68
86
  minScore?: number;
69
87
  confidence?: DuplicateClientConfidence;
70
88
  includeInactive?: boolean;
89
+ /**
90
+ * Period filter (YYYY-MM-DD, MX timezone). When set, only groups that contain
91
+ * at least one client CREATED in [createdFrom, createdTo] are returned — i.e.
92
+ * "which clients registered this period duplicate an existing one". Detection
93
+ * still compares against ALL clients (previous ones included).
94
+ */
95
+ createdFrom?: string;
96
+ createdTo?: string;
71
97
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hvp-shared",
3
- "version": "13.12.0",
3
+ "version": "13.14.0",
4
4
  "description": "Shared types and utilities for HVP backend and frontend",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",