0%

实习-03-MDD框架学习

MDD框架学习

任务

https://bip-daily.yyuap.com/#/
用户名:19908188888
密码: test0630

验证码666666

从图书订单TCC开始看,跟代码进行逻辑梳理

  • 首先是进入页面

image-20230202170945908

image-20230202171010198

  • 查看构建

image-20230202171110864

image-20230202171203111

可以对应上开发和实际页面,点击配置后进行代码跟进

order–>stock–>pay

  • 工程间调用关系梳理

image-20230201111246717

  • 工程中,分别学习

image-20230202171333291

image-20230202171348768

image-20230202171404751

看的过程中,结合mdd工程代码,进行学习

采用double shift进行查找yts相关进行学习,结合yts评审文档中mdd和yts结合过程,梳理yts在mdd中的作用,结合方式等

image-20230202171448043

学习笔记

总览

全局:

image-20230214151116644

上方:

image-20230214150755125

左侧:

image-20230214151429919

右侧为:

image-20230214151002135

下左侧为:

下右侧为:

image-20230214151053561

配置保存流程–跟进代码.md

页面操作及规则查看

image-20230203100154865

对应

image-20230203100239463

查看保存过程

image-20230203100319880

规则详细内容

com.yonyou.ucf.mdd.ext.bill.rule.biz.FillPKRule
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@Service("fillPKRule")
public class FillPKRule extends AbstractCommonRule {
public FillPKRule() {
}

public RuleExecuteResult execute(BillContext billContext, Map<String, Object> paramMap) throws Exception {
//列表查询dto:查询条件、分页、汇总显示
BillDataDto billData = (BillDataDto)this.getParam(paramMap);

List<BizObject> bills = this.getBills(billContext, paramMap);
FillFkDao.execute(billContext.getFullname(), bills);
return new RuleExecuteResult();
}
}

### com.yonyou.ucf.mdd.ext.dao.meta.biz.FillFkDao

public static <T extends BizObject> void execute(String fullname, List<T> bills) throws Exception {
initIPKGeneratorConfig();
Map<String, KeyIterator> insertEntityPK = ipkGeneratorConfig.configMap();


Entity entity=MetaDaoHelper.getEntity(fullname);
// 遍历所有对象
for (BizObject bill : bills) {

ObjectHierarchyBuilder.build(bill, entity);
// 设置主键
//20200722 只支持number 类型 ObjectPKWalker pkWalker = new ObjectPKWalker(insertEntityPK);
MddObjectPKWalker pkWalker = new MddObjectPKWalker(insertEntityPK);
ObjectWalker.walk(pkWalker, bill, fullname);

// 设置关联关系字段值(主子实体中,子对象外键)
ObjectFKWalker fkWalker = new ObjectFKWalker();
// 在一次遍历中通过next可以设置多个walker
// ChainWalker<Association, BizObject> otherWalker = new ...;
// fkWalker.setNext(otherWalker);
ObjectWalker.walk(fkWalker, bill, fullname);
}

}
com.yonyou.ucf.mdd.ext.bill.rule.check.CheckUniqueRule
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
@Service("checkUniqueRule")
public class CheckUniqueRule extends AbstractCommonRule {
private static final Logger log = LoggerFactory.getLogger(CheckUniqueRule.class);

public CheckUniqueRule() {
}

public RuleExecuteResult execute(BillContext billContext, Map<String, Object> paramMap) throws Exception {
if (billContext == null) {
return new RuleExecuteResult();
} else {
List<BizObject> bills = this.getBills(billContext, paramMap);
if (null != bills && bills.size() != 0) {
Entity entity = MetaDaoHelper.getEntity(billContext.getFullname());
if (null == entity) {
throw new Exception("查询元数据失败:" + billContext.getFullname());
} else {
ServiceSupportHolder holder = new ServiceSupportHolder(billContext, paramMap, bills, entity);
String config = this.getConfig();
holder.setConfig(config);
BillDataDto billDataDto = (BillDataDto)this.getParam(paramMap);
holder.setBillData(billDataDto);
IServiceSupportApi iServiceSupportApi = (IServiceSupportApi)AppContext.getBean(CheckUniqueSupportService.class);
return (RuleExecuteResult)iServiceSupportApi.execute(holder);
}
} else {
return new RuleExecuteResult();
}
}
}
}


### com.yonyou.ucf.mdd.support.abs.AbstractServiceSupport
public Object execute(ServiceSupportHolder holder) throws Exception {
beforeHandler(holder); //空
Object resultHandler = doExecute(holder);
afterExecute(holder, resultHandler); //空
return resultHandler;
}

### com.yonyou.ucf.mdd.support.support.CheckUniqueSupportService
@Override
protected Object doExecute(ServiceSupportHolder holder) throws Exception {
IDoBillService iDoBillService = getBeanDo(ServiceSupportStatic.CheckUnique.DO);
return iDoBillService.doExecute(holder);
}

