Oleada UX 4: Pagos/Adeudos (cobro en 1 click con recibo, plan de pagos), Monedero (movimientos narrados, ajustes auditados, MXN+USD), Inventario (alta rapida, conteo fisico con ajuste e historial, alertas accionables) + fix de folios de pago y cantidades de movimientos
This commit is contained in:
@@ -679,6 +679,85 @@ export interface AdeudoRow {
|
||||
num_ventas: number;
|
||||
total_adeudo: number;
|
||||
ultima_venta: string | null;
|
||||
plan?: PaymentPlan | null;
|
||||
}
|
||||
|
||||
export interface PaymentPlan {
|
||||
count: number;
|
||||
amount: number;
|
||||
next_payment_date: string | null;
|
||||
note: string;
|
||||
start: string | null;
|
||||
by: string;
|
||||
paid_count: number;
|
||||
remaining_count: number;
|
||||
}
|
||||
|
||||
export interface ReceiptApplied {
|
||||
id: number;
|
||||
name: string;
|
||||
date: string | null;
|
||||
applied: number;
|
||||
total: number;
|
||||
state: string;
|
||||
amount_due: number;
|
||||
}
|
||||
|
||||
export interface ReceiptData {
|
||||
folio: string;
|
||||
date: string;
|
||||
patient_id: number;
|
||||
patient: string;
|
||||
patient_code: string;
|
||||
phone: string;
|
||||
amount: number;
|
||||
payment_method: string;
|
||||
adeudo_anterior: number;
|
||||
saldo_restante: number;
|
||||
aplicado: ReceiptApplied[];
|
||||
operator: string;
|
||||
wallet_points: number;
|
||||
}
|
||||
|
||||
export type WalletTxType = 'accrual' | 'redemption' | 'adjustment' | 'expiration';
|
||||
|
||||
export interface WalletTransaction {
|
||||
id: number;
|
||||
type: WalletTxType;
|
||||
type_label: string;
|
||||
points: number;
|
||||
narration: string;
|
||||
description: string;
|
||||
reference: string;
|
||||
operator: string;
|
||||
date: string | null;
|
||||
}
|
||||
|
||||
export interface InventoryConteoLine {
|
||||
id: number;
|
||||
item_id: number;
|
||||
item: string;
|
||||
unit: string;
|
||||
qty_sistema: number;
|
||||
qty_contado: number;
|
||||
difference: number;
|
||||
cost: number;
|
||||
value_diff: number;
|
||||
move_id: number | null;
|
||||
}
|
||||
|
||||
export interface InventoryConteo {
|
||||
id: number;
|
||||
name: string;
|
||||
date: string | null;
|
||||
user_name: string;
|
||||
notes: string;
|
||||
total_items: number;
|
||||
total_diferencias: number;
|
||||
total_faltante: number;
|
||||
total_sobrante: number;
|
||||
total_value_diff: number;
|
||||
lines?: InventoryConteoLine[];
|
||||
}
|
||||
|
||||
export interface ComisionRow {
|
||||
@@ -1261,6 +1340,17 @@ export const odooApi = {
|
||||
return data;
|
||||
},
|
||||
|
||||
// Cobro del adeudo del paciente (parcial o total) + plan de pagos
|
||||
async payAdeudo(patientId: number, payload: { amount: number; payment_method: string }): Promise<{ status: string; payment: Payment; receipt: ReceiptData }> {
|
||||
const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/patients/${patientId}/pay_adeudo`, payload);
|
||||
return data;
|
||||
},
|
||||
|
||||
async setPaymentPlan(patientId: number, payload: { count: number; amount: number; next_payment_date?: string | null; note?: string }): Promise<{ status: string; plan: PaymentPlan }> {
|
||||
const { data } = await axios.put(`${ODOO_BASE}/skeen/frontend/v1/patients/${patientId}/payment_plan`, payload);
|
||||
return data;
|
||||
},
|
||||
|
||||
// Servicios
|
||||
async getServices(params?: { search?: string; category?: string; page?: number; page_size?: number }): Promise<{ status: string; services: Service[]; total?: number; page?: number; total_pages?: number }> {
|
||||
const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/services`, { params });
|
||||
@@ -1347,6 +1437,18 @@ export const odooApi = {
|
||||
return data;
|
||||
},
|
||||
|
||||
// Movimientos del monedero con narración legible
|
||||
async getWalletTransactions(walletId: number, params?: { type?: string; date_from?: string; date_to?: string }): Promise<{ status: string; wallet: Wallet; movimientos: WalletTransaction[]; total: number; sum_positive: number; sum_negative: number }> {
|
||||
const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/wallets/${walletId}/transactions`, { params: params || {} });
|
||||
return data;
|
||||
},
|
||||
|
||||
// Ajuste manual auditado de puntos (admin/gerencia)
|
||||
async adjustWallet(walletId: number, payload: { points: number; reason: string }): Promise<{ status: string; wallet: Wallet; applied: number; movimiento: { id: number; points: number; date: string; operator: string; narration: string } }> {
|
||||
const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/wallets/${walletId}/adjust`, payload);
|
||||
return data;
|
||||
},
|
||||
|
||||
// Pagos
|
||||
async getPayments(state?: string): Promise<{ status: string; payments: Payment[] }> {
|
||||
const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/payments`, { params: state ? { state } : {} });
|
||||
@@ -1487,6 +1589,22 @@ export const odooApi = {
|
||||
return data;
|
||||
},
|
||||
|
||||
// Conteo físico cíclico de inventario
|
||||
async getConteos(limit = 30): Promise<{ status: string; conteos: InventoryConteo[] }> {
|
||||
const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/inventario/conteos`, { params: { limit } });
|
||||
return data;
|
||||
},
|
||||
|
||||
async getConteo(id: number): Promise<{ status: string; conteo: InventoryConteo }> {
|
||||
const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/inventario/conteos/${id}`);
|
||||
return data;
|
||||
},
|
||||
|
||||
async createConteo(payload: { notes?: string; lines: { item_id: number; qty_contado: number }[] }): Promise<{ status: string; conteo: InventoryConteo; ajustes: number }> {
|
||||
const { data } = await axios.post(`${ODOO_BASE}/skeen/frontend/v1/inventario/conteos`, payload);
|
||||
return data;
|
||||
},
|
||||
|
||||
async getHorasAgenda(start?: string, end?: string): Promise<{ status: string; horas: HoraAgendaRow[] }> {
|
||||
const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/horas-agenda`, { params: { start, end } });
|
||||
return data;
|
||||
|
||||
Reference in New Issue
Block a user