fix: issue invoice on demand so view-invoice buttons actually work
The admin SPA never called POST /billing/invoices, so every session had invoice_uuid = null and the view-invoice buttons on the patient services tab (and MyPatients visit modal) were permanently disabled. Add a shared useIssueInvoice hook (idempotent create + finalize when draft) and wire it into: - DetailsStep: the wizard's final step now really issues the invoice - SessionServiceCard / PatientDetailPage: clicking view-invoice on a session without an invoice issues it first, then opens the summary - MyPatientsPage visit modal: same, replacing the dead disabled button Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,7 @@ import ConfirmDialog from '../components/ui/ConfirmDialog';
|
||||
import PersianDateInput from '../components/ui/PersianDateInput';
|
||||
import PatientCaseBanner, { Breadcrumb } from '../components/PatientCaseBanner';
|
||||
import SessionServiceCard, { type SessionCardData } from '../components/SessionServiceCard';
|
||||
import { useIssueInvoice } from '../hooks/useIssueInvoice';
|
||||
import AppointmentTurnCard, { type AppointmentCardData } from '../components/AppointmentTurnCard';
|
||||
import SessionPaymentAccordion, { type SessionPaymentData } from '../components/SessionPaymentAccordion';
|
||||
import InvoiceSummaryModal from '../components/InvoiceSummaryModal';
|
||||
@@ -81,6 +82,16 @@ export default function PatientDetailPage() {
|
||||
const nav = useNavigate();
|
||||
const [invoiceUuid, setInvoiceUuid] = useState<string | null>(null);
|
||||
|
||||
// «مشاهده فاکتور»: اگر session هنوز فاکتور ندارد، اول صادر میشود (idempotent).
|
||||
const issueInvoiceMut = useIssueInvoice(uuid);
|
||||
const viewInvoice = (s: SessionCardData) => {
|
||||
if (s.invoice_uuid) { setInvoiceUuid(s.invoice_uuid); return; }
|
||||
issueInvoiceMut.mutate(s.uuid, {
|
||||
onSuccess: (iv) => setInvoiceUuid(iv),
|
||||
onError: () => toast.error('صدور فاکتور ناموفق بود'),
|
||||
});
|
||||
};
|
||||
|
||||
// ── فرم «اطلاعات پرونده» (اینلاین، معادل tauri FileInfoSection) ──────────────
|
||||
// استان/شهر (Location) و بیمهٔ پایه (insurance-pricing) برای گزینههای فرم.
|
||||
const [editProvinceId, setEditProvinceId] = useState<number | null>(null);
|
||||
@@ -217,7 +228,7 @@ export default function PatientDetailPage() {
|
||||
) : (
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(240px, 1fr))', columnGap: 6, rowGap: 10, alignItems: 'stretch' }}>
|
||||
{sessions.map((s) => (
|
||||
<SessionServiceCard key={s.uuid} session={s} onSettle={(u) => nav(`/admin/patients/${uuid}/session/${u}/pay`)} onViewInvoice={(iv) => setInvoiceUuid(iv)} />
|
||||
<SessionServiceCard key={s.uuid} session={s} onSettle={(u) => nav(`/admin/patients/${uuid}/session/${u}/pay`)} onViewInvoice={viewInvoice} issuing={issueInvoiceMut.isPending} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user