package com.kaidi.oa.web; import com.kaidi.oa.common.ApiException; import com.kaidi.oa.common.ApiResp; import com.kaidi.oa.common.NotFoundException; import com.kaidi.oa.domain.SewageShiftHandover; import com.kaidi.oa.repository.SewageShiftHandoverRepository; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.time.Instant; import java.util.List; /** * 城镇污水运营·值班交接班(补深审计 MISSING 生产计划与调度·值班管理缺口)。 * * 区别于 HandoverController(人事岗位移交),本控制器专为水厂班次交接建模: * - 当班人员填写交接班记录(运行状态 / 设备情况 / 待办事项); * - 接班人在线签名确认:/{id}/accept,记录 acceptedAt(模拟移动端签名时间); * - 待接班列表:GET /pending — 返回 status=待接班 的记录; * - 今日交接记录:GET /today — 返回当日所有交接记录,支持按 plant 过滤。 * * 写口默认受 AuthInterceptor default-deny(ADMIN/APPROVER) 保护。 */ @RestController @RequestMapping("/api/oa/sewage-shift-handovers") public class SewageShiftHandoverController { private final SewageShiftHandoverRepository handoverRepo; public SewageShiftHandoverController(SewageShiftHandoverRepository handoverRepo) { this.handoverRepo = handoverRepo; } // ---------- 基础 CRUD ---------- @GetMapping public ApiResp> list( @RequestParam(required = false) String status, @RequestParam(required = false) String plant, @RequestParam(required = false) String handoverDate) { if (status != null && !status.isBlank()) { return ApiResp.ok(handoverRepo.findByStatus(status)); } if (plant != null && !plant.isBlank()) { return ApiResp.ok(handoverRepo.findByPlant(plant)); } if (handoverDate != null && !handoverDate.isBlank()) { return ApiResp.ok(handoverRepo.findByHandoverDate(handoverDate)); } return ApiResp.ok(handoverRepo.findAll()); } @GetMapping("/{id}") public ApiResp get(@PathVariable Long id) { return ApiResp.ok(handoverRepo.findById(id) .orElseThrow(() -> new NotFoundException("交接班记录不存在: " + id))); } public record HandoverRequest( String handoverDate, String shift, String plant, String outgoingStaff, String incomingStaff, Double treatedWater, Double codIn, Double codOut, Double ammoniaOut, String processStatus, String equipmentStatus, String faultRecord, String completedWorkOrders, String pendingItems, String safetyNotes, String chemicalNotes, String remark) { } @PostMapping public ApiResp create(@RequestBody HandoverRequest req) { if (req.handoverDate() == null || req.handoverDate().isBlank()) { throw new ApiException(400, "交接日期(handoverDate) 不能为空"); } if (req.outgoingStaff() == null || req.outgoingStaff().isBlank()) { throw new ApiException(400, "交班人(outgoingStaff) 不能为空"); } SewageShiftHandover h = new SewageShiftHandover(); h.setCode("SHO-" + (handoverRepo.count() + 1)); h.setHandoverDate(req.handoverDate()); h.setShift(req.shift()); h.setPlant(req.plant()); h.setOutgoingStaff(req.outgoingStaff()); h.setIncomingStaff(req.incomingStaff()); h.setTreatedWater(req.treatedWater()); h.setCodIn(req.codIn()); h.setCodOut(req.codOut()); h.setAmmoniaOut(req.ammoniaOut()); h.setProcessStatus(req.processStatus()); h.setEquipmentStatus(req.equipmentStatus()); h.setFaultRecord(req.faultRecord()); h.setCompletedWorkOrders(req.completedWorkOrders()); h.setPendingItems(req.pendingItems()); h.setSafetyNotes(req.safetyNotes()); h.setChemicalNotes(req.chemicalNotes()); h.setRemark(req.remark()); h.setStatus("待接班"); h.setCreatedAt(Instant.now()); return ApiResp.ok(handoverRepo.save(h)); } @PatchMapping("/{id}") @Transactional public ApiResp update(@PathVariable Long id, @RequestBody HandoverRequest req) { SewageShiftHandover h = handoverRepo.findById(id) .orElseThrow(() -> new NotFoundException("交接班记录不存在: " + id)); if ("已接班".equals(h.getStatus())) { throw new ApiException(409, "已接班的记录不允许修改"); } if (req.handoverDate() != null && !req.handoverDate().isBlank()) h.setHandoverDate(req.handoverDate()); if (req.shift() != null) h.setShift(req.shift()); if (req.plant() != null) h.setPlant(req.plant()); if (req.outgoingStaff() != null && !req.outgoingStaff().isBlank()) h.setOutgoingStaff(req.outgoingStaff()); if (req.incomingStaff() != null) h.setIncomingStaff(req.incomingStaff()); if (req.treatedWater() != null) h.setTreatedWater(req.treatedWater()); if (req.codIn() != null) h.setCodIn(req.codIn()); if (req.codOut() != null) h.setCodOut(req.codOut()); if (req.ammoniaOut() != null) h.setAmmoniaOut(req.ammoniaOut()); if (req.processStatus() != null) h.setProcessStatus(req.processStatus()); if (req.equipmentStatus() != null) h.setEquipmentStatus(req.equipmentStatus()); if (req.faultRecord() != null) h.setFaultRecord(req.faultRecord()); if (req.completedWorkOrders() != null) h.setCompletedWorkOrders(req.completedWorkOrders()); if (req.pendingItems() != null) h.setPendingItems(req.pendingItems()); if (req.safetyNotes() != null) h.setSafetyNotes(req.safetyNotes()); if (req.chemicalNotes() != null) h.setChemicalNotes(req.chemicalNotes()); if (req.remark() != null) h.setRemark(req.remark()); return ApiResp.ok(handoverRepo.save(h)); } @DeleteMapping("/{id}") @Transactional public ApiResp delete(@PathVariable Long id) { handoverRepo.findById(id).orElseThrow(() -> new NotFoundException("交接班记录不存在: " + id)); handoverRepo.deleteById(id); return ApiResp.ok(null); } // ---------- 接班签名确认(移动端)---------- public record AcceptRequest(String incomingStaff, String remark) { } @PostMapping("/{id}/accept") @Transactional public ApiResp accept(@PathVariable Long id, @RequestBody AcceptRequest req) { SewageShiftHandover h = handoverRepo.findById(id) .orElseThrow(() -> new NotFoundException("交接班记录不存在: " + id)); if ("已接班".equals(h.getStatus())) { throw new ApiException(409, "该交接班记录已签收,不可重复操作"); } if (req.incomingStaff() != null && !req.incomingStaff().isBlank()) { h.setIncomingStaff(req.incomingStaff()); } if (h.getIncomingStaff() == null || h.getIncomingStaff().isBlank()) { throw new ApiException(400, "接班人(incomingStaff) 不能为空"); } h.setAcceptedAt(Instant.now()); h.setStatus("已接班"); if (req.remark() != null) { String prev = h.getRemark() != null ? h.getRemark() : ""; h.setRemark(prev.isEmpty() ? req.remark() : prev + "; " + req.remark()); } return ApiResp.ok(handoverRepo.save(h)); } // ---------- 待接班列表 ---------- @GetMapping("/pending") public ApiResp> pending() { return ApiResp.ok(handoverRepo.findByStatus("待接班")); } }