|  |  | 
 |  |  | import com.mzl.flower.config.security.SecurityUtils; | 
 |  |  | import com.mzl.flower.constant.Constants; | 
 |  |  | import com.mzl.flower.dto.request.flower.*; | 
 |  |  | import com.mzl.flower.dto.request.flower.FlowerTagMultipleDTO; | 
 |  |  | import com.mzl.flower.dto.response.flower.*; | 
 |  |  | import com.mzl.flower.entity.FlowerDeleteDO; | 
 |  |  | import com.mzl.flower.entity.customer.Collect; | 
 |  |  | import com.mzl.flower.entity.customer.Customer; | 
 |  |  | import com.mzl.flower.entity.flower.*; | 
 |  |  | import com.mzl.flower.entity.menber.Member; | 
 |  |  | import com.mzl.flower.entity.payment.Cart; | 
 |  |  | import com.mzl.flower.entity.payment.Order; | 
 |  |  | import com.mzl.flower.entity.payment.OrderItem; | 
 |  |  | 
 |  |  | import com.mzl.flower.mapper.supplier.SupplierTypeMapper; | 
 |  |  | import com.mzl.flower.service.BaseService; | 
 |  |  | import com.mzl.flower.service.customer.BrowseService; | 
 |  |  | import com.mzl.flower.service.payment.RedisLockService; | 
 |  |  | import io.micrometer.core.instrument.util.StringUtils; | 
 |  |  | import lombok.extern.slf4j.Slf4j; | 
 |  |  | import org.springframework.beans.BeanUtils; | 
 |  |  | 
 |  |  | import org.springframework.scheduling.annotation.Async; | 
 |  |  | import org.springframework.stereotype.Service; | 
 |  |  | import org.springframework.transaction.annotation.Transactional; | 
 |  |  | import org.springframework.util.CollectionUtils; | 
 |  |  |  | 
 |  |  | import java.math.BigDecimal; | 
 |  |  | import java.math.RoundingMode; | 
 |  |  | import java.time.LocalDate; | 
 |  |  | import java.time.LocalDateTime; | 
 |  |  | import java.util.ArrayList; | 
 |  |  | import java.util.List; | 
 |  |  | import java.util.Map; | 
 |  |  | import java.util.*; | 
 |  |  | import java.util.concurrent.atomic.AtomicInteger; | 
 |  |  | import java.util.stream.Collectors; | 
 |  |  |  | 
 |  |  | @Slf4j | 
 |  |  | @Service | 
 |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private OrderItemMapper orderItemMapper; | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private RedisLockService lockService; | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  |     private FlowerDeleteService flowerDeleteService; | 
 |  |  |  | 
 |  |  |     private static final String FLOWER_KEY="com:mzl:flower:service:flower:%s:%s"; | 
 |  |  |  | 
 |  |  |     @Async | 
 |  |  |     public synchronized void updateFlowerSales(Order order){ | 
 |  |  |         List<OrderItem> items = orderItemMapper.selectList(new QueryWrapper<OrderItem>() | 
 |  |  | 
 |  |  |     public synchronized void updateCategoryInfo(Long category){ | 
 |  |  |         flowerMapper.updateFlowerCategoryInfo(category); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Async | 
 |  |  |     public  void updateFlowTypeRank(Long id,Long category,String level){ | 
 |  |  |  | 
 |  |  |         Flower flower =null; | 
 |  |  |         // 如果 id 不为空,则 category 和 level 可以为空 | 
 |  |  |         if (Objects.nonNull(id)) { | 
 |  |  |             flower = flowerMapper.selectById(id); | 
 |  |  |             if (flower == null) { | 
 |  |  |                 throw new IllegalArgumentException("Flower not found for ID: " + id); | 
 |  |  |             } | 
 |  |  |             category = flower.getCategory();  // 使用从数据库中检索到的 category | 
 |  |  |             level = flower.getLevel();        // 使用从数据库中检索到的 level | 
 |  |  |         } else { | 
 |  |  |             // 如果 id 为空,则 category 和 level 必须提供 | 
 |  |  |             if (Objects.isNull(category) || StringUtils.isEmpty(level)) { | 
 |  |  |                 throw new IllegalArgumentException("Category and level must be provided when ID is null"); | 
 |  |  |             } | 
 |  |  |             flower=new Flower(); | 
 |  |  |             flower.setCategory(category); | 
 |  |  |             flower.setLevel(level); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         String key=String.format(FLOWER_KEY, flower.getCategory(),flower.getLevel()); | 
 |  |  |  | 
 |  |  |         boolean lock = lockService.getObjectLock(key, ""); | 
 |  |  |         if(!lock){ | 
 |  |  |             return; | 
 |  |  |         } | 
 |  |  |         try{ | 
 |  |  |  | 
 |  |  |             flowerMapper.updateTypeRankNull(flower.getCategory(),flower.getLevel()); | 
 |  |  |  | 
 |  |  |             QueryWrapper<Flower> queryWrapper=new QueryWrapper<>(); | 
 |  |  |             queryWrapper.lambda().eq(Flower::getDeleted,false) | 
 |  |  |                     .eq(Objects.nonNull(flower.getCategory()),Flower::getCategory,flower.getCategory()) | 
 |  |  |                     .eq(StringUtils.isNotEmpty(flower.getLevel()),Flower::getLevel,flower.getLevel()) | 
 |  |  |                     .eq(Flower::getStatus,"UP") | 
 |  |  |                     .orderByAsc(Flower::getPrice); | 
 |  |  |             final List<Flower> flowerList = flowerMapper.selectList(queryWrapper); | 
 |  |  |  | 
 |  |  |             AtomicInteger index = new AtomicInteger(1); | 
 |  |  |             flowerList.forEach(f -> f.setTypeRank(index.getAndIncrement())); | 
 |  |  |  | 
 |  |  |             if(!CollectionUtils.isEmpty(flowerList)){ | 
 |  |  |                 flowerMapper.updateBatchTypeRank(flowerList); | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         }finally { | 
 |  |  |             lockService.releaseObjectLock(key,""); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |  | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 花农(供应商)提交商品 | 
 |  |  | 
 |  |  |             paramService.insertTableData(fc.getParamId(), g.getId(), params); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         // 更新商品价格在这里的分类 | 
 |  |  |         updateFlowTypeRank(null,g.getCategory(),g.getLevel()); | 
 |  |  |         return g.getId(); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | 
 |  |  |         } else { | 
 |  |  |             g.setPrice(dto.getPrice()); | 
 |  |  |             g.setStock(dto.getStock()); | 
 |  |  |             g.setLimited(dto.getLimited()); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         g.update(SecurityUtils.getUserId()); | 
 |  |  | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         // 更新商品价格在这里的分类 | 
 |  |  |         updateFlowTypeRank(null,g.getCategory(),g.getLevel()); | 
 |  |  |  | 
 |  |  |         return g.getId(); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     public Long editFlowerAdmin(FlowerUpdateAdminDTO dto){ | 
 |  |  |         Flower g = flowerMapper.selectById(dto.getId()); | 
 |  |  |         g.setSales(dto.getSales()); | 
 |  |  |         if (!org.springframework.util.StringUtils.isEmpty(dto.getLimited())) { | 
 |  |  |             if (g.getStock() == 0 || org.springframework.util.StringUtils.isEmpty(g.getStock())) { | 
 |  |  |                 throw new ValidationException("库存为0或者空时不能修改限购数量"); | 
 |  |  |             } | 
 |  |  |             if(g.getStock()<dto.getLimited()){ | 
 |  |  |                 throw new ValidationException("限购数量不能大于库存"); | 
 |  |  |             } | 
 |  |  |             g.setLimited(dto.getLimited()); | 
 |  |  |         }else{ | 
 |  |  |             g.setLimited(null); | 
 |  |  |         } | 
 |  |  |         g.update(SecurityUtils.getUserId()); | 
 |  |  |         flowerMapper.updateById(g); | 
 |  |  |  | 
 |  |  | 
 |  |  |             dto.setZoneName(String.join(",", zoneNameLs)); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         //TODO 合伙人加价列表 | 
 |  |  |  | 
 |  |  |         return dto; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | 
 |  |  |             //清除购物车商品 | 
 |  |  |             cartMapper.delete(new QueryWrapper<Cart>().eq("flower_id", id)); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         //更新排名 | 
 |  |  |         updateFlowTypeRank(null,f.getCategory(),f.getLevel()); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     public void deleteFlower(Long id){ | 
 |  |  |  | 
 |  |  |         final Flower flower = flowerMapper.selectById(id); | 
 |  |  |         if(flower == null){ | 
 |  |  |             throw new ValidationException("商品未找到"); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         flowerMapper.deleteById(id); | 
 |  |  |  | 
 |  |  |         //清除购物车商品 | 
 |  |  |         cartMapper.delete(new QueryWrapper<Cart>().eq("flower_id", id)); | 
 |  |  |         // 更新商品价格在这里的分类 | 
 |  |  |         updateFlowTypeRank(null,flower.getCategory(),flower.getLevel()); | 
 |  |  |  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     public void restoreFlower(Long id){ | 
 |  |  | 
 |  |  |         } | 
 |  |  |         f.setPrice(dto.getPrice()); | 
 |  |  |         flowerMapper.updateById(f); | 
 |  |  |         // 更新商品价格在这里的分类 | 
 |  |  |         updateFlowTypeRank(null,f.getCategory(),f.getLevel()); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     public void editFlowerStock(FlowerStockDTO dto){ | 
 |  |  | 
 |  |  |         dto.setUserId(SecurityUtils.getUserId()); | 
 |  |  |         dto.setParamId(paramService.getParamIdByCategoryId(dto.getCategory())); | 
 |  |  |         List<FlowerShowListDTO> ls = flowerMapper.selectFlowerShowList(page, dto); | 
 |  |  |         if(ls != null && ls.size() > 0){ | 
 |  |  |             Long partnerId = getCurrentCustomerPartner(); | 
 |  |  |             for(FlowerShowListDTO s : ls){ | 
 |  |  |                 BigDecimal price = getFinalPrice(partnerId, s.getCategory() | 
 |  |  |                         , s.getId(), s.getPrice(), s.getLevel()); | 
 |  |  |                 s.setPrice(price); | 
 |  |  |                 s.setCollection(s.getCollectCount() > 0); | 
 |  |  |                 s.setShopnum(s.getShopnum() == null ? 0 : s.getShopnum()); | 
 |  |  |  | 
 |  |  |                 if(s.getSales() != null && s.getRealSales() != null){ | 
 |  |  |                     s.setSales(s.getSales() + s.getRealSales()); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |         prepareShowList(ls); | 
 |  |  |  | 
 |  |  |         page.setRecords(ls); | 
 |  |  |  | 
 |  |  | 
 |  |  |         if(pId == null){ | 
 |  |  |             pId = getCurrentCustomerPartner(); | 
 |  |  |         } | 
 |  |  |         Customer p = getCurrentCustomerWithoutCheck(); | 
 |  |  |         Long levelId = p == null ? null : p.getLevelId(); | 
 |  |  |         Member member = getMember(levelId); | 
 |  |  |  | 
 |  |  |         BigDecimal price = getFinalPrice(pId, dto.getCategory() | 
 |  |  |                 , s.getId(), dto.getPrice(), dto.getLevel()); | 
 |  |  |                 , dto.getId(), dto.getPrice(), dto.getLevel()); | 
 |  |  |         dto.setPrice(price); | 
 |  |  |         dto.setPriceMember(calculateMemberPrice(price, member)); | 
 |  |  |  | 
 |  |  |         String userId = SecurityUtils.getUserId(); | 
 |  |  |         if(StringUtils.isNotEmpty(userId)) { | 
 |  |  | 
 |  |  |  | 
 |  |  |     public Page<FlowerShowListDTO> myCollect(Page page, FlowerShowQueryDTO dto) { | 
 |  |  |         dto.setUserId(SecurityUtils.getUserId()); | 
 |  |  |         /*if (StringUtils.isNotEmpty(dto.getColumn())) { | 
 |  |  |             List<OrderItem> orders = new ArrayList<>(); | 
 |  |  |             OrderItem i = new OrderItem(); | 
 |  |  |             i.setColumn(dto.getColumn()); | 
 |  |  |             i.setAsc(dto.isAsc()); | 
 |  |  |             page.setOrders(orders); | 
 |  |  |         }*/ | 
 |  |  |         if (StringUtils.isNotEmpty(dto.getColumn())) { | 
 |  |  |             if(dto.getColumn().contains("sales") | 
 |  |  |                     || dto.getColumn().contains("stock")){ | 
 |  |  |                 dto.setColumn(dto.getColumn() + " desc"); | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         dto.setParamId(paramService.getParamIdByCategoryId(dto.getCategory())); | 
 |  |  |         List<FlowerShowListDTO> flowerShowListDTOS = flowerMapper.myCollect(page, dto); | 
 |  |  |         prepareShowList(flowerShowListDTOS); | 
 |  |  |  | 
 |  |  |         page.setRecords(flowerShowListDTOS); | 
 |  |  |         return page; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     private void prepareShowList(List<FlowerShowListDTO> ls){ | 
 |  |  |         if(ls != null && ls.size() > 0){ | 
 |  |  |             Customer p = getCurrentCustomerWithoutCheck(); | 
 |  |  |             Long partnerId = p == null ? null : p.getPartnerId(); | 
 |  |  |             Long levelId = p == null ? null : p.getLevelId(); | 
 |  |  |             Member member = getMember(levelId); | 
 |  |  |  | 
 |  |  |             for(FlowerShowListDTO s : ls){ | 
 |  |  |                 BigDecimal price = getFinalPrice(partnerId, s.getCategory() | 
 |  |  |                         , s.getId(), s.getPrice(), s.getLevel()); | 
 |  |  |                 s.setPrice(price); | 
 |  |  |                 s.setPriceMember(calculateMemberPrice(price, member)); | 
 |  |  |  | 
 |  |  |                 s.setCollection(s.getCollectCount() > 0); | 
 |  |  |                 s.setShopnum(s.getShopnum() == null ? 0 : s.getShopnum()); | 
 |  |  |  | 
 |  |  |                 if(s.getSales() != null && s.getRealSales() != null){ | 
 |  |  |                     s.setSales(s.getSales() + s.getRealSales()); | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     public Page<FlowerShowListDTO> myBrowseHistory(Page page, FlowerShowQueryDTO dto) { | 
 |  |  | 
 |  |  |         }*/ | 
 |  |  |         dto.setParamId(paramService.getParamIdByCategoryId(dto.getCategory())); | 
 |  |  |         List<FlowerShowListDTO> flowerShowListDTOS = flowerMapper.myBrowseHistory(page, dto); | 
 |  |  |         prepareShowList(flowerShowListDTOS); | 
 |  |  |  | 
 |  |  |         page.setRecords(flowerShowListDTOS); | 
 |  |  |         return page; | 
 |  |  |     } | 
 |  |  | 
 |  |  |         if(dto.getZoneId()!=null && dto.getZoneId().size()>0){//添加专区 | 
 |  |  |             for (Long zoneId : dto.getZoneId()) { | 
 |  |  |                 for(Long flowerId : dto.getIds()) { | 
 |  |  |                     FlowerZoneMap fzp = flowerZoneMapMapper.selectOne(new QueryWrapper<FlowerZoneMap>().eq("flower_id", flowerId).eq("zone_id", zoneId)); | 
 |  |  |                     FlowerZoneMap fzp = flowerZoneMapMapper.selectOne(new QueryWrapper<FlowerZoneMap>() | 
 |  |  |                             .eq("flower_id", flowerId).eq("zone_id", zoneId)); | 
 |  |  |                     if(fzp==null){ | 
 |  |  |                         fzp = new FlowerZoneMap(); | 
 |  |  |                         fzp.setFlowerId(flowerId); | 
 |  |  | 
 |  |  |  | 
 |  |  |         return page; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     public void clearInvalidHistory(String userId) { | 
 |  |  |  | 
 |  |  |         List<Long> ids = flowerMapper.searchInvalidHistory(userId); | 
 |  |  |         if(ids!=null && ids.size()>0){ | 
 |  |  |             browseService.deleteBatchIds(ids); | 
 |  |  |  | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Transactional | 
 |  |  |     public void deleteFlowerBatch(FlowerBatchDTO dto) { | 
 |  |  |         List<Flower> flowerList = flowerMapper.getDeletdFlowByIds(dto.getIds()); | 
 |  |  |         //物理删除 | 
 |  |  |         flowerMapper.deleteBatchPhysics(dto.getIds()); | 
 |  |  |         // 备份 | 
 |  |  |         if(!CollectionUtils.isEmpty(flowerList)){ | 
 |  |  |             backupFlower(flowerList); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Async | 
 |  |  |     public void backupFlower(List<Flower> flowerList) { | 
 |  |  |         // 备份 | 
 |  |  |         final List<Long> idList = flowerList.stream().map(flower -> flower.getId()).collect(Collectors.toList()); | 
 |  |  |         final List<FlowerDeleteDO> flowerDeleteList = flowerDeleteService.getBaseMapper().selectBatchIds(idList); | 
 |  |  |         // 遍历flowerList 根据ID查找 ,如果flowerDeleteList 存在,则放入到更新列表里面去,如果flowerDeleteList不存在,则添加到新增列表里面去 | 
 |  |  |  | 
 |  |  |         // 将查询到的 flowerDeleteList 的 ID 转为 Set 以便快速查找 | 
 |  |  |         Set<Long> existingIds = flowerDeleteList.stream() | 
 |  |  |                 .map(FlowerDeleteDO::getId) | 
 |  |  |                 .collect(Collectors.toSet()); | 
 |  |  |         // 使用 Stream 进行更新和插入分类 | 
 |  |  |         List<FlowerDeleteDO> updateList = flowerList.stream() | 
 |  |  |                 .filter(flower -> existingIds.contains(flower.getId())) // 过滤出已存在的记录 | 
 |  |  |                 .map(flower -> convertToFlowerDeleteDO(flower))         // 转换为 FlowerDeleteDO 对象 | 
 |  |  |                 .collect(Collectors.toList()); | 
 |  |  |  | 
 |  |  |         List<FlowerDeleteDO> insertList = flowerList.stream() | 
 |  |  |                 .filter(flower -> !existingIds.contains(flower.getId())) // 过滤出不存在的记录 | 
 |  |  |                 .map(flower -> convertToFlowerDeleteDO(flower))          // 转换为 FlowerDeleteDO 对象 | 
 |  |  |                 .collect(Collectors.toList()); | 
 |  |  |  | 
 |  |  |         // 批量执行更新和新增操作 | 
 |  |  |         if (!updateList.isEmpty()) { | 
 |  |  |             flowerDeleteService.updateBatchById(updateList); // 批量更新 | 
 |  |  |         } | 
 |  |  |         if (!insertList.isEmpty()) { | 
 |  |  |             flowerDeleteService.saveBatch(insertList); // 批量插入 | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @Transactional | 
 |  |  |     public void restoreFlowerBatch(FlowerBatchDTO dto) { | 
 |  |  |         flowerMapper.restoreFlowerBatch(dto.getIds()); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     // 方法用于将 Flower 转换为 FlowerDeleteDO | 
 |  |  |     private FlowerDeleteDO convertToFlowerDeleteDO(Flower flower) { | 
 |  |  |         FlowerDeleteDO flowerDeleteDO=new FlowerDeleteDO(); | 
 |  |  |         BeanUtils.copyProperties(flower,flowerDeleteDO); | 
 |  |  |         // 其他需要备份的字段... | 
 |  |  |         return flowerDeleteDO; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     public void setFlowersLimited(FlowerLimitedDTO dto) { | 
 |  |  |         List<Long> ids = dto.getIds(); | 
 |  |  |         if (ids == null || ids.size() == 0) { | 
 |  |  |             throw new ValidationException("请选择商品"); | 
 |  |  |         } | 
 |  |  |         for (Long id : ids) { | 
 |  |  |             Flower f = flowerMapper.selectById(id); | 
 |  |  |             if (!org.springframework.util.StringUtils.isEmpty(dto.getLimited())) { | 
 |  |  |                 if (f.getStock() == 0 || org.springframework.util.StringUtils.isEmpty(f.getStock())) { | 
 |  |  |                     throw new ValidationException("商品" + f.getName() + "库存为0或者空时不能修改限购数量"); | 
 |  |  |                 } | 
 |  |  |                 if(f.getStock()<dto.getLimited()){ | 
 |  |  |                     throw new ValidationException("商品" + f.getName() + "限购数量不能大于库存"); | 
 |  |  |                 } | 
 |  |  |                 f.setLimited(dto.getLimited()); | 
 |  |  |             }else{ | 
 |  |  |                 f.setLimited(null); | 
 |  |  |             } | 
 |  |  |             flowerMapper.updateById(f); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |  | 
 |  |  | } |