🐛 修复收款流水继续认领与付款可付口径,并改用OA登录名提交流程
收款流水部分认领预填关联结算单并修正认领完成判定;正式结算尾款扣减预付占用;预付驳回重提纠正结算引用;临时额度取消强制项目额度校验;用户增加OA登录名供MK流程使用。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+6
@@ -39,6 +39,7 @@ import java.time.LocalDate;
|
|||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 收款流水视图实体类
|
* 收款流水视图实体类
|
||||||
@@ -91,4 +92,9 @@ public class ReceiptFlowVO extends KingdeeReceiptFlow {
|
|||||||
private BigDecimal receiptAmountEnd;
|
private BigDecimal receiptAmountEnd;
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
private List<ReceiptFlowRecord> claimRecords = new ArrayList<>();
|
private List<ReceiptFlowRecord> claimRecords = new ArrayList<>();
|
||||||
|
/**
|
||||||
|
* 本流水历史关联且仍有剩余可认领金额的应收正式结算单(继续认领时预填)
|
||||||
|
*/
|
||||||
|
@TableField(exist = false)
|
||||||
|
private List<Map<String, Object>> relatedSettlements = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|||||||
+4
@@ -132,6 +132,10 @@ public class User extends TenantEntity implements IPhone {
|
|||||||
* 是否是oa的账号
|
* 是否是oa的账号
|
||||||
*/
|
*/
|
||||||
private Integer isOa;
|
private Integer isOa;
|
||||||
|
/**
|
||||||
|
* OA登录名
|
||||||
|
*/
|
||||||
|
private String oaLoginId;
|
||||||
/**
|
/**
|
||||||
* OA上次更新时间(OA 的 modified 字段),仅同步比对使用
|
* OA上次更新时间(OA 的 modified 字段),仅同步比对使用
|
||||||
*/
|
*/
|
||||||
|
|||||||
-2
@@ -11,7 +11,6 @@ import lombok.AllArgsConstructor;
|
|||||||
import org.springblade.core.boot.ctrl.BladeController;
|
import org.springblade.core.boot.ctrl.BladeController;
|
||||||
import org.springblade.core.mp.support.Condition;
|
import org.springblade.core.mp.support.Condition;
|
||||||
import org.springblade.core.mp.support.Query;
|
import org.springblade.core.mp.support.Query;
|
||||||
import org.springblade.core.secure.utils.AuthUtil;
|
|
||||||
import org.springblade.core.tool.api.R;
|
import org.springblade.core.tool.api.R;
|
||||||
import org.springblade.core.tool.utils.StringUtil;
|
import org.springblade.core.tool.utils.StringUtil;
|
||||||
import org.springblade.process.pojo.dto.ApprovalDTO;
|
import org.springblade.process.pojo.dto.ApprovalDTO;
|
||||||
@@ -49,7 +48,6 @@ public class BusinessProcessController extends BladeController {
|
|||||||
if (param == null) {
|
if (param == null) {
|
||||||
param = new ApprovalDTO();
|
param = new ApprovalDTO();
|
||||||
}
|
}
|
||||||
param.setLoginName(AuthUtil.getUserAccount());
|
|
||||||
IPage<ApprovalVO> pages = businessProcessService.queryMkApprovalList(Condition.getPage(query), param);
|
IPage<ApprovalVO> pages = businessProcessService.queryMkApprovalList(Condition.getPage(query), param);
|
||||||
return R.data(pages);
|
return R.data(pages);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -71,7 +71,7 @@ public interface IBusinessProcessService extends IService<BusinessProcess> {
|
|||||||
* 获取流程当前节点详情
|
* 获取流程当前节点详情
|
||||||
*
|
*
|
||||||
* @param processInstanceId 流程实例id
|
* @param processInstanceId 流程实例id
|
||||||
* @param loginName MK登录名(手机号),可为空,为空时按流程发起人解析
|
* @param loginName MK登录名(OA登录名),可为空,为空时按流程发起人解析
|
||||||
* @return 当前节点列表
|
* @return 当前节点列表
|
||||||
*/
|
*/
|
||||||
List<?> getCurrentNodes(String processInstanceId, String loginName);
|
List<?> getCurrentNodes(String processInstanceId, String loginName);
|
||||||
@@ -80,7 +80,7 @@ public interface IBusinessProcessService extends IService<BusinessProcess> {
|
|||||||
* 获取流程实例详情
|
* 获取流程实例详情
|
||||||
*
|
*
|
||||||
* @param processInstanceId 流程实例id
|
* @param processInstanceId 流程实例id
|
||||||
* @param loginName MK登录名(手机号),可为空,为空时按流程发起人解析
|
* @param loginName MK登录名(OA登录名),可为空,为空时按流程发起人解析
|
||||||
* @return 流程实例详情
|
* @return 流程实例详情
|
||||||
*/
|
*/
|
||||||
Object getProcessInfo(String processInstanceId, String loginName);
|
Object getProcessInfo(String processInstanceId, String loginName);
|
||||||
|
|||||||
+22
-28
@@ -132,9 +132,9 @@ public class BusinessProcessServiceImpl extends ServiceImpl<BusinessProcessMappe
|
|||||||
public String processSubmit(MKProcessCreateDTO param) {
|
public String processSubmit(MKProcessCreateDTO param) {
|
||||||
AssertUtils.notNull(param, "提交流程参数不能为空");
|
AssertUtils.notNull(param, "提交流程参数不能为空");
|
||||||
AssertUtils.notBlank(param.getTemplateCode(), "模板编码不能为空");
|
AssertUtils.notBlank(param.getTemplateCode(), "模板编码不能为空");
|
||||||
// 前端拿到的手机号可能经 @Sensitive 脱敏(如 137****8880),这里从库取真实手机号覆盖
|
// MK loginName 使用当前用户 OA 登录名,未配置则不允许提交
|
||||||
String loginName = resolveCurrentUserPhone();
|
String loginName = resolveCurrentUserOaLoginId();
|
||||||
AssertUtils.notBlank(loginName, "当前用户手机号为空,无法提交审核流");
|
AssertUtils.notBlank(loginName, "当前用户OA登录名为空,无法提交审核流");
|
||||||
param.setSubmitIdentity(loginName);
|
param.setSubmitIdentity(loginName);
|
||||||
param.setLoginName(loginName);
|
param.setLoginName(loginName);
|
||||||
String bizType = param.getBizType();
|
String bizType = param.getBizType();
|
||||||
@@ -258,7 +258,7 @@ public class BusinessProcessServiceImpl extends ServiceImpl<BusinessProcessMappe
|
|||||||
resolvedLoginName = businessProcess.getPromoterLoginName();
|
resolvedLoginName = businessProcess.getPromoterLoginName();
|
||||||
}
|
}
|
||||||
if (StringUtil.isBlank(resolvedLoginName)) {
|
if (StringUtil.isBlank(resolvedLoginName)) {
|
||||||
resolvedLoginName = resolveCurrentUserPhone();
|
resolvedLoginName = resolveCurrentUserOaLoginId();
|
||||||
}
|
}
|
||||||
if (StringUtil.isBlank(resolvedLoginName)) {
|
if (StringUtil.isBlank(resolvedLoginName)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -291,10 +291,10 @@ public class BusinessProcessServiceImpl extends ServiceImpl<BusinessProcessMappe
|
|||||||
}
|
}
|
||||||
String loginName = businessProcess.getPromoterLoginName();
|
String loginName = businessProcess.getPromoterLoginName();
|
||||||
if (StringUtil.isBlank(loginName)) {
|
if (StringUtil.isBlank(loginName)) {
|
||||||
loginName = resolveCurrentUserPhone();
|
loginName = resolveCurrentUserOaLoginId();
|
||||||
}
|
}
|
||||||
if (StringUtil.isBlank(loginName)) {
|
if (StringUtil.isBlank(loginName)) {
|
||||||
log.warn("查询MK流程实例跳过,登录名为空 bizId={} processInstanceId={}",
|
log.warn("查询MK流程实例跳过,OA登录名为空 bizId={} processInstanceId={}",
|
||||||
bizId, businessProcess.getProcessInstanceId());
|
bizId, businessProcess.getProcessInstanceId());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -357,9 +357,9 @@ public class BusinessProcessServiceImpl extends ServiceImpl<BusinessProcessMappe
|
|||||||
}
|
}
|
||||||
String loginName = businessProcess.getPromoterLoginName();
|
String loginName = businessProcess.getPromoterLoginName();
|
||||||
if (StringUtil.isBlank(loginName)) {
|
if (StringUtil.isBlank(loginName)) {
|
||||||
loginName = resolveCurrentUserPhone();
|
loginName = resolveCurrentUserOaLoginId();
|
||||||
}
|
}
|
||||||
AssertUtils.notBlank(loginName, "当前用户手机号为空,无法删除审核流");
|
AssertUtils.notBlank(loginName, "当前用户OA登录名为空,无法删除审核流");
|
||||||
log.info("调用mk processDelete processInstanceId={} loginName={} bizId={} formInstanceId={}",
|
log.info("调用mk processDelete processInstanceId={} loginName={} bizId={} formInstanceId={}",
|
||||||
businessProcess.getProcessInstanceId(), loginName, bizId, businessProcess.getFormInstanceId());
|
businessProcess.getProcessInstanceId(), loginName, bizId, businessProcess.getFormInstanceId());
|
||||||
boolean deleted = mkService.processDelete(businessProcess.getProcessInstanceId(), loginName);
|
boolean deleted = mkService.processDelete(businessProcess.getProcessInstanceId(), loginName);
|
||||||
@@ -563,28 +563,19 @@ public class BusinessProcessServiceImpl extends ServiceImpl<BusinessProcessMappe
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从当前登录用户实体读取真实手机号(库内 SM2 密文先解密,绕过接口脱敏)
|
* 从当前登录用户实体读取 OA 登录名,作为 MK 接口 loginName
|
||||||
*/
|
*/
|
||||||
private String resolveCurrentUserPhone() {
|
private String resolveCurrentUserOaLoginId() {
|
||||||
Long userId = AuthUtil.getUserId();
|
Long userId = AuthUtil.getUserId();
|
||||||
if (userId != null) {
|
if (userId == null) {
|
||||||
User user = userService.getById(userId);
|
|
||||||
if (user != null) {
|
|
||||||
userService.decryptPhone(user);
|
|
||||||
if (StringUtil.isNotBlank(user.getPhone()) && !user.getPhone().contains("*")) {
|
|
||||||
return user.getPhone().trim();
|
|
||||||
}
|
|
||||||
if (StringUtil.isNotBlank(user.getAccount()) && user.getAccount().matches("^1\\d{10}$")) {
|
|
||||||
return user.getAccount().trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String account = AuthUtil.getUserAccount();
|
|
||||||
if (StringUtil.isNotBlank(account) && account.matches("^1\\d{10}$")) {
|
|
||||||
return account.trim();
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
User user = userService.getById(userId);
|
||||||
|
if (user == null || StringUtil.isBlank(user.getOaLoginId())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return user.getOaLoginId().trim();
|
||||||
|
}
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@Override
|
@Override
|
||||||
@@ -703,8 +694,8 @@ public class BusinessProcessServiceImpl extends ServiceImpl<BusinessProcessMappe
|
|||||||
processInstanceId = businessProcess.getProcessInstanceId();
|
processInstanceId = businessProcess.getProcessInstanceId();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
String loginName = resolveCurrentUserPhone();
|
String loginName = resolveCurrentUserOaLoginId();
|
||||||
AssertUtils.notBlank(loginName, "当前用户手机号为空,无法获取审核跳转地址");
|
AssertUtils.notBlank(loginName, "当前用户OA登录名为空,无法获取审核跳转地址");
|
||||||
String mkApprovalUrl = mkService.getMKApprovalUrl(processInstanceId, loginName);
|
String mkApprovalUrl = mkService.getMKApprovalUrl(processInstanceId, loginName);
|
||||||
AssertUtils.notBlank(mkApprovalUrl, "获取mk审批页面链接异常");
|
AssertUtils.notBlank(mkApprovalUrl, "获取mk审批页面链接异常");
|
||||||
return mkApprovalUrl;
|
return mkApprovalUrl;
|
||||||
@@ -921,6 +912,9 @@ public class BusinessProcessServiceImpl extends ServiceImpl<BusinessProcessMappe
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IPage<ApprovalVO> queryMkApprovalList(IPage<ApprovalVO> page, ApprovalDTO param) {
|
public IPage<ApprovalVO> queryMkApprovalList(IPage<ApprovalVO> page, ApprovalDTO param) {
|
||||||
|
String loginName = resolveCurrentUserOaLoginId();
|
||||||
|
AssertUtils.notBlank(loginName, "当前用户OA登录名为空,无法查询审核列表");
|
||||||
|
param.setLoginName(loginName);
|
||||||
if (MKDoc.RELATED.getCode().equals(param.getDocType())) {
|
if (MKDoc.RELATED.getCode().equals(param.getDocType())) {
|
||||||
// 我参与的,调用流程列表接口
|
// 我参与的,调用流程列表接口
|
||||||
MKProcessDTO processParam = approvalConvert.dto2mk(param);
|
MKProcessDTO processParam = approvalConvert.dto2mk(param);
|
||||||
|
|||||||
+1
@@ -70,6 +70,7 @@ public interface UserConvert {
|
|||||||
@Mapping(source = "lastname", target = "realName")
|
@Mapping(source = "lastname", target = "realName")
|
||||||
@Mapping(source = "mobile", target = "phone")
|
@Mapping(source = "mobile", target = "phone")
|
||||||
@Mapping(source = "email", target = "email")
|
@Mapping(source = "email", target = "email")
|
||||||
|
@Mapping(source = "loginid", target = "oaLoginId")
|
||||||
@Mapping(source = "modified", target = "oaModified")
|
@Mapping(source = "modified", target = "oaModified")
|
||||||
User baseConvert(OAPersonResponse person);
|
User baseConvert(OAPersonResponse person);
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
<result column="dept_id" property="deptId"/>
|
<result column="dept_id" property="deptId"/>
|
||||||
<result column="post_id" property="postId"/>
|
<result column="post_id" property="postId"/>
|
||||||
<result column="remark" property="remark"/>
|
<result column="remark" property="remark"/>
|
||||||
|
<result column="oa_login_id" property="oaLoginId"/>
|
||||||
<result column="oa_person_id" property="oaPersonId"/>
|
<result column="oa_person_id" property="oaPersonId"/>
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
|
|||||||
+1
@@ -366,6 +366,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
|
|||||||
user.setPostId(null);
|
user.setPostId(null);
|
||||||
user.setAccount(null);
|
user.setAccount(null);
|
||||||
user.setIsLeader(null);
|
user.setIsLeader(null);
|
||||||
|
user.setOaLoginId(null);
|
||||||
CacheUtil.clear(USER_CACHE);
|
CacheUtil.clear(USER_CACHE);
|
||||||
return submitUserInfo(user);
|
return submitUserInfo(user);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -1729,7 +1729,8 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
|||||||
Map<Long, BigDecimal> receiptClaimPaidBySettlement = hasReceivable
|
Map<Long, BigDecimal> receiptClaimPaidBySettlement = hasReceivable
|
||||||
? receiptClaimSettlementMapper.selectList(Wrappers.<ReceiptClaimSettlement>lambdaQuery()
|
? receiptClaimSettlementMapper.selectList(Wrappers.<ReceiptClaimSettlement>lambdaQuery()
|
||||||
.in(ReceiptClaimSettlement::getFormalSettlementId, settledIds)
|
.in(ReceiptClaimSettlement::getFormalSettlementId, settledIds)
|
||||||
.eq(ReceiptClaimSettlement::getStatus, 1)).stream()
|
.eq(ReceiptClaimSettlement::getStatus, 1)
|
||||||
|
.eq(ReceiptClaimSettlement::getIsDeleted, 0)).stream()
|
||||||
.collect(Collectors.groupingBy(ReceiptClaimSettlement::getFormalSettlementId,
|
.collect(Collectors.groupingBy(ReceiptClaimSettlement::getFormalSettlementId,
|
||||||
Collectors.reducing(BigDecimal.ZERO,
|
Collectors.reducing(BigDecimal.ZERO,
|
||||||
item -> money(item.getAllocatedReceiptAmount()), BigDecimal::add)))
|
item -> money(item.getAllocatedReceiptAmount()), BigDecimal::add)))
|
||||||
@@ -2161,7 +2162,8 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
|
|||||||
: receiptClaimSettlementMapper.selectList(
|
: receiptClaimSettlementMapper.selectList(
|
||||||
Wrappers.<ReceiptClaimSettlement>lambdaQuery()
|
Wrappers.<ReceiptClaimSettlement>lambdaQuery()
|
||||||
.eq(ReceiptClaimSettlement::getFormalSettlementId, settlement.getId())
|
.eq(ReceiptClaimSettlement::getFormalSettlementId, settlement.getId())
|
||||||
.eq(ReceiptClaimSettlement::getStatus, 1))
|
.eq(ReceiptClaimSettlement::getStatus, 1)
|
||||||
|
.eq(ReceiptClaimSettlement::getIsDeleted, 0))
|
||||||
.stream().map(ReceiptClaimSettlement::getAllocatedReceiptAmount).map(this::money)
|
.stream().map(ReceiptClaimSettlement::getAllocatedReceiptAmount).map(this::money)
|
||||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
}
|
}
|
||||||
|
|||||||
+121
-17
@@ -321,11 +321,15 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
|||||||
BigDecimal writeOffAmount = preSettlementReference
|
BigDecimal writeOffAmount = preSettlementReference
|
||||||
? projectAdvanceWriteOffService.sumBySettlement(TransportBusiConstant.SETTLEMENT_BILL_PRE, referenceId)
|
? projectAdvanceWriteOffService.sumBySettlement(TransportBusiConstant.SETTLEMENT_BILL_PRE, referenceId)
|
||||||
: projectAdvanceWriteOffService.sumBySettlement(TransportBusiConstant.SETTLEMENT_BILL_FORMAL, referenceId);
|
: projectAdvanceWriteOffService.sumBySettlement(TransportBusiConstant.SETTLEMENT_BILL_FORMAL, referenceId);
|
||||||
|
// 正式结算尾款还需扣减来源预结算进度预付(与正式结算剩余应付口径一致)
|
||||||
|
BigDecimal advanceOccupied = preSettlementReference
|
||||||
|
? BigDecimal.ZERO
|
||||||
|
: formalSettlementAdvanceOccupied(referenceId);
|
||||||
|
BigDecimal occupiedTotal = cumulativeAppliedAmount.add(writeOffAmount).add(advanceOccupied);
|
||||||
PaymentApplicationReferenceAmountVO amount = new PaymentApplicationReferenceAmountVO();
|
PaymentApplicationReferenceAmountVO amount = new PaymentApplicationReferenceAmountVO();
|
||||||
amount.setSettlementAmount(settlementAmount);
|
amount.setSettlementAmount(settlementAmount);
|
||||||
amount.setCumulativeAppliedAmount(cumulativeAppliedAmount.add(writeOffAmount));
|
amount.setCumulativeAppliedAmount(occupiedTotal);
|
||||||
amount.setPayableAmount(settlementAmount.subtract(cumulativeAppliedAmount).subtract(writeOffAmount)
|
amount.setPayableAmount(settlementAmount.subtract(occupiedTotal).max(BigDecimal.ZERO));
|
||||||
.max(BigDecimal.ZERO));
|
|
||||||
amount.setPaymentSequence(resolvePaymentSequence(preSettlementReference, referenceId, excludeId));
|
amount.setPaymentSequence(resolvePaymentSequence(preSettlementReference, referenceId, excludeId));
|
||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
@@ -1891,7 +1895,7 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 进度预付只认预结算单。尾款付款若同时带回一个并不存在的正式结算单 ID,改为按预结算单保存。
|
* 进度预付只认预结算单;尾款付款若 settlementId 实际是预结算单 ID 或正式结算单已不存在,改为按预结算单保存。
|
||||||
*/
|
*/
|
||||||
private void normalizeSettlementReference(PaymentApplicationSaveRequest request) {
|
private void normalizeSettlementReference(PaymentApplicationSaveRequest request) {
|
||||||
if ("progress_advance".equals(request.getPaymentType())) {
|
if ("progress_advance".equals(request.getPaymentType())) {
|
||||||
@@ -1901,33 +1905,62 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
|||||||
if (request.getPreSettlementId() == null) {
|
if (request.getPreSettlementId() == null) {
|
||||||
request.setPreSettlementId(request.getSettlementId());
|
request.setPreSettlementId(request.getSettlementId());
|
||||||
}
|
}
|
||||||
|
if (request.getPreSettlementId() == null && request.getSettlementIds() != null) {
|
||||||
|
request.setPreSettlementId(request.getSettlementIds().stream().filter(Objects::nonNull).findFirst().orElse(null));
|
||||||
|
}
|
||||||
request.setSettlementId(null);
|
request.setSettlementId(null);
|
||||||
request.setSettlementIds(null);
|
request.setSettlementIds(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!TransportBusiConstant.PAYMENT_TYPE_SETTLEMENT.equals(request.getPaymentType()) || request.getSettlementId() == null) {
|
if (!TransportBusiConstant.PAYMENT_TYPE_SETTLEMENT.equals(request.getPaymentType())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boolean hasPreSettlement = request.getPreSettlementId() != null
|
// settlementIds 中若含无效正式结算单 ID,先尝试纠正为预结算
|
||||||
|| (request.getPreSettlementIds() != null && request.getPreSettlementIds().stream().anyMatch(Objects::nonNull));
|
if (request.getSettlementId() == null && request.getSettlementIds() != null
|
||||||
if (!hasPreSettlement) {
|
&& !request.getSettlementIds().isEmpty()) {
|
||||||
|
request.setSettlementId(request.getSettlementIds().stream().filter(Objects::nonNull).findFirst().orElse(null));
|
||||||
|
}
|
||||||
|
if (request.getSettlementId() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
FormalSettlement formalSettlement = formalSettlementMapper.selectById(request.getSettlementId());
|
FormalSettlement formalSettlement = formalSettlementMapper.selectById(request.getSettlementId());
|
||||||
if (formalSettlement == null || Objects.equals(formalSettlement.getIsDeleted(), 1)) {
|
if (formalSettlement != null && !Objects.equals(formalSettlement.getIsDeleted(), 1)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 正式结算单不存在:若该 ID 实为预结算单,或请求已带预结算引用,则清空正式结算引用
|
||||||
|
PreSettlement preSettlement = preSettlementMapper.selectById(request.getSettlementId());
|
||||||
|
boolean isPreSettlement = preSettlement != null && !Objects.equals(preSettlement.getIsDeleted(), 1);
|
||||||
|
boolean hasPreSettlement = request.getPreSettlementId() != null
|
||||||
|
|| (request.getPreSettlementIds() != null && request.getPreSettlementIds().stream().anyMatch(Objects::nonNull));
|
||||||
|
if (isPreSettlement && request.getPreSettlementId() == null) {
|
||||||
|
request.setPreSettlementId(request.getSettlementId());
|
||||||
|
if (request.getPreSettlementIds() == null || request.getPreSettlementIds().isEmpty()) {
|
||||||
|
request.setPreSettlementIds(List.of(request.getSettlementId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isPreSettlement || hasPreSettlement) {
|
||||||
request.setSettlementId(null);
|
request.setSettlementId(null);
|
||||||
request.setSettlementIds(null);
|
request.setSettlementIds(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 预结算付款不挂正式结算单时,清掉历史误写入的正式结算单 ID,避免再次提交按正式结算单刷新。 */
|
/**
|
||||||
|
* 预结算付款不挂正式结算单时,清掉历史误写入的正式结算单 ID,避免再次提交按正式结算单刷新。
|
||||||
|
*/
|
||||||
private void clearDetachedFormalReference(PaymentApplication entity) {
|
private void clearDetachedFormalReference(PaymentApplication entity) {
|
||||||
if (entity.getId() == null || entity.getPreSettlementId() == null || entity.getSettlementId() != null) {
|
if (entity.getId() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean progressAdvance = "progress_advance".equals(entity.getPaymentType());
|
||||||
|
boolean preOnly = entity.getPreSettlementId() != null && entity.getSettlementId() == null;
|
||||||
|
if (!progressAdvance && !preOnly) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
baseMapper.update(null, Wrappers.<PaymentApplication>lambdaUpdate()
|
baseMapper.update(null, Wrappers.<PaymentApplication>lambdaUpdate()
|
||||||
.eq(PaymentApplication::getId, entity.getId())
|
.eq(PaymentApplication::getId, entity.getId())
|
||||||
.setSql("settlement_id = null, settlement_no = null"));
|
.setSql("settlement_id = null, settlement_no = null"));
|
||||||
|
entity.setSettlementId(null);
|
||||||
|
entity.setSettlementNo(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillReference(PaymentApplication entity, PaymentApplicationSaveRequest request) {
|
private void fillReference(PaymentApplication entity, PaymentApplicationSaveRequest request) {
|
||||||
@@ -1938,15 +1971,26 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
|||||||
entity.setProjectId(request.getProjectId()); entity.setProjectName(request.getProjectName()); entity.setDeptId(request.getDeptId()); entity.setDeptName(request.getDeptName()); entity.setContractId(request.getContractId()); entity.setContractNo(request.getContractNo()); entity.setContractName(request.getContractName()); entity.setPayerName(request.getPayerName()); entity.setPayeeName(request.getPayeeName()); entity.setSettlementAmount(request.getSettlementAmount()); entity.setPayableAmount(money(project.getFundDemand()).multiply(BigDecimal.valueOf(10000))); entity.setBillType(Func.isEmpty(project.getSettlementMode()) ? null : "项目预付");
|
entity.setProjectId(request.getProjectId()); entity.setProjectName(request.getProjectName()); entity.setDeptId(request.getDeptId()); entity.setDeptName(request.getDeptName()); entity.setContractId(request.getContractId()); entity.setContractNo(request.getContractNo()); entity.setContractName(request.getContractName()); entity.setPayerName(request.getPayerName()); entity.setPayeeName(request.getPayeeName()); entity.setSettlementAmount(request.getSettlementAmount()); entity.setPayableAmount(money(project.getFundDemand()).multiply(BigDecimal.valueOf(10000))); entity.setBillType(Func.isEmpty(project.getSettlementMode()) ? null : "项目预付");
|
||||||
} else if (request.getSettlementId() != null) {
|
} else if (request.getSettlementId() != null) {
|
||||||
FormalSettlement source = formalSettlementMapper.selectById(request.getSettlementId());
|
FormalSettlement source = formalSettlementMapper.selectById(request.getSettlementId());
|
||||||
if (source == null) throw new ServiceException("正式结算单不存在");
|
if (source == null || Objects.equals(source.getIsDeleted(), 1)) {
|
||||||
|
// 驳回重提等场景:settlementId 可能误存为预结算单 ID,降级走预结算分支
|
||||||
|
PreSettlement preSettlement = preSettlementMapper.selectById(request.getSettlementId());
|
||||||
|
if (preSettlement != null && !Objects.equals(preSettlement.getIsDeleted(), 1)) {
|
||||||
|
request.setPreSettlementId(preSettlement.getId());
|
||||||
|
request.setSettlementId(null);
|
||||||
|
fillPreSettlementReference(entity, preSettlement);
|
||||||
|
} else if (request.getPreSettlementId() != null) {
|
||||||
|
request.setSettlementId(null);
|
||||||
|
fillPreSettlementReference(entity, requireApprovedPreSettlement(request.getPreSettlementId()));
|
||||||
|
} else {
|
||||||
|
throw new ServiceException("正式结算单不存在");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (!TransportBusiConstant.APPROVED.equals(source.getApprovalStatus())) throw new ServiceException("只能选择审批通过、未作废的正式结算单");
|
if (!TransportBusiConstant.APPROVED.equals(source.getApprovalStatus())) throw new ServiceException("只能选择审批通过、未作废的正式结算单");
|
||||||
entity.setSettlementId(source.getId()); entity.setSettlementNo(source.getFormalSettlementNo()); entity.setPreSettlementId(null); entity.setPreSettlementNo(null);
|
entity.setSettlementId(source.getId()); entity.setSettlementNo(source.getFormalSettlementNo()); entity.setPreSettlementId(null); entity.setPreSettlementNo(null);
|
||||||
entity.setProjectId(source.getProjectId()); entity.setProjectName(source.getProjectName()); entity.setDeptId(source.getDeptId()); entity.setDeptName(source.getDeptName()); entity.setContractId(source.getContractId()); entity.setContractNo(source.getContractNo()); entity.setContractName(source.getContractName()); entity.setPayerName(source.getPayerName()); entity.setPayeeName(source.getPayeeName()); entity.setSettlementAmount(source.getSettlementAmount()); entity.setPayableAmount(payableOfFormalSettlement(source.getId(), source.getSettlementAmount(), entity.getId())); entity.setBillType("正式结算单");
|
entity.setProjectId(source.getProjectId()); entity.setProjectName(source.getProjectName()); entity.setDeptId(source.getDeptId()); entity.setDeptName(source.getDeptName()); entity.setContractId(source.getContractId()); entity.setContractNo(source.getContractNo()); entity.setContractName(source.getContractName()); entity.setPayerName(source.getPayerName()); entity.setPayeeName(source.getPayeeName()); entity.setSettlementAmount(source.getSettlementAmount()); entity.setPayableAmount(payableOfFormalSettlement(source.getId(), source.getSettlementAmount(), entity.getId())); entity.setBillType("正式结算单");
|
||||||
|
}
|
||||||
} else if (request.getPreSettlementId() != null) {
|
} else if (request.getPreSettlementId() != null) {
|
||||||
PreSettlement source = preSettlementMapper.selectById(request.getPreSettlementId());
|
fillPreSettlementReference(entity, requireApprovedPreSettlement(request.getPreSettlementId()));
|
||||||
if (source == null) throw new ServiceException("预结算单不存在");
|
|
||||||
if (!TransportBusiConstant.APPROVED.equals(source.getApprovalStatus())) throw new ServiceException("只能选择审批通过、未作废的预结算单");
|
|
||||||
entity.setPreSettlementId(source.getId()); entity.setPreSettlementNo(source.getPreSettlementNo()); entity.setSettlementId(null); entity.setSettlementNo(null); entity.setProjectId(source.getProjectId()); entity.setProjectName(source.getProjectName()); entity.setDeptId(source.getDeptId()); entity.setDeptName(source.getDeptName()); entity.setContractId(source.getContractId()); entity.setContractNo(source.getContractNo()); entity.setContractName(source.getContractName()); entity.setPayerName(source.getPayerName()); entity.setPayeeName(source.getPayeeName()); entity.setSettlementAmount(source.getSettlementAmount()); entity.setPayableAmount(payableOfPreSettlement(source.getId(), source.getSettlementAmount(), entity.getId())); entity.setBillType("预结算单");
|
|
||||||
} else {
|
} else {
|
||||||
entity.setProjectId(request.getProjectId()); entity.setProjectName(request.getProjectName()); entity.setDeptId(request.getDeptId()); entity.setDeptName(request.getDeptName()); entity.setContractId(request.getContractId()); entity.setContractNo(request.getContractNo()); entity.setContractName(request.getContractName()); entity.setPayerName(request.getPayerName()); entity.setPayeeName(request.getPayeeName()); entity.setSettlementAmount(request.getSettlementAmount()); entity.setPayableAmount(request.getPayableAmount()); entity.setBillType(request.getBillType());
|
entity.setProjectId(request.getProjectId()); entity.setProjectName(request.getProjectName()); entity.setDeptId(request.getDeptId()); entity.setDeptName(request.getDeptName()); entity.setContractId(request.getContractId()); entity.setContractNo(request.getContractNo()); entity.setContractName(request.getContractName()); entity.setPayerName(request.getPayerName()); entity.setPayeeName(request.getPayeeName()); entity.setSettlementAmount(request.getSettlementAmount()); entity.setPayableAmount(request.getPayableAmount()); entity.setBillType(request.getBillType());
|
||||||
}
|
}
|
||||||
@@ -1955,6 +1999,36 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
|||||||
&& money(entity.getPayableAmount()).compareTo(BigDecimal.ZERO) > 0) throw new ServiceException("申请付款金额不能超过可付款金额");
|
&& money(entity.getPayableAmount()).compareTo(BigDecimal.ZERO) > 0) throw new ServiceException("申请付款金额不能超过可付款金额");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PreSettlement requireApprovedPreSettlement(Long preSettlementId) {
|
||||||
|
PreSettlement source = preSettlementMapper.selectById(preSettlementId);
|
||||||
|
if (source == null || Objects.equals(source.getIsDeleted(), 1)) {
|
||||||
|
throw new ServiceException("预结算单不存在");
|
||||||
|
}
|
||||||
|
if (!TransportBusiConstant.APPROVED.equals(source.getApprovalStatus())) {
|
||||||
|
throw new ServiceException("只能选择审批通过、未作废的预结算单");
|
||||||
|
}
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillPreSettlementReference(PaymentApplication entity, PreSettlement source) {
|
||||||
|
entity.setPreSettlementId(source.getId());
|
||||||
|
entity.setPreSettlementNo(source.getPreSettlementNo());
|
||||||
|
entity.setSettlementId(null);
|
||||||
|
entity.setSettlementNo(null);
|
||||||
|
entity.setProjectId(source.getProjectId());
|
||||||
|
entity.setProjectName(source.getProjectName());
|
||||||
|
entity.setDeptId(source.getDeptId());
|
||||||
|
entity.setDeptName(source.getDeptName());
|
||||||
|
entity.setContractId(source.getContractId());
|
||||||
|
entity.setContractNo(source.getContractNo());
|
||||||
|
entity.setContractName(source.getContractName());
|
||||||
|
entity.setPayerName(source.getPayerName());
|
||||||
|
entity.setPayeeName(source.getPayeeName());
|
||||||
|
entity.setSettlementAmount(source.getSettlementAmount());
|
||||||
|
entity.setPayableAmount(payableOfPreSettlement(source.getId(), source.getSettlementAmount(), entity.getId()));
|
||||||
|
entity.setBillType("预结算单");
|
||||||
|
}
|
||||||
|
|
||||||
private List<FormalSettlement> resolveFormalSettlements(PaymentApplicationSaveRequest request, PaymentApplication entity) {
|
private List<FormalSettlement> resolveFormalSettlements(PaymentApplicationSaveRequest request, PaymentApplication entity) {
|
||||||
if (!TransportBusiConstant.PAYMENT_TYPE_SETTLEMENT.equals(request.getPaymentType())) return List.of();
|
if (!TransportBusiConstant.PAYMENT_TYPE_SETTLEMENT.equals(request.getPaymentType())) return List.of();
|
||||||
List<Long> ids = request.getSettlementIds() == null ? List.of() : request.getSettlementIds();
|
List<Long> ids = request.getSettlementIds() == null ? List.of() : request.getSettlementIds();
|
||||||
@@ -2358,15 +2432,45 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|
|||||||
return relationAmount.add(legacyAmount);
|
return relationAmount.add(legacyAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 正式结算可付款 = 结算金额 − 已申请付款 − 项目预付核销 */
|
/**
|
||||||
|
* 正式结算可付款 = 结算金额 − 已申请付款 − 项目预付核销 − 来源预结算进度预付占用。
|
||||||
|
* 进度预付占用与正式结算台账 remainingPayable 口径对齐,避免转正式后仍可按全额申请尾款。
|
||||||
|
*/
|
||||||
private BigDecimal payableOfFormalSettlement(Long settlementId, BigDecimal settlementAmount, Long excludeId) {
|
private BigDecimal payableOfFormalSettlement(Long settlementId, BigDecimal settlementAmount, Long excludeId) {
|
||||||
return money(settlementAmount)
|
return money(settlementAmount)
|
||||||
.subtract(cumulativeFormalSettlementApplied(settlementId, excludeId))
|
.subtract(cumulativeFormalSettlementApplied(settlementId, excludeId))
|
||||||
.subtract(projectAdvanceWriteOffService.sumBySettlement(
|
.subtract(projectAdvanceWriteOffService.sumBySettlement(
|
||||||
TransportBusiConstant.SETTLEMENT_BILL_FORMAL, settlementId))
|
TransportBusiConstant.SETTLEMENT_BILL_FORMAL, settlementId))
|
||||||
|
.subtract(formalSettlementAdvanceOccupied(settlementId))
|
||||||
.max(BigDecimal.ZERO);
|
.max(BigDecimal.ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正式结算来源预结算的进度预付占用合计:优先取来源行快照,快照为空时回退预结算实时已申请/已付。
|
||||||
|
*/
|
||||||
|
private BigDecimal formalSettlementAdvanceOccupied(Long settlementId) {
|
||||||
|
if (settlementId == null) {
|
||||||
|
return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
|
||||||
|
}
|
||||||
|
List<FormalSettlementSource> sources = formalSettlementSourceMapper.selectList(
|
||||||
|
Wrappers.<FormalSettlementSource>lambdaQuery()
|
||||||
|
.eq(FormalSettlementSource::getFormalSettlementId, settlementId)
|
||||||
|
.eq(FormalSettlementSource::getIsDeleted, 0));
|
||||||
|
if (sources.isEmpty()) {
|
||||||
|
return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
|
||||||
|
}
|
||||||
|
BigDecimal total = BigDecimal.ZERO;
|
||||||
|
for (FormalSettlementSource source : sources) {
|
||||||
|
BigDecimal occupied = money(source.getAdvanceAppliedAmount()).max(money(source.getAdvancePaidAmount()));
|
||||||
|
if (occupied.compareTo(BigDecimal.ZERO) <= 0 && source.getPreSettlementId() != null) {
|
||||||
|
occupied = findPreSettlementApplied(source.getPreSettlementId())
|
||||||
|
.max(findPreSettlementPaid(source.getPreSettlementId()));
|
||||||
|
}
|
||||||
|
total = total.add(occupied);
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
/** 预结算可付款 = 结算金额 − 已申请付款 − 项目预付核销 */
|
/** 预结算可付款 = 结算金额 − 已申请付款 − 项目预付核销 */
|
||||||
private BigDecimal payableOfPreSettlement(Long preSettlementId, BigDecimal settlementAmount, Long excludeId) {
|
private BigDecimal payableOfPreSettlement(Long preSettlementId, BigDecimal settlementAmount, Long excludeId) {
|
||||||
return money(settlementAmount)
|
return money(settlementAmount)
|
||||||
|
|||||||
+20
-5
@@ -252,8 +252,8 @@ public class ReceiptClaimRecordServiceImpl extends BaseServiceImpl<ReceiptClaimM
|
|||||||
BigDecimal flowClaimedAfter = money(flow.getClaimedAmount())
|
BigDecimal flowClaimedAfter = money(flow.getClaimedAmount())
|
||||||
.subtract(money(claim.getClaimAmount())).max(BigDecimal.ZERO);
|
.subtract(money(claim.getClaimAmount())).max(BigDecimal.ZERO);
|
||||||
flow.setClaimedAmount(flowClaimedAfter);
|
flow.setClaimedAmount(flowClaimedAfter);
|
||||||
// 认领状态对照公告未认领金额重算(作废分摊不计入累计)
|
// 认领状态对照可认领上限重算(作废分摊不计入累计)
|
||||||
flow.setClaimStatus(amountClaimStatus(flowClaimedAfter, flow.getUnclaimedAmount()));
|
flow.setClaimStatus(amountClaimStatus(flowClaimedAfter, claimCeiling(flow)));
|
||||||
receiptFlowMapper.updateById(flow);
|
receiptFlowMapper.updateById(flow);
|
||||||
|
|
||||||
// 作废不生成金蝶认领冲单:金蝶单号/状态保留原值(未推送为空,已推送为真实收款单信息),
|
// 作废不生成金蝶认领冲单:金蝶单号/状态保留原值(未推送为空,已推送为真实收款单信息),
|
||||||
@@ -411,13 +411,28 @@ public class ReceiptClaimRecordServiceImpl extends BaseServiceImpl<ReceiptClaimM
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 累计认领金额 → 流水认领状态:对照公告未认领金额判定(与收款流水侧口径一致)
|
* 累计认领金额 → 流水认领状态:对照可认领上限判定(与收款流水侧口径一致)
|
||||||
*/
|
*/
|
||||||
private String amountClaimStatus(BigDecimal claimedAmount, BigDecimal unclaimedAmount) {
|
private String amountClaimStatus(BigDecimal claimedAmount, BigDecimal claimCeiling) {
|
||||||
if (claimedAmount.compareTo(BigDecimal.ZERO) <= 0) {
|
if (claimedAmount.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
return "unclaimed";
|
return "unclaimed";
|
||||||
}
|
}
|
||||||
return claimedAmount.compareTo(money(unclaimedAmount)) >= 0 ? "claimed" : "partial";
|
return claimedAmount.compareTo(money(claimCeiling)) >= 0 ? "claimed" : "partial";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可认领上限:公告未认领金额与收款金额取较小正值(与收款流水侧口径一致)
|
||||||
|
*/
|
||||||
|
private BigDecimal claimCeiling(KingdeeReceiptFlow flow) {
|
||||||
|
BigDecimal unclaimed = money(flow.getUnclaimedAmount());
|
||||||
|
BigDecimal receipt = money(flow.getReceiptAmount());
|
||||||
|
if (receipt.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
return unclaimed;
|
||||||
|
}
|
||||||
|
if (unclaimed.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
return unclaimed;
|
||||||
|
}
|
||||||
|
return unclaimed.min(receipt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String amountStatus(BigDecimal paidAmount, BigDecimal settlementAmount) {
|
private String amountStatus(BigDecimal paidAmount, BigDecimal settlementAmount) {
|
||||||
|
|||||||
+126
-20
@@ -194,12 +194,16 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
|||||||
.eq(ReceiptFlowRecord::getReceiptFlowId, id)
|
.eq(ReceiptFlowRecord::getReceiptFlowId, id)
|
||||||
.in(ReceiptFlowRecord::getActionType, List.of("claim", "push"))
|
.in(ReceiptFlowRecord::getActionType, List.of("claim", "push"))
|
||||||
.orderByDesc(ReceiptFlowRecord::getCreateTime)));
|
.orderByDesc(ReceiptFlowRecord::getCreateTime)));
|
||||||
|
// 继续认领:带回本流水历史关联且仍有剩余可认领金额的结算单
|
||||||
|
vo.setRelatedSettlements(relatedSettlementCandidates(id));
|
||||||
return vo;
|
return vo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Map<String, Object>> settlementCandidates(String keyword, Long flowId) {
|
public List<Map<String, Object>> settlementCandidates(String keyword, Long flowId) {
|
||||||
existing(flowId);
|
existing(flowId);
|
||||||
|
// 本流水历史关联结算单优先保留(避免仅按创建时间 limit 截断后选不到)
|
||||||
|
Set<Long> relatedIds = relatedSettlementIds(flowId);
|
||||||
List<FormalSettlement> settlements = formalSettlementMapper.selectList(
|
List<FormalSettlement> settlements = formalSettlementMapper.selectList(
|
||||||
Wrappers.<FormalSettlement>lambdaQuery()
|
Wrappers.<FormalSettlement>lambdaQuery()
|
||||||
.eq(FormalSettlement::getSettlementType, RECEIVABLE)
|
.eq(FormalSettlement::getSettlementType, RECEIVABLE)
|
||||||
@@ -210,7 +214,24 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
|||||||
.or().like(FormalSettlement::getProjectName, keyword)
|
.or().like(FormalSettlement::getProjectName, keyword)
|
||||||
.or().like(FormalSettlement::getContractName, keyword))
|
.or().like(FormalSettlement::getContractName, keyword))
|
||||||
.orderByDesc(FormalSettlement::getCreateTime)
|
.orderByDesc(FormalSettlement::getCreateTime)
|
||||||
.last("limit 200"));
|
.last("limit 500"));
|
||||||
|
if (!relatedIds.isEmpty()) {
|
||||||
|
Set<Long> loadedIds = settlements.stream().map(FormalSettlement::getId)
|
||||||
|
.filter(Objects::nonNull).collect(Collectors.toSet());
|
||||||
|
List<Long> missingIds = relatedIds.stream().filter(id -> !loadedIds.contains(id)).toList();
|
||||||
|
if (!missingIds.isEmpty()) {
|
||||||
|
List<FormalSettlement> relatedSettlements = formalSettlementMapper.selectList(
|
||||||
|
Wrappers.<FormalSettlement>lambdaQuery()
|
||||||
|
.in(FormalSettlement::getId, missingIds)
|
||||||
|
.eq(FormalSettlement::getSettlementType, RECEIVABLE)
|
||||||
|
.eq(FormalSettlement::getApprovalStatus, APPROVED)
|
||||||
|
.eq(FormalSettlement::getStatus, 1));
|
||||||
|
List<FormalSettlement> merged = new ArrayList<>(relatedSettlements.size() + settlements.size());
|
||||||
|
merged.addAll(relatedSettlements);
|
||||||
|
merged.addAll(settlements);
|
||||||
|
settlements = merged;
|
||||||
|
}
|
||||||
|
}
|
||||||
// 候选结算单的累计认领金额一次聚合查询(避免逐单 N+1)
|
// 候选结算单的累计认领金额一次聚合查询(避免逐单 N+1)
|
||||||
Map<Long, BigDecimal> claimedMap = receiptClaimedAmounts(settlements.stream()
|
Map<Long, BigDecimal> claimedMap = receiptClaimedAmounts(settlements.stream()
|
||||||
.map(FormalSettlement::getId).toList());
|
.map(FormalSettlement::getId).toList());
|
||||||
@@ -218,6 +239,14 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
|||||||
.map(settlement -> candidateRow(settlement,
|
.map(settlement -> candidateRow(settlement,
|
||||||
claimedMap.getOrDefault(settlement.getId(), BigDecimal.ZERO)))
|
claimedMap.getOrDefault(settlement.getId(), BigDecimal.ZERO)))
|
||||||
.filter(row -> ((BigDecimal) row.get("remainingReceiptAmount")).compareTo(BigDecimal.ZERO) > 0)
|
.filter(row -> ((BigDecimal) row.get("remainingReceiptAmount")).compareTo(BigDecimal.ZERO) > 0)
|
||||||
|
.sorted((left, right) -> {
|
||||||
|
boolean leftRelated = relatedIds.contains(toLong(left.get("id")));
|
||||||
|
boolean rightRelated = relatedIds.contains(toLong(right.get("id")));
|
||||||
|
if (leftRelated == rightRelated) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return leftRelated ? -1 : 1;
|
||||||
|
})
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,6 +263,7 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
|||||||
Wrappers.<ReceiptClaimSettlement>lambdaQuery()
|
Wrappers.<ReceiptClaimSettlement>lambdaQuery()
|
||||||
.eq(ReceiptClaimSettlement::getFormalSettlementId, formalSettlementId)
|
.eq(ReceiptClaimSettlement::getFormalSettlementId, formalSettlementId)
|
||||||
.eq(ReceiptClaimSettlement::getStatus, 1)
|
.eq(ReceiptClaimSettlement::getStatus, 1)
|
||||||
|
.eq(ReceiptClaimSettlement::getIsDeleted, 0)
|
||||||
.orderByDesc(ReceiptClaimSettlement::getCreateTime));
|
.orderByDesc(ReceiptClaimSettlement::getCreateTime));
|
||||||
if (relations.isEmpty()) {
|
if (relations.isEmpty()) {
|
||||||
return List.of();
|
return List.of();
|
||||||
@@ -315,19 +345,19 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
|||||||
allocatedTotal = allocatedTotal.add(allocated);
|
allocatedTotal = allocatedTotal.add(allocated);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 公告未认领金额(认领上限与认领完成判定基准,A301-2 口径)
|
// 认领上限:公告未认领金额与收款金额取较小值(避免未认领金额异常偏大导致无法认领完成)
|
||||||
if (flow.getUnclaimedAmount() == null) {
|
if (flow.getUnclaimedAmount() == null) {
|
||||||
throw new ServiceException("公告未认领金额缺失,请先手动同步金蝶收款流水");
|
throw new ServiceException("公告未认领金额缺失,请先手动同步金蝶收款流水");
|
||||||
}
|
}
|
||||||
BigDecimal unclaimedAmount = money(flow.getUnclaimedAmount());
|
BigDecimal claimCeiling = claimCeiling(flow);
|
||||||
if (unclaimedAmount.compareTo(BigDecimal.ZERO) <= 0) {
|
if (claimCeiling.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
throw new ServiceException("该流水公告未认领金额为0,无需认领");
|
throw new ServiceException("该流水可认领金额为0,无需认领");
|
||||||
}
|
}
|
||||||
// 流水认领前已认领金额
|
// 流水认领前已认领金额
|
||||||
BigDecimal previousFlowClaimed = flowClaimedAmount(flow.getId());
|
BigDecimal previousFlowClaimed = flowClaimedAmount(flow.getId());
|
||||||
if (previousFlowClaimed.add(allocatedTotal).compareTo(unclaimedAmount) > 0) {
|
if (previousFlowClaimed.add(allocatedTotal).compareTo(claimCeiling) > 0) {
|
||||||
throw new ServiceException("累计认领金额不能超过公告未认领金额,剩余可认领 "
|
throw new ServiceException("累计认领金额不能超过可认领上限,剩余可认领 "
|
||||||
+ unclaimedAmount.subtract(previousFlowClaimed).max(BigDecimal.ZERO));
|
+ claimCeiling.subtract(previousFlowClaimed).max(BigDecimal.ZERO));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 当前用户部门
|
// 当前用户部门
|
||||||
@@ -380,6 +410,9 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
|||||||
relation.setClaimedReceiptAmount(previousClaimed);
|
relation.setClaimedReceiptAmount(previousClaimed);
|
||||||
// 本次分摊金额
|
// 本次分摊金额
|
||||||
relation.setAllocatedReceiptAmount(allocated);
|
relation.setAllocatedReceiptAmount(allocated);
|
||||||
|
// 有效分摊(与汇总/候选查询 status=1 口径一致)
|
||||||
|
relation.setStatus(1);
|
||||||
|
relation.setIsDeleted(0);
|
||||||
claimSettlementMapper.insert(relation);
|
claimSettlementMapper.insert(relation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,8 +423,8 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
|||||||
String fromStatus = normalizeClaimStatus(flow.getClaimStatus());
|
String fromStatus = normalizeClaimStatus(flow.getClaimStatus());
|
||||||
// 认领后累计金额
|
// 认领后累计金额
|
||||||
BigDecimal claimedAfter = previousFlowClaimed.add(allocatedTotal);
|
BigDecimal claimedAfter = previousFlowClaimed.add(allocatedTotal);
|
||||||
// 认领后状态(对照公告未认领金额)
|
// 认领后状态(对照可认领上限)
|
||||||
String toStatus = amountClaimStatus(claimedAfter, unclaimedAmount);
|
String toStatus = amountClaimStatus(claimedAfter, claimCeiling);
|
||||||
// 更新流水已认领金额
|
// 更新流水已认领金额
|
||||||
flow.setClaimedAmount(claimedAfter);
|
flow.setClaimedAmount(claimedAfter);
|
||||||
// 更新流水认领状态
|
// 更新流水认领状态
|
||||||
@@ -499,9 +532,9 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
|||||||
|
|
||||||
// 复制公告数据到实体(不覆盖本地认领字段)
|
// 复制公告数据到实体(不覆盖本地认领字段)
|
||||||
copyAnnounceRow(entity, announce, detailSerialNo, receiptAmount);
|
copyAnnounceRow(entity, announce, detailSerialNo, receiptAmount);
|
||||||
// 根据本地累计认领金额与最新公告未认领金额重新计算认领状态
|
// 根据本地累计认领金额与可认领上限重新计算认领状态
|
||||||
entity.setClaimStatus(amountClaimStatus(money(entity.getClaimedAmount()),
|
entity.setClaimStatus(amountClaimStatus(money(entity.getClaimedAmount()),
|
||||||
entity.getUnclaimedAmount()));
|
claimCeiling(entity)));
|
||||||
|
|
||||||
if (created) {
|
if (created) {
|
||||||
toInsert.add(entity);
|
toInsert.add(entity);
|
||||||
@@ -621,6 +654,46 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本流水历史关联过的结算单 id(有效分摊)
|
||||||
|
*/
|
||||||
|
private Set<Long> relatedSettlementIds(Long flowId) {
|
||||||
|
if (flowId == null) {
|
||||||
|
return Set.of();
|
||||||
|
}
|
||||||
|
return claimSettlementMapper.selectList(Wrappers.<ReceiptClaimSettlement>lambdaQuery()
|
||||||
|
.select(ReceiptClaimSettlement::getFormalSettlementId)
|
||||||
|
.eq(ReceiptClaimSettlement::getReceiptFlowId, flowId)
|
||||||
|
.eq(ReceiptClaimSettlement::getStatus, 1)
|
||||||
|
.eq(ReceiptClaimSettlement::getIsDeleted, 0)).stream()
|
||||||
|
.map(ReceiptClaimSettlement::getFormalSettlementId)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toCollection(HashSet::new));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 继续认领预填:本流水历史关联且仍有剩余可认领金额的结算单
|
||||||
|
*/
|
||||||
|
private List<Map<String, Object>> relatedSettlementCandidates(Long flowId) {
|
||||||
|
Set<Long> relatedIds = relatedSettlementIds(flowId);
|
||||||
|
if (relatedIds.isEmpty()) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
List<FormalSettlement> settlements = formalSettlementMapper.selectList(
|
||||||
|
Wrappers.<FormalSettlement>lambdaQuery()
|
||||||
|
.in(FormalSettlement::getId, relatedIds)
|
||||||
|
.eq(FormalSettlement::getSettlementType, RECEIVABLE)
|
||||||
|
.eq(FormalSettlement::getApprovalStatus, APPROVED)
|
||||||
|
.eq(FormalSettlement::getStatus, 1));
|
||||||
|
Map<Long, BigDecimal> claimedMap = receiptClaimedAmounts(settlements.stream()
|
||||||
|
.map(FormalSettlement::getId).toList());
|
||||||
|
return settlements.stream()
|
||||||
|
.map(settlement -> candidateRow(settlement,
|
||||||
|
claimedMap.getOrDefault(settlement.getId(), BigDecimal.ZERO)))
|
||||||
|
.filter(row -> ((BigDecimal) row.get("remainingReceiptAmount")).compareTo(BigDecimal.ZERO) > 0)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量聚合结算单的累计有效认领金额:一次 IN 查询按结算单分组求和,避免逐单 N+1
|
* 批量聚合结算单的累计有效认领金额:一次 IN 查询按结算单分组求和,避免逐单 N+1
|
||||||
*/
|
*/
|
||||||
@@ -631,7 +704,8 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
|||||||
}
|
}
|
||||||
return claimSettlementMapper.selectList(Wrappers.<ReceiptClaimSettlement>lambdaQuery()
|
return claimSettlementMapper.selectList(Wrappers.<ReceiptClaimSettlement>lambdaQuery()
|
||||||
.in(ReceiptClaimSettlement::getFormalSettlementId, ids)
|
.in(ReceiptClaimSettlement::getFormalSettlementId, ids)
|
||||||
.eq(ReceiptClaimSettlement::getStatus, 1)).stream()
|
.eq(ReceiptClaimSettlement::getStatus, 1)
|
||||||
|
.eq(ReceiptClaimSettlement::getIsDeleted, 0)).stream()
|
||||||
.collect(Collectors.groupingBy(ReceiptClaimSettlement::getFormalSettlementId,
|
.collect(Collectors.groupingBy(ReceiptClaimSettlement::getFormalSettlementId,
|
||||||
Collectors.reducing(BigDecimal.ZERO,
|
Collectors.reducing(BigDecimal.ZERO,
|
||||||
item -> money(item.getAllocatedReceiptAmount()), BigDecimal::add)));
|
item -> money(item.getAllocatedReceiptAmount()), BigDecimal::add)));
|
||||||
@@ -640,12 +714,42 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
|||||||
private BigDecimal flowClaimedAmount(Long flowId) {
|
private BigDecimal flowClaimedAmount(Long flowId) {
|
||||||
return claimSettlementMapper.selectList(Wrappers.<ReceiptClaimSettlement>lambdaQuery()
|
return claimSettlementMapper.selectList(Wrappers.<ReceiptClaimSettlement>lambdaQuery()
|
||||||
.eq(ReceiptClaimSettlement::getReceiptFlowId, flowId)
|
.eq(ReceiptClaimSettlement::getReceiptFlowId, flowId)
|
||||||
.eq(ReceiptClaimSettlement::getStatus, 1)).stream()
|
.eq(ReceiptClaimSettlement::getStatus, 1)
|
||||||
|
.eq(ReceiptClaimSettlement::getIsDeleted, 0)).stream()
|
||||||
.map(ReceiptClaimSettlement::getAllocatedReceiptAmount)
|
.map(ReceiptClaimSettlement::getAllocatedReceiptAmount)
|
||||||
.map(this::money)
|
.map(this::money)
|
||||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可认领上限:公告未认领金额与收款金额取较小正值。
|
||||||
|
* 主口径仍为 A301-2 公告未认领金额;与收款金额取 min,避免未认领金额异常偏大导致无法进入「认领完成」。
|
||||||
|
*/
|
||||||
|
private BigDecimal claimCeiling(KingdeeReceiptFlow flow) {
|
||||||
|
BigDecimal unclaimed = money(flow.getUnclaimedAmount());
|
||||||
|
BigDecimal receipt = money(flow.getReceiptAmount());
|
||||||
|
if (receipt.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
return unclaimed;
|
||||||
|
}
|
||||||
|
if (unclaimed.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
return unclaimed;
|
||||||
|
}
|
||||||
|
return unclaimed.min(receipt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long toLong(Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (value instanceof Long longValue) {
|
||||||
|
return longValue;
|
||||||
|
}
|
||||||
|
if (value instanceof Number number) {
|
||||||
|
return number.longValue();
|
||||||
|
}
|
||||||
|
return Func.toLong(String.valueOf(value));
|
||||||
|
}
|
||||||
|
|
||||||
private KingdeeReceiptFlow lockedFlow(Long flowId) {
|
private KingdeeReceiptFlow lockedFlow(Long flowId) {
|
||||||
KingdeeReceiptFlow flow = baseMapper.selectOne(Wrappers.<KingdeeReceiptFlow>lambdaQuery()
|
KingdeeReceiptFlow flow = baseMapper.selectOne(Wrappers.<KingdeeReceiptFlow>lambdaQuery()
|
||||||
.eq(KingdeeReceiptFlow::getId, flowId)
|
.eq(KingdeeReceiptFlow::getId, flowId)
|
||||||
@@ -824,18 +928,20 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
|||||||
flow.setClaimMe(announce.getClaimme());
|
flow.setClaimMe(announce.getClaimme());
|
||||||
BigDecimal claimedTotal = flowClaimedAmount(flow.getId());
|
BigDecimal claimedTotal = flowClaimedAmount(flow.getId());
|
||||||
flow.setClaimedAmount(claimedTotal);
|
flow.setClaimedAmount(claimedTotal);
|
||||||
String claimStatus = amountClaimStatus(claimedTotal, flow.getUnclaimedAmount());
|
BigDecimal claimCeiling = claimCeiling(flow);
|
||||||
|
String claimStatus = amountClaimStatus(claimedTotal, claimCeiling);
|
||||||
flow.setClaimStatus(claimStatus);
|
flow.setClaimStatus(claimStatus);
|
||||||
updateById(flow);
|
updateById(flow);
|
||||||
if (!CLAIMED.equals(claimStatus)) {
|
if (!CLAIMED.equals(claimStatus)) {
|
||||||
return ReceiptClaimPushResult.fail("累计认领金额(" + claimedTotal + ")与公告未认领金额("
|
return ReceiptClaimPushResult.fail("累计认领金额(" + claimedTotal + ")与可认领上限("
|
||||||
+ money(flow.getUnclaimedAmount()) + ")不一致,不满足推送条件");
|
+ claimCeiling + ")不一致,不满足推送条件");
|
||||||
}
|
}
|
||||||
// 分录取该流水全部有效分摊行(结算单id升序,跨认领主单归集)
|
// 分录取该流水全部有效分摊行(结算单id升序,跨认领主单归集)
|
||||||
List<ReceiptClaimSettlement> allocations = claimSettlementMapper.selectList(
|
List<ReceiptClaimSettlement> allocations = claimSettlementMapper.selectList(
|
||||||
Wrappers.<ReceiptClaimSettlement>lambdaQuery()
|
Wrappers.<ReceiptClaimSettlement>lambdaQuery()
|
||||||
.eq(ReceiptClaimSettlement::getReceiptFlowId, flow.getId())
|
.eq(ReceiptClaimSettlement::getReceiptFlowId, flow.getId())
|
||||||
.eq(ReceiptClaimSettlement::getStatus, 1)
|
.eq(ReceiptClaimSettlement::getStatus, 1)
|
||||||
|
.eq(ReceiptClaimSettlement::getIsDeleted, 0)
|
||||||
.orderByAsc(ReceiptClaimSettlement::getFormalSettlementId));
|
.orderByAsc(ReceiptClaimSettlement::getFormalSettlementId));
|
||||||
if (allocations.isEmpty()) {
|
if (allocations.isEmpty()) {
|
||||||
return ReceiptClaimPushResult.fail("该流水无有效认领分摊,无法推送");
|
return ReceiptClaimPushResult.fail("该流水无有效认领分摊,无法推送");
|
||||||
@@ -1075,13 +1181,13 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 累计认领金额 → 流水认领状态:对照公告未认领金额判定(claimed 即「认领完成」,唯一可推送状态)
|
* 累计认领金额 → 流水认领状态:对照可认领上限判定(claimed 即「认领完成」,唯一可推送状态)
|
||||||
*/
|
*/
|
||||||
private String amountClaimStatus(BigDecimal claimedAmount, BigDecimal unclaimedAmount) {
|
private String amountClaimStatus(BigDecimal claimedAmount, BigDecimal claimCeiling) {
|
||||||
if (claimedAmount.compareTo(BigDecimal.ZERO) <= 0) {
|
if (claimedAmount.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
return UNCLAIMED;
|
return UNCLAIMED;
|
||||||
}
|
}
|
||||||
return claimedAmount.compareTo(money(unclaimedAmount)) >= 0 ? CLAIMED : PARTIAL;
|
return claimedAmount.compareTo(money(claimCeiling)) >= 0 ? CLAIMED : PARTIAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String amountStatus(BigDecimal claimedAmount, BigDecimal settlementAmount) {
|
private String amountStatus(BigDecimal claimedAmount, BigDecimal settlementAmount) {
|
||||||
|
|||||||
+2
-4
@@ -246,10 +246,8 @@ public class TemporaryCreditLimitServiceImpl extends BaseServiceImpl<TemporaryCr
|
|||||||
TransportBusinessSupport.validateRequired(temporaryCreditLimit.getProjectCode(), "项目编号不能为空");
|
TransportBusinessSupport.validateRequired(temporaryCreditLimit.getProjectCode(), "项目编号不能为空");
|
||||||
TransportBusinessSupport.validateRequired(temporaryCreditLimit.getUndertakeDeptName(), "承办部门不能为空");
|
TransportBusinessSupport.validateRequired(temporaryCreditLimit.getUndertakeDeptName(), "承办部门不能为空");
|
||||||
TransportBusinessSupport.validateRequired(temporaryCreditLimit.getValidUntil() == null ? null : temporaryCreditLimit.getValidUntil().toString(), "请选择申请有效期至");
|
TransportBusinessSupport.validateRequired(temporaryCreditLimit.getValidUntil() == null ? null : temporaryCreditLimit.getValidUntil().toString(), "请选择申请有效期至");
|
||||||
if (temporaryCreditLimit.getProjectFundLimit() == null || temporaryCreditLimit.getUsedFundLimit() == null || temporaryCreditLimit.getRemainingFundLimit() == null) {
|
if (temporaryCreditLimit.getRemainingFundLimit() != null
|
||||||
throw new ServiceException("项目额度数据异常,请重新选择项目");
|
&& temporaryCreditLimit.getRemainingFundLimit().compareTo(BigDecimal.ZERO) < 0) {
|
||||||
}
|
|
||||||
if (temporaryCreditLimit.getRemainingFundLimit().compareTo(BigDecimal.ZERO) < 0) {
|
|
||||||
throw new ServiceException("项目剩余额度不能小于0");
|
throw new ServiceException("项目剩余额度不能小于0");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-2
@@ -70,10 +70,15 @@ public class ReceiptFlowWrapper extends BaseEntityWrapper<KingdeeReceiptFlow, Re
|
|||||||
case "failed" -> "处理失败";
|
case "failed" -> "处理失败";
|
||||||
default -> "未推送";
|
default -> "未推送";
|
||||||
});
|
});
|
||||||
// 剩余可认领金额 = 公告未认领金额 − 累计认领金额(认领上限为公告口径)
|
// 剩余可认领金额 = 可认领上限 − 累计认领金额(上限取公告未认领与收款金额较小值)
|
||||||
BigDecimal unclaimedAmount = money(entity.getUnclaimedAmount());
|
BigDecimal unclaimedAmount = money(entity.getUnclaimedAmount());
|
||||||
|
BigDecimal receiptAmount = money(entity.getReceiptAmount());
|
||||||
|
BigDecimal claimCeiling = unclaimedAmount;
|
||||||
|
if (receiptAmount.compareTo(BigDecimal.ZERO) > 0 && unclaimedAmount.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
claimCeiling = unclaimedAmount.min(receiptAmount);
|
||||||
|
}
|
||||||
BigDecimal claimedAmount = money(entity.getClaimedAmount());
|
BigDecimal claimedAmount = money(entity.getClaimedAmount());
|
||||||
vo.setRemainingAmount(unclaimedAmount.subtract(claimedAmount).max(BigDecimal.ZERO));
|
vo.setRemainingAmount(claimCeiling.subtract(claimedAmount).max(BigDecimal.ZERO));
|
||||||
vo.setCreateUserName(UserCache.getUserRealName(entity.getCreateUser()));
|
vo.setCreateUserName(UserCache.getUserRealName(entity.getCreateUser()));
|
||||||
vo.setUpdateUserName(UserCache.getUserRealName(entity.getUpdateUser()));
|
vo.setUpdateUserName(UserCache.getUserRealName(entity.getUpdateUser()));
|
||||||
return vo;
|
return vo;
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
-- 用户表:新增 OA 登录名,支持用户管理后台维护
|
||||||
|
-- 排序规则 utf8mb4_general_ci
|
||||||
|
|
||||||
|
ALTER TABLE `blade_user`
|
||||||
|
ADD COLUMN `oa_login_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'OA登录名' AFTER `is_oa`;
|
||||||
|
|
||||||
|
-- 从用户部门关联表回填已有 OA 登录账号
|
||||||
|
UPDATE `blade_user` bu
|
||||||
|
INNER JOIN (
|
||||||
|
SELECT `user_id`, MAX(`oa_login_id`) AS `oa_login_id`
|
||||||
|
FROM `blade_user_dept`
|
||||||
|
WHERE `is_deleted` = 0
|
||||||
|
AND `oa_login_id` IS NOT NULL
|
||||||
|
AND `oa_login_id` <> ''
|
||||||
|
GROUP BY `user_id`
|
||||||
|
) bud ON bud.`user_id` = bu.`id`
|
||||||
|
SET bu.`oa_login_id` = bud.`oa_login_id`
|
||||||
|
WHERE bu.`oa_login_id` IS NULL OR bu.`oa_login_id` = '';
|
||||||
Reference in New Issue
Block a user