修复同卡复核重复字段校验
This commit is contained in:
@@ -807,9 +807,14 @@ public class ReservationTaskWorkflowServiceImpl implements ReservationTaskWorkfl
|
||||
Map<String, ReservationTaskCardFieldDefinition> definitionByPath = new LinkedHashMap<>();
|
||||
activeDefinitions.forEach(definition -> definitionByPath.put(definition.fieldPath(), definition));
|
||||
List<ManualReviewResolutionFieldOverrideResult> results = new ArrayList<>();
|
||||
Set<String> seenPointers = new LinkedHashSet<>();
|
||||
Set<String> seenFieldPaths = new LinkedHashSet<>();
|
||||
for (ManualReviewResolutionFieldOverrideRequest request : requests) {
|
||||
String fieldPointer = trimToNull(request == null ? null : request.fieldPointer());
|
||||
ReservationTaskCardFieldDefinition definition = findEditableDefinitionByPointer(definitionByPath, fieldPointer);
|
||||
if (!seenPointers.add(fieldPointer) || !seenFieldPaths.add(definition.fieldPath())) {
|
||||
throw reviewPointerDuplicateError(fieldPointer, definition.fieldPath());
|
||||
}
|
||||
results.add(new ManualReviewResolutionFieldOverrideResult(
|
||||
fieldPointer,
|
||||
definition.fieldPath(),
|
||||
@@ -818,6 +823,17 @@ public class ReservationTaskWorkflowServiceImpl implements ReservationTaskWorkfl
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建重复复核字段错误,避免 confirmed payload 后值覆盖前值但审计保留多条冲突记录。
|
||||
*/
|
||||
private ReservationTaskWorkflowException reviewPointerDuplicateError(String fieldPointer, String fieldPath) {
|
||||
return new ReservationTaskWorkflowException(
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"TASK_REVIEW_POINTER_DUPLICATE",
|
||||
"复核字段指针重复。",
|
||||
List.of(fieldPointer + ": 重复指向字段 " + fieldPath + "。"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 复核 pointer 白名单使用当前卡型的可编辑字段全集;展示条件由合并后的 activeDefinitions 再兜底校验。
|
||||
*/
|
||||
|
||||
@@ -1912,6 +1912,53 @@ class SuperAgentTaskResultControllerTest {
|
||||
assertThat(sourceTaskCount).isEqualTo(1L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectManualReviewResolutionWhenPointerIsDuplicated() throws Exception {
|
||||
captureSourceMessage("mail-v3-manual-review-duplicate-pointer-001");
|
||||
String body = typeKnownManualReviewBody(
|
||||
"mail-v3-manual-review-duplicate-pointer-001",
|
||||
"CNF-V3-MR-DUP-001",
|
||||
"2026-09-05",
|
||||
"2026-09-07");
|
||||
MvcResult createResult = mockMvc.perform(signedPost(body, "nonce-v3-manual-review-duplicate-pointer-001"))
|
||||
.andExpect(status().isCreated())
|
||||
.andReturn();
|
||||
String taskId = com.jayway.jsonpath.JsonPath.read(
|
||||
createResult.getResponse().getContentAsString(),
|
||||
"$.items[0].task_id");
|
||||
String orderId = com.jayway.jsonpath.JsonPath.read(
|
||||
createResult.getResponse().getContentAsString(),
|
||||
"$.items[0].order_id");
|
||||
|
||||
mockMvc.perform(post("/api/reservation/tasks/{taskId}/manual-review-resolutions", taskId)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("""
|
||||
{
|
||||
"confirmed_order_id": "%s",
|
||||
"field_overrides": [
|
||||
{
|
||||
"field_pointer": "/extracted_fields/pms_room_type_code",
|
||||
"value": "RM3"
|
||||
},
|
||||
{
|
||||
"field_pointer": "/extracted_fields/pms_room_type_code",
|
||||
"value": "RM4"
|
||||
}
|
||||
]
|
||||
}
|
||||
""".formatted(orderId)))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.error_code").value("TASK_REVIEW_POINTER_DUPLICATE"))
|
||||
.andExpect(jsonPath("$.details[0]").value(containsString("/extracted_fields/pms_room_type_code")));
|
||||
|
||||
String taskStatus = jdbcTemplate.queryForObject("""
|
||||
SELECT task_status
|
||||
FROM workflow_reservation_task
|
||||
WHERE id = ?
|
||||
""", String.class, Long.valueOf(taskId));
|
||||
assertThat(taskStatus).isEqualTo("PENDING_CONFIRM");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRejectManualReviewResolutionWhenMissingFieldsAreNotResolved() throws Exception {
|
||||
captureSourceMessage("mail-v3-manual-review-missing-001");
|
||||
|
||||
Reference in New Issue
Block a user