| | |
| | | import cn.hutool.http.HttpRequest; |
| | | import cn.hutool.http.HttpResponse; |
| | | import cn.hutool.http.HttpUtil; |
| | | import com.alibaba.excel.EasyExcel; |
| | | import com.alibaba.excel.ExcelReader; |
| | | import com.alibaba.excel.read.metadata.ReadSheet; |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | 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.by4cloud.platformx.admin.api.entity.SysDept; |
| | | import com.by4cloud.platformx.admin.api.entity.SysDictItem; |
| | | import com.by4cloud.platformx.admin.api.feign.RemoteDeptService; |
| | | import com.by4cloud.platformx.admin.api.feign.RemoteDictService; |
| | | import com.by4cloud.platformx.business.api.feign.RemoteFlowProcessService; |
| | | import com.by4cloud.platformx.business.constant.FlowNameEnum; |
| | | import com.by4cloud.platformx.business.dto.*; |
| | | import com.by4cloud.platformx.business.entity.*; |
| | | import com.by4cloud.platformx.business.mapper.*; |
| | | import com.by4cloud.platformx.business.service.ContractService; |
| | | import com.by4cloud.platformx.business.utils.BatchInsertListener; |
| | | import com.by4cloud.platformx.business.utils.ItemGeneratorUtil; |
| | | import com.by4cloud.platformx.business.utils.NetworkFileToBase64; |
| | | import com.by4cloud.platformx.business.vo.ContractDetailVo; |
| | | import com.by4cloud.platformx.business.vo.ContractInvoiceVo; |
| | | import com.by4cloud.platformx.business.vo.ContractSlipVo; |
| | | import com.by4cloud.platformx.business.vo.FourAssociationPageVo; |
| | | import com.by4cloud.platformx.business.vo.*; |
| | | import com.by4cloud.platformx.common.core.util.R; |
| | | import com.by4cloud.platformx.common.data.datascope.DataScope; |
| | | import com.by4cloud.platformx.common.security.util.SecurityUtils; |
| | |
| | | import org.springframework.core.io.ClassPathResource; |
| | | import org.springframework.data.redis.core.StringRedisTemplate; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.IOException; |
| | | import java.io.OutputStream; |
| | |
| | | private final ContractInvoiceMapper contractInvoiceMapper; |
| | | private final StringRedisTemplate redisTemplate; |
| | | private final ContractOutBoundMapper contractOutBoundMapper; |
| | | private final RemoteDictService remoteDictService; |
| | | |
| | | @Value("${erp.ymj}") |
| | | private String ymjErp; |
| | |
| | | if (ObjUtil.isNotNull(addDTO.getDeliveryCycle())){ |
| | | contract.setExpirationDate(DateUtil.offsetDay(addDTO.getSignDate(),addDTO.getDeliveryCycle())); |
| | | } |
| | | |
| | | if (ObjUtil.isNotNull(contract.getSignDate()) && ObjUtil.isNotNull(contract.getExpirationDate())) { |
| | | Long bd = DateUtil.betweenDay(contract.getExpirationDate(), contract.getSignDate(), true); |
| | | contract.setDeliveryCycle(bd.intValue()); |
| | | } |
| | | contract.setContractNo(generateGYBContractNo()); |
| | | |
| | | if (!StrUtil.equals(addDTO.getContractCategory(), "water_house")){ |
| | |
| | | |
| | | /** |
| | | * 判断付款阶段列表是否符合标准 |
| | | * |
| | | * @param scheduleList 付款阶段列表 |
| | | * @return true 如果包含且仅包含标准的五个阶段,false 否则 |
| | | */ |
| | |
| | | map.put("buyerPart", contract.getBuyerPart()); |
| | | |
| | | |
| | | |
| | | //标的物 |
| | | List<Map<String, Object>> items = new ArrayList<>(); |
| | | subjectMatterList.stream().forEach(contractSubjectMatter -> { |
| | |
| | | } |
| | | return R.ok(); |
| | | } |
| | | |
| | | @Override |
| | | public R importContractMultiSheet(MultipartFile file) { |
| | | |
| | | // 用于收集所有 Sheet 解析后的最终结果(如果需要统一返回或处理) |
| | | // 注意:如果数据量极大,建议在 Listener 中直接入库,不要全部加载到内存 List 中 |
| | | List<ContractExceVO> baseList = new ArrayList<>(); |
| | | List<ContractPaymentScheduleExceVO> scheduleList = new ArrayList<>(); |
| | | List<ContractSubjectMatterExceVO> matterList = new ArrayList<>(); |
| | | |
| | | try (ExcelReader excelReader = EasyExcel.read(file.getInputStream()).build()) { |
| | | |
| | | // 1. 构建第一个 Sheet 的读取配置 |
| | | ReadSheet sheet0 = EasyExcel.readSheet(0) |
| | | .headRowNumber(1) // 表头行数 |
| | | .head(ContractExceVO.class) // 指定实体类 |
| | | .registerReadListener(new BatchInsertListener<ContractExceVO>(data -> { |
| | | baseList.addAll(data); |
| | | // 建议:在这里直接调用 service 保存,而不是 addTo List,除非数据量很小 |
| | | // contractService.saveBaseInfo(data); |
| | | })) |
| | | .build(); |
| | | |
| | | // 2. 构建第二个 Sheet 的读取配置 |
| | | ReadSheet sheet1 = EasyExcel.readSheet(1) |
| | | .headRowNumber(1) |
| | | .head(ContractSubjectMatterExceVO.class) |
| | | .registerReadListener(new BatchInsertListener<ContractSubjectMatterExceVO>(data -> { |
| | | matterList.addAll(data); |
| | | // contractService.saveSchedule(data); |
| | | })) |
| | | .build(); |
| | | |
| | | // 3. 构建第三个 Sheet 的读取配置 |
| | | ReadSheet sheet2 = EasyExcel.readSheet(2) |
| | | .headRowNumber(1) |
| | | .head(ContractPaymentScheduleExceVO.class) // 注意:这里你原代码写的是 ContractPaymentScheduleExceVO,但变量是 matterList,需确认实体类是否一致 |
| | | .registerReadListener(new BatchInsertListener<ContractPaymentScheduleExceVO>(data -> { |
| | | scheduleList.addAll(data); |
| | | // contractService.saveMatter(data); |
| | | })) |
| | | .build(); |
| | | |
| | | // 4. 依次执行读取 |
| | | // 注意:excelReader.read(sheet) 会复用同一个输入流,所以必须用 try-with-resources 确保流管理正确 |
| | | excelReader.read(sheet0); |
| | | excelReader.read(sheet1); |
| | | excelReader.read(sheet2); |
| | | // 后续处理 baseList, scheduleList, matterList |
| | | log.info("主表数据量: " + baseList.size()); |
| | | log.info("进度表数据量: " + scheduleList.size()); |
| | | log.info("标的物数据量: " + matterList.size()); |
| | | List<Map<String, String>> errList = new ArrayList<>(); |
| | | for (int i = 0; i < baseList.size(); i++) { |
| | | ContractExceVO contractExceVO = baseList.get(i); |
| | | if (StrUtil.isBlank(contractExceVO.getContractNo())) { |
| | | Map<String, String> map = new HashMap<String, String>(); |
| | | map.put("lineNum", "第" + (i + 1) + "行"); |
| | | map.put("errors", "合同编号为空"); |
| | | errList.add(map); |
| | | continue; |
| | | } |
| | | BusinessCustomer bc = businessCustomerMapper.selectOne(Wrappers.<BusinessCustomer>lambdaQuery() |
| | | .eq(BusinessCustomer::getErpCompanyCode, contractExceVO.getBcErpCode())); |
| | | if (ObjUtil.isNull(bc)) { |
| | | Map<String, String> map = new HashMap<String, String>(); |
| | | map.put("lineNum", "第" + (i + 1) + "行"); |
| | | map.put("errors", "客户erp编码不存在"); |
| | | errList.add(map); |
| | | continue; |
| | | } |
| | | R<List<SysDictItem>> rem = remoteDictService.getDictByType("economic_matters"); |
| | | if (!rem.isOk()) { |
| | | return R.failed("经济事项字典查询异常"); |
| | | } |
| | | List<SysDictItem> itemList = rem.getData(); |
| | | for (SysDictItem dictItem : itemList |
| | | ) { |
| | | if (StrUtil.equals(contractExceVO.getEconomicMatters(), dictItem.getLabel())) { |
| | | contractExceVO.setEconomicMatters(dictItem.getItemValue()); |
| | | break; |
| | | } |
| | | } |
| | | R<List<SysDictItem>> rsa = remoteDictService.getDictByType("supply_attribute"); |
| | | if (!rsa.isOk()) { |
| | | return R.failed("供应属性字典查询异常"); |
| | | } |
| | | for (SysDictItem dictItem : rsa.getData() |
| | | ) { |
| | | if (StrUtil.equals(contractExceVO.getSupplyAttribute().replace(" ", ""), dictItem.getLabel())) { |
| | | contractExceVO.setSupplyAttribute(dictItem.getItemValue()); |
| | | break; |
| | | } |
| | | } |
| | | R<List<SysDictItem>> rssa = remoteDictService.getDictByType("server_attribute"); |
| | | if (!rssa.isOk()) { |
| | | return R.failed("服务属性字典查询异常"); |
| | | } |
| | | for (SysDictItem dictItem : rssa.getData() |
| | | ) { |
| | | if (StrUtil.equals(contractExceVO.getContractAttribute().replace(" ", ""), dictItem.getLabel())) { |
| | | contractExceVO.setContractAttribute(dictItem.getItemValue()); |
| | | break; |
| | | } |
| | | } |
| | | R<List<SysDictItem>> ris = remoteDictService.getDictByType("industry_sector"); |
| | | if (!ris.isOk()) { |
| | | return R.failed("服务属性字典查询异常"); |
| | | } |
| | | for (SysDictItem dictItem : ris.getData() |
| | | ) { |
| | | if (StrUtil.equals(contractExceVO.getIndustryCode(), dictItem.getLabel())) { |
| | | contractExceVO.setIndustryCode(dictItem.getItemValue()); |
| | | break; |
| | | } |
| | | } |
| | | List<Contract> contractList = baseMapper.selectList(Wrappers.<Contract>lambdaQuery() |
| | | .eq(Contract::getContractNo, contractExceVO.getContractNo())); |
| | | if (CollUtil.isNotEmpty(contractList)) { |
| | | Map<String, String> map = new HashMap<String, String>(); |
| | | map.put("lineNum", "第" + (i + 1) + "行"); |
| | | map.put("errors", "合同编号已存在"); |
| | | errList.add(map); |
| | | continue; |
| | | } |
| | | Contract contract = BeanUtil.copyProperties(contractExceVO, Contract.class); |
| | | if (ObjUtil.isNotNull(contract.getSignDate()) && ObjUtil.isNotNull(contract.getExpirationDate())) { |
| | | Long bd = DateUtil.betweenDay(contract.getExpirationDate(), contract.getSignDate(), true); |
| | | contract.setDeliveryCycle(bd.intValue()); |
| | | } |
| | | contract.setPartyA(bc.getCompanyName()); |
| | | contract.setPartyAId(bc.getId()); |
| | | contract.setPartyB(SecurityUtils.getUser().getCompName()); |
| | | contract.setPartyBId(SecurityUtils.getUser().getCompId()); |
| | | contract.setContractStatus(2); |
| | | contract.setPaidAmount(ObjUtil.isNotNull(contract.getPaidAmount())? |
| | | contract.getPaidAmount():new BigDecimal("0")); |
| | | contract.setBillingAmout(ObjUtil.isNotNull(contract.getBillingAmout())? |
| | | contract.getBillingAmout():new BigDecimal("0")); |
| | | contract.setBillingStatus("1"); |
| | | baseMapper.insert(contract); |
| | | BigDecimal remainAmount = ObjUtil.isNotNull(contract.getPaidAmount())?contract.getPaidAmount():new BigDecimal("0"); |
| | | List<ContractSubjectMatterExceVO> resultMatter = matterList.stream().filter(item -> |
| | | StrUtil.isNotBlank(item.getMaterialCode()) && |
| | | StrUtil.equals(item.getContractNo(), contract.getContractNo())).collect(Collectors.toList()); |
| | | if (CollUtil.isNotEmpty(resultMatter)) { |
| | | for (ContractSubjectMatterExceVO subMatEx : resultMatter |
| | | ) { |
| | | ContractSubjectMatter subjectMatter = BeanUtil.copyProperties(subMatEx, ContractSubjectMatter.class); |
| | | subjectMatter.setContractId(contract.getId()); |
| | | subjectMatter.setDeliveredQuantity(StrUtil.isBlank(subMatEx.getDeliveredQuantity()) |
| | | ? new BigDecimal("0") : new BigDecimal(subMatEx.getDeliveredQuantity())); |
| | | subjectMatter.setRemainingQuantity(subjectMatter.getQuantity().subtract(subjectMatter.getDeliveredQuantity())); |
| | | subjectMatter.setDeliveryStatus(subjectMatter.getRemainingQuantity().compareTo(subjectMatter.getQuantity()) == 0 ? 0 |
| | | : subjectMatter.getRemainingQuantity().compareTo(new BigDecimal("0")) > 0 ? 1 : 2); |
| | | contractSubjectMatterMapper.insert(subjectMatter); |
| | | } |
| | | } |
| | | List<ContractPaymentScheduleExceVO> resultSchedule = scheduleList.stream().filter(item -> |
| | | StrUtil.equals(item.getContractNo(), contract.getContractNo())).collect(Collectors.toList()); |
| | | if (CollUtil.isNotEmpty(resultSchedule)) { |
| | | |
| | | for (int j = 0; j < resultSchedule.size(); j++) { |
| | | ContractPaymentSchedule schedule = new ContractPaymentSchedule(); |
| | | schedule.setStageName(resultSchedule.get(j).getStageName()); |
| | | schedule.setContractId(contract.getId()); |
| | | schedule.setPaymentRatio(StrUtil.isBlank(resultSchedule.get(j).getPaymentRatio()) |
| | | ? new BigDecimal("0") : new BigDecimal(resultSchedule.get(j).getPaymentRatio())); |
| | | schedule.setAgreedDays(StrUtil.isBlank(resultSchedule.get(j).getAgreedDays()) |
| | | ? 0 : Integer.valueOf(resultSchedule.get(j).getPaymentRatio())); |
| | | schedule.setPlannedAmount(contract.getAmount().multiply(schedule.getPaymentRatio()) |
| | | .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP)); |
| | | schedule.setPaymentStatus(0); |
| | | schedule.setStageOrder(j + 1); |
| | | if (remainAmount.compareTo(new BigDecimal("0"))>0&&schedule.getPlannedAmount().compareTo(new BigDecimal("0"))>0){ |
| | | remainAmount = remainAmount.subtract(schedule.getPlannedAmount()); |
| | | if (remainAmount.compareTo(new BigDecimal("0"))>=0){ |
| | | schedule.setPaymentStatus(2); |
| | | schedule.setActualAmount(schedule.getPlannedAmount()); |
| | | } |
| | | if (remainAmount.compareTo(new BigDecimal("0"))<0){ |
| | | schedule.setPaymentStatus(1); |
| | | schedule.setActualAmount(schedule.getPlannedAmount().add(remainAmount)); |
| | | } |
| | | } |
| | | contractPaymentScheduleMapper.insert(schedule); |
| | | if (schedule.getStageName().equals("质保金")&&contract.getAmount().subtract(ObjUtil.isNotNull(contract.getPaidAmount())? |
| | | contract.getPaidAmount():new BigDecimal("0")).compareTo(new BigDecimal("0"))>0){ |
| | | PaymentConfirm confirm = new PaymentConfirm(); |
| | | confirm.setBusGuestId(contract.getPartyAId()); |
| | | confirm.setBusGuestName(contract.getPartyA()); |
| | | confirm.setBusinessType("质保金应收"); |
| | | confirm.setConfirmTime(new Date()); |
| | | confirm.setContractId(contract.getId()); |
| | | confirm.setContractName(contract.getContractName()); |
| | | confirm.setContractNo(contract.getContractNo()); |
| | | confirm.setScheduleId(schedule.getId()); |
| | | confirm.setScheduleName(schedule.getStageName()); |
| | | confirm.setTransationAmount(contract.getAmount().subtract(ObjUtil.isNotNull(contract.getPaidAmount())? |
| | | contract.getPaidAmount():new BigDecimal("0"))); |
| | | confirm.setReceivableAmount(confirm.getTransationAmount()); |
| | | confirm.setTotalAmount(confirm.getTransationAmount().multiply(new BigDecimal("-1"))); |
| | | paymentConfirmMapper.insert(confirm); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | if (CollUtil.isNotEmpty(errList)) { |
| | | return R.failed(errList); |
| | | } |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | return R.failed("文件解析失败: " + e.getMessage()); |
| | | } |
| | | return R.ok(); |
| | | } |
| | | } |