package com.ruoyi.tms.service.impl;
|
|
import java.io.File;
|
import java.io.FileOutputStream;
|
import java.math.BigDecimal;
|
import java.math.RoundingMode;
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.HashMap;
|
import java.util.HashSet;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Set;
|
import java.util.stream.Collectors;
|
|
import com.alibaba.fastjson2.JSONObject;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.redis.RedisCache;
|
import com.ruoyi.common.enums.SystemDataNoEnum;
|
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.common.utils.DateUtils;
|
|
import com.ruoyi.common.utils.file.DownloadExportUtil;
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
import com.ruoyi.common.config.RuoYiConfig;
|
import org.apache.poi.ss.usermodel.*;
|
import org.apache.poi.ss.util.CellRangeAddress;
|
import org.apache.poi.xssf.streaming.SXSSFSheet;
|
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
|
import org.apache.poi.xssf.usermodel.XSSFColor;
|
import javax.annotation.Resource;
|
|
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.system.service.ISysConfigService;
|
import com.ruoyi.system.service.ISystemDataNoService;
|
import com.ruoyi.tms.domain.*;
|
import com.ruoyi.tms.mapper.*;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.http.HttpEntity;
|
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpMethod;
|
import org.springframework.http.MediaType;
|
import org.springframework.http.ResponseEntity;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.core.task.AsyncTaskExecutor;
|
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
import org.springframework.web.client.RestTemplate;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import com.alibaba.fastjson2.JSON;
|
import com.ruoyi.common.utils.PageUtils;
|
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.annotation.DataSource;
|
import com.ruoyi.common.enums.DataSourceType;
|
import com.ruoyi.common.core.service.BaseService;
|
|
import com.ruoyi.tms.service.ITmsReceivableFeeService;
|
import com.ruoyi.common.core.text.Convert;
|
|
/**
|
* 应收费用Service业务层处理
|
*
|
* @author ruoyi
|
* @date 2025-12-12
|
*/
|
@Service
|
@Transactional(rollbackFor = Exception.class)
|
public class TmsReceivableFeeServiceImpl extends BaseService<TmsReceivableFeeMapper, TmsReceivableFee> implements ITmsReceivableFeeService
|
{
|
protected final Logger logger = LoggerFactory.getLogger(getClass());
|
@Resource
|
private TmsReceivableFeeMapper tmsReceivableFeeMapper;
|
@Resource
|
private TmsReceivableFeeItemMapper tmsReceivableFeeItemMapper;
|
@Resource
|
private TmsDispatchOrderMapper tmsDispatchOrderMapper;
|
@Resource
|
ISysConfigService sysConfigService;
|
@Autowired
|
ISystemDataNoService systemDataNoService;
|
@Resource
|
private TmsArBillMapper tmsArBillMapper;
|
@Resource
|
private TmsArBillItemMapper tmsArBillItemMapper;
|
|
@Autowired
|
private RestTemplate restTemplate;
|
@Value("${custom.cwxtApi.url}")
|
private String url;
|
|
@Autowired
|
private RedisCache redisCache;
|
/**
|
* 查询应收费用
|
*
|
* @param id 应收费用ID
|
* @return 应收费用
|
*/
|
@DataSource(DataSourceType.SLAVE)
|
@Override
|
public TmsReceivableFee selectTmsReceivableFeeById(Integer id)
|
{
|
TmsReceivableFee tmsReceivableFee = tmsReceivableFeeMapper.selectTmsReceivableFeeById(id);
|
List<TmsReceivableFeeItem> tmsReceivableFeeItems = tmsReceivableFeeItemMapper.selectTmsReceivableFeeItemList(new TmsReceivableFeeItem() {{
|
setHeadId(id);
|
}});
|
tmsReceivableFee.setItems(tmsReceivableFeeItems);
|
return tmsReceivableFee;
|
}
|
|
|
@Override
|
public TmsReceivableFee selectTmsReceivableFeeByDispatchNo(String dispatchNo) {
|
TmsReceivableFee tmsReceivableFee = tmsReceivableFeeMapper.selectOne(new LambdaUpdateWrapper<TmsReceivableFee>()
|
.eq(TmsReceivableFee::getDispatchNo, dispatchNo)
|
.ne(TmsReceivableFee::getStatus, 2)
|
.last("limit 1")
|
);
|
if(tmsReceivableFee != null){
|
List<TmsReceivableFeeItem> tmsReceivableFeeItems = tmsReceivableFeeItemMapper.selectTmsReceivableFeeItemList(new TmsReceivableFeeItem() {{
|
setHeadId(tmsReceivableFee.getId());
|
}});
|
tmsReceivableFee.setItems(tmsReceivableFeeItems);
|
return tmsReceivableFee;
|
}
|
return null;
|
}
|
|
/**
|
* 查询应收费用 记录数
|
*
|
* @param tmsReceivableFee 应收费用
|
* @return 应收费用集合
|
*/
|
@DataSource(DataSourceType.SLAVE)
|
@Override
|
public int selectTmsReceivableFeeCount(TmsReceivableFee tmsReceivableFee)
|
{
|
return tmsReceivableFeeMapper.selectTmsReceivableFeeCount(tmsReceivableFee);
|
}
|
|
/**
|
* 查询应收费用列表
|
*
|
* @param tmsReceivableFee 应收费用
|
* @return 应收费用
|
*/
|
@DataSource(DataSourceType.SLAVE)
|
@Override
|
public List<TmsReceivableFee> selectTmsReceivableFeeList(TmsReceivableFee tmsReceivableFee)
|
{
|
return tmsReceivableFeeMapper.selectTmsReceivableFeeList(tmsReceivableFee);
|
}
|
|
/**
|
* 查询应收费用列表 异步 导出
|
*
|
* @param tmsReceivableFee 应收费用
|
* @param exportKey 导出功能的唯一标识
|
* @return 应收费用集合
|
*/
|
@DataSource(DataSourceType.SLAVE)
|
@Async
|
@Override
|
public void export(TmsReceivableFee tmsReceivableFee,String exportKey) {
|
|
super.export(TmsReceivableFee.class,exportKey,"tmsReceivableFeeData",(pageNum)->{
|
PageUtils.startPage(pageNum, Constants.EXPORT_PATE_SIZE);
|
return selectTmsReceivableFeeList(tmsReceivableFee);
|
});
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
* 新增应收费用
|
*
|
* @param tmsReceivableFee 应收费用
|
* @return 结果
|
*/
|
@Override
|
public int insertTmsReceivableFee(TmsReceivableFee tmsReceivableFee)
|
{
|
tmsReceivableFee.setCreateTime(DateUtils.getNowDate());
|
return tmsReceivableFeeMapper.insertTmsReceivableFee(tmsReceivableFee);
|
}
|
|
/**
|
* 新增应收费用[批量]
|
*
|
* @param tmsReceivableFees 应收费用
|
* @return 结果
|
*/
|
@Override
|
public int insertTmsReceivableFeeBatch(List<TmsReceivableFee> tmsReceivableFees)
|
{
|
int rows = tmsReceivableFeeMapper.insertTmsReceivableFeeBatch(tmsReceivableFees);
|
return rows;
|
}
|
|
/**
|
* 修改应收费用
|
*
|
* @param tmsReceivableFee 应收费用
|
* @return 结果
|
*/
|
@Override
|
public int updateTmsReceivableFee(TmsReceivableFee tmsReceivableFee)
|
{
|
tmsReceivableFee.setUpdateTime(DateUtils.getNowDate());
|
return tmsReceivableFeeMapper.updateTmsReceivableFee(tmsReceivableFee);
|
}
|
|
/**
|
* 修改应收费用[批量]
|
*
|
* @param tmsReceivableFees 应收费用
|
* @return 结果
|
*/
|
@Override
|
public int updateTmsReceivableFeeBatch(List<TmsReceivableFee> tmsReceivableFees){
|
return tmsReceivableFeeMapper.updateTmsReceivableFeeBatch(tmsReceivableFees);
|
}
|
|
@Override
|
public int closeTmsReceivableFeeById(Integer id) {
|
TmsReceivableFee tmsReceivableFee = selectTmsReceivableFeeById(id);
|
if(tmsReceivableFee != null){
|
tmsReceivableFee.setStatus(2);
|
updateTmsReceivableFee(tmsReceivableFee);
|
tmsDispatchOrderMapper.update(new LambdaUpdateWrapper<TmsDispatchOrder>()
|
.eq(TmsDispatchOrder::getId,tmsReceivableFee.getDispatchId())
|
.set(TmsDispatchOrder::getAccountsReceivableStatus,0)
|
);
|
}else{
|
throw new RuntimeException("数据不存在");
|
}
|
|
return 1;
|
}
|
|
/**
|
* 删除应收费用对象
|
*
|
* @param ids 需要删除的数据ID
|
* @return 结果
|
*/
|
@Override
|
public int deleteTmsReceivableFeeByIds(String ids)
|
{
|
return deleteTmsReceivableFeeByIds(Convert.toIntArray(ids));
|
}
|
|
/**
|
* 删除应收费用对象
|
*
|
*
|
* @param ids 需要删除的数据ID
|
* @return 结果
|
*/
|
@Override
|
public int deleteTmsReceivableFeeByIds(Integer[] ids)
|
{
|
return tmsReceivableFeeMapper.deleteTmsReceivableFeeByIds(ids);
|
}
|
|
@Override
|
public TmsArBill initArGenerate(Integer[] ids) {
|
|
List<TmsReceivableFee> tmsReceivableFees = tmsReceivableFeeMapper.
|
selectBatchIds(Arrays.asList(ids));
|
// 判断是否有不同的客户
|
boolean hasDifferentCustomers = tmsReceivableFees.stream()
|
.map(TmsReceivableFee::getCustomerId)
|
.distinct()
|
.count() > 1;
|
if (hasDifferentCustomers) {
|
throw new RuntimeException("所选费用包含不同客户,无法合并生成应收账单");
|
}
|
|
TmsArBill tmsArBill = new TmsArBill();
|
tmsArBill.setDispatchCount(tmsReceivableFees.size());
|
String s = sysConfigService.selectConfigByKey("sys.hk.rmb.rate");
|
BigDecimal exchangeRate = new BigDecimal(s);
|
tmsArBill.setSettleRate(exchangeRate);
|
TmsReceivableFee tmsReceivableFee = tmsReceivableFees.get(0);
|
tmsArBill.setCustomerId(tmsReceivableFee.getCustomerId());
|
tmsArBill.setCustomerName(tmsReceivableFee.getCustomerName());
|
tmsArBill.setBillName(DateUtils.dateTime()+tmsArBill.getCustomerName()+"账单");
|
|
tmsArBill.setSettleAmount(BigDecimal.ZERO);
|
tmsReceivableFees.forEach(item ->{
|
List<TmsReceivableFeeItem> tmsReceivableFeeItems = tmsReceivableFeeItemMapper.selectTmsReceivableFeeItemList(new TmsReceivableFeeItem() {{
|
setHeadId(item.getId());
|
}});
|
item.setItems(tmsReceivableFeeItems);
|
BigDecimal rmbAmount = item.getReceivableHKBAmount()
|
.multiply(exchangeRate)
|
.setScale(2, RoundingMode.HALF_UP);
|
item.setReceivableRmbSumAmount( item.getReceivableRMBAmount().add(rmbAmount));
|
tmsArBill.setSettleAmount(tmsArBill.getSettleAmount().add(item.getReceivableRmbSumAmount()));
|
|
});
|
tmsArBill.setTmsReceivableFees(tmsReceivableFees);
|
tmsArBill.setActualSettlementAmount(tmsArBill.getSettleAmount());
|
|
|
return tmsArBill;
|
}
|
|
|
@Override
|
public AjaxResult arGenerate(Integer[] ids) {
|
|
TmsArBill tmsArBill = initArGenerate(ids);
|
|
tmsArBill.setSystemNo(systemDataNoService.getNoByKey(SystemDataNoEnum.ZD));
|
tmsArBill.setSettledAmount(BigDecimal.ZERO);
|
tmsArBill.setInvoiceStatus(0);
|
tmsArBill.setStatus(0);
|
tmsArBill.setPushStatus(0); // 初始推送状态:未推送
|
tmsArBill.setCreateBy(SecurityUtils.getUsername());
|
tmsArBillMapper.insertTmsArBill(tmsArBill);
|
|
tmsReceivableFeeMapper.update(new LambdaUpdateWrapper<TmsReceivableFee>()
|
.set(TmsReceivableFee::getStatus,1)
|
.set( TmsReceivableFee::getBillRelationId,tmsArBill.getId())
|
.set(TmsReceivableFee::getBillRelationNo ,tmsArBill.getSystemNo())
|
.in(TmsReceivableFee::getId, ids)
|
);
|
|
List<TmsReceivableFee> tmsReceivableFees = tmsArBill.getTmsReceivableFees();
|
List<TmsArBillItem> rmb = tmsReceivableFees.stream().map(item -> {
|
TmsArBillItem billItem = new TmsArBillItem();
|
billItem.setBillId(tmsArBill.getId());
|
billItem.setProjectName(item.getProjectName());
|
billItem.setDispatchNo(item.getDispatchNo());
|
billItem.setOrderTime(item.getCreateTime());
|
billItem.setEstimateAmount(item.
|
getReceivableRmbSumAmount());
|
billItem.setCurrency("RMB");
|
billItem.setArFeeId(item.getId());
|
billItem.setStatus(0);
|
|
return billItem;
|
}).collect(Collectors.toList());
|
tmsArBillItemMapper.insertTmsArBillItemBatch(rmb);
|
|
// 向外部系统推送数据
|
AsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();
|
executor.execute(() -> pushToExternalSystem(tmsArBill, tmsReceivableFees));
|
|
return AjaxResult.success();
|
}
|
|
/**
|
* 向外部系统推送数据
|
* @param tmsArBill 应收账单
|
* @param tmsReceivableFees 应收费用列表
|
*/
|
@Async
|
protected void pushToExternalSystem(TmsArBill tmsArBill, List<TmsReceivableFee> tmsReceivableFees) {
|
java.util.Map<String, Object> requestBody = new java.util.HashMap<>();
|
try {
|
// 构建请求体
|
String apiUrl = url+"/addBill";
|
|
// 构建bill部分
|
java.util.Map<String, Object> billMap = new java.util.HashMap<>();
|
billMap.put("billName", tmsArBill.getBillName());
|
billMap.put("customerName", tmsArBill.getCustomerName());
|
billMap.put("payee", "");
|
billMap.put("responsiblePerson", "");
|
billMap.put("responsibleLeader", "");
|
billMap.put("settlementMethod", "");
|
billMap.put("businessType", "");
|
billMap.put("promotionRequirement", "");
|
billMap.put("isInternalSettlement", "0");
|
billMap.put("internalSettlementUnit", "");
|
billMap.put("documentCount", tmsReceivableFees.size());
|
billMap.put("totalAmount", tmsArBill.getSettleAmount());
|
billMap.put("currency", "RMB");
|
billMap.put("discountAmount", 0.00);
|
billMap.put("receivedAmount", 0.00);
|
billMap.put("pendingAmount", tmsArBill.getSettleAmount());
|
billMap.put("exchangeRate", tmsArBill.getSettleRate());
|
billMap.put("cnyAmount", tmsArBill.getSettleAmount());
|
billMap.put("periodType", "");
|
billMap.put("businessStartDate", "");
|
billMap.put("businessEndDate", "");
|
billMap.put("billingStartDate", "");
|
billMap.put("billingEndDate", "");
|
billMap.put("billGenerateDate", "");
|
billMap.put("billSendDate", "");
|
billMap.put("billDueDate", "");
|
billMap.put("settlementCategory", "");
|
billMap.put("settlementPeriod", "");
|
billMap.put("status", "0");
|
billMap.put("remark", "");
|
|
// 构建fees部分
|
List<java.util.Map<String, Object>> feesList = new java.util.ArrayList<>();
|
for (int i = 0; i < tmsReceivableFees.size(); i++) {
|
TmsReceivableFee fee = tmsReceivableFees.get(i);
|
java.util.Map<String, Object> feeMap = new java.util.HashMap<>();
|
feeMap.put("serialNumber", String.format("%03d", i + 1));
|
feeMap.put("relatedBillNo", "");
|
feeMap.put("sourceSystem", "TMS");
|
feeMap.put("businessSector", "0");
|
feeMap.put("documentType", "0");
|
feeMap.put("documentNo", fee.getDispatchNo() != null ? fee.getDispatchNo() : "");
|
feeMap.put("isInternalSettlement", "0");
|
feeMap.put("internalSettlementUnit", "");
|
feeMap.put("customerName", tmsArBill.getCustomerName());
|
feeMap.put("projectName", fee.getProjectName() != null ? fee.getProjectName() : "");
|
feeMap.put("businessTime", fee.getDispatchConfirmTime());
|
feeMap.put("receivableConfirmTime", fee.getDispatchConfirmTime());
|
feeMap.put("receivableAmount", fee.getReceivableRMBAmount().add(fee.getReceivableHKBAmount()));
|
// 构建receivableAmountStr
|
BigDecimal rmbAmount = fee.getReceivableRMBAmount();
|
BigDecimal hkbAmount = fee.getReceivableHKBAmount();
|
StringBuilder amountStr = new StringBuilder();
|
if (rmbAmount.compareTo(BigDecimal.ZERO) > 0) {
|
amountStr.append(rmbAmount).append("人民币");
|
}
|
if (hkbAmount.compareTo(BigDecimal.ZERO) > 0) {
|
if (amountStr.length() > 0) {
|
amountStr.append(" ");
|
}
|
amountStr.append(hkbAmount).append("港币");
|
}
|
feeMap.put("receivableAmountStr", amountStr.toString());
|
feeMap.put("status", "1");
|
feeMap.put("remark", "");
|
|
// 构建feeDetails部分
|
List<java.util.Map<String, Object>> feeDetailsList = new java.util.ArrayList<>();
|
List<TmsReceivableFeeItem> items = fee.getItems();
|
for (int j = 0; j < items.size(); j++) {
|
TmsReceivableFeeItem item = items.get(j);
|
java.util.Map<String, Object> feeDetailMap = new java.util.HashMap<>();
|
feeDetailMap.put("serialNumber", String.format("%03d", j + 1));
|
feeDetailMap.put("feeType", item.getFeeType());
|
feeDetailMap.put("feeName", item.getFeeName());
|
feeDetailMap.put("billingUnit", "次");
|
feeDetailMap.put("unitPrice", item.getRegisterAmount());
|
feeDetailMap.put("billingQuantity", item.getRegisterAmount());
|
feeDetailMap.put("billingAmount", item.getRegisterAmount());
|
feeDetailMap.put("actualAmount", item.getRegisterAmount());
|
feeDetailMap.put("currency", item.getCurrency());
|
feeDetailMap.put("feeRegTime", item.getRegisterTime());
|
feeDetailMap.put("remark", "");
|
feeDetailsList.add(feeDetailMap);
|
}
|
|
|
feeMap.put("feeDetails", feeDetailsList);
|
feesList.add(feeMap);
|
}
|
|
// 构建完整请求体
|
requestBody.put("bill", billMap);
|
requestBody.put("fees", feesList);
|
|
// 设置HTTP头
|
HttpHeaders headers = new HttpHeaders();
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
HttpEntity<String> entity = new HttpEntity<>(JSON.toJSONString(requestBody), headers);
|
|
// 发送API请求
|
ResponseEntity<String> response = restTemplate.exchange(apiUrl, HttpMethod.POST, entity, String.class);
|
logger.info("推送数据到外部系统成功,响应: {}", response.getBody());
|
|
// 解析响应,获取sourceSystemId
|
try {
|
JSONObject result = JSONObject.parseObject(response.getBody());
|
String sourceSystemId = result.getString("sourceSystemId");
|
if (sourceSystemId != null) {
|
tmsArBill.setSourceSystemId(Integer.parseInt(sourceSystemId));
|
}
|
} catch (Exception e) {
|
logger.error("解析外部系统响应失败: {}", e.getMessage());
|
}
|
|
|
// 更新推送状态为成功
|
tmsArBill.setPushStatus(2);
|
tmsArBill.setPushTime(DateUtils.getNowDate());
|
tmsArBillMapper.updateTmsArBill(tmsArBill);
|
} catch (Exception e) {
|
logger.error("推送数据到外部系统失败,账单ID: {}, 客户: {}",
|
tmsArBill.getId(), tmsArBill.getCustomerName(), e);
|
logger.debug("推送失败的请求数据: {}", JSON.toJSONString(requestBody));
|
|
// 更新推送状态为失败
|
tmsArBill.setPushStatus(3);
|
tmsArBill.setPushTime(DateUtils.getNowDate());
|
tmsArBillMapper.updateTmsArBill(tmsArBill);
|
}
|
}
|
|
/**
|
* 删除应收费用信息
|
*
|
* @param id 应收费用ID
|
* @return 结果
|
*/
|
@Override
|
public int deleteTmsReceivableFeeById(Integer id)
|
{
|
return tmsReceivableFeeMapper.deleteTmsReceivableFeeById(id);
|
}
|
}
|