### com.yonyou.ucf.mdd.support.support.check.checkunique.DoExecuteCheckUniqueService
@Override
public Object doExecute(ServiceSupportHolder holder) throws Exception {
BillDataDto item = holder.getBillData();
//是否check具体某个属性比如check_name,check_code
boolean isHasItem = null == item.getItem() ? false : true;
if (isHasItem) {
CheckItem checkItem = new Gson().fromJson(item.getItem(), CheckItem.class);
if (null == checkItem || checkItem.getKey() == null) {
return new RuleExecuteResult();
}
}
Entity entity = holder.getEntity();
//构建检查唯一性的BO对象
CheckUnionBO checkUnionBO = createCheckUnionBO(holder);
//待回滚的参数 并发唯一了
List<String> needRollList = new ArrayList<>();
List<BizObject> bills = holder.getBillList();
//是否支持内存check
try {
boolean autoCode = checkUnionBO.isAutoCode();
List<Map<String, Object>> codeTempDataCaches = new ArrayList<>();
// 自动编码下需要把编码换成UUID,防止并发时被唯一校验控制,在UpdateBillCodeRule由编码规则统一控制
if (!isHasItem && autoCode) {
codeTempDataCaches = checkUniqueCodeService.writeTempCode(bills, entity, holder.getBillContext(), holder.getParamMap());
}
//内存+redis检查
checkLocalUniqueService.checkUnionKeyObJVM(holder.getBillContext(), entity, checkUnionBO, bills, needRollList);
//数据库检查 联合唯一性校验, 当校验参数为 null 用 is null 拼接条件
UniqueCheckWalker uniqueCheckWalker = new UniqueCheckWalker(AppContext.getPartitionContextData(entity, true), false);
if (!isHasItem) {
checkDbUniqueService.checkUnionWithOutItem(holder, bills, entity, checkUnionBO.isCheckChild(), uniqueCheckWalker);
if (autoCode) {
checkUniqueCodeService.reWriteCode(codeTempDataCaches, bills, autoCode);
}
} else {
checkDbUniqueService.checkUnionWithItem(holder.getBillContext(), bills, item, entity, uniqueCheckWalker);
}
} finally {
if (null != needRollList && needRollList.size() > 0) {
if (TransactionSynchronizationManager.isActualTransactionActive()) {
TransactionSynchronizationManager.registerSynchronization(new DoExecuteAfterTransactionCompletion(needRollList));
}
}
}
return new RuleExecuteResult();
}
com.yonyou.ucf.mdd.ext.bill.rule.crud.SaveBillRule
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
@Service("saveBillRule")
public class SaveBillRule extends AbstractCommonRule {
private static final Logger log = LoggerFactory.getLogger(SaveBillRule.class);

public SaveBillRule() {
}

@ResubmitAnnotations
public RuleExecuteResult execute(BillContext billContext, Map<String, Object> paramMap) throws Exception {
return this.executeCommon(billContext, paramMap);
}

public RuleExecuteResult executeCommon(BillContext billContext, Map<String, Object> paramMap) throws Exception {
List<BizObject> bills = this.getBills(billContext, paramMap);
Entity entity = StringUtils.isBlank(billContext.getFullname()) ? null : IMetaUtils.entity(billContext.getFullname());
ServiceSupportHolder holder = new ServiceSupportHolder(billContext, paramMap, bills, entity);
holder.setcBillNo(billContext.getBillnum());
this.extendEnhance(holder);
IServiceSupportApi iServiceSupportApi = (IServiceSupportApi)AppContext.getBean(SaveBillSupportService.class);
return (RuleExecuteResult)iServiceSupportApi.execute(holder);
}

protected void extendEnhance(ServiceSupportHolder holder) {
holder.getAttribute().setAttr("saveRealAutoCode", false);
}
}


### com.yonyou.ucf.mdd.support.abs.AbstractServiceSupport
public Object execute(ServiceSupportHolder holder) throws Exception {
beforeHandler(holder);
Object resultHandler = doExecute(holder);
afterExecute(holder, resultHandler);
return resultHandler;
}

protected abstract Object doExecute(ServiceSupportHolder holder) throws Exception;


### com.yonyou.ucf.mdd.support.support.SaveBillSupportService
@Override
protected Object doExecute(ServiceSupportHolder holder) throws Exception {
IDoBillService iDoBillService = getBeanDo(ServiceSupportStatic.Save.DO);
return iDoBillService.doExecute(holder);
}

### com.yonyou.ucf.mdd.support.support.save.DoExecuteSaveBillService
/**
*
* @param holder
* @return
* @throws Exception
*
* @author Seraph
* @date 2021/5/2710:57 PM
*/
@Override
public Object doExecute(ServiceSupportHolder holder) throws Exception {
List<BizObject> bills = holder.getBillList();
for (BizObject bill : bills) {
checkRelevantRuleVerify(holder,bill);
executeOneBill(holder, bill);
}
return new RuleExecuteResult();
}

/**
*
* @param holder
* @param bill
* @throws Exception
*
* @author Seraph
* @date 2021/5/2710:57 PM
*/
@Override
public void executeOneBill(ServiceSupportHolder holder, BizObject bill) throws Exception {
BillContext billContext = holder.getBillContext();
boolean isInsert = EntityStatus.Insert == bill.getEntityStatus() ? true : false;
setAudit(isInsert, bill, holder.getEntity().fullname());
BarCodeSupport.generateBarCode(billContext, holder.getEntity(), bill);//处理条形码
setStatusInfoWhenInsert(holder,Status.newopen, bill, isInsert); //设置单据状态
dealSupportBpm(bill, billContext, isInsert);//处理工作流
String code = getAndDealCode(holder, billContext, bill, isInsert); //获取处置编码规则

//保存业务逻辑
Object result = saveBillServiceImpl.executeSave(billContext, bill, holder.getParamMap(), holder.getEntity(), isInsert);

//重置编码规则
if (null != code) {
bill.set("code", code);
}

BillSaveResult billSaveResult = (BillSaveResult) result;
String partitionWhereCondition = saveBillServiceImpl.buildQueryWhere4UpdateTree(holder.getEntity(), billContext); //构建扩展分词条件
updateTree(bill, billContext.getFullname(), AppContext.getTenantId(), billSaveResult, partitionWhereCondition); //更新树
// sendTimeLineSnapshot(billContext, bill, holder.getParamMap(), isInsert); //新增时上传时间轴快照
}


