package com.by4cloud.platformx.business.controller; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.util.ArrayUtil; 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.BipResVo; import com.by4cloud.platformx.business.entity.invoice.vo.InvoicingVo; import com.by4cloud.platformx.business.invoice.service.BIPYsService; import com.by4cloud.platformx.business.service.*; import com.by4cloud.platformx.business.vo.ContractOutBoundVo; import com.by4cloud.platformx.common.core.util.R; import com.by4cloud.platformx.common.data.mybatis.BaseModel; import com.by4cloud.platformx.common.excel.annotation.ResponseExcel; import com.by4cloud.platformx.common.log.annotation.SysLog; import com.by4cloud.platformx.common.security.annotation.Inner; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springdoc.core.annotations.ParameterObject; import org.springframework.http.HttpHeaders; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * 销售挂账 * * @author wjli * @date 2026-05-21 16:16:31 */ @RestController @RequiredArgsConstructor @RequestMapping("/saleCredit" ) @Tag(description = "saleCredit" , name = "销售挂账管理" ) @SecurityRequirement(name = HttpHeaders.AUTHORIZATION) public class SaleCreditController { private final SaleCreditService saleCreditService; private final ContractService contractService; private final BusinessCustomerService businessCustomerService; private final ContractOutBoundService contractOutBoundService; private final ProductService productService; private final ContractSubjectMatterService contractSubjectMatterService; private final RemoteDeptService remoteDeptService; private final InvoiceService invoiceService; private final BIPYsService bipYsService; /** * 分页查询 * @param page 分页对象 * @param saleCredit 销售挂账 * @return */ @Operation(summary = "分页查询" , description = "分页查询" ) @GetMapping("/page" ) @PreAuthorize("@pms.hasPermission('business_saleCredit_view')" ) public R getSaleCreditPage(@ParameterObject Page page, @ParameterObject SaleCredit saleCredit) { LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); return R.ok(saleCreditService.page(page, wrapper)); } /** * 通过id查询销售挂账 * @param id id * @return R */ @Operation(summary = "通过id查询" , description = "通过id查询" ) @GetMapping("/{id}" ) @PreAuthorize("@pms.hasPermission('business_saleCredit_view')" ) public R getById(@PathVariable("id" ) Long id) { return R.ok(saleCreditService.getById(id)); } /** * 新增销售挂账 * @param saleCredit 销售挂账 * @return R */ @Operation(summary = "新增销售挂账" , description = "新增销售挂账" ) @SysLog("新增销售挂账" ) @PostMapping @PreAuthorize("@pms.hasPermission('business_saleCredit_add')" ) public R save(@RequestBody SaleCredit saleCredit) { return R.ok(saleCreditService.save(saleCredit)); } /** * 新增销售挂账 * @param saleCredit 销售挂账 * @return R */ @Operation(summary = "销售挂账生成" , description = "销售挂账生成" ) @SysLog("销售挂账生成" ) @PostMapping("/saveSaleCredit") @PreAuthorize("@pms.hasPermission('business_saleCredit_add')" ) public R saveInvoice(@RequestBody SaleCredit saleCredit) { //开票中 saleCredit.setStatus(1); saleCreditService.save(saleCredit); //标记出库单被标识 List contractOutBoundList = saleCredit.getContractOutBoundList(); if(contractOutBoundList==null){ return R.failed("请选择出库单!"); } if(contractOutBoundList.size()==0){ return R.failed("请选择出库单!"); } //开票之前,先记录开票信息 //1.出库单进行标记,将出库单发票记录id填入。将InvoiceSatus=1开票中。 String outBoundIds = ""; for(ContractOutBoundVo vo : contractOutBoundList){ if(StrUtil.isEmpty(outBoundIds)){ outBoundIds = "" + vo.getId(); }else{ outBoundIds += "," + vo.getId(); } ContractOutBound outBound = contractOutBoundService.getById(vo.getId()); outBound.setSaleCreditId(saleCredit.getId()); outBound.setTotalPrice(vo.getTotalPrice()); outBound.setTotalTax(vo.getTotalTax()); outBound.setProductId(vo.getProductId()); outBound.setTaxRate(vo.getTaxRate()); outBound.setTaxClass(vo.getTaxClass()); outBound.setTaxCode(vo.getTaxCode()); outBound.setSpecification(vo.getSpecification()); outBound.setUnit(vo.getUnit()); outBound.setUnitPrice(vo.getUnitPrice()); outBound.setInvoiceSatus(1); contractOutBoundService.updateById(outBound); } //结算中记录出库单ids. saleCredit.setOutBoundIds(outBoundIds); //生成结算单号 saleCredit.setEntrustCode("JsNo"+System.currentTimeMillis()); saleCreditService.updateById(saleCredit); //生成vo /* InvoicingVo invoicingVo = invoiceService.toGetByCompareByVo(saleCredit,contractOutBoundList); 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){ saleCredit.setBlueResultStatus(1); saleCreditService.updateById(saleCredit); //StringBuffer errMsg = new StringBuffer(); BipResVo bipResVo = bipYsService.sendBIPYs(saleCredit); if (!bipResVo.getCode().equals("200")) { *//*if (StrUtil.isNotEmpty(errMsg)) { errMsg.append(","); } errMsg.append(saleCredit.getCreditCodeB()+ "应收发票推送失败:" + bipResVo.getMessage());*//* return R.failed("开票成功,推送bip失败,err:" + bipResVo.getMessage()); }else{ return R.ok("开票成功,推送big成功!"); } }else{ saleCredit.setStatus(2); saleCreditService.updateById(saleCredit); return R.failed("开票失败!原因:" + message); } }catch (Exception e){ saleCredit.setStatus(3); saleCreditService.updateById(saleCredit); return R.failed("开票失败!"); }*/ //return R.ok("销售挂账生成!"); //出库单已开票 List contractOutBounds = contractOutBoundService.list(new LambdaQueryWrapper() .eq(ContractOutBound::getSaleCreditId,saleCredit.getId()) ); for(ContractOutBound contractOutBound : contractOutBounds){ contractOutBound.setInvoiceSatus(2); } contractOutBoundService.updateBatchById(contractOutBounds); //开票成功 //开票记录单蓝票信息存储 saleCredit.setBlueResultStatus(1); saleCredit.setInvoiceRemark("开票成功!"); saleCredit.setBlueInvoiceTime(DateTime.now()); saleCreditService.updateById(saleCredit); //相关合同金额和开票状态进行修改。 Contract contract = contractService.getById(saleCredit.getContractId()); String billingStatus = contract.getBillingStatus(); if(contract.getBillingAmout()==null){ contract.setBillingAmout(saleCredit.getTotalAmount()); }else{ contract.setBillingAmout(contract.getBillingAmout().add(saleCredit.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 contract1 销售挂账 * @return R */ @Operation(summary = "获取发票列表" , description = "获取发票列表" ) @SysLog("获取发票列表" ) @GetMapping("/getInvoices") @PreAuthorize("@pms.hasPermission('business_saleCredit_view')" ) public R getInvoices(@ParameterObject Contract contract1) { Contract contract = contractService.getById(contract1.getId()); if(contract==null){ return R.failed("合同id错误"); } List saleCredits = saleCreditService.list(new LambdaQueryWrapper() .eq(SaleCredit::getContractId,contract1.getId()) .orderByAsc(BaseModel::getCreateTime) ); for(SaleCredit saleCredit : saleCredits){ if(saleCredit.getRedResultStatus()!=null && saleCredit.getRedResultStatus()>0){//说明已开红票 saleCredit.setBlueResultStatus(0); if(saleCredit.getRedResultStatus()==1){ saleCredit.setInvoiceRemark("开红票成功!"); saleCredit.setInvoicRedUrl("红票url"); }else{ //显示 saleCredit.getInvoiceRemark(); } }else{ if(saleCredit.getBlueResultStatus()==1){ saleCredit.setInvoiceRemark("开蓝票成功!"); saleCredit.setInvoicUrl("蓝票url"); }else if(saleCredit.getBlueResultStatus()==2){ //显示 saleCredit.getInvoiceRemark(); } } } return R.ok(saleCredits); } /** * 拼接销售挂账 * @param saleCredit1 销售挂账 * @return R */ @Operation(summary = "红冲发票" , description = "红冲发票" ) @SysLog("红冲发票" ) @PostMapping("/toRedStamp") @PreAuthorize("@pms.hasPermission('business_saleCredit_edit')" ) public R toRedStamp(@RequestBody SaleCredit saleCredit1) { if(saleCredit1.getId()==null){ return R.failed("销售挂账id不能为空!"); } SaleCredit saleCredit = saleCreditService.getById(saleCredit1.getId()); if(saleCredit==null){ return R.failed("销售挂账id不能为空!"); } /*try { Map map = invoiceService.toRedTicket(saleCredit); 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,saleCredit.getId()) ); for(ContractOutBound outBound : outBoundList){ outBound.setInvoiceSatus(0); outBound.setSaleCreditId(0l); } contractOutBoundService.updateBatchById(outBoundList); saleCredit.setRedInvoiceTime(DateTime.now()); saleCredit.setRedResultStatus(1); saleCredit.setInvoiceRemark("开红票成功!"); saleCreditService.updateById(saleCredit); //合同已开票金额和状态还原 Contract contract = contractService.getById(saleCredit.getContractId()); String billingStatus = contract.getBillingStatus(); BigDecimal bill = contract.getBillingAmout() == null ? BigDecimal.ZERO : contract.getBillingAmout(); BigDecimal credit = saleCredit.getTotalAmount() == null ? BigDecimal.ZERO : saleCredit.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 saleCredit 销售挂账 * @return R */ @Operation(summary = "拼接销售挂账" , description = "拼接销售挂账" ) @SysLog("拼接销售挂账" ) @GetMapping("/generatorInvoice") @PreAuthorize("@pms.hasPermission('business_saleCredit_view')" ) public R generatorInvoice(@ParameterObject SaleCredit saleCredit) { if(saleCredit.getContractId()==null){ return R.failed("合同id不能为空"); } Contract contract = contractService.getById(saleCredit.getContractId()); if(contract==null){ return R.failed("合同id错误"); } saleCredit.setContractName(contract.getContractName()); saleCredit.setContractNo(contract.getContractNo()); BusinessCustomer partA = businessCustomerService.getById(contract.getPartyAId()); if(partA!=null){ saleCredit.setPartyA(partA.getCompanyName()); saleCredit.setCreditCodeA(partA.getCreditCode()); saleCredit.setBankAccountA(partA.getBankAccount()); saleCredit.setBankNameA(partA.getBankName()); } R r = remoteDeptService.getById(contract.getPartyBId()); SysDept dept = r.getData(); if(dept!=null){ saleCredit.setPartyB(dept.getOrgName()); saleCredit.setCreditCodeB(dept.getOrgCode()); saleCredit.setBankAccountB(dept.getOrgBankAccount()); saleCredit.setBankNameB(dept.getOrgBank()); } List outBoundList = contractOutBoundService.list(new LambdaQueryWrapper() .eq(ContractOutBound::getContractId,contract.getId()) .eq(ContractOutBound::getInvoiceSatus,0) .orderByAsc(ContractOutBound::getOutBoundTime) ); if(outBoundList!=null){ if(!outBoundList.isEmpty()){ List list = new ArrayList<>(); for(ContractOutBound outBound : outBoundList){ ContractOutBoundVo vo = new ContractOutBoundVo(); BeanUtil.copyProperties(outBound,vo); Product product = productService.getOne(new LambdaQueryWrapper().eq(Product::getErpCode,outBound.getSubjectMatterCode()).last("limit 1")); Product productP = productService.getOne(new LambdaQueryWrapper().eq(Product::getId,product.getParentId()).last("limit 1")); if(product!=null){ vo.setProductId(product.getId()); vo.setInvoiceName("*"+product.getTaxClass()+"*" + (productP!=null?productP.getProductName():"") + "*"); vo.setTaxClass(product.getTaxClass()); vo.setTaxCode(product.getTaxCode()); vo.setTaxRate(product.getTaxRate()); } ContractSubjectMatter matter = contractSubjectMatterService.getOne(new LambdaQueryWrapper() .eq(ContractSubjectMatter::getContractId,contract.getId()) .eq(ContractSubjectMatter::getMaterialCode,outBound.getSubjectMatterCode()) .last("limit 1") ); if(matter!=null){ vo.setSpecification(matter.getSpecification()); vo.setUnit(matter.getUnit()); vo.setUnitPrice(matter.getUnitPrice()); } list.add(vo); } saleCredit.setContractOutBoundList(list); } } return R.ok(saleCredit); } /** * 修改销售挂账 * @param saleCredit 销售挂账 * @return R */ @Operation(summary = "修改销售挂账" , description = "修改销售挂账" ) @SysLog("修改销售挂账" ) @PutMapping @PreAuthorize("@pms.hasPermission('business_saleCredit_edit')" ) public R updateById(@RequestBody SaleCredit saleCredit) { return R.ok(saleCreditService.updateById(saleCredit)); } /** * 通过id删除销售挂账 * @param ids id列表 * @return R */ @Operation(summary = "通过id删除销售挂账" , description = "通过id删除销售挂账" ) @SysLog("通过id删除销售挂账" ) @DeleteMapping @PreAuthorize("@pms.hasPermission('business_saleCredit_del')" ) public R removeById(@RequestBody Long[] ids) { return R.ok(saleCreditService.removeBatchByIds(CollUtil.toList(ids))); } /** * 导出excel 表格 * @param saleCredit 查询条件 * @param ids 导出指定ID * @return excel 文件流 */ @ResponseExcel @GetMapping("/export") @PreAuthorize("@pms.hasPermission('business_saleCredit_export')" ) public List export(SaleCredit saleCredit,Long[] ids) { return saleCreditService.list(Wrappers.lambdaQuery(saleCredit).in(ArrayUtil.isNotEmpty(ids), SaleCredit::getId, ids)); } }