From 9d198015353490f6c5a0c6c3a1b22c4a2eb09535 Mon Sep 17 00:00:00 2001
From: Stephanos A
Date: Wed, 12 Aug 2026 13:11:24 +0300
Subject: [PATCH] Overall report and segment tariff override updates
---
.../fare-engine/fare-engine.service.ts | 40 ++++++--
.../src/app/reports/overall/page.tsx | 93 +++++++++++--------
2 files changed, 88 insertions(+), 45 deletions(-)
diff --git a/apps/edr-passenger-api/src/modules/fare-engine/fare-engine.service.ts b/apps/edr-passenger-api/src/modules/fare-engine/fare-engine.service.ts
index 69b0266ed..348e9d6be 100644
--- a/apps/edr-passenger-api/src/modules/fare-engine/fare-engine.service.ts
+++ b/apps/edr-passenger-api/src/modules/fare-engine/fare-engine.service.ts
@@ -88,20 +88,48 @@ export class FareEngineService {
where: {
routeId: route.id,
seatClassId: dto.seatClassId,
- originStopSequence: originStop.sequence,
- destinationStopSequence: destStop.sequence,
+ AND: [
+ {
+ OR: [
+ {
+ originStopSequence: originStop.sequence,
+ destinationStopSequence: destStop.sequence,
+ },
+ {
+ originStopSequence: destStop.sequence,
+ destinationStopSequence: originStop.sequence,
+ },
+ ],
+ },
+ {
+ OR: [{ validUntil: null }, { validUntil: { gte: now } }],
+ },
+ ],
validFrom: { lte: now },
- OR: [{ validUntil: null }, { validUntil: { gte: now } }],
nationality: dto.nationality ?? null,
},
}) ?? await this.prisma.segmentFareRule.findFirst({
where: {
routeId: route.id,
seatClassId: dto.seatClassId,
- originStopSequence: originStop.sequence,
- destinationStopSequence: destStop.sequence,
+ AND: [
+ {
+ OR: [
+ {
+ originStopSequence: originStop.sequence,
+ destinationStopSequence: destStop.sequence,
+ },
+ {
+ originStopSequence: destStop.sequence,
+ destinationStopSequence: originStop.sequence,
+ },
+ ],
+ },
+ {
+ OR: [{ validUntil: null }, { validUntil: { gte: now } }],
+ },
+ ],
validFrom: { lte: now },
- OR: [{ validUntil: null }, { validUntil: { gte: now } }],
nationality: null,
},
});
diff --git a/apps/edr-passenger-web/backoffice/src/app/reports/overall/page.tsx b/apps/edr-passenger-web/backoffice/src/app/reports/overall/page.tsx
index 5e23b92d6..0ecc7a885 100644
--- a/apps/edr-passenger-web/backoffice/src/app/reports/overall/page.tsx
+++ b/apps/edr-passenger-web/backoffice/src/app/reports/overall/page.tsx
@@ -8,7 +8,6 @@ import {
Tooltip, Legend, ResponsiveContainer, PieChart, Pie, Cell,
} from 'recharts';
import { bookingsApi } from '@/lib/api';
-import { dashboardApi } from '@/lib/api/dashboard';
import { apiClient } from '@/lib/api-client';
import { formatCurrency } from '@/lib/utils';
import ActionButton from '@/components/ui/ActionButton';
@@ -62,12 +61,6 @@ export default function ReportsPage() {
const dates = getDateRange();
// Confirmed-ticket revenue — same source as dashboard
- const { data: stats, isLoading: statsLoading } = useQuery({
- queryKey: ['backoffice-stats'],
- queryFn: dashboardApi.getBackofficeStats,
- staleTime: 60000,
- });
-
const { data: exchangeRates = [] } = useQuery({
queryKey: ['currencies'],
queryFn: () => apiClient.get('/currencies'),
@@ -92,19 +85,13 @@ export default function ReportsPage() {
return rate !== null ? sum + Math.round(totalMinor * rate) : sum;
}, 0);
- const normalRows = stats?.revenueByCurrency ?? [];
- const packageRows = stats?.packageRevenueByCurrency ?? [];
- const normalGrand = calcGrand(normalRows);
- const packageGrand = calcGrand(packageRows);
- const overallGrand = normalGrand + packageGrand;
-
// Bookings for charts / status distribution
const { data: bookingsData, isLoading: bookingsLoading } = useQuery({
- queryKey: ['all-bookings'],
- queryFn: () => bookingsApi.getAll({ pageSize: 1000 }),
+ queryKey: ['all-bookings', dates.startDate, dates.endDate],
+ queryFn: () => bookingsApi.getAll({ pageSize: 5000, dateFrom: dates.startDate, dateTo: dates.endDate }),
});
- const isLoading = statsLoading || bookingsLoading;
+ const isLoading = bookingsLoading;
const allBookings: any[] = Array.isArray(bookingsData?.items) ? bookingsData.items : [];
@@ -113,7 +100,7 @@ export default function ReportsPage() {
return d >= dates.startDate && d <= dates.endDate;
});
- const confirmedBookings = bookings.filter((b: any) => b.status !== 'CANCELLED' && b.status !== 'REFUNDED');
+ const confirmedBookings = bookings.filter((b: any) => b.status === 'CONFIRMED' || b.status === 'BOARDED');
const totalRevenueMinor = confirmedBookings.reduce((sum, b: any) => {
const rate = toEtbRate(b.currency);
@@ -151,6 +138,34 @@ export default function ReportsPage() {
return bookingType === 'PACKAGE' || Boolean(b.packageId);
}).length;
+ const normalRows = confirmedBookings
+ .filter((b: any) => {
+ const bookingType = String(b.bookingType || '').toUpperCase();
+ return bookingType !== 'PACKAGE' && !b.packageId;
+ })
+ .reduce((acc: Record, b: any) => {
+ const currency = b.currency || 'ETB';
+ acc[currency] = (acc[currency] || 0) + (b.totalMinor || 0);
+ return acc;
+ }, {} as Record);
+
+ const packageRows = confirmedBookings
+ .filter((b: any) => {
+ const bookingType = String(b.bookingType || '').toUpperCase();
+ return bookingType === 'PACKAGE' || Boolean(b.packageId);
+ })
+ .reduce((acc: Record, b: any) => {
+ const currency = b.currency || 'ETB';
+ acc[currency] = (acc[currency] || 0) + (b.totalMinor || 0);
+ return acc;
+ }, {} as Record);
+
+ const normalRowData = Object.entries(normalRows).map(([currency, totalMinor]) => ({ currency, totalMinor }));
+ const packageRowData = Object.entries(packageRows).map(([currency, totalMinor]) => ({ currency, totalMinor }));
+ const normalGrand = calcGrand(normalRowData);
+ const packageGrand = calcGrand(packageRowData);
+ const overallGrand = normalGrand + packageGrand;
+
const filteredRouteBookings = confirmedBookings.filter((b: any) => {
const origin = b.schedule?.originStation?.name || b.originStationName || b.origin || 'Unknown';
const destination = b.schedule?.destinationStation?.name || b.destinationStationName || b.destination || 'Unknown';
@@ -201,8 +216,8 @@ export default function ReportsPage() {
`th,td{border:1px solid #ccc;padding:4px 8px}th{background:#10b981;color:#fff}` +
`Revenue Report — ${esc(dates.startDate)} to ${esc(dates.endDate)}
` +
`Total Revenue: ${esc(formatCurrency(overallGrand, 'ETB'))} | ` +
- `Bookings: ${esc(String(stats?.totalBookings ?? 0))} | ` +
- `Tickets: ${esc(String(stats?.totalTickets ?? 0))}
` +
+ `Bookings: ${esc(String(totalBookingsCount))} | ` +
+ `Tickets: ${esc(String(totalTicketsCount))}
` +
`