diff --git a/.gitignore b/.gitignore index 783f90a..67cb198 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ target/ .idea/ *.iml .DS_Store + +# 本地调试脚本与探针输出(不入库) +local-debug/ diff --git a/src/main/java/com/yunhai/svchall/model/svc/SvcModels.java b/src/main/java/com/yunhai/svchall/model/svc/SvcModels.java index a077a39..a42e9c5 100644 --- a/src/main/java/com/yunhai/svchall/model/svc/SvcModels.java +++ b/src/main/java/com/yunhai/svchall/model/svc/SvcModels.java @@ -174,6 +174,26 @@ public final class SvcModels { private String flowGuid; @Size(max = 500) private String applyUrl; + // ===== 服务承诺(P1-1):管理端录入,全部可空 ===== + /** 协办部门(顿号分隔文本快照) */ + @Size(max = 500) + private String coopDepts; + /** 经办人员 */ + @Size(max = 64) + private String handlerName; + /** 办理时间(办公时段,区别于办理时限) */ + @Size(max = 200) + private String handleTimeDesc; + /** 跑现场次数(0=零跑动) */ + private Integer runCount; + /** 是否快递送达:0 否 / 1 是(到付)/ 2 是(学校承担) */ + private Integer expressFlag; + /** 收费标准 */ + @Size(max = 200) + private String feeDesc; + /** 收费依据 */ + @Size(max = 200) + private String feeBasis; private Integer sortNo; /** 指南附件 id 列表(保存时全量重绑 topic_type=svc_item_guide) */ private List attachmentIds; @@ -207,6 +227,14 @@ public final class SvcModels { private String formCode; private String flowGuid; private String applyUrl; + // ===== 服务承诺(P1-1):编辑页回显,与 SvcItemSaveRequest 同名 ===== + private String coopDepts; + private String handlerName; + private String handleTimeDesc; + private Integer runCount; + private Integer expressFlag; + private String feeDesc; + private String feeBasis; private Integer sortNo; private Integer status; private LocalDateTime publishTime; @@ -241,6 +269,13 @@ public final class SvcModels { vo.setFormCode(item.getFormCode()); vo.setFlowGuid(item.getFlowGuid()); vo.setApplyUrl(item.getApplyUrl()); + vo.setCoopDepts(item.getCoopDepts()); + vo.setHandlerName(item.getHandlerName()); + vo.setHandleTimeDesc(item.getHandleTimeDesc()); + vo.setRunCount(item.getRunCount()); + vo.setExpressFlag(item.getExpressFlag()); + vo.setFeeDesc(item.getFeeDesc()); + vo.setFeeBasis(item.getFeeBasis()); vo.setSortNo(item.getSortNo()); vo.setStatus(item.getStatus()); vo.setPublishTime(item.getPublishTime()); diff --git a/src/main/java/com/yunhai/svchall/service/impl/ServiceItemService.java b/src/main/java/com/yunhai/svchall/service/impl/ServiceItemService.java index 5ff2cc6..57813be 100644 --- a/src/main/java/com/yunhai/svchall/service/impl/ServiceItemService.java +++ b/src/main/java/com/yunhai/svchall/service/impl/ServiceItemService.java @@ -199,6 +199,14 @@ public class ServiceItemService { item.setFormCode(emptyToNull(req.getFormCode())); item.setFlowGuid(emptyToNull(req.getFlowGuid())); item.setApplyUrl(applyUrl); + // 服务承诺(P1-1):空串归一为 null,避免库里出现 "" 与 null 两种空值 + item.setCoopDepts(emptyToNull(req.getCoopDepts())); + item.setHandlerName(emptyToNull(req.getHandlerName())); + item.setHandleTimeDesc(emptyToNull(req.getHandleTimeDesc())); + item.setRunCount(req.getRunCount()); + item.setExpressFlag(req.getExpressFlag()); + item.setFeeDesc(emptyToNull(req.getFeeDesc())); + item.setFeeBasis(emptyToNull(req.getFeeBasis())); item.setSortNo(req.getSortNo() == null ? 0 : req.getSortNo()); item = itemRepository.save(item); diff --git a/src/test/java/com/yunhai/svchall/model/svc/SvcItemPromiseFieldsTest.java b/src/test/java/com/yunhai/svchall/model/svc/SvcItemPromiseFieldsTest.java new file mode 100644 index 0000000..792ef55 --- /dev/null +++ b/src/test/java/com/yunhai/svchall/model/svc/SvcItemPromiseFieldsTest.java @@ -0,0 +1,88 @@ +package com.yunhai.svchall.model.svc; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.yunhai.svchall.entity.ServiceItem; +import com.yunhai.svchall.model.svc.SvcModels.SvcItemEditVo; +import com.yunhai.svchall.model.svc.SvcModels.SvcItemSaveRequest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +/** + * 服务承诺字段(P1-1)的入参与回显契约测试。 + *

