package com.lincfusion.udyamlinc.officer; import com.lincfusion.udyamlinc.common.ApiResponse; import com.lincfusion.udyamlinc.security.TenantContext; import com.lincfusion.udyamlinc.dto.UdyamRequests.AlertActionRequest; import com.lincfusion.udyamlinc.dto.UdyamRequests.ScheduleVisitRequest; import com.lincfusion.udyamlinc.dto.UdyamRequests.VisitOutcomeRequest; import com.lincfusion.udyamlinc.dto.UdyamResponses.*; import com.lincfusion.udyamlinc.risk.RiskAlert; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; import java.util.List; /** * The field officer console API. Every route here is gated on SCOPE_OFFICER by * {@code SecurityConfig}, so an enterprise token can never reach it. */ @RestController @RequestMapping("/officer") @RequiredArgsConstructor public class OfficerController { private final OfficerService officerService; @GetMapping("/portfolio") public ApiResponse portfolio( TenantContext tenant, @RequestParam(defaultValue = OfficerService.ALL_BLOCKS) String block, @RequestParam(required = false) String month) { return ApiResponse.ok(officerService.portfolio(tenant, block, month)); } @GetMapping("/enterprises") public ApiResponse> enterprises( TenantContext tenant, @RequestParam(defaultValue = OfficerService.ALL_BLOCKS) String block) { return ApiResponse.ok(officerService.enterprises(tenant, block)); } /** Ids on this book that have a phone-app login. */ @GetMapping("/app-enrolled") public ApiResponse> appEnrolled( TenantContext tenant, @RequestParam(defaultValue = "ALL") String block) { return ApiResponse.ok(officerService.appEnrolled(tenant, block)); } @GetMapping("/enterprises/{enterpriseId}") public ApiResponse detail(TenantContext tenant, @PathVariable String enterpriseId) { return ApiResponse.ok(officerService.detail(tenant, enterpriseId)); } @GetMapping("/alerts") public ApiResponse> alerts( TenantContext tenant, @RequestParam(defaultValue = OfficerService.ALL_BLOCKS) String block, @RequestParam(required = false) String state) { return ApiResponse.ok(officerService.alerts(tenant, block, state)); } @PutMapping("/alerts/{alertId}") public ApiResponse disposition( TenantContext tenant, @PathVariable String alertId, @Valid @RequestBody AlertActionRequest request, @AuthenticationPrincipal String actor) { return ApiResponse.ok("Alert updated", officerService.disposition(tenant, alertId, request.state(), request.note(), actor)); } @GetMapping("/visits") public ApiResponse> visits( TenantContext tenant, @RequestParam(defaultValue = OfficerService.ALL_BLOCKS) String block) { return ApiResponse.ok(officerService.visits(tenant, block)); } @PostMapping("/visits") public ApiResponse schedule( TenantContext tenant, @Valid @RequestBody ScheduleVisitRequest request, @AuthenticationPrincipal String officer) { return ApiResponse.ok("Visit scheduled", officerService.schedule(tenant, request, officer)); } @PutMapping("/visits/{visitId}/outcome") public ApiResponse logOutcome( @PathVariable String visitId, @Valid @RequestBody VisitOutcomeRequest request) { return ApiResponse.ok("Outcome logged", officerService.logOutcome(visitId, request.outcome(), request.officerOverride())); } @GetMapping("/playbook") public ApiResponse> playbook() { return ApiResponse.ok(PlaybookCatalog.asResponses()); } @GetMapping("/sectors") public ApiResponse> sectors( TenantContext tenant, @RequestParam(defaultValue = OfficerService.ALL_BLOCKS) String block) { return ApiResponse.ok(officerService.sectorRollup(tenant, block)); } }