|
|
@@ -0,0 +1,286 @@
|
|
|
+package com.haha.service.impl;
|
|
|
+
|
|
|
+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.haha.common.enums.ActivityStatusEnum;
|
|
|
+import com.haha.common.enums.ActivityTypeEnum;
|
|
|
+import com.haha.common.enums.ApplyScopeEnum;
|
|
|
+import com.haha.common.exception.BusinessException;
|
|
|
+import com.haha.common.vo.StatusLabel;
|
|
|
+import com.haha.entity.ActivityProduct;
|
|
|
+import com.haha.entity.ActivityShop;
|
|
|
+import com.haha.entity.MarketingActivity;
|
|
|
+import com.haha.entity.dto.ActivityCreateDTO;
|
|
|
+import com.haha.entity.dto.ActivityQueryDTO;
|
|
|
+import com.haha.entity.dto.ActivityUpdateDTO;
|
|
|
+import com.haha.mapper.ActivityProductMapper;
|
|
|
+import com.haha.mapper.ActivityShopMapper;
|
|
|
+import com.haha.mapper.MarketingActivityMapper;
|
|
|
+import com.haha.service.MarketingActivityService;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+@RequiredArgsConstructor
|
|
|
+public class MarketingActivityServiceImpl extends ServiceImpl<MarketingActivityMapper, MarketingActivity> implements MarketingActivityService {
|
|
|
+
|
|
|
+ private final MarketingActivityMapper activityMapper;
|
|
|
+ private final ActivityShopMapper activityShopMapper;
|
|
|
+ private final ActivityProductMapper activityProductMapper;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public IPage<MarketingActivity> getPage(ActivityQueryDTO queryDTO) {
|
|
|
+ queryDTO.validate();
|
|
|
+ Page<MarketingActivity> page = new Page<>(queryDTO.getPage(), queryDTO.getPageSize());
|
|
|
+
|
|
|
+ LambdaQueryWrapper<MarketingActivity> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ wrapper.like(StringUtils.hasText(queryDTO.getActivityName()), MarketingActivity::getActivityName, queryDTO.getActivityName());
|
|
|
+ wrapper.eq(queryDTO.getActivityType() != null, MarketingActivity::getActivityType, queryDTO.getActivityType());
|
|
|
+ wrapper.eq(queryDTO.getStatus() != null, MarketingActivity::getStatus, queryDTO.getStatus());
|
|
|
+ wrapper.eq(queryDTO.getCreatorId() != null, MarketingActivity::getCreatorId, queryDTO.getCreatorId());
|
|
|
+ wrapper.ge(queryDTO.getStartTimeBegin() != null, MarketingActivity::getStartTime, queryDTO.getStartTimeBegin());
|
|
|
+ wrapper.le(queryDTO.getStartTimeEnd() != null, MarketingActivity::getStartTime, queryDTO.getStartTimeEnd());
|
|
|
+ wrapper.eq(MarketingActivity::getDeleted, 0);
|
|
|
+ wrapper.orderByDesc(MarketingActivity::getCreateTime);
|
|
|
+
|
|
|
+ IPage<MarketingActivity> result = this.page(page, wrapper);
|
|
|
+ result.getRecords().forEach(this::fillLabels);
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public MarketingActivity getDetail(Long id) {
|
|
|
+ MarketingActivity activity = this.getById(id);
|
|
|
+ if (activity == null || activity.getDeleted() == 1) {
|
|
|
+ throw new BusinessException(404, "活动不存在");
|
|
|
+ }
|
|
|
+ fillLabels(activity);
|
|
|
+ return activity;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public MarketingActivity create(ActivityCreateDTO dto, Long creatorId, String creatorName) {
|
|
|
+ MarketingActivity activity = new MarketingActivity();
|
|
|
+ activity.setActivityName(dto.getActivityName());
|
|
|
+ activity.setActivityType(dto.getActivityType());
|
|
|
+ activity.setActivityDesc(dto.getActivityDesc());
|
|
|
+ activity.setStartTime(dto.getStartTime());
|
|
|
+ activity.setEndTime(dto.getEndTime());
|
|
|
+ activity.setStatus(ActivityStatusEnum.DRAFT.getCode());
|
|
|
+ activity.setDiscountValue(dto.getDiscountValue());
|
|
|
+ activity.setMinAmount(dto.getMinAmount());
|
|
|
+ activity.setMaxDiscount(dto.getMaxDiscount());
|
|
|
+ activity.setApplyScope(dto.getApplyScope());
|
|
|
+ activity.setProductScope(dto.getProductScope());
|
|
|
+ activity.setTotalBudget(dto.getTotalBudget());
|
|
|
+ activity.setUsedBudget(BigDecimal.ZERO);
|
|
|
+ activity.setCreatorId(creatorId);
|
|
|
+ activity.setCreatorName(creatorName);
|
|
|
+ activity.setDeleted(0);
|
|
|
+
|
|
|
+ this.save(activity);
|
|
|
+
|
|
|
+ saveActivityShops(activity.getId(), dto.getShopIds(), dto.getApplyScope());
|
|
|
+ saveActivityProducts(activity.getId(), dto.getProductIds(), dto.getProductScope());
|
|
|
+
|
|
|
+ log.info("创建营销活动成功: id={}, name={}", activity.getId(), activity.getActivityName());
|
|
|
+ return activity;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public MarketingActivity update(ActivityUpdateDTO dto) {
|
|
|
+ MarketingActivity activity = this.getById(dto.getId());
|
|
|
+ if (activity == null || activity.getDeleted() == 1) {
|
|
|
+ throw new BusinessException(404, "活动不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!ActivityStatusEnum.canEdit(activity.getStatus())) {
|
|
|
+ throw new BusinessException(400, "当前状态不允许编辑");
|
|
|
+ }
|
|
|
+
|
|
|
+ activity.setActivityName(dto.getActivityName());
|
|
|
+ activity.setActivityDesc(dto.getActivityDesc());
|
|
|
+ activity.setStartTime(dto.getStartTime());
|
|
|
+ activity.setEndTime(dto.getEndTime());
|
|
|
+ activity.setDiscountValue(dto.getDiscountValue());
|
|
|
+ activity.setMinAmount(dto.getMinAmount());
|
|
|
+ activity.setMaxDiscount(dto.getMaxDiscount());
|
|
|
+ activity.setApplyScope(dto.getApplyScope());
|
|
|
+ activity.setProductScope(dto.getProductScope());
|
|
|
+ activity.setTotalBudget(dto.getTotalBudget());
|
|
|
+
|
|
|
+ this.updateById(activity);
|
|
|
+
|
|
|
+ activityShopMapper.deleteByActivityId(activity.getId());
|
|
|
+ activityProductMapper.deleteByActivityId(activity.getId());
|
|
|
+ saveActivityShops(activity.getId(), dto.getShopIds(), dto.getApplyScope());
|
|
|
+ saveActivityProducts(activity.getId(), dto.getProductIds(), dto.getProductScope());
|
|
|
+
|
|
|
+ log.info("更新营销活动成功: id={}", activity.getId());
|
|
|
+ return activity;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public boolean publish(Long id) {
|
|
|
+ MarketingActivity activity = this.getById(id);
|
|
|
+ if (activity == null || activity.getDeleted() == 1) {
|
|
|
+ throw new BusinessException(404, "活动不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!ActivityStatusEnum.canPublish(activity.getStatus())) {
|
|
|
+ throw new BusinessException(400, "当前状态不允许发布");
|
|
|
+ }
|
|
|
+
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
+ int newStatus = (now.isAfter(activity.getStartTime()) && now.isBefore(activity.getEndTime()))
|
|
|
+ ? ActivityStatusEnum.ONGOING.getCode()
|
|
|
+ : ActivityStatusEnum.PUBLISHED.getCode();
|
|
|
+
|
|
|
+ boolean result = activityMapper.updateStatus(id, newStatus) > 0;
|
|
|
+
|
|
|
+ if (result) {
|
|
|
+ log.info("发布营销活动成功: id={}, status={}", id, newStatus);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public boolean pause(Long id) {
|
|
|
+ MarketingActivity activity = this.getById(id);
|
|
|
+ if (activity == null || activity.getDeleted() == 1) {
|
|
|
+ throw new BusinessException(404, "活动不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!ActivityStatusEnum.canPause(activity.getStatus())) {
|
|
|
+ throw new BusinessException(400, "当前状态不允许暂停");
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean result = activityMapper.updateStatus(id, ActivityStatusEnum.PAUSED.getCode()) > 0;
|
|
|
+
|
|
|
+ if (result) {
|
|
|
+ log.info("暂停营销活动成功: id={}", id);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public boolean resume(Long id) {
|
|
|
+ MarketingActivity activity = this.getById(id);
|
|
|
+ if (activity == null || activity.getDeleted() == 1) {
|
|
|
+ throw new BusinessException(404, "活动不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!ActivityStatusEnum.canResume(activity.getStatus())) {
|
|
|
+ throw new BusinessException(400, "当前状态不允许恢复");
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean result = activityMapper.updateStatus(id, ActivityStatusEnum.ONGOING.getCode()) > 0;
|
|
|
+
|
|
|
+ if (result) {
|
|
|
+ log.info("恢复营销活动成功: id={}", id);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public boolean deleteActivity(Long id) {
|
|
|
+ MarketingActivity activity = this.getById(id);
|
|
|
+ if (activity == null) {
|
|
|
+ throw new BusinessException(404, "活动不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!ActivityStatusEnum.canDelete(activity.getStatus())) {
|
|
|
+ throw new BusinessException(400, "当前状态不允许删除");
|
|
|
+ }
|
|
|
+
|
|
|
+ activity.setDeleted(1);
|
|
|
+ boolean result = this.updateById(activity);
|
|
|
+
|
|
|
+ if (result) {
|
|
|
+ activityShopMapper.deleteByActivityId(id);
|
|
|
+ activityProductMapper.deleteByActivityId(id);
|
|
|
+ log.info("删除营销活动成功: id={}", id);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<MarketingActivity> getOngoingActivities() {
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
+ return activityMapper.selectOngoingActivities(ActivityStatusEnum.ONGOING.getCode(), now);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<Long> getActivityShopIds(Long activityId) {
|
|
|
+ return activityShopMapper.selectShopIdsByActivityId(activityId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<Long> getActivityProductIds(Long activityId) {
|
|
|
+ return activityProductMapper.selectProductIdsByActivityId(activityId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map<String, Object> getStatistics(Long activityId) {
|
|
|
+ Map<String, Object> stats = new HashMap<>();
|
|
|
+ stats.put("totalActivities", activityMapper.countTotal());
|
|
|
+ stats.put("ongoingActivities", activityMapper.countByStatus(ActivityStatusEnum.ONGOING.getCode()));
|
|
|
+ stats.put("pausedActivities", activityMapper.countByStatus(ActivityStatusEnum.PAUSED.getCode()));
|
|
|
+ return stats;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void saveActivityShops(Long activityId, List<Long> shopIds, Integer applyScope) {
|
|
|
+ if (applyScope != null && applyScope == ApplyScopeEnum.SPECIFIED_SHOP.getCode()
|
|
|
+ && shopIds != null && !shopIds.isEmpty()) {
|
|
|
+ for (Long shopId : shopIds) {
|
|
|
+ ActivityShop activityShop = new ActivityShop();
|
|
|
+ activityShop.setActivityId(activityId);
|
|
|
+ activityShop.setShopId(shopId);
|
|
|
+ activityShopMapper.insert(activityShop);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void saveActivityProducts(Long activityId, List<Long> productIds, Integer productScope) {
|
|
|
+ if (productScope != null && productScope == 2
|
|
|
+ && productIds != null && !productIds.isEmpty()) {
|
|
|
+ for (Long productId : productIds) {
|
|
|
+ ActivityProduct activityProduct = new ActivityProduct();
|
|
|
+ activityProduct.setActivityId(activityId);
|
|
|
+ activityProduct.setProductId(productId);
|
|
|
+ activityProductMapper.insert(activityProduct);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void fillLabels(MarketingActivity activity) {
|
|
|
+ StatusLabel statusLabel = ActivityStatusEnum.getLabelByCode(activity.getStatus());
|
|
|
+ activity.setStatusLabel(statusLabel.getLabel());
|
|
|
+ activity.setStatusColor(statusLabel.getColor());
|
|
|
+
|
|
|
+ StatusLabel typeLabel = ActivityTypeEnum.getLabelByCode(activity.getActivityType());
|
|
|
+ activity.setTypeLabel(typeLabel.getLabel());
|
|
|
+
|
|
|
+ StatusLabel applyScopeLabel = ApplyScopeEnum.getLabelByCode(activity.getApplyScope());
|
|
|
+ activity.setApplyScopeLabel(applyScopeLabel.getLabel());
|
|
|
+ }
|
|
|
+}
|