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>
30 lines
1.2 KiB
TypeScript
30 lines
1.2 KiB
TypeScript
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
import { api } from '../lib/api';
|
|
|
|
interface InvoicePayload { uuid: string; status: string }
|
|
|
|
/**
|
|
* صدور فاکتور یک مراجعه: ساخت idempotent (`POST /billing/invoices`) و سپس
|
|
* نهاییسازی draft. خروجی mutation، uuid فاکتور است تا caller مودال «خلاصه
|
|
* فاکتور» را باز کند. با recordUuid، لیست sessions همان بیمار invalidate
|
|
* میشود تا invoice_uuid کارتها بهروز شود.
|
|
*/
|
|
export function useIssueInvoice(recordUuid?: string) {
|
|
const qc = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: async (sessionUuid: string): Promise<string> => {
|
|
const res = await api.post<any>('/api/v1/billing/invoices', { session_uuid: sessionUuid });
|
|
const invoice = ((res as any)?.data?.data ?? (res as any)?.data) as InvoicePayload;
|
|
if (invoice.status === 'draft') {
|
|
await api.post(`/api/v1/billing/invoices/${invoice.uuid}/finalize`, {});
|
|
}
|
|
return invoice.uuid;
|
|
},
|
|
onSuccess: () => {
|
|
if (recordUuid) qc.invalidateQueries({ queryKey: ['patient-sessions', recordUuid] });
|
|
qc.invalidateQueries({ queryKey: ['invoice'] });
|
|
},
|
|
});
|
|
}
|