diff --git a/src/app/(app)/invoicing/page.tsx b/src/app/(app)/invoicing/page.tsx index af07ce5..15b05e7 100644 --- a/src/app/(app)/invoicing/page.tsx +++ b/src/app/(app)/invoicing/page.tsx @@ -12,6 +12,8 @@ import { Switch } from "@/components/ui/switch"; import { ModalShell } from "@/components/ui/modal-shell"; import { StockBookingSection, NEW_BOOKING_EVENT } from "@/components/invoicing/stock-booking-section"; import { getPocketBase } from "@/lib/pocketbase"; +import { useAuth } from "@/components/auth-provider"; +import { isRepUser } from "@/lib/rep-visibility"; import { cn } from "@/lib/utils"; import { useBooleanPreference } from "@/lib/use-boolean-preference"; import { colorForOrder } from "@/lib/order-color"; @@ -159,8 +161,14 @@ async function listAllInvoicingRows( return [firstPage, ...rest].flatMap((page) => page.items); } -async function loadInvoicingRows(pb: ReturnType): Promise { - const seedRows = await listAllInvoicingRows(pb, INVOICING_STATUS_FILTER); +async function loadInvoicingRows( + pb: ReturnType, + repId: string | null, +): Promise { + const repFilter = repId + ? ` && order.customer.rep = "${escapeFilterValue(repId)}"` + : ""; + const seedRows = await listAllInvoicingRows(pb, INVOICING_STATUS_FILTER + repFilter); const readyOrderIds = Array.from( new Set( seedRows @@ -174,6 +182,9 @@ async function loadInvoicingRows(pb: ReturnType): Promise< return seedRows; } + // No need to re-apply repFilter here — readyOrderIds is already + // derived from the rep-scoped seedRows above, so the sibling fetch + // (by explicit order id) is implicitly scoped too. const siblingFilter = readyOrderIds .map((orderId) => `order = "${escapeFilterValue(orderId)}"`) .join(" || "); @@ -1404,18 +1415,22 @@ export default function InvoicingPage() { // card list can render without a second round-trip. const [stockBookings, setStockBookings] = useState(null); + const { user } = useAuth(); + const load = useCallback(async () => { setRows(null); try { const pb = getPocketBase(); - const items = await loadInvoicingRows(pb); + const userType = (user as { user_type?: string[] } | null)?.user_type; + const repId = user && isRepUser(userType) ? user.id : null; + const items = await loadInvoicingRows(pb, repId); setRows(items); } catch (err) { const message = err instanceof Error ? err.message : String(err); toast.error(message); setRows([]); } - }, []); + }, [user]); /** * Lazy load of the booking list that surfaces on the Invoiced tab.