|
|
|
@ -358,17 +358,14 @@ public class WriteBackOrchestrator implements BotpReverseWriteFacade { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 源单行关闭:关闭标记始终反映「当前是否满足关闭条件」。 |
|
|
|
* 源单关闭:关闭标记始终反映「当前是否满足关闭条件」。 |
|
|
|
* |
|
|
|
* |
|
|
|
* <p><b>按源分录行逐行求值</b>,不是拿表头求值再一刀切——「已下推数量 >= 数量」这类条件 |
|
|
|
* <p><b>单据级语义</b>:条件比较的是整张源单的数量(下推量与回写量相等即关闭), |
|
|
|
* 引用的是分录行上的字段,用表头求值永远取不到值。</p> |
|
|
|
* 所以写的是<b>源单主表</b>那一行,不是分录行。多对一时一张目标单可能对应多张源单, |
|
|
|
|
|
|
|
* 按源单分别求值、分别关闭。</p> |
|
|
|
* |
|
|
|
* |
|
|
|
* <p><b>条件成立写 1,不成立写 0</b>:撤销 / 弃审把数量退回来之后条件不再成立, |
|
|
|
* <p><b>条件成立写 1,不成立写 0</b>:撤销 / 弃审把数量退回来之后条件不再成立, |
|
|
|
* 这里会把标记清掉、解除关闭(PRD §6.3 ④)。只写 1 不写 0 的话,被关掉的行永远关着。</p> |
|
|
|
* 这里会把标记清掉、解除关闭(PRD §6.3 ④)。只写 1 不写 0 的话,被关掉的单永远关着。</p> |
|
|
|
* |
|
|
|
|
|
|
|
* <p>条件里的字段引用建议写成 {@code 分录表.分录表.字段} 形式(如 |
|
|
|
|
|
|
|
* {@code pur_apply_entry.pur_apply_entry.orderqty >= pur_apply_entry.pur_apply_entry.qty}), |
|
|
|
|
|
|
|
* 这样在行上下文里能直接解析。</p> |
|
|
|
|
|
|
|
* |
|
|
|
* |
|
|
|
* @param rule 反写规则。 |
|
|
|
* @param rule 反写规则。 |
|
|
|
* @param entries 关联关系。 |
|
|
|
* @param entries 关联关系。 |
|
|
|
@ -379,21 +376,25 @@ public class WriteBackOrchestrator implements BotpReverseWriteFacade { |
|
|
|
if (StringUtils.isBlank(expression)) { |
|
|
|
if (StringUtils.isBlank(expression)) { |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
String sourceTable = resolveTableName(String.valueOf(rule.getSourceDocuments())); |
|
|
|
|
|
|
|
if (StringUtils.isBlank(sourceTable)) { |
|
|
|
|
|
|
|
log.warn("反写规则未配置源单或源单元数据不存在,跳过源单关闭。规则id={}", rule.getId()); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Map<String, List<ConvertRelationEntry>> bySourceBill = new LinkedHashMap<>(); |
|
|
|
for (ConvertRelationEntry entry : entries) { |
|
|
|
for (ConvertRelationEntry entry : entries) { |
|
|
|
String table = entry.getSourceEntryNumber(); |
|
|
|
if (StringUtils.isBlank(entry.getSourceId())) { |
|
|
|
if (StringUtils.isBlank(table)) { |
|
|
|
continue; |
|
|
|
// 走了 srcbillid 回退分支时拿不到源分录表名,无法安全写回,跳过
|
|
|
|
|
|
|
|
log.warn("源分录表名缺失(可能走了 srcbillid 回退分支),跳过源单行关闭。规则id={}", rule.getId()); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
ObjectValue sourceRow = queryRow(table, entry.getSourceEntryId()); |
|
|
|
bySourceBill.computeIfAbsent(entry.getSourceId(), k -> new ArrayList<>()).add(entry); |
|
|
|
if (sourceRow == null) { |
|
|
|
} |
|
|
|
|
|
|
|
for (String sourceBillId : bySourceBill.keySet()) { |
|
|
|
|
|
|
|
ObjectValue sourceBill = queryRow(sourceTable, sourceBillId); |
|
|
|
|
|
|
|
if (sourceBill == null) { |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
// 关闭标记始终反映「当前是否满足关闭条件」:正向推满时置 1,
|
|
|
|
boolean shouldClose = conditionHit(expression, null, sourceBill); |
|
|
|
// 撤销/弃审把数量退回来之后条件不再成立,这里会写回 0 解除关闭(PRD §6.3 ④)。
|
|
|
|
writeSourceRow(sourceTable, sourceBillId, BotpRuleConstant.COLUMN_CLOSED_FLAG, shouldClose ? 1 : 0); |
|
|
|
boolean shouldClose = conditionHit(expression, null, sourceRow); |
|
|
|
|
|
|
|
writeSourceRow(table, entry.getSourceEntryId(), BotpRuleConstant.COLUMN_CLOSED_FLAG, shouldClose ? 1 : 0); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -425,6 +426,25 @@ public class WriteBackOrchestrator implements BotpReverseWriteFacade { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
|
|
|
|
* 按单元数据 id 解析表名。 |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param headId 单元数据 id。 |
|
|
|
|
|
|
|
* @return 表名;解析不到时返回 null。 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
private String resolveTableName(String headId) { |
|
|
|
|
|
|
|
if (StringUtils.isBlank(headId)) { |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
OnlFormHead head = onlFormHeadService.getById(Long.valueOf(headId)); |
|
|
|
|
|
|
|
return head == null ? null : head.getTableName(); |
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
|
|
|
|
log.warn("解析单元数据表名失败,headId={},原因={}", headId, e.getMessage()); |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 覆盖方式记原值:把反写前的源单字段值写进关联关系,撤销时读出来恢复。 |
|
|
|
* 覆盖方式记原值:把反写前的源单字段值写进关联关系,撤销时读出来恢复。 |
|
|
|
* |
|
|
|
* |
|
|
|
* @param entry 关联关系。 |
|
|
|
* @param entry 关联关系。 |
|
|
|
@ -563,7 +583,7 @@ public class WriteBackOrchestrator implements BotpReverseWriteFacade { |
|
|
|
if (entries.isEmpty()) { |
|
|
|
if (entries.isEmpty()) { |
|
|
|
return Collections.emptyList(); |
|
|
|
return Collections.emptyList(); |
|
|
|
} |
|
|
|
} |
|
|
|
entries.sort((a, b) -> Integer.compare(parseOrder(a.getSerialNumber()), parseOrder(b.getSerialNumber()))); |
|
|
|
entries.sort(Comparator.comparing(ConvertPluginEntry::getSerialNumber, Comparator.nullsLast(Comparator.naturalOrder()))); |
|
|
|
List<WriteBackPlugIn> plugins = new ArrayList<>(entries.size()); |
|
|
|
List<WriteBackPlugIn> plugins = new ArrayList<>(entries.size()); |
|
|
|
for (ConvertPluginEntry entry : entries) { |
|
|
|
for (ConvertPluginEntry entry : entries) { |
|
|
|
plugins.add(plugInLoader.load(entry.getClassName(), WriteBackPlugIn.class)); |
|
|
|
plugins.add(plugInLoader.load(entry.getClassName(), WriteBackPlugIn.class)); |
|
|
|
@ -782,23 +802,6 @@ public class WriteBackOrchestrator implements BotpReverseWriteFacade { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 解析插件执行顺序,非数字排在最后。 |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param serialNumber 配置里的顺序值。 |
|
|
|
|
|
|
|
* @return 可比较的数值。 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
private static int parseOrder(String serialNumber) { |
|
|
|
|
|
|
|
if (StringUtils.isBlank(serialNumber)) { |
|
|
|
|
|
|
|
return Integer.MAX_VALUE; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
return Integer.parseInt(serialNumber.trim()); |
|
|
|
|
|
|
|
} catch (NumberFormatException e) { |
|
|
|
|
|
|
|
return Integer.MAX_VALUE; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* 校验请求入参。 |
|
|
|
* 校验请求入参。 |
|
|
|
* |
|
|
|
* |
|
|
|
* @param request 反写触发请求。 |
|
|
|
* @param request 反写触发请求。 |
|
|
|
|