+ * 守两件事: + * ① 管理端前端用的字段名 → {@link SvcItemSaveRequest} 能反序列化进来(Jackson 默认忽略未知字段, + * 名字写错不会报错、只会静默丢数据,必须显式测); + * ② {@link SvcItemEditVo#of} 能把实体上的 7 个字段原样映射到编辑页回显。 + *

+ * 不测 adminSave 的落库:那需要 mock repository,价值低于上面两条(字段名对齐是最易错点)。 + */ +class SvcItemPromiseFieldsTest { + + private static final ObjectMapper MAPPER = new ObjectMapper(); + + @Test + @DisplayName("SaveRequest 能接住前端传来的 7 个承诺字段(字段名不得漂移)") + void saveRequestDeserializesPromiseFields() throws Exception { + String json = "{" + + "\"coopDepts\":\"组织部、教务处\"," + + "\"handlerName\":\"田老师\"," + + "\"handleTimeDesc\":\"工作日 08:00-11:45\"," + + "\"runCount\":1," + + "\"expressFlag\":2," + + "\"feeDesc\":\"50 元\"," + + "\"feeBasis\":\"浙价费〔2020〕1 号\"" + + "}"; + + SvcItemSaveRequest req = MAPPER.readValue(json, SvcItemSaveRequest.class); + + assertEquals("组织部、教务处", req.getCoopDepts()); + assertEquals("田老师", req.getHandlerName()); + assertEquals("工作日 08:00-11:45", req.getHandleTimeDesc()); + assertEquals(1, req.getRunCount()); + assertEquals(2, req.getExpressFlag()); + assertEquals("50 元", req.getFeeDesc()); + assertEquals("浙价费〔2020〕1 号", req.getFeeBasis()); + } + + @Test + @DisplayName("EditVo.of 把实体 7 个承诺字段映射到回显") + void editVoMapsPromiseFields() { + ServiceItem item = new ServiceItem(); + item.setId(12); + item.setSiteCode("yhms"); + item.setItemCode("teacher-onboard"); + item.setTitle("教师入职办理"); + item.setCoopDepts("组织部、教务处"); + item.setHandlerName("田老师"); + item.setHandleTimeDesc("工作日 08:00-11:45"); + item.setRunCount(0); + item.setExpressFlag(1); + item.setFeeDesc("无"); + item.setFeeBasis(null); + + SvcItemEditVo vo = SvcItemEditVo.of(item); + + assertEquals("组织部、教务处", vo.getCoopDepts()); + assertEquals("田老师", vo.getHandlerName()); + assertEquals("工作日 08:00-11:45", vo.getHandleTimeDesc()); + assertEquals(0, vo.getRunCount()); + assertEquals(1, vo.getExpressFlag()); + assertEquals("无", vo.getFeeDesc()); + assertNull(vo.getFeeBasis()); + } + + @Test + @DisplayName("承诺字段全空时 SaveRequest 不报错(全部可空)") + void saveRequestAllowsNulls() throws Exception { + SvcItemSaveRequest req = MAPPER.readValue("{\"title\":\"x\"}", SvcItemSaveRequest.class); + + assertNull(req.getCoopDepts()); + assertNull(req.getRunCount()); + assertNull(req.getExpressFlag()); + assertNull(req.getFeeDesc()); + } +}