diff --git a/out/production/shkd-cosmic-debug/kd/cosmic/debug/tools/CosmicLauncher.class b/out/production/shkd-cosmic-debug/kd/cosmic/debug/tools/CosmicLauncher.class new file mode 100644 index 0000000..d908516 Binary files /dev/null and b/out/production/shkd-cosmic-debug/kd/cosmic/debug/tools/CosmicLauncher.class differ diff --git a/out/production/shkd-cosmic-debug/shkd/cosmic/debug/DebugApplication.class b/out/production/shkd-cosmic-debug/shkd/cosmic/debug/DebugApplication.class new file mode 100644 index 0000000..7659d9a Binary files /dev/null and b/out/production/shkd-cosmic-debug/shkd/cosmic/debug/DebugApplication.class differ diff --git a/out/production/sys/shkd/sys/sys/business/test.class b/out/production/sys/shkd/sys/sys/business/test.class new file mode 100644 index 0000000..5695200 Binary files /dev/null and b/out/production/sys/shkd/sys/sys/business/test.class differ diff --git a/out/production/sys/shkd/sys/sys/common/AppflgConstant.class b/out/production/sys/shkd/sys/sys/common/AppflgConstant.class new file mode 100644 index 0000000..72b133c Binary files /dev/null and b/out/production/sys/shkd/sys/sys/common/AppflgConstant.class differ diff --git a/sys/shkd-sys-sys/build.gradle b/sys/shkd-sys-sys/build.gradle deleted file mode 100644 index 8f470ce..0000000 --- a/sys/shkd-sys-sys/build.gradle +++ /dev/null @@ -1,14 +0,0 @@ -/* - * This is a kingdee cosmic template project that is automatically generated by the Kingdee cosmic development assistant plugin. - * If there are any issues during the use process, you can provide feedback to the kingdee developer community website. - * Website: https://developer.kingdee.com/developer?productLineId=29 - * Author: liebin.zheng - * Generate Date: 2024-10-25 13:35:51 - */ - -dependencies { - api project(':shkd-base-common') - api project(':shkd-base-helper') -} - - diff --git a/sys/shkd-sys-sys/src/main/java/resources/.gitkeep b/sys/shkd-sys-sys/src/main/java/resources/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/business/.gitkeep b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/business/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/common/AppflgConstant.java b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/common/AppflgConstant.java index 1d45dfa..c5ef03a 100644 --- a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/common/AppflgConstant.java +++ b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/common/AppflgConstant.java @@ -3,9 +3,9 @@ * If there are any issues during the use process, you can provide feedback to the kingdee developer community website. * Website: https://developer.kingdee.com/developer?productLineId=29 * Author: liebin.zheng - * Generate Date: 2024-10-25 13:35:51 + * Generate Date: 2024-10-25 14:27:06 */ -package shkd.sys.sys.common; +package shkd.shkd1.sys.sys.common; /** * sys云sys应用-通用常量类
@@ -13,7 +13,7 @@ package shkd.sys.sys.common; * 标识或缓存的常量,需以"KEY_"、"FID_"、"ENTRY_"或"SUBENTRY_"作为变量的前缀。
* * @author shkd - * @date 2024-10-25 13:35:51 + * @date 2024-10-25 14:27:06 */ public class AppflgConstant { diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/backlogTack/ToDoResendTack.java b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/backlogTack/ToDoResendTack.java new file mode 100644 index 0000000..ddb81b6 --- /dev/null +++ b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/backlogTack/ToDoResendTack.java @@ -0,0 +1,242 @@ +package shkd.sys.sys.midservice.backlogTack; + +import com.google.common.base.Objects; +import kd.bos.algo.DataSet; +import kd.bos.algo.Row; +import kd.bos.context.RequestContext; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.db.DB; +import kd.bos.db.DBRoute; +import kd.bos.exception.KDException; +import kd.bos.logging.Log; +import kd.bos.logging.LogFactory; +import kd.bos.login.utils.DateUtils; +import kd.bos.orm.query.QFilter; +import kd.bos.schedule.executor.AbstractTask; +import kd.bos.servicehelper.QueryServiceHelper; +import kd.bos.util.StringUtils; +import shkd.sys.sys.midservice.handler.CreateToDoHandler; +import shkd.sys.sys.midservice.handler.DealToDoHandler; +import shkd.sys.sys.midservice.handler.deleteToDoHandler; +import shkd.sys.sys.midservice.model.BacklogMessage; +import shkd.sys.sys.midservice.utils.GetUrlUtils; + +import java.util.*; + +public class ToDoResendTack extends AbstractTask { + private static final Log logger = LogFactory.getLog(ToDoResendTack.class); + + /*** + * 重发 + * @param requestContext 未使用 + * @param map 调度作业中的参数 + * @throws KDException 异常 + */ + @Override + public void execute(RequestContext requestContext, Map map) throws KDException { + logger.info("待办重发开始"); + String startTime = (String) map.get("starttime"); + String endTime = (String) map.get("endtime"); + Date startTimeDate = null; + Date endTimeDate = null; + if (StringUtils.isEmpty(startTime) || startTime.length() != 19) { + Date date = new Date(); + logger.error("调度作业参数提供的开始时间格式不对或者未传入开始时间,自动转成:" + date); + //获得前三天对应的时间 + endTimeDate = date; + long time = endTimeDate.getTime() - 86400000 * 3; + startTimeDate = new Date(time); + } else { + startTimeDate = DateUtils.parseDateTime(startTime, "yyyy-MM-dd HH:mm:ss"); + endTimeDate = DateUtils.parseDateTime(endTime, "yyyy-MM-dd HH:mm:ss"); + logger.info("待办重发-starttime:" + startTimeDate); + logger.info("待办重发-endtime:" + endTimeDate); + } + logger.info("组装待办、已办重发的数据"); + Date beginTimeDate = startTimeDate; + // 待办 + boolean hasNext = true; + logger.info("开始抽取待办,参数 beginTimeDate:" + beginTimeDate + "endTimeDate:" + endTimeDate); + extractToDoList(beginTimeDate, endTimeDate, "1"); + extractToDoList(beginTimeDate, endTimeDate, "2"); + extractToDoList(beginTimeDate, endTimeDate, "5"); + } + + /*** + * 抽取待办 + * @param startTime 开始时间 + * @param endTime 结束时间 + * @param t_status 待办状态 + * @return + */ + private void extractToDoList(Date startTime, Date endTime, String t_status) { + String accountId = System.getProperty("efms.midservice.accountid"); + logger.info("拼接sql,此次拼接的待办类型为:" + t_status + "(1:待办、2已办、5撤销),使用参数startTime:" + startTime + "endTime:" + + endTime); + StringBuffer cwbSql1 = new StringBuffer(); + cwbSql1.append("SELECT "); + cwbSql1.append("b.FID,"); + cwbSql1.append("b.FPROCDEFID,"); + cwbSql1.append("b.FTASKDEFKEY,"); + cwbSql1.append("b.FPROCINSTID,"); + cwbSql1.append("b.FEXECUTIONID,"); + cwbSql1.append("b.FPARENTTASKID,"); + cwbSql1.append("b.FOWNER,"); + cwbSql1.append("b.FASSIGNEE,"); + cwbSql1.append("b.FCLAIMTIME,"); + cwbSql1.append("b.FENDTIME,"); + cwbSql1.append("b.FDURATION,"); + cwbSql1.append("b.FPRIORITY,"); + cwbSql1.append("b.FDUEDATE,"); + cwbSql1.append("b.FFORMKEY,"); + cwbSql1.append("b.FCATEGORY,"); + cwbSql1.append("b.FISDISPLAY,"); + cwbSql1.append("b.FSTARTERID,"); + cwbSql1.append("b.FENTITYNUMBER,"); + cwbSql1.append("b.FCREATEDATE,"); + cwbSql1.append("b.FMODIFYDATE,"); + cwbSql1.append("b.FASSIGNEEID,"); + cwbSql1.append("b.FOWNERID,"); + cwbSql1.append("b.FEXECUTIONTYPE,"); + cwbSql1.append("b.FBUSINESSKEY,"); + cwbSql1.append("b.FYZJGROUPID,"); + cwbSql1.append("b.FPROCESSINGPAGE,"); + cwbSql1.append("b.FHANDLESTATE,"); + cwbSql1.append("b.FMOBILEFORMKEY,"); + cwbSql1.append("b.FDELEGATION,"); + cwbSql1.append("b.FBILLNO,"); + cwbSql1.append("b.FPROCESSINGMOBILEPAGE,"); + cwbSql1.append("b.FENDTYPE,"); + cwbSql1.append("b.FSOURCE,"); + cwbSql1.append("b.FVALIDATEOPERATION,"); + cwbSql1.append("b.FNAME,"); + cwbSql1.append("b.FSUBACTIVITYNAME,"); + cwbSql1.append("b.FDESCRIPTION,"); + cwbSql1.append("b.FSUBJECT,"); + cwbSql1.append("b.FENTITYNAME,"); + cwbSql1.append("b.FSENDERNAME,"); + cwbSql1.append("b.FSTARTNAME,"); + cwbSql1.append("b.FPARTICIPANTNAME,"); + cwbSql1.append("b.FGROUPNUMBER,"); + cwbSql1.append("b.FREALDURATION,"); + cwbSql1.append("b.FBATCHOP,"); + cwbSql1.append("b.FBILLTYPE,"); + cwbSql1.append("b.FBIZTRACENO,"); + cwbSql1.append("b.FSENDERNAMEFORMAT,"); + cwbSql1.append("b.FSTARTNAMEFORMAT,"); + cwbSql1.append("b.FPRESENTASSIGNEE,"); + cwbSql1.append("b.FORGUNITID,"); + cwbSql1.append("b.FORGVIEWID,"); + cwbSql1.append("b.FPROCESSTYPE,"); + cwbSql1.append("b.FSENDERID,"); + cwbSql1.append("b.FCONTROL,"); + cwbSql1.append("b.FEXTENDDATE,"); + cwbSql1.append("b.FEXTENDNUMBER,"); + cwbSql1.append("b.FEXTENDSTR1,"); + cwbSql1.append("b.FEXTENDSTR2,"); + cwbSql1.append("b.FDELETEREASON,"); + cwbSql1.append("b.FEXTENDFORMAT,"); + cwbSql1.append("b.FEXTENDMULSTR1,"); + cwbSql1.append("b.FEXTENDMULSTR2,"); + cwbSql1.append("a.FCREATEDATE fstarttime,"); + cwbSql1.append("c.FID as factivityId,"); + cwbSql1.append("d.FUSERID freceiveuserid,"); + cwbSql1.append("d.FUSERNAME freceiveusername,"); + cwbSql1.append("d.FCREATEDATE freceivetime,"); + cwbSql1.append("d.FENDTIME fcompletetime,"); + cwbSql1.append("d.FMODIFYDATE flastmodifytime "); + cwbSql1.append("from t_wf_hitaskinst b "); + cwbSql1.append("INNER JOIN t_wf_hiparticipant d on d.FTASKID=b.FID "); + cwbSql1.append("INNER JOIN t_wf_hiactinst c on c.FTASKID=b.FID "); + cwbSql1.append("INNER JOIN t_wf_hiprocinst a on a.FID=b.FPROCINSTID "); + cwbSql1.append("where b.FMODIFYDATE >= ? and b.FMODIFYDATE <=?"); + if (Objects.equal("1", t_status)) { + cwbSql1.append("and (b.FDELETEREASON is null or b.FDELETEREASON =' ' or b.fdeletereason='') "); + cwbSql1.append(" and b.FENDTIME is null and d.FENDTIME is null "); + } else if (Objects.equal("2", t_status)) { + // cwbSql1.append(" and (b.FDELETEREASON ='task complete' ) "); + cwbSql1.append(" and (b.FDELETEREASON ='task complete' or b.FDELETEREASON ='first_usertask_skip') "); + cwbSql1.append(" and b.FENDTIME is not null and d.FENDTIME is not null "); + } else if (Objects.equal("5", t_status)) { + cwbSql1.append(" and not ((b.FDELETEREASON is null or b.FDELETEREASON =' ' or b.fdeletereason='') "); + cwbSql1.append(" and b.FENDTIME is null and d.FENDTIME is null) "); + cwbSql1.append(" and not ((b.FDELETEREASON ='task complete' or b.FDELETEREASON ='first_usertask_skip') and b.FENDTIME is not null and d.FENDTIME is not null)"); + } + cwbSql1.append(" ORDER BY b.FMODIFYDATE,b.FID"); + DataSet cwbAmount1 = DB.queryDataSet(this.getClass().getName(), DBRoute.of("sys"), cwbSql1.toString(), new Object[]{startTime, endTime}); + Iterator iterator = cwbAmount1.iterator(); + logger.info("开始拼接待办数据"); + try { + while (iterator.hasNext()) { + Row next = iterator.next(); + //接收人手机号 + DynamicObject dynamicObject = QueryServiceHelper.queryOne("bos_user", "name,shkd_pid," + + "phone", new QFilter[]{new QFilter("id", "=", next.getString("freceiveuserid"))}); + String phone = dynamicObject.getString("phone"); + switch (t_status) { + case "1": + BacklogMessage backlogMessage = new BacklogMessage(); + //业务类型名称 + backlogMessage.setbName("业务类型名称"); + // 紧急程度 + backlogMessage.setUrGency("0"); + //当前节点名称 + backlogMessage.setCurrentStepName(next.getString("FNAME")); + //上步骤名称 + backlogMessage.setPreStepName(""); + // startname发起人名称 + backlogMessage.setSendUserName(dynamicObject.getString("startname")); + //接收人手机号 + backlogMessage.setReceiveUserId(phone); + //标题 + String title = "请处理" + next.getString("fstartname") + "提交的" + next.getString("fentityname"); + backlogMessage.setTitle(title); + //PC地址 + String pcUrl = GetUrlUtils.getInstance().getPcUrl(next.getString("fprocessingpage"), + next.getString("fprocessingmobilepage"), + next.getString("fsource"), + accountId, + next.getString("factivityId"), + next.getString("fbusinesskey"), + next.getString("fid")); + backlogMessage.setHandleUrl(pcUrl); + //PC地址查看 + backlogMessage.setViewUrl(pcUrl + "&ado=view"); + //app地址 + backlogMessage.setAppHandleUrl(pcUrl); + //App应用名称 + backlogMessage.setAppName(""); + //app地址查看 + backlogMessage.setAppViewUrl(pcUrl + "&ado=view"); + //业务id + backlogMessage.setPendingId(String.valueOf(next.getLong("fid"))); + // 业务编码 + backlogMessage.setBussinessCode(next.getString("fbillno")); + //属性 + backlogMessage.setPendingAttr("0"); + //notifyMsg 通知消息 + backlogMessage.setNotifyMsg(""); + //notifyMethod 通知方式 + backlogMessage.setNotifyMethod(""); + //业务自定义数据 + backlogMessage.setJsonData(""); + CreateToDoHandler.get_CreateToDoHandler().sendCreateToDo(backlogMessage); + break; + case "2": + DealToDoHandler.get_DealToDoHandler().sendDealToDo(next.getLong("id"),phone); + break; + case "5": + deleteToDoHandler.get_deleteToDoHandler().sendDeleteToDo(next.getLong("id"),phone); + break; + default: + break; + } + } + } catch (Exception e) { + logger.error("###待办数据拼接、发送失败,状态为"+t_status+",(1:待办,2:已办,5:撤销),具体原因:", e.getMessage(), e); + } + + logger.info("待办数据拼接和发送完成"); + } +} + diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/constant/ToDoCenterConstant.java b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/constant/ToDoCenterConstant.java new file mode 100644 index 0000000..9691a68 --- /dev/null +++ b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/constant/ToDoCenterConstant.java @@ -0,0 +1,16 @@ +package shkd.sys.sys.midservice.constant; + +/** + * @Description: + * @Author: FangShiXiao + * @Date: 2024/11/5 16:37 + * @Version: 1.0 + * @Ability + */ +public class ToDoCenterConstant { + public static String URI_send_addNew = "/bpm/task/api/addNew.dhtml"; + + public static String URI_SEND_finish = "/bpm/task/api/finishByRecordIdAndUserId.dhtml"; + + public static String URI_send_deleteP = "/oa/task/api/deletePendingByRecordIdAndUserId.dhtml"; +} diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/handler/CreateToDoHandler.java b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/handler/CreateToDoHandler.java new file mode 100644 index 0000000..60c0870 --- /dev/null +++ b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/handler/CreateToDoHandler.java @@ -0,0 +1,59 @@ +package shkd.sys.sys.midservice.handler; + +import com.alibaba.fastjson.JSONObject; +import kd.bos.logging.Log; +import kd.bos.logging.LogFactory; +import shkd.sys.sys.midservice.constant.ToDoCenterConstant; +import shkd.sys.sys.midservice.model.BacklogMessage; +import shkd.sys.sys.midservice.utils.RequestClient; + + +import java.util.Objects; + +/** + * @Description: + * @Author: FangShiXiao + * @Date: 2024/11/5 14:16 + * @Version: 1.0 + * @Ability 待办 + */ +public class CreateToDoHandler { + + private static Log logger = LogFactory.getLog(CreateToDoHandler.class); + private static CreateToDoHandler _CreateToDoHandler; + + public static synchronized CreateToDoHandler get_CreateToDoHandler(){ + if(_CreateToDoHandler == null){ + _CreateToDoHandler = new CreateToDoHandler(); + } + return _CreateToDoHandler; + } + public boolean sendCreateToDo(BacklogMessage messageInfo) { + try { + //body + JSONObject jsonObject2 = new JSONObject(); + jsonObject2.put("params",messageInfo); + String jsonMessage = jsonObject2.toJSONString(); + //调用接口结果 + String result = RequestClient.getInstance().callService(ToDoCenterConstant.URI_send_addNew,jsonMessage); + //接口调用结果 + JSONObject jsonObject = JSONObject.parseObject(result); + if(Objects.equals("success",jsonObject.getString("status"))){ + //发送成功 + //调用保存操作 + RequestClient.getInstance().saveCreateToDo(messageInfo.getTitle(),ToDoCenterConstant.URI_send_addNew,true,result,jsonMessage); + return true; + }else{ + //调用保存操作 + RequestClient.getInstance().saveCreateToDo(messageInfo.getTitle(),ToDoCenterConstant.URI_send_addNew,false,result,jsonMessage); + //发送失败 + logger.error("##接口调通失败"); + return false; + } + } catch (Exception e) { + logger.error("###调用接口失败:"+e.getMessage(),e); + return false; + } + } + +} diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/handler/DealToDoHandler.java b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/handler/DealToDoHandler.java new file mode 100644 index 0000000..d418ef5 --- /dev/null +++ b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/handler/DealToDoHandler.java @@ -0,0 +1,58 @@ +package shkd.sys.sys.midservice.handler; + +import com.alibaba.fastjson.JSONObject; +import kd.bos.logging.Log; +import kd.bos.logging.LogFactory; +import shkd.sys.sys.midservice.constant.ToDoCenterConstant; +import shkd.sys.sys.midservice.utils.RequestClient; + + +/** + * @Description: + * @Author: FangShiXiao + * @Date: 2024/11/5 14:18 + * @Version: 1.0 + * @Ability 处理(已办) + */ +public class DealToDoHandler { + private static Log logger = LogFactory.getLog(DealToDoHandler.class); + + private static DealToDoHandler _DealToDoHandler; + + public static synchronized DealToDoHandler get_DealToDoHandler(){ + if(_DealToDoHandler == null){ + _DealToDoHandler = new DealToDoHandler(); + } + return _DealToDoHandler; + } + + public boolean sendDealToDo(Long appRecordId,String userId) { + try { + //body + JSONObject jsonObject2 = new JSONObject(); + JSONObject jsonObject_1 = new JSONObject(); + jsonObject_1.put("appRecordId", appRecordId); + jsonObject_1.put("userId",userId); + jsonObject2.put("params",jsonObject_1); + String jsonMessage = jsonObject2.toJSONString(); + //调用接口结果 + String result = RequestClient.getInstance().callService(ToDoCenterConstant.URI_SEND_finish,jsonMessage); + //保存发送消息日志 + // writeMessageLog(MessageCenterConstant.URI_SEND_MESSAGE,messageInfo,result); + //接口调用结果 + JSONObject jsonObject = JSONObject.parseObject(result); + if(jsonObject.getBoolean("success")){ + //发送成功 + RequestClient.getInstance().saveDeLToDo(appRecordId,userId,ToDoCenterConstant.URI_SEND_finish,true,result,jsonMessage,"2"); + return true; + }else{ + //发送失败 + RequestClient.getInstance().saveDeLToDo(appRecordId,userId,ToDoCenterConstant.URI_SEND_finish,false,result,jsonMessage,"2"); + return false; + } + } catch (Exception e) { + logger.error("调用接口失败:"+e.getMessage(),e); + return false; + } + } +} diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/handler/deleteToDoHandler.java b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/handler/deleteToDoHandler.java new file mode 100644 index 0000000..0f6ad85 --- /dev/null +++ b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/handler/deleteToDoHandler.java @@ -0,0 +1,57 @@ +package shkd.sys.sys.midservice.handler; + +import com.alibaba.fastjson.JSONObject; +import kd.bos.logging.Log; +import kd.bos.logging.LogFactory; +import shkd.sys.sys.midservice.constant.ToDoCenterConstant; +import shkd.sys.sys.midservice.utils.RequestClient; + + +/** + * @Description: + * @Author: FangShiXiao + * @Date: 2024/11/5 14:18 + * @Version: 1.0 + * @Ability 撤销 + */ +public class deleteToDoHandler { + private static Log logger = LogFactory.getLog(deleteToDoHandler.class); + + private static deleteToDoHandler _deleteToDoHandler; + + public static synchronized deleteToDoHandler get_deleteToDoHandler(){ + if(_deleteToDoHandler == null){ + _deleteToDoHandler = new deleteToDoHandler(); + } + return _deleteToDoHandler; + } + + public boolean sendDeleteToDo(Long appRecordId,String userId) { + try { + //body + JSONObject jsonObject2 = new JSONObject(); + JSONObject jsonObject_1 = new JSONObject(); + jsonObject_1.put("appRecordId", appRecordId); + jsonObject_1.put("userId",userId); + jsonObject2.put("params",jsonObject_1); + String jsonMessage = jsonObject2.toJSONString(); + //调用接口结果 + String result = RequestClient.getInstance().callService(ToDoCenterConstant.URI_send_deleteP,jsonMessage); + //保存发送消息日志 + // writeMessageLog(MessageCenterConstant.URI_SEND_MESSAGE,messageInfo,result); + //接口调用结果 + JSONObject jsonObject = JSONObject.parseObject(result); + if(jsonObject.getBoolean("success")){ + //发送成功 + RequestClient.getInstance().saveDeLToDo(appRecordId,userId,ToDoCenterConstant.URI_send_deleteP,true,result,jsonMessage,"5"); + return true; + }else{ + RequestClient.getInstance().saveDeLToDo(appRecordId,userId,ToDoCenterConstant.URI_send_deleteP,false,result,jsonMessage,"5"); + return false; + } + } catch (Exception e) { + logger.error("###调用中台服务消息中心发送消息服务异常:"+e.getMessage(),e); + return false; + } + } +} diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/model/BacklogMessage.java b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/model/BacklogMessage.java new file mode 100644 index 0000000..7169bb7 --- /dev/null +++ b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/model/BacklogMessage.java @@ -0,0 +1,176 @@ +package shkd.sys.sys.midservice.model; + +/** + * @Description: + * @Author: FangShiXiao + * @Date: 2024/11/5 13:38 + * @Version: 1.0 + * @Ability + */ +public class BacklogMessage { + + private String bName;//业务类型名称 String false + private String urGency;//紧急程度 int true 0:普通;1:紧急;2:加急;3:特急 true + private String currentStepName;// 当前步骤名称 String false + private String preStepName;// 上步步骤名称 String false + private String sendUserName;// 发起人名称 String true + private String receiveUserId; //接收人 id String true 支持如下三种类型1.身份证号 2.手机号 3.登录账号 + private String title;// 待办名称 String true + private String handleUrl;// pc 办理 url 地址 String true + private String appHandleUrl;// app 办理地址 String false + private String appViewUrl;// app 查看地址 String false + private String appName;// 应用名称 String false + private String viewUrl;// pc 查看 url 地址 String true + private String pendingId;// 业务 id String true + private String bussinessCode;// 业务编码 String true + private String pendingAttr;// 属性 Int true 0:待办;1:待阅;3:承办 + private String notifyMsg;// 通知消息 String false + private String notifyMethod;// 通知方式 String false 0- 系统消息 1- 短信 2- 邮件3-app 消息推送。多个方式英文逗号隔开 + private String jsonData;// 业务自定义数据 String false 业务模块的数据,再调用查询待办的接口将会返回,建议传一个 json 字符串; + + public String getbName() { + return bName; + } + + public void setbName(String bName) { + this.bName = bName; + } + + public String getUrGency() { + return urGency; + } + + public void setUrGency(String urGency) { + this.urGency = urGency; + } + + public String getCurrentStepName() { + return currentStepName; + } + + public void setCurrentStepName(String currentStepName) { + this.currentStepName = currentStepName; + } + + public String getPreStepName() { + return preStepName; + } + + public void setPreStepName(String preStepName) { + this.preStepName = preStepName; + } + + public String getSendUserName() { + return sendUserName; + } + + public void setSendUserName(String sendUserName) { + this.sendUserName = sendUserName; + } + + public String getReceiveUserId() { + return receiveUserId; + } + + public void setReceiveUserId(String receiveUserId) { + this.receiveUserId = receiveUserId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getHandleUrl() { + return handleUrl; + } + + public void setHandleUrl(String handleUrl) { + this.handleUrl = handleUrl; + } + + public String getAppHandleUrl() { + return appHandleUrl; + } + + public void setAppHandleUrl(String appHandleUrl) { + this.appHandleUrl = appHandleUrl; + } + + public String getAppViewUrl() { + return appViewUrl; + } + + public void setAppViewUrl(String appViewUrl) { + this.appViewUrl = appViewUrl; + } + + public String getAppName() { + return appName; + } + + public void setAppName(String appName) { + this.appName = appName; + } + + public String getViewUrl() { + return viewUrl; + } + + public void setViewUrl(String viewUrl) { + this.viewUrl = viewUrl; + } + + public String getPendingId() { + return pendingId; + } + + public void setPendingId(String pendingId) { + this.pendingId = pendingId; + } + + public String getBussinessCode() { + return bussinessCode; + } + + public void setBussinessCode(String bussinessCode) { + this.bussinessCode = bussinessCode; + } + + public String getPendingAttr() { + return pendingAttr; + } + + public void setPendingAttr(String pendingAttr) { + this.pendingAttr = pendingAttr; + } + + public String getNotifyMsg() { + return notifyMsg; + } + + public void setNotifyMsg(String notifyMsg) { + this.notifyMsg = notifyMsg; + } + + public String getNotifyMethod() { + return notifyMethod; + } + + public void setNotifyMethod(String notifyMethod) { + this.notifyMethod = notifyMethod; + } + + public String getJsonData() { + return jsonData; + } + + public void setJsonData(String jsonData) { + this.jsonData = jsonData; + } + + +} diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/servicehandler/BacklogServiceHandle.java b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/servicehandler/BacklogServiceHandle.java new file mode 100644 index 0000000..f7843e8 --- /dev/null +++ b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/servicehandler/BacklogServiceHandle.java @@ -0,0 +1,112 @@ +package shkd.sys.sys.midservice.servicehandler; + +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.logging.Log; +import kd.bos.logging.LogFactory; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.QueryServiceHelper; +import kd.bos.workflow.engine.msg.ctx.MessageContext; +import kd.bos.workflow.engine.msg.handler.AbstractServiceHandler; +import kd.bos.workflow.engine.msg.info.ToDoInfo; +import shkd.sys.sys.midservice.handler.CreateToDoHandler; +import shkd.sys.sys.midservice.handler.DealToDoHandler; +import shkd.sys.sys.midservice.handler.deleteToDoHandler; +import shkd.sys.sys.midservice.model.BacklogMessage; + +import java.util.List; + +/** + * @Description: + * @Author: FangShiXiao + * @Date: 2024/11/5 14:07 + * @Version: 1.0 + * @Ability + */ +public class BacklogServiceHandle extends AbstractServiceHandler { + + public static final String TYPE = "todo"; + + private static final Log logger = LogFactory.getLog(BacklogServiceHandle.class); + + public void createToDo(MessageContext ctx, ToDoInfo todoInfo) { + + logger.info("###创建待办_createToDo"); + //几个待办 + List userIds = todoInfo.getUserIds(); + DynamicObjectCollection query = QueryServiceHelper.query("bos_user", "id,name,phone", new QFilter[]{new QFilter("id", "in", userIds)}); + DynamicObject dynamicObject = QueryServiceHelper.queryOne("wf_hitaskinst", "billno,startname,id,name", + new QFilter[]{new QFilter("id", "=", todoInfo.getTaskId())}); + for (DynamicObject query_one : query) { + + BacklogMessage backlogMessage = new BacklogMessage(); + //业务类型名称 + backlogMessage.setbName("业务类型名称"); + // 紧急程度 + backlogMessage.setUrGency("0"); + //当前节点名称 + backlogMessage.setCurrentStepName(dynamicObject.getString("name")); + //上步骤名称 + backlogMessage.setPreStepName(""); + // startname发起人名称 + backlogMessage.setSendUserName(dynamicObject.getString("startname")); + //接收人手机号 + backlogMessage.setReceiveUserId(query_one.getString("phone")); + //标题 + backlogMessage.setTitle(todoInfo.getTitle()); + //PC地址 + backlogMessage.setHandleUrl(todoInfo.getUrl()); + //PC地址查看 + backlogMessage.setViewUrl(todoInfo.getUrl()+"&ado=view"); + //app地址 + backlogMessage.setAppHandleUrl(todoInfo.getUrl()); + //App应用名称 + backlogMessage.setAppName(""); + //app地址查看 + backlogMessage.setAppViewUrl(todoInfo.getUrl()+"&ado=view"); + //业务id + backlogMessage.setPendingId(String.valueOf(todoInfo.getTaskId())); + // 业务编码 + backlogMessage.setBussinessCode(dynamicObject.getString("billno")); + //属性 + backlogMessage.setPendingAttr("0"); + //notifyMsg 通知消息 + backlogMessage.setNotifyMsg(""); + //notifyMethod 通知方式 + backlogMessage.setNotifyMethod(""); + //业务自定义数据 + backlogMessage.setJsonData(""); + CreateToDoHandler.get_CreateToDoHandler().sendCreateToDo(backlogMessage); + } + logger.info("###结束待办_createToDo"); + + } + + //已办 + public void dealToDo(MessageContext ctx, ToDoInfo info){ + logger.info("###创建已办_dealToDo"); + //几个已办 + List userIds = info.getUserIds(); + DynamicObjectCollection query = QueryServiceHelper.query("bos_user", "id,name,phone", new QFilter[]{new QFilter("id", "in", userIds)}); + //业务id + Long taskId = ctx.getTaskId(); + for (DynamicObject queryOne : query) { + DealToDoHandler.get_DealToDoHandler().sendDealToDo(taskId,queryOne.getString("phone")); + } + logger.info("###结束已办_dealToDo"); + + } + //撤销 + public void deleteToDo(MessageContext ctx, ToDoInfo info){ + logger.info("###创建撤销_deleteToDo"); + List userIds = info.getUserIds(); + DynamicObjectCollection query = QueryServiceHelper.query("bos_user", "id,name,phone", new QFilter[]{new QFilter("id", "in", userIds)}); + //业务id + Long taskId = ctx.getTaskId(); + for (DynamicObject queryOne : query) { + deleteToDoHandler.get_deleteToDoHandler().sendDeleteToDo(taskId,queryOne.getString("phone")); + } + logger.info("###结束撤销_deleteToDo"); + } + +} diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/utils/GetUrlUtils.java b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/utils/GetUrlUtils.java new file mode 100644 index 0000000..fe3d90c --- /dev/null +++ b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/utils/GetUrlUtils.java @@ -0,0 +1,52 @@ +package shkd.sys.sys.midservice.utils; + +/** + * @Description: + * @Author: FangShiXiao + * @Date: 2024/11/7 14:38 + * @Version: 1.0 + * @Ability 获得url地址 + */ +public class GetUrlUtils { + + private static GetUrlUtils _instance; + /** + * 获取实例 + */ + public static synchronized GetUrlUtils getInstance() { + if (_instance == null) { + _instance = new GetUrlUtils(); + } + return _instance; + } + + /** + * 构建待办链接 + * @param formId PC表单id + * @param mobFormId 移动表单id + * @param source 来源应用编码 + * @param accountId 数据中心 + * @param activityId 活动id + * @param pkId 单据id + * @param taskId 任务id + * @return + */ + public String getPcUrl(String formId, String mobFormId, String source, String accountId, + Object activityId, Object pkId, Object taskId) { + StringBuffer urlBuffer = new StringBuffer(); + urlBuffer.append(System.getProperty("efms.midservice.backlog.url")); + // urlBuffer.append("http:10.17.85:8022/ierp"); + urlBuffer.append("/integration/yzjShareOpen.do"); + urlBuffer.append("?formId=").append(formId); + urlBuffer.append("&mb_formId=").append(mobFormId); + urlBuffer.append("&pkId=").append(pkId); + urlBuffer.append("&src=").append(source.toLowerCase()); + urlBuffer.append("&accountId=").append(accountId); + urlBuffer.append("&activityId=").append(activityId); + urlBuffer.append("&tId=").append(taskId); + urlBuffer.append("&apptype=backlogMQ"); + return urlBuffer.toString(); + } + + +} diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/utils/RequestClient.java b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/utils/RequestClient.java new file mode 100644 index 0000000..446b0a5 --- /dev/null +++ b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/midservice/utils/RequestClient.java @@ -0,0 +1,130 @@ +package shkd.sys.sys.midservice.utils; + +import com.alibaba.fastjson.JSON; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import kd.bos.servicehelper.operation.SaveServiceHelper; +import kd.bos.util.HttpClientUtils; +import kd.bos.util.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * @Description: + * @Author: FangShiXiao + * @Date: 2024/11/5 14:46 + * @Version: 1.0 + * @Ability + */ +public class RequestClient { + private static RequestClient _instance; + private static Logger logger = LoggerFactory.getLogger(RequestClient.class); + // application/x-www-form-urlencoded + private String protocal;//http + private String ip;// 域名 + private String port;// 端口 + + private RequestClient() { + this.protocal = System.getProperty("efms.midservice.protocal"); + this.ip = System.getProperty("efms.midservice.ip"); + this.port = System.getProperty("efms.midservice.port"); + } + /** + * 获取中台服务客户端实例 + * + * @return + */ + public static synchronized RequestClient getInstance() { + if (_instance == null) { + _instance = new RequestClient(); + } + return _instance; + } + /** + * 封装中台请求头,执行POST请求 + * + * @param url 接口地址(不含http://ip:port的后半部分) + * @param body JSON格式字符串 + * @return 响应结果报文 + */ + public String callService(String url, String body) { + Map header = new HashMap<>(); + header.put("Content-Type", "application/x-www-form-urlencoded"); + StringBuffer urlStr = new StringBuffer(); + urlStr.append(this.protocal).append("://").append(this.ip); + if (!StringUtils.isEmpty(this.port)) { + urlStr.append(":").append(this.port); + } + urlStr.append(url); + String responseText = null; + try { + //直接POST请求 + responseText = HttpClientUtils.postjson(urlStr.toString(), header, body); + logger.info(String.format("###调用接口成功,请求URL:%s,请求Header:%s,请求Body:%s,响应报文:%s", url, JSON.toJSONString(header), body, responseText)); + } catch (IOException e) { + logger.error(String.format("###调用接口异常:%s,请求URL:%s,请求Header:%s,请求Body:%s", e.getMessage(), url, JSON.toJSONString(header), body), e); + } + return responseText; + } + + /*** + * 保存待办日志 + * @param title 标题 + * @param url 路径 + * @param isTrue 接口调用是否成功 + * @param result 响应报文 + * @param jsonMessage 请求报文 + */ + public void saveCreateToDo(String title,String url, boolean isTrue,String result,String jsonMessage){ + logger.info("###开始调用待办保存日志方法"); + StringBuffer urlStr = new StringBuffer(); + urlStr.append(this.protocal).append("://").append(this.ip); + if (!StringUtils.isEmpty(this.port)) { + urlStr.append(":").append(this.port); + } + urlStr.append(url);; + DynamicObject dynamicObject = BusinessDataServiceHelper.newDynamicObject("shkd_backlog"); + dynamicObject.set("shkd_url",urlStr); + dynamicObject.set("shkd_request",title); + dynamicObject.set("shkd_request_tag",jsonMessage); + dynamicObject.set("shkd_response",isTrue); + dynamicObject.set("shkd_response",result); + dynamicObject.set("shkd_status","0"); + SaveServiceHelper.save(new DynamicObject[]{dynamicObject}); + logger.info("###结束调用待办保存日志方法"); + } + /*** + * 保存待办日志 + * @param appRecordId 业务id + * @param userId 接收人id + * @param url 路径 + * @param isTrue 接口调用是否成功 + * @param result 响应报文 + * @param jsonMessage 请求报文 + * @param status 类型 2:已办 5:撤销 + */ + public void saveDeLToDo(Long appRecordId,String userId,String url,boolean isTrue,String result,String jsonMessage,String status){ + logger.info("###开始调用已办、撤销保存日志方法"); + StringBuffer urlStr = new StringBuffer(); + urlStr.append(this.protocal).append("://").append(this.ip); + if (!StringUtils.isEmpty(this.port)) { + urlStr.append(":").append(this.port); + } + urlStr.append(url); + DynamicObject dynamicObject = BusinessDataServiceHelper.newDynamicObject("shkd_backlog"); + dynamicObject.set("shkd_url",urlStr); + dynamicObject.set("shkd_request","业务id:"+appRecordId+",接收人手机号:"+userId); + dynamicObject.set("shkd_request_tag",jsonMessage); + dynamicObject.set("shkd_response",isTrue); + dynamicObject.set("shkd_response",result); + dynamicObject.set("shkd_status",status); + logger.info("###开始调用已办、撤销保存日志方法"); + + } + + +} diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/mservice/.gitkeep b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/mservice/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/api/PayBillApiSavePlugin.java b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/api/PayBillApiSavePlugin.java new file mode 100644 index 0000000..415303f --- /dev/null +++ b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/api/PayBillApiSavePlugin.java @@ -0,0 +1,58 @@ +package shkd.sys.sys.plugin.api; + +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.openapi.api.plugin.ApiSavePlugin; +import kd.bos.orm.query.QCP; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.BusinessDataServiceHelper; + +import java.util.List; +import java.util.Map; + +/** + * @Description + * @Author Tao + * @Date 2024/11/7 + */ +public class PayBillApiSavePlugin implements ApiSavePlugin { + @Override + public List> preHandleRequestData(List> reqData) { + //付款处理 → 收款人ID payee → 付款银行.编码 payerbank_number payeetype 收款人类型 → payeenumber 收款人编码 + //payeracctbank_number 付款银行账号.number + + //收款处理 → 付款人ID payer → 收款银行.number payeebank_number payertype 付款人类型 → payernumber 付款人编码 + //accountbank_number 收款银行账号.number + + //重复支付校验 + + String objectType;//对象类型(收/付人类型) + String objectNumber;//对象编码(收/付人编码) + String fieldName1;//字段名称(收/付人ID) + + String bankNumber;//(收/付款银行账号.number) + String fieldName2;//字段名称(收/付款银行.number) + for (Map map : reqData) { + Object payeetype = map.get("payeetype");//如果是收款人类型 则为付款处理保存接口 + if (payeetype != null) { + objectType = payeetype.toString(); + objectNumber = map.get("payeenumber").toString(); + fieldName1 = "payee"; + + bankNumber = map.get("payeracctbank_number").toString(); + fieldName2 = "payerbank_number"; + } else { + objectType = map.get("payertype").toString(); + objectNumber = map.get("payernumber").toString(); + fieldName1 = "payer"; + + bankNumber = map.get("accountbank_number").toString(); + fieldName2 = "payeebank_number"; + } + DynamicObject dynamicObject = BusinessDataServiceHelper.loadSingle(objectType, "id", new QFilter("billno", QCP.equals, objectNumber).toArray()); + DynamicObject amAccountbank = BusinessDataServiceHelper.loadSingle("am_accountbank", "id,bank,bank.number", new QFilter("number", QCP.equals, bankNumber).toArray()); + map.put(fieldName1, dynamicObject.getString("id")); + map.put(fieldName2, amAccountbank.getDynamicObject("bank").getString("number")); + } + return reqData; + } +} diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/api/PayBillApiSerializerPlugin.java b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/api/PayBillApiSerializerPlugin.java new file mode 100644 index 0000000..b0ecfe2 --- /dev/null +++ b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/api/PayBillApiSerializerPlugin.java @@ -0,0 +1,34 @@ +package shkd.sys.sys.plugin.api; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import kd.bos.openapi.api.plugin.ApiSerializerPlugin; +import kd.bos.openapi.api.plugin.SerializerResult; +import kd.bos.openapi.common.constant.MediaType; + +/** + * @Description + * @Author Tao + * @Date 2024/11/7 + */ +public class PayBillApiSerializerPlugin implements ApiSerializerPlugin { + private static final long serialVersionUID = 3514721933945848571L; + + @Override + public SerializerResult serialize(Object response, String accept, String contentType) { + try { + if (contentType.contains(MediaType.APPLICATION_JSON)) { + //返回text文本 + String responseStr = new ObjectMapper().writeValueAsString(response); + return new SerializerResult(MediaType.TEXT_PLAIN, "实际返回:" + responseStr); + } else { + //其他类型的出参序列化 + return null; + } + } catch (JsonProcessingException e) { + //处理异常时严禁抛出异常,可以定义自己的错误返回信息 + String result = "..."; + return new SerializerResult(MediaType.TEXT_PLAIN, result); + } + } +} diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/form/.gitkeep b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/form/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/operate/.gitkeep b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/operate/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/other/.gitkeep b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/other/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/report/.gitkeep b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/report/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/workflow/.gitkeep b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/workflow/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/webapi/.gitkeep b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/webapi/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sys/shkd-sys-sys/src/main/resources/.gitkeep b/sys/shkd-sys-sys/src/main/resources/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sys/src/main/java/fi/plugin/APPaymentListPlugin.java b/sys/src/main/java/fi/plugin/APPaymentListPlugin.java new file mode 100644 index 0000000..cb606cf --- /dev/null +++ b/sys/src/main/java/fi/plugin/APPaymentListPlugin.java @@ -0,0 +1,20 @@ +package fi.plugin; + +import kd.bos.form.control.events.BeforeItemClickEvent; +import kd.bos.form.control.events.ItemClickEvent; +import kd.bos.list.plugin.AbstractListPlugin; + +import java.util.EventObject; + +public class APPaymentListPlugin extends AbstractListPlugin { + + @Override + public void beforeItemClick(BeforeItemClickEvent evt) { + super.beforeItemClick(evt); + String itemKey = evt.getItemKey(); + if ("tbldel".equals(itemKey)){ + this.getView().showErrorNotification("测试————无法删除!"); + evt.setCancel(true); + } + } +} diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/business/test.java b/sys/src/main/java/sys/business/test.java similarity index 86% rename from sys/shkd-sys-sys/src/main/java/shkd/sys/sys/business/test.java rename to sys/src/main/java/sys/business/test.java index 9290473..5b53bf2 100644 --- a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/business/test.java +++ b/sys/src/main/java/sys/business/test.java @@ -1,4 +1,4 @@ -package shkd.sys.sys.business; +package sys.business; import java.util.ArrayList; import java.util.List;