diff --git a/backend/notification-service/src/main/java/com/finpay/notification/NotificationServiceApplication.java b/backend/notification-service/src/main/java/com/finpay/notification/NotificationServiceApplication.java index f79580d..4bdc653 100644 --- a/backend/notification-service/src/main/java/com/finpay/notification/NotificationServiceApplication.java +++ b/backend/notification-service/src/main/java/com/finpay/notification/NotificationServiceApplication.java @@ -3,13 +3,17 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.data.web.config.EnableSpringDataWebSupport; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; +import static org.springframework.data.web.config.EnableSpringDataWebSupport.PageSerializationMode.VIA_DTO; + @SpringBootApplication @EnableDiscoveryClient @EnableAsync @EnableScheduling +@EnableSpringDataWebSupport(pageSerializationMode = VIA_DTO) public class NotificationServiceApplication { public static void main(String[] args) { diff --git a/backend/notification-service/src/test/java/com/finpay/notification/controller/NotificationControllerIntegrationTest.java b/backend/notification-service/src/test/java/com/finpay/notification/controller/NotificationControllerIntegrationTest.java index 092b623..a6bda7d 100644 --- a/backend/notification-service/src/test/java/com/finpay/notification/controller/NotificationControllerIntegrationTest.java +++ b/backend/notification-service/src/test/java/com/finpay/notification/controller/NotificationControllerIntegrationTest.java @@ -259,7 +259,7 @@ void shouldReturnPaginatedNotifications() { assertThat(result).bodyJson() .extractingPath("$.content.length()").isEqualTo(3); assertThat(result).bodyJson() - .extractingPath("$.totalElements").isEqualTo(5); + .extractingPath("$.page.totalElements").isEqualTo(5); } @Test diff --git a/backend/payment-service/src/main/java/com/finpay/payment/PaymentServiceApplication.java b/backend/payment-service/src/main/java/com/finpay/payment/PaymentServiceApplication.java index 14a697a..c86d7a0 100644 --- a/backend/payment-service/src/main/java/com/finpay/payment/PaymentServiceApplication.java +++ b/backend/payment-service/src/main/java/com/finpay/payment/PaymentServiceApplication.java @@ -3,13 +3,17 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.data.web.config.EnableSpringDataWebSupport; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; +import static org.springframework.data.web.config.EnableSpringDataWebSupport.PageSerializationMode.VIA_DTO; + @SpringBootApplication @EnableDiscoveryClient @EnableAsync @EnableScheduling +@EnableSpringDataWebSupport(pageSerializationMode = VIA_DTO) public class PaymentServiceApplication { public static void main(String[] args) { diff --git a/backend/payment-service/src/test/java/com/finpay/payment/admin/AdminTransactionControllerIntegrationTest.java b/backend/payment-service/src/test/java/com/finpay/payment/admin/AdminTransactionControllerIntegrationTest.java index 38e4660..8900209 100644 --- a/backend/payment-service/src/test/java/com/finpay/payment/admin/AdminTransactionControllerIntegrationTest.java +++ b/backend/payment-service/src/test/java/com/finpay/payment/admin/AdminTransactionControllerIntegrationTest.java @@ -246,9 +246,9 @@ void shouldRespectPagination() { assertThat(result).bodyJson() .extractingPath("$.content.length()").isEqualTo(2); assertThat(result).bodyJson() - .extractingPath("$.totalElements").isEqualTo(5); + .extractingPath("$.page.totalElements").isEqualTo(5); assertThat(result).bodyJson() - .extractingPath("$.totalPages").isEqualTo(3); + .extractingPath("$.page.totalPages").isEqualTo(3); } @Test diff --git a/backend/user-service/src/main/java/com/finpay/user/UserServiceApplication.java b/backend/user-service/src/main/java/com/finpay/user/UserServiceApplication.java index 7c12ae9..a40802c 100644 --- a/backend/user-service/src/main/java/com/finpay/user/UserServiceApplication.java +++ b/backend/user-service/src/main/java/com/finpay/user/UserServiceApplication.java @@ -3,11 +3,15 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.data.web.config.EnableSpringDataWebSupport; import org.springframework.scheduling.annotation.EnableScheduling; +import static org.springframework.data.web.config.EnableSpringDataWebSupport.PageSerializationMode.VIA_DTO; + @SpringBootApplication @EnableDiscoveryClient @EnableScheduling +@EnableSpringDataWebSupport(pageSerializationMode = VIA_DTO) public class UserServiceApplication { public static void main(String[] args) { diff --git a/backend/user-service/src/test/java/com/finpay/user/admin/AdminUserControllerIntegrationTest.java b/backend/user-service/src/test/java/com/finpay/user/admin/AdminUserControllerIntegrationTest.java index e2a348c..3d687cf 100644 --- a/backend/user-service/src/test/java/com/finpay/user/admin/AdminUserControllerIntegrationTest.java +++ b/backend/user-service/src/test/java/com/finpay/user/admin/AdminUserControllerIntegrationTest.java @@ -104,7 +104,7 @@ void shouldReturnAllUsers() { assertThat(result).bodyJson() .extractingPath("$.content.length()").isEqualTo(3); assertThat(result).bodyJson() - .extractingPath("$.totalElements").isEqualTo(3); + .extractingPath("$.page.totalElements").isEqualTo(3); } @Test @@ -191,9 +191,9 @@ void shouldRespectPagination() { assertThat(result).bodyJson() .extractingPath("$.content.length()").isEqualTo(2); assertThat(result).bodyJson() - .extractingPath("$.totalElements").isEqualTo(5); + .extractingPath("$.page.totalElements").isEqualTo(5); assertThat(result).bodyJson() - .extractingPath("$.totalPages").isEqualTo(3); + .extractingPath("$.page.totalPages").isEqualTo(3); } @Test @@ -207,7 +207,7 @@ void shouldReturnEmptyPage() { assertThat(result).bodyJson() .extractingPath("$.content.length()").isEqualTo(0); assertThat(result).bodyJson() - .extractingPath("$.totalElements").isEqualTo(0); + .extractingPath("$.page.totalElements").isEqualTo(0); } } diff --git a/backend/wallet-service/src/main/java/com/finpay/wallet/WalletServiceApplication.java b/backend/wallet-service/src/main/java/com/finpay/wallet/WalletServiceApplication.java index efa9c87..8452afe 100644 --- a/backend/wallet-service/src/main/java/com/finpay/wallet/WalletServiceApplication.java +++ b/backend/wallet-service/src/main/java/com/finpay/wallet/WalletServiceApplication.java @@ -3,11 +3,15 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.data.web.config.EnableSpringDataWebSupport; import org.springframework.scheduling.annotation.EnableScheduling; +import static org.springframework.data.web.config.EnableSpringDataWebSupport.PageSerializationMode.VIA_DTO; + @SpringBootApplication @EnableDiscoveryClient @EnableScheduling +@EnableSpringDataWebSupport(pageSerializationMode = VIA_DTO) public class WalletServiceApplication { public static void main(String[] args) { diff --git a/backend/wallet-service/src/test/java/com/finpay/wallet/admin/AdminWalletControllerIntegrationTest.java b/backend/wallet-service/src/test/java/com/finpay/wallet/admin/AdminWalletControllerIntegrationTest.java index 322b8df..dea3b73 100644 --- a/backend/wallet-service/src/test/java/com/finpay/wallet/admin/AdminWalletControllerIntegrationTest.java +++ b/backend/wallet-service/src/test/java/com/finpay/wallet/admin/AdminWalletControllerIntegrationTest.java @@ -94,7 +94,7 @@ void shouldReturnAllWallets() { assertThat(result).bodyJson() .extractingPath("$.content.length()").isEqualTo(3); assertThat(result).bodyJson() - .extractingPath("$.totalElements").isEqualTo(3); + .extractingPath("$.page.totalElements").isEqualTo(3); } @Test @@ -145,9 +145,9 @@ void shouldRespectPagination() { assertThat(result).bodyJson() .extractingPath("$.content.length()").isEqualTo(2); assertThat(result).bodyJson() - .extractingPath("$.totalElements").isEqualTo(5); + .extractingPath("$.page.totalElements").isEqualTo(5); assertThat(result).bodyJson() - .extractingPath("$.totalPages").isEqualTo(3); + .extractingPath("$.page.totalPages").isEqualTo(3); } @Test diff --git a/frontend/e2e/admin/admin-fixtures.ts b/frontend/e2e/admin/admin-fixtures.ts index 66a1a40..54ab5d1 100644 --- a/frontend/e2e/admin/admin-fixtures.ts +++ b/frontend/e2e/admin/admin-fixtures.ts @@ -114,12 +114,12 @@ export function makePage(content: T[], totalElements?: number) { const total = totalElements ?? content.length; return { content, - totalElements: total, - totalPages: Math.max(1, Math.ceil(total / 20)), - number: 0, - size: 20, - first: true, - last: total <= 20, + page: { + totalElements: total, + totalPages: Math.max(1, Math.ceil(total / 20)), + number: 0, + size: 20, + }, }; } diff --git a/frontend/src/api/adminApi.ts b/frontend/src/api/adminApi.ts index a8f3310..db5b70e 100644 --- a/frontend/src/api/adminApi.ts +++ b/frontend/src/api/adminApi.ts @@ -115,12 +115,12 @@ export interface WalletMetrics { export interface PageResponse { content: T[]; - totalElements: number; - totalPages: number; - number: number; - size: number; - first: boolean; - last: boolean; + page: { + totalElements: number; + totalPages: number; + number: number; + size: number; + }; } // Query params diff --git a/frontend/src/api/billPaymentApi.ts b/frontend/src/api/billPaymentApi.ts index 52aab15..09ca535 100644 --- a/frontend/src/api/billPaymentApi.ts +++ b/frontend/src/api/billPaymentApi.ts @@ -61,10 +61,12 @@ export interface BillPayment { export interface BillPaymentPageResponse { content: BillPayment[]; - totalElements: number; - totalPages: number; - number: number; - size: number; + page: { + totalElements: number; + totalPages: number; + number: number; + size: number; + }; } // Static biller catalogue (v1) diff --git a/frontend/src/api/notificationApi.ts b/frontend/src/api/notificationApi.ts index de72a93..97d9c37 100644 --- a/frontend/src/api/notificationApi.ts +++ b/frontend/src/api/notificationApi.ts @@ -70,10 +70,12 @@ export interface NotificationPreferencesRequest { export interface NotificationPage { content: Notification[]; - totalElements: number; - totalPages: number; - size: number; - number: number; + page: { + totalElements: number; + totalPages: number; + size: number; + number: number; + }; } export const notificationService = { diff --git a/frontend/src/api/paymentApi.test.ts b/frontend/src/api/paymentApi.test.ts index 9293e24..7daf0ee 100644 --- a/frontend/src/api/paymentApi.test.ts +++ b/frontend/src/api/paymentApi.test.ts @@ -24,10 +24,12 @@ describe('paymentService', () => { http.get(`${BASE_URL}/api/v1/users/search`, () => HttpResponse.json({ content: [], - totalElements: 0, - totalPages: 0, - size: 5, - number: 0, + page: { + totalElements: 0, + totalPages: 0, + size: 5, + number: 0, + }, }), ), ); @@ -56,7 +58,7 @@ describe('paymentService', () => { const history = await paymentService.getTransferHistory('user-1'); expect(history.content).toHaveLength(2); - expect(history.totalElements).toBe(2); + expect(history.page.totalElements).toBe(2); }); }); diff --git a/frontend/src/api/paymentApi.ts b/frontend/src/api/paymentApi.ts index a5f51b6..bfe1fd9 100644 --- a/frontend/src/api/paymentApi.ts +++ b/frontend/src/api/paymentApi.ts @@ -10,10 +10,12 @@ export interface UserSearchResult { export interface UserSearchResponse { content: UserSearchResult[]; - totalElements: number; - totalPages: number; - size: number; - number: number; + page: { + totalElements: number; + totalPages: number; + size: number; + number: number; + }; } export interface MoneyTransferRequest { @@ -41,10 +43,12 @@ export interface MoneyTransfer { export interface TransferHistoryResponse { content: MoneyTransfer[]; - totalElements: number; - totalPages: number; - size: number; - number: number; + page: { + totalElements: number; + totalPages: number; + size: number; + number: number; + }; } // Money Request types @@ -88,10 +92,12 @@ export interface MoneyRequest { export interface MoneyRequestPageResponse { content: MoneyRequest[]; - totalElements: number; - totalPages: number; - size: number; - number: number; + page: { + totalElements: number; + totalPages: number; + size: number; + number: number; + }; } export const paymentService = { diff --git a/frontend/src/components/dashboard/RecentBillPayments.test.tsx b/frontend/src/components/dashboard/RecentBillPayments.test.tsx index ebdc1b2..07ebce8 100644 --- a/frontend/src/components/dashboard/RecentBillPayments.test.tsx +++ b/frontend/src/components/dashboard/RecentBillPayments.test.tsx @@ -33,10 +33,12 @@ describe('RecentBillPayments', () => { http.get(`${BASE_URL}/api/v1/payments/bills/user/:userId`, () => HttpResponse.json({ content: [], - totalElements: 0, - totalPages: 0, - number: 0, - size: 10, + page: { + totalElements: 0, + totalPages: 0, + number: 0, + size: 10, + }, }), ), ); @@ -93,10 +95,12 @@ describe('RecentBillPayments', () => { content: [ createMockBillPayment({ category: 'INTERNET', billerName: 'FiberNet ISP' }), ], - totalElements: 1, - totalPages: 1, - number: 0, - size: 10, + page: { + totalElements: 1, + totalPages: 1, + number: 0, + size: 10, + }, }), ), ); diff --git a/frontend/src/components/dashboard/RecentBillPayments.tsx b/frontend/src/components/dashboard/RecentBillPayments.tsx index 9f428c3..d752d05 100644 --- a/frontend/src/components/dashboard/RecentBillPayments.tsx +++ b/frontend/src/components/dashboard/RecentBillPayments.tsx @@ -89,7 +89,7 @@ export default function RecentBillPayments({ userId, onTransactionSelect }: Rece

Recent Bill Payments

- {data?.totalElements ?? 0} total + {data?.page.totalElements ?? 0} total
diff --git a/frontend/src/components/dashboard/RecentTransfers.test.tsx b/frontend/src/components/dashboard/RecentTransfers.test.tsx index 79de58c..a6a2dd6 100644 --- a/frontend/src/components/dashboard/RecentTransfers.test.tsx +++ b/frontend/src/components/dashboard/RecentTransfers.test.tsx @@ -47,10 +47,12 @@ describe('RecentTransfers', () => { http.get(`${BASE_URL}/api/v1/payments/transfers/user/:userId`, () => HttpResponse.json({ content: [], - totalElements: 0, - totalPages: 0, - size: 5, - number: 0, + page: { + totalElements: 0, + totalPages: 0, + size: 5, + number: 0, + }, }), ), ); @@ -84,10 +86,12 @@ describe('RecentTransfers', () => { createMockTransfer({ status: 'COMPLETED' }), createMockTransfer({ id: 'transfer-2', status: 'PROCESSING' }), ], - totalElements: 2, - totalPages: 1, - size: 5, - number: 0, + page: { + totalElements: 2, + totalPages: 1, + size: 5, + number: 0, + }, }), ), ); diff --git a/frontend/src/components/dashboard/RecentTransfers.tsx b/frontend/src/components/dashboard/RecentTransfers.tsx index 59e6a03..a69b65b 100644 --- a/frontend/src/components/dashboard/RecentTransfers.tsx +++ b/frontend/src/components/dashboard/RecentTransfers.tsx @@ -45,7 +45,7 @@ export default function RecentTransfers({ userId, onTransactionSelect }: RecentT

Recent Transfers

- {data?.totalElements ?? 0} total + {data?.page.totalElements ?? 0} total
diff --git a/frontend/src/hooks/useBillPayment.test.tsx b/frontend/src/hooks/useBillPayment.test.tsx index 9e5c0f5..a0f5a06 100644 --- a/frontend/src/hooks/useBillPayment.test.tsx +++ b/frontend/src/hooks/useBillPayment.test.tsx @@ -66,10 +66,12 @@ describe('useBillPayments', () => { createMockBillPayment({ id: 'b2', category: 'WATER', billerName: 'Metro Water' }), createMockBillPayment({ id: 'b3', category: 'INTERNET', billerName: 'FiberNet ISP' }), ], - totalElements: 3, - totalPages: 1, - number: 0, - size: 10, + page: { + totalElements: 3, + totalPages: 1, + number: 0, + size: 10, + }, }), ), ); @@ -95,10 +97,12 @@ describe('useBillPayments', () => { capturedSize = url.searchParams.get('size'); return HttpResponse.json({ content: [], - totalElements: 0, - totalPages: 0, - number: 2, - size: 20, + page: { + totalElements: 0, + totalPages: 0, + number: 2, + size: 20, + }, }); }), ); diff --git a/frontend/src/hooks/useTransfer.test.tsx b/frontend/src/hooks/useTransfer.test.tsx index e3f11b4..85a5fb5 100644 --- a/frontend/src/hooks/useTransfer.test.tsx +++ b/frontend/src/hooks/useTransfer.test.tsx @@ -48,10 +48,12 @@ describe('useTransferHistory', () => { http.get(`${BASE_URL}/api/v1/payments/transfers/user/:userId`, () => HttpResponse.json({ content: [], - totalElements: 0, - totalPages: 0, - size: 5, - number: 0, + page: { + totalElements: 0, + totalPages: 0, + size: 5, + number: 0, + }, }), ), ); @@ -87,10 +89,12 @@ describe('useTransferHistory', () => { createMockTransfer({ id: 't2', status: 'PROCESSING' }), createMockTransfer({ id: 't3', status: 'FAILED', failureReason: 'Insufficient funds' }), ], - totalElements: 3, - totalPages: 1, - size: 5, - number: 0, + page: { + totalElements: 3, + totalPages: 1, + size: 5, + number: 0, + }, }), ), ); diff --git a/frontend/src/pages/admin/AuditLogPage.tsx b/frontend/src/pages/admin/AuditLogPage.tsx index 06caa90..7cef642 100644 --- a/frontend/src/pages/admin/AuditLogPage.tsx +++ b/frontend/src/pages/admin/AuditLogPage.tsx @@ -163,8 +163,8 @@ export default function AuditLogPage() { data={data?.content ?? []} columns={columns} - pageCount={data?.totalPages ?? 0} - totalElements={data?.totalElements ?? 0} + pageCount={data?.page.totalPages ?? 0} + totalElements={data?.page.totalElements ?? 0} pagination={pagination} onPaginationChange={setPagination} sorting={sorting} diff --git a/frontend/src/pages/admin/TransactionMonitorPage.tsx b/frontend/src/pages/admin/TransactionMonitorPage.tsx index 1af584d..fefc304 100644 --- a/frontend/src/pages/admin/TransactionMonitorPage.tsx +++ b/frontend/src/pages/admin/TransactionMonitorPage.tsx @@ -201,8 +201,8 @@ export default function TransactionMonitorPage() { data={data?.content ?? []} columns={columns} - pageCount={data?.totalPages ?? 0} - totalElements={data?.totalElements ?? 0} + pageCount={data?.page.totalPages ?? 0} + totalElements={data?.page.totalElements ?? 0} pagination={pagination} onPaginationChange={setPagination} sorting={sorting} diff --git a/frontend/src/pages/admin/UserManagementPage.tsx b/frontend/src/pages/admin/UserManagementPage.tsx index ad920c2..84da8eb 100644 --- a/frontend/src/pages/admin/UserManagementPage.tsx +++ b/frontend/src/pages/admin/UserManagementPage.tsx @@ -188,8 +188,8 @@ export default function UserManagementPage() { data={data?.content ?? []} columns={columns} - pageCount={data?.totalPages ?? 0} - totalElements={data?.totalElements ?? 0} + pageCount={data?.page.totalPages ?? 0} + totalElements={data?.page.totalElements ?? 0} pagination={pagination} onPaginationChange={setPagination} sorting={sorting} diff --git a/frontend/src/pages/admin/WalletManagementPage.tsx b/frontend/src/pages/admin/WalletManagementPage.tsx index f8e87d2..437febe 100644 --- a/frontend/src/pages/admin/WalletManagementPage.tsx +++ b/frontend/src/pages/admin/WalletManagementPage.tsx @@ -179,8 +179,8 @@ export default function WalletManagementPage() { data={data?.content ?? []} columns={columns} - pageCount={data?.totalPages ?? 0} - totalElements={data?.totalElements ?? 0} + pageCount={data?.page.totalPages ?? 0} + totalElements={data?.page.totalElements ?? 0} pagination={pagination} onPaginationChange={setPagination} sorting={sorting} diff --git a/frontend/src/test/msw-handlers.ts b/frontend/src/test/msw-handlers.ts index 4d5fe7b..818ece8 100644 --- a/frontend/src/test/msw-handlers.ts +++ b/frontend/src/test/msw-handlers.ts @@ -56,10 +56,12 @@ export const handlers = [ createMockUserSearchResult(), createMockUserSearchResult({ id: 'user-3', email: 'bob@example.com', firstName: 'Bob', lastName: 'Jones' }), ], - totalElements: 2, - totalPages: 1, - size: 5, - number: 0, + page: { + totalElements: 2, + totalPages: 1, + size: 5, + number: 0, + }, }), ), @@ -96,10 +98,12 @@ export const handlers = [ status: 'PROCESSING', }), ], - totalElements: 2, - totalPages: 1, - size: 5, - number: 0, + page: { + totalElements: 2, + totalPages: 1, + size: 5, + number: 0, + }, }), ), @@ -117,30 +121,36 @@ export const handlers = [ http.get(`${BASE_URL}/api/v1/payments/requests/user/:userId`, () => HttpResponse.json({ content: [], - totalElements: 0, - totalPages: 0, - size: 10, - number: 0, + page: { + totalElements: 0, + totalPages: 0, + size: 10, + number: 0, + }, }), ), http.get(`${BASE_URL}/api/v1/payments/requests/pending/incoming`, () => HttpResponse.json({ content: [], - totalElements: 0, - totalPages: 0, - size: 10, - number: 0, + page: { + totalElements: 0, + totalPages: 0, + size: 10, + number: 0, + }, }), ), http.get(`${BASE_URL}/api/v1/payments/requests/pending/outgoing`, () => HttpResponse.json({ content: [], - totalElements: 0, - totalPages: 0, - size: 10, - number: 0, + page: { + totalElements: 0, + totalPages: 0, + size: 10, + number: 0, + }, }), ), @@ -168,10 +178,12 @@ export const handlers = [ http.get(`${BASE_URL}/api/v1/payments/bills/user/:userId`, () => HttpResponse.json({ content: [createMockBillPayment()], - totalElements: 1, - totalPages: 1, - number: 0, - size: 10, + page: { + totalElements: 1, + totalPages: 1, + number: 0, + size: 10, + }, }), ),