diff --git a/@rbv b/@rbv index 9a4de3624..0662169c5 160000 --- a/@rbv +++ b/@rbv @@ -1 +1 @@ -Subproject commit 9a4de36241ba367728a2c45c4b6b4ec475fb9d34 +Subproject commit 0662169c52c11b0bdb04e0935f7da4a18289026c diff --git a/src/main/java/com/rebuild/core/metadata/EntityHelper.java b/src/main/java/com/rebuild/core/metadata/EntityHelper.java index ed1627830..b6ec8ddc0 100644 --- a/src/main/java/com/rebuild/core/metadata/EntityHelper.java +++ b/src/main/java/com/rebuild/core/metadata/EntityHelper.java @@ -165,6 +165,7 @@ public class EntityHelper { public static final String ApprovalId = "approvalId"; public static final String ApprovalState = "approvalState"; public static final String ApprovalStepNode = "approvalStepNode"; + public static final String ApprovalLastUser = "approvalLastUser"; // 权限 diff --git a/src/main/java/com/rebuild/core/metadata/MetadataHelper.java b/src/main/java/com/rebuild/core/metadata/MetadataHelper.java index 5e77cf248..ac85011da 100644 --- a/src/main/java/com/rebuild/core/metadata/MetadataHelper.java +++ b/src/main/java/com/rebuild/core/metadata/MetadataHelper.java @@ -249,7 +249,8 @@ public class MetadataHelper { public static boolean isApprovalField(String fieldName) { return EntityHelper.ApprovalId.equalsIgnoreCase(fieldName) || EntityHelper.ApprovalState.equalsIgnoreCase(fieldName) - || EntityHelper.ApprovalStepNode.equalsIgnoreCase(fieldName); + || EntityHelper.ApprovalStepNode.equalsIgnoreCase(fieldName) + || EntityHelper.ApprovalLastUser.equalsIgnoreCase(fieldName); } /** diff --git a/src/main/java/com/rebuild/core/metadata/impl/Entity2Schema.java b/src/main/java/com/rebuild/core/metadata/impl/Entity2Schema.java index 45924b86d..6957408f1 100644 --- a/src/main/java/com/rebuild/core/metadata/impl/Entity2Schema.java +++ b/src/main/java/com/rebuild/core/metadata/impl/Entity2Schema.java @@ -93,7 +93,7 @@ public class Entity2Schema extends Field2Schema { "select min(typeCode) from MetaEntity").unique(); int typeCode = maxTypeCode == null || ObjectUtils.toInt(maxTypeCode[0]) == 0 ? 999 : (ObjectUtils.toInt(maxTypeCode[0]) - 1); - if (typeCode <= (License.isCommercial() ? 500 : 900)) { + if (typeCode <= (License.isCommercial() ? 399 : 949)) { throw new MetadataModificationException("ENTITY CODE EXCEEDS SYSTEM LIMIT : " + typeCode); } @@ -116,7 +116,7 @@ public class Entity2Schema extends Field2Schema { } record.setString("nameField", nameFiled); record = Application.getCommonsService().create(record); - tempMetaId.add(record.getPrimary()); + recordedMetaId.add(record.getPrimary()); Entity tempEntity = new UnsafeEntity(entityName, physicalName, entityLabel, typeCode, nameFiled); try { @@ -151,13 +151,13 @@ public class Entity2Schema extends Field2Schema { } } catch (Throwable ex) { log.error(null, ex); - Application.getCommonsService().delete(tempMetaId.toArray(new ID[0])); + Application.getCommonsService().delete(recordedMetaId.toArray(new ID[0])); throw new MetadataModificationException(Language.L("无法同步元数据到数据库 : %s", ex.getLocalizedMessage())); } boolean schemaReady = schema2Database(tempEntity); if (!schemaReady) { - Application.getCommonsService().delete(tempMetaId.toArray(new ID[0])); + Application.getCommonsService().delete(recordedMetaId.toArray(new ID[0])); throw new MetadataModificationException(Language.L("无法同步元数据到数据库")); } diff --git a/src/main/java/com/rebuild/core/metadata/impl/Field2Schema.java b/src/main/java/com/rebuild/core/metadata/impl/Field2Schema.java index 89dd93cc3..3bc1bac87 100644 --- a/src/main/java/com/rebuild/core/metadata/impl/Field2Schema.java +++ b/src/main/java/com/rebuild/core/metadata/impl/Field2Schema.java @@ -52,7 +52,7 @@ public class Field2Schema { private static final int DECIMAL_SCALE = 8; final protected ID user; - final protected Set tempMetaId = new HashSet<>(); + final protected Set recordedMetaId = new HashSet<>(); /** * @param user @@ -91,7 +91,7 @@ public class Field2Schema { boolean schemaReady = schema2Database(entity, new Field[]{field}); if (!schemaReady) { - Application.getCommonsService().delete(tempMetaId.toArray(new ID[0])); + Application.getCommonsService().delete(recordedMetaId.toArray(new ID[0])); throw new MetadataModificationException(Language.L("无法同步元数据到数据库")); } @@ -292,7 +292,7 @@ public class Field2Schema { } recordOfField = Application.getCommonsService().create(recordOfField); - tempMetaId.add(recordOfField.getPrimary()); + recordedMetaId.add(recordOfField.getPrimary()); // 以下会改变一些属性,因为并不想他们保存在元数据中 diff --git a/src/main/java/com/rebuild/core/service/approval/ApprovalFields2Schema.java b/src/main/java/com/rebuild/core/service/approval/ApprovalFields2Schema.java index d1660ffe2..22b9a324a 100644 --- a/src/main/java/com/rebuild/core/service/approval/ApprovalFields2Schema.java +++ b/src/main/java/com/rebuild/core/service/approval/ApprovalFields2Schema.java @@ -40,10 +40,15 @@ public class ApprovalFields2Schema extends Field2Schema { */ public boolean createFields(Entity approvalEntity) throws MetadataModificationException { if (MetadataHelper.hasApprovalField(approvalEntity)) { + if (!approvalEntity.containsField(EntityHelper.ApprovalLastUser)) { + return createApporvalLastUser(approvalEntity); + } return false; } - if (!(MetadataHelper.hasPrivilegesField(approvalEntity) || EasyMetaFactory.valueOf(approvalEntity).isPlainEntity())) { - throw new RebuildException("Unsupported entity : " + approvalEntity.getName()); + + if (!(MetadataHelper.hasPrivilegesField(approvalEntity) + || EasyMetaFactory.valueOf(approvalEntity).isPlainEntity())) { + throw new RebuildException("UNSUPPORTED ENTITY : " + approvalEntity.getName()); } Field apporvalId = createUnsafeField(approvalEntity, EntityHelper.ApprovalId, Language.L("审批流程"), @@ -52,16 +57,36 @@ public class ApprovalFields2Schema extends Field2Schema { DisplayType.STATE, true, false, false, true, true, null, null, null, null, ApprovalState.DRAFT.getState()); Field apporvalStepId = createUnsafeField(approvalEntity, EntityHelper.ApprovalStepNode, Language.L("审批步骤"), DisplayType.TEXT, true, false, false, true, false, null, null, null, null, null); + Field apporvalLastUser = buildApporvalLastUser(approvalEntity); boolean schemaReady = schema2Database(approvalEntity, - new Field[] { apporvalId, apporvalState, apporvalStepId }); + new Field[] { apporvalId, apporvalState, apporvalStepId, apporvalLastUser }); if (!schemaReady) { - Application.getCommonsService().delete(tempMetaId.toArray(new ID[0])); + Application.getCommonsService().delete(recordedMetaId.toArray(new ID[0])); throw new MetadataModificationException(Language.L("无法同步元数据到数据库")); } MetadataHelper.getMetadataFactory().refresh(false); return true; } + + // v2.7 最后审批人 + private boolean createApporvalLastUser(Entity approvalEntity) { + Field apporvalLastUser = buildApporvalLastUser(approvalEntity); + boolean schemaReady = schema2Database(approvalEntity, new Field[] { apporvalLastUser }); + + if (!schemaReady) { + Application.getCommonsService().delete(recordedMetaId.toArray(new ID[0])); + throw new MetadataModificationException(Language.L("无法同步元数据到数据库")); + } + + MetadataHelper.getMetadataFactory().refresh(false); + return true; + } + + private Field buildApporvalLastUser(Entity approvalEntity) { + return createUnsafeField(approvalEntity, EntityHelper.ApprovalLastUser, Language.L("最后审批人"), + DisplayType.REFERENCE, true, false, false, true, true, null, "User", CascadeModel.Ignore, null, null); + } } diff --git a/src/main/java/com/rebuild/core/service/approval/ApprovalProcessor.java b/src/main/java/com/rebuild/core/service/approval/ApprovalProcessor.java index 9971b636e..963b8d693 100644 --- a/src/main/java/com/rebuild/core/service/approval/ApprovalProcessor.java +++ b/src/main/java/com/rebuild/core/service/approval/ApprovalProcessor.java @@ -93,11 +93,14 @@ public class ApprovalProcessor extends SetUser { Set ccs = nextNodes.getCcUsers(this.getUser(), this.record, selectNextUsers); Set ccs4share = nextNodes.getCcUsers4Share(this.getUser(), this.record, selectNextUsers); - Record mainRecord = EntityHelper.forUpdate(this.record, this.getUser(), false); - mainRecord.setID(EntityHelper.ApprovalId, this.approval); - mainRecord.setInt(EntityHelper.ApprovalState, ApprovalState.PROCESSING.getState()); - mainRecord.setString(EntityHelper.ApprovalStepNode, nextNodes.getApprovalNode().getNodeId()); - Application.getBean(ApprovalStepService.class).txSubmit(mainRecord, ccs, nextApprovers); + Record recordOfMain = EntityHelper.forUpdate(this.record, this.getUser(), false); + recordOfMain.setID(EntityHelper.ApprovalId, this.approval); + recordOfMain.setInt(EntityHelper.ApprovalState, ApprovalState.PROCESSING.getState()); + recordOfMain.setString(EntityHelper.ApprovalStepNode, nextNodes.getApprovalNode().getNodeId()); + if (recordOfMain.getEntity().containsField(EntityHelper.ApprovalLastUser)) { + recordOfMain.setNull(EntityHelper.ApprovalLastUser); + } + Application.getBean(ApprovalStepService.class).txSubmit(recordOfMain, ccs, nextApprovers); // 非主事物 shareIfNeed(this.record, ccs4share); diff --git a/src/main/java/com/rebuild/core/service/approval/ApprovalStepService.java b/src/main/java/com/rebuild/core/service/approval/ApprovalStepService.java index 24a6405ae..8dbab67da 100644 --- a/src/main/java/com/rebuild/core/service/approval/ApprovalStepService.java +++ b/src/main/java/com/rebuild/core/service/approval/ApprovalStepService.java @@ -23,6 +23,7 @@ import com.rebuild.core.service.DataSpecificationNoRollbackException; import com.rebuild.core.service.general.GeneralEntityServiceContextHolder; import com.rebuild.core.service.notification.MessageBuilder; import com.rebuild.core.support.i18n.Language; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.Set; @@ -36,6 +37,7 @@ import java.util.Set; * @author devezhao * @since 07/11/2019 */ +@Slf4j @Service public class ApprovalStepService extends BaseService { @@ -167,6 +169,9 @@ public class ApprovalStepService extends BaseService { // 更新主记录状态 Record recordOfMain = EntityHelper.forUpdate(recordId, UserService.SYSTEM_USER, false); recordOfMain.setInt(EntityHelper.ApprovalState, ApprovalState.REJECTED.getState()); + if (recordOfMain.getEntity().containsField(EntityHelper.ApprovalLastUser)) { + recordOfMain.setID(EntityHelper.ApprovalLastUser, approver); + } super.update(recordOfMain); String rejectedMsg = Language.L("@%s 驳回了你的 %s 审批", approver, entityLabel); @@ -218,7 +223,7 @@ public class ApprovalStepService extends BaseService { // 最终状态(审批通过) if (goNextNode && (nextApprovers == null || nextNode == null)) { - Application.getEntityService(recordId.getEntityCode()).approve(recordId, ApprovalState.APPROVED); + Application.getEntityService(recordId.getEntityCode()).approve(recordId, ApprovalState.APPROVED, approver); return; } @@ -226,6 +231,9 @@ public class ApprovalStepService extends BaseService { if (goNextNode) { Record recordOfMain = EntityHelper.forUpdate(recordId, UserService.SYSTEM_USER, false); recordOfMain.setString(EntityHelper.ApprovalStepNode, nextNode); + if (recordOfMain.getEntity().containsField(EntityHelper.ApprovalLastUser)) { + recordOfMain.setID(EntityHelper.ApprovalLastUser, approver); + } super.update(recordOfMain); } @@ -269,7 +277,7 @@ public class ApprovalStepService extends BaseService { // 撤销 if (isRevoke) { - Application.getEntityService(recordId.getEntityCode()).approve(recordId, ApprovalState.REVOKED); + Application.getEntityService(recordId.getEntityCode()).approve(recordId, ApprovalState.REVOKED, null); } else { Record recordOfMain = EntityHelper.forUpdate(recordId, UserService.SYSTEM_USER, false); recordOfMain.setInt(EntityHelper.ApprovalState, useState.getState()); @@ -387,8 +395,10 @@ public class ApprovalStepService extends BaseService { final ApprovalState currentState = ApprovalHelper.getApprovalState(recordId); // 其他状态不能自动审批 - if (currentState == ApprovalState.DRAFT || currentState == ApprovalState.REJECTED + if (currentState == ApprovalState.DRAFT + || currentState == ApprovalState.REJECTED || currentState == ApprovalState.REVOKED) { + if (useApprover == null) useApprover = UserService.SYSTEM_USER; if (useApproval == null) useApproval = APPROVAL_NOID; @@ -404,10 +414,13 @@ public class ApprovalStepService extends BaseService { recordOfMain.setID(EntityHelper.ApprovalId, useApproval); recordOfMain.setString(EntityHelper.ApprovalStepNode, FlowNode.NODE_AUTOAPPROVAL); super.update(recordOfMain); - Application.getEntityService(recordId.getEntityCode()).approve(recordId, ApprovalState.APPROVED); + Application.getEntityService(recordId.getEntityCode()).approve(recordId, ApprovalState.APPROVED, useApprover); return true; + + } else { + log.warn("Invalid state {} for auto approval", currentState); + return false; } - return false; } } diff --git a/src/main/java/com/rebuild/core/service/general/EntityService.java b/src/main/java/com/rebuild/core/service/general/EntityService.java index cdf00c9eb..46cfa745e 100644 --- a/src/main/java/com/rebuild/core/service/general/EntityService.java +++ b/src/main/java/com/rebuild/core/service/general/EntityService.java @@ -114,7 +114,8 @@ public interface EntityService extends ServiceSpec { * * @param record * @param state 只接受通过或撤销 + * @param approvalUser 审批人 * @see com.rebuild.core.service.approval.ApprovalStepService */ - void approve(ID record, ApprovalState state); + void approve(ID record, ApprovalState state, ID approvalUser); } diff --git a/src/main/java/com/rebuild/core/service/general/GeneralEntityService.java b/src/main/java/com/rebuild/core/service/general/GeneralEntityService.java index adbef415b..786cbbd6a 100644 --- a/src/main/java/com/rebuild/core/service/general/GeneralEntityService.java +++ b/src/main/java/com/rebuild/core/service/general/GeneralEntityService.java @@ -541,13 +541,19 @@ public class GeneralEntityService extends ObservableService implements EntitySer } @Override - public void approve(ID record, ApprovalState state) { + public void approve(ID record, ApprovalState state, ID approvalUser) { Assert.isTrue( state == ApprovalState.REVOKED || state == ApprovalState.APPROVED, "Only REVOKED or APPROVED allowed"); Record approvalRecord = EntityHelper.forUpdate(record, UserService.SYSTEM_USER, false); approvalRecord.setInt(EntityHelper.ApprovalState, state.getState()); + if (state == ApprovalState.APPROVED + && approvalUser != null + && MetadataHelper.getEntity(record.getEntityCode()).containsField(EntityHelper.ApprovalLastUser)) { + approvalRecord.setID(EntityHelper.ApprovalLastUser, approvalUser); + } + delegateService.update(approvalRecord); // 触发器 diff --git a/src/main/java/com/rebuild/web/general/ReferenceSearchController.java b/src/main/java/com/rebuild/web/general/ReferenceSearchController.java index 7ab4f5d41..a8c09912b 100644 --- a/src/main/java/com/rebuild/web/general/ReferenceSearchController.java +++ b/src/main/java/com/rebuild/web/general/ReferenceSearchController.java @@ -177,7 +177,7 @@ public class ReferenceSearchController extends EntityController { private List resultSearch(String sqlWhere, Entity entity, int maxResults) { Field nameField = entity.getNameField(); - String sql = MessageFormat.format("select {0},{1} from {2} where {3}", + String sql = MessageFormat.format("select {0},{1} from {2} where ({3})", entity.getPrimaryField().getName(), nameField.getName(), entity.getName(), sqlWhere); if (!sqlWhere.contains(" order by ")) { diff --git a/src/main/resources/web/assets/css/rb-page.css b/src/main/resources/web/assets/css/rb-page.css index fe1c173ba..cc8b88b37 100644 --- a/src/main/resources/web/assets/css/rb-page.css +++ b/src/main/resources/web/assets/css/rb-page.css @@ -2840,21 +2840,27 @@ form { margin: 0 -5px; } -.form.approval-form .form-group { +.form.approval-form > .form-group { padding: 0 20px; } -.form.approval-form .form-group .zicon { +.form.approval-form > .form-group .zicon { float: left; padding-right: 6px; width: 18px; } -.form.approval-form .form-group .zicon.zmdi-mail-send { +.form.approval-form > .form-group .zicon.zmdi-mail-send { font-size: 1.1rem; margin-top: 2px; } +.form.approval-form .rbform { + background-color: #f5f5f5; + border-radius: 2px; + padding: 15px; +} + .form.approval-form .approval-list { padding: 5px 0; } @@ -3011,16 +3017,6 @@ form { text-align: center; } -.form.approval-form .rbform { - background-color: #f5f5f5; - border-radius: 3px; - padding: 12px 0; -} - -.form.approval-form .rbform .form-group.row { - padding: 10px 0; -} - .notification-page { padding: 0 10px; } diff --git a/src/main/resources/web/assets/js/rb-approval.js b/src/main/resources/web/assets/js/rb-approval.js index f094a01c4..6eaad15f3 100644 --- a/src/main/resources/web/assets/js/rb-approval.js +++ b/src/main/resources/web/assets/js/rb-approval.js @@ -419,6 +419,7 @@ class ApprovalApproveForm extends ApprovalUsersForm { (this._rbform = c)}> {this.state.aform.map((item) => { + item.isFull = true // eslint-disable-next-line no-undef return detectElement(item) })} diff --git a/src/main/resources/web/assets/js/rb-datalist.common.js b/src/main/resources/web/assets/js/rb-datalist.common.js index 363438440..83de82b29 100644 --- a/src/main/resources/web/assets/js/rb-datalist.common.js +++ b/src/main/resources/web/assets/js/rb-datalist.common.js @@ -555,7 +555,7 @@ const RbListCommon = { }) // via 过滤 - const via = $urlp('via', location.hash) + const via = $urlp('via') || $urlp('via', location.hash) if (via) { wpc.protocolFilter = `via:${via}` const $cleanVia = $(`
${$L('当前数据已过滤')}×
`).appendTo('.dataTables_filter') diff --git a/src/main/resources/web/assets/js/rb-view.js b/src/main/resources/web/assets/js/rb-view.js index 83dd7eef7..c16cfe626 100644 --- a/src/main/resources/web/assets/js/rb-view.js +++ b/src/main/resources/web/assets/js/rb-view.js @@ -36,15 +36,21 @@ class RbViewForm extends React.Component { } let hadApproval = res.data.hadApproval + let hadAlert = null if (wpc.type === 'DetailView') { - if (hadApproval === 2) $('.J_edit, .J_delete').attr({ disabled: true, title: $L('主记录正在审批中') }) - else if (hadApproval === 10) $('.J_edit, .J_delete').remove() + if (hadApproval === 2 || hadApproval === 10) { + if (window.RbViewPage) window.RbViewPage.setReadonly() + else $('.J_edit, .J_delete').remove() + + hadAlert = + } hadApproval = null } const viewData = {} const VFORM = ( + {hadAlert} {hadApproval && }
{res.data.elements.map((item) => {