fase 2.2: impuestos configurables por instancia (tasa por servicio/articulo, calculo por linea, desglose en POS/tickets/estado de cuenta, reporte de impuestos, permiso ventas.impuestos) con defaults apagados
This commit is contained in:
@@ -316,6 +316,9 @@ export interface Service {
|
||||
sequence?: number;
|
||||
sold_90d?: number | null;
|
||||
genera_monedero?: boolean;
|
||||
/** Impuesto propio del servicio (%) y si usa la tasa por defecto de la config */
|
||||
tax_rate?: number;
|
||||
tax_use_default?: boolean;
|
||||
}
|
||||
|
||||
export interface ImpactSimulationDoctor {
|
||||
@@ -476,6 +479,9 @@ export interface SaleLine {
|
||||
quantity: number;
|
||||
price_unit: number;
|
||||
subtotal: number;
|
||||
/** Tasa (%) e importe del impuesto de la línea (0 con impuestos apagados) */
|
||||
tax_rate?: number;
|
||||
tax_amount?: number;
|
||||
is_prescribed?: boolean;
|
||||
prescribed_by_id?: number | null;
|
||||
prescribed_by?: string | null;
|
||||
@@ -531,6 +537,9 @@ export interface Sale {
|
||||
subtotal: number;
|
||||
discount: number;
|
||||
tax: number;
|
||||
/** Impuesto sumado de las líneas y base sin impuesto (0 = sin impuestos) */
|
||||
tax_total?: number;
|
||||
subtotal_sin_impuesto?: number;
|
||||
total: number;
|
||||
amount_paid: number;
|
||||
amount_due: number;
|
||||
@@ -757,6 +766,9 @@ export interface InventoryItem {
|
||||
last_count_date: string | null;
|
||||
active: boolean;
|
||||
genera_monedero?: boolean;
|
||||
/** Impuesto propio del artículo (%) y si usa la tasa por defecto */
|
||||
tax_rate?: number;
|
||||
tax_use_default?: boolean;
|
||||
notes: string;
|
||||
stock_level: InventoryLevel;
|
||||
}
|
||||
@@ -963,6 +975,27 @@ export interface ServiceCategory {
|
||||
}
|
||||
|
||||
// ---- Ajustes de la clínica ----
|
||||
export interface ImpuestosSettings {
|
||||
/** Enciende el cálculo del impuesto en POS, tickets y reportes */
|
||||
activo: boolean;
|
||||
/** Etiqueta del impuesto (p. ej. 'IVA') */
|
||||
nombre: string;
|
||||
/** % aplicado cuando el catálogo no fija uno */
|
||||
tasa_default: number;
|
||||
/** El precio capturado ya trae impuesto: el subtotal se desglosa hacia atrás */
|
||||
precios_incluyen_impuesto: boolean;
|
||||
/** Tasas ofrecidas en los formularios (%) */
|
||||
tasa_opciones: number[];
|
||||
}
|
||||
|
||||
export const IMPUESTOS_DEFAULT: ImpuestosSettings = {
|
||||
activo: false,
|
||||
nombre: 'IVA',
|
||||
tasa_default: 0,
|
||||
precios_incluyen_impuesto: false,
|
||||
tasa_opciones: [0, 8, 16],
|
||||
};
|
||||
|
||||
export interface ClinicSettings {
|
||||
nombre: string;
|
||||
telefono: string;
|
||||
@@ -976,6 +1009,7 @@ export interface ClinicSettings {
|
||||
url_publica: string;
|
||||
moneda_base: string;
|
||||
nota_ticket: string;
|
||||
impuestos: ImpuestosSettings;
|
||||
}
|
||||
|
||||
export const CLINIC_SETTINGS_DEFAULT: ClinicSettings = {
|
||||
@@ -991,6 +1025,7 @@ export const CLINIC_SETTINGS_DEFAULT: ClinicSettings = {
|
||||
url_publica: '',
|
||||
moneda_base: 'MXN',
|
||||
nota_ticket: '',
|
||||
impuestos: IMPUESTOS_DEFAULT,
|
||||
};
|
||||
|
||||
export interface FrontendUser {
|
||||
@@ -1407,18 +1442,39 @@ export interface AppNotification {
|
||||
|
||||
export interface PosCheckoutPayload {
|
||||
partner_id: number;
|
||||
lines: { service_id?: number; item_id?: number; paquete_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; tax_rate?: number }[];
|
||||
discount?: number;
|
||||
/** Tasa de impuesto a nivel venta (opcional); cada línea puede traer la suya */
|
||||
tax_rate?: number;
|
||||
payment_method?: string;
|
||||
amount_received?: number;
|
||||
pay_with_points?: boolean;
|
||||
currency?: 'MXN' | 'USD';
|
||||
}
|
||||
|
||||
export interface ImpuestosDesglose {
|
||||
activo: boolean;
|
||||
nombre: string;
|
||||
incluido: boolean;
|
||||
subtotal: number;
|
||||
descuento: number;
|
||||
impuesto: number;
|
||||
total: number;
|
||||
subtotal_usd?: number;
|
||||
impuesto_usd?: number;
|
||||
total_usd?: number;
|
||||
}
|
||||
|
||||
export interface PosCheckoutResult {
|
||||
status: string;
|
||||
sale: Sale;
|
||||
payment: Payment | null;
|
||||
/** Desglose de la venta (subtotal, descuento, impuesto, total) */
|
||||
subtotal?: number;
|
||||
descuento?: number;
|
||||
impuesto?: number;
|
||||
total?: number;
|
||||
impuestos?: ImpuestosDesglose;
|
||||
cambio: number;
|
||||
/** Efectivo recibido en caja (MXN), para imprimir "Recibido" en el ticket */
|
||||
recibido?: number;
|
||||
@@ -1446,6 +1502,42 @@ export interface InventoryReportSummary {
|
||||
critical: number;
|
||||
}
|
||||
|
||||
// ---- Reporte de impuestos ----
|
||||
export interface TaxMonthRow {
|
||||
mes: string;
|
||||
base: number;
|
||||
impuesto: number;
|
||||
ventas: number;
|
||||
}
|
||||
|
||||
export interface TaxServiceRow {
|
||||
servicio: string;
|
||||
base: number;
|
||||
impuesto: number;
|
||||
cantidad: number;
|
||||
}
|
||||
|
||||
export interface TaxBranchRow {
|
||||
sucursal: string;
|
||||
base: number;
|
||||
impuesto: number;
|
||||
}
|
||||
|
||||
export interface TaxReportResult {
|
||||
status: string;
|
||||
start: string;
|
||||
end: string;
|
||||
activo: boolean;
|
||||
nombre: string;
|
||||
incluido: boolean;
|
||||
total_base: number;
|
||||
total_impuesto: number;
|
||||
total: number;
|
||||
por_mes: TaxMonthRow[];
|
||||
por_servicio: TaxServiceRow[];
|
||||
por_sucursal: TaxBranchRow[];
|
||||
}
|
||||
|
||||
export interface ApiResponse<T> {
|
||||
status: string;
|
||||
message?: string;
|
||||
@@ -2517,6 +2609,11 @@ export const odooApi = {
|
||||
return data;
|
||||
},
|
||||
|
||||
async getTaxReport(start?: string, end?: string): Promise<TaxReportResult> {
|
||||
const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/taxes`, { params: { start, end } });
|
||||
return data;
|
||||
},
|
||||
|
||||
// Tipo de cambio
|
||||
async getExchangeRate(): Promise<{ status: string; current: { rate: number; date: string; source: string } | null; history: { id: number; date: string; rate: number; source: string }[] }> {
|
||||
const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/exchange_rate`);
|
||||
|
||||
Reference in New Issue
Block a user