package com.ruoyi.account.service.impl;
|
|
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.StatementAccountDto;
|
import com.ruoyi.account.bean.dto.purchase.PurchaseInboundDto;
|
import com.ruoyi.account.bean.dto.purchase.PurchaseReturnDto;
|
import com.ruoyi.account.bean.dto.sales.SalesOutboundDto;
|
import com.ruoyi.account.bean.dto.sales.SalesReturnDto;
|
import com.ruoyi.account.bean.vo.StatementAccountVo;
|
import com.ruoyi.account.bean.vo.purchase.PurchaseInboundVo;
|
import com.ruoyi.account.bean.vo.purchase.PurchaseReturnVo;
|
import com.ruoyi.account.bean.vo.sales.SalesOutboundVo;
|
import com.ruoyi.account.bean.vo.sales.SalesReturnVo;
|
import com.ruoyi.account.mapper.AccountStatementDetailsMapper;
|
import com.ruoyi.account.mapper.AccountStatementMapper;
|
import com.ruoyi.account.mapper.purchase.AccountPurchasePaymentMapper;
|
import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper;
|
import com.ruoyi.account.pojo.AccountStatement;
|
import com.ruoyi.account.pojo.AccountStatementDetails;
|
import com.ruoyi.account.pojo.purchase.AccountPurchasePayment;
|
import com.ruoyi.account.pojo.sales.AccountSalesCollection;
|
import com.ruoyi.account.service.AccountStatementService;
|
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.utils.bean.BeanUtils;
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
import com.ruoyi.procurementrecord.mapper.ReturnManagementMapper;
|
import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper;
|
import com.ruoyi.stock.mapper.StockInRecordMapper;
|
import com.ruoyi.stock.mapper.StockOutRecordMapper;
|
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.YearMonth;
|
import java.time.format.DateTimeFormatter;
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.Random;
|
|
/**
|
* <p>
|
* 服务实现类
|
* </p>
|
*
|
* @author 芯导软件(江苏)有限公司
|
* @since 2026-05-19 09:42:47
|
*/
|
@Service
|
@RequiredArgsConstructor
|
@Transactional(rollbackFor = Exception.class)
|
public class AccountStatementServiceImpl extends ServiceImpl<AccountStatementMapper, AccountStatement> implements AccountStatementService {
|
|
private final AccountStatementMapper accountStatementMapper;
|
private final AccountSalesCollectionMapper accountSalesCollectionMapper;
|
private final StockOutRecordMapper stockOutRecordMapper;
|
private final StockInRecordMapper stockInRecordMapper;
|
private final ReturnManagementMapper returnManagementMapper;
|
private final AccountStatementDetailsMapper accountStatementDetailsMapper;
|
private final AccountPurchasePaymentMapper accountPurchasePaymentMapper;
|
private final PurchaseReturnOrdersMapper purchaseReturnOrdersMapper;
|
private static final DateTimeFormatter CODE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyMMdd");
|
|
@Override
|
public StatementAccountVo getAccountStatementDetailsByMonth(StatementAccountDto statementAccountDto) {
|
//对账月份转换成开始日期和结束日期区间
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
|
YearMonth yearMonth = YearMonth.parse(statementAccountDto.getStatementMonth(), formatter);
|
statementAccountDto.setStartDate(yearMonth.atDay(1));
|
statementAccountDto.setEndDate(yearMonth.atEndOfMonth());
|
if (statementAccountDto.getAccountType() == 1){
|
//应收对账--Customer
|
return getAccountStatementDetailsByCustomerAndMonth(statementAccountDto);
|
}else {
|
//应付对账--SupplierManage
|
return getAccountStatementDetailsBySupplierAndMonth(statementAccountDto);
|
}
|
}
|
|
@Override
|
public boolean addAccountStatement(StatementAccountVo statementAccountVo) {
|
//同一客户或者同一供应商,一个月份只能有一个对账单
|
List<AccountStatement> accountStatements = accountStatementMapper.selectList(Wrappers.<AccountStatement>lambdaQuery()
|
.eq(AccountStatement::getStatementMonth, statementAccountVo.getStatementMonth())
|
.eq(AccountStatement::getAccountType, statementAccountVo.getAccountType())
|
.eq(AccountStatement::getCustomerId, statementAccountVo.getCustomerId()));
|
if (CollectionUtils.isNotEmpty(accountStatements)){
|
throw new ServiceException("同一客户或者同一供应商,一个月份只能有一个对账单");
|
}
|
AccountStatement accountStatement = new AccountStatement();
|
BeanUtils.copyProperties(statementAccountVo, accountStatement);
|
accountStatement.setStatementNumber(genStatementAccountNo());
|
boolean save = save(accountStatement);
|
statementAccountVo.getAccountStatementDetails().stream().forEach(accountStatementDetails -> {
|
accountStatementDetails.setAccountStatementId(accountStatement.getId());
|
//添加对账单明细
|
accountStatementDetailsMapper.insert(accountStatementDetails);
|
});
|
return save;
|
}
|
|
@Override
|
public boolean deleteAccountStatement(List<Long> ids) {
|
//删除对账单明细
|
accountStatementDetailsMapper.delete(Wrappers.<AccountStatementDetails>lambdaQuery().in(AccountStatementDetails::getAccountStatementId, ids));
|
return removeByIds(ids);
|
}
|
|
@Override
|
public IPage<StatementAccountVo> listPageAccountStatement(Page page, StatementAccountDto statementAccountDto) {
|
return accountStatementMapper.listPageAccountStatement(page, statementAccountDto);
|
}
|
|
@Override
|
public void exportAccountStatement(HttpServletResponse response, StatementAccountDto statementAccountDto) {
|
List<StatementAccountVo> list = accountStatementMapper.listPageAccountStatement(new Page(1,-1),statementAccountDto).getRecords();
|
ExcelUtil<StatementAccountVo> util = new ExcelUtil<>(StatementAccountVo.class);
|
util.exportExcel(response, list , "对账单");
|
}
|
|
//根据客户和月份获取对账详情(销售)
|
private StatementAccountVo getAccountStatementDetailsByCustomerAndMonth(StatementAccountDto statementAccountDto) {
|
StatementAccountVo statementAccountVo = new StatementAccountVo();
|
statementAccountVo.setAccountType(1);//应收对账
|
List<AccountStatementDetails> accountStatementDetailsList = new ArrayList<>();
|
/*查询出库明细*/
|
SalesOutboundDto salesOutboundDto = new SalesOutboundDto();
|
salesOutboundDto.setCustomerId(statementAccountDto.getCustomerId());
|
salesOutboundDto.setStartDate(statementAccountDto.getStartDate());
|
salesOutboundDto.setEndDate(statementAccountDto.getEndDate());
|
List<SalesOutboundVo> salesOutboundVos = stockOutRecordMapper.listPageAccountSales(new Page(1, -1), salesOutboundDto).getRecords();
|
salesOutboundVos.stream().forEach(salesOutboundVo -> {
|
AccountStatementDetails accountStatementDetails = new AccountStatementDetails();
|
//数据日期=出库日期
|
accountStatementDetails.setOccurrenceDate(salesOutboundVo.getShippingDate());
|
//单据编号=出库单号
|
accountStatementDetails.setReceiptNumber(salesOutboundVo.getOutboundBatches());
|
//类型=出库
|
accountStatementDetails.setType(1);
|
//金额=出库金额
|
accountStatementDetails.setAmount(salesOutboundVo.getOutboundAmount());
|
//备注
|
accountStatementDetails.setRemark("产品销售出库,产品:"+salesOutboundVo.getProductName());
|
accountStatementDetailsList.add(accountStatementDetails);
|
});
|
/*查询收款明细*/
|
List<AccountSalesCollection> accountSalesCollections = accountSalesCollectionMapper.selectList(Wrappers.<AccountSalesCollection>lambdaQuery()
|
.eq(AccountSalesCollection::getCustomerId, statementAccountDto.getCustomerId())
|
.between(AccountSalesCollection::getCollectionDate, statementAccountDto.getStartDate(), statementAccountDto.getEndDate()));
|
accountSalesCollections.stream().forEach(accountSalesCollection -> {
|
AccountStatementDetails accountStatementDetails = new AccountStatementDetails();
|
//数据日期=收款日期
|
accountStatementDetails.setOccurrenceDate(accountSalesCollection.getCollectionDate());
|
//单据编号=收款单号
|
accountStatementDetails.setReceiptNumber(accountSalesCollection.getCollectionNumber());
|
//类型=收款
|
accountStatementDetails.setType(3);
|
//金额=收款金额
|
accountStatementDetails.setAmount(accountSalesCollection.getCollectionAmount());
|
//备注
|
accountStatementDetails.setRemark("客户回款,备注:"+accountSalesCollection.getRemark());
|
accountStatementDetailsList.add(accountStatementDetails);
|
});
|
/*查询退货明细*/
|
SalesReturnDto salesReturnDto = new SalesReturnDto();
|
salesReturnDto.setCustomerId(statementAccountDto.getCustomerId());
|
salesReturnDto.setStartDate(statementAccountDto.getStartDate());
|
salesReturnDto.setEndDate(statementAccountDto.getEndDate());
|
List<SalesReturnVo> salesReturnVos = returnManagementMapper.listPageAccountSalesReturn(new Page(1, -1), salesReturnDto).getRecords();
|
salesReturnVos.stream().forEach(salesReturnVo -> {
|
AccountStatementDetails accountStatementDetails = new AccountStatementDetails();
|
//数据日期=退货日期
|
accountStatementDetails.setOccurrenceDate(salesReturnVo.getMakeTime().toLocalDate());
|
//单据编号=退货单号
|
accountStatementDetails.setReceiptNumber(salesReturnVo.getReturnNo());
|
//类型=退货
|
accountStatementDetails.setType(5);
|
//金额=退款金额
|
accountStatementDetails.setAmount(salesReturnVo.getRefundAmount());
|
//备注
|
accountStatementDetails.setRemark("产品退货,原因:"+salesReturnVo.getReturnReason());
|
accountStatementDetailsList.add(accountStatementDetails);
|
});
|
//期初余额=上个月的期末余额
|
statementAccountVo.setOpeningBalance(BigDecimal.ZERO);
|
List<AccountStatement> accountStatements = accountStatementMapper.selectList(Wrappers.<AccountStatement>lambdaQuery()
|
.eq(AccountStatement::getAccountType, 1)
|
.eq(AccountStatement::getCustomerId, statementAccountDto.getCustomerId())
|
.eq(AccountStatement::getStatementMonth,
|
YearMonth.parse(statementAccountDto.getStatementMonth()).minusMonths(1).toString()));
|
if (CollectionUtils.isNotEmpty(accountStatements)){
|
statementAccountVo.setOpeningBalance(accountStatements.get(accountStatements.size() - 1).getClosingBalance());
|
}
|
//本期应收=出库-退货金额累计
|
statementAccountVo.setCurrentPlan(salesOutboundVos.stream().map(SalesOutboundVo::getOutboundAmount).reduce(BigDecimal.ZERO, BigDecimal::add)
|
.subtract(salesReturnVos.stream().map(SalesReturnVo::getRefundAmount).reduce(BigDecimal.ZERO, BigDecimal::add)));
|
//本期收款=收款金额累计
|
statementAccountVo.setCurrentActually(accountSalesCollections.stream().map(AccountSalesCollection::getCollectionAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
|
//期末余额=期初+应收-收款
|
statementAccountVo.setClosingBalance(statementAccountVo.getOpeningBalance().add(statementAccountVo.getCurrentPlan()).subtract(statementAccountVo.getCurrentActually()));
|
statementAccountVo.setAccountStatementDetails(accountStatementDetailsList);
|
return statementAccountVo;
|
}
|
|
//根据供应商和月份获取对账详情(采购)
|
private StatementAccountVo getAccountStatementDetailsBySupplierAndMonth(StatementAccountDto statementAccountDto) {
|
StatementAccountVo statementAccountVo = new StatementAccountVo();
|
statementAccountVo.setAccountType(2);//应付对账
|
List<AccountStatementDetails> accountStatementDetailsList = new ArrayList<>();
|
/*查询入库明细*/
|
PurchaseInboundDto purchaseInboundDto = new PurchaseInboundDto();
|
purchaseInboundDto.setSupplierId(statementAccountDto.getCustomerId());
|
purchaseInboundDto.setStartDate(statementAccountDto.getStartDate());
|
purchaseInboundDto.setEndDate(statementAccountDto.getEndDate());
|
List<PurchaseInboundVo> purchaseInboundVos = stockInRecordMapper.listPageAccountPurchase(new Page(1, -1), purchaseInboundDto).getRecords();
|
purchaseInboundVos.stream().forEach(purchaseInboundVo -> {
|
AccountStatementDetails accountStatementDetails = new AccountStatementDetails();
|
//数据日期=入库日期
|
accountStatementDetails.setOccurrenceDate(purchaseInboundVo.getInboundDate());
|
//单据编号=入库单号
|
accountStatementDetails.setReceiptNumber(purchaseInboundVo.getInboundBatches());
|
//类型=入库
|
accountStatementDetails.setType(2);
|
//金额=入库金额
|
accountStatementDetails.setAmount(purchaseInboundVo.getInboundAmount());
|
//备注
|
accountStatementDetails.setRemark("产品采购入库,产品:"+purchaseInboundVo.getProductName());
|
accountStatementDetailsList.add(accountStatementDetails);
|
});
|
/*查询付款明细*/
|
List<AccountPurchasePayment> accountPurchasePayments = accountPurchasePaymentMapper.selectList(Wrappers.<AccountPurchasePayment>lambdaQuery()
|
.eq(AccountPurchasePayment::getSupplierId, statementAccountDto.getCustomerId())
|
.between(AccountPurchasePayment::getPaymentDate, statementAccountDto.getStartDate(), statementAccountDto.getEndDate()));
|
accountPurchasePayments.stream().forEach(accountPurchasePayment -> {
|
AccountStatementDetails accountStatementDetails = new AccountStatementDetails();
|
//数据日期=付款日期
|
accountStatementDetails.setOccurrenceDate(accountPurchasePayment.getPaymentDate());
|
//单据编号=付款单号
|
accountStatementDetails.setReceiptNumber(accountPurchasePayment.getPaymentNumber());
|
//类型=付款
|
accountStatementDetails.setType(4);
|
//金额=付款金额
|
accountStatementDetails.setAmount(accountPurchasePayment.getPaymentAmount());
|
//备注
|
accountStatementDetails.setRemark("支付货款,备注:"+accountPurchasePayment.getRemark());
|
accountStatementDetailsList.add(accountStatementDetails);
|
});
|
/*查询退货明细*/
|
PurchaseReturnDto purchaseReturnDto = new PurchaseReturnDto();
|
purchaseReturnDto.setSupplierId(statementAccountDto.getCustomerId());
|
purchaseReturnDto.setStartDate(statementAccountDto.getStartDate());
|
purchaseReturnDto.setEndDate(statementAccountDto.getEndDate());
|
List<PurchaseReturnVo> purchaseReturnVos = purchaseReturnOrdersMapper.listPageAccountPurchaseReturn(new Page(1, -1), purchaseReturnDto).getRecords();
|
purchaseReturnVos.stream().forEach(purchaseReturnVo -> {
|
AccountStatementDetails accountStatementDetails = new AccountStatementDetails();
|
//数据日期=退货日期
|
accountStatementDetails.setOccurrenceDate(purchaseReturnVo.getPreparedAt().toLocalDate());
|
//单据编号=退货单号
|
accountStatementDetails.setReceiptNumber(purchaseReturnVo.getReturnNo());
|
//类型=退货
|
accountStatementDetails.setType(5);
|
//金额=退款金额
|
accountStatementDetails.setAmount(purchaseReturnVo.getTotalAmount());
|
//备注
|
accountStatementDetails.setRemark("产品退货,退货方式:"+purchaseReturnVo.getReturnType());
|
accountStatementDetailsList.add(accountStatementDetails);
|
});
|
//期初余额=上个月的期末余额
|
statementAccountVo.setOpeningBalance(BigDecimal.ZERO);
|
List<AccountStatement> accountStatements = accountStatementMapper.selectList(Wrappers.<AccountStatement>lambdaQuery()
|
.eq(AccountStatement::getAccountType, 2)
|
.eq(AccountStatement::getCustomerId, statementAccountDto.getCustomerId())
|
.eq(AccountStatement::getStatementMonth,
|
YearMonth.parse(statementAccountDto.getStatementMonth()).minusMonths(1).toString()));
|
if (CollectionUtils.isNotEmpty(accountStatements)){
|
statementAccountVo.setOpeningBalance(accountStatements.get(accountStatements.size() - 1).getClosingBalance());
|
}
|
//本期应付=入库-退货金额累计
|
statementAccountVo.setCurrentPlan(purchaseInboundVos.stream().map(PurchaseInboundVo::getInboundAmount).reduce(BigDecimal.ZERO, BigDecimal::add)
|
.subtract(purchaseReturnVos.stream().map(PurchaseReturnVo::getTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add)));
|
//本期付款=付款金额累计
|
statementAccountVo.setCurrentActually(accountPurchasePayments.stream().map(AccountPurchasePayment::getPaymentAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
|
//期末余额=期初+应收-收款
|
statementAccountVo.setClosingBalance(statementAccountVo.getOpeningBalance().add(statementAccountVo.getCurrentPlan()).subtract(statementAccountVo.getCurrentActually()));
|
statementAccountVo.setAccountStatementDetails(accountStatementDetailsList);
|
return statementAccountVo;
|
}
|
|
private String genStatementAccountNo() {
|
return "DZ" + LocalDateTime.now().format(CODE_TIME_FORMATTER) + new Random().nextInt(10);
|
}
|
}
|