112 lines
4.0 KiB
TypeScript
112 lines
4.0 KiB
TypeScript
import { useQuery } from '@tanstack/react-query';
|
|
import { api } from '../lib/api';
|
|
import type { ApiResponse, PaginatedResponse } from '../lib/api';
|
|
|
|
/**
|
|
* وضعیت پرداخت صورتحساب — مشتق از مجموع پرداختهای مراجعه در برابر سهم بیمار،
|
|
* نه ستون `invoices.status` (که فقط چرخهی حیات را نگه میدارد).
|
|
*/
|
|
export type PaymentRowStatus = 'paid' | 'partial' | 'unsettled';
|
|
|
|
/** One recorded invoice on the flat payments list (node 1). */
|
|
export interface PaymentRow {
|
|
invoice_uuid: string;
|
|
patient_uuid: string;
|
|
patient_name: string | null;
|
|
national_code: string | null;
|
|
issued_at: number;
|
|
amount_rials: number;
|
|
paid_rials: number;
|
|
status: PaymentRowStatus;
|
|
}
|
|
|
|
export interface PaymentFilters {
|
|
page: number;
|
|
national_code?: string;
|
|
status?: string; // paid | partial | unsettled
|
|
from?: number; // unix seconds
|
|
to?: number; // unix seconds
|
|
}
|
|
|
|
/** همان وضعیت مشتقشده، روی جدول جزئیات بیمار (node 2). */
|
|
export type InvoiceRowStatus = PaymentRowStatus;
|
|
|
|
export interface PatientInvoiceRow {
|
|
uuid: string;
|
|
number: number;
|
|
issued_at: number;
|
|
total_rials: number;
|
|
patient_rials: number;
|
|
paid_rials: number;
|
|
status: InvoiceRowStatus;
|
|
service_title: string | null;
|
|
items: Array<{ uuid: string; title: string; quantity: number; total_rials: number; patient_rials: number }>;
|
|
payments: InvoicePaymentRow[];
|
|
}
|
|
|
|
/** یک پرداخت ثبتشده روی مراجعهی همان صورتحساب. */
|
|
export interface InvoicePaymentRow {
|
|
method: string;
|
|
amount_rials: number;
|
|
paid_at: number;
|
|
created_by_name: string | null;
|
|
}
|
|
|
|
export interface PatientInvoicesPayload {
|
|
patient: { uuid: string; name: string | null; national_code: string | null };
|
|
data: PatientInvoiceRow[];
|
|
summary: PaymentsSummary;
|
|
meta: { totalRecords: number; totalPages: number; currentPage: number };
|
|
}
|
|
|
|
const LIMIT = 20;
|
|
|
|
/** Node 1 — flat, paginated list of the current tenant's recorded invoices. */
|
|
export function usePayments(filters: PaymentFilters) {
|
|
const qs = new URLSearchParams({ page: String(filters.page), limit: String(LIMIT) });
|
|
if (filters.national_code) qs.set('national_code', filters.national_code);
|
|
if (filters.status) qs.set('status', filters.status);
|
|
if (filters.from) qs.set('from', String(filters.from));
|
|
if (filters.to) qs.set('to', String(filters.to));
|
|
|
|
return useQuery<PaginatedResponse<PaymentRow>>({
|
|
queryKey: ['payments', filters],
|
|
queryFn: () => api.get(`/api/v1/my/billing/payments?${qs.toString()}`),
|
|
// ورود دوباره به صفحه همیشه داده را تازه میکند (پرداختها لحظهای عوض میشوند).
|
|
refetchOnMount: 'always',
|
|
});
|
|
}
|
|
|
|
export interface PaymentsSummary {
|
|
total_rials: number;
|
|
paid_rials: number;
|
|
unsettled_rials: number;
|
|
invoices_count: number;
|
|
}
|
|
|
|
/** Summary over the same filters as the list, so the stat cards match the table. */
|
|
export function usePaymentsSummary(filters: Omit<PaymentFilters, 'page'>) {
|
|
const qs = new URLSearchParams();
|
|
if (filters.national_code) qs.set('national_code', filters.national_code);
|
|
if (filters.status) qs.set('status', filters.status);
|
|
if (filters.from) qs.set('from', String(filters.from));
|
|
if (filters.to) qs.set('to', String(filters.to));
|
|
|
|
return useQuery<ApiResponse<PaymentsSummary>>({
|
|
queryKey: ['payments-summary', filters],
|
|
queryFn: () => api.get(`/api/v1/my/billing/payments/summary?${qs.toString()}`),
|
|
refetchOnMount: 'always',
|
|
});
|
|
}
|
|
|
|
/** Node 2 — a single patient's recorded invoices (header + paginated list). */
|
|
export function usePatientInvoices(patientUuid: string | undefined, page: number) {
|
|
return useQuery<ApiResponse<PatientInvoicesPayload>>({
|
|
queryKey: ['patient-invoices', patientUuid, page],
|
|
queryFn: () => api.get(`/api/v1/my/billing/patients/${patientUuid}/invoices?page=${page}&limit=${LIMIT}`),
|
|
enabled: !!patientUuid,
|
|
});
|
|
}
|
|
|
|
export const MY_PAYMENTS_LIMIT = LIMIT;
|