| | |
| | | package com.by4cloud.platformx.business.service.impl; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.date.DateUtil; |
| | | import cn.hutool.core.lang.tree.Tree; |
| | | import cn.hutool.core.lang.tree.TreeNode; |
| | | import cn.hutool.core.lang.tree.TreeUtil; |
| | | import cn.hutool.core.util.ObjUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.hutool.http.HttpRequest; |
| | | import cn.hutool.http.HttpResponse; |
| | | import cn.hutool.http.HttpUtil; |
| | | 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.business.dto.ProductAddDTO; |
| | | import com.by4cloud.platformx.business.dto.ProductQueryDTO; |
| | | import com.by4cloud.platformx.business.dto.SyncProductDTO; |
| | | import com.by4cloud.platformx.business.entity.BusinessCustomer; |
| | | import com.by4cloud.platformx.business.entity.Product; |
| | | import com.by4cloud.platformx.business.entity.TaxCode; |
| | | import com.by4cloud.platformx.business.mapper.ProductMapper; |
| | | import com.by4cloud.platformx.business.mapper.TaxCodeMapper; |
| | | import com.by4cloud.platformx.business.service.ProductService; |
| | | import com.by4cloud.platformx.business.vo.ProductExcelVO; |
| | | import com.by4cloud.platformx.business.vo.ProductSelectVo; |
| | | import com.by4cloud.platformx.common.core.util.R; |
| | | import com.by4cloud.platformx.common.data.datascope.DataScope; |
| | | import com.by4cloud.platformx.common.excel.vo.ErrorMessage; |
| | | import com.by4cloud.platformx.common.security.util.SecurityUtils; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import org.springframework.beans.BeanUtils; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.data.redis.core.StringRedisTemplate; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.validation.BindingResult; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.*; |
| | | import java.util.function.Function; |
| | | import java.util.stream.Collectors; |
| | | import java.util.stream.IntStream; |
| | | |
| | | ; |
| | | |
| | | /** |
| | | * 产品信息 |
| | |
| | | * @author platformx |
| | | * @date 2026-05-07 10:17:52 |
| | | */ |
| | | @Slf4j |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService { |
| | | @Override |
| | | public List<Tree<Long>> treeList(Long parentId, String productName) { |
| | | Long parent = parentId == null ? 0l : parentId; |
| | | |
| | | private final TaxCodeMapper taxCodeMapper; |
| | | |
| | | private final StringRedisTemplate redisTemplate; |
| | | |
| | | @Value("${erp.smj}") |
| | | private String smjErp; |
| | | |
| | | @Value("${erp.smjsc}") |
| | | private String smjscErp; |
| | | |
| | | @Value("${erp.smjzt}") |
| | | private String smjztErp; |
| | | |
| | | @Value("${dept.smj}") |
| | | private String smj; |
| | | |
| | | @Value("${dept.smjsc}") |
| | | private String smjsc; |
| | | |
| | | @Value("${dept.smjzt}") |
| | | private String smjzt; |
| | | |
| | | @Value("${dept.smjhw}") |
| | | private String smjhw; |
| | | |
| | | |
| | | @Override |
| | | public Page pageScope(Page page, Product product) { |
| | | if (StrUtil.equals(SecurityUtils.getUser().getCompId() + "", smj) || StrUtil.equals(SecurityUtils.getUser().getCompId() + "", smjhw)) { |
| | | List<String> smjList = new ArrayList<>(); |
| | | smjList.add(smj); |
| | | smjList.add(smjhw); |
| | | return baseMapper.page(page,product,smjList); |
| | | } |
| | | return baseMapper.pageScope(page,product,DataScope.of("comp_id")); |
| | | } |
| | | |
| | | @Override |
| | | public List<Tree<Long>> treeList() { |
| | | List<TreeNode<Long>> collect = baseMapper |
| | | .selectListByScope(Wrappers.<Product>lambdaQuery() |
| | | .like(StrUtil.isNotBlank(productName), Product::getProductName, productName) |
| | | .orderByAsc(Product::getCreateTime), DataScope.of("comp_id")) |
| | | .stream().map(getNodeFunction()).collect(Collectors.toList()); |
| | | |
| | | // 模糊查询 不组装树结构 直接返回 表格方便编辑 |
| | | if (StrUtil.isNotBlank(productName)) { |
| | | return collect.stream().map(node -> { |
| | | Tree<Long> tree = new Tree<>(); |
| | | tree.putAll(node.getExtra()); |
| | | BeanUtils.copyProperties(node, tree); |
| | | return tree; |
| | | }).collect(Collectors.toList()); |
| | | } |
| | | |
| | | return TreeUtil.build(collect, parent); |
| | | // if (StrUtil.isNotBlank(productName)) { |
| | | // return collect.stream().map(node -> { |
| | | // Tree<Long> tree = new Tree<>(); |
| | | // tree.putAll(node.getExtra()); |
| | | // BeanUtils.copyProperties(node, tree); |
| | | // return tree; |
| | | // }).collect(Collectors.toList()); |
| | | // } |
| | | TreeNode<Long> parent = new TreeNode<>(); |
| | | parent.setId(0L); |
| | | parent.setName("目录"); |
| | | parent.setParentId(-1L); |
| | | collect.add(parent); |
| | | return TreeUtil.build(collect, 0L); |
| | | } |
| | | |
| | | @NotNull |
| | | @Override |
| | | public List<ProductSelectVo> getProductList(Product product) { |
| | | return baseMapper.getProductListByScope(product,DataScope.of("comp_id")); |
| | | } |
| | | |
| | | |
| | | @NotNull |
| | | private Function<Product, TreeNode<Long>> getNodeFunction() { |
| | | return product -> { |
| | | TreeNode<Long> node = new TreeNode<>(); |
| | |
| | | node.setParentId(product.getParentId()); |
| | | //node.setWeight(product.getParentId()); |
| | | // 扩展属性 |
| | | Map<String, Object> extra = new HashMap<>(); |
| | | // Map<String, Object> extra = new HashMap<>(); |
| | | // extra.put("picPath", category.getPicPath()); |
| | | // extra.put("Type", category.getType()); |
| | | // extra.put("isShow", category.getIsShow()); |
| | |
| | | // extra.put("status", category.getStatus()); |
| | | |
| | | // 适配 vue3 |
| | | Map<String, Object> meta = new HashMap<>(); |
| | | // Map<String, Object> meta = new HashMap<>(); |
| | | /* meta.put("title", product.getProductName()); |
| | | meta.put("icon", product.getPrice());*/ |
| | | |
| | |
| | | return node; |
| | | }; |
| | | } |
| | | |
| | | @Override |
| | | public R getProductListByParentId(ProductQueryDTO queryDTO) { |
| | | String[] erpCodes = new String[]{"house_rental","electricity_bill","water_bill"}; |
| | | // MPJLambdaWrapper<Product> wrapper = new MPJLambdaWrapper<Product>() |
| | | // .selectAs("( SELECT count(1) FROM product t1 WHERE t1.parent_id = t.id )",Product::getChildNum) |
| | | // .selectAll(Product.class) |
| | | // .like(StrUtil.isNotEmpty(queryDTO.getProductName()),Product::getProductName,queryDTO.getProductName()) |
| | | // .eq(StrUtil.isNotEmpty(queryDTO.getParentId()),Product::getParentId,queryDTO.getParentId()) |
| | | // .in(StrUtil.isNotEmpty(queryDTO.getContractCategory())&&StrUtil.equals(queryDTO.getContractCategory(), "water_house"), |
| | | // Product::getErpCode,erpCodes); |
| | | if (StrUtil.isNotBlank(queryDTO.getProductIds())){ |
| | | String[] arr = queryDTO.getProductIds().split(","); |
| | | queryDTO.setProductId(Arrays.stream(arr).collect(Collectors.toList())); |
| | | } |
| | | if (StrUtil.equals(SecurityUtils.getUser().getCompId()+"","2089995177814495234")|| |
| | | StrUtil.equals(SecurityUtils.getUser().getCompId()+"","2101966257365045249")){ |
| | | List<ProductSelectVo> selectVos = baseMapper.getProductSMJListByParentId(queryDTO, Arrays.asList(erpCodes)); |
| | | if (selectVos.size()>2000){ |
| | | return R.ok(selectVos.subList(0,1999)); |
| | | } |
| | | return R.ok(selectVos); |
| | | } |
| | | List<ProductSelectVo> selectVos = baseMapper.getProductListByParentId(queryDTO, Arrays.asList(erpCodes),DataScope.of("comp_id")); |
| | | if (selectVos.size()>2000){ |
| | | return R.ok(selectVos.subList(0,1999)); |
| | | } |
| | | return R.ok(selectVos); |
| | | } |
| | | |
| | | @Override |
| | | public R saveErpProduct(List<ProductAddDTO> addDTOS) { |
| | | if (CollUtil.isNotEmpty(addDTOS)){ |
| | | for (ProductAddDTO addDTO:addDTOS |
| | | ) { |
| | | if (StrUtil.isBlank(addDTO.getErpCode())){ |
| | | return R.failed("erp编码不能为空"); |
| | | } |
| | | List<Product> classPro = baseMapper.selectListByScope(Wrappers.<Product>lambdaQuery() |
| | | .eq(StrUtil.isNotEmpty(addDTO.getErpTypeCode()),Product::getErpCode,addDTO.getErpTypeCode()) |
| | | .eq(StrUtil.isNotEmpty(addDTO.getErpTypeName()),Product::getProductName,addDTO.getErpTypeName()) |
| | | , DataScope.of("comp_id")); |
| | | if (CollUtil.isEmpty(classPro)){ |
| | | Product product = new Product(); |
| | | product.setProductName(addDTO.getErpTypeName()); |
| | | product.setProductType(addDTO.getSpecification()); |
| | | product.setParentId(0L); |
| | | product.setParentName("根级产品"); |
| | | product.setErpCode(addDTO.getErpTypeCode()); |
| | | TaxCode taxCode = taxCodeMapper.selectOne(Wrappers.<TaxCode>lambdaQuery().eq(TaxCode::getBm,addDTO.getTaxCode()).last("limit 1")); |
| | | if (ObjUtil.isNotNull(taxCode)){ |
| | | product.setTaxClass(taxCode.getSphwjc()); |
| | | product.setTaxRate(Double.valueOf(taxCode.getSl().replace("%",""))); |
| | | } |
| | | baseMapper.insert(product); |
| | | classPro.add(product); |
| | | } |
| | | List<Product> productList = baseMapper.selectListByScope(Wrappers.<Product>lambdaQuery() |
| | | .eq(StrUtil.isNotEmpty(addDTO.getErpCode()),Product::getErpCode,addDTO.getErpCode()) |
| | | , DataScope.of("comp_id")); |
| | | if (CollUtil.isEmpty(productList)){ |
| | | Product product = new Product(); |
| | | product.setProductName(addDTO.getErpName()); |
| | | product.setProductType(addDTO.getSpecification()); |
| | | product.setParentId(classPro.get(0).getId()); |
| | | product.setParentName(classPro.get(0).getProductName()); |
| | | product.setErpCode(addDTO.getErpCode()); |
| | | TaxCode taxCode = taxCodeMapper.selectOne(Wrappers.<TaxCode>lambdaQuery().eq(TaxCode::getBm,addDTO.getTaxCode()).last("limit 1")); |
| | | if (ObjUtil.isNotNull(taxCode)){ |
| | | product.setTaxClass(taxCode.getSphwjc()); |
| | | product.setTaxRate(Double.valueOf(taxCode.getSl().replace("%",""))); |
| | | } |
| | | baseMapper.insert(product); |
| | | } |
| | | } |
| | | } |
| | | return R.failed("数据为空"); |
| | | } |
| | | |
| | | @Override |
| | | public R importProduct(List<ProductExcelVO> excelVOList, BindingResult bindingResult) { |
| | | List<ErrorMessage> errorMessageList = (List<ErrorMessage>) bindingResult.getTarget(); |
| | | if (CollUtil.isNotEmpty(excelVOList)) { |
| | | List<List<ProductExcelVO>> groups = splitList(excelVOList, 5000); |
| | | groups.stream().forEach(group->{ |
| | | for (ProductExcelVO addDTO:group |
| | | ) { |
| | | Set<String> errorMsg = new HashSet<>(); |
| | | |
| | | if (StrUtil.isEmpty(addDTO.getErpTypeCode())&&StrUtil.isEmpty(addDTO.getErpTypeName())) { |
| | | errorMsg.add("产品分类信息没有"); |
| | | } |
| | | List<Product> one = this.listByScope(Wrappers.<Product>lambdaQuery().eq(Product::getErpCode, addDTO.getErpCode())); |
| | | if (CollUtil.isNotEmpty(one)){ |
| | | errorMsg.add("产品erp编码已存在"); |
| | | } |
| | | if (CollUtil.isEmpty(errorMsg)){ |
| | | List<Product> classPro = baseMapper.selectListByScope(Wrappers.<Product>lambdaQuery() |
| | | .eq(StrUtil.isNotEmpty(addDTO.getErpTypeCode()),Product::getErpCode,addDTO.getErpTypeCode()) |
| | | .eq(StrUtil.isNotEmpty(addDTO.getErpTypeName()),Product::getProductName,addDTO.getErpTypeName()) |
| | | , DataScope.of("comp_id")); |
| | | if (CollUtil.isEmpty(classPro)){ |
| | | Product product = new Product(); |
| | | product.setProductName(addDTO.getErpTypeName()); |
| | | product.setProductType(addDTO.getSpecification()); |
| | | product.setParentId(0L); |
| | | product.setParentName("根级产品"); |
| | | product.setErpCode(addDTO.getErpTypeCode()); |
| | | TaxCode taxCode = taxCodeMapper.selectOne(Wrappers.<TaxCode>lambdaQuery().eq(TaxCode::getBm,addDTO.getTaxCode()).last("limit 1")); |
| | | if (ObjUtil.isNotNull(taxCode)){ |
| | | product.setTaxClass(taxCode.getMc()); |
| | | product.setTaxRate(Double.valueOf(taxCode.getSl().replace("%",""))); |
| | | } |
| | | baseMapper.insert(product); |
| | | classPro.add(product); |
| | | } |
| | | Product product = new Product(); |
| | | product.setProductName(addDTO.getErpName()); |
| | | product.setProductType(addDTO.getSpecification()); |
| | | product.setParentId(classPro.get(0).getId()); |
| | | product.setParentName(classPro.get(0).getProductName()); |
| | | product.setErpCode(addDTO.getErpCode()); |
| | | TaxCode taxCode = taxCodeMapper.selectOne(Wrappers.<TaxCode>lambdaQuery().eq(TaxCode::getBm,addDTO.getTaxCode()).last("limit 1")); |
| | | if (ObjUtil.isNotNull(taxCode)){ |
| | | product.setTaxClass(taxCode.getMc()); |
| | | product.setTaxRate(Double.valueOf(taxCode.getSl().replace("%",""))); |
| | | } |
| | | baseMapper.insert(product); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | if (CollUtil.isNotEmpty(errorMessageList)) { |
| | | return R.failed(errorMessageList); |
| | | } |
| | | return R.ok(); |
| | | } |
| | | |
| | | public static <T> List<List<T>> splitList(List<T> list, int batchSize) { |
| | | if (list == null || list.isEmpty()) { |
| | | return Collections.emptyList(); |
| | | } |
| | | |
| | | int totalSize = list.size(); |
| | | // 计算需要分成多少组 |
| | | int batchCount = (totalSize + batchSize - 1) / batchSize; |
| | | |
| | | return IntStream.range(0, batchCount) |
| | | .mapToObj(i -> list.subList(i * batchSize, |
| | | Math.min((i + 1) * batchSize, totalSize))) |
| | | .collect(Collectors.toList()); |
| | | } |
| | | |
| | | @Override |
| | | public R syncSMJByDate(SyncProductDTO dto) { |
| | | String startDate = ""; |
| | | if (StrUtil.isBlank(dto.getStartDate())){ |
| | | startDate = DateUtil.formatDate(DateUtil.offsetDay(new Date(), -1)); |
| | | }else { |
| | | startDate = dto.getStartDate(); |
| | | } |
| | | String token = ""; |
| | | if (redisTemplate.hasKey("SMJ_ERP_TOKEN")) { |
| | | token = (String) redisTemplate.opsForValue().get("SMJ_ERP_TOKEN"); |
| | | } else { |
| | | token = getErpToken(); |
| | | } |
| | | if (StrUtil.isEmpty(token)){ |
| | | return R.failed("石煤机登录获取token失败"); |
| | | } |
| | | List<String> list = Arrays.asList("tenant1","tenant2","tenant3"); |
| | | for (int i = 0; i < list.size(); i++) { |
| | | String tan = list.get(i); |
| | | HttpResponse response = HttpRequest.get(smjErp + "/api/item/v1/byDateCre?startDate=" + startDate+"&tenantId="+tan) |
| | | .header("token", token) // 添加认证头 |
| | | .execute(); // 执行请求.post(ymjErp,request.toJSONString()); |
| | | log.info("石煤机——"+tan+"产品获取回参:{}", response.body()); |
| | | JSONObject proResult = JSONObject.parseObject(response.body()); |
| | | JSONArray items = proResult.getJSONArray("data"); |
| | | if (CollUtil.isNotEmpty(items)){ |
| | | log.info("石煤机产品获取数量:{}", items.size()); |
| | | items.stream().forEach(item->{ |
| | | JSONObject product = (JSONObject) item; |
| | | Product productClass = baseMapper.selectOne(Wrappers.<Product>lambdaQuery() |
| | | .eq(Product::getProductName,product.getString("itemClassName")) |
| | | // .and(wrapper -> wrapper.eq(Product::getCompId,"2089995177814495234") |
| | | // .or().eq(Product::getCompId,"2089996921978040321") |
| | | // .or().eq(Product::getCompId,"2089997578009128962") |
| | | // ) |
| | | .eq(StrUtil.equals(tan,"tenant1"),Product::getCompId,"2089995177814495234") |
| | | .eq(StrUtil.equals(tan,"tenant2"),Product::getCompId,"2089996921978040321") |
| | | .eq(StrUtil.equals(tan,"tenant3"),Product::getCompId,"2089997578009128962") |
| | | .last("limit 1") |
| | | ); |
| | | if(ObjUtil.isNull(productClass)){ |
| | | log.info("产品分类:{}不存在",product.getString("itemClassName")); |
| | | productClass = new Product(); |
| | | productClass.setProductName(product.getString("itemClassName")); |
| | | productClass.setErpCode(product.getString("itemClassName")); |
| | | productClass.setParentId(0L); |
| | | if(StrUtil.equals(tan,"tenant1")){ |
| | | productClass.setCompId(2089995177814495234L); |
| | | } |
| | | if(StrUtil.equals(tan,"tenant2")){ |
| | | productClass.setCompId(2089996921978040321L); |
| | | } |
| | | if(StrUtil.equals(tan,"tenant3")){ |
| | | productClass.setCompId(2089997578009128962L); |
| | | } |
| | | TaxCode taxCode = taxCodeMapper.selectOne(Wrappers.<TaxCode>lambdaQuery().eq(TaxCode::getBm,product.getString("tfTaxClass")).last("limit 1")); |
| | | if (ObjUtil.isNotNull(taxCode)){ |
| | | productClass.setTaxClass(taxCode.getSphwjc()); |
| | | productClass.setTaxRate(Double.valueOf(taxCode.getSl().replace("%",""))); |
| | | } |
| | | baseMapper.insert(productClass); |
| | | log.info("产品分类:{}新增成功",product.getString("itemClassName")); |
| | | } |
| | | Product productNew = baseMapper.selectOne(Wrappers.<Product>lambdaQuery() |
| | | .eq(Product::getErpCode,product.getString("itemNo")) |
| | | // .and(wrapper -> wrapper.eq(Product::getCompId,"2089995177814495234") |
| | | // .or().eq(Product::getCompId,"2089996921978040321") |
| | | // .or().eq(Product::getCompId,"2089997578009128962") |
| | | // ) |
| | | .eq(StrUtil.equals(tan,"tenant1"),Product::getCompId,"2089995177814495234") |
| | | .eq(StrUtil.equals(tan,"tenant2"),Product::getCompId,"2089996921978040321") |
| | | .eq(StrUtil.equals(tan,"tenant3"),Product::getCompId,"2089997578009128962") |
| | | .last("limit 1") |
| | | ); |
| | | if(ObjUtil.isNull(productNew)){ |
| | | log.info("产品:{}不存在",product.getString("itemNo")); |
| | | productNew = new Product(); |
| | | productNew.setProductName(product.getString("note")); |
| | | productNew.setErpCode(product.getString("itemNo")); |
| | | productNew.setProductType(product.getString("grade")); |
| | | if(StrUtil.equals(tan,"tenant1")){ |
| | | productNew.setCompId(2089995177814495234L); |
| | | } |
| | | if(StrUtil.equals(tan,"tenant2")){ |
| | | productNew.setCompId(2089996921978040321L); |
| | | } |
| | | if(StrUtil.equals(tan,"tenant3")){ |
| | | productNew.setCompId(2089997578009128962L); |
| | | } |
| | | productNew.setParentId(productClass.getId()); |
| | | TaxCode taxCode = taxCodeMapper.selectOne(Wrappers.<TaxCode>lambdaQuery().eq(TaxCode::getBm,product.getString("tfTaxClass")).last("limit 1")); |
| | | if (ObjUtil.isNotNull(taxCode)){ |
| | | productClass.setTaxClass(taxCode.getSphwjc()); |
| | | productClass.setTaxRate(Double.valueOf(taxCode.getSl().replace("%",""))); |
| | | } |
| | | baseMapper.insert(productNew); |
| | | log.info("产品:{}新增成功",product.getString("itemNo")); |
| | | return; |
| | | } |
| | | log.info("产品:{}存在",product.getString("itemNo")); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | return R.ok(); |
| | | } |
| | | |
| | | private String getErpToken() { |
| | | JSONObject loginJson = new JSONObject(); |
| | | loginJson.put("username", "admin"); |
| | | loginJson.put("password", "Zimafold@2026"); |
| | | log.info("石煤机产品获取token入参:{}", loginJson.toJSONString()); |
| | | String loginResp = HttpUtil.post(smjErp + "/api/account/v1/login", loginJson.toJSONString()); |
| | | log.info("石煤机产品获取token回参:{}", loginResp); |
| | | JSONObject respJson = JSONObject.parseObject(loginResp); |
| | | if (respJson.getInteger("code") == 0) { |
| | | JSONObject dataJson = JSONObject.parseObject(respJson.getString("data")); |
| | | redisTemplate.opsForValue().set("SMJ_ERP_TOEKN",dataJson.getString("token")); |
| | | log.info("石煤机erp token为:{}",dataJson.getString("token")); |
| | | return dataJson.getString("token"); |
| | | } |
| | | return ""; |
| | | } |
| | | } |