### com.yonyou.ucf.mdd.ext.bill.service.SaveBillServiceImpl
/**
* @see SaveBillServiceImpl#executeSave(com.yonyou.ucf.mdd.ext.model.BillContext, org.imeta.orm.base.BizObject, java.util.Map, org.imeta.core.model.Entity, java.lang.Boolean)
* @see InsertSqlExecutor#execute(org.imeta.core.model.Entity, java.util.List)
* @see UpdateSqlExecutor#execute(org.imeta.core.model.Entity, java.util.List)
*
* <p>
* execute insert or update with _statis value <code>String</code>
* </p>
*
* @param billContext billContext is one thread context {@link BillContext} in the variable has props context {@link Map} <code>null</code>save Resubmit key and other So.
* * fullname : metaUri of metaServer is the index of entity of meta
* @param bill business data in {@link com.yonyou.ucf.mdd.ext.bill.dto.BillDataDto}
* @param paramMap Singleton instance in rule china {@link Map} ,the request DTO in paramMap when in rule ,the DTO is instance of {@link BizObject} Array
* * when complete this rule set paramMap for return
* @param entity meta entity in metaServer
* @param isInert _statis value <code>String</code> insert or update
*
* @return execute result
* @throws Exception
*/
@Override
public Object executeSave(BillContext billContext, BizObject bill, Map<String, Object> paramMap, Entity entity, Boolean isInert) throws Exception {
try {
if (isInert) {
return executeInsert(billContext, bill, paramMap, entity);
}
return executeUpdate(billContext, bill, entity);
}catch (MddZeroResultMsgException zr){
throw new MddVouchStateMsgException(MsgExceptionCode.BILL_CHANGED_PLEASE_REFRESH);
}
}

/**
* @see SaveBillServiceImpl#executeSave(com.yonyou.ucf.mdd.ext.model.BillContext, org.imeta.orm.base.BizObject, java.util.Map, org.imeta.core.model.Entity, java.lang.Boolean)
* @see InsertSqlExecutor#execute(org.imeta.core.model.Entity, java.util.List)
*
* <p>
* execute insert or update with _statis value <code>String</code>
* </p>
*
* @param billContext billContext is one thread context {@link BillContext} in the variable has props context {@link Map} <code>null</code>save Resubmit key and other So.
* * fullname : metaUri of metaServer is the index of entity of meta
* @param bill business data in {@link com.yonyou.ucf.mdd.ext.bill.dto.BillDataDto}
* @param paramMap Singleton instance in rule china {@link Map} ,the request DTO in paramMap when in rule ,the DTO is instance of {@link BizObject} Array
* * when complete this rule set paramMap for return
* @param entity meta entity in metaServer
*
* @return execute result
* @throws Exception
*/
private Object executeInsert(BillContext billContext, BizObject bill, Map<String, Object> paramMap, Entity entity) throws Exception {
fillPubts4Insert(bill);
//开始递归插入数据
new InsertSqlExecutor(AppContext.getSqlSession()).execute(entity, bill);
//check project is open config of timeline and this bill is opened in timeline server
//sendTimeLineSnapshot(billContext, bill, paramMap);
return new BillSaveResult();
}


