feat: integrate consumption metrics into plan usage cycle tracking and UI display
This commit is contained in:
@@ -58,7 +58,6 @@ export class PlanUsageCycleAdapterMongoose implements IPlanUsageCycleAdapter {
|
|||||||
planId: data.planId,
|
planId: data.planId,
|
||||||
cycleStart: data.cycleStart,
|
cycleStart: data.cycleStart,
|
||||||
cycleEnd: data.cycleEnd,
|
cycleEnd: data.cycleEnd,
|
||||||
appointmentsCount: 0,
|
|
||||||
creationDate: now,
|
creationDate: now,
|
||||||
},
|
},
|
||||||
$set: { updateDate: now },
|
$set: { updateDate: now },
|
||||||
@@ -85,7 +84,6 @@ export class PlanUsageCycleAdapterMongoose implements IPlanUsageCycleAdapter {
|
|||||||
planId: data.planId,
|
planId: data.planId,
|
||||||
cycleStart: data.cycleStart,
|
cycleStart: data.cycleStart,
|
||||||
cycleEnd: data.cycleEnd,
|
cycleEnd: data.cycleEnd,
|
||||||
appointmentsCount: 0,
|
|
||||||
creationDate: now,
|
creationDate: now,
|
||||||
},
|
},
|
||||||
$inc: { appointmentsCount: data.quantity },
|
$inc: { appointmentsCount: data.quantity },
|
||||||
|
|||||||
@@ -49,6 +49,11 @@ export type SysAdminRecalculatePlanUsageCycleResult = {
|
|||||||
planId: string;
|
planId: string;
|
||||||
cycleStart: Date;
|
cycleStart: Date;
|
||||||
cycleEnd: Date;
|
cycleEnd: Date;
|
||||||
|
organizationsCount: number;
|
||||||
|
employeesCount: number;
|
||||||
|
servicesCount: number;
|
||||||
|
clientsCount: number;
|
||||||
|
repeatsCount: number;
|
||||||
appointmentsCount: number;
|
appointmentsCount: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { connect } from "mongoose";
|
|||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import AppointmentList from "../../../Models/Appointments/Appointments";
|
import AppointmentList from "../../../Models/Appointments/Appointments";
|
||||||
import CompaniesList from "../../../Models/Companies/Companies";
|
import CompaniesList from "../../../Models/Companies/Companies";
|
||||||
|
import MetricsList from "../../../Models/Metrics/Metrics";
|
||||||
import PlanUsageCycleList from "../../../Models/PlanUsageCycle/PlanUsageCycle";
|
import PlanUsageCycleList from "../../../Models/PlanUsageCycle/PlanUsageCycle";
|
||||||
import {
|
import {
|
||||||
SysAdminRecalculatePlanUsageCycleParams,
|
SysAdminRecalculatePlanUsageCycleParams,
|
||||||
@@ -37,12 +38,20 @@ export class SysAdminPlanUsageCycleService {
|
|||||||
throw new Error("No se pudo recalcular el uso del plan.");
|
throw new Error("No se pudo recalcular el uso del plan.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await MetricsList.calculateMetrics({ userId: params.userId });
|
||||||
|
const metrics = await MetricsList.getMetrics(params.userId);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
userId: params.userId,
|
userId: params.userId,
|
||||||
subscriptionId: String(updatedCycle.subscriptionId),
|
subscriptionId: String(updatedCycle.subscriptionId),
|
||||||
planId: String(updatedCycle.planId),
|
planId: String(updatedCycle.planId),
|
||||||
cycleStart: updatedCycle.cycleStart,
|
cycleStart: updatedCycle.cycleStart,
|
||||||
cycleEnd: updatedCycle.cycleEnd,
|
cycleEnd: updatedCycle.cycleEnd,
|
||||||
|
organizationsCount: metrics.organizationsCount,
|
||||||
|
employeesCount: metrics.employeesCount,
|
||||||
|
servicesCount: metrics.servicesCount,
|
||||||
|
clientsCount: metrics.clientsCount,
|
||||||
|
repeatsCount: metrics.repeatsCount || 0,
|
||||||
appointmentsCount: updatedCycle.appointmentsCount,
|
appointmentsCount: updatedCycle.appointmentsCount,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,11 @@ export type RecalculatePlanUsageCycleResult = {
|
|||||||
planId: string;
|
planId: string;
|
||||||
cycleStart: string;
|
cycleStart: string;
|
||||||
cycleEnd: string;
|
cycleEnd: string;
|
||||||
|
organizationsCount: number;
|
||||||
|
employeesCount: number;
|
||||||
|
servicesCount: number;
|
||||||
|
clientsCount: number;
|
||||||
|
repeatsCount: number;
|
||||||
appointmentsCount: number;
|
appointmentsCount: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export const RecalculationToolsModal = ({ initialUserId = '', onClose }: { initi
|
|||||||
<div style={{ background: 'rgba(255,255,255,0.03)', border: '1px solid var(--glass-border)', borderRadius: '12px', padding: '1.25rem' }}>
|
<div style={{ background: 'rgba(255,255,255,0.03)', border: '1px solid var(--glass-border)', borderRadius: '12px', padding: '1.25rem' }}>
|
||||||
<div style={{ marginBottom: '1rem' }}>
|
<div style={{ marginBottom: '1rem' }}>
|
||||||
<h3 style={{ fontSize: '1.1rem', fontWeight: '700', marginBottom: '0.35rem' }}>Recalcular uso del plan</h3>
|
<h3 style={{ fontSize: '1.1rem', fontWeight: '700', marginBottom: '0.35rem' }}>Recalcular uso del plan</h3>
|
||||||
<p style={{ color: 'var(--text-muted)', fontSize: '0.9rem' }}>Recuenta las reservas del ciclo actual para el userId seleccionado.</p>
|
<p style={{ color: 'var(--text-muted)', fontSize: '0.9rem' }}>Recuenta las reservas del ciclo actual y los contadores stock del userId seleccionado.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form onSubmit={(e) => { e.preventDefault(); handleRecalculatePlanUsage(); }} style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap', alignItems: 'flex-end' }}>
|
<form onSubmit={(e) => { e.preventDefault(); handleRecalculatePlanUsage(); }} style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap', alignItems: 'flex-end' }}>
|
||||||
@@ -82,6 +82,11 @@ export const RecalculationToolsModal = ({ initialUserId = '', onClose }: { initi
|
|||||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: '0.75rem' }}>
|
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: '0.75rem' }}>
|
||||||
<div><strong>Cycle Start</strong><br /><span style={{ color: 'var(--text-muted)' }}>{formatDateTime(usageResult.cycleStart)}</span></div>
|
<div><strong>Cycle Start</strong><br /><span style={{ color: 'var(--text-muted)' }}>{formatDateTime(usageResult.cycleStart)}</span></div>
|
||||||
<div><strong>Cycle End</strong><br /><span style={{ color: 'var(--text-muted)' }}>{formatDateTime(usageResult.cycleEnd)}</span></div>
|
<div><strong>Cycle End</strong><br /><span style={{ color: 'var(--text-muted)' }}>{formatDateTime(usageResult.cycleEnd)}</span></div>
|
||||||
|
<div><strong>Organizations</strong><br /><span style={{ color: 'var(--success)', fontWeight: 700 }}>{usageResult.organizationsCount}</span></div>
|
||||||
|
<div><strong>Collaborators</strong><br /><span style={{ color: 'var(--success)', fontWeight: 700 }}>{usageResult.employeesCount}</span></div>
|
||||||
|
<div><strong>Services</strong><br /><span style={{ color: 'var(--success)', fontWeight: 700 }}>{usageResult.servicesCount}</span></div>
|
||||||
|
<div><strong>Clients</strong><br /><span style={{ color: 'var(--success)', fontWeight: 700 }}>{usageResult.clientsCount}</span></div>
|
||||||
|
<div><strong>Repeats</strong><br /><span style={{ color: 'var(--success)', fontWeight: 700 }}>{usageResult.repeatsCount}</span></div>
|
||||||
<div><strong>Appointments</strong><br /><span style={{ color: 'var(--success)', fontWeight: 700 }}>{usageResult.appointmentsCount}</span></div>
|
<div><strong>Appointments</strong><br /><span style={{ color: 'var(--success)', fontWeight: 700 }}>{usageResult.appointmentsCount}</span></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -63,6 +63,11 @@ export type SysAdminRecalculatePlanUsageCycleResult = {
|
|||||||
planId: string;
|
planId: string;
|
||||||
cycleStart: string;
|
cycleStart: string;
|
||||||
cycleEnd: string;
|
cycleEnd: string;
|
||||||
|
organizationsCount: number;
|
||||||
|
employeesCount: number;
|
||||||
|
servicesCount: number;
|
||||||
|
clientsCount: number;
|
||||||
|
repeatsCount: number;
|
||||||
appointmentsCount: number;
|
appointmentsCount: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const getLimitCards = (plan: ISubscriptionInfo["plan"], metrics: DashboardMetric
|
|||||||
{ label: "Organizaciones", limit: plan.limitOrganizations, current: metrics?.organizationsCount },
|
{ label: "Organizaciones", limit: plan.limitOrganizations, current: metrics?.organizationsCount },
|
||||||
{ label: "Colaboradores", limit: plan.limitEmployees, current: metrics?.employeesCount },
|
{ label: "Colaboradores", limit: plan.limitEmployees, current: metrics?.employeesCount },
|
||||||
{ label: "Servicios", limit: plan.limitServices, current: metrics?.servicesCount },
|
{ label: "Servicios", limit: plan.limitServices, current: metrics?.servicesCount },
|
||||||
{ label: "Turnos", limit: plan.limitAppointments, current: metrics?.appointmentsCount },
|
{ label: "Turnos del último mes", limit: plan.limitAppointments, current: metrics?.appointmentsCount },
|
||||||
{ label: "Clientes", limit: plan.limitClients, current: metrics?.clientsCount },
|
{ label: "Clientes", limit: plan.limitClients, current: metrics?.clientsCount },
|
||||||
{ label: "Repeticiones", limit: plan.limitRepeats, current: metrics?.repeatsCount },
|
{ label: "Repeticiones", limit: plan.limitRepeats, current: metrics?.repeatsCount },
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user