| | |
| | | package com.ruoyi.aftersalesservice.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.aftersalesservice.dto.AfterSalesServiceImportDto; |
| | | import com.ruoyi.aftersalesservice.dto.AfterSalesServiceNewDto; |
| | | import com.ruoyi.aftersalesservice.dto.CountDto; |
| | | import com.ruoyi.aftersalesservice.mapper.AfterSalesServiceMapper; |
| | | import com.ruoyi.aftersalesservice.pojo.AfterSalesService; |
| | | import com.ruoyi.aftersalesservice.service.AfterSalesServiceService; |
| | | import com.ruoyi.basic.mapper.CustomerMapper; |
| | | import com.ruoyi.basic.pojo.Customer; |
| | | import com.ruoyi.common.utils.OrderUtils; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.project.system.domain.SysDept; |
| | | import com.ruoyi.project.system.domain.SysUser; |
| | | import com.ruoyi.project.system.mapper.SysDeptMapper; |
| | | import com.ruoyi.project.system.domain.SysDictData; |
| | | import com.ruoyi.project.system.mapper.SysDictDataMapper; |
| | | import com.ruoyi.project.system.mapper.SysUserMapper; |
| | | import com.ruoyi.sales.dto.SalesLedgerDto; |
| | | import com.ruoyi.sales.mapper.SalesLedgerMapper; |
| | | import com.ruoyi.sales.pojo.SalesLedger; |
| | | import com.ruoyi.sales.pojo.SalesLedgerProduct; |
| | | import com.ruoyi.sales.service.ISalesLedgerProductService; |
| | | import com.ruoyi.sales.service.ISalesLedgerService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.util.CollectionUtils; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * @author :yys |
| | |
| | | */ |
| | | @Service |
| | | @Slf4j |
| | | @RequiredArgsConstructor |
| | | public class AfterSalesServiceServiceImpl extends ServiceImpl<AfterSalesServiceMapper, AfterSalesService> implements AfterSalesServiceService { |
| | | |
| | | @Autowired |
| | | private AfterSalesServiceMapper afterSalesServiceMapper; |
| | | |
| | | @Autowired |
| | | private SysDeptMapper sysDeptMapper; |
| | | private final AfterSalesServiceMapper afterSalesServiceMapper; |
| | | private final SysDeptMapper sysDeptMapper; |
| | | private final SysUserMapper sysUserMapper; |
| | | private final ISalesLedgerProductService salesLedgerProductService; |
| | | private final ISalesLedgerService salesLedgerService; |
| | | private final com.ruoyi.sales.mapper.ShippingInfoMapper shippingInfoMapper; |
| | | private final CustomerMapper customerMapper; |
| | | private final SalesLedgerMapper salesLedgerMapper; |
| | | private final SysDictDataMapper sysDictDataMapper; |
| | | |
| | | @Override |
| | | public IPage<AfterSalesService> listPage(Page page, AfterSalesService afterSalesService) { |
| | | public IPage<AfterSalesServiceNewDto> listPage(Page page, AfterSalesServiceNewDto afterSalesService) { |
| | | Long tenantId = SecurityUtils.getLoginUser().getTenantId(); |
| | | SysDept sysDept = sysDeptMapper.selectDeptById(tenantId); |
| | | IPage<AfterSalesService> afterSalesServiceIPage = afterSalesServiceMapper.listPage(page, afterSalesService); |
| | | IPage<AfterSalesServiceNewDto> afterSalesServiceIPage = afterSalesServiceMapper.listPage(page, afterSalesService); |
| | | afterSalesServiceIPage.getRecords().forEach(item -> { |
| | | item.setDeptName(sysDept.getDeptName()); |
| | | }); |
| | | return afterSalesServiceIPage; |
| | | } |
| | | |
| | | @Override |
| | | public boolean addAfterSalesServiceDto(AfterSalesServiceNewDto afterSalesServiceNewDto) { |
| | | afterSalesServiceNewDto.setStatus(1); |
| | | if (afterSalesServiceNewDto.getProductModelIdList() != null && afterSalesServiceNewDto.getProductModelIdList().isEmpty() ) { |
| | | String productModelIds = afterSalesServiceNewDto.getProductModelIdList().stream() |
| | | .map(String::valueOf) |
| | | .collect(Collectors.joining(",")); |
| | | afterSalesServiceNewDto.setProductModelIds(productModelIds); |
| | | } |
| | | SysUser sysUser = sysUserMapper.selectUserById(afterSalesServiceNewDto.getCheckUserId()); |
| | | if(sysUser == null) throw new RuntimeException("审核人不存在"); |
| | | afterSalesServiceNewDto.setCheckNickName(sysUser.getNickName()); |
| | | if (StringUtils.isEmpty(afterSalesServiceNewDto.getAfterSalesServiceNo())) { |
| | | String string = OrderUtils.countAfterServiceTodayByCreateTime(afterSalesServiceMapper, "SH_"); |
| | | afterSalesServiceNewDto.setAfterSalesServiceNo(string); |
| | | } |
| | | return this.save(afterSalesServiceNewDto); |
| | | } |
| | | |
| | | @Override |
| | | public AfterSalesServiceNewDto getAfterSalesServiceNewDtoById(Long id) { |
| | | AfterSalesService afterSalesService = afterSalesServiceMapper.selectById(id); |
| | | if (afterSalesService == null) { |
| | | throw new RuntimeException("售后工单不存在"); |
| | | } |
| | | // 工单可以不关联产品(反馈登记导入、历史数据都是空),此处必须容错 |
| | | List<Long> collect = StringUtils.isEmpty(afterSalesService.getProductModelIds()) |
| | | ? new ArrayList<>() |
| | | : Arrays.stream(afterSalesService.getProductModelIds().split(",")) |
| | | .filter(StringUtils::isNotEmpty) |
| | | .map(Long::valueOf) |
| | | .collect(Collectors.toList()); |
| | | List<SalesLedgerProduct> list = collect.isEmpty() |
| | | ? new ArrayList<>() |
| | | : salesLedgerProductService.list(new QueryWrapper<SalesLedgerProduct>().lambda().in(SalesLedgerProduct::getId, collect)); |
| | | |
| | | if (StringUtils.isNotEmpty(afterSalesService.getProductModelQuantities())) { |
| | | String[] quantities = afterSalesService.getProductModelQuantities().split(","); |
| | | for (int i = 0; i < collect.size(); i++) { |
| | | Long productId = collect.get(i); |
| | | for (SalesLedgerProduct product : list) { |
| | | if (product.getId().equals(productId)) { |
| | | if (i < quantities.length && StringUtils.isNotEmpty(quantities[i])) { |
| | | product.setQuantity(new java.math.BigDecimal(quantities[i])); |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | for (SalesLedgerProduct product : list) { |
| | | com.ruoyi.sales.pojo.ShippingInfo shippingInfo = shippingInfoMapper.selectOne( |
| | | new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<com.ruoyi.sales.pojo.ShippingInfo>() |
| | | .eq(com.ruoyi.sales.pojo.ShippingInfo::getSalesLedgerProductId, product.getId()) |
| | | .orderByDesc(com.ruoyi.sales.pojo.ShippingInfo::getCreateTime) |
| | | .last("limit 1") |
| | | ); |
| | | if (shippingInfo != null) { |
| | | product.setShippingCarNumber(shippingInfo.getShippingCarNumber()); |
| | | product.setShippingDate(shippingInfo.getShippingDate()); |
| | | product.setShippingStatus(shippingInfo.getStatus()); |
| | | product.setExpressCompany(shippingInfo.getExpressCompany()); |
| | | product.setExpressNumber(shippingInfo.getExpressNumber()); |
| | | } |
| | | } |
| | | |
| | | AfterSalesServiceNewDto afterSalesServiceNewDto = new AfterSalesServiceNewDto(); |
| | | BeanUtils.copyProperties(afterSalesService, afterSalesServiceNewDto); |
| | | SalesLedgerDto salesLedgerDto = new SalesLedgerDto(); |
| | | if (afterSalesService.getSalesLedgerId() != null) { |
| | | SalesLedger byId = salesLedgerService.getById(afterSalesService.getSalesLedgerId()); |
| | | if (byId != null) { |
| | | BeanUtils.copyProperties(byId, salesLedgerDto); |
| | | } |
| | | } |
| | | salesLedgerDto.setProductData( list); |
| | | afterSalesServiceNewDto.setSalesLedgerDto(salesLedgerDto); |
| | | return afterSalesServiceNewDto; |
| | | } |
| | | |
| | | @Override |
| | | public List<CountDto> countAfterSalesService() { |
| | | List<CountDto> stringIntegerHashMap = afterSalesServiceMapper.countAfterSalesService(); |
| | | Integer total = 0; |
| | | for (CountDto countDto : stringIntegerHashMap) { |
| | | total += countDto.getCount(); |
| | | } |
| | | CountDto countDto = new CountDto(); |
| | | countDto.setStatus(3); |
| | | countDto.setCount(total); |
| | | stringIntegerHashMap.add(countDto); |
| | | |
| | | return stringIntegerHashMap; |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public AjaxResult importData(MultipartFile file) { |
| | | List<AfterSalesServiceImportDto> rows; |
| | | try { |
| | | ExcelUtil<AfterSalesServiceImportDto> util = new ExcelUtil<>(AfterSalesServiceImportDto.class); |
| | | rows = util.importExcel(file.getInputStream()); |
| | | } catch (Exception e) { |
| | | log.error("反馈登记导入-解析excel失败", e); |
| | | return AjaxResult.error("解析Excel失败:" + e.getMessage()); |
| | | } |
| | | if (CollectionUtils.isEmpty(rows)) { |
| | | return AjaxResult.error("导入文件无数据"); |
| | | } |
| | | Long tenantId = SecurityUtils.getLoginUser().getTenantId(); |
| | | Long userId = SecurityUtils.getUserId(); |
| | | int success = 0; |
| | | List<String> errors = new ArrayList<>(); |
| | | for (int i = 0; i < rows.size(); i++) { |
| | | AfterSalesServiceImportDto row = rows.get(i); |
| | | int rowNo = i + 2; // 首行为表头 |
| | | try { |
| | | String customerName = trim(row.getCustomerName()); |
| | | if (StringUtils.isEmpty(customerName)) { |
| | | errors.add("第" + rowNo + "行:客户名称为空"); |
| | | continue; |
| | | } |
| | | Customer customer = findCustomerByName(customerName, tenantId); |
| | | if (customer == null) { |
| | | errors.add("第" + rowNo + "行:客户[" + customerName + "]不存在"); |
| | | continue; |
| | | } |
| | | |
| | | String serviceTypeName = trim(row.getServiceType()); |
| | | String serviceTypeValue = dictValueByLabel("post_sale_waiting_list", serviceTypeName); |
| | | if (StringUtils.isEmpty(serviceTypeValue)) { |
| | | errors.add("第" + rowNo + "行:售后类型[" + serviceTypeName + "]不存在"); |
| | | continue; |
| | | } |
| | | |
| | | String urgencyName = trim(row.getUrgency()); |
| | | String urgencyValue = dictValueByLabel("degree_of_urgency", urgencyName); |
| | | if (StringUtils.isEmpty(urgencyValue)) { |
| | | errors.add("第" + rowNo + "行:紧急程度[" + urgencyName + "]不存在"); |
| | | continue; |
| | | } |
| | | |
| | | Long salesLedgerId = null; |
| | | String contractNo = trim(row.getSalesContractNo()); |
| | | if (StringUtils.isNotEmpty(contractNo)) { |
| | | SalesLedger ledger = salesLedgerMapper.selectOne(new LambdaQueryWrapper<SalesLedger>() |
| | | .eq(SalesLedger::getSalesContractNo, contractNo) |
| | | .eq(SalesLedger::getCustomerId, customer.getId()) |
| | | .last("limit 1")); |
| | | if (ledger == null) { |
| | | ledger = salesLedgerMapper.selectOne(new LambdaQueryWrapper<SalesLedger>() |
| | | .eq(SalesLedger::getSalesContractNo, contractNo) |
| | | .last("limit 1")); |
| | | } |
| | | if (ledger == null) { |
| | | errors.add("第" + rowNo + "行:销售单号[" + contractNo + "]不存在"); |
| | | continue; |
| | | } |
| | | salesLedgerId = ledger.getId(); |
| | | } |
| | | |
| | | AfterSalesServiceNewDto dto = new AfterSalesServiceNewDto(); |
| | | dto.setCustomerName(customer.getCustomerName()); |
| | | dto.setSalesLedgerId(salesLedgerId); |
| | | dto.setServiceType(serviceTypeValue); |
| | | dto.setUrgency(urgencyValue); |
| | | dto.setProDesc(row.getProDesc()); |
| | | dto.setFeedbackDate(row.getFeedbackDate() != null ? row.getFeedbackDate() : new Date()); |
| | | dto.setCheckUserId(userId); |
| | | dto.setProductModelIds(""); |
| | | dto.setProductModelQuantities(""); |
| | | |
| | | if (addAfterSalesServiceDto(dto)) { |
| | | success++; |
| | | } else { |
| | | errors.add("第" + rowNo + "行:保存失败"); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("反馈登记导入第{}行失败", rowNo, e); |
| | | errors.add("第" + rowNo + "行:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | AjaxResult result = AjaxResult.success(); |
| | | result.put("totalCount", rows.size()); |
| | | result.put("successCount", success); |
| | | result.put("failCount", rows.size() - success); |
| | | result.put("errors", errors); |
| | | result.put("msg", "导入完成:成功 " + success + " 条,失败 " + (rows.size() - success) + " 条"); |
| | | return result; |
| | | } |
| | | |
| | | private String trim(String value) { |
| | | return value == null ? null : value.trim(); |
| | | } |
| | | |
| | | private Customer findCustomerByName(String name, Long tenantId) { |
| | | List<Customer> customers = customerMapper.selectList(new LambdaQueryWrapper<Customer>() |
| | | .eq(Customer::getCustomerName, name)); |
| | | if (CollectionUtils.isEmpty(customers)) { |
| | | return null; |
| | | } |
| | | if (tenantId != null) { |
| | | for (Customer c : customers) { |
| | | if (tenantId.equals(c.getTenantId())) { |
| | | return c; |
| | | } |
| | | } |
| | | } |
| | | return customers.get(0); |
| | | } |
| | | |
| | | private String dictValueByLabel(String dictType, String label) { |
| | | if (StringUtils.isEmpty(label)) { |
| | | return null; |
| | | } |
| | | List<SysDictData> datas = sysDictDataMapper.selectDictDataByType(dictType); |
| | | if (CollectionUtils.isEmpty(datas)) { |
| | | return null; |
| | | } |
| | | for (SysDictData d : datas) { |
| | | if (label.equals(d.getDictLabel())) { |
| | | return d.getDictValue(); |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | } |