@@ -85,6 +85,7 @@ public class ReservationTaskWorkflowServiceImpl implements ReservationTaskWorkfl
private static final String PAYLOAD_SOURCE_DRAFT = " TASK_DRAFT " ;
private static final String PAYLOAD_SOURCE_CONFIRMATION = " TASK_CONFIRMATION " ;
private static final String PAYLOAD_SOURCE_MANUAL_REVIEW_RESOLUTION = " MANUAL_REVIEW_RESOLUTION " ;
private static final String V3_CATALOG_CODE = " M002V3 " ;
private static final String OPERA_OPERATION_CODE_PRECHECK = " SIMULATE_PRECHECK " ;
private static final String OPERA_OPERATION_CODE_WRITE = " SIMULATE_WRITE " ;
private static final int MAX_QUEUE_ORDER_RETRY = 5 ;
@@ -825,12 +826,15 @@ public class ReservationTaskWorkflowServiceImpl implements ReservationTaskWorkfl
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 ( ) );
String fieldPath = trimToNull ( request = = null ? null : request . fieldPath ( ) ) ;
ReservationTaskCardFieldDefinition definition =
findEditableDefinitionByOverride ( definitionByPath , fieldPointer , fieldPath ) ;
String resultFieldPointer = fieldPointer ! = null ? fieldPointer : fieldPointerFor ( definition . fieldPath ( ) ) ;
if ( ! seenPointers . add ( resultFieldPointer ) | | ! seenFieldPaths . add ( definition . fieldPath ( ) ) ) {
throw reviewPointerDuplicateError ( resultFieldPointer , definition . fieldPath ( ) ) ;
}
results . add ( new ManualReviewResolutionFieldOverrideResult (
f ieldPointer,
resultF ieldPointer,
definition . fieldPath ( ) ,
legacyFieldPathFor ( definition . fieldPath ( ) ) ,
request . value ( ) ) ) ;
@@ -883,6 +887,48 @@ public class ReservationTaskWorkflowServiceImpl implements ReservationTaskWorkfl
throw reviewPointerError ( fieldPointer ) ;
}
/**
* 按复核请求定位可编辑字段,支持 JSON Pointer、P0 主 field_path 和旧扁平 field_path。
*/
private ReservationTaskCardFieldDefinition findEditableDefinitionByOverride (
Map < String , ReservationTaskCardFieldDefinition > definitionByPath ,
String fieldPointer ,
String fieldPath ) {
ReservationTaskCardFieldDefinition pointerDefinition = null ;
if ( fieldPointer ! = null ) {
pointerDefinition = findEditableDefinitionByPointer ( definitionByPath , fieldPointer ) ;
}
ReservationTaskCardFieldDefinition pathDefinition = null ;
if ( fieldPath ! = null ) {
pathDefinition = findEditableDefinitionByFieldPath ( definitionByPath , fieldPath ) ;
}
if ( pointerDefinition ! = null & & pathDefinition ! = null
& & ! pointerDefinition . fieldPath ( ) . equals ( pathDefinition . fieldPath ( ) ) ) {
throw reviewPointerError ( fieldPointer + " / " + fieldPath ) ;
}
if ( pointerDefinition ! = null ) {
return pointerDefinition ;
}
if ( pathDefinition ! = null ) {
return pathDefinition ;
}
throw reviewPointerError ( null ) ;
}
/**
* 按矩阵字段路径查找可编辑字段,先将旧扁平路径归一化到 P0 主路径。
*/
private ReservationTaskCardFieldDefinition findEditableDefinitionByFieldPath (
Map < String , ReservationTaskCardFieldDefinition > definitionByPath ,
String fieldPath ) {
String canonicalFieldPath = canonicalSubmittedFieldPath ( definitionByPath , fieldPath ) ;
ReservationTaskCardFieldDefinition definition = definitionByPath . get ( canonicalFieldPath ) ;
if ( definition = = null | | ! isYes ( definition . editable ( ) ) ) {
throw reviewPointerError ( fieldPath ) ;
}
return definition ;
}
/**
* 将 RFC 6901 JSON Pointer 转换为可能的矩阵 field_path, 兼容数组下标到 [] 与旧扁平路径。
*/
@@ -1223,7 +1269,7 @@ public class ReservationTaskWorkflowServiceImpl implements ReservationTaskWorkfl
}
/**
* 按字段矩阵执行校验。复核解阻场景允许只读证据字段缺失,因为用户无法在该接口补齐 。
* 按字段矩阵执行校验。P0 V3 业务事件缺省旧 visible_reason 时做窄口兼容,其他只读必填仍要校验 。
*/
private List < String > validateDefinitionValues (
ReservationTaskSnapshot task ,
@@ -1237,7 +1283,7 @@ public class ReservationTaskWorkflowServiceImpl implements ReservationTaskWorkfl
for ( ReservationTaskCardFieldDefinition definition : activeDefinitions ) {
Object value = valueForField ( aiPayload , editedValues , definition . fieldPath ( ) ) ;
if ( validateRequired & & isMissingRequired ( task , definition , aiPayload , editedValues , value ) ) {
if ( allowMissingReadonlyRequired & & ! isYes ( definition . editable ( ) ) ) {
if ( allowMissingReadonlyRequired & & isReadonlyRequiredMissingAllowed ( definition , aiPayload ) ) {
continue ;
}
errors . add ( definition . fieldPath ( ) + " : 必填字段缺失。 " ) ;
@@ -1252,6 +1298,18 @@ public class ReservationTaskWorkflowServiceImpl implements ReservationTaskWorkfl
return errors ;
}
/**
* 兼容 0711 P0 业务事件: V3 message_event 没有旧矩阵根 visible_reason 字段,但保留 relevant_message_excerpt 作为证据。
*/
private boolean isReadonlyRequiredMissingAllowed (
ReservationTaskCardFieldDefinition definition ,
JsonNode aiPayload ) {
return ! isYes ( definition . editable ( ) )
& & " visible_reason " . equals ( definition . fieldPath ( ) )
& & V3_CATALOG_CODE . equals ( aiPayload . path ( " catalog_code " ) . asText ( ) )
& & aiPayload . path ( " v3_message_event " ) . isObject ( ) ;
}
/**
* 生成字段定义路径集合,用于最终确认时校验全部展示字段。
*/