瀏覽代碼

feat(mas): 新增企业负责人薪酬核定变更功能

- 新增企业负责人个人年度薪酬标准核定表及变更单实体常量定义
- 实现企业负责人个人年度薪酬标准核定表变更单表单插件逻辑
- 完善企业负责人个人年度薪酬标准核定表操作插件的回写功能
- 优化子企业负责人薪酬核定标准回写操作插件代码结构
- 统一使用常量替代硬编码字符串提升代码可维护性
- 增加变更单生成前的状态校验防止重复申请
- 引入单元格样式标记功能突出显示变更字段
- 完善附件复制与数据同步逻辑确保变更单完整性
- 添加操作成功后的确认框引导用户进入变更单界面
wyc 2 周之前
父節點
當前提交
0ad2c2705e

+ 10 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/common/MasConstant.java

@@ -192,5 +192,15 @@ public class MasConstant extends FormConstant {
     public static final String SUBCPCHFSALSTDCHG_ENTITYID = "nckd_subcpchfsalstdchg";
     /*-------------------------------------- 子企业负责人正职年度薪酬核定标准_变更单 end --------------------------------------*/
 
+    /*-------------------------------------- 子企业负责人正职年度薪酬核定标准_变更单 begin --------------------------------------*/
+    /** 企业负责人个人年度薪酬标准核定表_变更单-实体标识 */
+    public static final String ENTLDRANLSALSTDCHG_ENTITYID = "nckd_entldranlsalstdchg";
+    /*-------------------------------------- 子企业负责人正职年度薪酬核定标准_变更单 end --------------------------------------*/
+
+    /*-------------------------------------- 企业负责人个人年度薪酬标准核定表 begin --------------------------------------*/
+    /** 企业负责人个人年度薪酬标准核定表-实体标识 */
+    public static final String ENTLEADERANLSALSTD_ENTITYID = "nckd_entleaderanlsalstd";
+    /*-------------------------------------- 企业负责人个人年度薪酬标准核定表 end --------------------------------------*/
+
 
 }

+ 117 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/structappr/EntleaderAnlSalStdFormPlugin.java

@@ -1,21 +1,46 @@
 package nckd.jxccl.swc.mas.plugin.form.structappr;
 
+import kd.bos.bill.BillShowParameter;
+import kd.bos.dataentity.OperateOption;
 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.entity.constant.StatusEnum;
 import kd.bos.entity.datamodel.events.AfterAddRowEventArgs;
 import kd.bos.entity.datamodel.events.ChangeData;
 import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.entity.validate.BillStatus;
+import kd.bos.form.ConfirmCallBackListener;
+import kd.bos.form.ConfirmTypes;
+import kd.bos.form.IFormView;
+import kd.bos.form.IPageCache;
+import kd.bos.form.MessageBoxOptions;
+import kd.bos.form.MessageBoxResult;
+import kd.bos.form.ShowType;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+import kd.bos.form.events.MessageBoxClosedEvent;
 import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.mvc.SessionManager;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
+import kd.bos.servicehelper.AttachmentServiceHelper;
 import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.QueryServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.drp.mem.er.BillStatusEnum;
+import kd.hr.hbp.common.util.HRDynamicObjectUtils;
 import kd.sdk.plugin.Plugin;
 import nckd.jxccl.base.common.constant.FormConstant;
 import nckd.jxccl.base.common.enums.mas.ProjectCategoryEnum;
+import nckd.jxccl.base.common.exception.ValidationException;
 import nckd.jxccl.base.common.utils.ConvertUtil;
 import nckd.jxccl.base.common.utils.DateUtil;
 import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.base.common.utils.ShowOperExecuteResult;
+import nckd.jxccl.base.common.utils.StrFormatter;
+import nckd.jxccl.base.entity.helper.EntityHelper;
 import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
 import nckd.jxccl.swc.mas.common.MasConstant;
 
