import { Body, Controller, Get, Param, ParseUUIDPipe, Post, Query } from '@nestjs/common'; import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; import { CurrentUser } from '@edr/api-common'; import type { TCurrentUser } from '@tria-plc/api-common/modules/auth/types/current-user.type'; import { isSuperAdmin } from '../../../common/freight-permission.util'; import { RuleEngineApprove, RuleEngineCreate, RuleEngineView } from '../../../common/rule-engine-guards'; import { DecideRateChangeDto, SubmitRateChangeDto } from '../dto/rate-change-request.dto'; import { RateChangeStatus } from '../entities/rate-change-request.entity'; import { RateChangeRequestsService } from '../services/rate-change-requests.service'; /** * Edits to LIVE rates. Staff with `manage` propose (submit); only holders of * `approve` decide. Until a change is approved the live rate keeps its current * value, so pricing never moves on an unapproved edit. */ @ApiTags('rate-change-requests') @Controller('rate-change-requests') @ApiBearerAuth() export class RateChangeRequestsController { constructor(private readonly service: RateChangeRequestsService) {} @Post() @RuleEngineCreate('rates') @ApiOperation({ summary: 'Propose a change to a LIVE rate' }) submit(@Body() dto: SubmitRateChangeDto, @CurrentUser() user: TCurrentUser) { return this.service.submit(dto, user?.id); } @Get() @RuleEngineView('rates') @ApiOperation({ summary: 'List rate change requests, optionally by status' }) list(@Query('status') status?: RateChangeStatus) { return this.service.list(status); } @Post(':id/approve') @RuleEngineApprove('rates') @ApiOperation({ summary: 'Approve a rate change and put it into effect' }) approve( @Param('id', ParseUUIDPipe) id: string, @Body() dto: DecideRateChangeDto, @CurrentUser() user: TCurrentUser, ) { return this.service.approve(id, user?.id, dto.decisionNote, isSuperAdmin(user)); } @Post(':id/reject') @RuleEngineApprove('rates') @ApiOperation({ summary: 'Reject a rate change — the rate keeps its current value' }) reject( @Param('id', ParseUUIDPipe) id: string, @Body() dto: DecideRateChangeDto, @CurrentUser() user: TCurrentUser, ) { return this.service.reject(id, user?.id, dto.decisionNote); } }