diff --git a/assets/admin/hooks/useMyPayments.test.tsx b/assets/admin/hooks/useMyPayments.test.tsx index e2b2c5cc..a74edc92 100644 --- a/assets/admin/hooks/useMyPayments.test.tsx +++ b/assets/admin/hooks/useMyPayments.test.tsx @@ -9,7 +9,7 @@ vi.mock('../lib/api', () => ({ })); import { api } from '../lib/api'; -import { usePatientPayments, usePatientInvoices } from './useMyPayments'; +import { usePayments, usePatientInvoices } from './useMyPayments'; const get = api.get as ReturnType; @@ -25,10 +25,10 @@ beforeEach(() => { describe('useMyPayments', () => { it('builds the list URL with all active filters', async () => { - renderHook(() => usePatientPayments({ page: 2, national_code: '1744', status: 'paid', from: 100, to: 200 }), { wrapper }); + renderHook(() => usePayments({ page: 2, national_code: '1744', status: 'paid', from: 100, to: 200 }), { wrapper }); await waitFor(() => expect(get).toHaveBeenCalled()); const url = get.mock.calls[0][0] as string; - expect(url).toContain('/api/v1/my/billing/patient-payments?'); + expect(url).toContain('/api/v1/my/billing/payments?'); expect(url).toContain('page=2'); expect(url).toContain('national_code=1744'); expect(url).toContain('status=paid'); @@ -37,7 +37,7 @@ describe('useMyPayments', () => { }); it('omits empty filters from the list URL', async () => { - renderHook(() => usePatientPayments({ page: 1 }), { wrapper }); + renderHook(() => usePayments({ page: 1 }), { wrapper }); await waitFor(() => expect(get).toHaveBeenCalled()); const url = get.mock.calls[0][0] as string; expect(url).not.toContain('national_code='); diff --git a/assets/admin/hooks/useMyPayments.ts b/assets/admin/hooks/useMyPayments.ts index 0475a105..63b327d1 100644 --- a/assets/admin/hooks/useMyPayments.ts +++ b/assets/admin/hooks/useMyPayments.ts @@ -2,23 +2,24 @@ import { useQuery } from '@tanstack/react-query'; import { api } from '../lib/api'; import type { ApiResponse, PaginatedResponse } from '../lib/api'; -/** A derived per-patient payment status shown on the list (node 1). */ -export type PaymentRowStatus = 'paid' | 'unpaid' | 'unsettled'; +/** Two-state invoice status shown on both the list (node 1) and detail (node 2). */ +export type PaymentRowStatus = 'paid' | 'unsettled'; -export interface PatientPaymentRow { +/** 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; - invoice_count: number; - paid_rials: number; - remaining_rials: number; + issued_at: number; + amount_rials: number; status: PaymentRowStatus; } -export interface PatientPaymentFilters { +export interface PaymentFilters { page: number; national_code?: string; - status?: string; // paid | unsettled | unpaid + status?: string; // paid | unsettled from?: number; // unix seconds to?: number; // unix seconds } @@ -44,17 +45,17 @@ export interface PatientInvoicesPayload { const LIMIT = 20; -/** Node 1 — paginated per-patient payment summary for the current tenant. */ -export function usePatientPayments(filters: PatientPaymentFilters) { +/** 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>({ - queryKey: ['patient-payments', filters], - queryFn: () => api.get(`/api/v1/my/billing/patient-payments?${qs.toString()}`), + return useQuery>({ + queryKey: ['payments', filters], + queryFn: () => api.get(`/api/v1/my/billing/payments?${qs.toString()}`), }); } diff --git a/assets/admin/pages/MyPaymentsPage.test.tsx b/assets/admin/pages/MyPaymentsPage.test.tsx index 15512573..9b6d7d54 100644 --- a/assets/admin/pages/MyPaymentsPage.test.tsx +++ b/assets/admin/pages/MyPaymentsPage.test.tsx @@ -15,10 +15,10 @@ import MyPaymentsPage from './MyPaymentsPage'; const get = api.get as ReturnType; const ROWS = [ - { patient_uuid: 'p1', patient_name: 'دنیا خلیلی', national_code: '1744023654', - invoice_count: 2, paid_rials: 2350000, remaining_rials: 500000, status: 'unsettled' }, - { patient_uuid: 'p2', patient_name: 'علی بدیعی', national_code: '2200112233', - invoice_count: 1, paid_rials: 2000000, remaining_rials: 0, status: 'paid' }, + { invoice_uuid: 'iv1', patient_uuid: 'p1', patient_name: 'دنیا خلیلی', national_code: '1744023654', + issued_at: 1717000000, amount_rials: 2350000, status: 'paid' }, + { invoice_uuid: 'iv2', patient_uuid: 'p2', patient_name: 'علی بدیعی', national_code: '2200112233', + issued_at: 1718000000, amount_rials: 6000000, status: 'unsettled' }, ]; beforeEach(() => { @@ -28,14 +28,12 @@ beforeEach(() => { }); describe('MyPaymentsPage (لیست پرداخت‌ها)', () => { - it('renders patient payment rows with derived status labels', async () => { + it('renders a flat row per invoice with patient name and national code', async () => { renderWithProviders(, { route: '/admin/my-payments' }); expect(await screen.findByText('دنیا خلیلی')).toBeInTheDocument(); expect(screen.getByText('علی بدیعی')).toBeInTheDocument(); - // status labels appear both as a filter