登记收款选择账单直接核销,附件上传支持拖动上传
This commit is contained in:
+4
-2
@@ -8,10 +8,12 @@ import lombok.Data;
|
||||
*
|
||||
* <p>典型场景:</p>
|
||||
* <ul>
|
||||
* <li>余额核销账单/订单扣款 -> {@link ICustomerAccountApi#deductBalance}(余额减少,默认同步释放已用额度)</li>
|
||||
* <li>收款审核入账/反核销回补/退款 -> {@link ICustomerAccountApi#refundBalance}(余额增加)</li>
|
||||
* <li>订单扣款/账户余额支付 -> {@link ICustomerAccountApi#deductBalance}(余额减少)</li>
|
||||
* <li>收款审核入账/退款 -> {@link ICustomerAccountApi#refundBalance}(余额增加)</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>账单余额核销/反核销不使用本命令、不改动余额与额度。</p>
|
||||
*
|
||||
* @author bms
|
||||
* @date 2026-09-17
|
||||
*/
|
||||
|
||||
+7
-4
@@ -14,12 +14,15 @@ import com.bms.customer.customermoney.vo.CustomerAccountStatusVO;
|
||||
* 调用方自身的事务会与本操作共享事务(默认 REQUIRED),任一失败整体回滚。</p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>单据形成应收/计费开单:{@link #occupyCredit} 占用授信(used_credit 增加)</li>
|
||||
* <li>单据作废/计费核减:{@link #releaseCredit} 释放授信(used_credit 减少)</li>
|
||||
* <li>用账户余额支付/核销:{@link #deductBalance} 扣余额(可同步释放已用额度)</li>
|
||||
* <li>收款入账/退款/反核销回补:{@link #refundBalance} 加余额(可同步重新占用)</li>
|
||||
* <li>单据形成应收/计费开单:{@link #occupyCredit}(计费口径下为扣减账户余额,允许负余额欠费)</li>
|
||||
* <li>单据作废/计费核减:{@link #releaseCredit}(计费口径下为回补账户余额)</li>
|
||||
* <li>用账户余额支付:{@link #deductBalance} 扣余额</li>
|
||||
* <li>收款审核入账/退款:{@link #refundBalance} 加余额</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>注意(核销口径):应收账单的余额核销与反核销(含收款审核联动核销)<b>不调用本接口</b>,
|
||||
* 只更新账单已核销/未核销金额与状态,客户余额与授信额度均不发生变动。</p>
|
||||
*
|
||||
* @author bms
|
||||
* @date 2026-09-17
|
||||
*/
|
||||
|
||||
+3
@@ -125,6 +125,9 @@ public class CustomerReceipt extends BaseEntity
|
||||
/** 收款附件列表(存 ctr_customer_attachment,attachment_type='3',biz_id 关联本单) */
|
||||
private List<BmsCustomerAttachment> attachmentList;
|
||||
|
||||
/** 核销账单计划(登记时选择,审核通过后一并核销) */
|
||||
private List<ReceiptWriteoffPlan> writeoffPlans;
|
||||
|
||||
/** 收款附件数量(列表查询统计) */
|
||||
private Integer attachmentCount;
|
||||
}
|
||||
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
package com.bms.customer.customermoney.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.bms.common.core.domain.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 收款单核销账单计划 ctr_receipt_writeoff_plan
|
||||
*
|
||||
* <p>登记收款时指定待核销的应收账单(PENDING);收款审核通过后在同一事务内逐张执行核销,
|
||||
* 回写核销单ID并置 EFFECTIVE;待审核收款单被取消则置 CANCELLED;
|
||||
* 已生效的核销单后续在“余额核销”页被反核销则置 REVERSED(核销/反核销均不改动客户余额与额度)。</p>
|
||||
*
|
||||
* @author bms
|
||||
* @date 2026-10-08
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ReceiptWriteoffPlan extends BaseEntity
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 状态:待执行(收款单待审核) */
|
||||
public static final String STATUS_PENDING = "PENDING";
|
||||
/** 状态:已核销(收款审核通过并完成账单核销) */
|
||||
public static final String STATUS_EFFECTIVE = "EFFECTIVE";
|
||||
/** 状态:已作废(待审核收款单被取消,计划未执行) */
|
||||
public static final String STATUS_CANCELLED = "CANCELLED";
|
||||
/** 状态:已反核销(审核联动核销后,核销单在余额核销页被反核销) */
|
||||
public static final String STATUS_REVERSED = "REVERSED";
|
||||
|
||||
/** 主键 */
|
||||
private Long planId;
|
||||
|
||||
/** 收款单ID */
|
||||
private Long receiptId;
|
||||
|
||||
/** 应收账单ID */
|
||||
private Long arBillId;
|
||||
|
||||
/** 账单号快照 */
|
||||
private String billNo;
|
||||
|
||||
/** 客户ID */
|
||||
private Long customerId;
|
||||
|
||||
/** 账单币种(当前仅支持CNY) */
|
||||
private String currency;
|
||||
|
||||
/** 本次核销金额(本位币CNY) */
|
||||
private BigDecimal writeoffAmount;
|
||||
|
||||
/** 状态:PENDING/EFFECTIVE/CANCELLED/REVERSED */
|
||||
private String status;
|
||||
|
||||
/** 审核后生成的余额核销单ID */
|
||||
private Long writeoffId;
|
||||
|
||||
/** 核销日期(执行后展示) */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date writeoffDate;
|
||||
|
||||
/* ===== 关联展示字段(来自 ar_bill) ===== */
|
||||
|
||||
/** 账单名称 */
|
||||
private String billName;
|
||||
|
||||
/** 账单应收总额 */
|
||||
private BigDecimal totalAmount;
|
||||
|
||||
/** 账单已核销金额 */
|
||||
private BigDecimal writtenOffAmount;
|
||||
|
||||
/** 账单未核销金额 */
|
||||
private BigDecimal unwrittenAmount;
|
||||
|
||||
/** 账单状态 */
|
||||
private String billStatus;
|
||||
}
|
||||
+3
@@ -68,6 +68,9 @@ public interface CustomerMoneyMapper
|
||||
/** 取消收款单:PENDING -> CANCELLED */
|
||||
int cancelReceipt(@Param("id") Long id, @Param("updateBy") String updateBy);
|
||||
|
||||
/** 反核销联动:回退已确认收款单的已分配金额、回补未分配金额并重算收款类型(不动余额) */
|
||||
int updateReceiptAllocation(CustomerReceipt receipt);
|
||||
|
||||
/* ================= 余额流水 ================= */
|
||||
|
||||
/** 查询流水列表 */
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.bms.customer.customermoney.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import com.bms.customer.customermoney.domain.ReceiptWriteoffPlan;
|
||||
|
||||
/**
|
||||
* 收款单核销账单计划 Mapper
|
||||
*
|
||||
* @author bms
|
||||
* @date 2026-10-08
|
||||
*/
|
||||
public interface ReceiptWriteoffPlanMapper
|
||||
{
|
||||
/** 新增一条核销计划 */
|
||||
int insertPlan(ReceiptWriteoffPlan plan);
|
||||
|
||||
/** 按收款单查询全部计划(关联账单展示字段,按计划ID升序) */
|
||||
List<ReceiptWriteoffPlan> selectByReceiptId(@Param("receiptId") Long receiptId);
|
||||
|
||||
/** 执行成功回写:PENDING -> EFFECTIVE,记录核销单ID与核销日期 */
|
||||
int updateEffective(@Param("planId") Long planId,
|
||||
@Param("writeoffId") Long writeoffId,
|
||||
@Param("updateBy") String updateBy);
|
||||
|
||||
/** 收款单取消:其全部 PENDING 计划置 CANCELLED */
|
||||
int cancelPendingByReceiptId(@Param("receiptId") Long receiptId,
|
||||
@Param("updateBy") String updateBy);
|
||||
|
||||
/** 按核销单ID查询 EFFECTIVE 计划(反核销联动用) */
|
||||
ReceiptWriteoffPlan selectEffectiveByWriteoffId(@Param("writeoffId") Long writeoffId);
|
||||
|
||||
/** 反核销联动:EFFECTIVE -> REVERSED */
|
||||
int updateReversedByWriteoffId(@Param("writeoffId") Long writeoffId,
|
||||
@Param("updateBy") String updateBy);
|
||||
}
|
||||
+184
-4
@@ -5,8 +5,11 @@ import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -15,8 +18,13 @@ import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import com.bms.common.exception.ServiceException;
|
||||
import com.bms.common.utils.SecurityUtils;
|
||||
import com.bms.ar.domain.ArBalanceWriteoff;
|
||||
import com.bms.ar.domain.ArBankAccount;
|
||||
import com.bms.ar.domain.ArBill;
|
||||
import com.bms.ar.enums.ArBillStatus;
|
||||
import com.bms.ar.mapper.ArBankAccountMapper;
|
||||
import com.bms.ar.mapper.ArBillMapper;
|
||||
import com.bms.ar.service.IArBalanceWriteoffService;
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomer;
|
||||
import com.bms.customer.customerinfo.domain.BmsCustomerAttachment;
|
||||
import com.bms.customer.customerinfo.mapper.BmsCustomerMapper;
|
||||
@@ -28,8 +36,10 @@ import com.bms.customer.customermoney.domain.CustomerBalanceFlow;
|
||||
import com.bms.customer.customermoney.domain.CustomerCreditApply;
|
||||
import com.bms.customer.customermoney.domain.CustomerCreditFlow;
|
||||
import com.bms.customer.customermoney.domain.CustomerReceipt;
|
||||
import com.bms.customer.customermoney.domain.ReceiptWriteoffPlan;
|
||||
import com.bms.customer.customermoney.mapper.CustomerCreditApplyMapper;
|
||||
import com.bms.customer.customermoney.mapper.CustomerMoneyMapper;
|
||||
import com.bms.customer.customermoney.mapper.ReceiptWriteoffPlanMapper;
|
||||
import com.bms.customer.customermoney.service.ICreditQuotaService;
|
||||
import com.bms.customer.customermoney.service.ICustomerMoneyService;
|
||||
import com.bms.price.service.IPrcOrderBillService;
|
||||
@@ -79,6 +89,18 @@ public class CustomerMoneyServiceImpl implements ICustomerMoneyService
|
||||
@Autowired
|
||||
private ArBankAccountMapper arBankAccountMapper;
|
||||
|
||||
/** 应收账单:登记收款选择核销账单时校验账单状态/未核销额 */
|
||||
@Autowired
|
||||
private ArBillMapper arBillMapper;
|
||||
|
||||
/** 收款核销计划 */
|
||||
@Autowired
|
||||
private ReceiptWriteoffPlanMapper receiptWriteoffPlanMapper;
|
||||
|
||||
/** 余额核销:收款审核通过事务内逐张核销账单 */
|
||||
@Autowired
|
||||
private IArBalanceWriteoffService balanceWriteoffService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public List<CustomerAccount> selectAccountList(Long customerId)
|
||||
@@ -118,6 +140,7 @@ public class CustomerMoneyServiceImpl implements ICustomerMoneyService
|
||||
query.setBizType(BmsCustomerAttachment.BIZ_TYPE_CUSTOMER_RECEIPT);
|
||||
query.setBizId(id);
|
||||
receipt.setAttachmentList(bmsCustomerMapper.selectBmsCustomerAttachmentList(query));
|
||||
receipt.setWriteoffPlans(receiptWriteoffPlanMapper.selectByReceiptId(id));
|
||||
}
|
||||
return receipt;
|
||||
}
|
||||
@@ -134,6 +157,8 @@ public class CustomerMoneyServiceImpl implements ICustomerMoneyService
|
||||
{
|
||||
throw new ServiceException("收款金额必须大于0");
|
||||
}
|
||||
// 统一金额口径:入口即规范为两位小数,后续本位币、核销合计、余额分配均基于该值计算
|
||||
receipt.setAmount(receipt.getAmount().setScale(MONEY_SCALE, RoundingMode.HALF_UP));
|
||||
if (!StringUtils.hasText(receipt.getReceiptType()))
|
||||
{
|
||||
receipt.setReceiptType(CustomerReceipt.TYPE_PREPAY);
|
||||
@@ -231,11 +256,24 @@ public class CustomerMoneyServiceImpl implements ICustomerMoneyService
|
||||
BigDecimal baseAmount = receipt.getAmount().multiply(rate).setScale(MONEY_SCALE, RoundingMode.HALF_UP);
|
||||
receipt.setBaseAmount(baseAmount);
|
||||
|
||||
// 核销账单计划校验:当前账单均为人民币(CNY)账单,计划金额即本位币 CNY 金额,
|
||||
// 上限为收款按汇率折算后的本位币金额 baseAmount;核销本身不增减客户余额。
|
||||
List<ReceiptWriteoffPlan> plans = validateWriteoffPlans(receipt);
|
||||
BigDecimal allocatedBase = plans.stream()
|
||||
.map(ReceiptWriteoffPlan::getWriteoffAmount)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
// 全额分配=还款核销,部分分配=混合,不选账单=预充值/保持所选类型(本位币口径比较)
|
||||
if (!plans.isEmpty())
|
||||
{
|
||||
receipt.setReceiptType(allocatedBase.compareTo(baseAmount) == 0
|
||||
? CustomerReceipt.TYPE_REPAY : CustomerReceipt.TYPE_MIXED);
|
||||
}
|
||||
|
||||
receipt.setReceiptNo(generateNo("SK"));
|
||||
receipt.setStatus(CustomerReceipt.STATUS_PENDING);
|
||||
receipt.setAllocatedAmount(BigDecimal.ZERO);
|
||||
// 核销口径统一为本位币 CNY
|
||||
receipt.setUnallocatedAmount(baseAmount);
|
||||
// 核销金额即本位币 CNY,无需再乘汇率
|
||||
receipt.setAllocatedAmount(allocatedBase);
|
||||
receipt.setUnallocatedAmount(baseAmount.subtract(allocatedBase));
|
||||
if (!StringUtils.hasText(receipt.getInvoiceStatus()))
|
||||
{
|
||||
receipt.setInvoiceStatus("NONE");
|
||||
@@ -243,11 +281,146 @@ public class CustomerMoneyServiceImpl implements ICustomerMoneyService
|
||||
receipt.setVersion(0);
|
||||
customerMoneyMapper.insertReceipt(receipt);
|
||||
|
||||
// 核销计划落 PENDING,审核通过事务内再逐张执行
|
||||
String operator = receipt.getCreateBy();
|
||||
for (ReceiptWriteoffPlan plan : plans)
|
||||
{
|
||||
plan.setReceiptId(receipt.getId());
|
||||
plan.setStatus(ReceiptWriteoffPlan.STATUS_PENDING);
|
||||
plan.setCreateBy(operator);
|
||||
receiptWriteoffPlanMapper.insertPlan(plan);
|
||||
}
|
||||
|
||||
// 收款附件:复用客户附件表,业务模块挂 customer_receipt,biz_id 关联收款单
|
||||
saveReceiptAttachments(receipt);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验登记收款携带的核销账单计划并规范化。
|
||||
* 口径(暂不支持多币种账单):
|
||||
* 账单必须属于当前客户、账单币种为人民币 CNY、状态可核销(已确认/部分核销);
|
||||
* 每张本次核销额(CNY)大于0且不超过账单未核销额;
|
||||
* 合计不超过收款按汇率折算后的本位币金额 baseAmount(CNY)。
|
||||
* 审核时会再次锁账单强校验,防止登记后账单被别处抢先核销。
|
||||
*/
|
||||
private List<ReceiptWriteoffPlan> validateWriteoffPlans(CustomerReceipt receipt)
|
||||
{
|
||||
List<ReceiptWriteoffPlan> raw = receipt.getWriteoffPlans();
|
||||
if (CollectionUtils.isEmpty(raw))
|
||||
{
|
||||
return new ArrayList<>();
|
||||
}
|
||||
BigDecimal baseAmount = receipt.getBaseAmount() != null
|
||||
? receipt.getBaseAmount().setScale(MONEY_SCALE, RoundingMode.HALF_UP)
|
||||
: receipt.getAmount().multiply(receipt.getExchangeRate()).setScale(MONEY_SCALE, RoundingMode.HALF_UP);
|
||||
List<ReceiptWriteoffPlan> plans = new ArrayList<>();
|
||||
Set<Long> billIds = new HashSet<>();
|
||||
BigDecimal total = BigDecimal.ZERO;
|
||||
for (ReceiptWriteoffPlan item : raw)
|
||||
{
|
||||
if (item == null || item.getArBillId() == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
BigDecimal amount = item.getWriteoffAmount();
|
||||
if (amount == null)
|
||||
{
|
||||
throw new ServiceException("请填写每张账单的本次核销金额");
|
||||
}
|
||||
amount = amount.setScale(MONEY_SCALE, RoundingMode.HALF_UP);
|
||||
if (amount.compareTo(BigDecimal.ZERO) <= 0)
|
||||
{
|
||||
throw new ServiceException("核销金额必须大于0");
|
||||
}
|
||||
if (!billIds.add(item.getArBillId()))
|
||||
{
|
||||
throw new ServiceException("同一账单不能重复选择,请合并为一条并填写合计金额");
|
||||
}
|
||||
ArBill bill = arBillMapper.selectArBillById(item.getArBillId());
|
||||
if (bill == null)
|
||||
{
|
||||
throw new ServiceException("所选应收账单不存在,请刷新后重新选择");
|
||||
}
|
||||
if (!receipt.getCustomerId().equals(bill.getCustomerId()))
|
||||
{
|
||||
throw new ServiceException("账单【" + bill.getBillNo() + "】不属于当前客户");
|
||||
}
|
||||
// 现阶段仅支持人民币账单核销;外币账单暂不在此入口处理
|
||||
String billCurrency = StringUtils.hasText(bill.getCurrency())
|
||||
? bill.getCurrency().trim().toUpperCase() : BASE_CURRENCY;
|
||||
if (!BASE_CURRENCY.equals(billCurrency))
|
||||
{
|
||||
throw new ServiceException("账单【" + bill.getBillNo() + "】币种为 " + billCurrency
|
||||
+ ",当前仅支持人民币(CNY)账单核销");
|
||||
}
|
||||
ArBillStatus billStatus = ArBillStatus.of(bill.getStatus());
|
||||
if (billStatus == null || !billStatus.canWriteOff())
|
||||
{
|
||||
throw new ServiceException("账单【" + bill.getBillNo() + "】当前状态不允许核销:"
|
||||
+ (billStatus == null ? bill.getStatus() : billStatus.getLabel()));
|
||||
}
|
||||
BigDecimal unwritten = bill.getUnwrittenAmount() == null
|
||||
? BigDecimal.ZERO : bill.getUnwrittenAmount();
|
||||
if (amount.compareTo(unwritten) > 0)
|
||||
{
|
||||
throw new ServiceException("账单【" + bill.getBillNo() + "】本次核销金额 "
|
||||
+ amount.toPlainString() + " 超过其未核销金额 " + unwritten.toPlainString());
|
||||
}
|
||||
total = total.add(amount);
|
||||
if (total.compareTo(baseAmount) > 0)
|
||||
{
|
||||
throw new ServiceException("核销金额合计 " + total.toPlainString()
|
||||
+ " CNY 超过本收款单折算本位币金额 " + baseAmount.toPlainString() + " CNY");
|
||||
}
|
||||
|
||||
ReceiptWriteoffPlan plan = new ReceiptWriteoffPlan();
|
||||
plan.setArBillId(bill.getArBillId());
|
||||
plan.setBillNo(bill.getBillNo());
|
||||
plan.setCustomerId(bill.getCustomerId());
|
||||
plan.setCurrency(BASE_CURRENCY);
|
||||
plan.setWriteoffAmount(amount);
|
||||
plan.setRemark(StringUtils.hasText(item.getRemark()) ? item.getRemark().trim() : null);
|
||||
plans.add(plan);
|
||||
}
|
||||
return plans;
|
||||
}
|
||||
|
||||
/**
|
||||
* 收款审核通过后执行核销计划:同一事务内逐张锁账单核销,
|
||||
* 任一账单已被别处抢先核销导致超额时,整笔审核回滚(含余额入账),不产生半截数据。
|
||||
*/
|
||||
private void executeReceiptWriteoffPlans(CustomerReceipt receipt, String operator)
|
||||
{
|
||||
List<ReceiptWriteoffPlan> plans = receiptWriteoffPlanMapper.selectByReceiptId(receipt.getId());
|
||||
if (CollectionUtils.isEmpty(plans))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Date writeoffDate = new Date();
|
||||
for (ReceiptWriteoffPlan plan : plans)
|
||||
{
|
||||
if (!ReceiptWriteoffPlan.STATUS_PENDING.equals(plan.getStatus()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ArBalanceWriteoff cmd = new ArBalanceWriteoff();
|
||||
cmd.setArBillId(plan.getArBillId());
|
||||
cmd.setCustomerId(plan.getCustomerId());
|
||||
cmd.setReceiptId(receipt.getId());
|
||||
cmd.setWriteoffAmount(plan.getWriteoffAmount());
|
||||
cmd.setWriteoffDate(writeoffDate);
|
||||
cmd.setRemark("收款单审核联动核销:" + receipt.getReceiptNo());
|
||||
cmd.setCreateBy(operator);
|
||||
// writeoff 内部锁账单行、复核状态与未核销额,冲突时抛异常由外层事务统一回滚
|
||||
ArBalanceWriteoff done = balanceWriteoffService.writeoff(cmd);
|
||||
if (receiptWriteoffPlanMapper.updateEffective(plan.getPlanId(), done.getWriteoffId(), operator) != 1)
|
||||
{
|
||||
throw new ServiceException("收款核销计划状态已变化,请刷新后重试");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造汇率表来源说明:汇率来源(中国银行/央行等)+ 命中路径(正向/反向取倒数/经CNY交叉)。
|
||||
* resolveRate 返回对象的 remark 带 __RATE_PATH__ 前缀标记命中路径。
|
||||
@@ -343,6 +516,9 @@ public class CustomerMoneyServiceImpl implements ICustomerMoneyService
|
||||
{
|
||||
throw new ServiceException("收款单状态已变更,请刷新后重试");
|
||||
}
|
||||
|
||||
// 3. 登记时选择的账单在同一事务内一并核销;任一账单核销失败则整笔审核回滚
|
||||
executeReceiptWriteoffPlans(receipt, username);
|
||||
return receiptRows;
|
||||
}
|
||||
|
||||
@@ -359,7 +535,11 @@ public class CustomerMoneyServiceImpl implements ICustomerMoneyService
|
||||
{
|
||||
throw new ServiceException("仅待确认的收款单可以取消");
|
||||
}
|
||||
return customerMoneyMapper.cancelReceipt(id, SecurityUtils.getUsername());
|
||||
String operator = SecurityUtils.getUsername();
|
||||
int rows = customerMoneyMapper.cancelReceipt(id, operator);
|
||||
// 尚未执行的核销计划一并作废
|
||||
receiptWriteoffPlanMapper.cancelPendingByReceiptId(id, operator);
|
||||
return rows;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user