### com.yonyou.ucf.mdd.ext.dao.meta.crud.InsertSqlExecutor
/**
* 元数据crud封装的insert实现
*
* @author Bob
*/
@SuppressWarnings("DuplicatedCode")
public class InsertSqlExecutor extends MetaDaoSupport {

...

public <T extends BizObject> void execute(Entity entity, T data) throws Exception {
List<T> list = new ArrayList<T>(1);
list.add(data);
execute(entity, list, true);
}

private <T extends BizObject> void execute(Entity entity, List<T> list, boolean isPartition) throws Exception {
if (true) {//强制切换到InsertSqlExecutorNew
new InsertSqlExecutorNew(getSqlSession()).execute(entity, list);
return;
}
printLogWHenEntityNull(entity, list);
//传递多语开关配置到元数据上下文
String fullname = entity.fullname();
MddMultilingualUtil.setEnableI18n2Imeta();
//提前将insert插入,为yTenant 判断做准备
EntityStatusWalker statusWalker = new EntityStatusWalker();
for (BizObject bill : list) {
bill.setEntityStatus(EntityStatus.Insert);
ObjectWalker.walk(statusWalker, bill, fullname);
}
if (isPartition) {
setTenantandCorpWhenSave(entity, list);
}

InsertCheckWalker insertCheck = new InsertCheckWalker();
insertCheck.setNext(new FormatCheckWalker());
// 构造SQL语句
SqlBuilder<BizObject> builder = new InsertSqlBuilder();
for (BizObject bill : list) {
ObjectHierarchyBuilder.build(bill, entity);
ObjectFullWalker.walk(insertCheck, bill, fullname);
try {
batchSaveExecute(builder.build(entity, bill));
} catch (Throwable throwable) {
logger.error(throwable.getMessage());
throw new MddOrmErrorException(throwable.getMessage(),throwable);
}
}
}
com.yonyou.ucf.mdd.ext.pub.rule.SaveBusinessLogRule
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
@Order(2147483647)
@Service("saveBusinessLogRule")
public class SaveBusinessLogRule extends AbstractCommonRule {
private static final Logger logger = LoggerFactory.getLogger(SaveBusinessLogRule.class);
private ExecutorService taskExecutor;
private AuditLogSender auditLogSender;

public SaveBusinessLogRule() {
}

public RuleExecuteResult execute(final BillContext billContext, final Map<String, Object> paramMap) {
final List<BizObject> bills = this.getCloneBills(billContext, paramMap);
final String token = InvocationInfoProxy.getYhtAccessToken();
final String clientIp = (String)InvocationInfoProxy.getExtendAttribute("clientIp");
final String serviceCode = (String)InvocationInfoProxy.getExtendAttribute("serviceCode");
if (StringUtils.isBlank(serviceCode)) {
try {
BillDataDto billDataDto = (BillDataDto)this.getParam(paramMap);
if (null != billDataDto) {
Map<String, Object> externalData = BillUtils.getExternalData(billDataDto);
serviceCode = (String)externalData.get("serviceCode");
}
} catch (Exception var10) {
if (logger.isErrorEnabled()) {
logger.error("从BillDataDto扩展参数中获取serviceCode失败");
}
}
}

if (!CollectionUtils.isEmpty(bills)) {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
public void afterCompletion(int status) {
if (0 == status) {
SaveBusinessLogRule.this.getTaskExecutor().execute(() -> {
SaveBusinessLogRule.this.executeAsync(billContext, paramMap, token, clientIp, bills, serviceCode);
});
}

}
});
} else {
logger.warn("业务日志异步执行,未开启事务。");
this.getTaskExecutor().execute(() -> {
this.executeAsync(billContext, paramMap, token, clientIp, bills, serviceCode);
});
}
} else {
JsonFormatter formatter = new JsonFormatter(BizContext.getMetaRepository());
String json = formatter.toJson(bills, billContext.getFullname(), false, 32).toString();
logger.error("业务日志getCloneBills为空: 参数---billContext:{},bills:{}", JSONObject.toJSONString(billContext), json);
}

return new RuleExecuteResult();
}
com.yonyou.ucf.mdd.ext.bill.rule.biz.RefreshTsRule
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Service("refreshTsRule")
public class RefreshTsRule extends AbstractCommonRule {
public RefreshTsRule() {
}

public RuleExecuteResult execute(BillContext billContext, Map<String, Object> paramMap) throws Exception {
String fullname = billContext.getFullname();
List<BizObject> bills = this.getBills(billContext, paramMap);
String refreshField = (String)this.getParam(paramMap, "refreshField");
if (null != bills && bills.size() > 0) {
Iterator var6 = bills.iterator();

while(var6.hasNext()) {
BizObject bill = (BizObject)var6.next();
BillInfoUtils.refreshTs(fullname, bill, refreshField, AppContext.getTenantId());
DataCleanWalker dataCleanWalker = new DataCleanWalker();
dataCleanWalker.setNext(new ParallelTableWalker());
ObjectFullWalker.walk(dataCleanWalker, bill, fullname);
}

LogicDeleteHelper.removeLogicDelete(fullname, bills);
if (bills.size() == 1) {
this.putParam(paramMap, "return", bills.get(0));
} else {
this.putParam(paramMap, "return", bills);
}
}

return new RuleExecuteResult();
}
}
com.yonyou.common.bizflow.rule.BizFlowWriteBackRule低代码回写规则
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public RuleExecuteResult execute(BillContext billContext, Map<String, Object> paramMap) throws Exception {
RuleExecuteResult result = new RuleExecuteResult();
LogUtil.log("业务流:BizFlowWriteBackRule start! ");

try {
this.doWriteBack(billContext, paramMap);
LogUtil.log("业务流:BizFlowWriteBackRule end! ");
} catch (Exception var5) {
LogUtil.log("业务流:BizFlowWriteBackRule error!", var5);
}

return result;
}

private void doWriteBack(BillContext billContext, Map<String, Object> paramMap) throws Exception {
BillDataDto reqDto = (BillDataDto)paramMap.get("param");
String domain = BizFlowUtil.getDomain(billContext);
String billNum = BizFlowUtil.getBillNum(reqDto);
String tenantId = BizFlowUtil.getTenantId();
String token = InvocationInfoProxy.getYhtAccessToken();
String operate = billContext.getAction();
String subId = billContext.getSubid();
List<JSONObject> bills = BizFlowUtil.getBills(reqDto);
Iterator var11 = bills.iterator();

while(var11.hasNext()) {
JSONObject bill = (JSONObject)var11.next();
if (this.noNeedWriteBackConvert(bill, domain, operate)) {
LogUtil.log("业务流:BizFlowWriteBackRule skip bill: " + bill);
} else {
LogUtil.log("业务流:BizFlowWriteBackRule bill: " + bill);
ConvertParam convertParam = new ConvertParam();
convertParam.setTenantId(tenantId);
convertParam.setBillNum(billNum);
convertParam.setBillId(bill.getString("id"));
convertParam.addBill(bill);
convertParam.setToken(token);
convertParam.setOperate(operate);
convertParam.setSubId(subId);
convertParam.setDomain(domain);
LogUtil.log("业务流:BizFlowWriteBackRule convert PARAM: " + JSON.toJSONString(convertParam));
ConvertResult convertResult = BizFlowUtil.doWriteBackConvert(convertParam);
LogUtil.log("业务流:BizFlowWriteBackRule convert result: " + JSON.toJSONString(convertResult));
}
}

}

