# Admin Vouchers API — Changes Two updates to the admin vouchers list endpoint (`GET /admin/v1/vouchers`). ## 1. Redeemed-by user info Each voucher in the response now includes a `redeemedBy` object identifying the user who redeemed it, resolved from the auth database: ```json { "voucherId": "...", "code": "ABCD-1234", "status": "Redeemed", "redeemedByUserId": "auth0|123", "redeemedBy": { "id": "auth0|123", "fullName": "Filan Fisteku", "email": "filan@example.com" }, "redeemedAt": "2026-07-01T10:15:00Z" } ``` - `redeemedBy` is `null` for vouchers that haven't been redeemed. - The existing `redeemedByUserId` field is unchanged, so nothing breaks for current consumers. - Users are batch-loaded per page (one query for all distinct user IDs), following the same pattern as the admin pay-to-view purchases endpoint. ### Files changed | File | Change | |---|---| | `core/PicTv.Application/Dtos/Vouchers/VoucherDto.cs` | Added `RedeemedBy` property and new `VoucherRedeemedByDto` (`Id`, `FullName`, `Email`) | | `core/PicTv.Application/Vouchers/Queries/GetAdminVouchers/GetAdminVouchersQueryHandler.cs` | Injected `IAuthDbContext`; added `PopulateRedeemedByAsync` to enrich results with user name and email | ## 2. Order by reason New optional query parameter `orderByReason` (boolean, default `false`): ``` GET /admin/v1/vouchers?page=1&orderByReason=true ``` - When `true`, vouchers are sorted alphabetically by `reason`, with newest-first (`createdAt` descending) as the tiebreaker. - When omitted or `false`, the existing default ordering (newest first by `createdAt`) applies. ### Files changed | File | Change | |---|---| | `api/PicTv.Api/Routes/VoucherRoutes.cs` | Added `orderByReason` query parameter to the admin list endpoint | | `core/PicTv.Application/Vouchers/Queries/GetAdminVouchers/GetAdminVouchersQuery.cs` | Added `OrderByReason` property (defaults to `false`) | | `core/PicTv.Application/Vouchers/Queries/GetAdminVouchers/GetAdminVouchersQueryHandler.cs` | Applies `OrderBy(Reason).ThenByDescending(CreatedAt)` when the flag is set | ## Notes - No database or migration changes — `RedeemedByUserId`, `RedeemedAt`, and `Reason` were already stored on the `Voucher` entity. - If more sort columns are needed later (status, redeemed date, …), the boolean flag should be replaced with an `orderBy` enum parameter.