Просмотр исходного кода

feat(hr): 更新组织架构常量和岗位变更处理逻辑

- 将HAOS_ADMINORGHR相关常量更新为HAOS_ADMINORGHRF7
- 新增PatternUtil工具类用于模型处理
- 重构岗位确认回调服务和属性变更服务
- 更新岗位单据服务助手中的分录处理逻辑
- 修复岗位删除和选择确认的业务逻辑
- 优化岗位变更时的数据验证和缓存处理机制
jtd 2 недель назад
Родитель
Сommit
bea839c492
19 измененных файлов с 984 добавлено и 407 удалено
  1. 11 11
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/homs/business/application/event/GenerateEmploymentContractEventServicePlugin.java
  2. 5 5
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/homs/common/application/event/GECEventConstant.java
  3. 4 4
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/sdm/common/SanDingConstant.java
  4. 6 6
      code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/sdm/plugin/operate/SendTaskOpPlugin.java
  5. 52 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/PatternUtil.java
  6. 82 26
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/PositionBillConfirmCallBackService.java
  7. 139 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/PositionBillPropertyChangedService.java
  8. 128 88
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/PositionBillServiceHelper.java
  9. 79 6
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/PosBillEntryAddFormPlugin.java
  10. 15 15
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/PositionBillEntryFormPlugin.java
  11. 22 5
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/PositionBillFormPlugin.java
  12. 14 155
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/PosBillEntryAddSaveOpPlugin.java
  13. 171 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/PosBillEntryNewPositionTempSaveOpPlugin.java
  14. 8 11
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/PositionBillEntrySaveOpPlugin.java
  15. 116 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/AbsBillPositionSaveValidator.java
  16. 15 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionAddSaveValidator.java
  17. 72 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionBillEntryNameValidator.java
  18. 45 0
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionBillEntryNumberValidator.java
  19. 0 75
      code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionBillEntryValidator.java

+ 11 - 11
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/homs/business/application/event/GenerateEmploymentContractEventServicePlugin.java

@@ -143,17 +143,17 @@ public class GenerateEmploymentContractEventServicePlugin implements IEventServi
                 .add(GECEventConstant.HSPM_PERCRE_NUMBER)
                 .add(GECEventConstant.CNIDCARD_CREDENTIALSTYPE_ID)
                 .add(GECEventConstant.CNIDCARD_NUMBER)
-                .add(GECEventConstant.HAOS_ADMINORGHR_CORPORATEORG_ID)
+                .add(GECEventConstant.HAOS_ADMINORGHRF7_CORPORATEORG_ID)
                 .add(GECEventConstant.HRPI_EMPPOSORGREL_STARTDATE)
                 .add(GECEventConstant.HRPI_EMPLOYEE_ID)
                 .add(GECEventConstant.HRPI_EMPLOYEE_EMPNUMBER)
                 .add(GECEventConstant.HRPI_EMPLOYEE_NAME)
                 .add(GECEventConstant.HRPI_EMPLOYEE_NATIONALITY_ID)
                 .add(GECEventConstant.HRPI_EMPLOYEE_NATIONALITY_NUMBER)
-                .add(GECEventConstant.HAOS_ADMINORGHR_BELONGCOMPANY_ID)
-                .add(GECEventConstant.HAOS_ADMINORGHR_BELONGCOMPANY_SOURCEVID)
-                .add(GECEventConstant.HAOS_ADMINORGHR_ID)
-                .add(GECEventConstant.HAOS_ADMINORGHR_SOURCEVID)
+                .add(GECEventConstant.HAOS_ADMINORGHRF7_BELONGCOMPANY_ID)
+                .add(GECEventConstant.HAOS_ADMINORGHRF7_BELONGCOMPANY_SOURCEVID)
+                .add(GECEventConstant.HAOS_ADMINORGHRF7_ID)
+                .add(GECEventConstant.HAOS_ADMINORGHRF7_SOURCEVID)
                 .add(GECEventConstant.HBPM_POSITIONHR_ID)
                 .add(GECEventConstant.HBPM_POSITIONHR_SOURCEVID)
                 .add(GECEventConstant.HRPI_EMPPOSORGREL_JOB_NUMBER)
@@ -173,7 +173,7 @@ public class GenerateEmploymentContractEventServicePlugin implements IEventServi
         QueryEntityType queryEntityType = (QueryEntityType) MetadataServiceHelper.getDataEntityType(GET_EMPLOYEE_INFO_QUERY);
         DynamicObjectCollection personInfoColl = HRQueryEntityHelper.getInstance().getQueryDyoColl(queryEntityType, queryFields, new QFilter[]{qFilter}, orderBys);
         // 获取法律实体
-        List<Long> corporateorgIds = personInfoColl.stream().map(personInfo -> personInfo.getLong(GECEventConstant.HAOS_ADMINORGHR_CORPORATEORG_ID)).collect(Collectors.toList());
+        List<Long> corporateorgIds = personInfoColl.stream().map(personInfo -> personInfo.getLong(GECEventConstant.HAOS_ADMINORGHRF7_CORPORATEORG_ID)).collect(Collectors.toList());
         // 获取聘用单位
         DynamicObject[] signCompanyDyos = HRBaseServiceHelper.create(GECEventConstant.HBSS_SIGNCOMPANY_ENTITY).query(String.join(",", GECEventConstant.LAWENTITY_KEY, GECEventConstant.VID_KEY), new QFilter[]{new QFilter(GECEventConstant.LAWENTITY_KEY, QCP.in, corporateorgIds)});
         // 处理成 key->法律实体ID value->聘用单位ID
@@ -221,13 +221,13 @@ public class GenerateEmploymentContractEventServicePlugin implements IEventServi
             // 设置 常驻工作地
             contractApplyNewDyo.set(GECEventConstant.BASELOCATION_KEY, personInfo.getDynamicObject(GECEventConstant.HRPI_EMPPOSORGREL_WORKPLACE));
             // 设置 公司
-            contractApplyNewDyo.set(GECEventConstant.CURCOMPANY_KEY, EntityHelper.newEntity(GECEventConstant.ADMINORG_ENTITYID, personInfo.getLong(GECEventConstant.HAOS_ADMINORGHR_BELONGCOMPANY_ID)));
+            contractApplyNewDyo.set(GECEventConstant.CURCOMPANY_KEY, EntityHelper.newEntity(GECEventConstant.ADMINORG_ENTITYID, personInfo.getLong(GECEventConstant.HAOS_ADMINORGHRF7_BELONGCOMPANY_ID)));
             // 设置 公司历史
-            contractApplyNewDyo.set(GECEventConstant.SIGNEDCOMPANYHIS_KEY, EntityHelper.newEntity(GECEventConstant.ADMINORG_ENTITYID, personInfo.getLong(GECEventConstant.HAOS_ADMINORGHR_BELONGCOMPANY_SOURCEVID)));
+            contractApplyNewDyo.set(GECEventConstant.SIGNEDCOMPANYHIS_KEY, EntityHelper.newEntity(GECEventConstant.ADMINORG_ENTITYID, personInfo.getLong(GECEventConstant.HAOS_ADMINORGHRF7_BELONGCOMPANY_SOURCEVID)));
             // 设置 部门
-            contractApplyNewDyo.set(GECEventConstant.CURDEPT_KEY, EntityHelper.newEntity(GECEventConstant.ADMINORG_ENTITYID, personInfo.getLong(GECEventConstant.HAOS_ADMINORGHR_ID)));
+            contractApplyNewDyo.set(GECEventConstant.CURDEPT_KEY, EntityHelper.newEntity(GECEventConstant.ADMINORG_ENTITYID, personInfo.getLong(GECEventConstant.HAOS_ADMINORGHRF7_ID)));
             // 设置 部门历史
-            contractApplyNewDyo.set(GECEventConstant.DEPARTMENTHIS_KEY, EntityHelper.newEntity(GECEventConstant.ADMINORG_ENTITYID, personInfo.getLong(GECEventConstant.HAOS_ADMINORGHR_SOURCEVID)));
+            contractApplyNewDyo.set(GECEventConstant.DEPARTMENTHIS_KEY, EntityHelper.newEntity(GECEventConstant.ADMINORG_ENTITYID, personInfo.getLong(GECEventConstant.HAOS_ADMINORGHRF7_SOURCEVID)));
             // 设置 岗位
             contractApplyNewDyo.set(GECEventConstant.CURPOSTION_KEY, EntityHelper.newEntity(GECEventConstant.HBPM_POSITIONHR, personInfo.getLong(GECEventConstant.HBPM_POSITIONHR_ID)));
             // 设置 岗位历史
@@ -255,7 +255,7 @@ public class GenerateEmploymentContractEventServicePlugin implements IEventServi
             // 设置 联系方式
             contractApplyNewDyo.set(GECEventConstant.EMPPHONE_KEY, personInfo.getString(GECEventConstant.HSPM_PERCONTACT_PHONE));
             // 设置应签单位、实签单位
-            DynamicObject signCompanyDyo = signCompanyMap.get(personInfo.getLong(GECEventConstant.HAOS_ADMINORGHR_CORPORATEORG_ID));
+            DynamicObject signCompanyDyo = signCompanyMap.get(personInfo.getLong(GECEventConstant.HAOS_ADMINORGHRF7_CORPORATEORG_ID));
             if (HRObjectUtils.isEmpty(signCompanyDyo)) {
                 throw new KDBizException(String.format("没有可使用的应签/实签单位,组织分配ID[%s]", assignmentId));
             }

+ 5 - 5
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/homs/common/application/event/GECEventConstant.java