private boolean noNeedWriteBackConvert(JSONObject bill, String domain, String action) {
if (!"audit".equalsIgnoreCase(action) && !"unaudit".equalsIgnoreCase(action)) {
String flowId = ObjectUtil.getString(bill, "bizFlowId");
if ("developplatform".equalsIgnoreCase(domain) && ObjectUtil.isEmpty(flowId)) {
return true;
} else {
String writeBackSign = ObjectUtil.getString(bill, "bizFlowWriteBackSign");
return "bizFlowWriteBackSign".equals(writeBackSign);
}
} else {
return false;
}
}
com.yonyou.common.bizflow.rule.BizFlowPushRule
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private static final Logger log = LoggerFactory.getLogger(BizFlowPushRule.class);
@Autowired
IYpdBillDataService iYpdBillDataService;
@Autowired
MdfTemplateRunTimeServiceImpl mdfTemplateRunTimeService;

public BizFlowPushRule() {
}

public RuleExecuteResult execute(BillContext billContext, Map<String, Object> paramMap) throws Exception {
BizFlowRuleResult result = new BizFlowRuleResult();
LogUtil.log("业务流:bizFlowPush start! ");

try {
BillDataDto reqDto = (BillDataDto)paramMap.get("param");
Map<String, Object> cusMap = reqDto.getCustMap();
String billNum = BizFlowUtil.removeSuffix(reqDto.getBillnum());
List<JSONObject> bills = BizFlowUtil.getBills(reqDto);
String domain = BizFlowUtil.getDomain(billContext);
ConvertResult convertResult = BizFlowUtil.doPush(billNum, bills, cusMap, billContext.getSubid(), domain, billContext.getAction());
if (Boolean.TRUE.equals(AppContext.getCurrentUser().getNewArch())) {
this.busObjToUIData(billContext, paramMap, convertResult);
}

paramMap.put("bizFlowReturn", convertResult);
result.setConvertResult(convertResult);
LogUtil.log("业务流:bizFlowPush end! ");
} catch (Exception var10) {
LogUtil.log("业务流:bizFlowPush error!", var10);
}

return result;
}

image-20230203141336848

