DispatchRuleServiceImpl.java 9.96 KB
package com.diligrp.rider.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.diligrp.rider.common.enums.DispatchConditionType;
import com.diligrp.rider.common.exception.BizException;
import com.diligrp.rider.dto.DispatchRuleTemplateSaveDTO;
import com.diligrp.rider.entity.DispatchRuleCondition;
import com.diligrp.rider.entity.DispatchRuleTemplate;
import com.diligrp.rider.mapper.DispatchRuleConditionMapper;
import com.diligrp.rider.mapper.DispatchRuleTemplateMapper;
import com.diligrp.rider.service.DispatchRuleService;
import com.diligrp.rider.vo.DispatchRuleTemplateVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class DispatchRuleServiceImpl implements DispatchRuleService {

    private final DispatchRuleTemplateMapper templateMapper;
    private final DispatchRuleConditionMapper conditionMapper;

    @Override
    public DispatchRuleTemplateVO getActiveRule(Long cityId) {
        DispatchRuleTemplate template = templateMapper.selectOne(
                new LambdaQueryWrapper<DispatchRuleTemplate>()
                        .eq(DispatchRuleTemplate::getCityId, cityId)
                        .eq(DispatchRuleTemplate::getIsActive, 1)
                        .last("LIMIT 1"));
        if (template == null) return null;
        return toVO(template);
    }

    @Override
    public List<DispatchRuleTemplateVO> listTemplates(Long cityId) {
        List<DispatchRuleTemplate> templates = templateMapper.selectList(
                new LambdaQueryWrapper<DispatchRuleTemplate>()
                        .eq(DispatchRuleTemplate::getCityId, cityId)
                        .orderByDesc(DispatchRuleTemplate::getIsActive)
                        .orderByDesc(DispatchRuleTemplate::getUpdateTime));
        List<DispatchRuleTemplateVO> result = new ArrayList<>();
        for (DispatchRuleTemplate t : templates) {
            result.add(toVO(t));
        }
        return result;
    }

    @Override
    @Transactional
    public Long saveTemplate(Long cityId, DispatchRuleTemplateSaveDTO dto) {
        if (cityId == null || cityId < 1) throw new BizException("城市ID不能为空");
        if (dto == null) throw new BizException("请求参数不能为空");
        if (dto.getName() == null || dto.getName().isBlank()) throw new BizException("模板名称不能为空");

        long now = System.currentTimeMillis() / 1000;
        DispatchRuleTemplate template;

        if (dto.getId() != null) {
            template = requireTemplate(cityId, dto.getId());
        } else {
            template = new DispatchRuleTemplate();
            template.setCityId(cityId);
            template.setIsActive(0);
            template.setCreateTime(now);
        }

        template.setName(dto.getName());
        template.setGrabEnabled(dto.getGrabEnabled() != null ? dto.getGrabEnabled() : 1);
        template.setGrabTimeout(dto.getGrabTimeout() != null ? dto.getGrabTimeout() : 30);
        template.setGrabScope(dto.getGrabScope() != null ? dto.getGrabScope() : 1);
        template.setGrabMaxPerRider(dto.getGrabMaxPerRider() != null ? dto.getGrabMaxPerRider() : 3);
        template.setAutoDispatch(dto.getAutoDispatch() != null ? dto.getAutoDispatch() : 1);
        template.setUpdateTime(now);

        if (dto.getId() != null) {
            templateMapper.updateById(template);
        } else {
            templateMapper.insert(template);
        }

        // 整体替换条件列表
        conditionMapper.delete(new LambdaQueryWrapper<DispatchRuleCondition>()
                .eq(DispatchRuleCondition::getTemplateId, template.getId()));

        if (dto.getConditions() != null) {
            for (DispatchRuleTemplateSaveDTO.ConditionItem item : dto.getConditions()) {
                DispatchConditionType type = DispatchConditionType.fromCode(item.getConditionType());
                if (type == null) continue;

                DispatchRuleCondition condition = new DispatchRuleCondition();
                condition.setTemplateId(template.getId());
                condition.setConditionType(item.getConditionType());
                condition.setEnabled(item.getEnabled() != null ? item.getEnabled() : 1);
                condition.setThresholdValue(item.getThresholdValue() != null ? item.getThresholdValue() : BigDecimal.ZERO);
                condition.setSortOrder(item.getSortOrder() != null ? item.getSortOrder() : 0);
                condition.setCreateTime(now);
                condition.setUpdateTime(now);
                conditionMapper.insert(condition);
            }
        }

        return template.getId();
    }

    @Override
    @Transactional
    public void activateTemplate(Long cityId, Long templateId) {
        DispatchRuleTemplate template = requireTemplate(cityId, templateId);

        templateMapper.update(null, new LambdaUpdateWrapper<DispatchRuleTemplate>()
                .eq(DispatchRuleTemplate::getCityId, template.getCityId())
                .set(DispatchRuleTemplate::getIsActive, 0));

        templateMapper.update(null, new LambdaUpdateWrapper<DispatchRuleTemplate>()
                .eq(DispatchRuleTemplate::getId, templateId)
                .eq(DispatchRuleTemplate::getCityId, cityId)
                .set(DispatchRuleTemplate::getIsActive, 1)
                .set(DispatchRuleTemplate::getUpdateTime, System.currentTimeMillis() / 1000));
    }

    @Override
    @Transactional
    public void deleteTemplate(Long cityId, Long templateId) {
        DispatchRuleTemplate template = requireTemplate(cityId, templateId);
        if (template.getIsActive() == 1) throw new BizException("不能删除当前生效的模板");

        conditionMapper.delete(new LambdaQueryWrapper<DispatchRuleCondition>()
                .eq(DispatchRuleCondition::getTemplateId, templateId));
        templateMapper.deleteById(templateId);
    }

    @Override
    @Transactional
    public Long copyTemplate(Long cityId, Long templateId, String newName) {
        DispatchRuleTemplate source = requireTemplate(cityId, templateId);

        long now = System.currentTimeMillis() / 1000;

        DispatchRuleTemplate copy = new DispatchRuleTemplate();
        copy.setCityId(cityId);
        copy.setName(newName != null && !newName.isBlank() ? newName : source.getName() + "(副本)");
        copy.setIsActive(0);
        copy.setGrabEnabled(source.getGrabEnabled());
        copy.setGrabTimeout(source.getGrabTimeout());
        copy.setGrabScope(source.getGrabScope());
        copy.setGrabMaxPerRider(source.getGrabMaxPerRider());
        copy.setAutoDispatch(source.getAutoDispatch());
        copy.setCreateTime(now);
        copy.setUpdateTime(now);
        templateMapper.insert(copy);

        // 复制条件
        List<DispatchRuleCondition> conditions = conditionMapper.selectList(
                new LambdaQueryWrapper<DispatchRuleCondition>()
                        .eq(DispatchRuleCondition::getTemplateId, templateId));
        for (DispatchRuleCondition c : conditions) {
            DispatchRuleCondition nc = new DispatchRuleCondition();
            nc.setTemplateId(copy.getId());
            nc.setConditionType(c.getConditionType());
            nc.setEnabled(c.getEnabled());
            nc.setThresholdValue(c.getThresholdValue());
            nc.setSortOrder(c.getSortOrder());
            nc.setCreateTime(now);
            nc.setUpdateTime(now);
            conditionMapper.insert(nc);
        }

        return copy.getId();
    }

    private DispatchRuleTemplate requireTemplate(Long cityId, Long templateId) {
        if (cityId == null || cityId < 1) throw new BizException("城市ID不能为空");
        DispatchRuleTemplate template = templateMapper.selectOne(
                new LambdaQueryWrapper<DispatchRuleTemplate>()
                        .eq(DispatchRuleTemplate::getId, templateId)
                        .eq(DispatchRuleTemplate::getCityId, cityId)
                        .last("LIMIT 1"));
        if (template == null) throw new BizException("模板不存在");
        return template;
    }

    private DispatchRuleTemplateVO toVO(DispatchRuleTemplate template) {
        DispatchRuleTemplateVO vo = new DispatchRuleTemplateVO();
        vo.setId(template.getId());
        vo.setCityId(template.getCityId());
        vo.setName(template.getName());
        vo.setIsActive(template.getIsActive());
        vo.setGrabEnabled(template.getGrabEnabled());
        vo.setGrabTimeout(template.getGrabTimeout());
        vo.setGrabScope(template.getGrabScope());
        vo.setGrabMaxPerRider(template.getGrabMaxPerRider());
        vo.setAutoDispatch(template.getAutoDispatch());
        vo.setCreateTime(template.getCreateTime());
        vo.setUpdateTime(template.getUpdateTime());

        List<DispatchRuleCondition> conditions = conditionMapper.selectList(
                new LambdaQueryWrapper<DispatchRuleCondition>()
                        .eq(DispatchRuleCondition::getTemplateId, template.getId())
                        .orderByAsc(DispatchRuleCondition::getSortOrder));

        List<DispatchRuleTemplateVO.ConditionItem> items = new ArrayList<>();
        for (DispatchRuleCondition c : conditions) {
            DispatchRuleTemplateVO.ConditionItem item = new DispatchRuleTemplateVO.ConditionItem();
            item.setId(c.getId());
            item.setConditionType(c.getConditionType());
            item.setEnabled(c.getEnabled());
            item.setThresholdValue(c.getThresholdValue());
            item.setSortOrder(c.getSortOrder());

            DispatchConditionType type = DispatchConditionType.fromCode(c.getConditionType());
            if (type != null) {
                item.setConditionDesc(type.getDesc());
                item.setHasThreshold(type.isHasThreshold());
            }
            items.add(item);
        }
        vo.setConditions(items);
        return vo;
    }
}