Puntos 16 y 10: modulo de paquetes de sesiones (catalogo, saldo por paciente, descuento en agenda, venta en POS) + fix de auditoria silenciosa

This commit is contained in:
2026-09-24 17:17:29 +00:00
parent 09b4f25bb8
commit dcf2c367f1
18 changed files with 1892 additions and 17 deletions

View File

@@ -543,6 +543,8 @@ export interface LastSaleResponse {
}
export interface PatientPackage {
id?: number | null;
compra?: boolean;
service_id: number;
name: string;
package_sessions: number;
@@ -550,6 +552,74 @@ export interface PatientPackage {
used: number;
remaining: number;
next_date: string | null;
state?: string;
}
// ---------- Paquetes de sesiones ----------
export interface Paquete {
id: number;
name: string;
code: string;
service_id: number | null;
service: string;
sessions: number;
price: number;
price_per_session: number;
session_price: number;
duration_min: number;
validity_days: number;
notes: string;
color: string;
genera_monedero: boolean;
active: boolean;
sequence: number;
compras_count: number;
}
export interface PaqueteCompra {
id: number;
date: string | null;
patient_id: number;
patient: string;
phone: string;
paquete_id: number | null;
paquete: string;
service_id: number | null;
service: string;
sessions_total: number;
sessions_used: number;
sessions_remaining: number;
price: number;
expiry_date: string | null;
state: 'active' | 'finished' | 'expired' | 'cancelled';
venta_id: number | null;
venta: string;
user_login: string;
}
export interface PaqueteConsumo {
id: number;
date: string | null;
state: string;
cita_id: number | null;
cita_fecha: string | null;
cita_hora: string;
doctor: string;
estado_cita: string;
}
export interface PaquetePayload {
name?: string;
code?: string;
service_id?: number;
sessions?: number;
price?: number;
duration_min?: number;
validity_days?: number;
notes?: string;
color?: string;
genera_monedero?: boolean;
active?: boolean;
}
export interface MySaleItem {
@@ -1115,7 +1185,7 @@ export interface AppNotification {
export interface PosCheckoutPayload {
partner_id: number;
lines: { service_id?: number; item_id?: number; quantity: number; price_unit: number; description?: string; prescribed_by_id?: number }[];
lines: { service_id?: number; item_id?: number; paquete_id?: number; quantity: number; price_unit: number; description?: string; prescribed_by_id?: number }[];
discount?: number;
payment_method?: string;
amount_received?: number;
@@ -1975,6 +2045,60 @@ export const odooApi = {
return data;
},
// ---------- Paquetes de sesiones (catálogo y saldos) ----------
async getPaqueteCatalogo(params?: { search?: string; includeInactive?: boolean }): Promise<{ status: string; paquetes: Paquete[] }> {
const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/paquetes`, {
params: {
search: params?.search || undefined,
include_inactive: params?.includeInactive ? '1' : undefined,
},
});
return data;
},
async createPaquete(payload: PaquetePayload): Promise<{ status: string; paquete: Paquete; message?: string }> {
const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/paquetes`, payload);
return data;
},
async updatePaquete(id: number, payload: PaquetePayload): Promise<{ status: string; paquete: Paquete; message?: string }> {
const { data } = await axios.put(`${ODOO_BASE}/skeen/frontend/v1/paquetes/${id}`, payload);
return data;
},
async getPaqueteCompras(params?: {
patient_id?: number; state?: string; search?: string; doctor_id?: number;
start?: string; end?: string; includeAll?: boolean;
}): Promise<{ status: string; compras: PaqueteCompra[]; totales: Record<string, number> }> {
const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/paquetes/compras`, {
params: {
patient_id: params?.patient_id || undefined,
state: params?.state || undefined,
search: params?.search || undefined,
doctor_id: params?.doctor_id || undefined,
start: params?.start || undefined,
end: params?.end || undefined,
include_all: params?.includeAll ? '1' : undefined,
},
});
return data;
},
async getPaqueteConsumos(id: number): Promise<{ status: string; compra: PaqueteCompra; consumos: PaqueteConsumo[]; message?: string }> {
const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/paquetes/compras/${id}/consumos`);
return data;
},
async ajustarPaqueteCompra(id: number, payload: { sessions_total?: number; sessions_used?: number }): Promise<{ status: string; compra: PaqueteCompra; message?: string }> {
const { data } = await axios.put(`${ODOO_BASE}/skeen/frontend/v1/paquetes/compras/${id}`, payload);
return data;
},
async anularPaqueteCompra(id: number, reason: string): Promise<{ status: string; compra: PaqueteCompra; message?: string }> {
const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/paquetes/compras/${id}/anular`, { reason });
return data;
},
async getCashReportRange(start: string, end: string): Promise<{ status: string; total: number; by_method: Record<string, number> }> {
const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/cash`, { params: { start, end } });
return data;