com.yonyou.business.StockServiceTccRule
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
@Component("stockServiceTccRule")
public class StockSer viceTccRule extends AbstractCommonRule implements ITccRule {
// private static final String URI = "XMFYGJ102.XMFYGJ102.bookstock_yts";
//日常
private static final String URI = "GT52146AT26.GT52146AT26.bookstock_yts";

private static final String PRODUCTID = "sproductid";
private static final String ITOTAL = "itotal";
private static final String INUMBER = "inumber";
private static final String IONWAY = "ionway";
private static final String SNAME = "sname";

protected final static Logger logger = LoggerFactory.getLogger(StockServiceTccRule.class);

@Autowired
IOrderService orderService;

@Autowired
private RedisTemplate redisTemplate;

@Override
public RuleExecuteResult execute(BillContext billContext, Map<String, Object> map) throws Exception {
logger.info("StockServiceRule running!");
List<BizObject> bills = this.getBills(billContext, map);
boolean hasTccFlag = false;
for (BizObject bizObject : bills) {
String name = bizObject.get(SNAME);
if (!StringUtils.isEmpty(name) && name.toLowerCase(Locale.ENGLISH).indexOf("iris") != -1) {
hasTccFlag = true;
}
}
for (BizObject bizObject : bills) {
String ProductId = bizObject.get(PRODUCTID);
if (null == ProductId) {
throw new RuntimeException("商品ID不能为空");
}
// 下单数量
Integer num = bizObject.get(INUMBER);
if (null == num || num <= 0) {
throw new RuntimeException("数量不能为空或小于0");
}
BizObject stock = MetaDaoHelper.findById(URI, ProductId);
stock.put("_status", EntityStatus.Update);
// tcc模式,正向先扣库存
Integer oldItotal = (Integer)stock.get(ITOTAL);
if (num > oldItotal) {
throw new RuntimeException("库存不足");
}
stock.put(ITOTAL, oldItotal - num);
// 增加在途库存
Integer oldIonway = (Integer)stock.get(IONWAY);
stock.put(IONWAY, oldIonway + num);

Transaction yts = YtsContext.currentTransaction();
if (null != yts) {
stock.put("gtxid", yts.getGtxId());
stock.put("ptxid", yts.getPtxId());
stock.put("txid", yts.getTxId());
}

//将sorderid存入redis
String sorderid = bizObject.get("sorderid");
redisTemplate.opsForValue().set(sorderid,yts.getGtxId(),30l, TimeUnit.MINUTES);

MetaDaoHelper.update(URI, stock);

}
if (hasTccFlag) {
TourOrder order = new TourOrder();
order.setUserId(UUID.randomUUID().toString());
order.setTourOrderId(UUID.randomUUID().toString());
order.setOrderName("订单号:" + order.getOrderName());
order.setUserName("yongyou");

TourOrder norder = orderService.sagas(order);
try {
logger.info("order: {}", JSON.toJSONString(norder));
} catch (Throwable e) {
logger.warn("toJSONString error ", e);
}
}
return new RuleExecuteResult();
}

@Override
public RuleExecuteResult confirm(BillContext billContext, Map<String, Object> paramMap) throws Exception {
logger.info("StockServiceRule rollback!");
List<BizObject> bills = this.getBills(billContext, paramMap);
for (BizObject bizObject : bills) {
String ProductId = bizObject.get(PRODUCTID);
if (null == ProductId) {
throw new RuntimeException("商品ID不能为空");
}
// 下单数量
Integer num = bizObject.get(INUMBER);
if (null == num || num <= 0) {
throw new RuntimeException("数量不能为空或小于0");
}
// tcc模式成功,减去在途库存,交易完成
BizObject stock = MetaDaoHelper.findById(URI, ProductId);
stock.put("_status", EntityStatus.Update);
Integer oldIonway = (Integer)stock.get(IONWAY);
stock.put(IONWAY, oldIonway - num);

MetaDaoHelper.update(URI, stock);
}
return new RuleExecuteResult();
}

@Override
public RuleExecuteResult cancel(BillContext billContext, Map<String, Object> map) throws Exception {
logger.info("StockServiceRule rollback!");
List<BizObject> bills = this.getBills(billContext, map);
for (BizObject bizObject : bills) {
String ProductId = bizObject.get(PRODUCTID);
if (null == ProductId) {
throw new RuntimeException("商品ID不能为空");
}
// 下单数量
Integer num = bizObject.get(INUMBER);
if (null == num || num <= 0) {
throw new RuntimeException("数量不能为空或小于0");
}
// tcc模式失败,将在途库存加回可用库存
BizObject stock = MetaDaoHelper.findById(URI, ProductId);
stock.put("_status", EntityStatus.Update);
Integer oldItotal = (Integer)stock.get(ITOTAL);
stock.put(ITOTAL, oldItotal + num);

Integer oldIonway = (Integer)stock.get(IONWAY);
stock.put(IONWAY, oldIonway - num);

MetaDaoHelper.update(URI, stock);
}
return new RuleExecuteResult();
}

}
com.yonyou.business.PayServiceTccRule
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
@Component("payServiceTccRule")
public class PayServiceTccRule extends AbstractCommonRule implements ITccRule {
// private static final String URI = "XMFYGJ103.XMFYGJ103.bookpay_yts";
//日常
private static final String URI = "GT52131AT25.GT52131AT25.bookpay_yts";

private static final String SUSERID = "sbuyer";
private static final String FTOTAL = "ftotal";
private static final String FAVAILABLE = "favailable";
private static final String FONWAY = "fonway";
private static final String SNAME = "sname";


@Autowired
IOrderService orderService;

protected final static Logger logger = LoggerFactory.getLogger(PayServiceTccRule.class);

@Override
public RuleExecuteResult execute(BillContext billContext, Map<String, Object> map) throws Exception {
logger.info("PayServiceRule running!");
List<BizObject> bills = this.getBills(billContext, map);
boolean hasTccFlag = false;
for (BizObject bizObject : bills) {
String name = bizObject.get(SNAME);
if (!StringUtils.isEmpty(name) && name.toLowerCase(Locale.ENGLISH).indexOf("tcc") != -1) {
hasTccFlag = true;
}
}
/*if(hasTccFlag) {
TourOrder order = new TourOrder();
order.setUserId(UUID.randomUUID().toString());
order.setTourOrderId(UUID.randomUUID().toString());
order.setOrderName("订单号:" + order.getOrderName());
order.setUserName("yongyou");
orderService.tcc(order);
}*/

for (BizObject bizObject : bills) {
// 账户
String UserId = bizObject.get(SUSERID);
if (null == UserId) {
throw new RuntimeException("账户ID不能为空");
}
// 待支付金额
BigDecimal total = bizObject.get(FTOTAL);
if (null == total || total.floatValue() <= 0) {
throw new RuntimeException("支付金额不能为空或小于0");
}
BizObject pay = MetaDaoHelper.findById(URI, UserId);
pay.put("_status", EntityStatus.Update);
// 账户可用金额
BigDecimal oldFavailable = pay.get(FAVAILABLE);
if (total.floatValue() > oldFavailable.floatValue()) {
throw new RuntimeException("当前账户余额不足");
}

pay.put(FAVAILABLE, oldFavailable.subtract(total));
// 账户在途金额,增加待付金额
BigDecimal oldOnway = pay.get(FONWAY);
pay.put(FONWAY, oldOnway.add(total));

Transaction yts = YtsContext.currentTransaction();
if (null != yts) {
pay.put("gtxid", yts.getGtxId());
pay.put("ptxid", yts.getPtxId());
pay.put("txid", yts.getTxId());
}
MetaDaoHelper.update(URI, pay);
}

return new RuleExecuteResult();
}

@Override
public RuleExecuteResult confirm(BillContext billContext, Map<String, Object> map) throws Exception {
logger.info("PayServiceRule rollback!");
List<BizObject> bills = this.getBills(billContext, map);
for (BizObject bizObject : bills) {
// 账户
String UserId = bizObject.get(SUSERID);
if (null == UserId) {
throw new RuntimeException("账户ID不能为空");
}
// 待支付金额
BigDecimal total = bizObject.get(FTOTAL);
if (null == total || total.floatValue() <= 0) {
throw new RuntimeException("支付金额不能为空或小于0");
}
BizObject pay = MetaDaoHelper.findById(URI, UserId);
pay.put("_status", EntityStatus.Update);

// 成功则把在途金额减掉,交易完成
BigDecimal oldOnway = pay.get(FONWAY);
pay.put(FONWAY, oldOnway.subtract(total));

MetaDaoHelper.update(URI, pay);
}
return new RuleExecuteResult();
}

@Override
public RuleExecuteResult cancel(BillContext billContext, Map<String, Object> map) throws Exception {
logger.info("PayServiceRule rollback!");
List<BizObject> bills = this.getBills(billContext, map);
for (BizObject bizObject : bills) {
// 账户
String UserId = bizObject.get(SUSERID);
if (null == UserId) {
throw new RuntimeException("账户ID不能为空");
}
// 待支付金额
BigDecimal total = bizObject.get(FTOTAL);
if (null == total || total.floatValue() <= 0) {
throw new RuntimeException("支付金额不能为空或小于0");
}
BizObject pay = MetaDaoHelper.findById(URI, UserId);
pay.put("_status", EntityStatus.Update);

// 失败则把在途金额加回可用金额
BigDecimal old = pay.get(FAVAILABLE);
pay.put(FAVAILABLE, old.add(total));

BigDecimal oldOnway = pay.get(FONWAY);
pay.put(FONWAY, oldOnway.subtract(total));

MetaDaoHelper.update(URI, pay);
}
return new RuleExecuteResult();
}

}

