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:
@@ -1,12 +1,16 @@
|
||||
import { toast } from 'sonner';
|
||||
import { formatRial } from '../../lib/utils';
|
||||
import type { SessionCardData } from '../SessionServiceCard';
|
||||
import { METHOD_LABELS } from './PaymentStep';
|
||||
import { useIssueInvoice } from '../../hooks/useIssueInvoice';
|
||||
|
||||
const primaryBtn: React.CSSProperties = { background: '#5559CE', color: '#fff', border: 'none', borderRadius: 4, height: 46, fontSize: 14, fontWeight: 500, cursor: 'pointer' };
|
||||
const ghostBtn: React.CSSProperties = { background: 'transparent', color: '#5559CE', border: '1px solid #5559CE', borderRadius: 4, height: 46, fontSize: 14, fontWeight: 500, cursor: 'pointer' };
|
||||
|
||||
interface Props {
|
||||
session: SessionCardData;
|
||||
/** برای invalidate شدن لیست sessions بعد از صدور فاکتور. */
|
||||
recordUuid?: string;
|
||||
onBack: () => void;
|
||||
onFinish: () => void;
|
||||
}
|
||||
@@ -15,8 +19,17 @@ interface Props {
|
||||
* گام «جزییات» — پورت tauri Step3Final با دیتای واقعی:
|
||||
* خلاصهی سرویس/هزینه/تخفیف + لیست پرداختشدهها + مانده. مشترک بین
|
||||
* NewSessionPage (ویزارد سهگامه) و SessionPaymentPage (دوگامه).
|
||||
* «صدور فاکتور» فاکتور را واقعاً صادر میکند (create + finalize) و بعد onFinish.
|
||||
*/
|
||||
export default function DetailsStep({ session, onBack, onFinish }: Props) {
|
||||
export default function DetailsStep({ session, recordUuid, onBack, onFinish }: Props) {
|
||||
const issueMut = useIssueInvoice(recordUuid);
|
||||
const issue = () => {
|
||||
if (session.invoice_uuid) { onFinish(); return; }
|
||||
issueMut.mutate(session.uuid, {
|
||||
onSuccess: () => onFinish(),
|
||||
onError: () => toast.error('صدور فاکتور ناموفق بود'),
|
||||
});
|
||||
};
|
||||
const finalPrice = session.final_price_rials ?? 0;
|
||||
const discountRials = session.discount_rials ?? 0;
|
||||
const debt = session.patient_debt_rials ?? 0;
|
||||
@@ -71,7 +84,9 @@ export default function DetailsStep({ session, onBack, onFinish }: Props) {
|
||||
|
||||
<div style={{ display: 'flex', gap: 8, marginTop: 16, width: '100%', maxWidth: 320, margin: '16px auto 0' }}>
|
||||
<button type="button" style={{ ...ghostBtn, flex: 1 }} onClick={onBack}>انصراف</button>
|
||||
<button type="button" style={{ ...primaryBtn, flex: 1 }} onClick={onFinish}>صدور فاکتور</button>
|
||||
<button type="button" disabled={issueMut.isPending} style={{ ...primaryBtn, flex: 1 }} onClick={issue}>
|
||||
{issueMut.isPending ? 'در حال صدور…' : 'صدور فاکتور'}
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user