@@ -195,9 +195,9 @@ public class GECEventConstant extends FormConstant {
     public static final String CNIDCARD_NUMBER = "cnidcard.number";
 
     /** HR行政组织.ID */
-    public static final String HAOS_ADMINORGHR_ID = "haos_adminorghr.id";
+    public static final String HAOS_ADMINORGHRF7_ID = "haos_adminorghrf7.id";
     /** HR行政组织.法律实体.ID */
-    public static final String HAOS_ADMINORGHR_CORPORATEORG_ID = "haos_adminorghr.corporateorg.id";
+    public static final String HAOS_ADMINORGHRF7_CORPORATEORG_ID = "haos_adminorghrf7.corporateorg.id";
 
     /** 员工.ID */
     public static final String HRPI_EMPLOYEE_ID = "hrpi_employee.id";
@@ -211,11 +211,11 @@ public class GECEventConstant extends FormConstant {
     public static final String HRPI_EMPLOYEE_NATIONALITY_NUMBER = "hrpi_employee.nationality.number";
 
     /** HR行政组织.所属公司.ID */
-    public static final String HAOS_ADMINORGHR_BELONGCOMPANY_ID = "haos_adminorghr.belongcompany.id";
+    public static final String HAOS_ADMINORGHRF7_BELONGCOMPANY_ID = "haos_adminorghrf7.belongcompany.id";
     /** HR行政组织.所属公司.关联历史版本 */
-    public static final String HAOS_ADMINORGHR_BELONGCOMPANY_SOURCEVID = "haos_adminorghr.belongcompany.sourcevid";
+    public static final String HAOS_ADMINORGHRF7_BELONGCOMPANY_SOURCEVID = "haos_adminorghrf7.belongcompany.sourcevid";
     /** HR行政组织.关联历史版本 */
-    public static final String HAOS_ADMINORGHR_SOURCEVID = "haos_adminorghr.sourcevid";
+    public static final String HAOS_ADMINORGHRF7_SOURCEVID = "haos_adminorghrf7.sourcevid";
 
     /** 岗位信息维护.ID */
     public static final String HBPM_POSITIONHR_ID = "hbpm_positionhr.id";

+ 4 - 4
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/sdm/common/SanDingConstant.java

@@ -73,13 +73,13 @@ public class SanDingConstant extends FormConstant {
     public static final String ATTACHMENTPANEL_KEY = "attachmentpanel";
 
     /** 行政组织.ID */
-    public static final String HAOS_ADMINORGHR_ID = "haos_adminorghr.id";
+    public static final String HAOS_ADMINORGHRF7_ID = "haos_adminorghrf7.id";
     /** 行政组织.业务ID */
-    public static final String HAOS_ADMINORGHR_BOID = "haos_adminorghr.boid";
+    public static final String HAOS_ADMINORGHRF7_BOID = "haos_adminorghrf7.boid";
     /** 行政组织.关联历史版本 */
-    public static final String HAOS_ADMINORGHR_SOURCEVID = "haos_adminorghr.sourcevid";
+    public static final String HAOS_ADMINORGHRF7_SOURCEVID = "haos_adminorghrf7.sourcevid";
     /** HR行政组织.所属公司.业务ID */
-    public static final String HAOS_ADMINORGHR_BELONGCOMPANY_BOID = "haos_adminorghr.belongcompany.boid";
+    public static final String HAOS_ADMINORGHRF7_BELONGCOMPANY_BOID = "haos_adminorghrf7.belongcompany.boid";
 
     /** 公司负责人.负责人.ID */
     public static final String NCKD_COMPANYMANAGE_NCKD_MANAGER_ID = "nckd_companymanager.nckd_manager.id";

+ 6 - 6
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/sdm/plugin/operate/SendTaskOpPlugin.java

@@ -121,9 +121,9 @@ public class SendTaskOpPlugin extends AbstractOperationServicePlugIn {
         String queryFields = QueryFieldBuilder.create()
                 .add(SanDingConstant.BOID_KEY)
                 .add(SanDingConstant.SOURCEVID_KEY)
-                .add(SanDingConstant.HAOS_ADMINORGHR_BOID)
-                .add(SanDingConstant.HAOS_ADMINORGHR_SOURCEVID)
-                .add(SanDingConstant.HAOS_ADMINORGHR_BELONGCOMPANY_BOID)
+                .add(SanDingConstant.HAOS_ADMINORGHRF7_BOID)
+                .add(SanDingConstant.HAOS_ADMINORGHRF7_SOURCEVID)
+                .add(SanDingConstant.HAOS_ADMINORGHRF7_BELONGCOMPANY_BOID)
                 .buildSelect();
         String orderBys = QueryFieldBuilder.create()
                 .addAsc(SanDingConstant.ADMINORG, SanDingConstant.LEVEL_KEY)
@@ -137,14 +137,14 @@ public class SendTaskOpPlugin extends AbstractOperationServicePlugIn {
         // 处理成 key->公司BOID value->List<Map<String, Long>>
         Map<Long, List<Map<String, Long>>> companyPositionMap = positionDyoColl.stream()
             .collect(Collectors.groupingBy(
-                positionDyo -> positionDyo.getLong(SanDingConstant.HAOS_ADMINORGHR_BELONGCOMPANY_BOID),
+                positionDyo -> positionDyo.getLong(SanDingConstant.HAOS_ADMINORGHRF7_BELONGCOMPANY_BOID),
                 Collectors.mapping(
                     positionDyo -> {
                         Map<String, Long> positionOrgMap = new HashMap<>();
                         positionOrgMap.put("positionBoId", positionDyo.getLong(SanDingConstant.BOID_KEY));
                         positionOrgMap.put("positionSourceVid", positionDyo.getLong(SanDingConstant.BOID_KEY));
-                        positionOrgMap.put("adminOrgBoId", positionDyo.getLong(SanDingConstant.HAOS_ADMINORGHR_BOID));
-                        positionOrgMap.put("adminOrgSourceVid", positionDyo.getLong(SanDingConstant.HAOS_ADMINORGHR_BOID));
+                        positionOrgMap.put("adminOrgBoId", positionDyo.getLong(SanDingConstant.HAOS_ADMINORGHRF7_BOID));
+                        positionOrgMap.put("adminOrgSourceVid", positionDyo.getLong(SanDingConstant.HAOS_ADMINORGHRF7_BOID));
                         return positionOrgMap;
                     },
                     Collectors.toList()

+ 52 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/PatternUtil.java

@@ -0,0 +1,52 @@
+package nckd.jxccl.hrmp.hbpm.business.hr;
+
+import kd.bos.entity.ISVInfo;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.servicehelper.ISVServiceHelper;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 模型工具类
+ * @author: jtd
+ * @date: 2025/12/24 19:45
+ */
+public class PatternUtil {
+    private static final Log logger = LogFactory.getLog(PatternUtil.class);
+    private static final char[] SPECIAL_SEPARATORS = new char[]{'!', '_', '\\'};
+    private static final Pattern SPECIAL_SEPARATORS_REGEX;
+    public static final String ISV_ID;
+    public static final String ISV_NAME;
+
+    static {
+        StringBuilder stringBuffer = new StringBuilder();
+
+        for(int i = 0; i < SPECIAL_SEPARATORS.length; ++i) {
+            stringBuffer.append("\\").append(SPECIAL_SEPARATORS[i]).append("+");
+            if (i < SPECIAL_SEPARATORS.length - 1) {
+                stringBuffer.append("|");
+            }
+        }
+
+        SPECIAL_SEPARATORS_REGEX = Pattern.compile(stringBuffer.toString());
+        ISVInfo isvInfo = ISVServiceHelper.getISVInfo();
+        ISV_ID = isvInfo.getId();
+        ISV_NAME = isvInfo.getName();
+        logger.info("do isExProperty,the isv is {} {}", ISV_ID, ISV_NAME);
+    }
+
+    public static boolean valideName(String orgName) {
+        Matcher matcher = SPECIAL_SEPARATORS_REGEX.matcher(orgName);
+        return matcher.find();
+    }
+
+    public static boolean isExProperty(String property) {
+        if (property == null) {
+            return false;
+        } else {
+            return property.endsWith("_ext") || property.contains(ISV_ID + "_") || property.contains(ISV_NAME + "_");
+        }
+    }
+}

+ 82 - 26
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/PositionBillConfirmCallBackService.java

@@ -11,9 +11,12 @@ import kd.bos.form.IFormView;
 import kd.bos.form.MessageBoxResult;
 import kd.bos.form.control.EntryGrid;
 import kd.bos.form.events.MessageBoxClosedEvent;
+import kd.bos.orm.ORM;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.hr.hbp.common.util.HRStringUtils;
+import kd.hr.homs.business.domain.orgfast.repository.AdminOrgFastChgHelper;
 import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
 
 import java.util.Arrays;
@@ -35,41 +38,45 @@ public class PositionBillConfirmCallBackService extends PositionBillBaseService
 
     public void confirmCallBack(MessageBoxClosedEvent event) {
         String callBackId = event.getCallBackId();
-        if (callBackId.startsWith(PositionBillConstant.DELETE_ROWS_PREFIX)) {
-            if (event.getResult() == MessageBoxResult.Cancel) {
-                return;
-            }
-
-            EntryGrid coopRelEntryGrid = getView().getControl(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY);
-            int[] selectRows = coopRelEntryGrid.getSelectRows();
-            HRBaseServiceHelper hrBaseServiceHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
-            List<Long> entryIdList = Lists.newArrayListWithExpectedSize(selectRows.length);
-            if (PositionBillConstant.DELETE_ROWS_ADD_OP.equals(callBackId)) {
-                List<Long> positionIds = Lists.newArrayListWithExpectedSize(selectRows.length);
-                int[] deleteRows = validateHasChildOrgAndDelete();
-                if (deleteRows.length == 0) {
+        if (!"effect_confirm".equals(callBackId) || event.getResult() != MessageBoxResult.Yes) {
+            if (callBackId.startsWith(PositionBillConstant.DELETE_ROWS_PREFIX)) {
+                if (event.getResult() == MessageBoxResult.Cancel) {
                     return;
                 }
 
-                for(int i = 0; i < deleteRows.length; ++i) {
-                    int row = deleteRows[i];
-                    entryIdList.add(getModel().getEntryEntity(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).get(row).getLong(PositionBillConstant.ID_KEY));
-                    positionIds.add(getModel().getEntryEntity(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).get(row).getLong(String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ADD_TAG)));
+                EntryGrid coopRelEntryGrid = getView().getControl(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY);
+                int[] selectRows = coopRelEntryGrid.getSelectRows();
+                HRBaseServiceHelper hrBaseServiceHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
+                List<Long> entryIdList = Lists.newArrayListWithExpectedSize(selectRows.length);
+                if (PositionBillConstant.DELETE_ROWS_ADD_OP.equals(callBackId)) {
+                    List<Long> positionIds = Lists.newArrayListWithExpectedSize(selectRows.length);
+                    int[] deleteRows = validateHasChildPositionAndDelete();
+                    if (deleteRows.length == 0) {
+                        return;
+                    }
+
+                    for (int i = 0; i < deleteRows.length; ++i) {
+                        int row = deleteRows[i];
+                        entryIdList.add(getModel().getEntryEntity(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).get(row).getLong(PositionBillConstant.ID_KEY));
+                        positionIds.add(getModel().getEntryEntity(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).get(row).getLong(String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ADD_TAG)));
+                    }
+
+                    getModel().deleteEntryRows(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY, deleteRows);
+                    PositionBillServiceHelper.delAddMaster(positionIds);
+                } else if (PositionBillConstant.DELETE_ROWS_CHANGE_OP.equals(callBackId)) {
+                    entryIdList = getModel().getEntryEntity(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY).stream().map((entry) -> entry.getLong(PositionBillConstant.ID_KEY)).collect(Collectors.toList());
+                    getModel().deleteEntryRows(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY, selectRows);
                 }
 
-                getModel().deleteEntryRows(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY, deleteRows);
-                PositionBillServiceHelper.delAddMaster(positionIds);
-            } else if (PositionBillConstant.DELETE_ROWS_CHANGE_OP.equals(callBackId)) {
-                entryIdList = getModel().getEntryEntity(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY).stream().map((entry) -> entry.getLong(PositionBillConstant.ID_KEY)).collect(Collectors.toList());
-                getModel().deleteEntryRows(PositionBillConstant.NCKD_ENTRYENTITY_CHANGE_KEY, selectRows);
+                getView().showSuccessNotification("删除成功");
+                hrBaseServiceHelper.delete(entryIdList.toArray(new Long[0]));
             }
-
-            getView().showSuccessNotification("删除成功");
-            hrBaseServiceHelper.delete(entryIdList.toArray(new Long[0]));
         }
+
+        changePositionConfirm(event, callBackId);
     }
 
-    private int[] validateHasChildOrgAndDelete() {
+    private int[] validateHasChildPositionAndDelete() {
         EntryGrid strategyEntryGrid = getView().getControl(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY);
         int[] rows = strategyEntryGrid.getSelectRows();
         // 要删除的岗位
@@ -145,4 +152,53 @@ public class PositionBillConfirmCallBackService extends PositionBillBaseService
 
         return deleteRowIndexList.stream().mapToInt(Integer::intValue).toArray();
     }
+
+    private void changePositionConfirm(MessageBoxClosedEvent messageBoxClosedEvent, String callBackId) {
+        if (callBackId.startsWith("select_position_")) {
+            String suffix = callBackId.replace("select_position_", "");
+            String lineSuffix = "_" + suffix;
+            HRBaseServiceHelper helper = new HRBaseServiceHelper(PositionBillConstant.HBPM_POSITIONHR);
+            EntryGrid entryGrid = getView().getControl(PositionBillConstant.NCKD_ENTRYENTITY + lineSuffix);
+            String positionRow = getView().getPageCache().get("positionRow");
+            int row = Integer.parseInt(positionRow);
+            if (messageBoxClosedEvent.getResult() != MessageBoxResult.Yes) {
+                DynamicObject entryEntityDyn = getModel().getDataEntity(true).getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY + lineSuffix).get(row);
+                String positionOld = getView().getPageCache().get("positionOld");
+                if (HRStringUtils.isNotEmpty(positionOld)) {// 461
+                    QFilter filter = new QFilter(PositionBillConstant.ID_KEY, QCP.equals, Long.parseLong(positionOld));
+                    DynamicObject position = helper.queryOne(String.join(",", PositionBillConstant.ID_KEY, PositionBillConstant.NAME_KEY, PositionBillConstant.NUMBER_KEY), filter.toArray());
+                    entryEntityDyn.set(PositionBillConstant.NCKD_POSITION + lineSuffix, position);
+                } else {
+                    entryEntityDyn.set(PositionBillConstant.NCKD_POSITION + lineSuffix, null);
+                }
+
+                getView().updateView(PositionBillConstant.NCKD_ENTRYENTITY + lineSuffix);
+                return;
+            }
+
+            DynamicObject entryEntityDyn = PositionBillServiceHelper.getFocusEntry(suffix, getView(), row);
+            long positionId = entryEntityDyn.getLong(PositionBillConstant.NCKD_POSITION + lineSuffix);
+            QFilter filter = new QFilter(PositionBillConstant.ID_KEY, QCP.equals, positionId);
+            DynamicObject org = helper.queryOne("id,parentorg,simplename,adminorgtype,establishmentdate,corporateorg,tobedisableflag,adminorglayer,adminorgfunction,companyarea,city,workplace", filter.toArray());
+            long entryId = ORM.create().genLongId(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
+            entryEntityDyn.set("id", entryId);
+
+            //setChangeSence(lineSuffix, entryEntityDyn, row);
+            getView().updateView(PositionBillConstant.NCKD_ENTRYENTITY + lineSuffix);
+        } else if (callBackId.equals(PositionBillConstant.CHANGE_TAG)) {
+            String entryId = String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, callBackId);
+            EntryGrid entryGrid = getView().getControl(entryId);
+            int row = entryGrid.getEntryState().getFocusRow();
+            if (messageBoxClosedEvent.getResult() == MessageBoxResult.Yes) {
+                AdminOrgFastChgHelper.cleanOrgBaseInfoForBillEntry(getView(), row, callBackId, entryId);
+            } else {
+                String oldId = getView().getPageCache().get("entry_position_value");
+                getModel().beginInit();
+                getModel().setValue(callBackId, Long.parseLong(oldId), row);
+                getModel().endInit();
+                getView().updateView(callBackId, row);
+            }
+        }
+
+    }
 }

+ 139 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/PositionBillPropertyChangedService.java

@@ -0,0 +1,139 @@
+package nckd.jxccl.hrmp.hbpm.business.hr;
+
+import kd.bos.common.enums.EnableEnum;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.metadata.IDataEntityProperty;
+import kd.bos.dataentity.metadata.clr.DataEntityPropertyCollection;
+import kd.bos.entity.datamodel.events.PropertyChangedArgs;
+import kd.bos.entity.property.BasedataProp;
+import kd.bos.form.ConfirmCallBackListener;
+import kd.bos.form.IFormView;
+import kd.bos.form.MessageBoxOptions;
+import kd.bos.form.plugin.IFormPlugin;
+import kd.bos.orm.ORM;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.hr.hbp.common.util.HRStringUtils;
+import kd.hr.homs.business.utils.PatternUtil;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+
+import java.util.Map;
+
+/**
+ *
+ * @entity:
+ * @author: jtd
+ * @date: 2025/12/24 22:05
+ */
+public class PositionBillPropertyChangedService extends PositionBillBaseService {
+    private IFormPlugin closeCallBackPlugin;
+    private final Map<String, Map<?, DynamicObject>> baseDataCacheMap;
+
+    public IFormPlugin getCloseCallBackPlugin() {
+        return closeCallBackPlugin;
+    }
+
+    public void setCloseCallBackPlugin(IFormPlugin closeCallBackPlugin) {
+        this.closeCallBackPlugin = closeCallBackPlugin;
+    }
+
+    public PositionBillPropertyChangedService(IFormView view, Map<String, Map<?, DynamicObject>> baseDataCacheMap) {
+        super(view);
+        this.baseDataCacheMap = baseDataCacheMap;
+    }
+
+    public void propertyChanged(PropertyChangedArgs changedArgs) {
+        if (!HRStringUtils.equals(EnableEnum.YES.getCode(), getModel().getContextVariable("entryimport"))) {
+            IDataEntityProperty property = changedArgs.getProperty();
+            int rowIndex = changedArgs.getChangeSet()[0].getRowIndex();
+            String fieldKey = property.getName();
+            String suffix = getSuffixByFieldKey(fieldKey);
+            String entryName = String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, suffix);
+            Object objectNew = changedArgs.getChangeSet()[0].getNewValue();
+            Object objectOld = changedArgs.getChangeSet()[0].getOldValue();
+            if (fieldKey.equals(String.join("_", PositionBillConstant.NCKD_POSITION, suffix))) {
+                if (objectOld == null) {
+                    entrySelectF7Change(property, suffix, rowIndex);
+                } else if (objectNew != null) {
+                    showConfirmByOldValue(changedArgs, suffix, rowIndex);
+                }
+            }
+        }
+
+    }
+
+    private void entrySelectF7Change(IDataEntityProperty property, String suffix, int row) {
+        DataEntityPropertyCollection entryEntityInfo = getModel().getDataEntity(true).getDynamicObjectCollection(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, suffix)).getDynamicObjectType().getProperties();
+        // 分录要转换的键值
+        Map<String, String> posBillTransKeyMap = PositionBillServiceHelper.getTransKeyMap(PositionBillConstant.NCKD_POSBILL_TRANSKEY_ENTITY);
+        // 岗位要转换的键值
+        Map<String, String> positionTransKeyMap = PositionBillServiceHelper.getTransKeyMap(PositionBillConstant.NCKD_POSITION_TRANSKEY_ENTITY);
+
+        StringBuilder selectSqlBuilder = new StringBuilder();
+        for(IDataEntityProperty iDataEntityProperty : entryEntityInfo) {
+            if (PatternUtil.isExProperty(iDataEntityProperty.getName())) {
+                String selectName = iDataEntityProperty.getName().substring(suffix.length() + 1);
+                if (posBillTransKeyMap.containsKey(selectName)) {
+                    selectSqlBuilder.append(",").append(posBillTransKeyMap.get(selectName));
+                } else if (positionTransKeyMap.containsKey(selectName)) {
+                    selectSqlBuilder.append(",").append(positionTransKeyMap.get(selectName));
+                } else {
+                    selectSqlBuilder.append(",").append(selectName);
+                }
+            }
+        }
+
+        BasedataProp basedataProp = (BasedataProp) property;
+        String baseEntityId = basedataProp.getBaseEntityId();
+        Map<?, DynamicObject> dyMap = baseDataCacheMap.get(baseEntityId);
+        String lineSuffix = "_"+suffix;
+        DynamicObject entryEntityDyn = PositionBillServiceHelper.getFocusEntry(suffix, getView(), row);
+        DynamicObject position = null;
+        long positionId = entryEntityDyn.getLong(String.join(".", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ID_KEY));
+        if (dyMap != null) {
+            position = dyMap.get(positionId);
+        }
+
+        // 从数据库获取岗位数据
+        if (position == null) {
+            HRBaseServiceHelper helper = new HRBaseServiceHelper(PositionBillConstant.HBPM_POSITIONHR);
+            QFilter filter = new QFilter(PositionBillConstant.ID_KEY, QCP.equals, positionId);
+            position = helper.loadOne(selectSqlBuilder.toString(), filter.toArray());
+        }
+
+        if (position != null) {
+            long entryId = ORM.create().genLongId(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
+            entryEntityDyn.set(PositionBillConstant.ID_KEY, entryId);
+
+            for(IDataEntityProperty iDataEntityProperty : entryEntityInfo) {
+                if (PatternUtil.isExProperty(iDataEntityProperty.getName())) {
+                    entryEntityDyn.set(iDataEntityProperty.getName(), position.get(iDataEntityProperty.getName().substring(suffix.length() + 1)));
+                }
+            }
+
+            //setChangeScene(prefixLine, entryEntityDyn, row);
+            getView().updateView(PositionBillConstant.NCKD_ENTRYENTITY+lineSuffix);
+        }
+
+    }
+
+    private void showConfirmByOldValue(PropertyChangedArgs e, String suffix, int rowIndex) {
+        DynamicObject position = (DynamicObject) e.getChangeSet()[0].getOldValue();
+        Long positionOld = position != null ? position.getLong(PositionBillConstant.ID_KEY) : null;
+        getView().getPageCache().put("positionOld", positionOld == null ? "" : String.valueOf(positionOld));
+        getView().getPageCache().put("positionRow", String.valueOf(rowIndex));
+        ConfirmCallBackListener confirmCallBackListener = new ConfirmCallBackListener("select_position_" + suffix, getCloseCallBackPlugin());
+        getView().showConfirm("切换岗位后,当前已修改的内容将会丢失,是否继续?", MessageBoxOptions.OKCancel, confirmCallBackListener);
+    }
+
+    private String getSuffixByFieldKey(String fieldKey) {
+        int charIndex = fieldKey.lastIndexOf("_");
+        String suffix = "";
+        if (charIndex != -1) {
+            suffix = fieldKey.substring(charIndex+1);
+        }
+
+        return suffix;
+    }
+}

+ 128 - 88
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/PositionBillServiceHelper.java

@@ -4,24 +4,30 @@ import com.kingdee.util.StringUtils;
 import kd.bos.bill.BillShowParameter;
 import kd.bos.bill.OperationStatus;
 import kd.bos.common.enums.EnableEnum;
+import kd.bos.dataentity.OperateOption;
 import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.serialization.SerializationUtils;
 import kd.bos.entity.constant.StatusEnum;
 import kd.bos.entity.datamodel.IDataModel;
+import kd.bos.entity.operate.OperateOptionConst;
+import kd.bos.entity.operate.result.OperationResult;
 import kd.bos.form.CloseCallBack;
 import kd.bos.form.IFormView;
 import kd.bos.form.ShowType;
 import kd.bos.form.control.EntryGrid;
+import kd.bos.list.ListShowParameter;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 import kd.bos.servicehelper.MetadataServiceHelper;
+import kd.bos.servicehelper.operation.OperationServiceHelper;
 import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
 import kd.hr.hbp.common.constants.history.HisModelDataStatusEnum;
-import kd.hr.hbp.common.model.history.param.HisDeleteParam;
 import kd.hr.hbp.common.util.HRDateTimeUtils;
 import kd.hr.hbp.common.util.HRDynamicObjectUtils;
 import kd.hr.hbp.common.util.HRObjectUtils;
 import kd.hr.hbp.common.util.HRStringUtils;
-import kd.sdk.hr.hbp.business.helper.history.HisModelServiceHelper;
 import kd.sdk.hr.hdm.common.enums.reg.RegBillStatusEnum;
 import nckd.jxccl.base.common.utils.QueryFieldBuilder;
 import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
@@ -40,6 +46,8 @@ import java.util.stream.Collectors;
  */
 public class PositionBillServiceHelper {
 
+    private static final Log log = LogFactory.getLog(PositionBillServiceHelper.class);
+
     /**
      * 获取分录序号
      * @param iDataModel
@@ -63,7 +71,7 @@ public class PositionBillServiceHelper {
      * @param operation
      * @param pluginName
      */
-    public static void openViewForm(IFormView iFormView, String operation, String pluginName) {
+    public static void openViewForm(IFormView iFormView, String operation, String pluginName, QFilter filter) {
         if (iFormView.getModel().getValue(PositionBillConstant.ORG_KEY) == null) {
             iFormView.showTipNotification("请先填写组织体系管理组织。");
         } else {
@@ -80,26 +88,35 @@ public class PositionBillServiceHelper {
                 }
             }
 
-            BillShowParameter formShowParameter = new BillShowParameter();
+            ListShowParameter listShowParameter = new ListShowParameter();
+            if (filter != null) {// 200
+                listShowParameter.getListFilterParameter().getQFilters().add(filter);
+            }
+
             switch (operation) {
                 case PositionBillConstant.ADD_TAG:
+                    BillShowParameter formShowParameter = new BillShowParameter();
+                    formShowParameter.setCustomParam("position_bsed", iFormView.getModel().getValue(PositionBillConstant.NCKD_EFFDT) == null ? HRDateTimeUtils.getNowDateTime().getTime() : ((Date)iFormView.getModel().getValue(PositionBillConstant.NCKD_EFFDT)).getTime());
                     formShowParameter.setFormId(PositionBillConstant.NCKD_POSBILLENTRYADD_ENTITY);
-                    break;
-                case PositionBillConstant.CHANGE_TAG:
-                    formShowParameter.setFormId(PositionBillConstant.NCKD_POSBILLENTRYCHANGE_ENTITY);
-            }
-            formShowParameter.setCustomParam("position_bsed", iFormView.getModel().getValue(PositionBillConstant.NCKD_EFFDT) == null ? HRDateTimeUtils.getNowDateTime().getTime() : ((Date)iFormView.getModel().getValue(PositionBillConstant.NCKD_EFFDT)).getTime());
-            formShowParameter.getOpenStyle().setShowType(ShowType.Modal);
-            formShowParameter.setCustomParam("billid", iFormView.getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY));
-            formShowParameter.setCustomParam("billBsed", iFormView.getModel().getDataEntity().getDate(PositionBillConstant.NCKD_EFFDT));
-            formShowParameter.setCloseCallBack(new CloseCallBack(pluginName, operation));
-            if (HRStringUtils.equals(iFormView.getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP)) {
-                formShowParameter.setHasRight(true);
+                    formShowParameter.getOpenStyle().setShowType(ShowType.Modal);
+                    formShowParameter.setCustomParam("billid", iFormView.getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY));
+                    formShowParameter.setCustomParam("billBsed", iFormView.getModel().getDataEntity().getDate(PositionBillConstant.NCKD_EFFDT));
+                    formShowParameter.setCloseCallBack(new CloseCallBack(pluginName, operation));
+                    if (HRStringUtils.equals(EnableEnum.NO.getCode(), iFormView.getPageCache().get("isList"))) {
+                        formShowParameter.setCustomParam("parentId", iFormView.getPageCache().get("parentId"));
+                    }
+
+                    if (HRStringUtils.equals(iFormView.getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP)) {
+                        formShowParameter.setHasRight(true);
+                    }
+                    formShowParameter.setCustomParam("org", iFormView.getModel().getDataEntity().getLong(String.join(".", PositionBillConstant.ORG_KEY, PositionBillConstant.ID_KEY)));
+                    int sequence = getEntrySeq(iFormView.getModel(), PositionChangeTypeEnum.ADD.getNumber());
+                    formShowParameter.setCustomParam("sequence", sequence);
+                    //formShowParameter.setCustomParam("OP_VALIDATOR_BILL_ORG_ALL_CHANGE_ORG_KEY", getThisBillAllValidateDataStr(dynamicObject));
+                    //formShowParameter.setCustomParam("OP_VALIDATOR_BILL_ORG_NEW_ORG_NUMBERS_KEY", getThisBillOrgNumbersStr(dynamicObject));
+                    iFormView.showForm(formShowParameter);
+                default:
             }
-            formShowParameter.setCustomParam("org", iFormView.getModel().getDataEntity().getLong(String.join(".", PositionBillConstant.ORG_KEY, PositionBillConstant.ID_KEY)));
-            int sequence = getEntrySeq(iFormView.getModel(), PositionChangeTypeEnum.ADD.getNumber());
-            formShowParameter.setCustomParam("sequence", sequence);
-            iFormView.showForm(formShowParameter);
         }
     }
 
@@ -108,12 +125,29 @@ public class PositionBillServiceHelper {
      * @param positionIdList
      */
     public static void delAddMaster(List<Long> positionIdList) {
-        HisDeleteParam hisDeleteParam = new HisDeleteParam();
-        hisDeleteParam.setEntityNumber(PositionBillConstant.HBPM_POSITIONHR);
-        hisDeleteParam.setDataList(Arrays.asList(HRBaseServiceHelper.create(PositionBillConstant.HBPM_POSITIONHR).loadDynamicObjectArray(positionIdList.toArray())));
-        HisModelServiceHelper.deleteBo(hisDeleteParam);
-        //HRBaseServiceHelper positionHrHelper = new HRBaseServiceHelper(PositionBillConstant.HBPM_POSITIONHR);
-        //positionHrHelper.deleteByFilter(new QFilter[]{new QFilter(PositionBillConstant.ID_KEY, QCP.in, positionIdList)});
+//        HisDeleteParam hisDeleteParam = new HisDeleteParam();
+//        hisDeleteParam.setEntityNumber(PositionBillConstant.HBPM_POSITIONHR);
+//        hisDeleteParam.setDataList(Arrays.asList(HRBaseServiceHelper.create(PositionBillConstant.HBPM_POSITIONHR).loadDynamicObjectArray(positionIdList.toArray())));
+//        HisModelServiceHelper.deleteBo(hisDeleteParam);
+        HRBaseServiceHelper positionHrHelper = new HRBaseServiceHelper(PositionBillConstant.HBPM_POSITIONHR);
+        positionHrHelper.deleteByFilter(new QFilter[]{new QFilter(PositionBillConstant.BOID_KEY, QCP.in, positionIdList)});
+    }
+
+    public static DynamicObject getFocusEntry(String suffix, IFormView view, int row) {
+        EntryGrid entryGrid = view.getControl(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, suffix));
+        if (row == -1) {
+            row = entryGrid.getEntryState().getFocusRow();
+        }
+
+        DynamicObject entryEntityDyn = view.getModel().getDataEntity(true).getDynamicObjectCollection(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, suffix)).get(row);
+        long entityId = entryEntityDyn.getLong(PositionBillConstant.ID_KEY);
+        if (entityId != 0L) {
+            HRBaseServiceHelper serviceHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
+            serviceHelper.deleteOne(entityId);
+            entryEntityDyn.set(PositionBillConstant.ID_KEY, 0L);
+        }
+
+        return entryEntityDyn;
     }
 
     /**
@@ -141,10 +175,9 @@ public class PositionBillServiceHelper {
         return transKeyMap;
     }
 
-
     /**
      * 构建岗位
-     * 用于获取/回收岗位编码
+     * 用于校验岗位数据或获取/回收岗位编码
      * @param addDy
      * @return
      */
@@ -154,7 +187,7 @@ public class PositionBillServiceHelper {
 
     /**
      * 构建岗位
-     * 用于获取/回收岗位编码
+     * 用于校验岗位数据或获取/回收岗位编码
      * @param addDy
      * @param transKeyMap
      * @return
@@ -208,77 +241,63 @@ public class PositionBillServiceHelper {
         return positionDyo;
     }
 
-    public static void entryEntityMore(IDataModel iDataModel, IFormView iFormView, String tag, OperationStatus status, String pluginName) {
-        /*EntryGrid entryEntity = iFormView.getControl(ENTRY_ENTITY_PREFIX + tag);
+    public static void entryEntityMore(IDataModel iDataModel, IFormView iFormView, String tag, OperationStatus status) {
+        EntryGrid entryEntity = iFormView.getControl(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, tag));
         int row = entryEntity.getEntryState().getFocusRow();
-        DynamicObject dynamicObject = iDataModel.getDataEntity(true).getDynamicObjectCollection(ENTRY_ENTITY_PREFIX + tag).get(row);
+        DynamicObject dynamicObject = iDataModel.getDataEntity(true).getDynamicObjectCollection(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, tag)).get(row);
         Map map = HRDynamicObjectUtils.convertDynamicObjectToMap(dynamicObject);
-        long id = dynamicObject.getLong("id");
+        long id = dynamicObject.getLong(PositionBillConstant.ID_KEY);
         BillShowParameter formShowParameter = new BillShowParameter();
-        if ("add".equals(tag)) {
-            formShowParameter.setFormId(PositionBillConstant.NCKD_POSBILLENTRYADD);
-        } else if ("change".equals(tag)) {
-            formShowParameter.setFormId(PositionBillConstant.NCKD_POSBILLENTRYCHANGE);
-        }
+        Object dy = dynamicObject.get(String.join("_", PositionBillConstant.NCKD_POSITION, tag));
+        if (dy == null) {// 1977
+            iFormView.showTipNotification("请先选择岗位。");
+        } else {
+            if (PositionBillConstant.CHANGE_TAG.equals(tag)) {
+                formShowParameter.setFormId(PositionBillConstant.NCKD_POSBILLENTRYCHANGE_ENTITY);
+            }
 
-        HRBaseServiceHelper helper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY);
-        boolean exists = helper.isExists(id);
-        if (exists) {
-            formShowParameter.setPkId(id);
-        }
-        formShowParameter.setStatus(status);
-        formShowParameter.setCustomParam("id", id);
-        formShowParameter.getOpenStyle().setShowType(ShowType.Modal);
-        formShowParameter.setCustomParam("selectObject", SerializationUtils.toJsonString(map));
-        formShowParameter.setCustomParam("billid", iDataModel.getValue(PositionBillConstant.ID_KEY));
-        formShowParameter.setCustomParam("iscard", "isCardFalse");
-        formShowParameter.setCustomParam("org_bsed", iFormView.getModel().getValue(PositionBillConstant.NCKD_EFFDT) == null ? HRDateTimeUtils.getNowDateTime().getTime() : ((Date)iFormView.getModel().getValue(PositionBillConstant.NCKD_EFFDT)).getTime());
-        formShowParameter.setCustomParam("org", iDataModel.getDataEntity().getLong("org.id"));
-        formShowParameter.setCustomParam("billstatus", iDataModel.getDataEntity().get(PositionBillConstant.BILL_STATUS_KEY));
-        int sequence = getEntrySeq(iDataModel, PositionBillConstant.CHANGE_TYPE_MAP.get(tag));
-        formShowParameter.setCustomParam("sequence", sequence);
-        formShowParameter.setCloseCallBack(new CloseCallBack(pluginName, ENTRY_ENTITY_PREFIX + tag));
-        iFormView.showForm(formShowParameter);*/
+            // 获取岗位申请单分录服务
+            HRBaseServiceHelper helper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILLENTRY_ENTITY);
+            boolean exists = helper.isExists(id);
+            if (exists) {
+                formShowParameter.setPkId(id);
+            } else {
+                formShowParameter.setCustomParam("id", id);
+            }
 
-        String entryEntityId = "nckd_entryentity_" + tag;
-        EntryGrid strategyEntryGrid = iFormView.getControl(entryEntityId);
-        int row = strategyEntryGrid.getEntryState().getFocusRow();
-        DynamicObject dynamicObject = iDataModel.getDataEntity(true).getDynamicObjectCollection(entryEntityId).get(row);
-        Long id = dynamicObject.getLong(PositionBillConstant.ID_KEY);
-        BillShowParameter formShowParameter = new BillShowParameter();
-        formShowParameter.setCustomParam("position_bsed", iFormView.getModel().getValue(PositionBillConstant.NCKD_EFFDT) == null ? HRDateTimeUtils.getNowDateTime().getTime() : ((Date)iFormView.getModel().getValue(PositionBillConstant.NCKD_EFFDT)).getTime());
-        if (PositionBillConstant.ADD_TAG.equals(tag)) {
-            formShowParameter.setFormId(PositionBillConstant.NCKD_POSBILLENTRYADD_ENTITY);
-        } else if (PositionBillConstant.CHANGE_TAG.equals(tag)) {
-            formShowParameter.setFormId(PositionBillConstant.NCKD_POSBILLENTRYCHANGE_ENTITY);
-        }
-        formShowParameter.setPkId(id);
-        formShowParameter.setStatus(status);
-        if (HRStringUtils.equals(iFormView.getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP)) {
-            formShowParameter.setHasRight(true);
-        }
+            if (HRStringUtils.equals(iFormView.getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP)) {
+                formShowParameter.setHasRight(true);
+            }
 
-        if (!status.equals(OperationStatus.VIEW)) {
-            formShowParameter.setCloseCallBack(new CloseCallBack(pluginName, tag));
+            formShowParameter.setStatus(status);
+            formShowParameter.setCustomParam("id", id);
+            formShowParameter.getOpenStyle().setShowType(ShowType.Modal);
+            formShowParameter.setCustomParam("selectObject", SerializationUtils.toJsonString(map));
+            formShowParameter.setCustomParam("billid", iDataModel.getValue(PositionBillConstant.ID_KEY));
+            formShowParameter.setCustomParam("positionid", String.valueOf(dynamicObject.getLong(String.join("_", PositionBillConstant.NCKD_POSITION, tag))));
+            formShowParameter.setCustomParam("iscard", "isCardFalse");
+            formShowParameter.setCustomParam("position_bsed", iDataModel.getValue(PositionBillConstant.NCKD_EFFDT) == null ? HRDateTimeUtils.getNowDateTime().getTime() : ((Date) iDataModel.getValue(PositionBillConstant.NCKD_EFFDT)).getTime());
+            formShowParameter.setCustomParam("org", iDataModel.getDataEntity().getLong(String.join(".", PositionBillConstant.ORG_KEY, PositionBillConstant.ID_KEY)));
+            formShowParameter.setCustomParam("billstatus", iDataModel.getDataEntity().get(PositionBillConstant.BILL_STATUS_KEY));
+            int sequence = getEntrySeq(iFormView.getModel(), PositionChangeTypeEnum.getNumberByTag(tag));
+            formShowParameter.setCustomParam("sequence", sequence);
+            formShowParameter.setCloseCallBack(new CloseCallBack("nckd.jxccl.hrmp.hbpm.plugin.form.hr.PositionBillFormPlugin", tag));
+            //formShowParameter.setCustomParam("OP_VALIDATOR_BILL_ORG_ALL_CHANGE_ORG_KEY", getThisBillAllValidateDataStr(iDataModel.getDataEntity(true)));
+            //formShowParameter.setCustomParam("OP_VALIDATOR_BILL_ORG_NEW_ORG_NUMBERS_KEY", getThisBillOrgNumbersStr(iDataModel.getDataEntity(true)));
+            iFormView.showForm(formShowParameter);
         }
-        formShowParameter.getOpenStyle().setShowType(ShowType.Modal);
-        iFormView.showForm(formShowParameter);
     }
 
-    public static void openEditPage(IDataModel iDataModel, IFormView iFormView, String tag, OperationStatus status) {
-        String entryEntityKey = String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, tag);
-        EntryGrid strategyEntryGrid = iFormView.getControl(entryEntityKey);
+    public static void openEditAddPage(OperationStatus status, IDataModel iDataModel, IFormView iFormView) {
+        EntryGrid strategyEntryGrid = iFormView.getControl(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY);
         int row = strategyEntryGrid.getEntryState().getFocusRow();
-        DynamicObject dynamicObject = iDataModel.getDataEntity(true).getDynamicObjectCollection(entryEntityKey).get(row);
-        Long id = dynamicObject.getLong(PositionBillConstant.ID_KEY);
+        DynamicObject addDy = iDataModel.getDataEntity(true).getDynamicObjectCollection(PositionBillConstant.NCKD_ENTRYENTITY_ADD_KEY).get(row);
+        Long adddyId = addDy.getLong(PositionBillConstant.ID_KEY);
+        Map map = HRDynamicObjectUtils.convertDynamicObjectToMap(addDy);
         BillShowParameter formShowParameter = new BillShowParameter();
-        if (PositionBillConstant.ADD_TAG.equals(tag)) {
-            formShowParameter.setFormId(PositionBillConstant.NCKD_POSBILLENTRYADD_ENTITY);
-        } else if (PositionBillConstant.CHANGE_TAG.equals(tag)) {
-            formShowParameter.setFormId(PositionBillConstant.NCKD_POSBILLENTRYCHANGE_ENTITY);
-        }
+        formShowParameter.setFormId(PositionBillConstant.NCKD_POSBILLENTRYADD_ENTITY);
         formShowParameter.setCustomParam("position_bsed", iDataModel.getValue(PositionBillConstant.NCKD_EFFDT) == null ? HRDateTimeUtils.getNowDateTime().getTime() : ((Date) iDataModel.getValue(PositionBillConstant.NCKD_EFFDT)).getTime());
-        formShowParameter.setPkId(id);
+        formShowParameter.setPkId(adddyId);
         formShowParameter.setStatus(status);
         formShowParameter.setCustomParam("billid", iDataModel.getDataEntity().getLong(PositionBillConstant.ID_KEY));
         if (HRStringUtils.equals(iFormView.getFormShowParameter().getAppId(), PositionBillConstant.WFTASK_APP)) {
@@ -286,10 +305,31 @@ public class PositionBillServiceHelper {
         }
 
         if (!status.equals(OperationStatus.VIEW)) {
-            formShowParameter.setCloseCallBack(new CloseCallBack("nckd.jxccl.hrmp.hbpm.plugin.form.hr.PositionBillFormPlugin", tag));
+            formShowParameter.setCloseCallBack(new CloseCallBack("nckd.jxccl.hrmp.hbpm.plugin.form.hr.PositionBillFormPlugin", PositionBillConstant.ADD_TAG));
         }
 
+        formShowParameter.setCustomParam("selectObject", SerializationUtils.toJsonString(map));
         formShowParameter.getOpenStyle().setShowType(ShowType.Modal);
+        //formShowParameter.setCustomParam("OP_VALIDATOR_BILL_ORG_ALL_CHANGE_ORG_KEY", getThisBillAllValidateDataStr(dynamicObject));
+        //formShowParameter.setCustomParam("OP_VALIDATOR_BILL_ORG_NEW_ORG_NUMBERS_KEY", getThisBillOrgNumbersStr(dynamicObject));
         iFormView.showForm(formShowParameter);
     }
+
+    public static OperationResult executeOperateOnlyValidate(String operationKey, DynamicObject[] positionDys, OperateOption option) {
+        OperateOption operateOption = option;
+        if (option == null) {
+            operateOption = OperateOption.create();
+        }
+
+        operateOption.setVariableValue(OperateOptionConst.ISHASRIGHT, Boolean.TRUE.toString());
+        operateOption.setVariableValue(OperateOptionConst.ONLY_VALIDATE, Boolean.TRUE.toString());
+
+        try {
+            return OperationServiceHelper.executeOperate(operationKey, PositionBillConstant.HBPM_POSITIONHR, positionDys, operateOption);
+        } catch (Exception ex) {
+            log.error("executeOperate  error", ex);
+            throw ex;
+        }
+    }
+
 }

+ 79 - 6
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/PosBillEntryAddFormPlugin.java

@@ -3,11 +3,15 @@ package nckd.jxccl.hrmp.hbpm.plugin.form.hr;
 import kd.bos.common.enums.EnableEnum;
 import kd.bos.dataentity.entity.DataEntityState;
 import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
 import kd.bos.dataentity.metadata.dynamicobject.DynamicProperty;
+import kd.bos.dataentity.serialization.SerializationUtils;
 import kd.bos.dataentity.utils.ObjectUtils;
 import kd.bos.dataentity.utils.StringUtils;
 import kd.bos.entity.datamodel.events.PropertyChangedArgs;
 import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.entity.property.BasedataProp;
+import kd.bos.entity.property.MulBasedataProp;
 import kd.bos.form.ConfirmCallBackListener;
 import kd.bos.form.ConfirmTypes;
 import kd.bos.form.IPageCache;
@@ -24,13 +28,17 @@ import kd.bos.servicehelper.coderule.CodeRuleServiceHelper;
 import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
 import kd.hr.hbp.common.util.HRObjectUtils;
 import kd.hr.hbp.common.util.HRStringUtils;
+import kd.hr.homs.business.utils.PatternUtil;
 import nckd.jxccl.hrmp.hbpm.business.hr.PositionBillServiceHelper;
 import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
 
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.EventObject;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.stream.Stream;
 
 /**
  * 岗位申请-新增岗位表单插件
@@ -53,8 +61,9 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
     public void beforeBindData(EventObject e) {
         super.beforeBindData(e);
 
-        // 如果是新增
-        long entityId = getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY);
+        getPageCache().put("paramsChangeSetNumber", "false");
+        DynamicObject positionDy = getModel().getDataEntity();
+        long entityId = positionDy.getLong(PositionBillConstant.ID_KEY);
         if (entityId == 0L) {
             Long billId = getView().getFormShowParameter().getCustomParam("billid");
             getModel().setValue(PositionBillConstant.NCKD_BILLID, billId);
@@ -62,10 +71,15 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
         }
 
         // 设置生效时间
-        long positionBsedTime = getView().getFormShowParameter().getCustomParam("position_bsed");
-        getModel().setValue(PositionBillConstant.NCKD_BSED, new Date(positionBsedTime));
-        getModel().setValue(PositionBillConstant.ENABLE, EnableEnum.YES.getCode());
+        Object positionBsedStr = getView().getFormShowParameter().getCustomParam("position_bsed");
+        if (positionBsedStr != null) {
+            long positionBsedTime = Long.parseLong(positionBsedStr.toString());
+            getModel().setValue(PositionBillConstant.NCKD_BSED, new Date(positionBsedTime));
+        } else {
+            getModel().setValue(PositionBillConstant.NCKD_BSED, new Date());
+        }
 
+        getModel().setValue(PositionBillConstant.ENABLE, EnableEnum.YES.getCode());
         // 设置岗位编码
         if (HRStringUtils.isEmpty(getModel().getDataEntity().getString(PositionBillConstant.NUMBER_KEY))) {
             setPositionNumber(PositionBillServiceHelper.getPositionHrDy(getModel().getDataEntity()), true);
@@ -73,6 +87,7 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
             setPositionNumberEnable();
         }
 
+        getPageCache().put("paramsChangeSetNumber", "true");
         // 新增的时候生成岗位ID
         String positionIdKey = String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ID_KEY);
         long positionId = getModel().getDataEntity().getLong(positionIdKey);
@@ -80,6 +95,8 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
             positionId = ORM.create().genLongId(PositionBillConstant.HBPM_POSITIONHR);
             getModel().setValue(positionIdKey, positionId);
         }
+
+        getPageCache().put("masterOrg", String.valueOf(positionDy.getLong(String.join(".", PositionBillConstant.NCKD_ORG, PositionBillConstant.ID_KEY))));
     }
 
     private void setPositionNumberEnable() {
@@ -196,10 +213,66 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
             getView().getPageCache().put("beforeParentPositionId", parentPosition.getString(PositionBillConstant.ID_KEY));
         }
 
-        // 取消变更提示
+        Object selectObject = getView().getFormShowParameter().getCustomParam("selectObject");
+        if (selectObject != null) {
+            Map<String, Object> map = SerializationUtils.fromJsonString(selectObject.toString(), Map.class);
+            Map<String, Object> noPrefixMap = map.entrySet().stream().collect(HashMap::new, (m, v) -> m.put((v.getKey()).replace("_"+PositionBillConstant.ADD_TAG, ""), v.getValue()), HashMap::putAll);
+            List<String> props = new ArrayList();
+
+            for(String prop : noPrefixMap.keySet()) {
+                if (PatternUtil.isExProperty(prop)) {
+                    props.add(prop);
+                }
+            }
+
+            // 获取需要转换的键值
+            Map<String, String> transKeyMap = PositionBillServiceHelper.getTransKeyMap(PositionBillConstant.NCKD_POSBILL_TRANSKEY_ENTITY);
+            transKeyMap.forEach((key, value) -> {
+                noPrefixMap.put(value, noPrefixMap.get(key));
+                noPrefixMap.remove(key);
+                props.remove(key);
+            });
+
+            Stream<String> fields = Stream.of(props.toArray(new String[0]));
+            fields.forEach((s) -> setValue(s, noPrefixMap.get(s)));
+        }
+
+        // 取消数据标哥标识
         getModel().setDataChanged(false);
     }
 
+    private void setValue(String key, Object value) {
+        if (getModel().getProperty(key) != null) {
+            Class<?> propertyType = getModel().getDataEntityType().getProperty(key).getPropertyType();
+            DynamicProperty dynamicProperty = getModel().getDataEntityType().getProperty(key);
+            if (value != null) {
+                if (propertyType.equals(DynamicObject.class) && dynamicProperty instanceof BasedataProp) {
+                    // 岗位特殊处理
+                    Object id = PositionBillConstant.NCKD_POSITION.equals(key) ? value : ((Map)value).get(PositionBillConstant.ID_KEY);
+                    if (id != null && !HRStringUtils.equals(value.toString(), "0")) {
+                        getModel().setValue(key, id);
+                    }
+                } else if (propertyType.equals(DynamicObject.class) && dynamicProperty instanceof MulBasedataProp && value instanceof List) {
+                    MulBasedataProp property = (MulBasedataProp) getModel().getDataEntityType().getProperty(key);
+                    DynamicObjectCollection dynamicObjectCollection = new DynamicObjectCollection();
+                        HRBaseServiceHelper serviceHelper = new HRBaseServiceHelper(property.getBaseEntityId());
+                    ((List)value).forEach((map) -> {
+                        DynamicObject dy = new DynamicObject(property.getDynamicCollectionItemPropertyType());
+                        dy.set("fbasedataid_id", ((Map)map).get("fbasedataid_id"));
+                        DynamicObject emptyDynamicObject = serviceHelper.generateEmptyDynamicObject();
+                        emptyDynamicObject.set(PositionBillConstant.ID_KEY, ((Map)map).get("fbasedataid_id"));
+                        dy.set("fbasedataid", emptyDynamicObject);
+                        dynamicObjectCollection.add(dy);
+                    });
+                    getModel().setValue(key, !dynamicObjectCollection.isEmpty() ? dynamicObjectCollection : null);
+                } else {
+                    getModel().setValue(key, value);
+                }
+
+            }
+        }
+    }
+
     @Override
     public void propertyChanged(PropertyChangedArgs changedArgs) {
         String fieldKey = changedArgs.getProperty().getName();

+ 15 - 15
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/PositionBillEntryFormPlugin.java

@@ -142,14 +142,16 @@ public class PositionBillEntryFormPlugin extends AbstractFormPlugin implements B
         if (HRStringUtils.equals(operateKey, PositionBillConstant.SAVE_OP) || HRStringUtils.equals(operateKey, PositionBillConstant.SAVE_AND_NEW_OP)) {
 
             IFormView parentView = getBillFormView(getView());
-            Map<String, Map<String, ILocaleString>> parentBoIdToChildNameMap = Maps.newHashMapWithExpectedSize(16);
+            // 组织下同级岗位名称数据 {orgBoid:{positionId:positionName}}
+            Map<String, Map<String, ILocaleString>> orgBoIdToSiblingNameMap = Maps.newHashMapWithExpectedSize(16);
+            // 岗位编码数据 {positionId:number}
             Map<String, String> numberMap = Maps.newHashMapWithExpectedSize(16);
             if (parentView != null) {
-                setValidateData(parentView, PositionBillConstant.ADD_TAG, parentBoIdToChildNameMap, numberMap);
-                setValidateData(parentView, PositionBillConstant.CHANGE_TAG, parentBoIdToChildNameMap, numberMap);
+                setValidateData(parentView, PositionBillConstant.ADD_TAG, orgBoIdToSiblingNameMap, numberMap);
+                setValidateData(parentView, PositionBillConstant.CHANGE_TAG, orgBoIdToSiblingNameMap, numberMap);
             }
 
-            operate.getOption().setVariableValue("OP_BILL_CHILD_NAMES_MAP", JSONObject.toJSONString(parentBoIdToChildNameMap));
+            operate.getOption().setVariableValue("OP_BILL_SIBLING_NAMES_MAP", JSONObject.toJSONString(orgBoIdToSiblingNameMap));
             operate.getOption().setVariableValue("OP_BILL_NUMBER_MAP", JSONObject.toJSONString(numberMap));
             operate.getOption().setVariableValue("OP_VALIDATOR_BILL_POSITION_ALL_CHANGE_POSITION_KEY", getView().getFormShowParameter().getCustomParam("OP_VALIDATOR_BILL_POSITION_ALL_CHANGE_POSITION_KEY"));
         }
@@ -165,9 +167,9 @@ public class PositionBillEntryFormPlugin extends AbstractFormPlugin implements B
     }
 
 
-    private void setValidateData(IFormView parentView, String suffix, Map<String, Map<String, ILocaleString>> parentBoIdToChildNameMap, Map<String, String> numberMap) {
+    private void setValidateData(IFormView parentView, String suffix, Map<String, Map<String, ILocaleString>> orgBoIdToSiblingNameMap, Map<String, String> numberMap) {
         for(DynamicObject addEntryDy : parentView.getModel().getDataEntity(true).getDynamicObjectCollection(String.join("_", PositionBillConstant.NCKD_ENTRYENTITY, suffix))) {
-            DynamicObject parentPositionDy = addEntryDy.getDynamicObject(String.join("_", PositionBillConstant.NCKD_PARENT, suffix));
+            DynamicObject adminOrgDy = addEntryDy.getDynamicObject(String.join("_", PositionBillConstant.NCKD_ADMINORG, suffix));
             String positionKey = String.join("_", PositionBillConstant.NCKD_POSITION_KEY, suffix);
             String positionIdKey = String.join(".", positionKey, PositionBillConstant.ID_KEY);
             if (PositionBillConstant.ADD_TAG.equals(suffix)) {
@@ -175,17 +177,15 @@ public class PositionBillEntryFormPlugin extends AbstractFormPlugin implements B
             }
 
             long positionId = addEntryDy.getLong(positionIdKey);
-            if (parentPositionDy != null) {
-                long boId = parentPositionDy.getLong(PositionBillConstant.BOID_KEY);
-                Map<String, ILocaleString> childNameMap = parentBoIdToChildNameMap.get(String.valueOf(boId));
-                if (childNameMap == null) {
-                    childNameMap = Maps.newHashMapWithExpectedSize(16);
-                }
-
-                childNameMap.put(String.valueOf(positionId), addEntryDy.getLocaleString(String.join("_", PositionBillConstant.NCKD_NAME_KEY, suffix)));
-                parentBoIdToChildNameMap.put(String.valueOf(boId), childNameMap);
+            long boId = adminOrgDy.getLong(PositionBillConstant.BOID_KEY);
+            Map<String, ILocaleString> siblingNameMap = orgBoIdToSiblingNameMap.get(String.valueOf(boId));
+            if (siblingNameMap == null) {
+                siblingNameMap = Maps.newHashMapWithExpectedSize(16);
             }
 
+            siblingNameMap.put(String.valueOf(positionId), addEntryDy.getLocaleString(String.join("_", PositionBillConstant.NCKD_NAME_KEY, suffix)));
+            orgBoIdToSiblingNameMap.put(String.valueOf(boId), siblingNameMap);
+
             numberMap.put(String.valueOf(positionId), addEntryDy.getString(String.join("_", PositionBillConstant.NCKD_NUMBER_KEY, suffix)));
         }
 

+ 22 - 5
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/form/hr/PositionBillFormPlugin.java

@@ -5,6 +5,7 @@ import kd.bos.bill.BillShowParameter;
 import kd.bos.bill.OperationStatus;
 import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.entity.BillEntityType;
+import kd.bos.entity.datamodel.events.PropertyChangedArgs;
 import kd.bos.entity.operate.result.OperationResult;
 import kd.bos.form.ConfirmCallBackListener;
 import kd.bos.form.ConfirmTypes;
@@ -14,20 +15,25 @@ import kd.bos.form.events.AfterDoOperationEventArgs;
 import kd.bos.form.events.ClosedCallBackEvent;
 import kd.bos.form.events.MessageBoxClosedEvent;
 import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
 import kd.bos.mvc.bill.BillView;
 import kd.bos.orm.ORM;
 import kd.bos.orm.query.QCP;
 import kd.bos.orm.query.QFilter;
 import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
 import kd.hr.hbp.common.util.HRStringUtils;
+import kd.hr.hbp.common.util.concurrent.NullableConcurrentHashMap;
 import kd.hr.homs.business.domain.batchbill.repository.AdminOrgBatchChgHelper;
 import kd.sdk.hr.hdm.common.enums.reg.RegBillStatusEnum;
 import nckd.jxccl.hrmp.hbpm.business.hr.PositionBillClosedCallBackService;
 import nckd.jxccl.hrmp.hbpm.business.hr.PositionBillConfirmCallBackService;
+import nckd.jxccl.hrmp.hbpm.business.hr.PositionBillPropertyChangedService;
 import nckd.jxccl.hrmp.hbpm.business.hr.PositionBillServiceHelper;
 import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
 
 import java.util.EventObject;
+import java.util.Map;
 import java.util.Objects;
 
 /**
@@ -36,6 +42,8 @@ import java.util.Objects;
  * @date: 2025-10-25 13:38
  */
 public class PositionBillFormPlugin extends AbstractFormPlugin {
+    private static final Log LOG = LogFactory.getLog(PositionBillFormPlugin.class);
+    private final Map<String, Map<?, DynamicObject>> baseDataCacheMap = new NullableConcurrentHashMap(3);
 
     @Override
     public void afterBindData(EventObject e) {
@@ -57,6 +65,15 @@ public class PositionBillFormPlugin extends AbstractFormPlugin {
         }
     }
 
+    @Override
+    public void propertyChanged(PropertyChangedArgs e) {
+        super.propertyChanged(e);
+
+        PositionBillPropertyChangedService propertyChangedService = new PositionBillPropertyChangedService(getView(), baseDataCacheMap);
+        propertyChangedService.setCloseCallBackPlugin(this);
+        propertyChangedService.propertyChanged(e);
+    }
+
     @Override
     public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
         super.afterDoOperation(afterDoOperationEventArgs);
@@ -79,13 +96,13 @@ public class PositionBillFormPlugin extends AbstractFormPlugin {
         String opKey = afterDoOperationEventArgs.getOperateKey();
         switch (opKey) {
             case PositionBillConstant.NEWENTRY_ADD_OP:
-                PositionBillServiceHelper.openViewForm(getView(), PositionBillConstant.ADD_TAG, getPluginName());
-                break;
-            case PositionBillConstant.NEWENTRY_CHANGE_OP:
-                PositionBillServiceHelper.openViewForm(getView(), PositionBillConstant.CHANGE_TAG, getPluginName());
+                PositionBillServiceHelper.openViewForm(getView(), PositionBillConstant.ADD_TAG, getPluginName(), null);
                 break;
             case PositionBillConstant.EDIT_ADD_OP:
-                PositionBillServiceHelper.openEditPage(getModel(), getView(), PositionBillConstant.ADD_TAG, status);
+                PositionBillServiceHelper.openEditAddPage(status, getModel(), getView());
+                break;
+            case PositionBillConstant.EDIT_CHANGE_OP:
+                PositionBillServiceHelper.entryEntityMore(getModel(), getView(), PositionBillConstant.CHANGE_TAG, status);
                 break;
             case PositionBillConstant.DELETE_ROWS_ADD_OP:
             case PositionBillConstant.DELETE_ROWS_CHANGE_OP:

+ 14 - 155
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/PosBillEntryAddSaveOpPlugin.java

@@ -1,173 +1,32 @@
 package nckd.jxccl.hrmp.hbpm.plugin.operate.hr;
 
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
 import kd.bos.dataentity.OperateOption;
-import kd.bos.dataentity.entity.DynamicObject;
-import kd.bos.entity.constant.StatusEnum;
 import kd.bos.entity.operate.OperateOptionConst;
-import kd.bos.entity.operate.result.IOperateInfo;
-import kd.bos.entity.operate.result.OperationResult;
-import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
-import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
-import kd.bos.exception.KDBizException;
-import kd.bos.orm.query.QCP;
-import kd.bos.orm.query.QFilter;
-import kd.bos.service.operation.OperationServiceImpl;
-import kd.bos.servicehelper.coderule.CodeRuleServiceHelper;
-import kd.bos.servicehelper.operation.SaveServiceHelper;
-import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
-import kd.hr.hbp.common.constants.history.HisModelDataStatusEnum;
-import kd.hr.hbp.common.util.HRStringUtils;
-import nckd.jxccl.hrmp.hbpm.business.hr.PositionBillServiceHelper;
+import kd.bos.entity.plugin.AddValidatorsEventArgs;
 import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
-
-import java.util.List;
-import java.util.Map;
+import nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator.PositionAddSaveValidator;
 
 /**
- * 岗位申请-新增岗位保存OP
+ * 岗位申请-岗位新设保存操作插件
  * @entity: nckd_posbillentryadd
  * @author: jtd
- * @date: 2025-11-08 15:30
+ * @date: 2025/12/18 09:57
  */
-public class PosBillEntryAddSaveOpPlugin extends AbstractOperationServicePlugIn {
-
-    private static final String PAGECACHE_KEY_BILLNO_FROM_INIT_VALUE_OF_OPERATION = "coderule_billno_from_init_value_of_operation";
+public class PosBillEntryAddSaveOpPlugin extends PositionBillEntrySaveOpPlugin {
 
     @Override
-    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
-        super.beginOperationTransaction(e);
-
-        DynamicObject[] positionEntities = e.getDataEntities();
-        if (positionEntities.length == 0) {
-            return;
-        }
+    public void onAddValidators(AddValidatorsEventArgs e) {
+        super.onAddValidators(e);
 
-        // 获取岗位和上级岗位的业务ID
-        List<Long> positionBoIds = Lists.newArrayListWithExpectedSize(positionEntities.length);
-        // 获取 行政组织业务ID
-        List<Long> adminorgBoIds = Lists.newArrayListWithExpectedSize(positionEntities.length);
-        // 岗位ID标识
-        String positionIdKey = String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ID_KEY);
-        for (DynamicObject positionEntity : positionEntities) {
-            positionBoIds.add(positionEntity.getLong(positionIdKey));
-            adminorgBoIds.add(positionEntity.getLong(PositionBillConstant.NCKD_ADMINORGBOID_KEY));
-            // 获取上级岗位
-            DynamicObject parentPositionVersionDy = positionEntity.getDynamicObject(PositionBillConstant.NCKD_PARENT);
-            if (parentPositionVersionDy != null) {
-                long parentOrgBoId = parentPositionVersionDy.getLong(PositionBillConstant.BOID_KEY);
-                positionBoIds.add(parentOrgBoId);
-            }
-        }
-
-        // 根据岗位ID从数据库中获取岗位信息
-        HRBaseServiceHelper positionServiceHelper = HRBaseServiceHelper.create(PositionBillConstant.HBPM_POSITIONHR);
-        DynamicObject[] positionDyos = positionServiceHelper.loadDynamicObjectArray(new QFilter[]{new QFilter(PositionBillConstant.ID_KEY, QCP.in, positionBoIds)});
-        Map<Long, DynamicObject> dbPositionMap = Maps.newHashMapWithExpectedSize(positionDyos.length);
-        for (DynamicObject positionDyo : positionDyos) {
-            dbPositionMap.put(positionDyo.getLong(PositionBillConstant.ID_KEY), positionDyo);
-        }
-        // 根据组织BOID从数据库中获取组织信息
-        DynamicObject[] adminOrgDyos = HRBaseServiceHelper.create(PositionBillConstant.ADMINORG_ENTITYID).loadDynamicObjectArray(new QFilter[]{new QFilter(PositionBillConstant.ID_KEY, QCP.in, adminorgBoIds)});
-        Map<Long, DynamicObject> dbAdminOrgMap = Maps.newHashMapWithExpectedSize(adminOrgDyos.length);
-        for (DynamicObject adminOrgDyo : adminOrgDyos) {
-            dbAdminOrgMap.put(adminOrgDyo.getLong(PositionBillConstant.BOID_KEY), adminOrgDyo);
-        }
-        // 构建岗位对象
-        OperateOption operateOption = OperateOption.create();
-        List<DynamicObject> positionList = Lists.newArrayListWithExpectedSize(positionEntities.length);
-        // 需要转换的键值
-        Map<String, String> transKeyMap = PositionBillServiceHelper.getTransKeyMap(PositionBillConstant.NCKD_POSITION_TRANSKEY_ENTITY);
-
-        for (DynamicObject positionEntity : positionEntities) {
-            long positionId = positionEntity.getLong(positionIdKey);
-            // 如果数据库存在则用数据库的岗位对象
-            DynamicObject positionDyo = dbPositionMap.get(positionId);
-            // 不存在则创建一个
-            if (positionDyo == null) {
-                positionDyo = positionServiceHelper.generateEmptyDynamicObject();
-            }
-            // 将表单中的信息赋值到岗位信息中
-            PositionBillServiceHelper.getPositionHrDy(positionEntity, positionDyo, transKeyMap);// 调用保存会自动设置
-            // 设置ID为岗位ID
-            positionDyo.set(PositionBillConstant.ID_KEY, positionId);
-            // 设置 是否标准岗位
-            positionDyo.set(PositionBillConstant.ISSTANDARDPOS_KEY, "9");// 暂存的数据固定为9,由于标品岗位一定会生成历史版本数据,所以为了能够正常的多次保存且不显示在岗位中需要这样做
-            // 设置 行政组织
-            positionDyo.set(PositionBillConstant.ADMINORG, dbAdminOrgMap.get(positionEntity.getLong(PositionBillConstant.NCKD_ADMINORGBOID_KEY)));
-            // 设置 上级岗位
-            DynamicObject parentPositionVersionDy = positionEntity.getDynamicObject(PositionBillConstant.NCKD_PARENT);
-            if (parentPositionVersionDy != null) {
-                positionDyo.set(PositionBillConstant.PARENT_KEY, dbPositionMap.get(parentPositionVersionDy.getLong(PositionBillConstant.BOID_KEY)));
-            } else {
-                positionDyo.set(PositionBillConstant.PARENT_KEY, null);
-            }
-            positionList.add(positionDyo);
-            String number = positionDyo.getString(PositionBillConstant.NUMBER_KEY);
-            // 设置 编码为已变更
-            if (HRStringUtils.isNotEmpty(number)) {
-                operateOption.setVariableValue(positionId + "coderule_billno_from_initAbstractCodeRule", PAGECACHE_KEY_BILLNO_FROM_INIT_VALUE_OF_OPERATION);
-            }
-        }
-        // 设置岗位临时新增标识
-        //operateOption.setVariableValue("OP_ADD_POSITION_TEMP_TAG", Boolean.TRUE.toString());
-        // 跳过功能权限校验
-        operateOption.setVariableValue(OperateOptionConst.ISHASRIGHT, Boolean.TRUE.toString());
-        // 跳过数据权限校验
-        operateOption.setVariableValue(OperateOptionConst.SKIPCHECKPERMISSION, Boolean.TRUE.toString());
-        List<String> errorMsgList = Lists.newArrayList();
-        List successPkIds = Lists.newArrayList();
-        for (int index = 0; index < positionList.size(); ++index) {
-            DynamicObject positionDyo = positionList.get(index);
-            String orgId = "";
-            // 设置编码
-            if (HRStringUtils.isBlank(positionDyo.getString(PositionBillConstant.NUMBER_KEY))) {
-                orgId = String.valueOf(positionDyo.getLong(String.join("_", PositionBillConstant.ORG_KEY, PositionBillConstant.ID_KEY)));
-                String positionNumber = CodeRuleServiceHelper.getNumber(PositionBillConstant.HBPM_POSITIONHR, positionDyo, orgId);
-                positionDyo.set(PositionBillConstant.NUMBER_KEY, positionNumber);
-            }
-            // 保存
-            OperationServiceImpl opImpl = new OperationServiceImpl();
-            OperationResult saveResult = opImpl.localInvokeOperation(PositionBillConstant.SAVE_OP, new DynamicObject[]{positionDyo}, operateOption);
-            if (!saveResult.isSuccess()) {
-                // 回收编码
-                if (HRStringUtils.isNotBlank(orgId)) {
-                    CodeRuleServiceHelper.recycleNumber(PositionBillConstant.HBPM_POSITIONHR, positionDyo, orgId, positionDyo.getString(PositionBillConstant.NUMBER_KEY));
-                }
-
-                for(IOperateInfo operateInfo : saveResult.getAllErrorOrValidateInfo()) {
-                    errorMsgList.add(operateInfo.getMessage());
-                }
-            } else {
-                successPkIds.addAll(saveResult.getSuccessPkIds());
-                DynamicObject[] dbPositionEntityDys = positionServiceHelper.loadDynamicObjectArray(new QFilter[]{new QFilter(PositionBillConstant.ID_KEY, QCP.in, saveResult.getSuccessPkIds())});
-                DynamicObject dbPositionEntityDy = dbPositionEntityDys[0];
-                DynamicObject positionEntity = positionEntities[index];
-                positionEntity.set(positionIdKey, dbPositionEntityDy.get(PositionBillConstant.ID_KEY));
-                positionEntity.set(PositionBillConstant.NUMBER_KEY, dbPositionEntityDy.getString(PositionBillConstant.NUMBER_KEY));
-            }
-        }
-        if (!errorMsgList.isEmpty()) {
-            throw new KDBizException(String.join(System.lineSeparator(), errorMsgList));
-        } else {
-            // 由于标品会强制设置值,所以需要后置更新
-            //updatePositionStatus(successPkIds);
+        OperateOption option = getOption();
+        String onlyValidate = option.getVariableValue(OperateOptionConst.ONLY_VALIDATE, Boolean.FALSE.toString());// 22
+        if (Boolean.TRUE.toString().equals(onlyValidate)) {
+            e.addValidator(new PositionAddSaveValidator());
         }
     }
 
-    /**
-     * 更新岗位信息的状态
-     * @param successPkIds
-     */
-    private void updatePositionStatus(List successPkIds) {
-        HRBaseServiceHelper positionServiceHelper = HRBaseServiceHelper.create(PositionBillConstant.HBPM_POSITIONHR);
-        DynamicObject[] positionDys = positionServiceHelper.loadDynamicObjectArray(new QFilter[]{new QFilter(PositionBillConstant.BOID_KEY, QCP.in, successPkIds)});
-        for (DynamicObject positionDy : positionDys) {
-            positionDy.set(PositionBillConstant.STATUS, StatusEnum.A);
-            positionDy.set(PositionBillConstant.DATA_STATUS, HisModelDataStatusEnum.TEMP.getStatus());
-        }
-        SaveServiceHelper.save(positionDys);
+    @Override
+    protected String getOperationKey() {
+        return PositionBillConstant.SAVE_OP;
     }
-
 }

+ 171 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/PosBillEntryNewPositionTempSaveOpPlugin.java

@@ -0,0 +1,171 @@
+package nckd.jxccl.hrmp.hbpm.plugin.operate.hr;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.constant.StatusEnum;
+import kd.bos.entity.operate.OperateOptionConst;
+import kd.bos.entity.operate.result.IOperateInfo;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
+import kd.bos.exception.KDBizException;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.service.operation.OperationServiceImpl;
+import kd.bos.servicehelper.coderule.CodeRuleServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.hr.hbp.common.constants.history.HisModelDataStatusEnum;
+import kd.hr.hbp.common.util.HRStringUtils;
+import nckd.jxccl.hrmp.hbpm.business.hr.PositionBillServiceHelper;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 岗位申请-新增岗位保存操作插件
+ * @entity: nckd_posbillentryadd
+ * @author: jtd
+ * @date: 2025-11-08 15:30
+ */
+public class PosBillEntryNewPositionTempSaveOpPlugin extends AbstractOperationServicePlugIn {
+
+    @Override
+    public void beginOperationTransaction(BeginOperationTransactionArgs e) {
+        super.beginOperationTransaction(e);
+
+        DynamicObject[] positionEntities = e.getDataEntities();
+        if (positionEntities.length == 0) {
+            return;
+        }
+
+        // 获取岗位和上级岗位的业务ID
+        List<Long> positionBoIds = Lists.newArrayListWithExpectedSize(positionEntities.length);
+        // 获取 行政组织业务ID
+        List<Long> adminorgBoIds = Lists.newArrayListWithExpectedSize(positionEntities.length);
+        // 岗位ID标识
+        String positionIdKey = String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ID_KEY);
+        for (DynamicObject positionEntity : positionEntities) {
+            positionBoIds.add(positionEntity.getLong(positionIdKey));
+            adminorgBoIds.add(positionEntity.getLong(PositionBillConstant.NCKD_ADMINORGBOID_KEY));
+            // 获取上级岗位
+            DynamicObject parentPositionVersionDy = positionEntity.getDynamicObject(PositionBillConstant.NCKD_PARENT);
+            if (parentPositionVersionDy != null) {
+                long parentOrgBoId = parentPositionVersionDy.getLong(PositionBillConstant.BOID_KEY);
+                positionBoIds.add(parentOrgBoId);
+            }
+        }
+
+        // 根据岗位ID从数据库中获取岗位信息
+        HRBaseServiceHelper positionServiceHelper = HRBaseServiceHelper.create(PositionBillConstant.HBPM_POSITIONHR);
+        DynamicObject[] positionDyos = positionServiceHelper.loadDynamicObjectArray(new QFilter[]{new QFilter(PositionBillConstant.ID_KEY, QCP.in, positionBoIds)});
+        Map<Long, DynamicObject> dbPositionMap = Maps.newHashMapWithExpectedSize(positionDyos.length);
+        for (DynamicObject positionDyo : positionDyos) {
+            dbPositionMap.put(positionDyo.getLong(PositionBillConstant.ID_KEY), positionDyo);
+        }
+        // 根据组织BOID从数据库中获取组织信息
+        DynamicObject[] adminOrgDyos = HRBaseServiceHelper.create(PositionBillConstant.ADMINORG_ENTITYID).loadDynamicObjectArray(new QFilter[]{new QFilter(PositionBillConstant.ID_KEY, QCP.in, adminorgBoIds)});
+        Map<Long, DynamicObject> dbAdminOrgMap = Maps.newHashMapWithExpectedSize(adminOrgDyos.length);
+        for (DynamicObject adminOrgDyo : adminOrgDyos) {
+            dbAdminOrgMap.put(adminOrgDyo.getLong(PositionBillConstant.BOID_KEY), adminOrgDyo);
+        }
+        // 构建岗位对象
+        OperateOption operateOption = OperateOption.create();
+        List<DynamicObject> positionList = Lists.newArrayListWithExpectedSize(positionEntities.length);
+        // 需要转换的键值
+        Map<String, String> transKeyMap = PositionBillServiceHelper.getTransKeyMap(PositionBillConstant.NCKD_POSITION_TRANSKEY_ENTITY);
+
+        for (DynamicObject positionEntity : positionEntities) {
+            long positionId = positionEntity.getLong(positionIdKey);
+            // 如果数据库存在则用数据库的岗位对象
+            DynamicObject positionDyo = dbPositionMap.get(positionId);
+            // 不存在则创建一个
+            if (positionDyo == null) {
+                positionDyo = positionServiceHelper.generateEmptyDynamicObject();
+            }
+            // 将表单中的信息赋值到岗位信息中
+            PositionBillServiceHelper.getPositionHrDy(positionEntity, positionDyo, transKeyMap);// 调用保存会自动设置
+            // 设置ID为岗位ID
+            positionDyo.set(PositionBillConstant.ID_KEY, positionId);
+            // 设置 是否标准岗位
+            positionDyo.set(PositionBillConstant.ISSTANDARDPOS_KEY, "9");// 暂存的数据固定为9,由于标品岗位一定会生成历史版本数据,所以为了能够正常的多次保存且不显示在岗位中需要这样做
+            // 设置 行政组织
+            positionDyo.set(PositionBillConstant.ADMINORG, dbAdminOrgMap.get(positionEntity.getLong(PositionBillConstant.NCKD_ADMINORGBOID_KEY)));
+            // 设置 上级岗位
+            DynamicObject parentPositionVersionDy = positionEntity.getDynamicObject(PositionBillConstant.NCKD_PARENT);
+            if (parentPositionVersionDy != null) {
+                positionDyo.set(PositionBillConstant.PARENT_KEY, dbPositionMap.get(parentPositionVersionDy.getLong(PositionBillConstant.BOID_KEY)));
+            } else {
+                positionDyo.set(PositionBillConstant.PARENT_KEY, null);
+            }
+            positionList.add(positionDyo);
+            String number = positionDyo.getString(PositionBillConstant.NUMBER_KEY);
+            // 设置 编码为已变更
+            if (HRStringUtils.isNotEmpty(number)) {
+                operateOption.setVariableValue(positionId + "coderule_billno_from_initAbstractCodeRule", "coderule_billno_from_init_value_of_operation");
+            }
+        }
+        // 设置岗位临时新增标识
+        //operateOption.setVariableValue("OP_ADD_POSITION_TEMP_TAG", Boolean.TRUE.toString());
+        // 跳过功能权限校验
+        operateOption.setVariableValue(OperateOptionConst.ISHASRIGHT, Boolean.TRUE.toString());
+        // 跳过数据权限校验
+        operateOption.setVariableValue(OperateOptionConst.SKIPCHECKPERMISSION, Boolean.TRUE.toString());
+        List<String> errorMsgList = Lists.newArrayList();
+        List successPkIds = Lists.newArrayList();
+        for (int index = 0; index < positionList.size(); ++index) {
+            DynamicObject positionDyo = positionList.get(index);
+            String orgId = "";
+            // 设置编码
+            if (HRStringUtils.isBlank(positionDyo.getString(PositionBillConstant.NUMBER_KEY))) {
+                orgId = String.valueOf(positionDyo.getLong(String.join("_", PositionBillConstant.ORG_KEY, PositionBillConstant.ID_KEY)));
+                String positionNumber = CodeRuleServiceHelper.getNumber(PositionBillConstant.HBPM_POSITIONHR, positionDyo, orgId);
+                positionDyo.set(PositionBillConstant.NUMBER_KEY, positionNumber);
+            }
+            // 保存
+            OperationServiceImpl opImpl = new OperationServiceImpl();
+            OperationResult saveResult = opImpl.localInvokeOperation(PositionBillConstant.SAVE_OP, new DynamicObject[]{positionDyo}, operateOption);
+            if (!saveResult.isSuccess()) {
+                // 回收编码
+                if (HRStringUtils.isNotBlank(orgId)) {
+                    CodeRuleServiceHelper.recycleNumber(PositionBillConstant.HBPM_POSITIONHR, positionDyo, orgId, positionDyo.getString(PositionBillConstant.NUMBER_KEY));
+                }
+
+                for(IOperateInfo operateInfo : saveResult.getAllErrorOrValidateInfo()) {
+                    errorMsgList.add(operateInfo.getMessage());
+                }
+            } else {
+                successPkIds.addAll(saveResult.getSuccessPkIds());
+                DynamicObject[] dbPositionEntityDys = positionServiceHelper.loadDynamicObjectArray(new QFilter[]{new QFilter(PositionBillConstant.ID_KEY, QCP.in, saveResult.getSuccessPkIds())});
+                DynamicObject dbPositionEntityDy = dbPositionEntityDys[0];
+                DynamicObject positionEntity = positionEntities[index];
+                positionEntity.set(positionIdKey, dbPositionEntityDy.get(PositionBillConstant.ID_KEY));
+                positionEntity.set(PositionBillConstant.NUMBER_KEY, dbPositionEntityDy.getString(PositionBillConstant.NUMBER_KEY));
+            }
+        }
+        if (!errorMsgList.isEmpty()) {
+            throw new KDBizException(String.join(System.lineSeparator(), errorMsgList));
+        } else {
+            // 由于标品会强制设置值,所以需要后置更新
+            //updatePositionStatus(successPkIds);
+        }
+    }
+
+    /**
+     * 更新岗位信息的状态
+     * @param successPkIds
+     */
+    private void updatePositionStatus(List successPkIds) {
+        HRBaseServiceHelper positionServiceHelper = HRBaseServiceHelper.create(PositionBillConstant.HBPM_POSITIONHR);
+        DynamicObject[] positionDys = positionServiceHelper.loadDynamicObjectArray(new QFilter[]{new QFilter(PositionBillConstant.BOID_KEY, QCP.in, successPkIds)});
+        for (DynamicObject positionDy : positionDys) {
+            positionDy.set(PositionBillConstant.STATUS, StatusEnum.A);
+            positionDy.set(PositionBillConstant.DATA_STATUS, HisModelDataStatusEnum.TEMP.getStatus());
+        }
+        SaveServiceHelper.save(positionDys);
+    }
+
+}

+ 8 - 11
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/PositionBillEntrySaveOpPlugin.java

@@ -1,28 +1,25 @@
 package nckd.jxccl.hrmp.hbpm.plugin.operate.hr;
 
-import kd.bos.dataentity.OperateOption;
-import kd.bos.entity.operate.OperateOptionConst;
 import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
 import kd.bos.entity.plugin.AddValidatorsEventArgs;
-import kd.hr.homs.opplugin.web.orgbatch.validator.OrgAddSaveValidator;
-import nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator.PositionBillEntryValidator;
+import nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator.PositionBillEntryNumberValidator;
 
 /**
  * 岗位申请单分录保存操作插件
  * @entity: nckd_positionbillentry
  * @author: jtd
- * @date: 2025/12/18 09:57
+ * @date: 2025/12/23 19:17
  */
-public class PositionBillEntrySaveOpPlugin extends AbstractOperationServicePlugIn {
+public abstract class PositionBillEntrySaveOpPlugin extends AbstractOperationServicePlugIn {
 
     @Override
     public void onAddValidators(AddValidatorsEventArgs e) {
         super.onAddValidators(e);
 
-        OperateOption option = this.getOption();
-        String onlyValidate = option.getVariableValue(OperateOptionConst.ONLY_VALIDATE, Boolean.FALSE.toString());// 22
-        if (Boolean.TRUE.toString().equals(onlyValidate)) {
-            e.addValidator(new PositionBillEntryValidator());
-        }
+        //e.addValidator(new PositionBillEntryNameValidator());
+        e.addValidator(new PositionBillEntryNumberValidator());
+        //e.addValidator(new PositionBillEntryImportValidator());
     }
+
+    protected abstract String getOperationKey();
 }

+ 116 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/AbsBillPositionSaveValidator.java

@@ -0,0 +1,116 @@
+package nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import kd.bos.common.enums.EnableEnum;
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.metadata.IDataEntityProperty;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.operate.OperateOptionConst;
+import kd.bos.entity.operate.result.OperateErrorInfo;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.bos.entity.validate.ValidateResult;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
+import kd.hr.hbp.common.util.HRObjectUtils;
+import kd.hr.hbp.common.util.HRStringUtils;
+import nckd.jxccl.hrmp.hbpm.business.hr.PositionBillServiceHelper;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 岗位申请单分录校验器
+ * @author: jtd
+ * @date: 2025/12/23 20:55
+ */
+public abstract class AbsBillPositionSaveValidator extends AbstractValidator  {
+    abstract String getOperationKey();
+
+    @Override
+    public void initialize() {
+        super.initialize();
+
+        String ignoreBillNoForContent = getOption().getVariableValue("OP_VALIDATOR_PREFIX_IGNORE", Boolean.FALSE.toString());
+        if (Boolean.TRUE.toString().equals(ignoreBillNoForContent)) {
+            setAddBillNoForContent(false);
+        }
+    }
+
+    @Override
+    public void validate() {
+        HRBaseServiceHelper positionHrServiceHelper = HRBaseServiceHelper.create(PositionBillConstant.HBPM_POSITIONHR);
+        ExtendedDataEntity[] entities = getDataEntities();
+        List<DynamicObject> addPositionList = Lists.newArrayListWithExpectedSize(entities.length);
+        OperateOption operateOption = OperateOption.create();
+        OperateOption option = getOption();
+        operateOption.mergeValue(option);
+        // 跳过系统默认的权限校验,数据、操作权限等
+        operateOption.setVariableValue(OperateOptionConst.SKIPCHECKPERMISSION, Boolean.TRUE.toString());
+        // 跳过字段值合规性校验
+        operateOption.setVariableValue("SkipMustInput", Boolean.TRUE.toString());
+        Map<Object, ExtendedDataEntity> entityMap = Maps.newHashMapWithExpectedSize(entities.length);
+
+        for(ExtendedDataEntity entity : entities) {
+            DynamicObject positionDy = entity.getDataEntity();
+            long positionId = positionDy.getLong(String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ID_KEY));
+            entityMap.put(positionId, entity);
+        }
+
+        for(ExtendedDataEntity entity : entities) {
+            DynamicObject positionEntity = entity.getDataEntity();
+            long positionId = positionEntity.getLong(String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ID_KEY));
+            DynamicObject addPositionDy = PositionBillServiceHelper.getPositionHrDy(positionEntity);
+            addPositionDy.set(PositionBillConstant.ID_KEY, positionId);
+            addPositionDy.set(PositionBillConstant.BOID_KEY, positionEntity.get(String.join(".", PositionBillConstant.NCKD_POSITION, PositionBillConstant.BOID_KEY)));
+            DynamicObject parentPositionVersionDy = positionEntity.getDynamicObject(PositionBillConstant.NCKD_PARENT);
+            if (parentPositionVersionDy != null) {
+                long parentOrgBoId = parentPositionVersionDy.getLong(PositionBillConstant.BOID_KEY);
+                if (!HRObjectUtils.isEmpty(parentOrgBoId) && parentOrgBoId > 0L) {
+                    // 过滤 当前版本 并且 数据版本生效 并且 不是标准岗位
+                    // 这是为了避免查出申请单中暂存的岗位,逻辑参考于kd.hr.homs.opplugin.web.orgbatch.validator.AbsBillOrgSaveValidator
+                    QFilter qFilter = new QFilter(PositionBillConstant.IS_CURRENT_VERSION, QCP.equals, Boolean.TRUE)
+                            .and(PositionBillConstant.DATA_STATUS, QCP.equals, EnableEnum.YES.getCode())
+                            .and(PositionBillConstant.ISSTANDARDPOS_KEY, QCP.equals, EnableEnum.NO.getCode())
+                            .and(PositionBillConstant.ID_KEY, QCP.equals, parentOrgBoId);
+                    DynamicObject currentParentDy = positionHrServiceHelper.loadDynamicObject(qFilter);
+                    if (currentParentDy != null) {
+                        addPositionDy.set(PositionBillConstant.NCKD_PARENT, currentParentDy);
+                    }
+                }
+            }
+
+            String number = addPositionDy.getString(PositionBillConstant.NUMBER_KEY);
+            if (HRStringUtils.isNotEmpty(number)) {
+                operateOption.setVariableValue(positionId + "coderule_billno_from_initAbstractCodeRule", "coderule_billno_from_init_value_of_operation");
+            }
+
+            addPositionList.add(addPositionDy);
+            IDataEntityProperty masteridProperty = positionEntity.getDataEntityType().getProperties().get(PositionBillConstant.MASTER_ID);
+            positionEntity.getDataEntityState().setBizChanged(masteridProperty.getOrdinal(), false);
+        }
+
+        if (!addPositionList.isEmpty()) {
+            OperationResult operationResult = PositionBillServiceHelper.executeOperateOnlyValidate(getOperationKey(), addPositionList.toArray(new DynamicObject[0]), operateOption);
+            if (operationResult != null && !operationResult.isSuccess()) {
+                for(ValidateResult validateError : operationResult.getValidateResult().getValidateErrors()) {
+                    for(OperateErrorInfo operateErrorInfo : validateError.getAllErrorInfo()) {
+                        Object pkValue = operateErrorInfo.getPkValue();
+                        ExtendedDataEntity entity = entityMap.get(pkValue);
+                        if (entity != null) {
+                            addErrorMessage(entity, operateErrorInfo.getMessage());
+                        } else {
+                            addErrorMessage(entities[0], operateErrorInfo.getMessage());
+                        }
+                    }
+                }
+            }
+        }
+
+    }
+
+}

+ 15 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionAddSaveValidator.java

@@ -0,0 +1,15 @@
+package nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator;
+
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+
+/**
+ * 岗位申请-岗位新设保存校验器
+ * @author: jtd
+ * @date: 2025-11-08 17:23
+ */
+public class PositionAddSaveValidator extends AbsBillPositionSaveValidator {
+    @Override
+    String getOperationKey() {
+        return PositionBillConstant.SAVE_OP;
+    }
+}

+ 72 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionBillEntryNameValidator.java

@@ -0,0 +1,72 @@
+package nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator;
+
+import com.alibaba.fastjson.JSONObject;
+import com.google.common.collect.Sets;
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.ILocaleString;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.hr.hbp.common.util.HRStringUtils;
+import nckd.jxccl.hrmp.hbpm.common.hr.MultiLangEnum;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 岗位申请单分录名称校验器
+ * @author: jtd
+ * @date: 2025/12/23 21:16
+ */
+public class PositionBillEntryNameValidator extends AbstractValidator {
+    @Override
+    public void validate() {
+        OperateOption option = validateContext.getOption();
+        // 获取组织下的岗位同胞数据 {orgBoid:{positionId:positionName}}
+        String billPositionNameMapStr = option.getVariableValue("OP_BILL_SIBLING_NAMES_MAP", "");
+        if (HRStringUtils.isNotEmpty(billPositionNameMapStr)) {
+            JSONObject orgBoIdToSiblingNameMap = JSONObject.parseObject(billPositionNameMapStr);
+            Set<String> errorIds = Sets.newHashSetWithExpectedSize(getDataEntities().length);
+
+            for(ExtendedDataEntity data : getDataEntities()) {
+                // 获取校验数据
+                DynamicObject dataEntity = data.getDataEntity();
+                // 获取组织数据
+                DynamicObject adminOrgDy = dataEntity.getDynamicObject(PositionBillConstant.NCKD_ADMINORG);
+                long orgBoId = adminOrgDy.getLong(PositionBillConstant.BOID_KEY);
+                String adminOrgName = adminOrgDy.getString(PositionBillConstant.NAME_KEY);
+
+                // 获取岗位数据
+                ILocaleString positionNameMap = dataEntity.getLocaleString(PositionBillConstant.NAME_KEY);
+                long positionId = dataEntity.getLong(String.join(".", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ID_KEY));
+                long positionBoId = dataEntity.getLong(String.join(".", PositionBillConstant.NCKD_POSITION, PositionBillConstant.BOID_KEY));
+                // 获取该组织下的岗位名称数据
+                JSONObject siblingNameMap = orgBoIdToSiblingNameMap.getJSONObject(String.valueOf(orgBoId));
+                if (siblingNameMap != null) {
+                    for(String siblingId : siblingNameMap.keySet()) {
+                        if (!siblingId.equals(String.valueOf(positionId)) && !siblingId.equals(String.valueOf(positionBoId))) {
+                            JSONObject nameMap = siblingNameMap.getJSONObject(siblingId);
+
+                            for(Map.Entry<String, String> nameEntry : positionNameMap.entrySet()) {
+                                String lang = nameEntry.getKey();
+                                if (!ILocaleString.GLang.equals(lang)) {
+                                    String siblingName = nameMap.getString(lang);
+                                    if (HRStringUtils.isNotEmpty(siblingName) && siblingName.equals(nameEntry.getValue()) && !errorIds.contains(positionBoId + "_" + lang)) {
+                                        addErrorMessage(data, String.format("本单中“%1$s”下已存在%2$s名称为“%3$s”的岗位,请修改。", adminOrgName, MultiLangEnum.getName(lang), siblingName));
+                                        errorIds.add(positionBoId + "_" + lang);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (option.containsVariable("isimport") && Boolean.parseBoolean(option.getVariableValue("isimport"))) {
+                // 业务逻辑
+            }
+
+        }
+    }
+}

+ 45 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionBillEntryNumberValidator.java

@@ -0,0 +1,45 @@
+package nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator;
+
+import com.alibaba.fastjson.JSONObject;
+import kd.bos.dataentity.OperateOption;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.entity.ExtendedDataEntity;
+import kd.bos.entity.validate.AbstractValidator;
+import kd.hr.hbp.common.util.HRStringUtils;
+import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
+
+/**
+ * 岗位申请单分录编码校验器
+ * @author: jtd
+ * @date: 2025/12/24 11:04
+ */
+public class PositionBillEntryNumberValidator extends AbstractValidator {
+    @Override
+    public void validate() {
+        OperateOption option = validateContext.getOption();
+        // 获取岗位编码数据 {positionId:number}
+        String billPositionNumberMapStr = option.getVariableValue("OP_BILL_NUMBER_MAP", "");
+        if (HRStringUtils.isNotEmpty(billPositionNumberMapStr)) {
+            JSONObject numberMap = JSONObject.parseObject(billPositionNumberMapStr);
+
+            for(ExtendedDataEntity data : getDataEntities()) {
+                DynamicObject dataEntity = data.getDataEntity();
+                String number = dataEntity.getString(PositionBillConstant.NUMBER_KEY);
+                if (HRStringUtils.isNotEmpty(number)) {
+                    long positionId = dataEntity.getLong(String.join(".", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ID_KEY));
+
+                    for(String siblingId : numberMap.keySet()) {
+                        if (!siblingId.equals(String.valueOf(positionId)) && number.equals(numberMap.getString(siblingId))) {
+                            addErrorMessage(data, "岗位编码在本单已存在,请修改。");
+                        }
+                    }
+                }
+            }
+        }
+
+        if (option.containsVariable("isimport") && Boolean.parseBoolean(option.getVariableValue("isimport"))) {
+            // 业务逻辑
+        }
+
+    }
+}

+ 0 - 75
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/plugin/operate/hr/validator/PositionBillEntryValidator.java

@@ -1,75 +0,0 @@
-package nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator;
-
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
-import kd.bos.coderule.util.MultiLangEnumBridge;
-import kd.bos.dataentity.OperateOption;
-import kd.bos.dataentity.entity.DynamicObject;
-import kd.bos.dataentity.entity.ILocaleString;
-import kd.bos.entity.ExtendedDataEntity;
-import kd.bos.entity.validate.AbstractValidator;
-import kd.hr.hbp.common.util.HRStringUtils;
-import nckd.jxccl.hrmp.hbpm.common.hr.MultiLangEnum;
-import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
-
-import java.util.Map;
-
-/**
- * 岗位申请单分录校验器
- * @author: jtd
- * @date: 2025-11-08 17:23
- */
-public class PositionBillEntryValidator extends AbstractValidator {
-
-    @Override
-    public void validate() {
-        // 获取Op参数 校验岗位编码重复和岗位名称重复
-        OperateOption option = validateContext.getOption();
-        // 获取组织下的岗位同胞数据 {orgBoId: {id:positionid, number:positionnumber, name:positionname}}
-        String billPositionSiblingMapStr = option.getVariableValue("OP_BILL_SIBLING_MAP", "");
-        if (HRStringUtils.isNotEmpty(billPositionSiblingMapStr)) {
-            JSONObject orgBoIdToSiblingPositionMap = JSONObject.parseObject(billPositionSiblingMapStr);
-            // 遍历保存数据
-            for (ExtendedDataEntity data : getDataEntities()) {
-                // 获取单据对象
-                DynamicObject positionDy = data.getDataEntity();
-                DynamicObject orgDy = positionDy.getDynamicObject(PositionBillConstant.NCKD_ADMINORG);
-                long orgBoId = orgDy.getLong(PositionBillConstant.BOID_KEY);
-                long positionId = positionDy.getLong(String.format("%s.id", PositionBillConstant.NCKD_POSITION));
-                String positionNumber = positionDy.getString(PositionBillConstant.NUMBER_KEY);
-                ILocaleString positionNameMap = positionDy.getLocaleString(PositionBillConstant.NAME_KEY);
-                // 获取岗位同胞数据进行遍历处理
-                JSONArray siblingPositionArr = orgBoIdToSiblingPositionMap.getJSONArray(String.valueOf(orgBoId));
-                if (siblingPositionArr != null) {
-                    for (int i = 0, size = siblingPositionArr.size(); i < size; i++) {
-                        JSONObject positionObj = siblingPositionArr.getJSONObject(i);
-                        // 如果是当前岗位则跳过
-                        if (positionObj.getString(PositionBillConstant.ID_KEY).equals(positionId)) {
-                            continue;
-                        }
-
-                        // 如果编码重复
-                        if (positionObj.getString(PositionBillConstant.NUMBER_KEY).equals(positionNumber)) {
-                            addErrorMessage(data, "岗位编码在本单已存在,请修改。");
-                            continue;
-                        }
-
-                        // 如果名称重复 多语言校验
-                        for (Map.Entry<String, String> nameEntry : positionNameMap.entrySet()) {
-                            String lang = nameEntry.getKey();
-                            if ("GLang".equals(lang)) {
-                                continue;
-                            }
-
-                            String name = positionObj.getJSONObject(PositionBillConstant.NAME_KEY).getString(lang);
-                            if (name.equals(nameEntry.getValue())) {
-                                addErrorMessage(data, String.format("本单中“%1$s”下已存在%2$s名称为“%3$s”的岗位,请修改。", orgDy.getString(PositionBillConstant.NAME_KEY), MultiLangEnum.getName(lang), name));
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-}