MDD框架com.yonyou.ucf.mdf.app.service.impl.BillServiceImp add方法梳理(部分内容).md

com.yonyou.ucf.mdf.app.service.impl.BillServiceImp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Override
public String add(BaseReqDto addDto) throws Exception {
try {
//
RuleContext ruleContext = RuleEngineUtils.prepareRuleContext(addDto, OperationTypeEnum.ADD);
RuleExecuteResult result = RuleEngine.getInstance().execute(ruleContext);
if (result.getMsgCode() != 1) {
throw new BusinessException(result.getMessage());
} else {
return result.getData() == null ? "" : GsonHelper.ToJSon(result.getData());
}
} catch (Exception e) {
logger.error("bill add 异常",e);
throw new BusinessException(e.getMessage());
}
}

com/yonyou/ucf/mdd/rule/api/RuleEngine.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**
* 规则引擎执行入口
*
* @param ruleContext 规则执行所需数据
* @return
*/
public RuleExecuteResult execute(RuleContext ruleContext) throws MddBaseException {
Queue<? extends RuleRegister> ruleList ;
try {
ruleList = doGetRules(ruleContext);
} catch (Throwable e) {
log.error("获取规则列表异常!", e);
throw new BusinessException(e.getMessage(), e);
}
try {
return doExecRules(ruleContext, ruleList);
} catch (Throwable e) {
log.error("执行rule异常!", e);
throw new BusinessException(e.getMessage(), e);
}
}

/**
* 调用handleRuleList 方法返回 规则列表
* 可适配自定义获取规则列表的 处理器。
* 自定义RuleListHandler 需实现 IRuleListHandler
*
* @param ruleContext
* @return
*/
public Queue<? extends RuleRegister> doGetRules(RuleContext ruleContext) throws Exception {
IRuleListHandler ruleListHandler = ruleContext.getRuleListHandler();
if (null == ruleListHandler) {
ruleListHandler = new DefaultRuleListHandler();
log.debug("##RuleEngine:doGetRules # 使用 DefaultRuleListHandler");
} else {
log.debug("##RuleEngine:doGetRules # 使用自定义 RuleListHandler");
}
Queue ruleList = ruleListHandler.handleRuleList(ruleContext);
ExtListUtil.checkRuleList(ruleList);
return ruleList;
}

com/yonyou/ucf/mdd/rule/handler/DefaultRuleListHandler.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
@Override
public Queue<RuleRegister> handleRuleList(RuleContext ruleContext) throws Exception {

Object bill = ruleContext.getCustomMap().get("param");
String action = ruleContext.getOperateType() == null ? ruleContext.getOperationTypeEx() : ruleContext.getOperateType().getValue();
String[] ruleLvs = ruleContext.getRuleLvs();
if (ruleContext.isMakeup()) {//如果是异步规则,是否支持失败后规则补偿
return getMakeupRuleList(action, ruleContext.getTenantId());
}
Object uiTenantId = ruleContext.getTenantId();
if (ruleContext.getTenantId() == null || StringUtils.isEmpty(ruleContext.getTenantId() + "")) {
uiTenantId = AppContext.getTenantIdNoCallBack();
}
return getRuleList(ruleContext.getBillnum(), ruleLvs, action, bill, uiTenantId);
}



