Files
ERP/oa-backend/src/main/java/com/kaidi/oa/web/SewageShiftHandoverController.java
T
QiufengandClaude Opus 4.8 5e51dc3f56 SNAPSHOT W7 已部署稳定态 — 凯迪ERP+OA一体化平台 (MET 73.3%)
恢复点(restore point)。别人改崩后可 git reset --hard 回到此提交。

== 此快照内容 ==
- 后端 oa-backend: 734 控制器 / 711 实体 (Spring Boot 3.2.5 + SQLite, 端口8091)
- 前端 modern-ui/app: Vue3+Vite, 约700页 (构建产物已在 oa-backend/src/main/resources/static)
- 数据库 oa-backend/data/oa.db: 含全部演示数据 (强制入库, 6.6MB)
- 交接文档 go.md + go-code-reference/endpoints/entities/database.md
- 多代理建设脚本 .claude/wf-*.js

== 状态 ==
- 对 凯迪科技ERP_20260507.xlsx 合规 MET ~73.3% (PARTIAL 75: 34可建+6种子/bug+35外部硬天花板)
- 安全: 5轮红队+5轮复检, default-deny分级鉴权, 连续零可利用
- W3~W7 累计补完436缺口; W8末轮(40缺口)为半成品(源码树可编译但未集成)
- 运行: cd oa-backend; java -jar build/libs/oa-backend-0.1.0.jar --server.port=8091; admin/123456

== 排除(gitignore, 可再生) ==
node_modules / oa-backend/build / .jdks / *.log / Backup-ERP-* / 弃用的OFBiz核心(只保留modern-ui)
完整文件夹备份见同目录 Backup-ERP-20260615-191517/ (含上述全部, 仅缺 node_modules)

时间戳: 20260615-191517

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 19:19:15 +08:00

180 lines
8.2 KiB
Java

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<SewageShiftHandover>> 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<SewageShiftHandover> 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<SewageShiftHandover> 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<SewageShiftHandover> 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<Void> 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<SewageShiftHandover> 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<List<SewageShiftHandover>> pending() {
return ApiResp.ok(handoverRepo.findByStatus("待接班"));
}
}