|
|
@@ -0,0 +1,279 @@
|
|
|
+package shop.alien.store.service.impl;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
+import shop.alien.entity.store.SportsEquipmentFacility;
|
|
|
+import shop.alien.entity.store.SportsFacilityArea;
|
|
|
+import shop.alien.entity.store.StoreImg;
|
|
|
+import shop.alien.mapper.SportsEquipmentFacilityMapper;
|
|
|
+import shop.alien.mapper.SportsFacilityAreaMapper;
|
|
|
+import shop.alien.mapper.StoreImgMapper;
|
|
|
+import shop.alien.store.service.SportsFacilityAreaService;
|
|
|
+
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 运动设施区域服务实现类
|
|
|
+ *
|
|
|
+ * @author assistant
|
|
|
+ * @since 2025-12-19
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+@RequiredArgsConstructor
|
|
|
+@Transactional(rollbackFor = Exception.class)
|
|
|
+public class SportsFacilityAreaServiceImpl extends ServiceImpl<SportsFacilityAreaMapper, SportsFacilityArea>
|
|
|
+ implements SportsFacilityAreaService {
|
|
|
+
|
|
|
+ private final SportsFacilityAreaMapper areaMapper;
|
|
|
+ private final SportsEquipmentFacilityMapper facilityMapper;
|
|
|
+ private final StoreImgMapper storeImgMapper;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 运动器材设施图片类型
|
|
|
+ */
|
|
|
+ private static final Integer IMG_TYPE_SPORTS_EQUIPMENT = 28;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除标志:未删除
|
|
|
+ */
|
|
|
+ private static final int DELETE_FLAG_NOT_DELETED = 0;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除标志:已删除
|
|
|
+ */
|
|
|
+ private static final int DELETE_FLAG_DELETED = 1;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 默认排序号
|
|
|
+ */
|
|
|
+ private static final int DEFAULT_SORT_ORDER = 0;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Integer createArea(Integer storeId, String areaName) {
|
|
|
+ log.info("新建区域,storeId={},areaName={}", storeId, areaName);
|
|
|
+
|
|
|
+ // 1. 参数验证
|
|
|
+ if (storeId == null || storeId <= 0) {
|
|
|
+ log.warn("新建区域失败,门店ID无效:{}", storeId);
|
|
|
+ throw new IllegalArgumentException("门店ID不能为空且必须大于0");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(areaName)) {
|
|
|
+ log.warn("新建区域失败,区域名称为空");
|
|
|
+ throw new IllegalArgumentException("区域名称不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 区域名称长度验证(限10字)
|
|
|
+ String trimmedAreaName = areaName.trim();
|
|
|
+ if (trimmedAreaName.length() > 10) {
|
|
|
+ log.warn("新建区域失败,区域名称长度超过10字:{},长度:{}", trimmedAreaName, trimmedAreaName.length());
|
|
|
+ throw new IllegalArgumentException("区域名称长度不能超过10个字符");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 检查该门店下是否已存在相同名称的区域(未删除的)
|
|
|
+ LambdaQueryWrapper<SportsFacilityArea> checkWrapper = new LambdaQueryWrapper<>();
|
|
|
+ checkWrapper.eq(SportsFacilityArea::getStoreId, storeId)
|
|
|
+ .eq(SportsFacilityArea::getAreaName, trimmedAreaName)
|
|
|
+ .eq(SportsFacilityArea::getDeleteFlag, DELETE_FLAG_NOT_DELETED);
|
|
|
+ long existCount = this.count(checkWrapper);
|
|
|
+ if (existCount > 0) {
|
|
|
+ log.warn("新建区域失败,该门店下已存在相同名称的区域:storeId={},areaName={}", storeId, trimmedAreaName);
|
|
|
+ throw new IllegalArgumentException("该门店下已存在相同名称的区域");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 创建区域记录
|
|
|
+ SportsFacilityArea area = new SportsFacilityArea();
|
|
|
+ area.setStoreId(storeId);
|
|
|
+ area.setAreaName(trimmedAreaName);
|
|
|
+ area.setSortOrder(DEFAULT_SORT_ORDER);
|
|
|
+ area.setDeleteFlag(DELETE_FLAG_NOT_DELETED);
|
|
|
+
|
|
|
+ // 5. 保存到数据库
|
|
|
+ boolean saveResult = this.save(area);
|
|
|
+ if (!saveResult) {
|
|
|
+ log.error("新建区域失败,保存数据库失败:storeId={},areaName={}", storeId, trimmedAreaName);
|
|
|
+ throw new RuntimeException("新建区域失败,保存数据库失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("新建区域成功,storeId={},areaName={},区域ID={}", storeId, trimmedAreaName, area.getId());
|
|
|
+ return area.getId();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<SportsFacilityArea> listAreas(Integer storeId) {
|
|
|
+ log.info("查询区域列表,storeId={}", storeId);
|
|
|
+
|
|
|
+ // 参数验证
|
|
|
+ if (storeId == null || storeId <= 0) {
|
|
|
+ log.warn("查询区域列表失败,门店ID无效:{}", storeId);
|
|
|
+ throw new IllegalArgumentException("门店ID不能为空且必须大于0");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询该门店下的所有未删除区域,按排序号升序,相同排序号按创建时间降序
|
|
|
+ LambdaQueryWrapper<SportsFacilityArea> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
+ queryWrapper.eq(SportsFacilityArea::getStoreId, storeId)
|
|
|
+ .eq(SportsFacilityArea::getDeleteFlag, DELETE_FLAG_NOT_DELETED)
|
|
|
+ .orderByAsc(SportsFacilityArea::getSortOrder)
|
|
|
+ .orderByDesc(SportsFacilityArea::getCreatedTime);
|
|
|
+
|
|
|
+ List<SportsFacilityArea> areaList = this.list(queryWrapper);
|
|
|
+ log.info("查询区域列表成功,storeId={},区域数量:{}", storeId, areaList.size());
|
|
|
+ return areaList;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean updateArea(Integer areaId, String areaName, Integer sortOrder) {
|
|
|
+ log.info("更新区域,areaId={},areaName={},sortOrder={}", areaId, areaName, sortOrder);
|
|
|
+
|
|
|
+ // 参数验证
|
|
|
+ if (areaId == null || areaId <= 0) {
|
|
|
+ log.warn("更新区域失败,区域ID无效:{}", areaId);
|
|
|
+ throw new IllegalArgumentException("区域ID不能为空且必须大于0");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询区域是否存在
|
|
|
+ SportsFacilityArea existingArea = this.getById(areaId);
|
|
|
+ if (existingArea == null || existingArea.getDeleteFlag() == DELETE_FLAG_DELETED) {
|
|
|
+ log.warn("更新区域失败,区域不存在或已删除:areaId={}", areaId);
|
|
|
+ throw new IllegalArgumentException("区域不存在或已删除");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建更新条件
|
|
|
+ LambdaUpdateWrapper<SportsFacilityArea> updateWrapper = new LambdaUpdateWrapper<>();
|
|
|
+ updateWrapper.eq(SportsFacilityArea::getId, areaId);
|
|
|
+
|
|
|
+ // 更新区域名称
|
|
|
+ if (StringUtils.isNotBlank(areaName)) {
|
|
|
+ String trimmedAreaName = areaName.trim();
|
|
|
+ // 验证长度
|
|
|
+ if (trimmedAreaName.length() > 10) {
|
|
|
+ log.warn("更新区域失败,区域名称长度超过10字:{},长度:{}", trimmedAreaName, trimmedAreaName.length());
|
|
|
+ throw new IllegalArgumentException("区域名称长度不能超过10个字符");
|
|
|
+ }
|
|
|
+ // 检查是否与其他区域重复(排除自己)
|
|
|
+ LambdaQueryWrapper<SportsFacilityArea> checkWrapper = new LambdaQueryWrapper<>();
|
|
|
+ checkWrapper.eq(SportsFacilityArea::getStoreId, existingArea.getStoreId())
|
|
|
+ .eq(SportsFacilityArea::getAreaName, trimmedAreaName)
|
|
|
+ .eq(SportsFacilityArea::getDeleteFlag, DELETE_FLAG_NOT_DELETED)
|
|
|
+ .ne(SportsFacilityArea::getId, areaId);
|
|
|
+ long existCount = this.count(checkWrapper);
|
|
|
+ if (existCount > 0) {
|
|
|
+ log.warn("更新区域失败,该门店下已存在相同名称的区域:storeId={},areaName={}", existingArea.getStoreId(), trimmedAreaName);
|
|
|
+ throw new IllegalArgumentException("该门店下已存在相同名称的区域");
|
|
|
+ }
|
|
|
+ updateWrapper.set(SportsFacilityArea::getAreaName, trimmedAreaName);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新排序号
|
|
|
+ if (sortOrder != null) {
|
|
|
+ updateWrapper.set(SportsFacilityArea::getSortOrder, sortOrder);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 执行更新
|
|
|
+ boolean updateResult = this.update(updateWrapper);
|
|
|
+ log.info("更新区域{},areaId={}", updateResult ? "成功" : "失败", areaId);
|
|
|
+ return updateResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean deleteArea(Integer areaId) {
|
|
|
+ log.info("删除区域,areaId={}", areaId);
|
|
|
+
|
|
|
+ // 参数验证
|
|
|
+ if (areaId == null || areaId <= 0) {
|
|
|
+ log.warn("删除区域失败,区域ID无效:{}", areaId);
|
|
|
+ throw new IllegalArgumentException("区域ID不能为空且必须大于0");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询区域是否存在
|
|
|
+ SportsFacilityArea area = this.getById(areaId);
|
|
|
+ if (area == null || area.getDeleteFlag() == DELETE_FLAG_DELETED) {
|
|
|
+ log.warn("删除区域失败,区域不存在或已删除:areaId={}", areaId);
|
|
|
+ throw new IllegalArgumentException("区域不存在或已删除");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 1. 逻辑删除区域
|
|
|
+ LambdaUpdateWrapper<SportsFacilityArea> areaUpdateWrapper = new LambdaUpdateWrapper<>();
|
|
|
+ areaUpdateWrapper.eq(SportsFacilityArea::getId, areaId)
|
|
|
+ .set(SportsFacilityArea::getDeleteFlag, DELETE_FLAG_DELETED);
|
|
|
+ boolean deleteAreaResult = this.update(areaUpdateWrapper);
|
|
|
+
|
|
|
+ // 2. 逻辑删除该区域下的所有设施
|
|
|
+ LambdaUpdateWrapper<SportsEquipmentFacility> facilityUpdateWrapper = new LambdaUpdateWrapper<>();
|
|
|
+ facilityUpdateWrapper.eq(SportsEquipmentFacility::getAreaId, areaId)
|
|
|
+ .set(SportsEquipmentFacility::getDeleteFlag, DELETE_FLAG_DELETED);
|
|
|
+ int deletedFacilityCount = facilityMapper.update(null, facilityUpdateWrapper);
|
|
|
+
|
|
|
+ // 3. 物理删除该区域下的所有实景图片
|
|
|
+ LambdaQueryWrapper<StoreImg> deleteImageWrapper = new LambdaQueryWrapper<>();
|
|
|
+ deleteImageWrapper.eq(StoreImg::getStoreId, area.getStoreId())
|
|
|
+ .eq(StoreImg::getBusinessId, areaId)
|
|
|
+ .eq(StoreImg::getImgType, IMG_TYPE_SPORTS_EQUIPMENT);
|
|
|
+ int deletedImageCount = storeImgMapper.delete(deleteImageWrapper);
|
|
|
+
|
|
|
+ log.info("删除区域{},areaId={},同时删除了{}个设施和{}张图片",
|
|
|
+ deleteAreaResult ? "成功" : "失败", areaId, deletedFacilityCount, deletedImageCount);
|
|
|
+ return deleteAreaResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean batchDeleteAreas(Integer storeId, List<Integer> areaIds) {
|
|
|
+ log.info("批量删除区域,storeId={},areaIds={}", storeId, areaIds);
|
|
|
+
|
|
|
+ // 参数验证
|
|
|
+ if (storeId == null || storeId <= 0) {
|
|
|
+ log.warn("批量删除区域失败,门店ID无效:{}", storeId);
|
|
|
+ throw new IllegalArgumentException("门店ID不能为空且必须大于0");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (CollectionUtils.isEmpty(areaIds)) {
|
|
|
+ log.warn("批量删除区域失败,区域ID列表为空");
|
|
|
+ throw new IllegalArgumentException("区域ID列表不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证所有区域都属于该门店
|
|
|
+ LambdaQueryWrapper<SportsFacilityArea> checkWrapper = new LambdaQueryWrapper<>();
|
|
|
+ checkWrapper.eq(SportsFacilityArea::getStoreId, storeId)
|
|
|
+ .in(SportsFacilityArea::getId, areaIds)
|
|
|
+ .eq(SportsFacilityArea::getDeleteFlag, DELETE_FLAG_NOT_DELETED);
|
|
|
+ long validCount = this.count(checkWrapper);
|
|
|
+ if (validCount != areaIds.size()) {
|
|
|
+ log.warn("批量删除区域失败,部分区域不存在或不属于该门店:storeId={},areaIds={},有效数量={}", storeId, areaIds, validCount);
|
|
|
+ throw new IllegalArgumentException("部分区域不存在或不属于该门店");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 1. 批量逻辑删除区域
|
|
|
+ LambdaUpdateWrapper<SportsFacilityArea> areaUpdateWrapper = new LambdaUpdateWrapper<>();
|
|
|
+ areaUpdateWrapper.eq(SportsFacilityArea::getStoreId, storeId)
|
|
|
+ .in(SportsFacilityArea::getId, areaIds)
|
|
|
+ .set(SportsFacilityArea::getDeleteFlag, DELETE_FLAG_DELETED);
|
|
|
+ boolean deleteAreaResult = this.update(areaUpdateWrapper);
|
|
|
+
|
|
|
+ // 2. 批量逻辑删除这些区域下的所有设施
|
|
|
+ LambdaUpdateWrapper<SportsEquipmentFacility> facilityUpdateWrapper = new LambdaUpdateWrapper<>();
|
|
|
+ facilityUpdateWrapper.eq(SportsEquipmentFacility::getStoreId, storeId)
|
|
|
+ .in(SportsEquipmentFacility::getAreaId, areaIds)
|
|
|
+ .set(SportsEquipmentFacility::getDeleteFlag, DELETE_FLAG_DELETED);
|
|
|
+ int deletedFacilityCount = facilityMapper.update(null, facilityUpdateWrapper);
|
|
|
+
|
|
|
+ // 3. 批量物理删除这些区域下的所有实景图片
|
|
|
+ LambdaQueryWrapper<StoreImg> deleteImageWrapper = new LambdaQueryWrapper<>();
|
|
|
+ deleteImageWrapper.eq(StoreImg::getStoreId, storeId)
|
|
|
+ .in(StoreImg::getBusinessId, areaIds)
|
|
|
+ .eq(StoreImg::getImgType, IMG_TYPE_SPORTS_EQUIPMENT);
|
|
|
+ int deletedImageCount = storeImgMapper.delete(deleteImageWrapper);
|
|
|
+
|
|
|
+ log.info("批量删除区域{},storeId={},区域数量={},同时删除了{}个设施和{}张图片",
|
|
|
+ deleteAreaResult ? "成功" : "失败", storeId, areaIds.size(), deletedFacilityCount, deletedImageCount);
|
|
|
+ return deleteAreaResult;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|