|
@@ -1,32 +1,47 @@
|
|
|
package com.pj.api.invoice.service;
|
|
|
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
+import cn.hutool.core.codec.Base64;
|
|
|
import cn.hutool.core.date.DateUtil;
|
|
|
+import cn.hutool.core.lang.Snowflake;
|
|
|
+import cn.hutool.core.util.IdUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
import cn.hutool.http.HttpUtil;
|
|
|
+import cn.hutool.json.JSON;
|
|
|
+import cn.hutool.json.JSONArray;
|
|
|
+import cn.hutool.json.JSONObject;
|
|
|
import cn.hutool.json.JSONUtil;
|
|
|
-import com.alibaba.fastjson.JSONObject;
|
|
|
import com.pj.api.invoice.bo.InvoiceApply;
|
|
|
+import com.pj.api.invoice.bo.InvoiceApplyCallBackSub;
|
|
|
import com.pj.api.invoice.bo.InvoiceApplySub;
|
|
|
import com.pj.api.invoice.bo.InvoiceApplySubDetail;
|
|
|
import com.pj.api.invoice.utils.InvoiceUtils;
|
|
|
import com.pj.api.wx.bo.Attach;
|
|
|
import com.pj.api.wx.bo.PriceBO;
|
|
|
+import com.pj.current.config.InvoiceConfig;
|
|
|
import com.pj.project.tb_fee_details.TbFeeDetails;
|
|
|
import com.pj.project.tb_fee_details.TbFeeDetailsService;
|
|
|
+import com.pj.project.tb_fee_statistics.TbFeeStatistics;
|
|
|
import com.pj.project.tb_invoice_details.TbInvoiceDetails;
|
|
|
import com.pj.project.tb_invoice_details.TbInvoiceDetailsService;
|
|
|
import com.pj.project.tb_invoice_info.TbInvoiceInfo;
|
|
|
import com.pj.project.tb_invoice_info.TbInvoiceInfoService;
|
|
|
+import com.pj.project.tb_invoice_info.dto.FeeDeatilsGroup;
|
|
|
import com.pj.project.tb_invoice_order.TbInvoiceOrder;
|
|
|
import com.pj.project.tb_invoice_order.TbInvoiceOrderService;
|
|
|
import com.pj.project.tb_order.TbOrder;
|
|
|
import com.pj.project.tb_order.TbOrderService;
|
|
|
+import com.pj.project4sp.global.BusinessException;
|
|
|
+import com.pj.utils.so.SoMap;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.scheduling.annotation.Async;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
import java.math.BigDecimal;
|
|
|
import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
/**
|
|
@@ -42,92 +57,213 @@ import java.util.*;
|
|
|
public class InvoiceApplyService {
|
|
|
|
|
|
@Resource
|
|
|
+ TbInvoiceDetailsService tbInvoiceDetailsService;
|
|
|
+ @Resource
|
|
|
TbInvoiceInfoService tbInvoiceInfoService;
|
|
|
@Resource
|
|
|
TbInvoiceOrderService tbInvoiceOrderService;
|
|
|
@Resource
|
|
|
TbFeeDetailsService tbFeeDetailsService;
|
|
|
@Resource
|
|
|
- TbOrderService tbOrderService;
|
|
|
+ InvoiceConfig invoiceConfig;
|
|
|
+
|
|
|
+
|
|
|
+ private static final String appid = "5644763";
|
|
|
+ private static final String appsecret = "F382196D16B98BC6F4A461Ced7505953";
|
|
|
+ private static final String applyUrl = "http://117.141.148.233:8765/monolithic/uni/invoice/invoiceBillPush";
|
|
|
+ private static final String applyAction = "billPus";
|
|
|
+ private static final String businessTaxRateCode = "3040408000000000000";
|
|
|
+ private static final String carTaxRateCode = "3040502020200000000";
|
|
|
+ private static final String sellerTaxpayerId = "915003006188392540";
|
|
|
+ private static final String sellerName = "金蝶软件(中国)有限公司";
|
|
|
|
|
|
- public static final String appid = "5644763 ";
|
|
|
- public static final String appsecret = "F382196D16B98BC6F4A461Ced7505953";
|
|
|
- public static final String applyUrl = "http://117.141.148.233:8765/monolithic/uni/invoice/invoiceBillPush";
|
|
|
- public static final String applyAction = "billPus";
|
|
|
- public static final String businessTaxRateCode = "3040408000000000000";
|
|
|
- public static final String carTaxRateCode = "3040502020200000000";
|
|
|
+ public void applyInvoice(String infoId, String drawer){
|
|
|
+ String code = this.preApply(infoId, drawer);
|
|
|
+ if(!StrUtil.equals("SUCCESS", code)) {
|
|
|
+ throw new BusinessException("开票申请推送失败!");
|
|
|
+ }
|
|
|
+// TbInvoiceInfo info = tbInvoiceInfoService.getById(infoId);
|
|
|
+// if(info.getIsApply() == 0){
|
|
|
+// info.setIsApply(1);
|
|
|
+// tbInvoiceInfoService.updateById(info);
|
|
|
+// }
|
|
|
+// List<TbInvoiceDetails> invoiceDetails = tbInvoiceDetailsService.findByInfoId(infoId);
|
|
|
+// for (TbInvoiceDetails invoiceDetail : invoiceDetails) {
|
|
|
+// if(invoiceDetail.getIsApply() == 0){
|
|
|
+// invoiceDetail.setIsApply(1);
|
|
|
+// }
|
|
|
+// }
|
|
|
+// tbInvoiceDetailsService.updateBatchById(invoiceDetails);
|
|
|
+ }
|
|
|
|
|
|
- public void preApply(TbInvoiceDetails invoiceDetail) throws Exception{
|
|
|
+
|
|
|
+ public String preApply(String infoId, String drawer){
|
|
|
Date now = new Date();
|
|
|
Map<String, String> param = new HashMap<>();
|
|
|
- param.put("action",applyAction);
|
|
|
- param.put("appid", appid);
|
|
|
+ param.put("action",invoiceConfig.getApplyAction());
|
|
|
+ param.put("appid", invoiceConfig.getAppId());
|
|
|
param.put("timestamp", InvoiceUtils.date2StrByInt(now, "yyyyMMddHHmmssFFF"));
|
|
|
param.put("transid", InvoiceUtils.genTransId());
|
|
|
- String sign = InvoiceUtils.createSign(InvoiceUtils.getSortedMap(param), appsecret);
|
|
|
+ String sign = InvoiceUtils.createSign(InvoiceUtils.getSortedMap(param), invoiceConfig.getAppSecret());
|
|
|
param.put("sign", sign);
|
|
|
//拼装请求url
|
|
|
- String url = InvoiceUtils.getUrl(applyUrl, param);
|
|
|
+ String url = InvoiceUtils.getUrl(invoiceConfig.getApplyUrl(), param);
|
|
|
+
|
|
|
+ TbInvoiceInfo info = tbInvoiceInfoService.getById(infoId);
|
|
|
+ List<TbInvoiceDetails> invoiceDetails = tbInvoiceDetailsService.findByInfoId(infoId);
|
|
|
|
|
|
- TbInvoiceInfo info = tbInvoiceInfoService.getById(invoiceDetail.getInfoId());
|
|
|
- List<TbInvoiceOrder> orders = tbInvoiceOrderService.findByDetailId(invoiceDetail.getId());
|
|
|
|
|
|
//开始组装接口参数
|
|
|
InvoiceApply invoiceApply = new InvoiceApply();
|
|
|
invoiceApply.setRequestId(now.getTime()+"")
|
|
|
- .setBusinessSystemCode("ali_test")
|
|
|
+ .setBusinessSystemCode("SW_TEST")
|
|
|
.setInterfaceCode("BILL.PUSH");
|
|
|
List<InvoiceApplySub> applys = new ArrayList<>();
|
|
|
- for (TbInvoiceOrder order : orders) {
|
|
|
+ for (TbInvoiceDetails invoiceDetail : invoiceDetails) {
|
|
|
InvoiceApplySub apply = new InvoiceApplySub();
|
|
|
- apply.setBillNo(order.getId()).setPayType("微信支付").setTransactionId(order.getTransactionId())
|
|
|
+ apply.setBillNo(invoiceDetail.getId()).setPayType("微信支付")
|
|
|
.setBillDate(DateUtil.format(now, "yyyy-MM-dd"))
|
|
|
- .setTotalAmount(order.getBillMoney())
|
|
|
+ .setTotalAmount(invoiceDetail.getMoney()).setIncludeTaxFlag(1)
|
|
|
.setAutoInvoice(1).setAutoMerge(1)
|
|
|
.setInvoiceType("007")
|
|
|
.setBuyerName(info.getEntityName()).setBuyerTaxpayerId(info.getTaxIdNo())
|
|
|
.setBuyerRecipientMail(info.getEmail())
|
|
|
.setBuyerProperty(0)
|
|
|
- .setSellerTaxpayerId("91450103MA5NA8UF74")
|
|
|
- .setIncludeTaxFlag(1)
|
|
|
+ .setBuyerBankAndAccount(info.getBank()+info.getBankNo())
|
|
|
+ .setTextField1(info.getCustomerName())
|
|
|
+ .setSellerName(invoiceConfig.getSellerName())
|
|
|
+ .setSellerTaxpayerId(invoiceConfig.getSellerTaxpayerId())
|
|
|
+
|
|
|
.setTaxationStyle(0)
|
|
|
- .setDrawer("开票人");
|
|
|
+ .setDrawer(drawer);
|
|
|
+
|
|
|
+ //将所有开票订单的收费明细放在一个集合中,并对其分组
|
|
|
+ List<TbInvoiceOrder> orders = tbInvoiceOrderService.findByDetailId(invoiceDetail.getId());
|
|
|
+ List<FeeDeatilsGroup> feeDetailsGroupList = grouping(orders);
|
|
|
+
|
|
|
List<InvoiceApplySubDetail> applyDetails = new ArrayList<>();
|
|
|
- List<TbFeeDetails> feeDetails = tbFeeDetailsService.findBusinessFeeByTransactionId(order.getTransactionId());
|
|
|
- for (TbFeeDetails feeDetail : feeDetails) {
|
|
|
+ Snowflake snowflake = IdUtil.getSnowflake(1, 1);
|
|
|
+ for (FeeDeatilsGroup group : feeDetailsGroupList) {
|
|
|
+ String detailId = snowflake.nextIdStr();
|
|
|
InvoiceApplySubDetail applyDetail = new InvoiceApplySubDetail();
|
|
|
- applyDetail.setAmount(feeDetail.getItemPrice())
|
|
|
- .setDetailId(feeDetail.getId())
|
|
|
- .setGoodsName(feeDetail.getItemTypeName())
|
|
|
- .setLineProperty(2)
|
|
|
- .setPrice(feeDetail.getUnitPrice())
|
|
|
- .setTaxRate(feeDetail.getTaxRate().toString())
|
|
|
- .setRevenueCode(businessTaxRateCode);
|
|
|
- applyDetails.add(applyDetail);
|
|
|
- }
|
|
|
- TbOrder tbOrder = tbOrderService.findByTransactionId(order.getTransactionId());
|
|
|
- String attachStr = tbOrder.getAttach();
|
|
|
- Attach attach = JSONUtil.toBean(attachStr, Attach.class);
|
|
|
- List<PriceBO> cars = JSONUtil.toList(attach.getC(), PriceBO.class);
|
|
|
- BigDecimal carAmount = new BigDecimal(0);
|
|
|
- if(cars.size()>0){
|
|
|
- for (PriceBO car : cars) {
|
|
|
- carAmount = carAmount.add(car.getP());
|
|
|
+ applyDetail.setAmount(group.getItemPrice())
|
|
|
+ .setDetailId(detailId)
|
|
|
+ .setGoodsName(group.getItemTypeName())
|
|
|
+ .setLineProperty(2)
|
|
|
+ .setQuantity(group.getNum())
|
|
|
+ .setPrice(group.getUnitPrice())
|
|
|
+ .setTaxRate(group.getTaxRate().toString());
|
|
|
+ if(StrUtil.equals("0.09", applyDetail.getTaxRate())){
|
|
|
+ applyDetail.setRevenueCode(invoiceConfig.getCarTaxRateCode());
|
|
|
+ }else{
|
|
|
+ applyDetail.setRevenueCode(invoiceConfig.getBusinessTaxRateCode());
|
|
|
}
|
|
|
+ applyDetails.add(applyDetail);
|
|
|
}
|
|
|
- InvoiceApplySubDetail carApplyDetail = new InvoiceApplySubDetail();
|
|
|
- carApplyDetail.setAmount(carAmount).setGoodsName("停车费")
|
|
|
- .setTaxRate("0.09").setLineProperty(2).setRevenueCode(carTaxRateCode);
|
|
|
- applyDetails.add(carApplyDetail);
|
|
|
apply.setBillDetail(applyDetails);
|
|
|
applys.add(apply);
|
|
|
}
|
|
|
- invoiceApply.setData(applys);
|
|
|
+
|
|
|
+ log.info("invoice apply url:" + url);
|
|
|
+
|
|
|
+ String applysJson = JSONUtil.toJsonStr(applys);
|
|
|
+ log.info("invoice apply data:" + applysJson);
|
|
|
+
|
|
|
+ String applysBase64 = Base64.encode(applysJson);
|
|
|
+ invoiceApply.setData(applysBase64);
|
|
|
+
|
|
|
String paramStr = JSONUtil.toJsonStr(invoiceApply);
|
|
|
log.info("invoice apply paramStr:" + paramStr);
|
|
|
-// JSONObject result = InvoiceUtils.httppost(url, JSONObject.parseObject(paramStr));
|
|
|
+
|
|
|
String result = HttpUtil.createPost(url).header("Content-Type", "application/json").body(paramStr).execute().body();
|
|
|
log.info("invoice apply result:" + result);
|
|
|
+ JSONObject jsonResult = JSONUtil.parseObj(result);
|
|
|
+ if( StrUtil.equals("0", jsonResult.getStr("code"))){
|
|
|
+ return "SUCCESS";
|
|
|
+ }else {
|
|
|
+ return "FAIl";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private List<FeeDeatilsGroup> grouping(List<TbInvoiceOrder> invoiceOrderList){
|
|
|
+ List<TbFeeDetails> feeDetailsList = new ArrayList<>();
|
|
|
+ for (TbInvoiceOrder invoiceOrder : invoiceOrderList) {
|
|
|
+ List<TbFeeDetails> detailsList = tbFeeDetailsService.findByTransactionId(invoiceOrder.getTransactionId());
|
|
|
+ feeDetailsList.addAll(detailsList);
|
|
|
+ }
|
|
|
+ List<FeeDeatilsGroup> list = new ArrayList<>();
|
|
|
+ for (TbFeeDetails detail : feeDetailsList) {
|
|
|
+ FeeDeatilsGroup group = new FeeDeatilsGroup();
|
|
|
+ BeanUtil.copyProperties(detail, group);
|
|
|
+ String hash = (detail.getItemTypeName() + detail.getUnitPrice()).hashCode() + "";
|
|
|
+ group.setGroupHash(hash);
|
|
|
+ list.add(group);
|
|
|
+ }
|
|
|
+ Map<String, List<FeeDeatilsGroup>> collect = list.stream()
|
|
|
+ .collect(Collectors.groupingBy(FeeDeatilsGroup::getGroupHash));
|
|
|
+ List<FeeDeatilsGroup> completeGroups = new ArrayList<>();
|
|
|
+ for (String key : collect.keySet()) {
|
|
|
+ List<FeeDeatilsGroup> partGroups = collect.get(key);
|
|
|
+ FeeDeatilsGroup realGroup = new FeeDeatilsGroup();
|
|
|
+ realGroup.setItemTypeName(partGroups.get(0).getItemTypeName())
|
|
|
+ .setUnitPrice(partGroups.get(0).getUnitPrice())
|
|
|
+ .setTaxRate(partGroups.get(0).getTaxRate());
|
|
|
+ for (FeeDeatilsGroup partGroup : partGroups) {
|
|
|
+ realGroup.setItemPrice(realGroup.getItemPrice().add(partGroup.getItemPrice()))
|
|
|
+ .setNoTaxPrice(realGroup.getNoTaxPrice().add(partGroup.getNoTaxPrice()))
|
|
|
+ .setTaxPrice(realGroup.getTaxPrice().add(partGroup.getTaxPrice()))
|
|
|
+ .setNum(realGroup.getNum() + partGroup.getNum());
|
|
|
+ }
|
|
|
+ completeGroups.add(realGroup);
|
|
|
+ }
|
|
|
+ return completeGroups;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public synchronized Map<String, Object> callBack(String sub) {
|
|
|
+ log.info("进入开票回调:");
|
|
|
+ Map<String, Object> map = new LinkedHashMap<>();
|
|
|
+
|
|
|
+ JSONObject jsonObject = JSONUtil.parseObj(sub);
|
|
|
+ InvoiceApplyCallBackSub callBackSub = JSONUtil.toBean(jsonObject, InvoiceApplyCallBackSub.class);
|
|
|
+
|
|
|
+ TbInvoiceDetails invoiceDetail = tbInvoiceDetailsService.getById(callBackSub.getBillNo());
|
|
|
+ if(invoiceDetail == null){
|
|
|
+ log.info("开票信息子记录{}不存在:", callBackSub.getBillNo());
|
|
|
+ map.put("code", 500);
|
|
|
+ map.put("message", "失败,开票信息数据异常");
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+ if(invoiceDetail.getIsApply() == 2){
|
|
|
+ log.info("重复回调,开票信息子记录{}已开票成功:", callBackSub.getBillNo());
|
|
|
+ }else{
|
|
|
+ invoiceDetail.setIsApply(2).setInvoiceNo(callBackSub.getInvoiceNum()).setInvoiceCode(callBackSub.getInvoiceCode())
|
|
|
+ .setFileUrl(callBackSub.getInvoiceFileUrl()).setImageUrl(callBackSub.getInvoiceImageUrl());
|
|
|
+ tbInvoiceDetailsService.updateById(invoiceDetail);
|
|
|
+ TbInvoiceInfo info = tbInvoiceInfoService.getById(invoiceDetail.getInfoId());
|
|
|
+// List<TbInvoiceDetails> infoAllDetails = tbInvoiceDetailsService.findByInfoId(info.getId());
|
|
|
+// String newInvoiceNo = "";
|
|
|
+// for (TbInvoiceDetails detail : infoAllDetails) {
|
|
|
+// newInvoiceNo = StrUtil.isEmpty(newInvoiceNo) ?
|
|
|
+// detail.getInvoiceNo() : newInvoiceNo+","+detail.getInvoiceNo();
|
|
|
+// }
|
|
|
+ info.setIsApply(2);
|
|
|
+ tbInvoiceInfoService.updateById(info);
|
|
|
+ String oldInvoiceNo = info.getInvoiceNo();
|
|
|
+ String newInvoiceNo = StrUtil.isEmpty(oldInvoiceNo) ?
|
|
|
+ callBackSub.getInvoiceNum() : oldInvoiceNo+","+callBackSub.getInvoiceNum();
|
|
|
+
|
|
|
+ SoMap so = new SoMap();
|
|
|
+ so.put("id", info.getId());
|
|
|
+ so.put("invoiceTime", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
|
|
|
+ so.put("invoiceNo", newInvoiceNo);
|
|
|
+ tbInvoiceInfoService.complete(so);
|
|
|
+
|
|
|
+ }
|
|
|
+ map.put("code", 200);
|
|
|
+ map.put("message", "成功");
|
|
|
+ return map;
|
|
|
}
|
|
|
|
|
|
}
|