浏览代码

feat(hr): 实现岗位申请模块功能优化与数据校验增强

- 新增三定任务表单插件,支持附件上传校验
- 优化岗位申请单据状态判断逻辑,使用枚举替代硬编码
- 重构岗位申请相关常量类,统一字段命名规范
- 增强岗位新增保存操作插件,完善数据复制与状态设置
- 添加多语言枚举支持,提升国际化能力
- 优化岗位申请表单插件,改进组织机构关联逻辑
- 完善岗位申请验证器,移除冗余枚举定义
- 新增岗位申请单分录保存操作插件,支持数据验证控制
jtd 1 小时之前
父节点
当前提交
a0596dfa47

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

@@ -69,6 +69,8 @@ public class SanDingConstant extends FormConstant {
     public static final String NCKD_AUTHORIZEDSTRENGTH_KEY = "nckd_authorizedstrength";
     /** 缺编人数 */
     public static final String NCKD_STAFFINGSHORTFALL_KEY = "nckd_staffingshortfall";
+    /** 附件 */
+    public static final String ATTACHMENTPANEL_KEY = "attachmentpanel";
 
     /** 行政组织.ID */
     public static final String HAOS_ADMINORGHR_ID = "haos_adminorghr.id";

+ 32 - 0
code/hr/nckd-jxccl-hr/src/main/java/nckd/jxccl/hr/sdm/plugin/form/SanDingTaskFormPlugin.java

@@ -0,0 +1,32 @@
+package nckd.jxccl.hr.sdm.plugin.form;
+
+import kd.bos.form.control.AttachmentPanel;
+import kd.bos.form.events.BeforeDoOperationEventArgs;
+import kd.bos.form.operate.FormOperate;
+import kd.bos.form.plugin.AbstractFormPlugin;
+import kd.hr.hbp.common.util.HRStringUtils;
+import nckd.jxccl.hr.sdm.common.SanDingConstant;
+
+/**
+ * 三定任务表单插件
+ * @entity: nckd_sandingtask
+ * @author: jtd
+ * @date: 2025/12/18 20:12
+ */
+public class SanDingTaskFormPlugin extends AbstractFormPlugin {
+
+    @Override
+    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
+        super.beforeDoOperation(args);
+
+        FormOperate formOperate = (FormOperate)args.getSource();
+        String operateKey = formOperate.getOperateKey();
+        if (HRStringUtils.equals(SanDingConstant.SUBMIT_OP, operateKey)) {
+            AttachmentPanel attachmentPanel = getControl(SanDingConstant.ATTACHMENTPANEL_KEY);
+            if (attachmentPanel.getAttachmentData().isEmpty()) {
+                getView().showTipNotification("请按要求上传附件。");
+                args.setCancel(true);
+            }
+        }
+    }
+}

+ 12 - 27
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/business/hr/PositionBillService.java

@@ -18,6 +18,7 @@ import kd.bos.servicehelper.MetadataServiceHelper;
 import kd.hr.hbp.business.servicehelper.HRBaseServiceHelper;
 import kd.hr.hbp.common.util.HRDateTimeUtils;
 import kd.hr.hbp.common.util.HRStringUtils;
+import kd.sdk.hr.hdm.common.enums.reg.RegBillStatusEnum;
 import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
 
 import java.util.Date;
@@ -32,19 +33,9 @@ public class PositionBillService {
 
     private static final Map<String, String> changeTypeToLocaleMap = Maps.newHashMapWithExpectedSize(2);
 
-    private static final Map<String, String> billStatusToLocaleMap = Maps.newHashMapWithExpectedSize(7);
-
     static {
         changeTypeToLocaleMap.put("add", "新增岗位");
         changeTypeToLocaleMap.put("change", "变更信息");
-
-        billStatusToLocaleMap.put("B", "已提交");
-        billStatusToLocaleMap.put("D", "审批中");
-        billStatusToLocaleMap.put("C", "审批通过");
-        billStatusToLocaleMap.put("E", "审批不通过");
-        billStatusToLocaleMap.put("F", "已废弃");
-        billStatusToLocaleMap.put("G", "待重新提交");
-        billStatusToLocaleMap.put("LD", "已删除");
     }
 
     /**
@@ -69,47 +60,41 @@ public class PositionBillService {
      * @param iFormView
      * @param operation
      * @param pluginName
-     * @param filter
      */
-    public static void openViewForm(IFormView iFormView, String operation, String pluginName, QFilter filter) {
+    public static void openViewForm(IFormView iFormView, String operation, String pluginName) {
         if (iFormView.getModel().getValue("org") == null) {// 179
             iFormView.showTipNotification("请先填写组织体系管理组织。");
         } else {
-            HRBaseServiceHelper orgBatchChgBillHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILL);
-            QFilter idFilter = new QFilter("id", "=", iFormView.getModel().getDataEntity().getLong("id"));
-            DynamicObject dynamicObject = orgBatchChgBillHelper.loadDynamicObject(idFilter);
+            HRBaseServiceHelper positionBillHelper = new HRBaseServiceHelper(PositionBillConstant.NCKD_POSITIONBILL);
+            QFilter idFilter = new QFilter(PositionBillConstant.ID_KEY, "=", iFormView.getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY));
+            DynamicObject dynamicObject = positionBillHelper.loadDynamicObject(idFilter);
             if (dynamicObject != null) {
                 String billStatus = dynamicObject.getString(PositionBillConstant.BILL_STATUS_KEY);
-                if (!billStatus.equals("A") && !billStatus.equals("G") && !billStatus.equals("D") && (!billStatus.equals("B") || !StringUtils.equals(iFormView.getFormShowParameter().getAppId(), "wftask"))) {
+                if (!billStatus.equals(RegBillStatusEnum.TEMPSTORAGE.getCode()) && !billStatus.equals(RegBillStatusEnum.WAITRESUBMIT.getCode()) && !billStatus.equals(RegBillStatusEnum.APPROVING.getCode()) && (!billStatus.equals(RegBillStatusEnum.ALREADYSUBMIT.getCode()) || !StringUtils.equals(iFormView.getFormShowParameter().getAppId(), "wftask"))) {
                     String operateLocaleName = changeTypeToLocaleMap.get(operation);
-                    String auditstatusName = billStatusToLocaleMap.get(dynamicObject.getString(PositionBillConstant.BILL_STATUS_KEY));
-                    iFormView.showErrorNotification(String.format("“%1$s”的单据不能“%2$s”。", new Object[]{auditstatusName, operateLocaleName}));
+                    String auditstatusName = RegBillStatusEnum.getName(dynamicObject.getString(PositionBillConstant.BILL_STATUS_KEY));
+                    iFormView.showErrorNotification(String.format("“%1$s”的单据不能“%2$s”。", auditstatusName, operateLocaleName));
                     return;
                 }
             }
 
-            ListShowParameter listShowParameter = new ListShowParameter();
-            if (filter != null) {// 202
-                listShowParameter.getListFilterParameter().getQFilters().add(filter);
-            }
-
             BillShowParameter formShowParameter = new BillShowParameter();
-
             switch (operation) {
                 case PositionBillConstant.NEWENTRY_ADD:
                     formShowParameter.setFormId(PositionBillConstant.NCKD_POSBILLENTRYADD);
                     break;
                 case PositionBillConstant.NEWENTRY_CHANGE:
                     formShowParameter.setFormId(PositionBillConstant.NCKD_POSBILLENTRYCHANGE);
-                    break;
             }
-
             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));
-            formShowParameter.setCustomParam("org", iFormView.getModel().getDataEntity().getLong("org.id"));
+            if (HRStringUtils.equals(iFormView.getFormShowParameter().getAppId(), "wftask")) {
+                formShowParameter.setHasRight(true);
+            }
+            formShowParameter.setCustomParam("org", iFormView.getModel().getDataEntity().getLong(String.join(".", PositionBillConstant.ORG_KEY, PositionBillConstant.ID_KEY)));
             int sequence = getEntrySeq(iFormView.getModel(), PositionBillConstant.CHANGE_TYPE_ADD);
             formShowParameter.setCustomParam("sequence", sequence);
             iFormView.showForm(formShowParameter);

+ 44 - 0
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/common/hr/MultiLangEnum.java

@@ -0,0 +1,44 @@
+package nckd.jxccl.hrmp.hbpm.common.hr;
+
+import kd.bos.coderule.util.MultiLangEnumBridge;
+
+/**
+ * 多语言枚举
+ * @author: jtd
+ * @date: 2025/12/17 21:52
+ */
+public enum MultiLangEnum {
+    CHINES_SIMP("zh_CN", new MultiLangEnumBridge("简体中文", "MultiLangEnum_0", "hrmp-haos-common")),
+    CHINES_TRAD("zh_TW", new MultiLangEnumBridge("繁体中文", "MultiLangEnum_1", "hrmp-haos-common")),
+    ENGLISH("en_US", new MultiLangEnumBridge("英文", "MultiLangEnum_2", "hrmp-haos-common"));
+
+    private String code;
+    private MultiLangEnumBridge bridge = null;
+
+    private MultiLangEnum(String code, MultiLangEnumBridge bridge) {
+        this.code = code;
+        this.bridge = bridge;
+    }
+
+    public static String getName(String code) {
+        if (code == null) {
+            return null;
+        } else {
+            for(MultiLangEnum se : values()) {
+                if (code.equals(se.getCode())) {
+                    return se.getName();
+                }
+            }
+
+            return null;
+        }
+    }
+
+    public String getCode() {
+        return this.code;
+    }
+
+    public String getName() {
+        return this.bridge.loadKDString();
+    }
+}

+ 39 - 123
code/hrmp/nckd-jxccl-hrmp/src/main/java/nckd/jxccl/hrmp/hbpm/common/hr/PositionBillConstant.java

@@ -6,164 +6,80 @@ import java.util.HashMap;
 import java.util.Map;
 
 /**
- * 岗位常量
+ * 岗位申请常量
  * @author: jtd
  * @date: 2025-10-20 16:29
  */
 public class PositionBillConstant extends FormConstant {
 
-    /**
-     * 岗位F7组织树(去时间)
-     */
-    public static final String NCKD_NOTIME_POSTREELISTF7 = "nckd_notime_postreelistf7";
+    /** 岗位/标岗F7组织树(自定义)实体标识 */
+    public static final String NCKD_HBPM_POSORGTREELISTF_ENTITY = "nckd_hbpm_posorgtreelistf";
+    /** 岗位信息键值转换实体标识 */
+    public static final String NCKD_POSITION_TRANSKEY_ENTITY = "nckd_position_transkey";
 
-    /**
-     * 行政组织树表单ID
-     */
+    /** 行政组织树表单ID */
     public static final String HAOS_ORGTREELISTF7 = "haos_orgtreelistf7";
-
-    /**
-     * 岗位变动类型表单ID
-     */
+    /** 岗位变动类型表单ID */
     public static final String NCKD_POSITION_CHANGETYPE = "nckd_position_changetype";
-
-    /**
-     * 变动类型
-     */
+    /** 变动类型 */
     public static final String NCKD_CHANGETYPE = "nckd_changetype";
-
-    /**
-     * 变动类型-岗位新设
-     */
+    /** 变动类型-岗位新设 */
     public static final Long CHANGE_TYPE_ADD = 1010L;
-
-    /**
-     * 变动类型-岗位变更
-     */
+    /** 变动类型-岗位变更 */
     public static final Long CHANGE_TYPE_CHANGE = 1020L;
-
-    /**
-     * 变动类型Map
-     */
+    /** 变动类型Map */
     public static final Map<String, Long> CHANGE_TYPE_MAP = new HashMap(){{
         put("add", CHANGE_TYPE_ADD);
         put("change", CHANGE_TYPE_CHANGE);
     }};
-
-    /**
-     * 岗位信息维护表单ID
-     */
+    /** 岗位信息维护表单ID */
     public static final String HBPM_POSITIONHR = "hbpm_positionhr";
-
-
-    /**
-     * 岗位申请单表单ID
-     */
+    /** 岗位申请单表单ID */
     public static final String NCKD_POSITIONBILL = "nckd_positionbill";
-
-    /**
-     * 岗位申请单分录表单ID
-     */
+    /** 岗位申请单分录表单ID */
     public static final String NCKD_POSITIONBILLENTRY = "nckd_positionbillentry";
-
-    /**
-     * 岗位申请-新增岗位表单ID
-     */
+    /** 岗位申请-新增岗位表单ID */
     public static final String NCKD_POSBILLENTRYADD = "nckd_posbillentryadd";
-
-    /**
-     * 岗位申请-变更信息表单ID
-     */
+    /** 岗位申请-变更信息表单ID */
     public static final String NCKD_POSBILLENTRYCHANGE = "nckd_posbillentrychange";
-
-    /**
-     * 岗位职责分录ID
-     */
+    /** 岗位职责分录ID */
     public static final String NCKD_POSDUTYENTRYENTITY = "nckd_posdutyentryentity";
-
-    /**
-     * 新增分录-岗位新设OP
-     */
+    /** 新增分录-岗位新设OP */
     public static final String NEWENTRY_ADD = "newentry_add";
-
-    /**
-     * 新增分录-岗位变更OP
-     */
+    /** 新增分录-岗位变更OP */
     public static final String NEWENTRY_CHANGE = "newentry_change";
-
-    /**
-     * 删除分录-岗位新设OP
-     */
+    /** 删除分录-岗位新设OP */
     public static final String DELETEENTRY_ADD = "deleteentry_add";
-
-    /**
-     * 删除分录-岗位变更OP
-     */
+    /** 删除分录-岗位变更OP */
     public static final String DELETEENTRY_CHANGE = "deleteentry_change";
-
-    /**
-     * 编辑-岗位新设OP
-     */
+    /** 编辑-岗位新设OP */
     public static final String EDIT_ADD = "edit_add";
-
-    /**
-     * 编辑-岗位变更OP
-     */
+    /** 编辑-岗位变更OP */
     public static final String EDIT_CHANGE = "edit_change";
-
-    /**
-     * 岗位申请单内码
-     */
+    /** 岗位申请单内码 */
     public static final String NCKD_BILLID = "nckd_billid";
-
-    /**
-     * 生效日期
-     */
+    /** 生效日期 */
     public static final String NCKD_EFFDT = "nckd_effdt";
-
-    /**
-     * 设立日期
-     */
+    /** 设立日期 */
     public static final String NCKD_ESTDATE = "nckd_estdate";
-
-    /**
-     * 设立日期
-     */
+    /** 设立日期 */
     public static final String ESTABLISHMENTDATE_KEY = "establishmentdate";
-
-    /**
-     * 分录顺序号
-     */
+    /** 分录顺序号 */
     public static final String NCKD_SEQUENCE = "nckd_sequence";
-
-    /**
-     * 行政组织
-     */
+    /** 行政组织 */
     public static final String NCKD_ADMINORG = "nckd_adminorg";
-
-    /**
-     * 岗位
-     */
+    /** 岗位 */
     public static final String NCKD_POSITION = "nckd_position";
-
-    /**
-     * 上级岗位
-     */
+    /** 上级岗位 */
     public static final String NCKD_PARENT = "nckd_parent";
-
-    /**
-     * 上级岗位
-     */
+    /** 上级岗位 */
     public static final String PARENT_KEY = "parent";
-
-    /**
-     * 组织体系管理组织
-     */
+    /** 组织体系管理组织 */
     public static final String NCKD_ORG = "nckd_org";
-
-    /**
-     * 生效日期
-     */
+    /** 生效日期 */
     public static final String NCKD_BSED = "nckd_bsed";
-
-}
+    /** 行政组织业务ID */
+    public static final String NCKD_ADMINORGBOID_KEY = "nckd_adminorgboid";
+    /** 岗位业务ID */
+    public static final String NCKD_POSITIONBOID_KEY = "nckd_positionboid";
+}

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

@@ -50,7 +50,6 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
     public void beforeBindData(EventObject e) {
         super.beforeBindData(e);
 
-        getPageCache().put("paramsChangeSetNumber", Boolean.FALSE.toString());
         // 如果是新增
         long entityId = getModel().getDataEntity().getLong(PositionBillConstant.ID_KEY);
         if (entityId == 0L) {
@@ -70,7 +69,6 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
         } else {
             setPositionNumberEnable();
         }
-        getPageCache().put("paramsChangeSetNumber", Boolean.TRUE.toString());
 
         // 新增的时候生成岗位ID
         String positionIdKey = String.format("%s_id", PositionBillConstant.NCKD_POSITION);
@@ -96,14 +94,15 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
     }
 
     private void setPositionNumber(DynamicObject positionHrDy) {
+        DynamicObject dataEntity = getModel().getDataEntity();// 157
         // 组织体系管理组织
-        DynamicObject org = getModel().getDataEntity().getDynamicObject(PositionBillConstant.NCKD_ORG);
+        DynamicObject org = dataEntity.getDynamicObject(PositionBillConstant.NCKD_ORG);
         if (org == null) {
             getView().setEnable(Boolean.FALSE, PositionBillConstant.NUMBER_KEY);
             return;
         }
 
-        String number = getModel().getDataEntity().getString(PositionBillConstant.NUMBER_KEY);
+        String number = dataEntity.getString(PositionBillConstant.NUMBER_KEY);
         if (HRStringUtils.isNotEmpty(number) && !HRStringUtils.equals(number, getView().getPageCache().get(CODERULE_NUMBER))) {
             return;
         }
@@ -111,7 +110,9 @@ public class PosBillEntryAddFormPlugin extends AbstractFormPlugin {
         long orgid = org.getLong(PositionBillConstant.ID_KEY);
         boolean cudeRule = CodeRuleServiceHelper.isExist(PositionBillConstant.HBPM_POSITIONHR, positionHrDy, String.valueOf(orgid));
         if (cudeRule) {
-            if (CodeRuleServiceHelper.isModifiable(PositionBillConstant.HBPM_POSITIONHR, positionHrDy, String.valueOf(org.getLong(PositionBillConstant.ID_KEY)))) {
+            boolean fromDatabase = dataEntity.getDataEntityState().getFromDatabase();
+            boolean modifiable = CodeRuleServiceHelper.isModifiable(PositionBillConstant.HBPM_POSITIONHR, positionHrDy, String.valueOf(org.getLong(PositionBillConstant.ID_KEY)));
+            if (modifiable || fromDatabase) {
                 String positionNumber = CodeRuleServiceHelper.getNumber(PositionBillConstant.HBPM_POSITIONHR, positionHrDy, String.valueOf(org.getLong(PositionBillConstant.ID_KEY)));
                 HRBaseServiceHelper hrBaseServiceHelper = new HRBaseServiceHelper(PositionBillConstant.HBPM_POSITIONHR);
                 QFilter qFilter = new QFilter(PositionBillConstant.NUMBER_KEY, QCP.equals, positionNumber);

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

@@ -1,6 +1,7 @@
 package nckd.jxccl.hrmp.hbpm.plugin.form.hr;
 
 import kd.bos.bill.OperationStatus;
+import kd.bos.common.enums.EnableEnum;
 import kd.bos.form.FormShowParameter;
 import kd.bos.form.events.BeforeDoOperationEventArgs;
 import kd.bos.form.field.BasedataEdit;
@@ -11,7 +12,6 @@ import kd.bos.list.ListShowParameter;
 import kd.hr.hbp.common.util.HRStringUtils;
 import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
 
-import java.math.BigInteger;
 import java.util.EventObject;
 
 /**
@@ -41,6 +41,7 @@ public class PositionBillEntryFormPlugin extends AbstractFormPlugin implements B
 
         FormShowParameter formShowParameter = getView().getFormShowParameter();
         setOrg();
+        setDefaultValue();
         if (formShowParameter.getCustomParam("sequence") != null && getModel().getDataEntity(true).getInt(PositionBillConstant.NCKD_SEQUENCE) == 0) {
             getModel().setValue(PositionBillConstant.NCKD_SEQUENCE, formShowParameter.getCustomParam("sequence"));
         }
@@ -58,11 +59,21 @@ public class PositionBillEntryFormPlugin extends AbstractFormPlugin implements B
                 getModel().beginInit();
                 getModel().setValue(PositionBillConstant.NCKD_ORG, orgParam);
                 getModel().endInit();
-                getPageCache().put("isInit", BigInteger.ONE.toString());
+                getPageCache().put("isInit", EnableEnum.YES.getCode());
             }
         }
     }
 
+    /**
+     * 设置单头ID
+     */
+    private void setDefaultValue() {
+        Object billId = getView().getFormShowParameter().getCustomParam("billid");
+        if (billId != null) {// 135
+            getModel().setValue(PositionBillConstant.NCKD_BILLID, Long.parseLong(String.valueOf(billId)));
+        }
+    }
+
     public void afterBindData(EventObject e) {
         super.afterBindData(e);
 
@@ -86,14 +97,14 @@ public class PositionBillEntryFormPlugin extends AbstractFormPlugin implements B
         // 替换岗位F7模板
         if (PositionBillConstant.NCKD_POSITION.equals(fieldKey)) {
             ListShowParameter showParameter = (ListShowParameter) beforeF7SelectEvent.getFormShowParameter();
-            showParameter.setFormId(PositionBillConstant.NCKD_NOTIME_POSTREELISTF7);
+            showParameter.setFormId(PositionBillConstant.NCKD_HBPM_POSORGTREELISTF_ENTITY);
             showParameter.setCaption("岗位");
         }
 
         // 替换上级岗位F7模板
         if (PositionBillConstant.NCKD_PARENT.equals(fieldKey)) {
             ListShowParameter showParameter = (ListShowParameter) beforeF7SelectEvent.getFormShowParameter();
-            showParameter.setFormId(PositionBillConstant.NCKD_NOTIME_POSTREELISTF7);
+            showParameter.setFormId(PositionBillConstant.NCKD_HBPM_POSORGTREELISTF_ENTITY);
             showParameter.setCaption("上级岗位");
         }
     }

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

@@ -92,22 +92,22 @@ public class PositionBillFormPlugin extends AbstractFormPlugin {
         String opKey = afterDoOperationEventArgs.getOperateKey();
         switch (opKey) {
             case PositionBillConstant.NEWENTRY_ADD:
-                PositionBillService.openViewForm(this.getView(), opKey, this.getPluginName(), null);
+                PositionBillService.openViewForm(this.getView(), opKey, this.getPluginName());
                 break;
-            case "newentry_change":
-                PositionBillService.openViewForm(this.getView(), opKey, this.getPluginName(), null);
+            case PositionBillConstant.NEWENTRY_CHANGE:
+                PositionBillService.openViewForm(this.getView(), opKey, this.getPluginName());
                 break;
             case "deleteentry_add":
-                PositionBillService.openViewForm(this.getView(), "add", this.getPluginName(), null);
+                PositionBillService.openViewForm(this.getView(), "add", this.getPluginName());
                 break;
             case "deleteentry_change":
-                PositionBillService.openViewForm(this.getView(), "add", this.getPluginName(), null);
+                PositionBillService.openViewForm(this.getView(), "add", this.getPluginName());
                 break;
             case "edit_add":
-                PositionBillService.openViewForm(this.getView(), "add", this.getPluginName(), null);
+                PositionBillService.openViewForm(this.getView(), "add", this.getPluginName());
                 break;
             case "edit_change":
-                PositionBillService.openViewForm(this.getView(), "add", this.getPluginName(), null);
+                PositionBillService.openViewForm(this.getView(), "add", this.getPluginName());
                 break;
         }
     }
@@ -118,13 +118,13 @@ public class PositionBillFormPlugin extends AbstractFormPlugin {
 
         switch (closedCallBackEvent.getActionId()) {
             case "add":
-                PositionBillService.openViewForm(this.getView(), "add", this.getPluginName(), null);
+                PositionBillService.openViewForm(this.getView(), "add", this.getPluginName());
                 break;
             case "change":
-                PositionBillService.openViewForm(this.getView(), "change", this.getPluginName(), null);
+                PositionBillService.openViewForm(this.getView(), "change", this.getPluginName());
                 break;
             case "delete":
-                PositionBillService.openViewForm(this.getView(), "delete", this.getPluginName(), null);
+                PositionBillService.openViewForm(this.getView(), "delete", this.getPluginName());
                 break;
             case "edit":
         }

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

@@ -5,48 +5,39 @@ 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.entity.DynamicObjectCollection;
-import kd.bos.dataentity.metadata.IDataEntityProperty;
-import kd.bos.dataentity.metadata.clr.DataEntityPropertyCollection;
-import kd.bos.entity.EntityMetadataCache;
 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.AddValidatorsEventArgs;
 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.BusinessDataServiceHelper;
-import kd.bos.servicehelper.QueryServiceHelper;
+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.HRDynamicObjectUtils;
 import kd.hr.hbp.common.util.HRStringUtils;
+import nckd.jxccl.base.common.utils.QueryFieldBuilder;
 import nckd.jxccl.hrmp.hbpm.common.hr.PositionBillConstant;
-import nckd.jxccl.hrmp.hbpm.plugin.operate.hr.validator.PositionBillEntryValidator;
 
-import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 /**
  * 岗位申请-新增岗位保存OP
+ * @entity: nckd_posbillentryadd
  * @author: jtd
  * @date: 2025-11-08 15:30
  */
 public class PosBillEntryAddSaveOpPlugin extends AbstractOperationServicePlugIn {
 
-    private static final String FIELD_PREFIX = "nckd_";
-
-    @Override
-    public void onAddValidators(AddValidatorsEventArgs e) {
-        super.onAddValidators(e);
-
-        e.addValidator(new PositionBillEntryValidator());
-    }
+    private static final String PAGECACHE_KEY_BILLNO_FROM_INIT_VALUE_OF_OPERATION = "coderule_billno_from_init_value_of_operation";
 
     @Override
     public void beginOperationTransaction(BeginOperationTransactionArgs e) {
@@ -59,68 +50,75 @@ public class PosBillEntryAddSaveOpPlugin extends AbstractOperationServicePlugIn
 
         // 获取岗位和上级岗位的业务ID
         List<Long> positionBoIds = Lists.newArrayListWithExpectedSize(positionEntities.length);
-        for (DynamicObject orgEntity : positionEntities) {
-            positionBoIds.add(orgEntity.getLong(String.format("%s_id", PositionBillConstant.NCKD_POSITION)));
-
+        // 获取 行政组织业务ID
+        List<Long> adminorgBoIds = Lists.newArrayListWithExpectedSize(positionEntities.length);
+        for (DynamicObject positionEntity : positionEntities) {
+            positionBoIds.add(positionEntity.getLong(String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ID_KEY)));
+            adminorgBoIds.add(positionEntity.getLong(PositionBillConstant.NCKD_ADMINORGBOID_KEY));
             // 获取上级岗位
-            DynamicObject parentPositionVersionDy = orgEntity.getDynamicObject(PositionBillConstant.NCKD_PARENT);
+            DynamicObject parentPositionVersionDy = positionEntity.getDynamicObject(PositionBillConstant.NCKD_PARENT);
             if (parentPositionVersionDy != null) {
                 long parentOrgBoId = parentPositionVersionDy.getLong(PositionBillConstant.BOID_KEY);
                 positionBoIds.add(parentOrgBoId);
-                //orgEntity.set("adminorgboid", Long.valueOf(parentOrgBoId));
             }
         }
 
-        // 根据岗位业务ID从数据库中获取岗位信息
-        DynamicObjectCollection positionQueryDyColl = QueryServiceHelper.query(PositionBillConstant.HBPM_POSITIONHR, PositionBillConstant.ID_KEY, new QFilter[]{new QFilter(PositionBillConstant.ID_KEY, QCP.in, positionBoIds)});
-        List<Object> listIds = new ArrayList<Object>();
-        positionQueryDyColl.forEach(row -> listIds.add(row.getLong(PositionBillConstant.ID_KEY)));
-        DynamicObject[] dbPositionDys = BusinessDataServiceHelper.load(listIds.toArray(), EntityMetadataCache.getDataEntityType(PositionBillConstant.HBPM_POSITIONHR));
-        Map<Long, DynamicObject> dbPositionMap = Maps.newHashMapWithExpectedSize(dbPositionDys.length);
-        for (DynamicObject dbPositionDy : dbPositionDys) {
-            dbPositionMap.put(dbPositionDy.getLong(PositionBillConstant.ID_KEY), dbPositionDy);
+        // 根据岗位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.ADMINORGHR_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);
-        for (DynamicObject positionEntity : positionEntities) {
-            long positionId = positionEntity.getLong(String.format("%s_id", PositionBillConstant.NCKD_POSITION));
+        // 查询需要转换的键值
+        String selectFields = QueryFieldBuilder.create().add(PositionBillConstant.NUMBER_KEY).add(PositionBillConstant.NAME_KEY).buildSelect();
+        DynamicObject[] transKeyDyos = HRBaseServiceHelper.create(PositionBillConstant.NCKD_POSITION_TRANSKEY_ENTITY).queryOriginalArray(selectFields, null);
+        // key->目标字段 value->源字段
+        Map<String, String> transKeyMap = Arrays.stream(transKeyDyos).map(Function.identity()).collect(Collectors.toMap(transKeyDyo -> transKeyDyo.getString(PositionBillConstant.NAME_KEY), transKeyDyo -> transKeyDyo.getString(PositionBillConstant.NUMBER_KEY), (oldValue, newValue) -> newValue));
 
+        for (DynamicObject positionEntity : positionEntities) {
+            long positionId = positionEntity.getLong(String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ID_KEY));
             // 如果数据库存在则用数据库的岗位对象
-            DynamicObject positionDy = dbPositionMap.get(positionId);
+            DynamicObject positionDyo = dbPositionMap.get(positionId);
             // 不存在则创建一个
-            if (positionDy == null) {
-                positionDy = BusinessDataServiceHelper.newDynamicObject(PositionBillConstant.HBPM_POSITIONHR);
-            }
-
-            // 键值转换
-            Map<String, String> transKeyMap = new HashMap<String, String>();
-            DataEntityPropertyCollection properties = positionDy.getDataEntityType().getProperties();
-            for (IDataEntityProperty property : properties) {
-                String name = property.getName();
-                if (name.startsWith(FIELD_PREFIX)) {
-                    transKeyMap.put(name.substring(name.indexOf(FIELD_PREFIX)), name);
-                }
+            if (positionDyo == null) {
+                positionDyo = positionServiceHelper.generateEmptyDynamicObject();
             }
-            // 设立日期单独处理
-            transKeyMap.put(PositionBillConstant.ESTABLISHMENTDATE_KEY, PositionBillConstant.NCKD_ESTDATE);
-
             // 将表单中的信息赋值到岗位信息中
-            HRDynamicObjectUtils.copy(positionEntity, positionDy);
-            positionDy.set(PositionBillConstant.ID_KEY, positionId);
+            HRDynamicObjectUtils.copy(positionEntity, positionDyo, transKeyMap);
+            // 设置 行政组织
+            positionDyo.set(PositionBillConstant.ADMINORG, dbAdminOrgMap.get(positionEntity.getLong(PositionBillConstant.NCKD_ADMINORGBOID_KEY)));
+             // 设置ID
+            positionDyo.set(PositionBillConstant.ID_KEY, positionId);
+            // 设置 上级岗位
             DynamicObject parentPositionVersionDy = positionEntity.getDynamicObject(PositionBillConstant.NCKD_PARENT);
             if (parentPositionVersionDy != null) {
-                positionDy.set(PositionBillConstant.PARENT_KEY, dbPositionMap.get(parentPositionVersionDy.getLong(PositionBillConstant.BOID_KEY)));
+                positionDyo.set(PositionBillConstant.PARENT_KEY, dbPositionMap.get(parentPositionVersionDy.getLong(PositionBillConstant.BOID_KEY)));
             } else {
-                positionDy.set(PositionBillConstant.PARENT_KEY, null);
+                positionDyo.set(PositionBillConstant.PARENT_KEY, null);
             }
-            positionDy.set(PositionBillConstant.STATUS, StatusEnum.A);
-            positionDy.set(PositionBillConstant.ENABLE, EnableEnum.YES.getCode());
-            positionList.add(positionDy);
-            String number = positionDy.getString("number");
+            // 设置 数据状态
+            positionDyo.set(PositionBillConstant.STATUS, StatusEnum.A);
+            // 设置 业务状态
+            positionDyo.set(PositionBillConstant.ENABLE, EnableEnum.YES.getCode());
+            // 设置 是否标准岗位
+            positionDyo.set(PositionBillConstant.ISSTANDARDPOS_KEY, EnableEnum.NO.getCode());
+            // 设置 数据版本状态
+            //positionDyo.set(PositionBillConstant.DATA_STATUS, HisModelDataStatusEnum.TEMP.getStatus());
+            positionList.add(positionDyo);
+            String number = positionDyo.getString("number");
+            // 设置 编码为已变更
             if (HRStringUtils.isNotEmpty(number)) {
-                operateOption.setVariableValue(positionId + "coderule_billno_from_initAbstractCodeRule", "coderule_billno_from_init_value_of_operation");
+                operateOption.setVariableValue(positionId + "coderule_billno_from_initAbstractCodeRule", PAGECACHE_KEY_BILLNO_FROM_INIT_VALUE_OF_OPERATION);
             }
         }
         // 跳过功能权限校验
@@ -128,27 +126,44 @@ public class PosBillEntryAddSaveOpPlugin extends AbstractOperationServicePlugIn
         // 跳过数据权限校验
         operateOption.setVariableValue(OperateOptionConst.SKIPCHECKPERMISSION, Boolean.TRUE.toString());
         StringBuilder errorMsg = new StringBuilder();
-        for (int index = 0; index < positionList.size(); index++) {
-            DynamicObject positionDy = positionList.get(index);
+        List<String> errorMsgList = Lists.newArrayList();
+        List successPkIds = Lists.newArrayList();
+        for (int index = 0; index < positionList.size(); ++index) {
+            DynamicObject positionDyo = positionList.get(index);
             OperationServiceImpl opImpl = new OperationServiceImpl();
-            OperationResult saveResult = opImpl.localInvokeOperation(PositionBillConstant.SAVE_OP, new DynamicObject[] { positionDy }, operateOption);
+            OperationResult saveResult = opImpl.localInvokeOperation(PositionBillConstant.SAVE_OP, new DynamicObject[]{positionDyo}, operateOption);
             if (!saveResult.isSuccess()) {
-                List<IOperateInfo> errorOrValidateInfo = saveResult.getAllErrorOrValidateInfo();
-                for (IOperateInfo operateInfo : errorOrValidateInfo) {
-                    errorMsg.append(operateInfo.getMessage());
+                for(IOperateInfo operateInfo : saveResult.getAllErrorOrValidateInfo()) {
+                    errorMsgList.add(operateInfo.getMessage());
                 }
             } else {
-                //DynamicObject[] dbPositionEntityDys = OrgRepository.getInstance().queryOrgDys(String.join(",", PositionBillConstant.ID_KEY, PositionBillConstant.NUMBER_KEY), new QFilter(PositionBillConstant.ID_KEY, QCP.in, saveResult.getSuccessPkIds()));
-                DynamicObject[] dbPositionEntityDys = null;
+                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(String.format("%s_id", PositionBillConstant.NCKD_POSITION), dbPositionEntityDy.get(PositionBillConstant.ID_KEY));
+                positionEntity.set(String.join("_", PositionBillConstant.NCKD_POSITION, PositionBillConstant.ID_KEY), dbPositionEntityDy.get(PositionBillConstant.ID_KEY));
                 positionEntity.set(PositionBillConstant.NUMBER_KEY, dbPositionEntityDy.getString(PositionBillConstant.NUMBER_KEY));
             }
         }
-        if (errorMsg.length() > 0) {
-            throw new KDBizException(errorMsg.toString());
+        if (!errorMsgList.isEmpty()) {
+            throw new KDBizException(String.join(System.lineSeparator(), errorMsgList));
+        } else {
+            // 由于标品会强制设置值,所以需要后置更新
+            updatePositionDataStatus(successPkIds);
+        }
+    }
+
+    /**
+     * 更新岗位数据版本状态
+     * @param successPkIds
+     */
+    private void updatePositionDataStatus(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.DATA_STATUS, HisModelDataStatusEnum.TEMP.getStatus());
         }
+        SaveServiceHelper.save(positionDys);
     }
 
 }

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

@@ -0,0 +1,28 @@
+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;
+
+/**
+ * 岗位申请单分录保存操作插件
+ * @entity: nckd_positionbillentry
+ * @author: jtd
+ * @date: 2025/12/18 09:57
+ */
+public 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());
+        }
+    }
+}

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

@@ -9,6 +9,7 @@ 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;
@@ -20,42 +21,6 @@ import java.util.Map;
  */
 public class PositionBillEntryValidator extends AbstractValidator {
 
-    private enum MultiLangEnum {
-        CHINES_SIMP("zh_CN", new MultiLangEnumBridge("简体中文", "MultiLangEnum_0", "hrmp-haos-common")),
-        CHINES_TRAD("zh_TW", new MultiLangEnumBridge("繁体中文", "MultiLangEnum_1", "hrmp-haos-common")),
-        ENGLISH("en_US", new MultiLangEnumBridge("英文", "MultiLangEnum_2", "hrmp-haos-common"));
-
-        private String code;
-        private MultiLangEnumBridge bridge = null;
-
-        private MultiLangEnum(String code, MultiLangEnumBridge bridge) {
-            this.code = code;
-            this.bridge = bridge;
-        }
-
-        public static String getName(String code) {
-            if (code == null) {
-                return null;
-            } else {
-                for(MultiLangEnum se : values()) {
-                    if (code.equals(se.getCode())) {
-                        return se.getName();
-                    }
-                }
-
-                return null;
-            }
-        }
-
-        public String getCode() {
-            return this.code;
-        }
-
-        public String getName() {
-            return this.bridge.loadKDString();
-        }
-    }
-
     @Override
     public void validate() {
         // 获取Op参数 校验岗位编码重复和岗位名称重复