import { Body,Controller,Get,Param,Post,Query,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 {
employeeActionSchema,handoverAmendmentSchema,handoverCreateSchema,handoverItemSchema,
operationalEvidenceSchema,operationalTaskCreateSchema,operationalTaskTemplateSchema,
} from '../../../common/validation/critical-write.schemas';
type EmployeeActionBody = z.infer<typeof employeeActionSchema>;
type HandoverAmendmentBody = z.infer<typeof handoverAmendmentSchema>;
type HandoverCreateBody = z.infer<typeof handoverCreateSchema>;
type HandoverItemBody = z.infer<typeof handoverItemSchema>;
type OperationalEvidenceBody = z.infer<typeof operationalEvidenceSchema>;
type OperationalTaskCreateBody = z.infer<typeof operationalTaskCreateSchema>;
type OperationalTaskTemplateBody = z.infer<typeof operationalTaskTemplateSchema>;
import { TaskService } from '../application/task.service';
import { HandoverService } from '../application/handover.service';
import { OperationsTodayService } from '../read-models/operations-today.service';
import { HandoverAmendmentService } from '../application/handover-amendment.service';
import { BusinessDateService } from '../../../common/time/business-date.service';
@Controller('/operations')
@UseGuards(AuthGuard,OrganizationContextGuard,LocationContextGuard,PermissionGuard)
export class OperationsController {
constructor(
private readonly tasks:TaskService,
private readonly handovers:HandoverService,
private readonly handoverAmendments:HandoverAmendmentService,
private readonly today:OperationsTodayService,
private readonly businessDates:BusinessDateService,
) {}
@Get('/today')
@RequirePermissions('operations.read')
async getToday(@Req() req:LocationScopedRequest,@Query('businessDate') businessDate?:string) {
const resolved=businessDate??await this.businessDates.forLocation({
organizationId:req.organizationId!,locationId:req.locationId!,
});
return this.today.get({
organizationId:req.organizationId!,locationId:req.locationId!,businessDate:resolved,
});
}
@Get('/tasks/:id')
@RequirePermissions('operations.read')
getTask(@Req() req:LocationScopedRequest,@Param('id') id:string) {
return this.today.getTask({
organizationId:req.organizationId!,locationId:req.locationId!,taskId:id,
});
}
@Post('/task-templates')
@RequirePermissions('operations.manage')
template(
@Req() req:LocationScopedRequest,
@Body(new ZodValidationPipe(operationalTaskTemplateSchema)) body:OperationalTaskTemplateBody,
) {
return this.tasks.createTemplate({
organizationId:req.organizationId!,locationId:req.locationId!,...body,
});
}
@Post('/tasks')
@RequirePermissions('operations.manage')
async createTask(
@Req() req:LocationScopedRequest,
@Body(new ZodValidationPipe(operationalTaskCreateSchema)) body:OperationalTaskCreateBody,
) {
const businessDate=await this.businessDates.forLocation({
organizationId:req.organizationId!,locationId:req.locationId!,
});
return this.tasks.createTask({
organizationId:req.organizationId!,locationId:req.locationId!,businessDate,...body,
});
}
@Post('/tasks/:id/start')
@RequirePermissions('operations.complete')
start(
@Req() req:LocationScopedRequest,@Param('id') id:string,
@Body(new ZodValidationPipe(employeeActionSchema)) body:EmployeeActionBody,
) {
return this.tasks.start({
organizationId:req.organizationId!,locationId:req.locationId!,taskId:id,employeeId:body.employeeId,
});
}
@Post('/tasks/:id/evidence')
@RequirePermissions('operations.complete')
evidence(
@Req() req:LocationScopedRequest,@Param('id') id:string,
@Body(new ZodValidationPipe(operationalEvidenceSchema)) body:OperationalEvidenceBody,
) {
return this.tasks.addEvidence({
organizationId:req.organizationId!,locationId:req.locationId!,taskId:id,...body,
});
}
@Post('/tasks/:id/complete')
@RequirePermissions('operations.complete')
complete(
@Req() req:LocationScopedRequest,@Param('id') id:string,
@Body(new ZodValidationPipe(employeeActionSchema)) body:EmployeeActionBody,
) {
return this.tasks.complete({
organizationId:req.organizationId!,locationId:req.locationId!,taskId:id,employeeId:body.employeeId,
});
}
@Post('/handovers')
@RequirePermissions('operations.handover.manage')
async handover(
@Req() req:LocationScopedRequest,
@Body(new ZodValidationPipe(handoverCreateSchema)) body:HandoverCreateBody,
) {
const businessDate=await this.businessDates.forLocation({
organizationId:req.organizationId!,locationId:req.locationId!,
});
return this.handovers.create({
organizationId:req.organizationId!,locationId:req.locationId!,businessDate,...body,
});
}
@Post('/handovers/:id/items')
@RequirePermissions('operations.handover.manage')
handoverItem(
@Req() req:LocationScopedRequest,@Param('id') id:string,
@Body(new ZodValidationPipe(handoverItemSchema)) body:HandoverItemBody,
) {
return this.handovers.addItem({
organizationId:req.organizationId!,locationId:req.locationId!,handoverId:id,...body,
});
}
@Post('/handovers/:id/publish')
@RequirePermissions('operations.handover.manage')
publish(@Req() req:LocationScopedRequest,@Param('id') id:string) {
return this.handovers.publish(req.organizationId!,req.locationId!,id);
}
@Post('/handovers/:id/acknowledge')
@RequirePermissions('operations.handover.manage')
acknowledge(@Req() req:LocationScopedRequest,@Param('id') id:string) {
return this.handovers.acknowledge(req.organizationId!,req.locationId!,id);
}
@Post('/handovers/:id/amendments')
@RequirePermissions('operations.handover.manage')
amendHandover(
@Req() req:LocationScopedRequest,@Param('id') id:string,
@Body(new ZodValidationPipe(handoverAmendmentSchema)) body:HandoverAmendmentBody,
) {
return this.handoverAmendments.amend({
organizationId:req.organizationId!,locationId:req.locationId!,handoverId:id,
body:body.body,employeeId:body.employeeId,
});
}
@Post('/handovers/:id/close')
@RequirePermissions('operations.handover.manage')
closeHandover(@Req() req:LocationScopedRequest,@Param('id') id:string) {
return this.handoverAmendments.close({
organizationId:req.organizationId!,locationId:req.locationId!,handoverId:id,
});
}
}