@@ -25,6 +50,7 @@ import java.time.LocalDateTime;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.EventObject;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -293,6 +319,97 @@ public class EntleaderAnlSalStdFormPlugin extends AbstractFormPlugin implements
         }
     }
 
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
+        if(afterDoOperationEventArgs.getOperationResult() != null && afterDoOperationEventArgs.getOperationResult().isSuccess()){
+            String operateKey = afterDoOperationEventArgs.getOperateKey();
+            if(operateKey.equalsIgnoreCase("change")){
+                DynamicObject data = this.getModel().getDataEntity();
+                //校验有没有暂存或进行中的审批单
+                QueryFieldBuilder queryFieldBuilder = QueryFieldBuilder.create()
+                        .add(FormConstant.BILL_NO_KEY);
+                QFilter filter = new QFilter(FormConstant.BILL_STATUS_KEY, QCP.not_equals, BillStatus.C.toString())
+                        .and(String.join(".", MasConstant.SUBCORPCHIEFSALSTD_ENTITYID,  FormConstant.ID_KEY), QCP.in, data.getLong(FormConstant.ID_KEY));
+                DynamicObjectCollection query = QueryServiceHelper.query(MasConstant.SUBCPCHFSALSTDCHG_ENTITYID, queryFieldBuilder.buildSelect(), new QFilter[]{filter});
+                if(!query.isEmpty()){
+                    String number = query.get(0).getString(FormConstant.BILL_NO_KEY);
+                    throw new ValidationException(StrFormatter.format("已存在暂存或进行中的变更单【单据号:{}】,请勿重复申请。", number));
+                }
+
+                DynamicObjectCollection entryColl = data.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
+                DynamicObject newSubcpChfSalStdChg = EntityHelper.newEntity(MasConstant.ENTLDRANLSALSTDCHG_ENTITYID);
+                HRDynamicObjectUtils.copy(data,newSubcpChfSalStdChg);
+                newSubcpChfSalStdChg.set(FormConstant.NCKD_DESCRIPTION,data.getString(FormConstant.DESCRIPTION_KEY));
+                newSubcpChfSalStdChg.set(MasConstant.ENTLEADERANLSALSTD_ENTITYID,data);
+                newSubcpChfSalStdChg.set(FormConstant.BILL_STATUS_KEY, BillStatusEnum.SAVED.getValue());
+                List<Map<String, Object>> attachments = AttachmentServiceHelper.getAttachments("nckd_subcorpchiefsalstd", data.getLong(FormConstant.ID_KEY), "nckd_attachmentpanelap");
+
+                //变更前
+                DynamicObjectCollection newEntryColl = newSubcpChfSalStdChg.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
+                DynamicObjectCollection newOldEntryColl = newSubcpChfSalStdChg.getDynamicObjectCollection("nckd_oldentryentity");
+                for (DynamicObject newEntry : newEntryColl) {
+                    //设置源id
+                    int seq = newEntry.getInt(FormConstant.SEQ_KEY);
+                    List<DynamicObject> filteredEntries = entryColl.stream().filter(entry -> entry.getInt(FormConstant.SEQ_KEY) == seq).collect(Collectors.toList());
+                    long originId = 0L;
+                    if(!filteredEntries.isEmpty()){
+                        originId = filteredEntries.get(0).getLong(FormConstant.ID_KEY);
+                    }
+                    newEntry.set("nckd_originid", originId);
+
+                    DynamicObject newOldEntry = newOldEntryColl.addNew();
+                    DataEntityPropertyCollection properties = newOldEntry.getDynamicObjectType().getProperties();
+                    for (IDataEntityProperty property : properties) {
+                        String oldName = property.getName();
+                        String name = oldName.replace("old","");
+                        newOldEntry.set(oldName, newEntry.get(name));
+                    }
+                    newOldEntry.set("nckd_originidold", originId);
+                }
+                OperationResult operationResult = SaveServiceHelper.saveOperate(MasConstant.ENTLDRANLSALSTDCHG_ENTITYID, new DynamicObject[]{newSubcpChfSalStdChg}, OperateOption.create());
+                if (!operationResult.isSuccess()) {
+                    String parentPageId = this.getView().getFormShowParameter().getPageId();
+                    IFormView parentView = SessionManager.getCurrent().getViewNoPlugin(parentPageId);
+                    IPageCache pageCache = (IPageCache) parentView.getService(IPageCache.class);
+                    Map<String, String> customData = operationResult.getCustomData();
+                    //成功的记录
+                    Map<Object, Object> successMap = new HashMap<>();
+                    for (Object successPkId : operationResult.getSuccessPkIds()) {
+                        successMap.put(successPkId, customData.get(successPkId.toString()));
+                    }
+                    this.getView().showForm(ShowOperExecuteResult.getOperResultForm("载入党政职务履历", successMap, pageCache, operationResult));
+                    this.getView().invokeOperation(FormConstant.REFRESH_OP);
+                } else {
+                    // 自定义确认框按钮名称
+                    Map<Integer, String> btnNameMaps = new HashMap<Integer, String>();
+                    btnNameMaps.put(2, "我知道了");
+                    btnNameMaps.put(6, "进入变更单");
+                    ConfirmCallBackListener confirmCallBackListener =
+                            new ConfirmCallBackListener("openchange", this);
+                    List<Object> successPkIds = operationResult.getSuccessPkIds();
+                    this.getPageCache().put("changeid", ConvertUtil.toStr(successPkIds.get(0)));
+                    this.getView().showConfirm("提示","发起暂存状态「变更单」成功,点击“进入变更单”按钮或在列表页面点击“查看变更单”即可进行数据变更并提交审批。", MessageBoxOptions.OKCancel, ConfirmTypes.Default, confirmCallBackListener,btnNameMaps);
+                }
+            }
+        }
+    }
+
+
+
+    @Override
+    public void confirmCallBack(MessageBoxClosedEvent messageBoxClosedEvent) {
+        if ("openchange".equals(messageBoxClosedEvent.getCallBackId())
+                && messageBoxClosedEvent.getResult() == MessageBoxResult.Yes) {
+            BillShowParameter billShowParameter = new BillShowParameter();
+            billShowParameter.setFormId(MasConstant.ENTLDRANLSALSTDCHG_ENTITYID);
+            billShowParameter.getOpenStyle().setShowType(ShowType.MainNewTabPage);
+            String id = this.getPageCache().get("changeid");
+            // 设置单据主键ID(关键步骤)
+            billShowParameter.setPkId(id);
+            this.getView().showForm(billShowParameter);
+        }
+    }
+
     /**
      * 设置支付N锁定或解锁
      * @param installmentYears 分期支付年

+ 9 - 18
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/structappr/SubcorpChiefSalStdFormPlugin.java

@@ -1,6 +1,5 @@
 package nckd.jxccl.swc.mas.plugin.form.structappr;
 
-import com.google.common.collect.Sets;
 import kd.bos.bill.BillShowParameter;
 import kd.bos.dataentity.OperateOption;
 import kd.bos.dataentity.entity.DynamicObject;
@@ -12,7 +11,6 @@ import kd.bos.entity.datamodel.events.AfterAddRowEventArgs;
 import kd.bos.entity.datamodel.events.ChangeData;
 import kd.bos.entity.datamodel.events.PropertyChangedArgs;
 import kd.bos.entity.operate.result.OperationResult;
-import kd.bos.entity.report.CellStyle;
 import kd.bos.entity.validate.BillStatus;
 import kd.bos.form.ConfirmCallBackListener;
 import kd.bos.form.ConfirmTypes;
@@ -21,7 +19,6 @@ import kd.bos.form.IPageCache;
 import kd.bos.form.MessageBoxOptions;
 import kd.bos.form.MessageBoxResult;
 import kd.bos.form.ShowType;
-import kd.bos.form.control.EntryGrid;
 import kd.bos.form.events.AfterDoOperationEventArgs;
 import kd.bos.form.events.MessageBoxClosedEvent;
 import kd.bos.form.plugin.AbstractFormPlugin;
@@ -50,7 +47,6 @@ import nckd.jxccl.swc.mas.common.MasConstant;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.time.LocalDateTime;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.EventObject;
@@ -353,7 +349,7 @@ public class SubcorpChiefSalStdFormPlugin extends AbstractFormPlugin implements
                 }
 
                 DynamicObjectCollection entryColl = data.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
-                DynamicObject newSubcpChfSalStdChg = EntityHelper.newEntity("nckd_subcpchfsalstdchg");
+                DynamicObject newSubcpChfSalStdChg = EntityHelper.newEntity(MasConstant.SUBCPCHFSALSTDCHG_ENTITYID);
                 HRDynamicObjectUtils.copy(data,newSubcpChfSalStdChg);
                 newSubcpChfSalStdChg.set(FormConstant.NCKD_DESCRIPTION,data.getString(FormConstant.DESCRIPTION_KEY));
                 newSubcpChfSalStdChg.set(MasConstant.SUBCORPCHIEFSALSTD_ENTITYID,data);
@@ -374,20 +370,15 @@ public class SubcorpChiefSalStdFormPlugin extends AbstractFormPlugin implements
                     newEntry.set("nckd_originid", originId);
 
                     DynamicObject newOldEntry = newOldEntryColl.addNew();
-                    newOldEntry.set(MasConstant.NCKD_PROJECTCATEGORY+"old", newEntry.getDynamicObject(MasConstant.NCKD_PROJECTCATEGORY));
-                    newOldEntry.set(MasConstant.NCKD_SALARYITEM+"old", newEntry.getDynamicObject(MasConstant.NCKD_SALARYITEM));
-                    newOldEntry.set(MasConstant.NCKD_DEFERREDPAYITEM+"old", newEntry.getBoolean(MasConstant.NCKD_DEFERREDPAYITEM));
-                    newOldEntry.set(MasConstant.NCKD_APPRSTD+"old", newEntry.getInt(MasConstant.NCKD_APPRSTD));
-                    newOldEntry.set(MasConstant.NCKD_DEFERPAYTOTALAMT+"old", newEntry.getInt(MasConstant.NCKD_DEFERPAYTOTALAMT));
-                    newOldEntry.set(MasConstant.NCKD_INSTALLMENTYEARS+"old", newEntry.getInt(MasConstant.NCKD_INSTALLMENTYEARS));
+                    DataEntityPropertyCollection properties = newOldEntry.getDynamicObjectType().getProperties();
+                    for (IDataEntityProperty property : properties) {
+                        String oldName = property.getName();
+                        String name = oldName.replace("old","");
+                        newOldEntry.set(oldName, newEntry.get(name));
+                    }
                     newOldEntry.set("nckd_originidold", originId);
-                    for (int i = 1; i <= 10; i++) {
-                        newOldEntry.set(MasConstant.NCKD_PAYAMOUNT+i+"old", newEntry.get(MasConstant.NCKD_PAYAMOUNT+i));
-                        newOldEntry.set(MasConstant.NCKD_PAYYEAR+i+"old", newEntry.get(MasConstant.NCKD_PAYYEAR+i));
-                     }
-
                 }
-                OperationResult operationResult = SaveServiceHelper.saveOperate("nckd_subcpchfsalstdchg", new DynamicObject[]{newSubcpChfSalStdChg}, OperateOption.create());
+                OperationResult operationResult = SaveServiceHelper.saveOperate(MasConstant.SUBCPCHFSALSTDCHG_ENTITYID, new DynamicObject[]{newSubcpChfSalStdChg}, OperateOption.create());
                 if (!operationResult.isSuccess()) {
                     String parentPageId = this.getView().getFormShowParameter().getPageId();
                     IFormView parentView = SessionManager.getCurrent().getViewNoPlugin(parentPageId);
@@ -422,7 +413,7 @@ public class SubcorpChiefSalStdFormPlugin extends AbstractFormPlugin implements
         if ("openchange".equals(messageBoxClosedEvent.getCallBackId())
                 && messageBoxClosedEvent.getResult() == MessageBoxResult.Yes) {
             BillShowParameter billShowParameter = new BillShowParameter();
-            billShowParameter.setFormId("nckd_subcpchfsalstdchg");
+            billShowParameter.setFormId(MasConstant.SUBCPCHFSALSTDCHG_ENTITYID);
             billShowParameter.getOpenStyle().setShowType(ShowType.MainNewTabPage);
             String id = this.getPageCache().get("changeid");
             // 设置单据主键ID(关键步骤)

+ 231 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/form/structappr/change/EntldrAnlSalStdChgFormPlugin.java

@@ -0,0 +1,231 @@
+package nckd.jxccl.swc.mas.plugin.form.structappr.change;
+
+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.entity.datamodel.events.AfterAddRowEventArgs;
+import kd.bos.entity.datamodel.events.ChangeData;
+import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.entity.report.CellStyle;
+import kd.bos.form.control.EntryGrid;
+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.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.utils.ConvertUtil;
+import nckd.jxccl.base.common.utils.DateUtil;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
+import nckd.jxccl.base.orm.helper.QFilterCommonHelper;
+import nckd.jxccl.swc.mas.common.MasConstant;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.EventObject;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+* 企业负责人个人年度薪酬标准核定表_变更单
+* 实体标识:nckd_entldranlsalstdchg
+* @author W.Y.C
+* @date 2025/12/3 18:41
+* @version 1.0
+*/
+public class EntldrAnlSalStdChgFormPlugin extends AbstractFormPlugin implements Plugin {
+
+    @Override
+    public void afterBindData(EventObject e) {
+        DynamicObjectCollection entryCollection = this.getModel().getEntryEntity(FormConstant.NCKD_ENTRYENTITY);
+        for (int rowIndex = 0; rowIndex < entryCollection.size(); rowIndex++) {
+            DynamicObject entry = entryCollection.get(rowIndex);
+            int installmentYears = entry.getInt(MasConstant.NCKD_INSTALLMENTYEARS);
+            initOperateOption(installmentYears,rowIndex);
+        }
+        markChange();
+    }
+
+    @Override
+    public void afterAddRow(AfterAddRowEventArgs e) {
+        initOperateOption(0,e.getInsertRow());
+    }
+
+    @Override
+    public void propertyChanged(PropertyChangedArgs e) {
+        String fieldKey = e.getProperty().getName();
+        ChangeData[] changeSet = e.getChangeSet();
+        int rowIndex = changeSet[0].getRowIndex();
+        Object oldValue = changeSet[0].getOldValue();
+        Object newValue = changeSet[0].getNewValue();
+        if (MasConstant.NCKD_INSTALLMENTYEARS.equalsIgnoreCase(fieldKey)) {
+            if (!Objects.equals(oldValue, newValue)) {
+                initOperateOption(ConvertUtil.toInt(newValue), rowIndex);
+            }
+        }  else if (MasConstant.NCKD_APPRSTD.equalsIgnoreCase(fieldKey)) {
+            DynamicObject payUnit = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(MasConstant.NCKD_PAYUNIT));
+            DynamicObject lawEntity = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(MasConstant.NCKD_LAWENTITY));
+            DynamicObject projectCategory = ConvertUtil.toDynamicObjectOrNull(this.getModel().getValue(MasConstant.NCKD_PROJECTCATEGORY));
+            Date year = ConvertUtil.toDate(this.getModel().getValue(MasConstant.NCKD_YEAR));
+            //判断“核定标准”是否大于0
+            BigDecimal apprStd = ConvertUtil.toBigDecimal(newValue);
+            if (apprStd != null && apprStd.compareTo(BigDecimal.ZERO) > 0) {
+                if (payUnit != null && lawEntity != null && year != null && projectCategory != null) {
+                    if (!Objects.equals(oldValue, newValue)) {
+                        //计算:延期支付总金额、支付年份1、支付年份1....
+                        //====================================== 获取延期支付比例 begin ======================================
+                        LocalDateTime localDateTime = DateUtil.toLocalDateTime(year);
+                        LocalDateTime beginOfYear = DateUtil.beginOfYear(localDateTime);
+                        LocalDateTime endOfYear = DateUtil.endOfYear(localDateTime);
+
+                        QueryFieldBuilder deferPayRatoConfQueryFieldBuilder = QueryFieldBuilder.create()
+                                .add(MasConstant.NCKD_PROJECTCATEGORY)
+                                .addIdNumberName(MasConstant.NCKD_PAYUNIT)
+                                .addIdNumberName(MasConstant.NCKD_DEFERPAYMONEY)
+                                .add(MasConstant.NCKD_DEFERPAYRATIO)
+                                .add(MasConstant.NCKD_DEFERPAYRATIO)
+                                .add(MasConstant.NCKD_PAYOUTTIMES)
+                                .add(MasConstant.NCKD_YEAR)
+                                .add(FormConstant.NCKD_ENTRYENTITY)
+                                .add(FormConstant.NCKD_ENTRYENTITY, MasConstant.NCKD_TIMES)
+                                .add(FormConstant.NCKD_ENTRYENTITY, MasConstant.NCKD_PAYOUTRATIO)
+                                .add(FormConstant.NCKD_ENTRYENTITY, MasConstant.NCKD_PAYOUTMONEY)
+                                .add(FormConstant.NCKD_ENTRYENTITY, MasConstant.NCKD_DEFERREDPAYITEM)
+                                .add(FormConstant.NCKD_ENTRYENTITY, MasConstant.NCKD_DEFERREDPAYDESC)
+                                .add(FormConstant.NCKD_ENTRYENTITY, MasConstant.NCKD_TERMPAYDESC)
+                                .orderDesc(MasConstant.CREATE_TIME_KEY)
+                                .orderAsc(String.join(".", FormConstant.NCKD_ENTRYENTITY, MasConstant.NCKD_TIMES));
+                        QFilter deferPayRatoConfFilter = new QFilter(MasConstant.NCKD_PAYUNIT, QCP.equals, payUnit.getLong(FormConstant.ID_KEY))
+                                .and(MasConstant.NCKD_LAWENTITY, QCP.equals, lawEntity.getLong(FormConstant.ID_KEY))
+                                .and(MasConstant.NCKD_YEAR, QCP.large_equals, DateUtil.toDate(beginOfYear))
+                                .and(MasConstant.NCKD_YEAR, QCP.less_equals, DateUtil.toDate(endOfYear))
+                                .and(QFilterCommonHelper.getEnableFilter());
+                        DynamicObject[] dbDeferPayRatoConfArray = BusinessDataServiceHelper.load(MasConstant.DEFERPAYRATOCONF_ENTITYID, deferPayRatoConfQueryFieldBuilder.buildSelect(), new QFilter[]{deferPayRatoConfFilter});
+                        Map<String, List<DynamicObject>> dbDeferPayRatoConfMap = Arrays.stream(dbDeferPayRatoConfArray)
+                                .collect(Collectors.groupingBy(obj -> {
+                                    DynamicObject dbProjectCategory = obj.getDynamicObject(MasConstant.NCKD_PROJECTCATEGORY);
+                                    if (dbProjectCategory != null) {
+                                        return dbProjectCategory.getString(FormConstant.NUMBER_KEY);
+                                    }
+                                    return ""; // 处理无项目分类的情况
+                                }));
+                        List<DynamicObject> dbDeferPayRatoConfList = dbDeferPayRatoConfMap.get(projectCategory.getString(FormConstant.NUMBER_KEY));
+
+                        if (dbDeferPayRatoConfList != null && !dbDeferPayRatoConfList.isEmpty()) {
+                            DynamicObject deferPayRatoConf = dbDeferPayRatoConfList.get(0);
+                            //延期支付比例(%)
+                            BigDecimal deferPayRatio = deferPayRatoConf.getBigDecimal(MasConstant.NCKD_DEFERPAYRATIO);
+                            //延期支付金额
+                            BigDecimal deferPayMoney = deferPayRatoConf.getBigDecimal(MasConstant.NCKD_DEFERPAYMONEY);
+                            LocalDateTime beginYear = DateUtil.toLocalDateTime(deferPayRatoConf.getDate(MasConstant.NCKD_YEAR));
+                            BigDecimal deferPayTotalAmt;
+                            if (deferPayMoney != null && deferPayMoney.compareTo(BigDecimal.ZERO) > 0) {
+                                //优先使用【延期支付金额】
+                                deferPayTotalAmt = deferPayMoney;
+                            } else {
+                                //核算标准*延期支付比例/100
+                                deferPayTotalAmt = apprStd.multiply(deferPayRatio.divide(new BigDecimal(100), 2, RoundingMode.DOWN));
+                            }
+                            this.getModel().setValue(MasConstant.NCKD_DEFERPAYTOTALAMT, deferPayTotalAmt, rowIndex);
+                            DynamicObjectCollection entryColl = deferPayRatoConf.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
+                            int i = 0;
+                            for (DynamicObject entry : entryColl) {
+                                int times = entry.getInt(MasConstant.NCKD_TIMES);
+                                //兑现比例(%)
+                                BigDecimal payoutRatio = entry.getBigDecimal(MasConstant.NCKD_PAYOUTRATIO);
+                                //兑现金额
+                                BigDecimal payoutMoney = entry.getBigDecimal(MasConstant.NCKD_PAYOUTMONEY);
+                                BigDecimal payaMount;
+                                if (payoutMoney != null && payoutMoney.compareTo(BigDecimal.ZERO) > 0) {
+                                    //优先使用【兑现金额】
+                                    payaMount = payoutMoney;
+                                } else {
+                                    //延期支付总金额*兑现比例
+                                    payaMount = deferPayTotalAmt.multiply(payoutRatio.divide(new BigDecimal(100), 2, RoundingMode.DOWN));
+                                }
+                                if (i != 0) {
+                                    beginYear = DateUtil.addYears(beginYear, 1);
+                                }
+                                this.getModel().setValue(MasConstant.NCKD_PAYYEAR + (i + 1), DateUtil.toDate(beginYear), rowIndex);
+                                this.getModel().setValue(MasConstant.NCKD_PAYAMOUNT + (i + 1), payaMount, rowIndex);
+                                i++;
+                            }
+
+                        }
+                        //====================================== 获取延期支付比例 end ======================================
+
+                    }
+                }
+            } else {
+                this.getModel().setValue(MasConstant.NCKD_DEFERPAYTOTALAMT, null);
+            }
+        }
+        markChange();
+    }
+
+    //标记变更
+    private void markChange(){
+        DynamicObjectCollection entryColl = this.getModel().getDataEntity(true).getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
+        DynamicObjectCollection oldEntryColl = this.getModel().getDataEntity(true).getDynamicObjectCollection("nckd_oldentryentity");
+
+        List<CellStyle> cellStyles = new ArrayList<>();
+        int i = 0;
+        for (DynamicObject entry : entryColl) {
+            long originId = entry.getLong("nckd_originid");
+            for (DynamicObject oldEntry : oldEntryColl) {
+                long oldOriginId = oldEntry.getLong("nckd_originidold");
+                if(originId == oldOriginId){
+                    DataEntityPropertyCollection properties = oldEntry.getDynamicObjectType().getProperties();
+                    for (IDataEntityProperty property : properties) {
+                        String oldName = property.getName();
+                        String name = oldName.replace("old","");
+                        Object value = entry.get(name);
+                        Object oldValue = oldEntry.get(oldName);
+                        if(!Objects.equals(value, oldValue)){
+                            CellStyle cellStyle = new CellStyle();
+                            cellStyle.setFieldKey(name);
+                            cellStyle.setRow(i);
+                            cellStyle.setForeColor("#fb2323");
+                            cellStyles.add(cellStyle);
+                        }
+
+                    }
+                }
+            }
+            i++;
+        }
+        EntryGrid entryGrid = this.getControl(FormConstant.NCKD_ENTRYENTITY);
+        entryGrid.setCellStyle(cellStyles);
+
+    }
+    /**
+     * 设置支付N锁定或解锁
+     * @param installmentYears 分期支付年
+     * @param rowIndex 行索引
+     * @return: void
+     * @author W.Y.C
+     * @date: 2025/11/29 20:48
+     */
+    private void initOperateOption(int installmentYears, int rowIndex) {
+        if(rowIndex > -1) {
+            for (int i = 1; i <= 10; i++) {
+                this.getView().setEnable(false, rowIndex, MasConstant.NCKD_PAYYEAR + i);
+                this.getView().setEnable(false, rowIndex, MasConstant.NCKD_PAYAMOUNT + i);
+            }
+            for (int i = 1; i <= installmentYears; i++) {
+                this.getView().setEnable(true, rowIndex, MasConstant.NCKD_PAYYEAR + i);
+                this.getView().setEnable(true, rowIndex, MasConstant.NCKD_PAYAMOUNT + i);
+
+            }
+        }
+    }
+
+}

