import { Body,Controller,Get,Param,Post,Req,UseGuards } from '@nestjs/common';
import type { z } from 'zod';
import { AuthGuard } from '../../../common/auth/auth.guard';
import { OrganizationContextGuard } from '../../../common/auth/organization-context.guard';
import { LocationContextGuard,type LocationScopedRequest } from '../../../common/auth/location-context.guard';
import { PermissionGuard } from '../../../common/auth/permission.guard';
import { RequirePermissions } from '../../../common/auth/permissions.decorator';
import { ZodValidationPipe } from '../../../common/validation/zod-validation.pipe';
import {
billingOpenSchema,billingSplitCustomSchema,billingSplitEqualSchema,
billingSplitItemsSchema,billingSplitSeatsSchema,
} from '../../../common/validation/critical-write.schemas';
type BillingOpenBody = z.infer<typeof billingOpenSchema>;
type BillingSplitItemsBody = z.infer<typeof billingSplitItemsSchema>;
type BillingSplitSeatsBody = z.infer<typeof billingSplitSeatsSchema>;
type BillingSplitEqualBody = z.infer<typeof billingSplitEqualSchema>;
type BillingSplitCustomBody = z.infer<typeof billingSplitCustomSchema>;
import { BillingService } from '../application/billing.service';
import { CheckSplitService } from '../application/check-split.service';
import { CheckDetailService } from '../read-models/check-detail.service';
@Controller('/billing')
@UseGuards(AuthGuard,OrganizationContextGuard,LocationContextGuard,PermissionGuard)
export class BillingController {
constructor(
private readonly billing:BillingService,
private readonly splits:CheckSplitService,
private readonly detail:CheckDetailService,
) {}
@Get('/checks/:id')
@RequirePermissions('billing.read')
get(@Req() req:LocationScopedRequest,@Param('id') id:string) {
return this.detail.get(req.organizationId!,req.locationId!,id);
}
@Post('/checks')
@RequirePermissions('billing.manage')
open(
@Req() req:LocationScopedRequest,
@Body(new ZodValidationPipe(billingOpenSchema)) body:BillingOpenBody,
) {
return this.billing.openCheck({
organizationId:req.organizationId!,locationId:req.locationId!,
serviceSessionId:body.serviceSessionId,currencyCode:body.currencyCode,
});
}
@Post('/checks/:id/rebuild')
@RequirePermissions('billing.manage')
rebuild(@Req() req:LocationScopedRequest,@Param('id') id:string) {
return this.billing.rebuildTotals({
organizationId:req.organizationId!,locationId:req.locationId!,checkId:id,
});
}
@Post('/checks/:id/split/items')
@RequirePermissions('billing.manage')
splitItems(
@Req() req:LocationScopedRequest,@Param('id') id:string,
@Body(new ZodValidationPipe(billingSplitItemsSchema)) body:BillingSplitItemsBody,
) {
return this.billing.splitByItems({
organizationId:req.organizationId!,locationId:req.locationId!,
sourceCheckId:id,orderItemIds:body.orderItemIds,
});
}
@Post('/checks/:id/split/seats')
@RequirePermissions('billing.manage')
splitSeats(
@Req() req:LocationScopedRequest,@Param('id') id:string,
@Body(new ZodValidationPipe(billingSplitSeatsSchema)) body:BillingSplitSeatsBody,
) {
return this.splits.splitBySeat({
organizationId:req.organizationId!,locationId:req.locationId!,
sourceCheckId:id,seatNumbers:body.seatNumbers,
});
}
@Post('/checks/:id/split/equal')
@RequirePermissions('billing.manage')
splitEqual(
@Req() req:LocationScopedRequest,@Param('id') id:string,
@Body(new ZodValidationPipe(billingSplitEqualSchema)) body:BillingSplitEqualBody,
) {
return this.splits.splitEqual({
organizationId:req.organizationId!,locationId:req.locationId!,
sourceCheckId:id,parts:body.parts,
});
}
@Post('/checks/:id/split/custom')
@RequirePermissions('billing.manage')
splitCustom(
@Req() req:LocationScopedRequest,@Param('id') id:string,
@Body(new ZodValidationPipe(billingSplitCustomSchema)) body:BillingSplitCustomBody,
) {
return this.splits.splitCustom({
organizationId:req.organizationId!,locationId:req.locationId!,
sourceCheckId:id,amountsMinor:body.amountsMinor,
});
}
}
