From 9394b44f78ddbe6c7d8c175470c3bdf8341f5dc4 Mon Sep 17 00:00:00 2001 From: zhangh <12345@abc> Date: Sat, 15 Feb 2025 17:12:51 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9B=E5=BB=BA{bd}=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E3=80=81=E6=B7=BB=E5=8A=A0=E6=8A=AC=E5=A4=B4=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E3=80=81=E7=94=9F=E6=88=90=E6=A0=B8=E7=AE=97=E7=BB=B4=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- settings.gradle | 8 + .../java/yem/base/common/utils/OrgUtil.java | 22 + yem-cosmic-debug/build.gradle | 62 +-- yem-wm/yem-wm-bd/build.gradle | 13 + .../FieldMapBillPlugin.class.uniqueId0 | Bin 0 -> 10958 bytes .../compileJava/previous-compilation-data.bin | Bin 0 -> 107437 bytes yem-wm/yem-wm-bd/build/tmp/jar/MANIFEST.MF | 16 + .../build/tmp/sourcesJar/MANIFEST.MF | 2 + .../dynamic/AddCompanyDynamicPlugin.java | 157 ++++++ .../dynamic/AddCustomerDynamicPlugin.java | 135 +++++ .../dynamic/AddSupplierDynamicPlugin.java | 138 ++++++ .../form/BulkbilltplFiDBillPlugin.java | 117 +++++ .../CompanyBankInforDynamicPlugin.java | 86 ++++ .../operation/CompanyInfoSaveOpService.java | 28 ++ .../validator/CompanyInfoSaveValidator.java | 48 ++ .../dynamic/CompanyManInforDynamicPlugin.java | 99 ++++ .../form/FieldMapBillPlugin.java | 284 +++++++++++ .../CreateContractAuditOpPlugin.java | 110 +++++ .../operation/CreateDealAuditOpPlugin.java | 108 ++++ .../CreateInsuranceAuditOpPlugin.java | 108 ++++ .../operation/CreateInvoiceAuditOpPlugin.java | 109 ++++ .../operation/DeleteInsuranceOpPlugin.java | 38 ++ .../dynamic/CusBankDynamicPlugin.java | 76 +++ .../dynamic/CusManDynamicPlugin.java | 85 ++++ .../wm/bd/qrcode/form/QRCodeFormPlugin.java | 31 ++ .../dynamic/SupBankDynamicPlugin.java | 76 +++ .../dynamic/SupManDynamicPlugin.java | 84 ++++ .../java/yem/wm/bd/util/BothCardHelper.java | 464 ++++++++++++++++++ 28 files changed, 2475 insertions(+), 29 deletions(-) create mode 100644 yem-base/yem-base-common/src/main/java/yem/base/common/utils/OrgUtil.java create mode 100644 yem-wm/yem-wm-bd/build.gradle create mode 100644 yem-wm/yem-wm-bd/build/tmp/compileJava/compileTransaction/stash-dir/FieldMapBillPlugin.class.uniqueId0 create mode 100644 yem-wm/yem-wm-bd/build/tmp/compileJava/previous-compilation-data.bin create mode 100644 yem-wm/yem-wm-bd/build/tmp/jar/MANIFEST.MF create mode 100644 yem-wm/yem-wm-bd/build/tmp/sourcesJar/MANIFEST.MF create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/addcompany/dynamic/AddCompanyDynamicPlugin.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/addcustomer/dynamic/AddCustomerDynamicPlugin.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/addsupplier/dynamic/AddSupplierDynamicPlugin.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/bulkbilltpl/form/BulkbilltplFiDBillPlugin.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/companybankinfor/dynamic/CompanyBankInforDynamicPlugin.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/companyinfo/operation/CompanyInfoSaveOpService.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/companyinfo/validator/CompanyInfoSaveValidator.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/companymaninfor/dynamic/CompanyManInforDynamicPlugin.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/form/FieldMapBillPlugin.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/CreateContractAuditOpPlugin.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/CreateDealAuditOpPlugin.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/CreateInsuranceAuditOpPlugin.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/CreateInvoiceAuditOpPlugin.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/DeleteInsuranceOpPlugin.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/customerbankinfor/dynamic/CusBankDynamicPlugin.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/customermaninfor/dynamic/CusManDynamicPlugin.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/qrcode/form/QRCodeFormPlugin.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/supplierbankinfor/dynamic/SupBankDynamicPlugin.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/suppliermaninfor/dynamic/SupManDynamicPlugin.java create mode 100644 yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/util/BothCardHelper.java diff --git a/settings.gradle b/settings.gradle index 2ad02c4..5d3c85f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -19,6 +19,9 @@ include( ':yem-wm-es', ':yem-wm-is', ':yem-wm-ct', + + + ':yem-wm-bd', ) // -------------- 引入苍穹调试工程模块 -------------- @@ -43,3 +46,8 @@ project(':yem-wm-es').projectDir = new File('yem-wm/yem-wm-es') project(':yem-wm-is').projectDir = new File('yem-wm/yem-wm-is') // -------------- 引入wm云-ct应用模块 -------------- project(':yem-wm-ct').projectDir = new File('yem-wm/yem-wm-ct') + + + +// -------------- 引入wm云-bd应用模块 -------------- +project(':yem-wm-bd').projectDir = new File('yem-wm/yem-wm-bd') diff --git a/yem-base/yem-base-common/src/main/java/yem/base/common/utils/OrgUtil.java b/yem-base/yem-base-common/src/main/java/yem/base/common/utils/OrgUtil.java new file mode 100644 index 0000000..89f7e71 --- /dev/null +++ b/yem-base/yem-base-common/src/main/java/yem/base/common/utils/OrgUtil.java @@ -0,0 +1,22 @@ +package yem.base.common.utils; + +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.QueryServiceHelper; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @Description 组织帮助类 + * @Author: zhangh + * @CreateTime: 2025-02-08 11:13 + */ +public class OrgUtil { + public static List getOrgPattern(){ + DynamicObjectCollection typeColl = QueryServiceHelper.query("bos_org_pattern", "id,number", + new QFilter[]{new QFilter("patterntype", "in", new String[]{"1", "2"})}); + List patternList = typeColl.stream().map(x -> x.getLong("id")).collect(Collectors.toList()); + return patternList; + } +} diff --git a/yem-cosmic-debug/build.gradle b/yem-cosmic-debug/build.gradle index 3c2d383..d51e4c1 100644 --- a/yem-cosmic-debug/build.gradle +++ b/yem-cosmic-debug/build.gradle @@ -1,30 +1,34 @@ -/* - * 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-04-19 14:42:16 - */ - -dependencies { - - // 公共基础包 - implementation project(':yem-base-common') - - // 引入wmc云 - ydn应用模块 - implementation project(':yem-wmc-ydn') - // 引入wmc云 ca应用模块 - implementation project(':yem-wmc-ca') - // 引入wmc云 imc应用模块 - implementation project(':yem-wmc-imc') - - // 引入wm云 cm应用模块 - implementation project(':yem-wm-cm') - // 引入wm云 es应用模块 - implementation project(':yem-wm-es') - // 引入wm云 is应用模块 - implementation project(':yem-wm-is') - // 引入wm云 ct应用模块 - implementation project(':yem-wm-ct') - +/* + * 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-04-19 14:42:16 + */ + +dependencies { + + // 公共基础包 + implementation project(':yem-base-common') + + // 引入wmc云 - ydn应用模块 + implementation project(':yem-wmc-ydn') + // 引入wmc云 ca应用模块 + implementation project(':yem-wmc-ca') + // 引入wmc云 imc应用模块 + implementation project(':yem-wmc-imc') + + // 引入wm云 cm应用模块 + implementation project(':yem-wm-cm') + // 引入wm云 es应用模块 + implementation project(':yem-wm-es') + // 引入wm云 is应用模块 + implementation project(':yem-wm-is') + // 引入wm云 ct应用模块 + implementation project(':yem-wm-ct') + + + // 引入wm云 bd应用模块 + implementation project(':yem-wm-bd') + } \ No newline at end of file diff --git a/yem-wm/yem-wm-bd/build.gradle b/yem-wm/yem-wm-bd/build.gradle new file mode 100644 index 0000000..ddbc00e --- /dev/null +++ b/yem-wm/yem-wm-bd/build.gradle @@ -0,0 +1,13 @@ +/* + * 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: 2025-02-07 11:06:50 + */ + +dependencies { + api project(':yem-base-common') +} + + diff --git a/yem-wm/yem-wm-bd/build/tmp/compileJava/compileTransaction/stash-dir/FieldMapBillPlugin.class.uniqueId0 b/yem-wm/yem-wm-bd/build/tmp/compileJava/compileTransaction/stash-dir/FieldMapBillPlugin.class.uniqueId0 new file mode 100644 index 0000000000000000000000000000000000000000..6839a4dbd49384c7acbabff111bb7b3d53ed536e GIT binary patch literal 10958 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 literal 0 HcmV?d00001 diff --git a/yem-wm/yem-wm-bd/build/tmp/jar/MANIFEST.MF b/yem-wm/yem-wm-bd/build/tmp/jar/MANIFEST.MF new file mode 100644 index 0000000..a098bd8 --- /dev/null +++ b/yem-wm/yem-wm-bd/build/tmp/jar/MANIFEST.MF @@ -0,0 +1,16 @@ +Manifest-Version: 1.0 +Jar-Id: +Project-Name: yem-wm-bd +Build-Tool: Gradle 7.6.3 +Build-Date: 2025-02-15 10:49:38 +Built-By: Kingdee Cosmic Developer Tools +Build-Num: 20250215104938457 +App-Name: +Git-Branch: yem_goodday_zh +Cloud-Name: +Group-Name: yem.cosmic +Bundle-Version: 1.0.0 +Git-Commit-Hash: 20330ae5e80eca3fd4d5412f4f4d9e814230fa0f +Build-Image: +Build-Jdk: 1.8.0_131 + diff --git a/yem-wm/yem-wm-bd/build/tmp/sourcesJar/MANIFEST.MF b/yem-wm/yem-wm-bd/build/tmp/sourcesJar/MANIFEST.MF new file mode 100644 index 0000000..59499bc --- /dev/null +++ b/yem-wm/yem-wm-bd/build/tmp/sourcesJar/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 + diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/addcompany/dynamic/AddCompanyDynamicPlugin.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/addcompany/dynamic/AddCompanyDynamicPlugin.java new file mode 100644 index 0000000..055b5ad --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/addcompany/dynamic/AddCompanyDynamicPlugin.java @@ -0,0 +1,157 @@ +package yem.wm.bd.addcompany.dynamic; + +import kd.bos.bill.AbstractBillPlugIn; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.entity.datamodel.IDataModel; +import kd.bos.entity.datamodel.events.ChangeData; +import kd.bos.entity.datamodel.events.PropertyChangedArgs; +import kd.bos.form.IFormView; +import kd.bos.form.control.Control; +import kd.bos.form.events.ClosedCallBackEvent; +import kd.bos.form.field.BasedataEdit; +import kd.bos.list.ListShowParameter; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import yem.base.common.utils.OrgUtil; +import yem.base.common.utils.YEM; +import yem.wm.bd.util.BothCardHelper; + +import java.util.EventObject; + +/** + * @Description 添加公司抬头--表单插件 + * 1、加载界面时,默认获取单据中的{抬头明细(隐藏)}中的公司抬头信息自动给界面赋值 + * 2、切换公司,重新加载公司的默认信息 + * 3、点击确定给父页面返回数据 + * @Author: zhangh + * @CreateTime: 2025-02-08 10:14 + */ +public class AddCompanyDynamicPlugin extends AbstractBillPlugIn { + + @Override + public void afterCreateNewData(EventObject e) { + BothCardHelper.init(this);//加载父页面的信息携带到动态表单上 + } + + @Override + public void registerListener(EventObject e) { + this.addClickListeners("yem_companybank", "yem_companylinkman"); + this.addClickListeners("btnok"); + this.initF7(); + } + + /** + * @return void + * @Description: 对公司进行添加事件的注册以及过滤 + * @function 功能 + * @purposes 用途 + */ + public void initF7() { + String orgtype = (String) this.getModel().getValue("yem_orgtype");//判断系统使用的是《业务单元》还是《公司抬头》 + if ("bos_org".equals(orgtype)) { + BasedataEdit orgF7 = this.getControl("yem_org");//获取公司抬头控件 + orgF7.addBeforeF7SelectListener((beforeF7SelectEvent) -> { + ListShowParameter showParameter = (ListShowParameter) beforeF7SelectEvent.getFormShowParameter(); + QFilter qFilter = new QFilter("orgpattern", "in", OrgUtil.getOrgPattern()); + showParameter.getListFilterParameter().setFilter(qFilter);//列表添加条件:判断公司《组织形态》中的【组织类型】是否是法人企业、法人分支机构 + }); + } + } + + @Override + public void click(EventObject evt) { + super.click(evt); + Control c = (Control) evt.getSource(); + String key = c.getKey().toLowerCase(); + switch (key) { + case "yem_companylinkman"://联系人 + BothCardHelper.showChangePage(this, "yem_bd_companymaninfor");//跳转动态表单 + break; + case "yem_companybank"://开户行 + BothCardHelper.showChangePage(this, "yem_bd_companybankinfor");//跳转动态表单 + break; + case "btnok"://确定按钮 + this.btnOk();//点击确定给父页面返回数据 + break; + } + } + + @Override + public void propertyChanged(PropertyChangedArgs e) { + String key = e.getProperty().getName(); + ChangeData[] changeData = e.getChangeSet(); + Object newValue = changeData[0].getNewValue(); + switch (key) { + case "yem_org"://组织 + this.companyChanged(newValue);//切换组织,根据默认逻辑给公司信息赋值 + break; + } + } + + /** + * @Description: 切换公司组织,公司信息进行重新赋值 + * @function 功能 + * @purposes 用途 + */ + public void companyChanged(Object newValue) { + DynamicObject company = (DynamicObject) newValue; + if (company != null) { + String orgtype = (String) this.getModel().getValue("yem_orgtype");//获取组织类型 + company = BusinessDataServiceHelper.loadSingleFromCache(company.getLong("id"), company.getDataEntityType().getName()); + DynamicObject org = null; + + if ("bos_org".equals(orgtype)) { + org = company;//判断是《业务单元》,默认取值为公司 + } else { + org = company.getDynamicObject("yem_org");//判断是《公司抬头》,取值为《公司抬头》中的《组织》 + } + + if (org != null) { + BothCardHelper.fillCoInfo(this.getModel(), org);////默认给表单所有信息赋值 + } + } + } + + @Override + public void closedCallBack(ClosedCallBackEvent e) { + String id = e.getActionId(); + Object returnData = e.getReturnData(); + switch (id) { + case "yem_bd_companymaninfor"://《公司联系人信息》表单标识 + BothCardHelper.setCompanyManInfor(this, returnData, null);//点击《公司联系人信息》之后,给父页面的信息赋值 + break; + + case "yem_bd_companybankinfor"://《公司银行信息》表单标识 + BothCardHelper.setCompanyBankInfor(this, returnData);//点击《公司银行信息》之后,给父页面的信息赋值 + break; + + } + } + + /** + * @return void + * @Description: 点击确定给父页面返回信息 + * @function 功能 + * @purposes 用途 + */ + public void btnOk() { + + IFormView view = this.getView(); + IDataModel model = this.getModel(); + IFormView parentView = view.getParentView(); + IDataModel parentModel = parentView.getModel(); + + BothCardHelper.btnOkParent(this);//将动态表单的信息返回给付页面 + String defaultInfor = this.getView().getPageCache().get("data"); + if (YEM.isNotEmpty(defaultInfor)) { + parentModel.setValue("yem_isdefaultinfor", defaultInfor);//默认信息(公司) + } + + DynamicObject company = (DynamicObject) model.getValue("yem_org"); + String companyName = company != null ? company.getString("name") : ""; + parentModel.setValue("yem_companyname", companyName);//公司名称 + + view.sendFormAction(parentView); + view.close(); + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/addcustomer/dynamic/AddCustomerDynamicPlugin.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/addcustomer/dynamic/AddCustomerDynamicPlugin.java new file mode 100644 index 0000000..a3bf5ea --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/addcustomer/dynamic/AddCustomerDynamicPlugin.java @@ -0,0 +1,135 @@ +package yem.wm.bd.addcustomer.dynamic; + +import kd.bos.bill.AbstractBillPlugIn; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.entity.datamodel.IDataModel; +import kd.bos.entity.datamodel.events.ChangeData; +import kd.bos.entity.datamodel.events.PropertyChangedArgs; +import kd.bos.form.IFormView; +import kd.bos.form.control.Control; +import kd.bos.form.events.ClosedCallBackEvent; +import kd.bos.form.field.BasedataEdit; +import kd.bos.list.ListShowParameter; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.basedata.BaseDataServiceHelper; +import yem.wm.bd.util.BothCardHelper; + +import java.util.EventObject; + +/** + * @Description 添加客户 + * 1、加载界面时,默认获取单据中的{抬头明细(隐藏)}中的客户信息自动给界面赋值 + * 2、切换【客户】,重新加载【客户】的默认信息 + * 3、点击确定给父页面返回数据 + * @Author: zhangh + * @CreateTime: 2025-02-08 15:15 + */ +public class AddCustomerDynamicPlugin extends AbstractBillPlugIn { + + @Override + public void afterCreateNewData(EventObject e) { + BothCardHelper.init(this);//加载父页面的信息携带到动态表单上 + } + + @Override + public void registerListener(EventObject e) { + super.registerListener(e); + this.addClickListeners("yem_customerbank", "yem_customerlinkman"); + this.addClickListeners("btnok"); + this.initF7(); + } + + /** + * @return void + * @Description: 对客户进行添加事件的注册以及过滤 + * @function 功能 + * @purposes 用途 + */ + private void initF7() { + IFormView parentView = this.getView().getParentView(); + IDataModel parentModel = parentView.getModel(); + DynamicObject org = (DynamicObject) parentModel.getValue("org");//获取父页面的【组织】 + BasedataEdit baseDataCtr = this.getControl("yem_customer");//获取【客户】字段控件 + baseDataCtr.addBeforeF7SelectListener((beforeF7SelectEvent) -> { + ListShowParameter showParameter = (ListShowParameter) beforeF7SelectEvent.getFormShowParameter(); + if (org != null) { + QFilter filter = BaseDataServiceHelper.getBaseDataFilter(showParameter.getBillFormId(), org.getLong("id"));//根据【组织】对【客户】字段进行过滤 + if (filter != null) { + filter.and(new QFilter("status", "=", "C")); + } else { + filter = new QFilter("status", "=", "C"); + } + showParameter.getListFilterParameter().getQFilters().add(filter); + } + }); + } + + /** + * @param e + * @return void + * @Description: 切换字段发生只改变 + * @function 切换【客户】发生改变 + * @purposes 用途 + */ + @Override + public void propertyChanged(PropertyChangedArgs e) { + String key = e.getProperty().getName(); + switch (key) { + case "yem_customer"://客户 + BothCardHelper.setCustomerInfor(this);//切换客户,根据默认逻辑给客户信息赋值 + break; + } + } + + @Override + public void click(EventObject evt) { + Control c = (Control) evt.getSource(); + String key = c.getKey().toLowerCase(); + switch (key) { + case "yem_customerbank":// 开户行 + BothCardHelper.showChangePage(this, "yem_bd_customerbankinfor");//跳转动态表单 + break; + case "yem_customerlinkman":// 点击联系人 + BothCardHelper.showChangePage(this, "yem_bd_customermaninfor");//跳转动态表单 + break; + case "btnok"://确定按钮 + this.btnOk();//点击确定给父页面返回数据 + break; + } + } + + /** + * @return void + * @Description: 点击确定给父页面返回信息 + * @function 功能 + * @purposes 用途 + */ + private void btnOk() { + IFormView view = this.getView(); + IDataModel model = this.getModel(); + IFormView parentView = view.getParentView(); + IDataModel parentModel = parentView.getModel(); + BothCardHelper.btnOkParent(this);//将动态表单的信息返回给付页面 + DynamicObject customer = (DynamicObject) model.getValue("yem_customer"); + + String companyName = customer != null ? customer.getString("name") : ""; + parentModel.setValue("yem_customername", companyName);//客户名称 + + view.sendFormAction(parentView); + view.close(); + } + + @Override + public void closedCallBack(ClosedCallBackEvent e) { + String id = e.getActionId(); + Object returnData = e.getReturnData(); + switch (id) { + case "yem_bd_customerbankinfor"://《客户银行信息》回填 + BothCardHelper.setCustBankInfor(this, returnData);//点击《客户银行信息》之后,给父页面的信息赋值 + break; + case "yem_bd_customermaninfor"://《客户联系人信息》回填 + BothCardHelper.setCustManInfor(this, returnData);//点击《客户联系人信息》之后,给父页面的信息赋值 + break; + } + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/addsupplier/dynamic/AddSupplierDynamicPlugin.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/addsupplier/dynamic/AddSupplierDynamicPlugin.java new file mode 100644 index 0000000..4f07e2f --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/addsupplier/dynamic/AddSupplierDynamicPlugin.java @@ -0,0 +1,138 @@ +package yem.wm.bd.addsupplier.dynamic; + +import kd.bos.bill.AbstractBillPlugIn; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.entity.datamodel.IDataModel; +import kd.bos.entity.datamodel.events.PropertyChangedArgs; +import kd.bos.form.IFormView; +import kd.bos.form.control.Control; +import kd.bos.form.events.ClosedCallBackEvent; +import kd.bos.form.field.BasedataEdit; +import kd.bos.list.ListShowParameter; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.basedata.BaseDataServiceHelper; +import yem.wm.bd.util.BothCardHelper; + +import java.util.EventObject; + +/** + * @Description 添加供应商 + * 1、加载界面时,默认获取单据中的{抬头明细(隐藏)}中的供应商信息自动给界面赋值 + * 2、切换【供应商】,重新加载【供应商】的默认信息 + * 3、点击确定给父页面返回数据 + * @Author: zhangh + * @CreateTime: 2025-02-08 16:32 + */ +public class AddSupplierDynamicPlugin extends AbstractBillPlugIn { + + @Override + public void afterCreateNewData(EventObject e) { + BothCardHelper.init(this);//加载父页面的信息携带到动态表单上 + } + + @Override + public void registerListener(EventObject e) { + super.registerListener(e); + this.addClickListeners("yem_supplierbank", "yem_supplierlinkman"); + this.addClickListeners("btnok"); + this.initF7(); + } + + /** + * @return void + * @Description: 对供应商进行添加事件的注册以及过滤 + * @function 功能 + * @purposes 用途 + */ + private void initF7() { + IFormView parentView = this.getView().getParentView(); + IDataModel parentModel = parentView.getModel(); + DynamicObject org = (DynamicObject) parentModel.getValue("org");//获取父页面的【组织】 + BasedataEdit baseDataCtr = this.getControl("yem_supplier");//获取【供应商】字段控件 + if (baseDataCtr == null) { + return; + } + baseDataCtr.addBeforeF7SelectListener((beforeF7SelectEvent) -> { + ListShowParameter showParameter = (ListShowParameter) beforeF7SelectEvent.getFormShowParameter(); + if (org != null) { + QFilter filter = BaseDataServiceHelper.getBaseDataFilter(showParameter.getBillFormId(), org.getLong("id"));//根据【组织】对【供应商】字段进行过滤 + if (filter != null) { + filter.and(new QFilter("status", "=", "C")); + } else { + filter = new QFilter("status", "=", "C"); + } + showParameter.getListFilterParameter().getQFilters().add(filter); + } + }); + } + + /** + * @param e + * @return void + * @Description: 切换字段发生只改变 + * @function 切换【供应商】发生改变 + * @purposes 用途 + */ + @Override + public void propertyChanged(PropertyChangedArgs e) { + String key = e.getProperty().getName(); + switch (key) { + case "yem_supplier"://供应商 + BothCardHelper.setSupplierInfor(this); + break; + } + } + + @Override + public void click(EventObject evt) { + Control c = (Control) evt.getSource(); + String key = c.getKey().toLowerCase(); + switch (key) { + case "yem_supplierbank":// 开户行 + BothCardHelper.showChangePage(this, "yem_bd_supplierbankinfor");//跳转动态表单 + break; + case "yem_supplierlinkman":// 点击联系人 + BothCardHelper.showChangePage(this, "yem_bd_suppliermaninfor");//跳转动态表单 + break; + case "btnok"://确定按钮 + this.btnOk();//点击确定按钮返回数据 + break; + } + } + + /** + * @return void + * @Description: 点击确定给父页面返回信息 + * @function 功能 + * @purposes 用途 + */ + private void btnOk() { + IFormView view = this.getView(); + IDataModel model = this.getModel(); + IFormView parentView = view.getParentView(); + IDataModel parentModel = parentView.getModel(); + + BothCardHelper.btnOkParent(this);//将动态表单的信息返回给付页面 + DynamicObject supplier = (DynamicObject) model.getValue("yem_supplier");//获取供应商 + String companyName = supplier != null ? supplier.getString("name") : ""; + parentModel.setValue("yem_suppliername", companyName);//供应商名称 + + view.sendFormAction(parentView); + view.close(); + } + + @Override + public void closedCallBack(ClosedCallBackEvent e) { + String id = e.getActionId(); + Object returnData = e.getReturnData(); + switch (id) { + case "yem_bd_supplierbankinfor": + BothCardHelper.setSuppBankInfor(this, returnData); + break; + // 联系人信息回填 + case "yem_bd_suppliermaninfor": + BothCardHelper.setCustManInfor(this, returnData);//点击《供应商联系人信息》之后,给父页面的信息赋值 + break; + } + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/bulkbilltpl/form/BulkbilltplFiDBillPlugin.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/bulkbilltpl/form/BulkbilltplFiDBillPlugin.java new file mode 100644 index 0000000..18892eb --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/bulkbilltpl/form/BulkbilltplFiDBillPlugin.java @@ -0,0 +1,117 @@ +package yem.wm.bd.bulkbilltpl.form; + +import kd.bos.bill.AbstractBillPlugIn; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.form.control.Control; +import kd.bos.form.events.ClosedCallBackEvent; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.QueryServiceHelper; +import yem.base.common.utils.OrgUtil; +import yem.wm.bd.util.BothCardHelper; + +import java.util.EventObject; + +/** + * @Description 抬头信息加载功能 + * 1、在新增单据时,抬头信息根据【公司】加载公司的默认信息 + * 2、点击客户、供应商、公司面板弹动态表单,在动态表单上填写信息,然后回填到单据上 + * 3、在打开单据时以及动态表单回传单据时,给抬头信息中的标签默认赋值 + * @Author: zhangh + * @CreateTime: 2025-02-07 18:20 + */ +public class BulkbilltplFiDBillPlugin extends AbstractBillPlugIn { + + /** + * @param e + * @return void + * @Description: 在新增单据时,默认给{抬头明细(隐藏)}赋默认值 + * @function 根据【公司】默认赋值 + * @purposes + */ + @Override + public void afterCreateNewData(EventObject e) { + DynamicObject org = (DynamicObject) this.getModel().getValue("org");//公司 + if (org != null) { + QFilter[] qFilters = new QFilter[]{new QFilter("orgpattern", "in", OrgUtil.getOrgPattern()), + new QFilter("id", "=", org.getPkValue())};//添加公司的判断条件,在公司的条件下,判断公司《组织形态》中的【组织类型】是否是法人企业、法人分支机构 + if (QueryServiceHelper.exists("bos_org", qFilters)) {//判断业务单元的数据是否满足条件 + BothCardHelper.fillCoInfo(this.getModel(), org);//默认给{抬头明细(隐藏)}信息赋值 + } + } + } + + /** + * @param e + * @return void + * @Description: 打开单据默认给标签赋值 + * @function 在打开单据时,根据{抬头明细(隐藏)}信息中的字段数据默认给客户、供应商、公司标签赋默认值 + * @purposes 用途 + */ + @Override + public void afterBindData(EventObject e) { + BothCardHelper.setCoLabel(this);//默认给公司的标签赋值 + BothCardHelper.setSupplierLabel(this);//默认给供应商的标签赋值 + BothCardHelper.setCustomerLabel(this);//默认给客户的标签赋值 + } + + /** + * @param e + * @return void + * @Description: 注册标签,添加事件 + * @function 功能 + * @purposes 在click中可以触发 + */ + @Override + public void registerListener(EventObject e) { + this.addClickListeners("yem_card_addgys", "yem_addgys1", "yem_addgys2", + "yem_card_addco", "yem_addco1", "yem_addco2", + "yem_card_addkh", "yem_addpayer", "yem_addpayer1", + "yem_changegys", "yem_changeco", "yem_changepayer"); + } + + @Override + public void click(EventObject evt) { + String key = ((Control) evt.getSource()).getKey(); + String name = this.getModel().getDataEntityType().getName(); + switch (key) { + case "yem_card_addco"://添加公司的图标 + case "yem_addco1"://添加公司的标签【+】 + case "yem_addco2"://添加公司的标签【添加】 + case "yem_changeco"://切换公司的标签【切换】 + BothCardHelper.showChangePage(this, "yem_bd_addcompany");//跳转动态表单 + break; + + case "yem_card_addgys"://添加供应商的图标 + case "yem_addgys1"://添加供应商的标签【+】 + case "yem_addgys2"://添加供应商的标签【添加】 + case "yem_changegys"://切换供应商的标签【切换】 + BothCardHelper.showChangePage(this, "yem_bd_addsupplier");//跳转动态表单 + break; + + case "yem_card_addkh"://添加客户的图标 + case "yem_addpayer"://添加客户的标签【+】 + case "yem_addpayer1"://添加客户的标签【添加】 + case "yem_changepayer"://切换客户的标签【切换】 + BothCardHelper.showChangePage(this, "yem_bd_addcustomer");//跳转动态表单 + break; + default: + break; + } + } + + @Override + public void closedCallBack(ClosedCallBackEvent e) { + String id = e.getActionId(); + switch (id) { + case "yem_bd_addcompany"://《添加公司抬头》动态表单标识 + BothCardHelper.setCoLabel(this);//默认给公司的标签赋值 + break; + case "yem_bd_addsupplier"://《添加供应商》动态表单标识 + BothCardHelper.setSupplierLabel(this);//默认给供应商的标签赋值 + break; + case "yem_bd_addcustomer"://《添加客户》动态表单标识 + BothCardHelper.setCustomerLabel(this);//默认给客户的标签赋值 + break; + } + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/companybankinfor/dynamic/CompanyBankInforDynamicPlugin.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/companybankinfor/dynamic/CompanyBankInforDynamicPlugin.java new file mode 100644 index 0000000..0a96798 --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/companybankinfor/dynamic/CompanyBankInforDynamicPlugin.java @@ -0,0 +1,86 @@ +package yem.wm.bd.companybankinfor.dynamic; + +import kd.bos.bill.AbstractBillPlugIn; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.entity.datamodel.IDataModel; +import kd.bos.form.IFormView; +import kd.bos.form.control.Control; +import kd.bos.form.control.EntryGrid; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import yem.wm.bd.util.BothCardHelper; + +import java.util.EventObject; + +/** + * @Description 公司银行信息 + * 1、加载界面时,默认获取《公司抬头》中的{银行信息}自动给单据体赋值 + * 2、选中行数据之后,点击确定给父页面返回数据 + * @Author: zhangh + * @CreateTime: 2025-02-08 11:42 + */ +public class CompanyBankInforDynamicPlugin extends AbstractBillPlugIn { + + @Override + public void afterCreateNewData(EventObject e) { + IFormView view = this.getView(); + IDataModel model = view.getModel(); + + IFormView parentView = view.getParentView(); + IDataModel parentModel = parentView.getModel(); + + DynamicObject company = (DynamicObject) parentModel.getValue("yem_org");//获取父页面的【公司抬头】 + if (company != null) { + String orgtype = (String) parentModel.getValue("yem_orgtype");//获取父页面的【组织类型】 + DynamicObject org = null; + if ("bos_org".equals(orgtype)) { + org = BothCardHelper.queryCompany(company);//系统参数是《业务单元》,根据《业务单元》获取《公司抬头》 + } else { + org = BusinessDataServiceHelper.loadSingleFromCache(company.getLong("id"), company.getDataEntityType().getName()); + } + + DynamicObjectCollection banksentry = org.getDynamicObjectCollection("yem_banksentry");//获取《公司抬头》中的{银行信息} + for (DynamicObject bank : banksentry) { + int row = model.createNewEntryRow("yem_entryentity");//动态表单添加行 + model.setValue("yem_account", bank.get("yem_account"), row);//银行账号 + model.setValue("yem_accountnumber", bank.get("yem_accountnumber"), row);//银行账号 + model.setValue("yem_accountname", bank.get("yem_accountname"), row);//账户名称 + model.setValue("yem_bankaccount", bank.get("yem_bankaccount"), row);//开户银行 + model.setValue("yem_bankaddress", bank.get("yem_bankaddress"), row);//银行地址 + model.setValue("yem_swiftcode", bank.get("yem_swiftcode"), row);//swift code + } + } + } + + @Override + public void click(EventObject evt) { + super.click(evt); + String key = ((Control) evt.getSource()).getKey(); + switch (key) { + case "btnok"://点击确定按钮 + this.btnOk();//点击确定按钮返回数据 + break; + } + } + + /** + * @return void + * @Description: 点击确定给父页面返回信息 + * @function 功能 + * @purposes 用途 + */ + private void btnOk() { + IFormView view = this.getView(); + IDataModel model = this.getModel(); + int selectRows = ((EntryGrid) view.getControl("yem_entryentity")).getEntryState().getFocusRow();//获取选中行的行数 + DynamicObject row = model.getEntryRowEntity("yem_entryentity", selectRows);//获取选中行的数据 + view.returnDataToParent(row); + view.close(); + } + + @Override + public void registerListener(EventObject e) { + super.registerListener(e); + this.addClickListeners("btnok"); + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/companyinfo/operation/CompanyInfoSaveOpService.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/companyinfo/operation/CompanyInfoSaveOpService.java new file mode 100644 index 0000000..11cb351 --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/companyinfo/operation/CompanyInfoSaveOpService.java @@ -0,0 +1,28 @@ +package yem.wm.bd.companyinfo.operation; + +import kd.bos.entity.plugin.AbstractOperationServicePlugIn; +import kd.bos.entity.plugin.AddValidatorsEventArgs; +import kd.bos.entity.plugin.PreparePropertysEventArgs; +import yem.wm.bd.companyinfo.validator.CompanyInfoSaveValidator; + +import java.util.List; + +/** + * @Description 公司抬头保存操作 + * 校验{银行信息}、{联系人信息}有且有唯一的默认值 + * @Author: zhangh + * @CreateTime: 2025-02-08 17:05 + */ +public class CompanyInfoSaveOpService extends AbstractOperationServicePlugIn { + @Override + public void onPreparePropertys(PreparePropertysEventArgs e) { + List fieldKeys = e.getFieldKeys(); + fieldKeys.add("yem_isdefaultbank");//{银行信息}--【默认】 + fieldKeys.add("yem_isdefaultlinkman");//{联系人信息}--【默认】 + } + + @Override + public void onAddValidators(AddValidatorsEventArgs e) { + e.addValidator(new CompanyInfoSaveValidator()); + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/companyinfo/validator/CompanyInfoSaveValidator.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/companyinfo/validator/CompanyInfoSaveValidator.java new file mode 100644 index 0000000..96b9bc2 --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/companyinfo/validator/CompanyInfoSaveValidator.java @@ -0,0 +1,48 @@ +package yem.wm.bd.companyinfo.validator; + +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.entity.ExtendedDataEntity; +import kd.bos.entity.validate.AbstractValidator; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @Description 公司抬头保存校验 + * 校验{银行信息}、{联系人信息}有且有唯一的默认值 + * @Author: zhangh + * @CreateTime: 2025-02-08 17:09 + */ +public class CompanyInfoSaveValidator extends AbstractValidator { + @Override + public void validate() { + for (ExtendedDataEntity extendedDataEntity : this.getDataEntities()) { + checkDefault(extendedDataEntity); + } + } + + /** + * @Description: 校验逻辑 + * @function 校验{银行信息}、{联系人信息}有且仅有唯一的默认值 + * @purposes 用途 + * @param extendedDataEntity + * @return void + */ + + public void checkDefault(ExtendedDataEntity extendedDataEntity) { + DynamicObject dataEntity = extendedDataEntity.getDataEntity();//获取单据的实体 + + DynamicObjectCollection banksentry = dataEntity.getDynamicObjectCollection("yem_banksentry");//获取《公司抬头》--{银行信息} + List isdefaultbank = banksentry.stream().filter(x -> x.getBoolean("yem_isdefaultbank") == true).collect(Collectors.toList());//获取《公司抬头》--{银行信息}中【默认】为是的集合 + if (banksentry.size() > 0 && (isdefaultbank.size() > 1 || isdefaultbank.size() == 0)) { + this.addErrorMessage(extendedDataEntity, "银行信息中需要有一个默认。"); + } + + DynamicObjectCollection linkmanentry = dataEntity.getDynamicObjectCollection("yem_linkmanentry");//获取《公司抬头》--{联系人信息} + List isdefaultlinkman = linkmanentry.stream().filter(x -> x.getBoolean("yem_isdefaultlinkman") == true).collect(Collectors.toList());//获取《公司抬头》--{联系人信息}中【默认】为是的集合 + if (linkmanentry.size() > 0 && (isdefaultlinkman.size() > 1 || isdefaultlinkman.size() == 0)) { + this.addErrorMessage(extendedDataEntity, "联系人信息中需要有一个默认的联系人。"); + } + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/companymaninfor/dynamic/CompanyManInforDynamicPlugin.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/companymaninfor/dynamic/CompanyManInforDynamicPlugin.java new file mode 100644 index 0000000..a00862d --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/companymaninfor/dynamic/CompanyManInforDynamicPlugin.java @@ -0,0 +1,99 @@ +package yem.wm.bd.companymaninfor.dynamic; + +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.entity.datamodel.IDataModel; +import kd.bos.form.IFormView; +import kd.bos.form.control.Control; +import kd.bos.form.control.EntryGrid; +import kd.bos.form.plugin.AbstractFormPlugin; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import yem.wm.bd.util.BothCardHelper; + +import java.util.ArrayList; +import java.util.EventObject; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @Description 公司人员信息--表单插件 + * 1、加载界面时,默认获取《公司抬头》中的{联系人信息}自动给单据体赋值 + * 2、选中行数据之后,点击确定给父页面返回数据 + * @Author: zhangh + * @CreateTime: 2025-02-08 14:39 + */ +public class CompanyManInforDynamicPlugin extends AbstractFormPlugin { + @Override + public void afterCreateNewData(EventObject e) { + IFormView view = this.getView();//动态表单的view视图 + IDataModel model = view.getModel();//动态表单的model模型 + + IFormView parentView = view.getParentView();//获取父页面的view视图 + IDataModel parentModel = parentView.getModel();//获取父页面的model模型 + + DynamicObject company = (DynamicObject) parentModel.getValue("yem_org");//获取父页面的【公司字段】 + if (company != null) { + String orgtype = (String) parentModel.getValue("yem_orgtype");//获取父页面的【组织类型】 + DynamicObject org = null; + if ("bos_org".equals(orgtype)) { + org = BothCardHelper.queryCompany(company);//系统参数是《业务单元》,获取《公司抬头》 + } else { + org = BusinessDataServiceHelper.loadSingleFromCache(company.getLong("id"), company.getDataEntityType().getName()); + } + + if (org != null) { + DynamicObjectCollection linkmanentry = org.getDynamicObjectCollection("yem_linkmanentry");//《公司抬头》信息中{联系人信息} + for (DynamicObject linkman : linkmanentry) { + int row = model.createNewEntryRow("yem_entryentity");//动态表单单据体添加行 + model.setValue("yem_companylinkman", linkman.get("yem_contactperson"), row);//人员 + model.setValue("yem_companytel", linkman.get("yem_phonenum"), row);//电话 + model.setValue("yem_companyemail", linkman.get("yem_addemail"), row);//E-Mail + model.setValue("yem_companyvx", linkman.get("yem_suppliervx"), row);//微信 + model.setValue("yem_companyqq", linkman.get("yem_supplierqq"), row);//QQ + model.setValue("yem_companyfax", org.get("yem_fax"), row);//传真 + } + } + } + } + + @Override + public void click(EventObject evt) { + super.click(evt); + String key = ((Control) evt.getSource()).getKey(); + switch (key) { + case "btnok"://确定按钮 + this.btnOk();//点击确定按钮返回数据 + break; + } + } + + /** + * @Description: 点击确定给父页面返回信息 + * @function 功能 + * @purposes 用途 + * @return void + */ + public void btnOk() { + EntryGrid entryGrid = this.getView().getControl("yem_entryentity");//获取单据体控件 + int[] selectRows = entryGrid.getSelectRows();//获取选中的行数 + List list = new ArrayList<>(); + for (int rowIndex : selectRows) { + DynamicObject entryRowEntity = this.getModel().getEntryRowEntity("yem_entryentity", rowIndex); + list.add(entryRowEntity); + } + + List defaultInfor = list.stream().filter(x -> x.getBoolean("yem_default") == true).collect(Collectors.toList());//判断选中的行数中是否勾选了【默认】 + if (defaultInfor.size() == 0 || defaultInfor.size() > 1){ + this.getView().showErrorNotification("公司联系人信息中需要有勾选一个默认的联系人。"); + return; + } + this.getView().returnDataToParent(list); + this.getView().close(); + } + + @Override + public void registerListener(EventObject e) { + super.registerListener(e); + this.addClickListeners("btnok"); + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/form/FieldMapBillPlugin.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/form/FieldMapBillPlugin.java new file mode 100644 index 0000000..c584c1d --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/form/FieldMapBillPlugin.java @@ -0,0 +1,284 @@ +package yem.wm.bd.createbasedata.form; + +import kd.bos.bill.AbstractBillPlugIn; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.LocaleString; +import kd.bos.dataentity.metadata.IDataEntityProperty; +import kd.bos.dataentity.metadata.IDataEntityType; +import kd.bos.dataentity.metadata.dynamicobject.DynamicProperty; +import kd.bos.dataentity.serialization.SerializationUtils; +import kd.bos.dataentity.utils.StringUtils; +import kd.bos.designer.botp.BillTreeBuildParameter; +import kd.bos.designer.botp.EntityParseHelper; +import kd.bos.designer.query.QueryEntityParseHelper; +import kd.bos.designer.query.QueryEntityTreeBuildParameter; +import kd.bos.entity.EntityType; +import kd.bos.entity.MainEntityType; +import kd.bos.entity.botp.CRFormula; +import kd.bos.entity.botp.plugin.args.LoadFuncTypesEventArgs; +import kd.bos.entity.botp.runtime.ConvertFuncLoader; +import kd.bos.entity.datamodel.events.ChangeData; +import kd.bos.entity.datamodel.events.PropertyChangedArgs; +import kd.bos.entity.function.FunctionTypes; +import kd.bos.entity.property.AttachmentProp; +import kd.bos.entity.property.IFieldHandle; +import kd.bos.entity.tree.TreeNode; +import kd.bos.form.CloseCallBack; +import kd.bos.form.FormShowParameter; +import kd.bos.form.ShowType; +import kd.bos.form.control.Control; +import kd.bos.form.events.ClosedCallBackEvent; +import kd.bos.servicehelper.MetadataServiceHelper; +import yem.base.common.utils.YEM; + +import java.util.ArrayList; +import java.util.EventObject; +import java.util.List; + +/** + * @Description 字段映射配置-表单插件 + * 1、选择【目标实体】自动带出【目标实体】中的所有字段 + * 2、值改变清空【源单字段】、【计算公式】,自动清空与之对应的隐藏字段 + * 3、点击【源单字段】之后,跳转《选择单据字段》,然后在《选择单据字段》中点击确定之后,携带信息到表单上 + * 4、点击【计算公式】之后,跳转《表达式》,然后在《表达式》中点击确定之后,携带信息到单据上 + * @Author: zhangh + * @CreateTime: 2025-02-13 14:19 + */ +public class FieldMapBillPlugin extends AbstractBillPlugIn { + + @Override + public void propertyChanged(PropertyChangedArgs e) { + String name = e.getProperty().getName(); + ChangeData[] changeSet = e.getChangeSet(); + Object newValue = changeSet[0].getNewValue(); + int rowIndex = changeSet[0].getRowIndex(); + switch (name) { + case "yem_targetentity"://目标实体 + setTargetVAlue();//选择【目标实体】,自动带出【目标实体】对应的所有字段 + break; + case "yem_sourcefield": + if (YEM.isEmpty(newValue)) { + this.getModel().setValue("yem_sourcekey", "", rowIndex);//清空【源单字段】,清空隐藏的【源单字段标识】 + } + break; + case "yem_formulas": + if (YEM.isEmpty(newValue)) { + this.getModel().setValue("yem_math", "", rowIndex);//清空【计算公式】,清空隐藏的【公式】 + } + break; + default: + break; + } + } + + /** + * @return void + * @Description: 选择【目标实体】,自动带出【目标实体】对应的所有字段 + * @function + * @purposes + */ + public void setTargetVAlue() { + this.getModel().deleteEntryData("yem_fieldcontrast_e");//先清楚{字段对照}单据体所有数据 + DynamicObject targetentity = (DynamicObject) this.getModel().getValue("yem_targetentity");//获取【目标实体】 + if (targetentity == null) return; + MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType(targetentity.getString("number"));//获取元数据模型,主要用于读取字段类型和字段模型相关。 + + for (EntityType entityType : dataEntityType.getAllEntities().values()) {//遍历字段类型 + for (IDataEntityProperty property : entityType.getFields().values()) { + if (!(property instanceof IFieldHandle)) continue; + int rowIndex = this.getModel().createNewEntryRow("yem_fieldcontrast_e");//{字段对照}添加行 + DynamicProperty field = (DynamicProperty) property; + String targetFieldKey = field.getName();//获取字段标识 + String targetFieldName = buildPropFullCaption(property);//获取字段名称 + this.getModel().setValue("yem_targetkey", targetFieldKey, rowIndex); + this.getModel().setValue("yem_targetfield", targetFieldName, rowIndex); + } + } + } + + /** + * @Description: 获取字段的名称 + * @function 功能 + * @purposes 用途 + * @param property 字段实体属性 + * @return String 返回字段名称(包含单据体名称) + */ + public String buildPropFullCaption(IDataEntityProperty property) { + List captions = new ArrayList(); + IDataEntityType parentType = property.getParent(); //获取字段的上级控件 + LocaleString displayCaption; + if (parentType instanceof MainEntityType) {//判断上级控件是实体 + captions.add("单据头"); + } else if (parentType instanceof EntityType) {//判断上级控件是单据体 + displayCaption = (parentType).getDisplayName();//获取单据体的名称 + captions.add(displayCaption == null ? "" : displayCaption.toString()); + } + + if (property instanceof DynamicProperty) { + displayCaption = property.getDisplayName(); + captions.add(displayCaption == null ? property.getName() : displayCaption.toString()); + } else { + captions.add(property.getName()); + } + + return StringUtils.join(captions.toArray(), "."); + } + + @Override + public void registerListener(EventObject e) { + this.addClickListeners("yem_sourcefield", "yem_formulas"); + } + + @Override + public void click(EventObject evt) { + String key = ((Control) evt.getSource()).getKey(); + switch (key) { + case "yem_sourcefield"://【源单字段】 + showSourceField();//点击【源单字段】,跳转《选择单据字段》 + break; + case "yem_formulas"://【计算公式】 + showFormula();//点击【计算公式】,跳转《表达式》 + break; + } + } + + /** + * @Description: 跳转《表达式》 + * @function 创建树形结构,然后跳转《选择单据字段》携带参数 + * @purposes + * @return void + */ + + public void showFormula() { + DynamicObject sourceentity = (DynamicObject) this.getModel().getValue("yem_sourceentity");//获取【源单实体】 + if (sourceentity == null) { + this.getView().showErrorNotification("请先填写源单实体。"); + return; + } + + DynamicObject targetentity = (DynamicObject) this.getModel().getValue("yem_targetentity");//获取【目标单实体】 + MainEntityType targeEntityType = MetadataServiceHelper.getDataEntityType(targetentity.getString("number"));//获取元数据模型,主要用于读取字段类型和字段模型相关。 + int row = this.getModel().getEntryCurrentRowIndex("yem_fieldcontrast_e"); + String targetPropName = (String) this.getModel().getValue("yem_targetkey", row); + IDataEntityProperty targetProperty = targeEntityType.findProperty(targetPropName); + if (targetProperty == null || (targetProperty instanceof AttachmentProp)) return; + + MainEntityType sourceMainType = MetadataServiceHelper.getDataEntityType(sourceentity.getString("number"));//获取元数据模型,主要用于读取字段类型和字段模型相关。 + + BillTreeBuildParameter parameter = new BillTreeBuildParameter(sourceMainType);//创建树性结构的参数 + parameter.setIncludePKField(true);//是否包含单据id + TreeNode billTreeNode = EntityParseHelper.buildBillTreeNodes(parameter);//创建树性结构 + String billNodeJson = SerializationUtils.toJsonString(billTreeNode);//序列化树形结构 + + String formula = (String) this.getModel().getValue("yem_math", row);//获取【计算公式】 + if (StringUtils.isBlank(formula)) { + CRFormula crFormula = new CRFormula(); + formula = SerializationUtils.toJsonString(crFormula);//序列话计算公式 + } + + FunctionTypes functionTypes = FunctionTypes.getCommonFuncs();//输出预置的公共函数 + FunctionTypes cloudFunc = ConvertFuncLoader.loadBizCloudFuncTypes(); + functionTypes.getFunctionGroups().addAll(cloudFunc.getFunctionGroups());//添加函数分组集合 + functionTypes.getFunctionTypes().addAll(cloudFunc.getFunctionTypes());//添加函数定义集合 + LoadFuncTypesEventArgs args = new LoadFuncTypesEventArgs(functionTypes); + String funcsXML = FunctionTypes.serializeToXML(args.getFuncTypes());//对预置的函数进行序列化 + + FormShowParameter showParameter = new FormShowParameter(); + showParameter.setFormId("botp_formula");//跳转《表达式》 + showParameter.getCustomParams().put("formula", formula);//传参,计算公式的参数 + showParameter.getCustomParams().put("entitynumber", sourceentity.getString("number"));//传参, 单据标识 + showParameter.getCustomParams().put("treenodes", billNodeJson);//传参,序列化的树形结构 + + showParameter.getCustomParams().put("functiontypes", funcsXML);//传参,序列化的预置函数 + showParameter.setCloseCallBack(new CloseCallBack(this, "yem_formulas")); + showParameter.getOpenStyle().setShowType(ShowType.Modal); + this.getView().showForm(showParameter); + } + + /** + * @Description: 跳转《选择单据字段》 + * @function 创建树形结构,然后跳转《选择单据字段》携带参数 + * @purposes 用途 + * @return void + */ + public void showSourceField() { + DynamicObject sourceentity = (DynamicObject) this.getModel().getValue("yem_sourceentity");//获取【源单实体】 + if (sourceentity == null) { + this.getView().showErrorNotification("请先填写源单实体。"); + return; + } + + DynamicObject targetentity = (DynamicObject) this.getModel().getValue("yem_targetentity");//获取【目标单实体】 + MainEntityType targeEntityType = MetadataServiceHelper.getDataEntityType(targetentity.getString("number"));//获取元数据模型,主要用于读取字段类型和字段模型相关。 + + int row = this.getModel().getEntryCurrentRowIndex("yem_fieldcontrast_e");//获取当前焦点行 + String targetFieldValue = (String) this.getModel().getValue("yem_targetkey", row);//获取【目标字段】的标识 + + IDataEntityProperty targetProperty = targeEntityType.findProperty(targetFieldValue);///需要过滤显示的字段类型,根据【目标字段】进行过滤 + if (targetProperty == null) return; + + MainEntityType sourceMainType = MetadataServiceHelper.getDataEntityType(sourceentity.getString("number"));//获取元数据模型,主要用于读取字段类型和字段模型相关。 + BillTreeBuildParameter parameter = new BillTreeBuildParameter(sourceMainType, null, targetProperty);//创建树性结构的参数,树形结构显示的字段类型和【目标字段】一致 + parameter.setIncludePKField(true);//是否包含单据id + TreeNode billTreeNode = EntityParseHelper.buildBillTreeNodes(parameter);//创建树性结构 + + FormShowParameter showParameter = new FormShowParameter(); + showParameter.setFormId("botp_selectfield"); + String nodesJson = SerializationUtils.toJsonString(billTreeNode);//序列化 + showParameter.getCustomParams().put("treenodes", nodesJson);//传参 + showParameter.setCloseCallBack(new CloseCallBack(this, "yem_sourcefield")); + showParameter.getOpenStyle().setShowType(ShowType.Modal); + this.getView().showForm(showParameter); + } + + @Override + public void closedCallBack(ClosedCallBackEvent e) { + String actionId = e.getActionId(); + Object returnData = e.getReturnData(); + switch (actionId) { + case "yem_sourcefield"://【源单字段】 + setSourceInfor((String) returnData);//《选择单据字段》点击确定之后,将信息返回到单据上 + break; + case "yem_formulas": + setForMulas((String) returnData); + break; + } + } + + /** + * @Description: 《表达式》点击确定之后,将信息返回到单据上 + * @function 功能 + * @purposes 用途 + * @param returnData 《表达式》的返回值(序列化后的计算表达式) + * @return void + */ + public void setForMulas(String returnData) { + if (StringUtils.isNotBlank(returnData)) { + CRFormula formula = SerializationUtils.fromJsonString(returnData, CRFormula.class);//将返回值转换成计算公式 + int row = this.getModel().getEntryCurrentRowIndex("yem_fieldcontrast_e");//获取选中的焦点行 + this.getModel().setValue("yem_math", returnData, row);//计算公式序列话后的数据 + this.getModel().setValue("yem_formulas", formula.getExprDesc(), row);//输出合并后的计算公式描述 + } + } + + /** + * @Description: 《选择单据字段》点击确定之后,将信息返回到单据上 + * @function 功能 + * @purposes 用途 + * @param returnData 《选择单据字段》的返回值(字段标识) + * @return void + */ + public void setSourceInfor(String returnData) { + DynamicObject sourceentity = (DynamicObject) this.getModel().getValue("yem_sourceentity");//获取【源单实体】 + MainEntityType sourceMainType = MetadataServiceHelper.getDataEntityType(sourceentity.getString("number"));//获取元数据模型,主要用于读取字段类型和字段模型相关。 + IDataEntityProperty property = null; + for (EntityType entityType : sourceMainType.getAllEntities().values()) { + if (!entityType.getFields().containsKey(returnData)) continue;//判断返回的字段标识是否存在 + property = entityType.getFields().get(returnData); + } + if (property == null) return; + int rowIndex = this.getModel().getEntryCurrentRowIndex("yem_fieldcontrast_e");//获取选中的焦点行 + this.getModel().setValue("yem_sourcekey", returnData, rowIndex);//【源单字段标识】 + this.getModel().setValue("yem_sourcefield", buildPropFullCaption(property), rowIndex);//【源单字段】 + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/CreateContractAuditOpPlugin.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/CreateContractAuditOpPlugin.java new file mode 100644 index 0000000..6e973ba --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/CreateContractAuditOpPlugin.java @@ -0,0 +1,110 @@ +package yem.wm.bd.createbasedata.operation; + +import kd.bos.dataentity.OperateOption; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.dataentity.metadata.IDataEntityType; +import kd.bos.dataentity.serialization.SerializationUtils; +import kd.bos.entity.EntityType; +import kd.bos.entity.MainEntityType; +import kd.bos.entity.botp.CRFormula; +import kd.bos.entity.formula.BOSExpressionContext; +import kd.bos.entity.formula.CalcExprParser; +import kd.bos.entity.formula.RowDataModel; +import kd.bos.entity.function.FunctionManage; +import kd.bos.entity.plugin.AbstractOperationServicePlugIn; +import kd.bos.entity.plugin.args.EndOperationTransactionArgs; +import kd.bos.orm.query.QCP; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import kd.bos.servicehelper.MetadataServiceHelper; +import kd.bos.servicehelper.operation.OperationServiceHelper; +import yem.base.common.utils.DynamicObjectUtil; +import yem.base.common.utils.YEM; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Description 审核生成合同资料 + * 1、第一次点击审核生成合同资料 + * 2、第二次点击审核以及合同变更更新合同资料 + * @Author: zhangh + * @CreateTime: 2025-02-13 10:04 + */ +public class CreateContractAuditOpPlugin extends AbstractOperationServicePlugIn { + + @Override + public void endOperationTransaction(EndOperationTransactionArgs e) { + DynamicObject[] dataEntities = e.getDataEntities(); + for (DynamicObject dataEntity : dataEntities) { + String name = dataEntity.getDataEntityType().getName(); + dataEntity = BusinessDataServiceHelper.loadSingleFromCache(dataEntity.getLong("id"), name);//变更方案确认之后,添加泵更更新的逻辑 + createDataBase(dataEntity, name);//生成以及跟新《合同资料》 + } + } + + /** + * @param dataEntity 合同实体 + * @param name 合同标识 + * @return void + * @Description: 生成以及更新《合同资料》 + * @function 审核时生成《合同资料》以及更新《合同资料》 + * @purposes 用途 + */ + public void createDataBase(DynamicObject dataEntity, String name) { + + List qFilters = new ArrayList<>(); + + qFilters.add(new QFilter("yem_billkey", QCP.equals, name));//《合同资料》中【单据标识】条件 + qFilters.add(new QFilter("yem_billid", QCP.equals, dataEntity.getLong("id"))); + + String selectfields = DynamicObjectUtil.getSelectfields("yem_bd_contractinfor", false); + DynamicObject baseData = BusinessDataServiceHelper.loadSingle("yem_bd_contractinfor", selectfields, qFilters.toArray(new QFilter[]{}));//根据条件查询《合同资料》 + + if (baseData == null) {//如果查询到的《合同资料》为空,则创建《合同资料》实体 + baseData = BusinessDataServiceHelper.newDynamicObject("yem_bd_contractinfor"); + } + + qFilters.clear(); + qFilters.add(new QFilter("yem_sourceentity.number", QCP.equals, name)); + qFilters.add(new QFilter("yem_targetentity.number", QCP.equals, "yem_bd_contractinfor")); + String selectfield = DynamicObjectUtil.getSelectfields("yem_bd_fieldmap", false); + selectfield = DynamicObjectUtil.getEntrySelectfields(selectfield, "yem_bd_fieldmap", "yem_fieldcontrast_e", false); + DynamicObject fieldmap = BusinessDataServiceHelper.loadSingle("yem_bd_fieldmap", selectfield, qFilters.toArray(new QFilter[]{}));//查询《字段映射配置》表 + if (fieldmap != null) { + DynamicObjectCollection fieldcontrastEntry = fieldmap.getDynamicObjectCollection("yem_fieldcontrast_e");//获取《字段映射》配置中的{字段对照} + MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType(name);//获取元数据模型,主要用于读取字段类型和字段模型相关。 + for (DynamicObject entry : fieldcontrastEntry) { + String sourcekey = entry.getString("yem_sourcekey");//获取《字段映射配置》中{字段对照}【源单标识】字段 + String math = entry.getString("yem_math");//获取《字段映射配置》中{字段对照}【计算公式】字段 + Object value = null; + if (YEM.isNotEmpty(sourcekey)) { + for (EntityType type : dataEntityType.getAllEntities().values()) { + if (!(type instanceof MainEntityType)) continue;//判断是否属于单据头,如果是单据体则跳出循环 + if (!type.getFields().containsKey(sourcekey)) continue;;//判断源单字段是否是单据头字段,如果不是单据头字段,则跳出本次循环 + value = dataEntity.get(sourcekey); + } + + } else if (YEM.isNotEmpty(math)) { + CRFormula formula = SerializationUtils.fromJsonString(math, CRFormula.class);//对【计算公式】进行序列话 + String expression = formula.getExpression();//获取计算公式的表达式 + //RowDataModel第一个入参要传入当前的实体名,如解析单据体的数据,则传入单据体标识 + RowDataModel rowDataModel = new RowDataModel(name, dataEntityType); + rowDataModel.setRowContext(dataEntity); + BOSExpressionContext bosExpressionContext = new BOSExpressionContext(rowDataModel);//创建表达式运行上下文对象 + value = CalcExprParser.getExpressionValue(expression, bosExpressionContext, FunctionManage.get());//根据表达式取值 + } + //目标字段 + String targetfieidexp = entry.getString("yem_targetkey"); + MainEntityType dataTarEntityType = MetadataServiceHelper.getDataEntityType("yem_bd_contractinfor");//获取元数据模型,主要用于读取字段类型和字段模型相关。 + for (EntityType entityType : dataTarEntityType.getAllEntities().values()) { + if (!(entityType instanceof MainEntityType)) continue;//判断是否属于单据头,如果是单据体则跳出循环 + if (!entityType.getFields().containsKey(targetfieidexp)) continue;//判断源单字段是否是单据头字段,如果不是单据头字段,则跳出本次循环 + baseData.set(targetfieidexp, value); + } + } + OperationServiceHelper.executeOperate("save", "yem_bd_contractinfor", new DynamicObject[]{baseData}, OperateOption.create()); + } + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/CreateDealAuditOpPlugin.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/CreateDealAuditOpPlugin.java new file mode 100644 index 0000000..f6d4153 --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/CreateDealAuditOpPlugin.java @@ -0,0 +1,108 @@ +package yem.wm.bd.createbasedata.operation; + +import kd.bos.dataentity.OperateOption; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.dataentity.serialization.SerializationUtils; +import kd.bos.entity.EntityType; +import kd.bos.entity.MainEntityType; +import kd.bos.entity.botp.CRFormula; +import kd.bos.entity.formula.BOSExpressionContext; +import kd.bos.entity.formula.CalcExprParser; +import kd.bos.entity.formula.RowDataModel; +import kd.bos.entity.function.FunctionManage; +import kd.bos.entity.plugin.AbstractOperationServicePlugIn; +import kd.bos.entity.plugin.args.EndOperationTransactionArgs; +import kd.bos.orm.query.QCP; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import kd.bos.servicehelper.MetadataServiceHelper; +import kd.bos.servicehelper.operation.OperationServiceHelper; +import yem.base.common.utils.DynamicObjectUtil; +import yem.base.common.utils.YEM; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Description 审核生成协议资料 + * 1、第一次点击审核生成协议资料 + * 2、第二次点击审核以及合同变更更新协议资料 + * @Author: zhangh + * @CreateTime: 2025-02-14 18:12 + */ +public class CreateDealAuditOpPlugin extends AbstractOperationServicePlugIn { + @Override + public void endOperationTransaction(EndOperationTransactionArgs e) { + DynamicObject[] dataEntities = e.getDataEntities(); + for (DynamicObject dataEntity : dataEntities) { + String name = dataEntity.getDataEntityType().getName(); + dataEntity = BusinessDataServiceHelper.loadSingleFromCache(dataEntity.getLong("id"), name);//变更方案确认之后,添加泵更更新的逻辑 + createDataBase(dataEntity, name);//生成以及跟新《协议资料》 + } + } + + /** + * @param dataEntity 合同实体 + * @param name 合同标识 + * @return void + * @Description: 生成以及更新《协议资料》 + * @function 审核时生成《协议资料》以及更新《协议资料》 + * @purposes 用途 + */ + public void createDataBase(DynamicObject dataEntity, String name) { + + List qFilters = new ArrayList<>(); + + qFilters.add(new QFilter("yem_billkey", QCP.equals, name));//《协议资料》中【单据标识】条件 + qFilters.add(new QFilter("yem_billid", QCP.equals, dataEntity.getLong("id"))); + + String selectfields = DynamicObjectUtil.getSelectfields("yem_bd_agreementinfo", false); + DynamicObject baseData = BusinessDataServiceHelper.loadSingle("yem_bd_agreementinfo", selectfields, qFilters.toArray(new QFilter[]{}));//根据条件查询《协议资料》 + + if (baseData == null) {//如果查询到的《协议资料》为空,则创建《协议资料》实体 + baseData = BusinessDataServiceHelper.newDynamicObject("yem_bd_agreementinfo"); + } + + qFilters.clear(); + qFilters.add(new QFilter("yem_sourceentity.number", QCP.equals, name)); + qFilters.add(new QFilter("yem_targetentity.number", QCP.equals, "yem_bd_agreementinfo")); + String selectfield = DynamicObjectUtil.getSelectfields("yem_bd_fieldmap", false); + selectfield = DynamicObjectUtil.getEntrySelectfields(selectfield, "yem_bd_fieldmap", "yem_fieldcontrast_e", false); + DynamicObject fieldmap = BusinessDataServiceHelper.loadSingle("yem_bd_fieldmap", selectfield, qFilters.toArray(new QFilter[]{}));//查询《字段映射配置》表 + if (fieldmap != null) { + DynamicObjectCollection fieldcontrastEntry = fieldmap.getDynamicObjectCollection("yem_fieldcontrast_e");//获取《字段映射》配置中的{字段对照} + MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType(name);//获取元数据模型,主要用于读取字段类型和字段模型相关。 + for (DynamicObject entry : fieldcontrastEntry) { + String sourcekey = entry.getString("yem_sourcekey");//获取《字段映射配置》中{字段对照}【源单标识】字段 + String math = entry.getString("yem_math");//获取《字段映射配置》中{字段对照}【计算公式】字段 + Object value = null; + if (YEM.isNotEmpty(sourcekey)) { + for (EntityType type : dataEntityType.getAllEntities().values()) { + if (!(type instanceof MainEntityType)) continue;//判断是否属于单据头,如果是单据体则跳出循环 + if (!type.getFields().containsKey(sourcekey)) continue;;//判断源单字段是否是单据头字段,如果不是单据头字段,则跳出本次循环 + value = dataEntity.get(sourcekey); + } + + } else if (YEM.isNotEmpty(math)) { + CRFormula formula = SerializationUtils.fromJsonString(math, CRFormula.class);//对【计算公式】进行序列话 + String expression = formula.getExpression();//获取计算公式的表达式 + //RowDataModel第一个入参要传入当前的实体名,如解析单据体的数据,则传入单据体标识 + RowDataModel rowDataModel = new RowDataModel(name, dataEntityType); + rowDataModel.setRowContext(dataEntity); + BOSExpressionContext bosExpressionContext = new BOSExpressionContext(rowDataModel);//创建表达式运行上下文对象 + value = CalcExprParser.getExpressionValue(expression, bosExpressionContext, FunctionManage.get());//根据表达式取值 + } + //目标字段 + String targetfieidexp = entry.getString("yem_targetkey"); + MainEntityType dataTarEntityType = MetadataServiceHelper.getDataEntityType("yem_bd_agreementinfo");//获取元数据模型,主要用于读取字段类型和字段模型相关。 + for (EntityType entityType : dataTarEntityType.getAllEntities().values()) { + if (!(entityType instanceof MainEntityType)) continue;//判断是否属于单据头,如果是单据体则跳出循环 + if (!entityType.getFields().containsKey(targetfieidexp)) continue;//判断源单字段是否是单据头字段,如果不是单据头字段,则跳出本次循环 + baseData.set(targetfieidexp, value); + } + } + OperationServiceHelper.executeOperate("save", "yem_bd_agreementinfo", new DynamicObject[]{baseData}, OperateOption.create()); + } + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/CreateInsuranceAuditOpPlugin.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/CreateInsuranceAuditOpPlugin.java new file mode 100644 index 0000000..d4e2132 --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/CreateInsuranceAuditOpPlugin.java @@ -0,0 +1,108 @@ +package yem.wm.bd.createbasedata.operation; + +import kd.bos.dataentity.OperateOption; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.dataentity.serialization.SerializationUtils; +import kd.bos.entity.EntityType; +import kd.bos.entity.MainEntityType; +import kd.bos.entity.botp.CRFormula; +import kd.bos.entity.formula.BOSExpressionContext; +import kd.bos.entity.formula.CalcExprParser; +import kd.bos.entity.formula.RowDataModel; +import kd.bos.entity.function.FunctionManage; +import kd.bos.entity.plugin.AbstractOperationServicePlugIn; +import kd.bos.entity.plugin.args.EndOperationTransactionArgs; +import kd.bos.orm.query.QCP; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import kd.bos.servicehelper.MetadataServiceHelper; +import kd.bos.servicehelper.operation.OperationServiceHelper; +import yem.base.common.utils.DynamicObjectUtil; +import yem.base.common.utils.YEM; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Description 审核生成保险资料 + * 1、第一次点击审核生成保险资料 + * 2、第二次点击审核以及合同变更更新保险资料 + * @Author: zhangh + * @CreateTime: 2025-02-14 18:20 + */ +public class CreateInsuranceAuditOpPlugin extends AbstractOperationServicePlugIn { + @Override + public void endOperationTransaction(EndOperationTransactionArgs e) { + DynamicObject[] dataEntities = e.getDataEntities(); + for (DynamicObject dataEntity : dataEntities) { + String name = dataEntity.getDataEntityType().getName(); + dataEntity = BusinessDataServiceHelper.loadSingleFromCache(dataEntity.getLong("id"), name);//变更方案确认之后,添加泵更更新的逻辑 + createDataBase(dataEntity, name);//生成以及跟新《保险资料》 + } + } + + /** + * @param dataEntity 合同实体 + * @param name 合同标识 + * @return void + * @Description: 生成以及更新《保险资料》 + * @function 审核时生成《保险资料》以及更新《保险资料》 + * @purposes 用途 + */ + public void createDataBase(DynamicObject dataEntity, String name) { + + List qFilters = new ArrayList<>(); + + qFilters.add(new QFilter("yem_billkey", QCP.equals, name));//《保险资料》中【单据标识】条件 + qFilters.add(new QFilter("yem_billid", QCP.equals, dataEntity.getLong("id"))); + + String selectfields = DynamicObjectUtil.getSelectfields("yem_bd_insuranceinfor", false); + DynamicObject baseData = BusinessDataServiceHelper.loadSingle("yem_bd_insuranceinfor", selectfields, qFilters.toArray(new QFilter[]{}));//根据条件查询《保险资料》 + + if (baseData == null) {//如果查询到的《保险资料》为空,则创建《保险资料》实体 + baseData = BusinessDataServiceHelper.newDynamicObject("yem_bd_insuranceinfor"); + } + + qFilters.clear(); + qFilters.add(new QFilter("yem_sourceentity.number", QCP.equals, name)); + qFilters.add(new QFilter("yem_targetentity.number", QCP.equals, "yem_bd_insuranceinfor")); + String selectfield = DynamicObjectUtil.getSelectfields("yem_bd_fieldmap", false); + selectfield = DynamicObjectUtil.getEntrySelectfields(selectfield, "yem_bd_fieldmap", "yem_fieldcontrast_e", false); + DynamicObject fieldmap = BusinessDataServiceHelper.loadSingle("yem_bd_fieldmap", selectfield, qFilters.toArray(new QFilter[]{}));//查询《字段映射配置》表 + if (fieldmap != null) { + DynamicObjectCollection fieldcontrastEntry = fieldmap.getDynamicObjectCollection("yem_fieldcontrast_e");//获取《字段映射》配置中的{字段对照} + MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType(name);//获取元数据模型,主要用于读取字段类型和字段模型相关。 + for (DynamicObject entry : fieldcontrastEntry) { + String sourcekey = entry.getString("yem_sourcekey");//获取《字段映射配置》中{字段对照}【源单标识】字段 + String math = entry.getString("yem_math");//获取《字段映射配置》中{字段对照}【计算公式】字段 + Object value = null; + if (YEM.isNotEmpty(sourcekey)) { + for (EntityType type : dataEntityType.getAllEntities().values()) { + if (!(type instanceof MainEntityType)) continue;//判断是否属于单据头,如果是单据体则跳出循环 + if (!type.getFields().containsKey(sourcekey)) continue;;//判断源单字段是否是单据头字段,如果不是单据头字段,则跳出本次循环 + value = dataEntity.get(sourcekey); + } + + } else if (YEM.isNotEmpty(math)) { + CRFormula formula = SerializationUtils.fromJsonString(math, CRFormula.class);//对【计算公式】进行序列话 + String expression = formula.getExpression();//获取计算公式的表达式 + //RowDataModel第一个入参要传入当前的实体名,如解析单据体的数据,则传入单据体标识 + RowDataModel rowDataModel = new RowDataModel(name, dataEntityType); + rowDataModel.setRowContext(dataEntity); + BOSExpressionContext bosExpressionContext = new BOSExpressionContext(rowDataModel);//创建表达式运行上下文对象 + value = CalcExprParser.getExpressionValue(expression, bosExpressionContext, FunctionManage.get());//根据表达式取值 + } + //目标字段 + String targetfieidexp = entry.getString("yem_targetkey"); + MainEntityType dataTarEntityType = MetadataServiceHelper.getDataEntityType("yem_bd_insuranceinfor");//获取元数据模型,主要用于读取字段类型和字段模型相关。 + for (EntityType entityType : dataTarEntityType.getAllEntities().values()) { + if (!(entityType instanceof MainEntityType)) continue;//判断是否属于单据头,如果是单据体则跳出循环 + if (!entityType.getFields().containsKey(targetfieidexp)) continue;//判断源单字段是否是单据头字段,如果不是单据头字段,则跳出本次循环 + baseData.set(targetfieidexp, value); + } + } + OperationServiceHelper.executeOperate("save", "yem_bd_insuranceinfor", new DynamicObject[]{baseData}, OperateOption.create()); + } + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/CreateInvoiceAuditOpPlugin.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/CreateInvoiceAuditOpPlugin.java new file mode 100644 index 0000000..a7b8cdc --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/CreateInvoiceAuditOpPlugin.java @@ -0,0 +1,109 @@ +package yem.wm.bd.createbasedata.operation; + +import kd.bos.dataentity.OperateOption; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.dataentity.serialization.SerializationUtils; +import kd.bos.entity.EntityType; +import kd.bos.entity.MainEntityType; +import kd.bos.entity.botp.CRFormula; +import kd.bos.entity.formula.BOSExpressionContext; +import kd.bos.entity.formula.CalcExprParser; +import kd.bos.entity.formula.RowDataModel; +import kd.bos.entity.function.FunctionManage; +import kd.bos.entity.plugin.AbstractOperationServicePlugIn; +import kd.bos.entity.plugin.args.EndOperationTransactionArgs; +import kd.bos.orm.query.QCP; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import kd.bos.servicehelper.MetadataServiceHelper; +import kd.bos.servicehelper.operation.OperationServiceHelper; +import yem.base.common.utils.DynamicObjectUtil; +import yem.base.common.utils.YEM; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Description 审核生成发票资料 + * 1、第一次点击审核生成发票资料 + * 2、第二次点击审核以及合同变更更新发票资料 + * @Author: zhangh + * @CreateTime: 2025-02-14 18:06 + */ +public class CreateInvoiceAuditOpPlugin extends AbstractOperationServicePlugIn { + + @Override + public void endOperationTransaction(EndOperationTransactionArgs e) { + DynamicObject[] dataEntities = e.getDataEntities(); + for (DynamicObject dataEntity : dataEntities) { + String name = dataEntity.getDataEntityType().getName(); + dataEntity = BusinessDataServiceHelper.loadSingleFromCache(dataEntity.getLong("id"), name);//变更方案确认之后,添加泵更更新的逻辑 + createDataBase(dataEntity, name);//生成以及跟新《发票资料》 + } + } + + /** + * @param dataEntity 合同实体 + * @param name 合同标识 + * @return void + * @Description: 生成以及更新《发票资料》 + * @function 审核时生成《发票资料》以及更新《发票资料》 + * @purposes 用途 + */ + public void createDataBase(DynamicObject dataEntity, String name) { + + List qFilters = new ArrayList<>(); + + qFilters.add(new QFilter("yem_billkey", QCP.equals, name));//《发票资料》中【单据标识】条件 + qFilters.add(new QFilter("yem_billid", QCP.equals, dataEntity.getLong("id"))); + + String selectfields = DynamicObjectUtil.getSelectfields("yem_bd_invoiceinfor", false); + DynamicObject baseData = BusinessDataServiceHelper.loadSingle("yem_bd_invoiceinfor", selectfields, qFilters.toArray(new QFilter[]{}));//根据条件查询《发票资料》 + + if (baseData == null) {//如果查询到的《发票资料》为空,则创建《发票资料》实体 + baseData = BusinessDataServiceHelper.newDynamicObject("yem_bd_invoiceinfor"); + } + + qFilters.clear(); + qFilters.add(new QFilter("yem_sourceentity.number", QCP.equals, name)); + qFilters.add(new QFilter("yem_targetentity.number", QCP.equals, "yem_bd_invoiceinfor")); + String selectfield = DynamicObjectUtil.getSelectfields("yem_bd_fieldmap", false); + selectfield = DynamicObjectUtil.getEntrySelectfields(selectfield, "yem_bd_fieldmap", "yem_fieldcontrast_e", false); + DynamicObject fieldmap = BusinessDataServiceHelper.loadSingle("yem_bd_fieldmap", selectfield, qFilters.toArray(new QFilter[]{}));//查询《字段映射配置》表 + if (fieldmap != null) { + DynamicObjectCollection fieldcontrastEntry = fieldmap.getDynamicObjectCollection("yem_fieldcontrast_e");//获取《字段映射》配置中的{字段对照} + MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType(name);//获取元数据模型,主要用于读取字段类型和字段模型相关。 + for (DynamicObject entry : fieldcontrastEntry) { + String sourcekey = entry.getString("yem_sourcekey");//获取《字段映射配置》中{字段对照}【源单标识】字段 + String math = entry.getString("yem_math");//获取《字段映射配置》中{字段对照}【计算公式】字段 + Object value = null; + if (YEM.isNotEmpty(sourcekey)) { + for (EntityType type : dataEntityType.getAllEntities().values()) { + if (!(type instanceof MainEntityType)) continue;//判断是否属于单据头,如果是单据体则跳出循环 + if (!type.getFields().containsKey(sourcekey)) continue;;//判断源单字段是否是单据头字段,如果不是单据头字段,则跳出本次循环 + value = dataEntity.get(sourcekey); + } + + } else if (YEM.isNotEmpty(math)) { + CRFormula formula = SerializationUtils.fromJsonString(math, CRFormula.class);//对【计算公式】进行序列话 + String expression = formula.getExpression();//获取计算公式的表达式 + //RowDataModel第一个入参要传入当前的实体名,如解析单据体的数据,则传入单据体标识 + RowDataModel rowDataModel = new RowDataModel(name, dataEntityType); + rowDataModel.setRowContext(dataEntity); + BOSExpressionContext bosExpressionContext = new BOSExpressionContext(rowDataModel);//创建表达式运行上下文对象 + value = CalcExprParser.getExpressionValue(expression, bosExpressionContext, FunctionManage.get());//根据表达式取值 + } + //目标字段 + String targetfieidexp = entry.getString("yem_targetkey"); + MainEntityType dataTarEntityType = MetadataServiceHelper.getDataEntityType("yem_bd_invoiceinfor");//获取元数据模型,主要用于读取字段类型和字段模型相关。 + for (EntityType entityType : dataTarEntityType.getAllEntities().values()) { + if (!(entityType instanceof MainEntityType)) continue;//判断是否属于单据头,如果是单据体则跳出循环 + if (!entityType.getFields().containsKey(targetfieidexp)) continue;//判断源单字段是否是单据头字段,如果不是单据头字段,则跳出本次循环 + baseData.set(targetfieidexp, value); + } + } + OperationServiceHelper.executeOperate("save", "yem_bd_invoiceinfor", new DynamicObject[]{baseData}, OperateOption.create()); + } + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/DeleteInsuranceOpPlugin.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/DeleteInsuranceOpPlugin.java new file mode 100644 index 0000000..253bb34 --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/createbasedata/operation/DeleteInsuranceOpPlugin.java @@ -0,0 +1,38 @@ +package yem.wm.bd.createbasedata.operation; + +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.entity.plugin.AbstractOperationServicePlugIn; +import kd.bos.entity.plugin.args.BeforeOperationArgs; +import kd.bos.orm.query.QCP; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import kd.bos.servicehelper.operation.DeleteServiceHelper; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Description 删除核算维度数据 + * 合同单据在点击删除时,同步删除核算维度资料 + * @Author: zhangh + * @CreateTime: 2025-02-14 18:22 + */ +public class DeleteInsuranceOpPlugin extends AbstractOperationServicePlugIn { + + @Override + public void beforeExecuteOperationTransaction(BeforeOperationArgs e) { + for (DynamicObject dataEntity : e.getDataEntities()) { + //需要判断是否是变更单,如果是变更单据,则跳出 + String name = dataEntity.getDataEntityType().getName(); + dataEntity = BusinessDataServiceHelper.loadSingleFromCache(dataEntity.getLong("id"), name); + + DynamicObject fieldmap = BusinessDataServiceHelper.loadSingle("yem_bd_fieldmap", "id,yem_targetentity", new QFilter[]{new QFilter("yem_sourceentity.number", QCP.equals, name)});//查询《核算维度字段映射配置》 + if (fieldmap != null) { + List qFilters = new ArrayList<>(); + qFilters.add(new QFilter("yem_billkey", QCP.equals, name)); + qFilters.add(new QFilter("yem_billid", QCP.equals, dataEntity.getLong("id"))); + DeleteServiceHelper.delete(fieldmap.getDynamicObject("yem_targetentity").getString("number"), qFilters.toArray(new QFilter[]{})); + } + } + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/customerbankinfor/dynamic/CusBankDynamicPlugin.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/customerbankinfor/dynamic/CusBankDynamicPlugin.java new file mode 100644 index 0000000..c737f1e --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/customerbankinfor/dynamic/CusBankDynamicPlugin.java @@ -0,0 +1,76 @@ +package yem.wm.bd.customerbankinfor.dynamic; + +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.entity.datamodel.IDataModel; +import kd.bos.form.IFormView; +import kd.bos.form.control.Control; +import kd.bos.form.control.EntryGrid; +import kd.bos.form.plugin.AbstractFormPlugin; +import kd.bos.servicehelper.BusinessDataServiceHelper; + +import java.util.EventObject; + +/** + * @Description 客户银行信息 + * 1、加载界面时,默认获取《客户》中的{银行信息}自动给单据体赋值 + * 2、选中行数据之后,点击确定给父页面返回数据 + * @Author: zhangh + * @CreateTime: 2025-02-08 16:03 + */ +public class CusBankDynamicPlugin extends AbstractFormPlugin { + + @Override + public void afterCreateNewData(EventObject e) { + IFormView view = this.getView(); + IDataModel model = view.getModel(); + + IFormView parentView = view.getParentView(); + IDataModel parentModel = parentView.getModel(); + + DynamicObject customer = (DynamicObject) parentModel.getValue("yem_customer");//获取父页面的【客户】字段 + if (customer != null) { + customer = BusinessDataServiceHelper.loadSingleFromCache(customer.getLong("id"), customer.getDataEntityType().getName()); + + DynamicObjectCollection banksentry = customer.getDynamicObjectCollection("entry_bank");//《客户》中的{银行信息} + for (DynamicObject bank : banksentry) { + int row = model.createNewEntryRow("yem_entryentity");//动态表单单据体添加行数 + model.setValue("yem_accountnumber", bank.get("bankaccount"), row);//银行账号 + model.setValue("yem_accountname", bank.get("accountname"), row);//账户名称 + model.setValue("yem_bankaccount", bank.get("bank"), row);//开户银行 + } + } + } + + @Override + public void click(EventObject evt) { + super.click(evt); + String key = ((Control) evt.getSource()).getKey(); + switch (key) { + case "btnok"://确定按钮 + this.btnOk();//点击确定按钮返回数据 + break; + } + } + + /** + * @Description: 点击确定给父页面返回信息 + * @function 功能 + * @purposes 用途 + * @return void + */ + private void btnOk() { + IFormView view = this.getView(); + IDataModel model = this.getModel(); + int selectRows = ((EntryGrid) view.getControl("yem_entryentity")).getEntryState().getFocusRow();//获取选中行的行数 + DynamicObject row = model.getEntryRowEntity("yem_entryentity", selectRows);//获取选中行的数据 + view.returnDataToParent(row); + view.close(); + } + + @Override + public void registerListener(EventObject e) { + super.registerListener(e); + this.addClickListeners("btnok"); + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/customermaninfor/dynamic/CusManDynamicPlugin.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/customermaninfor/dynamic/CusManDynamicPlugin.java new file mode 100644 index 0000000..8139a3b --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/customermaninfor/dynamic/CusManDynamicPlugin.java @@ -0,0 +1,85 @@ +package yem.wm.bd.customermaninfor.dynamic; + +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.entity.datamodel.IDataModel; +import kd.bos.form.IFormView; +import kd.bos.form.control.Control; +import kd.bos.form.control.EntryGrid; +import kd.bos.form.plugin.AbstractFormPlugin; +import kd.bos.servicehelper.BusinessDataServiceHelper; + +import java.util.EventObject; + +/** + * @Description 客户人员信息 + * 1、加载界面时,默认获取《客户》中的{联系人信息}以及{联系人信息}中【关联地值】属性【详细地址】、【微信】、【QQ】自动给单据体赋值 + * 2、选中行数据之后,点击确定给父页面返回数据 + * @Author: zhangh + * @CreateTime: 2025-02-08 16:12 + */ +public class CusManDynamicPlugin extends AbstractFormPlugin { + + @Override + public void afterCreateNewData(EventObject e) { + IFormView view = this.getView(); + IDataModel model = view.getModel(); + + IFormView parentView = view.getParentView(); + IDataModel parentModel = parentView.getModel(); + + DynamicObject customer = (DynamicObject) parentModel.getValue("yem_customer");//获取父页面的【客户】字段 + if (customer != null) { + customer = BusinessDataServiceHelper.loadSingleFromCache(customer.getLong("id"), customer.getDataEntityType().getName()); + + DynamicObjectCollection linkmanentry = customer.getDynamicObjectCollection("entry_linkman");//《客户》中的{联系人信息} + for (DynamicObject linkman : linkmanentry) { + int row = model.createNewEntryRow("yem_entryentity");//动态表单单据体添加行数 + model.setValue("yem_customeruser", linkman.get("contactperson"), row);//人员 + model.setValue("yem_customertel", linkman.get("phone"), row);//电话 + model.setValue("yem_customeremail", linkman.get("email"), row);//E-Mail + model.setValue("yem_customerfax", linkman.get("fax"), row);//传真 + + DynamicObject associatedaddress = linkman.getDynamicObject("associatedaddress");//关联地址 + if (associatedaddress != null) { + associatedaddress = BusinessDataServiceHelper.loadSingleFromCache(associatedaddress.getLong("id"), associatedaddress.getDataEntityType().getName()); + model.setValue("yem_customervx", associatedaddress.get("yem_suppliervx"), row);//微信(公司)--微信 + model.setValue("yem_customerqq", associatedaddress.get("yem_supplierqq"), row);//QQ(公司)--QQ + model.setValue("yem_customeraddr", associatedaddress.get("detailaddress"), row);//地址(客户)--详细地址 + } + } + } + } + + @Override + public void click(EventObject evt) { + super.click(evt); + String key = ((Control) evt.getSource()).getKey(); + switch (key) { + case "btnok"://确定按钮 + this.btnOk();//点击确定按钮返回数据 + break; + } + } + + /** + * @Description: 点击确定给父页面返回信息 + * @function 功能 + * @purposes 用途 + * @return void + */ + public void btnOk() { + IFormView view = this.getView(); + IDataModel model = this.getModel(); + int selectRows = ((EntryGrid) view.getControl("yem_entryentity")).getEntryState().getFocusRow();//获取选中行的行数 + DynamicObject row = model.getEntryRowEntity("yem_entryentity", selectRows);//获取选中行的数据 + view.returnDataToParent(row); + view.close(); + } + + @Override + public void registerListener(EventObject e) { + super.registerListener(e); + this.addClickListeners("btnok"); + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/qrcode/form/QRCodeFormPlugin.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/qrcode/form/QRCodeFormPlugin.java new file mode 100644 index 0000000..8692780 --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/qrcode/form/QRCodeFormPlugin.java @@ -0,0 +1,31 @@ +package yem.wm.bd.qrcode.form; + +import kd.bos.bill.AbstractBillPlugIn; +import kd.bos.form.control.Control; + +import java.util.EventObject; + +/** + * @Description + * @Author: zhangh + * @CreateTime: 2025-02-15 15:43 + */ +public class QRCodeFormPlugin extends AbstractBillPlugIn { + @Override + public void registerListener(EventObject e) { + this.addClickListeners(new String[]{"yem_field"}); + } + + @Override + public void click(EventObject e) { + String key = ((Control) e.getSource()).getKey(); + switch (key) { + case "yem_field": + showFiled(); + break; + } + } + + public void showFiled() { + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/supplierbankinfor/dynamic/SupBankDynamicPlugin.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/supplierbankinfor/dynamic/SupBankDynamicPlugin.java new file mode 100644 index 0000000..f264ab9 --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/supplierbankinfor/dynamic/SupBankDynamicPlugin.java @@ -0,0 +1,76 @@ +package yem.wm.bd.supplierbankinfor.dynamic; + +import kd.bos.bill.AbstractBillPlugIn; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.entity.datamodel.IDataModel; +import kd.bos.form.IFormView; +import kd.bos.form.control.Control; +import kd.bos.form.control.EntryGrid; +import kd.bos.servicehelper.BusinessDataServiceHelper; + +import java.util.EventObject; + +/** + * @Description 供应商银行信息-表单插件 + * 1、加载界面时,默认获取《供应商》中的{银行信息}自动给单据体赋值 + * 2、选中行数据之后,点击确定给父页面返回数据 + * @Author: zhangh + * @CreateTime: 2025-02-08 16:52 + */ +public class SupBankDynamicPlugin extends AbstractBillPlugIn { + + @Override + public void afterCreateNewData(EventObject e) { + IFormView view = this.getView(); + IDataModel model = view.getModel(); + + IFormView parentView = view.getParentView(); + IDataModel parentModel = parentView.getModel(); + + DynamicObject supplier = (DynamicObject) parentModel.getValue("yem_supplier");//获取父页面的【供应商】字段 + if (supplier != null) { + supplier = BusinessDataServiceHelper.loadSingleFromCache(supplier.getLong("id"), supplier.getDataEntityType().getName()); + + DynamicObjectCollection banksentry = supplier.getDynamicObjectCollection("entry_bank");//获取《供应商》中的{银行信息} + for (DynamicObject bank : banksentry) { + int row = model.createNewEntryRow("yem_entryentity");//动态表单单据体添加行数 + model.setValue("yem_accountnumber", bank.get("bankaccount"), row);//银行账号 + model.setValue("yem_accountname", bank.get("accountname"), row);//账户名称 + model.setValue("yem_bankaccount", bank.get("bank"), row);//开户银行 + } + } + } + + @Override + public void click(EventObject evt) { + super.click(evt); + String key = ((Control) evt.getSource()).getKey(); + switch (key) { + case "btnok"://确定按钮 + this.btnOk();//点击确定按钮返回数据 + break; + } + } + + /** + * @Description: 点击确定给父页面返回信息 + * @function 功能 + * @purposes 用途 + * @return void + */ + private void btnOk() { + IFormView view = this.getView(); + IDataModel model = this.getModel(); + int selectRows = ((EntryGrid) view.getControl("yem_entryentity")).getEntryState().getFocusRow();//获取选中行的行数 + DynamicObject row = model.getEntryRowEntity("yem_entryentity", selectRows);//获取选中行的数据 + view.returnDataToParent(row); + view.close(); + } + + @Override + public void registerListener(EventObject e) { + super.registerListener(e); + this.addClickListeners("btnok"); + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/suppliermaninfor/dynamic/SupManDynamicPlugin.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/suppliermaninfor/dynamic/SupManDynamicPlugin.java new file mode 100644 index 0000000..1e393f1 --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/suppliermaninfor/dynamic/SupManDynamicPlugin.java @@ -0,0 +1,84 @@ +package yem.wm.bd.suppliermaninfor.dynamic; + +import kd.bos.bill.AbstractBillPlugIn; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.entity.datamodel.IDataModel; +import kd.bos.form.IFormView; +import kd.bos.form.control.Control; +import kd.bos.form.control.EntryGrid; +import kd.bos.servicehelper.BusinessDataServiceHelper; + +import java.util.EventObject; + +/** + * @Description 供应商人员信息-表单插件 + * 1、加载界面时,默认获取《供应商》中的{人员信息}以及{人员信息}中【关联地址】属性【详细地址】、【微信】、【QQ】自动给单据体赋值 + * 2、选中行数据之后,点击确定给父页面返回数据 + * @Author: zhangh + * @CreateTime: 2025-02-08 16:57 + */ +public class SupManDynamicPlugin extends AbstractBillPlugIn { + @Override + public void afterCreateNewData(EventObject e) { + IFormView view = this.getView(); + IDataModel model = view.getModel(); + + IFormView parentView = view.getParentView(); + IDataModel parentModel = parentView.getModel(); + + DynamicObject supplier = (DynamicObject) parentModel.getValue("yem_supplier");//获取父页面的【供应商】字段 + if (supplier != null) { + supplier = BusinessDataServiceHelper.loadSingleFromCache(supplier.getLong("id"), supplier.getDataEntityType().getName()); + + DynamicObjectCollection linkmanentry = supplier.getDynamicObjectCollection("entry_linkman");//获取《供应商》中的{联系人信息} + for (DynamicObject linkman : linkmanentry) { + int row = model.createNewEntryRow("yem_entryentity");//动态表单单据体添加行数 + model.setValue("yem_supplieruser", linkman.get("contactperson"), row);//人员 + model.setValue("yem_suppliertel", linkman.get("phone"), row);//电话 + model.setValue("yem_supplieremail", linkman.get("email"), row);//E-Mail + model.setValue("yem_supplierfax", linkman.get("fax"), row);//传真 + + DynamicObject associatedaddress = linkman.getDynamicObject("associatedaddress");//关联地址 + if (associatedaddress != null) { + associatedaddress = BusinessDataServiceHelper.loadSingleFromCache(associatedaddress.getLong("id"), associatedaddress.getDataEntityType().getName()); + model.setValue("yem_suppliervx", associatedaddress.get("yem_suppliervx"), row);//微信(公司)--微信 + model.setValue("yem_supplierqq", associatedaddress.get("yem_supplierqq"), row);//QQ(公司)--QQ + model.setValue("yem_supplieraddr", associatedaddress.get("detailaddress"), row);//地址(客户)--详细地址 + } + } + } + } + + @Override + public void click(EventObject evt) { + super.click(evt); + String key = ((Control) evt.getSource()).getKey(); + switch (key) { + case "btnok"://确定按钮 + this.btnOk();//点击确定按钮返回数据 + break; + } + } + + /** + * @Description: 点击确定给父页面返回信息 + * @function 功能 + * @purposes 用途 + * @return void + */ + public void btnOk() { + IFormView view = this.getView(); + IDataModel model = this.getModel(); + int selectRows = ((EntryGrid) view.getControl("yem_entryentity")).getEntryState().getFocusRow();//获取选中行的行数 + DynamicObject row = model.getEntryRowEntity("yem_entryentity", selectRows);//获取选中行的数据 + view.returnDataToParent(row); + view.close(); + } + + @Override + public void registerListener(EventObject e) { + super.registerListener(e); + this.addClickListeners("btnok"); + } +} diff --git a/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/util/BothCardHelper.java b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/util/BothCardHelper.java new file mode 100644 index 0000000..bba7b43 --- /dev/null +++ b/yem-wm/yem-wm-bd/src/main/java/yem/wm/bd/util/BothCardHelper.java @@ -0,0 +1,464 @@ +package yem.wm.bd.util; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import kd.bos.bill.AbstractBillPlugIn; +import kd.bos.bill.OperationStatus; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.dataentity.metadata.IDataEntityProperty; +import kd.bos.dataentity.metadata.clr.DataEntityPropertyCollection; +import kd.bos.dataentity.serialization.SerializationUtils; +import kd.bos.entity.datamodel.IDataModel; +import kd.bos.form.CloseCallBack; +import kd.bos.form.FormShowParameter; +import kd.bos.form.IFormView; +import kd.bos.form.ShowType; +import kd.bos.form.control.Label; +import kd.bos.form.plugin.AbstractFormPlugin; +import kd.bos.orm.query.QCP; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import kd.bos.servicehelper.parameter.SystemParamServiceHelper; +import yem.base.common.utils.DynamicObjectUtil; +import yem.base.common.utils.YEM; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @Description 抬头信息帮助类 + * @Author: zhangh + * @CreateTime: 2025-02-07 18:32 + */ +public class BothCardHelper { + + private static final String ADD_CO = "yem_flex_addco"; + private static final String INFO_CO = "yem_flex_coinfo"; + private static final String ADD_GYS = "yem_flex_addgys"; + private static final String INFO_GYS = "yem_flex_gysinfo1"; + private static final String ADD_KH = "yem_flex_addbuyer"; + private static final String INFO_KH = "yem_flex_buyerinfo1"; + + /** + * @param form 基类类名 + * @param formId 跳转动态表单的标识 + * @Description: 跳转动态表单(无参数 , 没有给子页面传递任何参数) + * @function + * @purposes 多处调用,防止代码的重复型 + */ + public static void showChangePage(AbstractBillPlugIn form, String formId) { + IFormView view = form.getView();//获取单据的view视图 + FormShowParameter parameter = new FormShowParameter(); + parameter.getOpenStyle().setShowType(ShowType.Modal);//界面显示分格为弹窗,模态显示 + parameter.setFormId(formId);//添加跳转的动态表单标识 + parameter.setStatus(OperationStatus.ADDNEW);//打开表单的界面状态为新增 + parameter.setCloseCallBack(new CloseCallBack(form, formId));//回调 + view.showForm(parameter); + } + + /** + * @param form 基类名称(AbstractBillPlugIn) + * @Description: 公司抬头信息标签赋值 + * @function 根据{抬头信息}隐藏字段给标签赋值 + * @purposes 套打等可以使用 + */ + public static void setCoLabel(AbstractBillPlugIn form) { + IDataModel model = form.getView().getModel();//获取单据的model + DynamicObject company = (DynamicObject) model.getValue("yem_org");//获取单据{抬头明细(隐藏)}中的【公司抬头】 + if (YEM.isEmpty(company)) { + form.getView().setVisible(Boolean.TRUE, ADD_CO);//判断公司为空,显示添加公司的图标 + form.getView().setVisible(Boolean.FALSE, INFO_CO);//判断公司为空,隐藏编辑公司的图标 + } else { + ((Label) form.getControl("yem_conamelabel")).setText((String) model.getValue("yem_companyname"));//公司名称 + ((Label) form.getControl("yem_cotin")).setText((String) model.getValue("yem_companytin"));//纳税人识别号(公司) + ((Label) form.getControl("yem_cobank")).setText((String) model.getValue("yem_companybank"));//开户行(公司) + ((Label) form.getControl("yem_coacct")).setText((String) model.getValue("yem_companyacct"));//账号(公司) + ((Label) form.getControl("yem_coaddr")).setText((String) model.getValue("yem_companyaddr"));//地址(公司) + + String isdefaultinfor = (String) model.getValue("yem_isdefaultinfor");//获取默认信息(公司) + JSONObject jsonObject = JSON.parseObject(isdefaultinfor);//将String类型转换成JSONObject + + String colinkman = (String) (YEM.isEmpty(isdefaultinfor) ? model.getValue("yem_companylinkman") : jsonObject.get("yem_companylinkman"));//联系人 + ((Label) form.getControl("yem_colinkman")).setText(colinkman);//联系人(公司) + + String cotel = (String) (YEM.isEmpty(isdefaultinfor) ? model.getValue("yem_companytel") : jsonObject.get("yem_companytel"));//电话 + ((Label) form.getControl("yem_cotel")).setText(cotel);//电话(公司) + + String coemail = (String) (YEM.isEmpty(isdefaultinfor) ? model.getValue("yem_companyemail") : jsonObject.get("yem_companyemail"));//E-Mail + ((Label) form.getControl("yem_coemail")).setText(coemail);//E-Mail(公司) + + String covx = (String) (YEM.isEmpty(isdefaultinfor) ? model.getValue("yem_companyvx") : jsonObject.get("yem_companyvx"));//微信 + ((Label) form.getControl("yem_covx")).setText(covx);//微信(公司) + + String coqq = (String) (YEM.isEmpty(isdefaultinfor) ? model.getValue("yem_companyqq") : jsonObject.get("yem_companyqq"));//QQ + ((Label) form.getControl("yem_coqq")).setText(coqq);//QQ(公司) + + String cofax = (String) (YEM.isEmpty(isdefaultinfor) ? model.getValue("yem_companyfax") : jsonObject.get("yem_companyfax"));//传真 + ((Label) form.getControl("yem_cofax")).setText(cofax);//传真(公司) + form.getView().setVisible(Boolean.FALSE, ADD_CO);//判断公司不为空,隐藏添加公司的图标 + form.getView().setVisible(Boolean.TRUE, INFO_CO);//判断公司不为空,显示编辑公司的图标 + } + } + + /** + * @param form 基类名称 + * @Description: 供应商抬头信息标签赋值 + * @function 根据{抬头信息}隐藏字段给标签赋值 + * @purposes 套打等可以使用 + */ + public static void setSupplierLabel(AbstractBillPlugIn form) { + IDataModel model = form.getView().getModel();//获取view中的model + DynamicObject supplier = (DynamicObject) model.getValue("yem_supplier");//获取单据{抬头明细(隐藏)}中的【供应商】 + if (YEM.isEmpty(supplier)) { + form.getView().setVisible(Boolean.TRUE, ADD_GYS);//判断供应商为空,显示供应商添加的图标 + form.getView().setVisible(Boolean.FALSE, INFO_GYS);//判断供应商为空,隐藏供应商编辑的图标 + } else { + ((Label) form.getControl("yem_gysname")).setText((String) model.getValue("yem_suppliername"));//供应商名称 + ((Label) form.getControl("yem_gystin")).setText((String) model.getValue("yem_suppliertin"));//纳税人识别号(供应商) + ((Label) form.getControl("yem_gysbank")).setText((String) model.getValue("yem_supplierbank"));//开户行(供应商) + ((Label) form.getControl("yem_gysacct")).setText((String) model.getValue("yem_supplieracct"));//账号(供应商) + ((Label) form.getControl("yem_gyslinkman")).setText((String) model.getValue("yem_supplierlinkman"));//联系人(供应商) + ((Label) form.getControl("yem_gystel")).setText((String) model.getValue("yem_suppliertel"));//电话(供应商) + ((Label) form.getControl("yem_gysaddr")).setText((String) model.getValue("yem_supplieraddr"));//地址(供应商) + ((Label) form.getControl("yem_gysemail")).setText((String) model.getValue("yem_supplieremail"));//E-Mail(供应商) + ((Label) form.getControl("yem_gysvx")).setText((String) model.getValue("yem_suppliervx"));//微信(供应商) + ((Label) form.getControl("yem_gysqq")).setText((String) model.getValue("yem_supplierqq"));//QQ(供应商) + ((Label) form.getControl("yem_gysfax")).setText((String) model.getValue("yem_supplierfax"));//传真(供应商) + form.getView().setVisible(Boolean.FALSE, ADD_GYS);//判断供应商不为空,隐藏供应商添加的图标 + form.getView().setVisible(Boolean.TRUE, INFO_GYS);//判断供应商不为空,显示供应商编辑的图标 + } + } + + /** + * @param form 基类名称 + * @Description: 客户抬头信息标签赋值 + * @function 根据{抬头信息}隐藏字段给标签赋值 + * @purposes 套打等可以使用 + */ + public static void setCustomerLabel(AbstractBillPlugIn form) { + IDataModel model = form.getView().getModel();//获取view中的model + DynamicObject customer = (DynamicObject) model.getValue("yem_customer");//获取单据{抬头明细(隐藏)}中的【客户】 + if (YEM.isEmpty(customer)) { + form.getView().setVisible(Boolean.TRUE, ADD_KH);//判断客户为空,显示客户添加的图标 + form.getView().setVisible(Boolean.FALSE, INFO_KH);//判断客户为空,隐藏客户编辑的图标 + } else { + ((Label) form.getControl("yem_payername")).setText((String) model.getValue("yem_customername"));//客户名称 + ((Label) form.getControl("yem_payertin")).setText((String) model.getValue("yem_customertin"));//纳税人识别号(客户) + ((Label) form.getControl("yem_payerbank")).setText((String) model.getValue("yem_customerbank"));//开户行(客户) + ((Label) form.getControl("yem_payeracct")).setText((String) model.getValue("yem_customeracct"));//账号(客户) + ((Label) form.getControl("yem_payerlinkman")).setText((String) model.getValue("yem_customerlinkman"));//联系人(客户) + ((Label) form.getControl("yem_payertel")).setText((String) model.getValue("yem_customertel"));//电话(客户) + ((Label) form.getControl("yem_payeraddr")).setText((String) model.getValue("yem_customeraddr"));//地址(客户) + ((Label) form.getControl("yem_payeremail")).setText((String) model.getValue("yem_customeremail"));//E-Mail(客户) + ((Label) form.getControl("yem_payervx")).setText((String) model.getValue("yem_customervx"));//微信(客户) + ((Label) form.getControl("yem_payerqq")).setText((String) model.getValue("yem_customerqq"));//QQ(客户) + ((Label) form.getControl("yem_payerfax")).setText((String) model.getValue("yem_customerfax"));//传真(客户) + form.getView().setVisible(Boolean.FALSE, ADD_KH);//判断客户不为空,隐藏客户添加的图标 + form.getView().setVisible(Boolean.TRUE, INFO_KH);//判断客户不为空,显示客户编辑的图标 + } + } + + /** + * @Description: 公司抬头信息实体赋值 + * @function 新增单据时,默认给{公司抬头}赋值 + * @purposes 用途 + */ + public static void fillCoInfo(IDataModel model, DynamicObject org) { + boolean viewBill = SystemParamServiceHelper.isViewBill("");//获取系统参数,后边进行调整 + String orgKey = viewBill ? "yem_bd_companyinfo" : "bos_org";//根据系统参数获取系统是使用《业务单元》还是《公司抬头》 + model.setValue("yem_orgtype", orgKey); //组织类型 + model.setValue("yem_org", org.getLong("id"));//公司抬头 + model.setValue("yem_companyname", org.getString("name"));//公司名称 + + DynamicObject companyinfo = queryCompany(org);//根据《业务单元》查询《公司抬头》 + if (companyinfo != null) {//判断《公司抬头》实体是否为空 + model.setValue("yem_companytin", companyinfo.get("yem_negocionum"));//纳税人识别号(公司)--纳税识别号 + model.setValue("yem_companyaddr", companyinfo.getString("yem_addresscn"));//地址(公司)--地址 + model.setValue("yem_companyfax", companyinfo.getString("yem_fax"));//传真(公司)--传真 + + DynamicObjectCollection banksentry = companyinfo.getDynamicObjectCollection("yem_banksentry");//《公司抬头》中的{银行信息} + List banksentryDefault = banksentry.stream().filter(x -> x.getBoolean("yem_isdefaultbank") == true).collect(Collectors.toList());//获取《公司抬头》中{银行信息}中的默认数据 + if (banksentryDefault.size() > 0) { + DynamicObject row = banksentryDefault.get(0);//《公司抬头》中的{银行信息}默认数据只有唯一一个 + String bankaccount = row.getDynamicObject("yem_bankaccount") != null ? row.getDynamicObject("yem_bankaccount").getString("name") : "";//获取开户银行 + model.setValue("yem_companybank", bankaccount);//开户行(公司)--开户银行 + model.setValue("yem_companyacct", row.get("yem_accountnumber"));//账号(公司)--银行账户 + } + + DynamicObjectCollection linkmanentry = companyinfo.getDynamicObjectCollection("yem_linkmanentry");//《公司抬头》中的{联系人信息} + List manentryDefault = linkmanentry.stream().filter(x -> x.getBoolean("yem_isdefaultlinkman") == true).collect(Collectors.toList());//获取《公司抬头》中{联系人信息}中的默认数据 + if (manentryDefault.size() > 0) { + DynamicObject row = manentryDefault.get(0);//《公司抬头》中的{联系人信息}默认数据只有唯一一个 + model.setValue("yem_companylinkman", row.getString("yem_contactperson"));//联系人(公司)--名称 + model.setValue("yem_companytel", row.get("yem_phonenum"));//电话(公司)--联系电话 + model.setValue("yem_companyemail", row.get("yem_addemail"));//E-Mail(公司)--电子邮箱 + model.setValue("yem_companyvx", row.get("yem_suppliervx"));//微信(公司)--微信 + model.setValue("yem_companyqq", row.get("yem_supplierqq"));//QQ(公司)--QQ + } + } + } + + /** + * @param org 《业务单元》实体 + * @return DynamicObject 返回的是《公司抬头》实体 + * @Description: 查询单据 + * @function 根据业务单元查询获取《公司抬头》 + * @purposes + */ + public static DynamicObject queryCompany(DynamicObject org) { + String selectfields = DynamicObjectUtil.getSelectfields("yem_bd_companyinfo", false);//获取《公司抬头》表头字段标识 + selectfields = DynamicObjectUtil.getEntrySelectfields(selectfields, "yem_bd_companyinfo", "yem_banksentry", false);//获取《公司抬头》中{银行信息}分录所有字段标识 + selectfields = DynamicObjectUtil.getEntrySelectfields(selectfields, "yem_bd_companyinfo", "yem_linkmanentry", false);//获取《公司抬头》中{联系人信息}分录所有字段标识 + DynamicObject companyinfo = BusinessDataServiceHelper.loadSingle("yem_bd_companyinfo", selectfields, new QFilter[]{new QFilter("yem_org", QCP.equals, org.getLong("id"))});//根据公司条件查询《公司抬头》 + return companyinfo; + } + + /** + * @param form 基类类名 + * @Description: 加载动态表单的逻辑处理 + * @function 将父页面的信息携带到动态表单上 + * @purposes + */ + public static void init(AbstractFormPlugin form) { + IFormView view = form.getView();//获取动态表单的view视图 + IDataModel model = view.getModel();//获取动态表单的模型model + + IFormView parentView = view.getParentView();//获取父页面的view视图 + IDataModel parentModel = parentView.getModel();//获取父页面的模型model + + DataEntityPropertyCollection properties = model.getDataEntityType().getProperties();//获取动态表单上的所有字段控件 + for (IDataEntityProperty property : properties) { + String propName = property.getName();//获取字段控件的标识 + if (parentModel.getProperty(propName) != null) {//判断该字段标识在父页面中是否存在 + Object propValue = parentModel.getValue(propName);//如果存在获取在父页面中的值 + if (propValue instanceof DynamicObject) {//类型是实体 + DynamicObject obj = (DynamicObject) propValue;//获取实体id + model.setValue(propName, obj.getPkValue()); + } else { + model.setValue(propName, propValue); + } + } + } + } + + /** + * @Description: 回填银行信息 + * @function :《公司银行信息》点击确定之后,回填公司银行信息 + * @purposes 用途 + */ + public static void setCompanyBankInfor(AbstractFormPlugin form, Object returnData) { + DynamicObject data = (DynamicObject) returnData; + IFormView view = form.getView(); + IDataModel model = view.getModel(); + + if (data != null) { + DynamicObject bankaccount = data.getDynamicObject("yem_bankaccount"); + String bank = bankaccount != null ? bankaccount.getString("name") : ""; + model.setValue("yem_companybank", bank);//开户行 + model.setValue("yem_companyacct", data.getString("yem_accountnumber"));//账号 + } + } + + /** + * @Description: 回填联系人信息 + * @function :《公司人员信息》点击确定之后,回填公司联系人信息 + * @purposes 用途 + */ + public static void setCompanyManInfor(AbstractFormPlugin form, Object returnData, DynamicObject isdefaultInfor) { + List data = (List) returnData; + IFormView view = form.getView(); + IDataModel model = view.getModel(); + + if (data != null && data.size() > 0) { + DataEntityPropertyCollection properties = data.get(0).getDataEntityType().getProperties();//获取{联系人信息}单据体的所有字段 + + for (IDataEntityProperty property : properties) {//适用于实体字段给单据的表头字段赋值 + String name = property.getName();//获取实体字段的标识 + if (model.getProperty(name) != null) { + List linkman = data.stream().map(x -> x.getString(name)).collect(Collectors.toList()); + model.setValue(name, String.join(";", linkman)); + } + } + + List defaultManInfor = data.stream().filter(x -> x.getBoolean("yem_default") == true).collect(Collectors.toList());//获取《公司联系人信息》回填的默认信息 + if (defaultManInfor.size() > 0) { + view.getPageCache().put("data", SerializationUtils.toJsonString(defaultManInfor.get(0)));//将默认信息放在缓存李,在回传的时候可以使用 + } + } + } + + /** + * @Description: 切换【客户】,客户信息值改变 + * @function 切换【客户】之后,客户信息根据赋值逻辑重新赋值 + * @purposes 用途 + */ + public static void setCustomerInfor(AbstractFormPlugin form) { + IFormView view = form.getView(); + IDataModel model = view.getModel(); + + DynamicObject customer = (DynamicObject) model.getValue("yem_customer"); + if (customer != null) { + customer = BusinessDataServiceHelper.loadSingleFromCache(customer.getLong("id"), customer.getDataEntityType().getName()); + + model.setValue("yem_customertin", customer.getString("societycreditcode"));//纳税人识别号(供应商)--纳税人识别号(供应商) + + DynamicObjectCollection entry_bank = customer.getDynamicObjectCollection("entry_bank");//银行信息 + List bankentryDefault = entry_bank.stream().filter(x -> x.getBoolean("isdefault_bank") == true).collect(Collectors.toList()); + if (bankentryDefault.size() > 0) { + DynamicObject row = bankentryDefault.get(0); + String bank = row.getDynamicObject("bank") != null ? row.getDynamicObject("bank").getString("name") : ""; + model.setValue("yem_customerbank", bank);//开户行(公司)--开户银行 + model.setValue("yem_customeracct", row.get("bankaccount"));//账号(公司)--银行账户 + } + + DynamicObjectCollection linkmanentry = customer.getDynamicObjectCollection("entry_linkman");//联系人信息 + List manentryDefault = linkmanentry.stream().filter(x -> x.getBoolean("isdefault_linkman") == true).collect(Collectors.toList()); + + if (manentryDefault.size() > 0) { + DynamicObject row = manentryDefault.get(0); + model.setValue("yem_customerlinkman", row.getString("contactperson"));//联系人(公司)--名称 + model.setValue("yem_customertel", row.get("phone"));//电话(公司)--联系电话 + model.setValue("yem_customeremail", row.get("email"));//E-Mail(公司)--电子邮箱 + model.setValue("yem_customerfax", row.get("fax"));//传真(公司)--传真 + + DynamicObject associatedaddress = row.getDynamicObject("associatedaddress");//关联地址 + if (associatedaddress != null) { + associatedaddress = BusinessDataServiceHelper.loadSingleFromCache(associatedaddress.getLong("id"), associatedaddress.getDataEntityType().getName()); + model.setValue("yem_customervx", associatedaddress.get("yem_suppliervx"));//微信(公司)--微信 + model.setValue("yem_customerqq", associatedaddress.get("yem_supplierqq"));//QQ(公司)--QQ + model.setValue("yem_customeraddr", associatedaddress.get("detailaddress"));//地址(客户)--详细地址 + } + } + } + } + + /** + * @Description: 《客户银行信息》点击确定,返回值 + * @function 《客户银行信息》点击确定之后,给《添加客户》中的信息赋值 + * @purposes 用途 + */ + public static void setCustBankInfor(AbstractBillPlugIn form, Object returnData) { + DynamicObject data = (DynamicObject) returnData; + IFormView view = form.getView(); + IDataModel model = view.getModel(); + + if (data != null) { + DynamicObject bankaccount = data.getDynamicObject("yem_bankaccount");//获取《客户银行信息》中的【开户行】 + String bank = bankaccount != null ? bankaccount.getString("name") : ""; + model.setValue("yem_customerbank", bank);//开户行 + model.setValue("yem_customeracct", data.getString("yem_accountnumber"));//账号 + } + } + + /** + * @Description: 《客户人员信息》点击确定,返回值 + * @function 《客户人员信息》点击确定之后,给《添加客户》中的信息赋值 + * @purposes 用途 + */ + public static void setCustManInfor(AbstractBillPlugIn form, Object returnData) { + DynamicObject data = (DynamicObject) returnData; + IFormView view = form.getView(); + IDataModel model = view.getModel(); + + if (data != null) { + DataEntityPropertyCollection properties = data.getDataEntityType().getProperties();//获取返回信息的所有字段标识(只有表头字段,没有单据体字段) + for (IDataEntityProperty property : properties) { + String name = property.getName();//获取字段标识 + if (model.getProperty(name) != null) { + model.setValue(name, data.get(name));//进行赋值 + } + } + } + } + + /** + * @Description: 切换【供应商】,重新赋值 + * @function 切换【供应商】之后,根据赋值逻辑,重新赋值 + * @purposes 用途 + */ + public static void setSupplierInfor(AbstractFormPlugin form) { + IFormView view = form.getView(); + IDataModel model = view.getModel(); + + DynamicObject supplier = (DynamicObject) model.getValue("yem_supplier");//获取【供应商】字段 + if (supplier != null) { + supplier = BusinessDataServiceHelper.loadSingleFromCache(supplier.getLong("id"), supplier.getDataEntityType().getName()); + + model.setValue("yem_suppliertin", supplier.getString("societycreditcode"));//纳税人识别号(供应商)--纳税人识别号(供应商) + + DynamicObjectCollection entry_bank = supplier.getDynamicObjectCollection("entry_bank");//《供应商》--{银行信息} + List bankentryDefault = entry_bank.stream().filter(x -> x.getBoolean("isdefault_bank") == true).collect(Collectors.toList());//获取《供应商》中{银行信息}的默认数据 + if (bankentryDefault.size() > 0) { + DynamicObject row = bankentryDefault.get(0); + String bank = row.getDynamicObject("bank") != null ? row.getDynamicObject("bank").getString("name") : "";//开户行 + model.setValue("yem_supplierbank", bank);//开户行(公司)--开户银行 + model.setValue("yem_supplieracct", row.get("bankaccount"));//账号(公司)--银行账户 + } + + DynamicObjectCollection linkmanentry = supplier.getDynamicObjectCollection("entry_linkman");//《供应商》--联系人信息 + List manentryDefault = linkmanentry.stream().filter(x -> x.getBoolean("isdefault_linkman") == true).collect(Collectors.toList());//获取《供应商》中{联系人信息}的默认数据 + + if (manentryDefault.size() > 0) { + DynamicObject row = manentryDefault.get(0); + model.setValue("yem_supplierlinkman", row.getString("contactperson"));//联系人(公司)--名称 + model.setValue("yem_suppliertel", row.get("phone"));//电话(公司)--联系电话 + model.setValue("yem_supplieremail", row.get("email"));//E-Mail(公司)--电子邮箱 + model.setValue("yem_supplierfax", row.get("fax"));//传真(公司)--传真 + + DynamicObject associatedaddress = row.getDynamicObject("associatedaddress");//关联地址 + if (associatedaddress != null) { + associatedaddress = BusinessDataServiceHelper.loadSingleFromCache(associatedaddress.getLong("id"), associatedaddress.getDataEntityType().getName()); + model.setValue("yem_suppliervx", associatedaddress.get("yem_suppliervx"));//微信(公司)--微信 + model.setValue("yem_supplierqq", associatedaddress.get("yem_supplierqq"));//QQ(公司)--QQ + model.setValue("yem_supplieraddr", associatedaddress.get("detailaddress"));//地址(客户)--详细地址 + } + } + } + } + + /** + * @Description: 《供应商银行信息》点击确定,返回值 + * @function 《供应商银行信息》点击确定之后,给《添加客户》中的信息赋值 + * @purposes 用途 + */ + public static void setSuppBankInfor(AbstractBillPlugIn form, Object returnData) { + DynamicObject data = (DynamicObject) returnData; + IFormView view = form.getView(); + IDataModel model = view.getModel(); + + if (data != null) { + DynamicObject bankaccount = data.getDynamicObject("yem_bankaccount"); + String bank = bankaccount != null ? bankaccount.getString("name") : ""; + model.setValue("yem_supplierbank", bank);//开户行 + model.setValue("yem_supplieracct", data.getString("yem_accountnumber"));//账号 + } + } + + /** + * @param form 基类类名 + * @return void + * @Description: 将动态表单的信息返回给父页面 + * @function + * @purposes 用途 + */ + public static void btnOkParent(AbstractFormPlugin form) { + IFormView view = form.getView();//获取动态表单view视图 + IDataModel model = view.getModel();//获取动态表单模型model + IFormView parentView = view.getParentView();//获取父页面view视图 + IDataModel parentModel = parentView.getModel();//获取父页面莫得了模型 + DataEntityPropertyCollection properties = model.getDataEntityType().getProperties();//获取动态表单所有字段控件 + for (IDataEntityProperty property : properties) { + String propName = property.getName();//获取字段标识 + if (parentModel.getProperty(propName) != null) { + Object propValue = model.getValue(propName);//子啊动态表单上获取字段的值 + if (propValue instanceof DynamicObject) {//判断值类型是否是DynamicObject实体 + DynamicObject obj = (DynamicObject) propValue; + parentModel.setValue(propName, obj.getPkValue()); + } else { + parentModel.setValue(propName, propValue); + } + } + } + } +}