/**
* <p>
* important : action eq check and key is not null in billObject action set value check_key<code>null</code>
* getList should merge check with check_key
* </p>
*
* @param ruleLvs Rule Level :ruleLvs[0] = "common"; ruleLvs[1] = uiMetaBaseInfo.getSubid(); ruleLvs[2] = uiMetaBaseInfo.getBillnum();
* over rule : from high to low
* @param action the action for request exp: save,delete,update,list and so on
* @param bill object {@link BaseDto} if type of {@link BaseDto} return this else come from param others is <code>null</code>
* @param tenantId tenantId
* @return
* @throws Exception
*/
@SuppressWarnings({"rawtypes"})
private Queue<RuleRegister> getRuleList(String billnum, String[] ruleLvs, String action, Object bill, Object tenantId) throws Exception {
BaseDto billDto = getBaseDto(bill);
if (isCheck(action)) {
Map obj = new Gson().fromJson(billDto.getItem(), Map.class);
if (null != obj && obj.get("key") != null) {
action = "check_" + obj.get("key").toString();
}
}
String ruleKey = null;
if (null != billDto) {
if (null != billDto.getRuleKey()) {
ruleKey = billDto.getRuleKey();
} else {
if (StringUtils.equalsIgnoreCase(OperationTypeEnum.REFER.getValue(), action) || StringUtils.equalsIgnoreCase(action, OperationTypeEnum.REFERREFRESH.getValue())) {
ruleKey = billDto.getrefCode();
}
}
}
//获取可执行的redis队列
Queue<RuleRegister> ruleList = getAndFilterRules(billnum, action, ruleKey, tenantId, ruleLvs);
/* 设置依赖关系 */
dependOnRule(ruleList);
return ruleList;
}



/**
* 获取规则列表
* 根据ruleKey 规则关键字过滤
* 高级别规则对低级别规则的覆盖
*
* <p>
* 通过lvs循环查找规则
* 1)ruleLvs[2] = "common";
* 2)ruleLvs[1] = uiMetaBaseInfo.getSubid();
* 3)ruleLvs[0] = uiMetaBaseInfo.getBillnum();
* </p>
*
* @param action 动作
* @param ruleKey 规则关键字
* @param tenantId 租户ID
* @return
*/
public Queue<RuleRegister> getAndFilterRules(String billnum, String action, String ruleKey, Object tenantId, String[] ruleLvsOri) {
// 获取缓存, foreach 外,减少调用次数
List<RuleRegister> ruleRegisters;
if (RuleUtil.isOpenCache()) {//是否开启规则缓存,建议都开启,默认开启
ruleRegisters = RuleUtil.getBillNumRuleFromCache(tenantId, billnum, ruleLvsOri, action);
} else {
ruleRegisters = RuleUtil.initBillNumRuleRegister(tenantId, ruleLvsOri,action);
}
if(Tracker.switchEnable()){
Map<String, Object> inparam = new HashMap <>();
inparam.put("billnum", billnum);
inparam.put("action", action);
inparam.put("ruleKey", ruleKey);
inparam.put("tenantId", tenantId);
inparam.put("ruleLvsOri", ruleLvsOri);
Tracker.recordLogClues(this.getClass().getName(), "getAndFilterRules", inparam, ruleRegisters, "获取规则列表, 通过RuleUtil 获取的结果");
}

Queue<RuleRegister> ruleRegisterQueue = new LinkedList<>();
RuleStatus ruleStatus = new RuleStatus();
String[] ruleLvs = ruleLvsOri.clone();
//数组反转
ArrayUtils.reverse(ruleLvs);
for (int i = 0; i < ruleLvs.length; i++) {
String ruleLv = ruleLvs[i];
List<RuleRegister> tmpList = filterRules(ruleLv, ruleKey, ruleRegisters);
//增加同级别覆盖逻辑, 通过配置指定
overrideRule(tmpList, ruleRegisterQueue, ruleStatus, ruleLvs.length - i);
}
//队列排序
List<RuleRegister> list = new LinkedList(ruleRegisterQueue);
Collections.sort(list, RuleComparatorUtil.getInstance().getCmp());
ruleRegisterQueue.clear();
ruleRegisterQueue.addAll(list);
return ruleRegisterQueue;

}

com/yonyou/ucf/mdd/rule/utils/RuleUtil.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/**
* 初始化表单基本的规则列表,如果是check_action,同步查询出check的规则列表
*
* @param tenantId 租户ID
* @param ruleLvsOri
* @return
*/
public static List<RuleRegister> initBillNumRuleRegister(Object tenantId, String[] ruleLvsOri,String ruleaction) {
Map<String, Object> params = new HashMap<>();
params.put("tenantId", tenantId);
List<String> list = new ArrayList<>();
for (String rule :ruleLvsOri){
if (StringUtils.isNotEmpty(rule)){
list.add(rule);
}
}
List<String> actionList = new ArrayList<>();
actionList.add(ruleaction);
if (ruleaction.startsWith("check_")){
list.add("check");
actionList.add("check");
}
params.put("list", list);
params.put("actionList", actionList);
List<RuleRegister> ruleRegisterList = findAllBillRuleRegister(params);
return ruleRegisterList;

}


/**
* 获取表单列表,可按照billnum进行过滤
*
* @param params
* @return
*/
private static List<RuleRegister> findAllBillRuleRegister(Map<String, Object> params) {
List<RuleRegister> ruleRegisterList = null;
try {
IRuleRegisterMapperDao iruledao = UBaseContext.getBean(IRuleRegisterMapperDao.class);
if (null == iruledao) {
iruledao = new RuleRegisterMapperDaoImpl();
}
ruleRegisterList = iruledao.findAllBillRuleRegister(params);
// 增加逻辑如果初始化当前租户没有规则,则使用公共规则 使用租户ID为0的
if (null == ruleRegisterList || ruleRegisterList.isEmpty()) {
params.put(MddConstants.PARAM_TENANT_ID, ExtCommonUtil.getZeroTenant());
ruleRegisterList = AppContext.getBean(IRuleRegisterMapperDao.class).findAllBillRuleRegister(params);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return ruleRegisterList;
}