feat: 归档前校验钩子与价格表查看接口接缝(#57/#58)

This commit is contained in:
weicw
2026-10-31 06:37:16 +08:00
parent e6442c1777
commit a99b97ac8a
7 changed files with 160 additions and 0 deletions
@@ -0,0 +1,33 @@
package com.gxwebsoft.approval.controller;
import com.gxwebsoft.approval.service.ApprovalPriceService;
import com.gxwebsoft.approval.vo.ApprovalPriceViewVO;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 设施价格表只读接口:受众全体员工,独立权限点 `approval:price:view`(ADR 0008)。
*/
@Api(tags = "设施价格表")
@RestController
@RequestMapping("/api/approval/price")
public class ApprovalPriceController extends BaseController {
@Resource
private ApprovalPriceService priceService;
@PreAuthorize("hasAuthority('approval:price:view')")
@ApiOperation("当前生效版本与历史版本")
@GetMapping
public ApiResult<ApprovalPriceViewVO> view() {
return success(priceService.view());
}
}
@@ -110,4 +110,11 @@ public interface ApprovalDocumentType {
/** 撤回/驳回时清空本单需清空的字段(业务表不随引擎回滚)。 */
default void onRoundReset(ApprovalInstance instance, User user) {
}
/**
* 归档前校验:单据可在归档时拒绝(如价格表不允许追溯生效日期)。
* 失败抛 BusinessException。
*/
default void validateBeforeArchive(ApprovalInstance instance) {
}
}
@@ -0,0 +1,17 @@
package com.gxwebsoft.approval.document;
import java.util.List;
/**
* 价格表查询提供者:只读视图的接缝(ADR 0008 / 0012)。
*
* <p>价格表单据实现注册为 Bean 后,价格查看页只依赖本接口;没有实现时页面返回明确空态。</p>
*/
public interface ApprovalPriceProvider {
/** 当前生效版本:已归档且生效日期不晚于今天的最新一版;无则 null。 */
ApprovalPriceVersion current();
/** 历史版本:已归档版本按生效日期倒序,最多 {@code limit} 条。 */
List<ApprovalPriceVersion> history(int limit);
}
@@ -0,0 +1,39 @@
package com.gxwebsoft.approval.document;
import com.gxwebsoft.approval.support.ApprovalLineSpec;
import com.gxwebsoft.approval.vo.ApprovalFieldVO;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 价格表版本(审批实例即版本,ADR 0012):当前生效版本与历史版本共用本结构。
*/
@Data
public class ApprovalPriceVersion implements Serializable {
private static final long serialVersionUID = 1L;
private Long instanceId;
private String bizNo;
private LocalDate effectiveDate;
private LocalDateTime archiveTime;
private String reportOrgName;
private List<ApprovalFieldVO> fields = new ArrayList<>();
private List<Map<String, Object>> lines = new ArrayList<>();
private List<ApprovalLineSpec> lineColumns = new ArrayList<>();
private BigDecimal amountTotal;
}
@@ -0,0 +1,39 @@
package com.gxwebsoft.approval.service;
import com.gxwebsoft.approval.document.ApprovalPriceProvider;
import com.gxwebsoft.approval.document.ApprovalPriceVersion;
import com.gxwebsoft.approval.vo.ApprovalPriceViewVO;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* 价格表只读查询:当前生效版本 + 历史版本(ADR 0008 / 0012)。
*
* <p>没有任何价格表实现时返回空态,不抛异常——页面需要展示明确空态而不是报错。</p>
*/
@Service
public class ApprovalPriceService {
/** 历史版本默认展示条数。 */
private static final int DEFAULT_HISTORY_LIMIT = 50;
@Resource
private org.springframework.beans.factory.ObjectProvider<ApprovalPriceProvider> provider;
public ApprovalPriceViewVO view() {
ApprovalPriceProvider priceProvider = provider.getIfAvailable();
ApprovalPriceViewVO vo = new ApprovalPriceViewVO();
if (priceProvider == null) {
vo.setCurrent(null);
vo.setHistory(new ArrayList<>());
return vo;
}
vo.setCurrent(priceProvider.current());
List<ApprovalPriceVersion> history = priceProvider.history(DEFAULT_HISTORY_LIMIT);
vo.setHistory(history == null ? new ArrayList<>() : history);
return vo;
}
}
@@ -374,6 +374,10 @@ public class ApprovalTaskService {
if (!ApprovalConstants.STATUS_APPROVED.equals(locked.getStatus())) {
throw new BusinessException("单据状态已变化,请刷新后重试");
}
ApprovalDocumentType documentType = documentRegistry.find(locked.getFlowCode());
if (documentType != null) {
documentType.validateBeforeArchive(locked);
}
ensureTaskCurrent(task, locked);
if (updatePendingTask(taskId, ApprovalConstants.TASK_DONE, null) == 0) {
throw new BusinessException("任务已处理");
@@ -0,0 +1,21 @@
package com.gxwebsoft.approval.vo;
import com.gxwebsoft.approval.document.ApprovalPriceVersion;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 价格表查看页数据:上半部分当前生效版本,下半部分历史版本(按生效日期倒序)。
*/
@Data
@ApiModel(description = "价格表查看")
public class ApprovalPriceViewVO implements Serializable {
private static final long serialVersionUID = 1L;
private ApprovalPriceVersion current;
private List<ApprovalPriceVersion> history;
}