package com.by4cloud.platformx.business.controller; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.by4cloud.platformx.admin.api.entity.SysDept; import com.by4cloud.platformx.admin.api.feign.RemoteDeptService; import com.by4cloud.platformx.business.entity.*; import com.by4cloud.platformx.business.entity.invoice.vo.InvoicingVo; import com.by4cloud.platformx.business.invoice.service.BIPYsService; import com.by4cloud.platformx.business.entity.invoice.vo.BipResVo; import com.by4cloud.platformx.business.invoice.service.FpInvoiceResultService; import com.by4cloud.platformx.business.service.*; import com.by4cloud.platformx.business.vo.ContractOutBoundVo; import com.by4cloud.platformx.business.vo.InvoicePreviewVo; import com.by4cloud.platformx.common.core.util.R; import com.by4cloud.platformx.common.data.mybatis.BaseModel; import com.by4cloud.platformx.common.log.annotation.SysLog; import com.by4cloud.platformx.common.security.annotation.Inner; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.persistence.Column; import org.springframework.security.access.prepost.PreAuthorize; import com.by4cloud.platformx.common.excel.annotation.ResponseExcel; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import org.springdoc.core.annotations.ParameterObject; import org.springframework.http.HttpHeaders; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; import java.util.stream.Collectors; /** * 开票信息 * * @author wjli * @date 2026-06-04 10:50:20 */ @RestController @RequiredArgsConstructor @RequestMapping("/billingInfo" ) @Tag(description = "billingInfo" , name = "开票信息管理" ) @SecurityRequirement(name = HttpHeaders.AUTHORIZATION) public class BillingInfoController { private final BillingInfoService billingInfoService; private final BillingItemService billingItemService; private final ContractService contractService; private final ContractOutBoundService contractOutBoundService; private final InvoiceService invoiceService; private final BIPYsService bipYsService; /** * 通过id查询开票信息 * @param id id * @return R */ @Operation(summary = "通过id查询" , description = "通过id查询" ) @GetMapping("/getById/{id}" ) public R getById(@PathVariable("id" ) Long id) { return R.ok(billingInfoService.getById(id)); } /** * 拼接发票信息 * @param previewVo 合同ID和出库单ID * @return R */ @Operation(summary = "拼接发票信息" , description = "拼接发票信息" ) @SysLog("拼接发票信息" ) @GetMapping("/saveInvoice") @Inner(value = false) public R saveInvoice(@ParameterObject InvoicePreviewVo previewVo) { //参数判断 if(previewVo.getContractId() == null){ return R.failed("合同id不能为空"); } Contract contractTemp = contractService.getById(previewVo.getContractId()); if(contractTemp == null){ return R.failed("合同id错误"); } BillingInfo billingInfo = billingInfoService.getInviceByContractId(previewVo,contractTemp,1); //拼装开票项内容 List contractOutBoundVos = billingInfo.getContractOutBoundList(); if(contractOutBoundVos!=null && !contractOutBoundVos.isEmpty()) { for(ContractOutBoundVo vo : contractOutBoundVos){ BillingItem item = new BillingItem(); //开票信息id item.setBillingInfoId(billingInfo.getId()); //关联合同ID item.setContractId(billingInfo.getContractId()); //开票产品名称 item.setInvoiceName(vo.getInvoiceName()); //客商ID item.setBusGuestId(vo.getBusGuestId()); //产品id item.setProductId(vo.getProductId()); //标的物规格/型号 item.setSpecification(vo.getSpecification()); //开票产品数量 item.setProductNum(vo.getOutBoundNum()); //标的物编码 item.setSubjectMatterCode(vo.getSubjectMatterCode()); //标的物名称 item.setSubjectMatterName(vo.getSubjectMatterName()); //计量单位(个/台/吨/项/套等) item.setUnit(vo.getUnit()); //开票状态(0-未开票 1-开票中 2-已开票) item.setBillingStatus(1); //总单价 item.setTotalPrice(vo.getTotalPrice()); //单价 item.setUnitPrice(vo.getUnitPrice()); //税收分类 item.setTaxClass(vo.getTaxClass()); //税收编码 item.setTaxCode(vo.getTaxCode()); //总税额 item.setTotalTax(vo.getTotalTax()); //税率(百分比,如13表示13%) item.setTaxRate(vo.getTaxRate()); //不含税总额 item.setTotalPriceNoTax(vo.getTotalPriceNoTax()); //所关联出库单ID item.setContractOutBoundIds(vo.getContractOutBoundIds()); billingItemService.save(item); } } //生成vo /*InvoicingVo invoicingVo = invoiceService.toGetByCompareByVo1(billingInfo,contractOutBoundVos); try { Map objectMap = invoiceService.toKaipiao(invoicingVo); Boolean success = (Boolean) objectMap.get("success"); String message = (String) objectMap.get("message"); //System.out.println(saleCredit.getEntrustCode() + "的railwayEntrust蓝字开票结果为:" + success + "------" + message); if(success){ billingInfo.setBlueResultStatus(1); billingInfoService.updateById(billingInfo); //推bi'p BipResVo bipResVo = bipYsService.sendBIPYss(billingInfo); if (!bipResVo.getCode().equals("200")) { *//*if (StrUtil.isNotEmpty(errMsg)) { errMsg.append(","); } errMsg.append(saleCredit.getCreditCodeB()+ "应收发票推送失败:" + bipResVo.getMessage());*//* billingInfo.setBipStatus(1); billingInfoService.updateById(billingInfo); return R.failed("开票成功,推送bip失败,err:" + bipResVo.getMessage()); }else{ billingInfo.setBipStatus(200); billingInfoService.updateById(billingInfo); return R.ok("开票成功,推送big成功!"); } }else{ billingInfo.setBlueResultStatus(2); billingInfoService.updateById(billingInfo); return R.failed("开票失败!err:" + message); } }catch (Exception e){ billingInfo.setStatus(3); billingInfoService.updateById(billingInfo); return R.failed("开票失败!err:" + e.getMessage()); }*/ //出库单已开票 List contractOutBounds = contractOutBoundService.list(new LambdaQueryWrapper() .eq(ContractOutBound::getSaleCreditId,billingInfo.getId()) ); for(ContractOutBound contractOutBound : contractOutBounds){ contractOutBound.setInvoiceSatus(2); } contractOutBoundService.updateBatchById(contractOutBounds); //开票成功 //开票记录单蓝票信息存储 billingInfo.setBlueResultStatus(1); billingInfo.setInvoiceRemark("开票成功!"); billingInfo.setBlueInvoiceTime(DateTime.now()); billingInfoService.updateById(billingInfo); //相关合同金额和开票状态进行修改。 Contract contract = contractService.getById(billingInfo.getContractId()); String billingStatus = contract.getBillingStatus(); if(contract.getBillingAmout()==null){ contract.setBillingAmout(billingInfo.getTotalAmount()); }else{ contract.setBillingAmout(contract.getBillingAmout().add(billingInfo.getTotalAmount())); } int res = contract.getAmount().compareTo(contract.getBillingAmout()); if("2".equals(billingStatus)) { if (res == 0) { contract.setBillingStatus("3"); } else if (res > 0) { contract.setBillingStatus("2"); } else { return R.failed("已付金额不能大于总金额!"); } } contractService.updateById(contract); return R.ok("开票成功,推送bip成功!"); } /** * 拼接销售挂账 * @param billingInfo1 开票信息 * @return R */ @Operation(summary = "开发票" , description = "开发票" ) @SysLog("开发票" ) @PostMapping("/toRedStamp") @PreAuthorize("@pms.hasPermission('business_saleCredit_edit')" ) public R toRedStamp(@RequestBody BillingInfo billingInfo1) { if(billingInfo1.getId()==null){ return R.failed("开票信息id不能为空!"); } BillingInfo billingInfo = billingInfoService.getById(billingInfo1.getId()); if(billingInfo==null){ return R.failed("开票信息id不能错误!"); } /* try { Map map = invoiceService.toRedTicket1(billingInfo); Boolean success = (Boolean) map.get("success"); if(success){ return R.ok("红字开票成功"); }else { return R.failed((String) map.get("message")); } }catch (Exception e){ e.printStackTrace(); return R.failed("红字开票失败"); }*/ //出库单恢复到未开票状态 List outBoundList = contractOutBoundService.list(new LambdaQueryWrapper() .eq(ContractOutBound::getSaleCreditId,billingInfo.getId()) ); for(ContractOutBound outBound : outBoundList){ outBound.setInvoiceSatus(0); outBound.setSaleCreditId(0l); } contractOutBoundService.updateBatchById(outBoundList); billingInfo.setRedInvoiceTime(DateTime.now()); billingInfo.setRedResultStatus(1); billingInfo.setInvoiceRemark("开红票成功!"); billingInfoService.updateById(billingInfo); //合同已开票金额和状态还原 Contract contract = contractService.getById(billingInfo.getContractId()); String billingStatus = contract.getBillingStatus(); BigDecimal bill = contract.getBillingAmout() == null ? BigDecimal.ZERO : contract.getBillingAmout(); BigDecimal credit = billingInfo.getTotalAmount() == null ? BigDecimal.ZERO : billingInfo.getTotalAmount(); BigDecimal diff = bill.subtract(credit); int res = diff.compareTo(BigDecimal.ZERO); if("3".equals(billingStatus)){ if(res>=0){ contract.setBillingStatus("2"); contract.setBillingAmout(BigDecimal.ZERO); }else{ return R.failed("已开票金额负数报错!"); } } contractService.updateById(contract); return R.ok("红冲开票成功!"); } /** * 拼接发票信息 * @param previewVo 合同ID和出库单ID * @return R */ @Operation(summary = "拼接发票信息" , description = "拼接发票信息" ) @SysLog("拼接发票信息" ) @GetMapping("/generatorInvoice") @Inner(value = false) public R generatorInvoice(@ParameterObject InvoicePreviewVo previewVo) { //参数判断 if(previewVo.getContractId() == null){ return R.failed("合同id不能为空"); } Contract contract = contractService.getById(previewVo.getContractId()); if(contract == null){ return R.failed("合同id错误"); } BillingInfo billingInfo = billingInfoService.getInviceByContractId(previewVo,contract,0); return R.ok(billingInfo); } }