Files
edr-platform/apps/edr-freight-api/src/modules/payment/payment.controller.ts
2026-08-02 22:29:58 +00:00

96 lines
3.3 KiB
TypeScript

import {
Controller,
Get,
HttpStatus,
Param,
ParseUUIDPipe,
Query,
Res,
} from "@nestjs/common";
import {
ApiTags,
ApiOperation,
ApiQuery,
ApiOkResponse,
ApiProduces,
} from "@nestjs/swagger";
import { Response } from "express";
import { CurrentUser, Public } from "@edr/api-common";
import type { TCurrentUser } from "@tria-plc/api-common/modules/auth/types/current-user.type";
import { BookingStaff, BookingView } from "../../common/booking-guards";
import { UserTradeAccessService } from "../user-trade-access/user-trade-access.service";
import { FREIGHT_PERMS } from "../../seed/freight-permissions.registry";
import { PaymentService } from "./payment.service";
import { IntentStatusDto } from "./payments.dto";
@ApiTags("Payment")
@Controller("payments")
export class PaymentController {
constructor(
private readonly paymentService: PaymentService,
private readonly userTradeAccessService: UserTradeAccessService,
) { }
// Customer-detail payments tab — same one-of rule as the bookings tab.
@Get("by-company/:companyId/customer-view")
@BookingStaff([FREIGHT_PERMS.customers.view, FREIGHT_PERMS.payments.view])
@ApiOperation({ summary: "List payments for a company (customer-view shape, backoffice)" })
findByCompanyCustomerView(
@Param("companyId", ParseUUIDPipe) companyId: string,
) {
return this.paymentService.findByCompanyId(companyId);
}
@Get("summary")
@BookingView()
@ApiOperation({ summary: "Payment count/amount summary for dashboard cards" })
getSummary() {
return this.paymentService.getSummary();
}
@Get("all")
@BookingView()
@ApiOperation({ summary: "Get all payments with filters (view-only, any staff)" })
@ApiQuery({ name: "search", required: false })
@ApiQuery({ name: "status", required: false })
@ApiQuery({ name: "method", required: false })
@ApiQuery({ name: "page", required: false })
@ApiQuery({ name: "pageSize", required: false })
async getAll(
@CurrentUser() user: TCurrentUser,
@Query("search") search?: string,
@Query("status") status?: string,
@Query("method") method?: string,
@Query("page") page?: string,
@Query("pageSize") pageSize?: string,
) {
// Per-user trade-direction scope, applied via the booking in ref_id.
const allowed =
await this.userTradeAccessService.resolveAllowedDirections(user);
return this.paymentService.getAll({
search,
status,
method,
page: page ? parseInt(page) : 1,
pageSize: pageSize ? parseInt(pageSize) : 10,
tradeDirections: allowed ?? undefined,
});
}
@Get("intents/:bookingId")
@ApiOperation({ summary: "Get payment intent status for a booking" })
@ApiOkResponse({ type: IntentStatusDto })
getIntent(@Param("bookingId") bookingId: string) {
return this.paymentService.getIntentByBookingId(bookingId);
}
@Get("receipt/:orderId")
@Public()
@ApiOperation({ summary: "Generate a payment receipt HTML page" })
@ApiProduces("text/html")
async receipt(@Param("orderId") orderId: string, @Res() res: Response) {
const html = await this.paymentService.genReceiptHtml(orderId);
return res.status(HttpStatus.OK).type("html").send(html);
}
}