Merge branch 'master' into develop

This commit is contained in:
RB 2022-07-31 16:25:12 +08:00
commit b644bbee0a
4 changed files with 113 additions and 31 deletions

View file

@ -418,6 +418,9 @@ public class ApprovalStepService extends InternalPersistService {
if (useApprover == null) useApprover = UserService.SYSTEM_USER;
if (useApproval == null) useApproval = APPROVAL_NOID;
// 作废之前
cancelAliveSteps(recordId, null, null, null, false);
ID stepId = createStepIfNeed(recordId, useApproval,
FlowNode.NODE_AUTOAPPROVAL, useApprover, false, FlowNode.NODE_ROOT,
CalendarUtils.now(), getBatchNo(recordId, useApproval, FlowNode.NODE_ROOT));

View file

@ -34,6 +34,7 @@ import com.rebuild.core.service.general.series.SeriesGeneratorFactory;
import com.rebuild.core.service.notification.NotificationObserver;
import com.rebuild.core.service.query.QueryHelper;
import com.rebuild.core.service.trigger.*;
import com.rebuild.core.service.trigger.impl.AutoApproval;
import com.rebuild.core.service.trigger.impl.GroupAggregation;
import com.rebuild.core.support.i18n.Language;
import com.rebuild.core.support.task.TaskExecutors;
@ -95,44 +96,63 @@ public class GeneralEntityService extends ObservableService implements EntitySer
}
}
record = super.createOrUpdate(record);
if (details == null || details.isEmpty()) return record;
// 含明细
final boolean hasDetails = details != null && !details.isEmpty();
// 主记录+明细记录处理
String dtf = MetadataHelper.getDetailToMainField(record.getEntity().getDetailEntity()).getName();
ID mainid = record.getPrimary();
boolean checkDetailsRepeated = rcm == GeneralEntityServiceContextHolder.RCM_CHECK_DETAILS
|| rcm == GeneralEntityServiceContextHolder.RCM_CHECK_ALL;
// 先删除
for (Record d : details) {
if (d instanceof DeleteRecord) delete(d.getPrimary());
boolean hasAutoApprovalForDetails = false;
if (hasDetails) {
Entity de = record.getEntity().getDetailEntity();
TriggerAction[] hasTriggers = de == null ? null
: RobotTriggerManager.instance.getActions(de, TriggerWhen.APPROVED);
hasAutoApprovalForDetails = hasTriggers != null && hasTriggers.length > 0;
AutoApproval.setLazyAutoApproval();
}
// 再保存
for (Record d : details) {
if (d instanceof DeleteRecord) continue;
try {
record = super.createOrUpdate(record);
if (!hasDetails) return record;
if (checkDetailsRepeated) {
d.setID(dtf, mainid); // for check
// 主记录+明细记录处理
List<Record> repeated = getAndCheckRepeated(d, 20);
if (!repeated.isEmpty()) {
throw new RepeatedRecordsException(repeated);
final String dtf = MetadataHelper.getDetailToMainField(record.getEntity().getDetailEntity()).getName();
final ID mainid = record.getPrimary();
final boolean checkDetailsRepeated = rcm == GeneralEntityServiceContextHolder.RCM_CHECK_DETAILS
|| rcm == GeneralEntityServiceContextHolder.RCM_CHECK_ALL;
// 先删除
for (Record d : details) {
if (d instanceof DeleteRecord) delete(d.getPrimary());
}
// 再保存
for (Record d : details) {
if (d instanceof DeleteRecord) continue;
if (checkDetailsRepeated) {
d.setID(dtf, mainid); // for check
List<Record> repeated = getAndCheckRepeated(d, 20);
if (!repeated.isEmpty()) {
throw new RepeatedRecordsException(repeated);
}
}
if (d.getPrimary() == null) {
d.setID(dtf, mainid);
create(d);
} else {
update(d);
}
}
if (d.getPrimary() == null) {
d.setID(dtf, mainid);
create(d);
} else {
update(d);
return record;
} finally {
if (hasAutoApprovalForDetails) {
AutoApproval.executeLazyAutoApproval();
}
}
return record;
}
@Override
@ -152,8 +172,7 @@ public class GeneralEntityService extends ObservableService implements EntitySer
// 先更新
record = super.update(record);
// 传导给明细若有
// 仅分组聚合触发器
// 主记录修改时传导给明细若有以便触发分组聚合触发器
Entity de = record.getEntity().getDetailEntity();
if (de != null) {
TriggerAction[] hasTriggers = RobotTriggerManager.instance.getActions(de, TriggerWhen.UPDATE);
@ -699,6 +718,7 @@ public class GeneralEntityService extends ObservableService implements EntitySer
RobotTriggerManual triggerManual = new RobotTriggerManual();
// 传导给明细若有
// FIXME 此时明细可能尚未做好变更例如新建自动审批
Entity de = approvalRecord.getEntity().getDetailEntity();
TriggerAction[] hasTriggers = de == null ? null : RobotTriggerManager.instance.getActions(de,

View file

@ -17,13 +17,23 @@ import com.rebuild.core.service.trigger.ActionContext;
import com.rebuild.core.service.trigger.ActionType;
import com.rebuild.core.service.trigger.TriggerAction;
import com.rebuild.core.service.trigger.TriggerException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.NamedThreadLocal;
import java.util.ArrayList;
import java.util.List;
/**
* @author devezhao
* @since 2020/7/31
*/
@Slf4j
public class AutoApproval extends TriggerAction {
private static final ThreadLocal<List<AutoApproval>> LAZY_AUTOAPPROVAL = new NamedThreadLocal<>("Lazy AutoApproval");
private OperatingContext operatingContext;
public AutoApproval(ActionContext context) {
super(context);
}
@ -40,6 +50,15 @@ public class AutoApproval extends TriggerAction {
@Override
public void execute(OperatingContext operatingContext) throws TriggerException {
this.operatingContext = operatingContext;
List<AutoApproval> lazyed;
if ((lazyed = isLazyAutoApproval(false)) != null) {
lazyed.add(this);
log.info("Lazy AutoApproval : {}", lazyed);
return;
}
ID recordId = operatingContext.getAnyRecord().getPrimary();
String useApprover = ((JSONObject) actionContext.getActionContent()).getString("useApprover");
String useApproval = ((JSONObject) actionContext.getActionContent()).getString("useApproval");
@ -49,4 +68,44 @@ public class AutoApproval extends TriggerAction {
ID.isId(useApprover) ? ID.valueOf(useApprover) : null,
ID.isId(useApproval) ? ID.valueOf(useApproval) : null);
}
@Override
public String toString() {
String s = super.toString();
if (operatingContext != null) s += "#OperatingContext:" + operatingContext;
return s;
}
// --
/**
* 跳过自动审批
* @see #isLazyAutoApproval(boolean)
*/
public static void setLazyAutoApproval() {
LAZY_AUTOAPPROVAL.set(new ArrayList<>());
}
/**
* @return
*/
public static List<AutoApproval> isLazyAutoApproval(boolean once) {
List<AutoApproval> lazyed = LAZY_AUTOAPPROVAL.get();
if (lazyed != null && once) LAZY_AUTOAPPROVAL.remove();
return lazyed;
}
/**
* @return
*/
public static int executeLazyAutoApproval() {
List<AutoApproval> lazyed = isLazyAutoApproval(true);
if (lazyed != null) {
for (AutoApproval a : lazyed) {
log.info("Lazy AutoApproval execute : {}", a);
a.execute(a.operatingContext);
}
}
return lazyed == null ? 0 : lazyed.size();
}
}

View file

@ -610,13 +610,13 @@ class RbFormElement extends React.Component {
*/
checkValue() {
const err = this.isValueError()
this.setState({ hasError: err || null })
const errMsg = err ? this.props.label + err : null
if (this.isValueUnchanged() && !this.props.$$$parent.isNew) {
if (err) this.props.$$$parent.setFieldValue(this.props.field, this.state.value, errMsg)
else this.props.$$$parent.setFieldUnchanged(this.props.field, this.state.value)
} else {
this.setState({ hasError: err })
this.props.$$$parent.setFieldValue(this.props.field, this.state.value, errMsg)
}
}