+ 101 - 0
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/operate/structappr/change/EntldrAnlSalStdChgOpPlugin.java

@@ -0,0 +1,101 @@
+package nckd.jxccl.swc.mas.plugin.operate.structappr.change;
+
+import kd.bos.dataentity.OperateOption;
+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.entity.MainEntityType;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.PreparePropertysEventArgs;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.MetadataServiceHelper;
+import kd.bos.servicehelper.operation.OperationServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.sdk.plugin.Plugin;
+import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.exception.ValidationException;
+import nckd.jxccl.swc.mas.common.MasConstant;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+* 企业负责人个人年度薪酬标准核定表_变更单-反写操作
+* 实体标识:nckd_entldranlsalstdchg
+* @author W.Y.C
+* @date 2025/12/3 19:15
+* @version 1.0
+*/
+public class EntldrAnlSalStdChgOpPlugin extends AbstractOperationServicePlugIn implements Plugin {
+    @Override
+    public void onPreparePropertys(PreparePropertysEventArgs e) {
+        e.getFieldKeys().addAll(this.billEntityType.getAllFields().keySet());
+    }
+
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+        List<Long> subcorpChiefSalStdArray = new ArrayList<>();
+        for (DynamicObject dataEntity : e.getDataEntities()) {
+            long subcorpChiefSalStdId = dataEntity.getLong(String.join(".", MasConstant.ENTLEADERANLSALSTD_ENTITYID, FormConstant.ID_KEY));
+            subcorpChiefSalStdArray.add(subcorpChiefSalStdId);
+        }
+        MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType(MasConstant.ENTLEADERANLSALSTD_ENTITYID);
+        DynamicObject[] load = BusinessDataServiceHelper.load(subcorpChiefSalStdArray.toArray(new Long[0]), dataEntityType);
+        // 按ID分组
+        Map<Long, DynamicObject> groupedById = Arrays.stream(load)
+                .collect(Collectors.toMap(
+                        obj -> obj.getLong(FormConstant.ID_KEY),
+                        obj -> obj
+                ));
+        for (DynamicObject dataEntity : e.getDataEntities()) {
+            long subcorpChiefSalStdId = dataEntity.getLong(String.join(".",MasConstant.ENTLEADERANLSALSTD_ENTITYID, FormConstant.ID_KEY));
+            DynamicObjectCollection entryColl = dataEntity.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
+
+            DynamicObject updateSubcorpChiefSalStd = groupedById.get(subcorpChiefSalStdId);
+            DynamicObjectCollection updateSubcorpChiefSalStdEntryColl = updateSubcorpChiefSalStd.getDynamicObjectCollection(FormConstant.NCKD_ENTRYENTITY);
+
+            for (DynamicObject entry : entryColl) {
+                long originid = entry.getLong("nckd_originid");
+                for (DynamicObject updateSubcorpChiefSalStdEntry : updateSubcorpChiefSalStdEntryColl) {
+                    long id = updateSubcorpChiefSalStdEntry.getLong(FormConstant.ID_KEY);
+                    if(originid == id){
+                        DataEntityPropertyCollection properties = entry.getDynamicObjectType().getProperties();
+                        for (IDataEntityProperty property : properties) {
+                            String name = property.getName();
+                            if(name.contains("nckd_") && !name.contains("nckd_originid")) {
+                                updateSubcorpChiefSalStdEntry.set(name, entry.get(name));
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+            updateSubcorpChiefSalStd.set(FormConstant.MODIFY_TIME_KEY,new Date());
+            dataEntity.set(FormConstant.MODIFIER_KEY,dataEntity.get(FormConstant.CREATOR_KEY));
+        }
+
+        OperationResult operationResult2 = OperationServiceHelper.executeOperate("unsubmit", MasConstant.ENTLEADERANLSALSTD_ENTITYID, load);
+        if(operationResult2.isSuccess()) {
+            OperateOption option = OperateOption.create();
+            //跳过状态校验
+            option.setVariableValue("rmStatusControl", "true");
+            OperationResult operationResult1 = SaveServiceHelper.saveOperate(MasConstant.ENTLEADERANLSALSTD_ENTITYID, load, option);
+            if (operationResult1 != null && !operationResult1.isSuccess()) {
+                throw new ValidationException("回写【企业负责人个人年度薪酬标准核定表】失败,原因:" + operationResult1.getMessage());
+            }
+            OperationResult operationResult3 = OperationServiceHelper.executeOperate("submit", MasConstant.ENTLEADERANLSALSTD_ENTITYID, load);
+            if (operationResult3 != null && !operationResult3.isSuccess()) {
+                throw new ValidationException("回写【企业负责人个人年度薪酬标准核定表】失败,原因:" + operationResult3.getMessage());
+            }
+        }else{
+            throw new ValidationException("回写【企业负责人个人年度薪酬标准核定表】失败,原因:" + operationResult2.getMessage());
+        }
+    }
+}

+ 34 - 12
code/swc/nckd-jxccl-swc/src/main/java/nckd/jxccl/swc/mas/plugin/operate/structappr/change/SubcpChfSalstdChgBackOpPlugin.java

@@ -1,16 +1,22 @@
 package nckd.jxccl.swc.mas.plugin.operate.structappr.change;
 
+import kd.bos.dataentity.OperateOption;
 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.entity.MainEntityType;
+import kd.bos.entity.operate.result.OperationResult;
 import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
 import kd.bos.entity.plugin.PreparePropertysEventArgs;
 import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
 import kd.bos.servicehelper.BusinessDataServiceHelper;
 import kd.bos.servicehelper.MetadataServiceHelper;
+import kd.bos.servicehelper.operation.OperationServiceHelper;
 import kd.bos.servicehelper.operation.SaveServiceHelper;
 import kd.sdk.plugin.Plugin;
 import nckd.jxccl.base.common.constant.FormConstant;
+import nckd.jxccl.base.common.exception.ValidationException;
 import nckd.jxccl.swc.mas.common.MasConstant;
 
 import java.util.ArrayList;
@@ -20,8 +26,12 @@ import java.util.Map;
 import java.util.stream.Collectors;
 
 /**
- * 单据操作插件
- */
+* 子企业负责人正职年度薪酬核定标准-回写op
+* 实体标识:nckd_subcorpchiefsalstd
+* @author W.Y.C
+* @date 2025/12/3 20:03
+* @version 1.0
+*/
 public class SubcpChfSalstdChgBackOpPlugin extends AbstractOperationServicePlugIn implements Plugin {
 
     @Override
@@ -56,15 +66,12 @@ public class SubcpChfSalstdChgBackOpPlugin extends AbstractOperationServicePlugI
                 for (DynamicObject updateSubcorpChiefSalStdEntry : updateSubcorpChiefSalStdEntryColl) {
                     long id = updateSubcorpChiefSalStdEntry.getLong(FormConstant.ID_KEY);
                     if(originid == id){
-                        updateSubcorpChiefSalStdEntry.set(MasConstant.NCKD_PROJECTCATEGORY, entry.getDynamicObject(MasConstant.NCKD_PROJECTCATEGORY));
-                        updateSubcorpChiefSalStdEntry.set(MasConstant.NCKD_SALARYITEM, entry.getDynamicObject(MasConstant.NCKD_SALARYITEM));
-                        updateSubcorpChiefSalStdEntry.set(MasConstant.NCKD_DEFERREDPAYITEM, entry.getBoolean(MasConstant.NCKD_DEFERREDPAYITEM));
-                        updateSubcorpChiefSalStdEntry.set(MasConstant.NCKD_APPRSTD, entry.getInt(MasConstant.NCKD_APPRSTD));
-                        updateSubcorpChiefSalStdEntry.set(MasConstant.NCKD_DEFERPAYTOTALAMT, entry.getInt(MasConstant.NCKD_DEFERPAYTOTALAMT));
-                        updateSubcorpChiefSalStdEntry.set(MasConstant.NCKD_INSTALLMENTYEARS, entry.getInt(MasConstant.NCKD_INSTALLMENTYEARS));
-                        for (int i = 1; i <= 10; i++) {
-                            updateSubcorpChiefSalStdEntry.set(MasConstant.NCKD_PAYAMOUNT+i, entry.get(MasConstant.NCKD_PAYAMOUNT+i));
-                            updateSubcorpChiefSalStdEntry.set(MasConstant.NCKD_PAYYEAR+i, entry.get(MasConstant.NCKD_PAYYEAR+i));
+                        DataEntityPropertyCollection properties = entry.getDynamicObjectType().getProperties();
+                        for (IDataEntityProperty property : properties) {
+                            String name = property.getName();
+                            if(name.contains("nckd_") && !name.contains("nckd_originid")) {
+                                updateSubcorpChiefSalStdEntry.set(name, entry.get(name));
+                            }
                         }
                         break;
                     }
@@ -72,6 +79,21 @@ public class SubcpChfSalstdChgBackOpPlugin extends AbstractOperationServicePlugI
             }
         }
 
-        SaveServiceHelper.update(load);
+        OperationResult operationResult2 = OperationServiceHelper.executeOperate("unsubmit", MasConstant.SUBCORPCHIEFSALSTD_ENTITYID, load);
+        if(operationResult2.isSuccess()) {
+            OperateOption option = OperateOption.create();
+            //跳过状态校验
+            option.setVariableValue("rmStatusControl", "true");
+            OperationResult operationResult1 = SaveServiceHelper.saveOperate(MasConstant.SUBCORPCHIEFSALSTD_ENTITYID, load, option);
+            if (operationResult1 != null && !operationResult1.isSuccess()) {
+                throw new ValidationException("回写【企业负责人个人年度薪酬标准核定表】失败,原因:" + operationResult1.getMessage());
+            }
+            OperationResult operationResult3 = OperationServiceHelper.executeOperate("submit", MasConstant.SUBCORPCHIEFSALSTD_ENTITYID, load);
+            if (operationResult3 != null && !operationResult3.isSuccess()) {
+                throw new ValidationException("回写【企业负责人个人年度薪酬标准核定表】失败,原因:" + operationResult3.getMessage());
+            }
+        }else{
+            throw new ValidationException("回写【企业负责人个人年度薪酬标准核定表】失败,原因:" + operationResult2.getMessage());
+        }
     }
 }