package com.ruoyi.account.service.impl.purchase;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.account.bean.dto.purchase.AccountPurchasePaymentDto;
import com.ruoyi.account.bean.vo.purchase.AccountPurchasePaymentVo;
import com.ruoyi.account.mapper.AccountStatementDetailsMapper;
import com.ruoyi.account.mapper.purchase.AccountPaymentApplicationMapper;
import com.ruoyi.account.mapper.purchase.AccountPurchasePaymentMapper;
import com.ruoyi.account.pojo.AccountStatementDetails;
import com.ruoyi.account.pojo.purchase.AccountPaymentApplication;
import com.ruoyi.account.pojo.purchase.AccountPurchasePayment;
import com.ruoyi.account.service.purchase.AccountPurchasePaymentService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.purchase.dto.SavePaymentDto;
import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
import com.ruoyi.purchase.pojo.PurchaseLedger;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
/**
*
* 财务管理--付款单 服务实现类
*
*
* @author 芯导软件(江苏)有限公司
* @since 2026-05-19 04:14:51
*/
@Service
@RequiredArgsConstructor
public class AccountPurchasePaymentServiceImpl extends ServiceImpl implements AccountPurchasePaymentService {
private static final DateTimeFormatter CODE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyMMddHHmmss");
private final AccountPurchasePaymentMapper accountPurchasePaymentMapper;
private final AccountStatementDetailsMapper accountStatementDetailsMapper;
private final AccountPaymentApplicationMapper accountPaymentApplicationMapper;
private final PurchaseLedgerMapper purchaseLedgerMapper;
@Override
public IPage listPageAccountPurchasePayment(Page page, AccountPurchasePaymentDto accountPurchasePaymentDto) {
return accountPurchasePaymentMapper.listPageAccountPurchasePayment(page, accountPurchasePaymentDto);
}
@Override
public boolean addAccountPurchasePayment(AccountPurchasePayment accountPurchasePayment) {
if (StringUtils.isEmpty(accountPurchasePayment.getPaymentNumber())) {
accountPurchasePayment.setPaymentNumber(genAccountPurchasePaymentNo());
}
//校验累计付款金额不能超过申请金额
AccountPaymentApplication accountPaymentApplication = accountPaymentApplicationMapper.selectById(accountPurchasePayment.getAccountPaymentApplicationId());
List accountPurchasePayments = accountPurchasePaymentMapper.selectList(Wrappers.lambdaQuery().eq(AccountPurchasePayment::getAccountPaymentApplicationId, accountPurchasePayment.getAccountPaymentApplicationId()));
BigDecimal totalPaymentAmount = accountPurchasePayments.stream().map(AccountPurchasePayment::getPaymentAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
if (accountPaymentApplication.getPaymentAmount().compareTo(totalPaymentAmount) < 0) {
throw new ServiceException("累计付款金额不能超过申请金额");
}
return save(accountPurchasePayment);
}
@Override
public void exportAccountPurchasePayment(HttpServletResponse response, AccountPurchasePaymentDto accountPurchasePaymentDto) {
List list = accountPurchasePaymentMapper.listPageAccountPurchasePayment(new Page(1,-1),accountPurchasePaymentDto).getRecords();
ExcelUtil util = new ExcelUtil<>(AccountPurchasePaymentVo.class);
util.exportExcel(response, list , "付款单");
}
@Override
public boolean deleteAccountPurchasePayment(List ids) {
//如果该付款单已经生成对账单则无法删除
List accountPurchasePayments = accountPurchasePaymentMapper.selectByIds(ids);
List strings = accountPurchasePayments.stream().map(AccountPurchasePayment::getPaymentNumber).toList();
List accountStatementDetails = accountStatementDetailsMapper.selectList(Wrappers.lambdaQuery()
.in(AccountStatementDetails::getReceiptNumber, strings));
if (CollectionUtils.isNotEmpty(accountStatementDetails)){
throw new ServiceException("该付款单已经生成对账单,无法删除");
}
return removeByIds(ids);
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean savePayment(SavePaymentDto dto) {
if (dto.getPaymentDate() == null) {
throw new ServiceException("请选择付款日期");
}
if (dto.getPaymentAmount() == null || dto.getPaymentAmount().compareTo(BigDecimal.valueOf(0.01)) < 0) {
throw new ServiceException("请输入付款金额");
}
if (StringUtils.isEmpty(dto.getPurchaseContractNumber())) {
throw new ServiceException("采购合同号不能为空");
}
if (dto.getSupplierId() == null) {
throw new ServiceException("供应商不能为空");
}
PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectOne(new LambdaQueryWrapper()
.eq(PurchaseLedger::getPurchaseContractNumber, dto.getPurchaseContractNumber()));
if (purchaseLedger == null) {
throw new ServiceException("采购合同不存在");
}
if (purchaseLedger.getSupplierId() == null || purchaseLedger.getSupplierId().longValue() != dto.getSupplierId().longValue()) {
throw new ServiceException("供应商与合同不匹配");
}
List stockInRecordIds = accountPurchasePaymentMapper.selectStockInRecordIdsByPurchaseLedgerId(purchaseLedger.getId());
if (CollectionUtils.isEmpty(stockInRecordIds)) {
throw new ServiceException("该合同暂无可付款的采购入库记录");
}
AccountPaymentApplication application = new AccountPaymentApplication();
application.setSupplierId(dto.getSupplierId().intValue());
application.setStockInRecordIds(stockInRecordIds.stream().map(String::valueOf).collect(Collectors.joining(",")));
application.setInvoiceApplicationNo(genPaymentApplicationNo());
application.setPaymentMethod(dto.getPaymentMethod());
application.setPaymentContent(dto.getPurchaseContractNumber());
application.setApplyDate(dto.getPaymentDate());
application.setRemark(dto.getRemark());
application.setStatus(1);
application.setPaymentAmount(dto.getPaymentAmount());
accountPaymentApplicationMapper.insert(application);
AccountPurchasePayment payment = new AccountPurchasePayment();
payment.setAccountPaymentApplicationId(application.getId());
payment.setSupplierId(dto.getSupplierId().intValue());
payment.setPaymentDate(dto.getPaymentDate());
payment.setPaymentMethod(dto.getPaymentMethod());
payment.setPaymentAmount(dto.getPaymentAmount());
payment.setPaymentNumber(genAccountPurchasePaymentNo());
payment.setRemark(dto.getRemark());
return save(payment);
}
private String genPaymentApplicationNo() {
return "FK" + LocalDateTime.now().format(CODE_TIME_FORMATTER) + new Random().nextInt(10);
}
private String genAccountPurchasePaymentNo() {
return "SK" + LocalDateTime.now().format(CODE_TIME_FORMATTER) + new Random().nextInt(10);
}
}