POS: boton Cobrar desde cita (precarga paciente/servicio/doctor) y ticket termico imprimible con reimpresion en Ventas

This commit is contained in:
2026-09-01 22:39:26 +00:00
parent 2710d9d92d
commit f0d7ac4c01
5 changed files with 296 additions and 72 deletions

View File

@@ -1,8 +1,9 @@
import type { FC } from 'react';
import { useEffect, useState, useCallback } from 'react';
import { Plus, Trash2, CreditCard, ShoppingCart, Search, Undo2, Download } from 'lucide-react';
import { Plus, Trash2, CreditCard, ShoppingCart, Search, Undo2, Download, Printer } from 'lucide-react';
import Layout from '../components/Layout';
import { usePatientDrawer } from '../components/PatientDrawer';
import TicketPrint from '../components/TicketPrint';
import {
Card,
Button,
@@ -59,6 +60,8 @@ const Ventas: FC = () => {
const [refunding, setRefunding] = useState(false);
const [refundAmount, setRefundAmount] = useState('');
const [refundReason, setRefundReason] = useState('');
// Reimprimir ticket de una venta ya registrada
const [printSale, setPrintSale] = useState<Sale | null>(null);
const [search, setSearch] = useState('');
const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(50);
@@ -378,6 +381,9 @@ const Ventas: FC = () => {
</td>
<td className="p-3">
<div className="flex items-center gap-1">
<Button variant="ghost" size="sm" onClick={() => setPrintSale(s)} title="Reimprimir ticket">
<Printer size={16} className="text-theme-heading" />
</Button>
{s.amount_due > 0 && (
<Button variant="ghost" size="sm" onClick={() => openPay(s)} title="Pagar">
<CreditCard size={16} className="text-theme-heading mr-1.5" />
@@ -428,6 +434,9 @@ const Ventas: FC = () => {
]}
actions={
<div className="flex items-center gap-1">
<Button variant="ghost" size="sm" onClick={() => setPrintSale(s)} title="Reimprimir ticket">
<Printer size={16} className="text-theme-heading" />
</Button>
{s.amount_due > 0 && (
<Button variant="ghost" size="sm" onClick={() => openPay(s)}>
<CreditCard size={16} className="text-theme-heading" />
@@ -665,6 +674,28 @@ const Ventas: FC = () => {
</div>
)}
</Modal>
{/* Reimprimir ticket de la venta (formato térmico ~80mm) */}
<TicketPrint
isOpen={!!printSale}
onClose={() => setPrintSale(null)}
ticket={printSale && {
folio: printSale.name,
fecha: printSale.date,
paciente: printSale.patient,
lines: printSale.lines.map((l) => ({
name: l.service || l.item || l.description,
qty: l.quantity,
price: l.price_unit,
subtotal: l.subtotal,
})),
subtotal: printSale.subtotal,
discount: printSale.discount,
total: printSale.total,
amount_paid: printSale.amount_paid,
amount_due: printSale.amount_due,
}}
/>
</Layout>
);
};