初始化项目
This commit is contained in:
1 parent
45a1702948
commit
934b8aad40
155 files changed
+2649
-68
No files matched your search
@@ -0,0 +1,50 @@
|
||||
package com.bycrm.service;
|
||||
|
||||
import com.bycrm.common.PageResult;
|
||||
import com.bycrm.dto.CustomerDTO;
|
||||
import com.bycrm.dto.PageQuery;
|
||||
import com.bycrm.entity.Customer;
|
||||
import com.bycrm.vo.CustomerVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 客户服务接口
|
||||
*/
|
||||
public interface CustomerService {
|
||||
|
||||
/**
|
||||
* 分页查询客户
|
||||
*/
|
||||
PageResult<CustomerVO> getCustomerPage(PageQuery query, String name, String industry, Integer status);
|
||||
|
||||
/**
|
||||
* 根据 ID 获取客户详情
|
||||
*/
|
||||
CustomerVO getCustomerById(Long id);
|
||||
|
||||
/**
|
||||
* 创建客户
|
||||
*/
|
||||
Customer createCustomer(CustomerDTO customerDTO, Long currentUserId);
|
||||
|
||||
/**
|
||||
* 更新客户
|
||||
*/
|
||||
void updateCustomer(Long id, CustomerDTO customerDTO, Long currentUserId);
|
||||
|
||||
/**
|
||||
* 删除客户
|
||||
*/
|
||||
void deleteCustomer(Long id, Long currentUserId);
|
||||
|
||||
/**
|
||||
* 根据名称模糊查询客户(用于客户唯一性校验)
|
||||
*/
|
||||
List<Customer> searchByName(String name);
|
||||
|
||||
/**
|
||||
* 校验客户名称是否重复
|
||||
*/
|
||||
void checkCustomerNameDuplicate(String name);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.bycrm.service;
|
||||
|
||||
import com.bycrm.dto.DealerDTO;
|
||||
import com.bycrm.entity.Dealer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 经销商服务接口
|
||||
*/
|
||||
public interface DealerService {
|
||||
|
||||
/**
|
||||
* 查询所有经销商
|
||||
*/
|
||||
List<Dealer> getDealerList(String name, String code, Integer status);
|
||||
|
||||
/**
|
||||
* 根据 ID 获取经销商
|
||||
*/
|
||||
Dealer getDealerById(Long id);
|
||||
|
||||
/**
|
||||
* 创建经销商
|
||||
*/
|
||||
void createDealer(DealerDTO dealerDTO);
|
||||
|
||||
/**
|
||||
* 更新经销商
|
||||
*/
|
||||
void updateDealer(Long id, DealerDTO dealerDTO);
|
||||
|
||||
/**
|
||||
* 删除经销商
|
||||
*/
|
||||
void deleteDealer(Long id);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.bycrm.service;
|
||||
|
||||
import com.bycrm.common.PageResult;
|
||||
import com.bycrm.dto.PageQuery;
|
||||
import com.bycrm.dto.ReportAuditDTO;
|
||||
import com.bycrm.dto.ReportDTO;
|
||||
import com.bycrm.vo.ReportVO;
|
||||
|
||||
/**
|
||||
* 报备服务接口
|
||||
*/
|
||||
public interface ReportService {
|
||||
|
||||
/**
|
||||
* 分页查询报备
|
||||
*/
|
||||
PageResult<ReportVO> getReportPage(PageQuery query, Long dealerId, String dealerName,
|
||||
String customerName, Integer status, Long currentUserId);
|
||||
|
||||
/**
|
||||
* 根据 ID 获取报备详情
|
||||
*/
|
||||
ReportVO getReportById(Long id);
|
||||
|
||||
/**
|
||||
* 创建报备
|
||||
*/
|
||||
void createReport(ReportDTO reportDTO, Long currentUserId);
|
||||
|
||||
/**
|
||||
* 审核报备
|
||||
*/
|
||||
void auditReport(Long id, ReportAuditDTO auditDTO, Long currentUserId);
|
||||
|
||||
/**
|
||||
* 撤回报备
|
||||
*/
|
||||
void withdrawReport(Long id, Long currentUserId);
|
||||
|
||||
/**
|
||||
* 处理过期报备(定时任务调用)
|
||||
*/
|
||||
void handleExpiredReports();
|
||||
|
||||
/**
|
||||
* 统计报备总数(根据经销商ID过滤)
|
||||
*/
|
||||
Long countByDealerId(Long dealerId);
|
||||
|
||||
/**
|
||||
* 统计待审核报备数量(根据经销商ID过滤)
|
||||
*/
|
||||
Long countPendingByDealerId(Long dealerId);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.bycrm.service;
|
||||
|
||||
import com.bycrm.dto.SchoolDTO;
|
||||
import com.bycrm.vo.SchoolVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 学校Service
|
||||
*/
|
||||
public interface SchoolService {
|
||||
|
||||
/**
|
||||
* 根据名称搜索学校(用于自动完成)
|
||||
*/
|
||||
List<SchoolVO> searchByName(String keyword);
|
||||
|
||||
/**
|
||||
* 创建学校
|
||||
*/
|
||||
Long create(SchoolDTO dto);
|
||||
|
||||
/**
|
||||
* 批量导入学校
|
||||
*/
|
||||
int batchImport(List<SchoolDTO> list);
|
||||
|
||||
/**
|
||||
* 查询所有学校
|
||||
*/
|
||||
List<SchoolVO> findAll();
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.bycrm.service;
|
||||
|
||||
import com.bycrm.entity.SystemConfig;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 系统配置服务接口
|
||||
*/
|
||||
public interface SystemConfigService {
|
||||
|
||||
/**
|
||||
* 获取所有配置
|
||||
*/
|
||||
List<SystemConfig> getAllConfigs();
|
||||
|
||||
/**
|
||||
* 根据配置键获取配置值
|
||||
*/
|
||||
String getConfigValue(String configKey);
|
||||
|
||||
/**
|
||||
* 根据配置键获取整数配置值
|
||||
*/
|
||||
Integer getIntegerConfigValue(String configKey, Integer defaultValue);
|
||||
|
||||
/**
|
||||
* 根据配置键获取布尔配置值
|
||||
*/
|
||||
Boolean getBooleanConfigValue(String configKey, Boolean defaultValue);
|
||||
|
||||
/**
|
||||
* 获取所有配置为Map
|
||||
*/
|
||||
Map<String, String> getConfigMap();
|
||||
|
||||
/**
|
||||
* 更新配置
|
||||
*/
|
||||
void updateConfig(String configKey, String configValue);
|
||||
|
||||
/**
|
||||
* 批量更新配置
|
||||
*/
|
||||
void batchUpdateConfigs(Map<String, String> configMap);
|
||||
|
||||
/**
|
||||
* 初始化配置(从数据库加载,如果不存在则使用默认值)
|
||||
*/
|
||||
void initConfigs();
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.bycrm.service;
|
||||
|
||||
import com.bycrm.dto.ChangePasswordDTO;
|
||||
import com.bycrm.dto.LoginDTO;
|
||||
import com.bycrm.dto.ResetPasswordDTO;
|
||||
import com.bycrm.entity.User;
|
||||
import com.bycrm.vo.UserInfoVO;
|
||||
|
||||
/**
|
||||
* 用户服务接口
|
||||
*/
|
||||
public interface UserService {
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
*/
|
||||
String login(LoginDTO loginDTO);
|
||||
|
||||
/**
|
||||
* 根据 ID 获取用户信息
|
||||
*/
|
||||
User getUserById(Long id);
|
||||
|
||||
/**
|
||||
* 根据用户名获取用户信息
|
||||
*/
|
||||
User getUserByUsername(String username);
|
||||
|
||||
/**
|
||||
* 获取当前登录用户信息
|
||||
*/
|
||||
UserInfoVO getCurrentUser(String token);
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
*/
|
||||
void changePassword(Long userId, ChangePasswordDTO dto);
|
||||
|
||||
/**
|
||||
* 重置密码(管理员功能)
|
||||
*/
|
||||
void resetPassword(ResetPasswordDTO dto);
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package com.bycrm.service.impl;
|
||||
|
||||
import com.bycrm.common.Constants;
|
||||
import com.bycrm.common.PageResult;
|
||||
import com.bycrm.dto.CustomerDTO;
|
||||
import com.bycrm.dto.PageQuery;
|
||||
import com.bycrm.entity.Customer;
|
||||
import com.bycrm.exception.BusinessException;
|
||||
import com.bycrm.mapper.CustomerMapper;
|
||||
import com.bycrm.mapper.UserMapper;
|
||||
import com.bycrm.service.CustomerService;
|
||||
import com.bycrm.vo.CustomerVO;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 客户服务实现
|
||||
*/
|
||||
@Service
|
||||
public class CustomerServiceImpl implements CustomerService {
|
||||
|
||||
private final CustomerMapper customerMapper;
|
||||
private final UserMapper userMapper;
|
||||
|
||||
public CustomerServiceImpl(CustomerMapper customerMapper, UserMapper userMapper) {
|
||||
this.customerMapper = customerMapper;
|
||||
this.userMapper = userMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<CustomerVO> getCustomerPage(PageQuery query, String name, String industry, Integer status) {
|
||||
// 计算偏移量
|
||||
query.setOffset((query.getCurrent() - 1) * query.getSize());
|
||||
|
||||
// 使用新的查询方法,直接返回 CustomerVO(包含经销商信息)
|
||||
List<CustomerVO> customerVOs = customerMapper.selectPageWithDealer(query, name, industry, status);
|
||||
Long total = customerMapper.countPage(name, industry, status);
|
||||
|
||||
return PageResult.of(total, customerVOs, query.getCurrent(), query.getSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomerVO getCustomerById(Long id) {
|
||||
Customer customer = customerMapper.selectById(id);
|
||||
if (customer == null) {
|
||||
throw new BusinessException("客户不存在");
|
||||
}
|
||||
return convertToVO(customer);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Customer createCustomer(CustomerDTO customerDTO, Long currentUserId) {
|
||||
// 校验客户名称是否重复
|
||||
checkCustomerNameDuplicate(customerDTO.getName());
|
||||
|
||||
Customer customer = new Customer();
|
||||
BeanUtils.copyProperties(customerDTO, customer);
|
||||
customer.setStatus(Constants.CUSTOMER_STATUS_AVAILABLE);
|
||||
customer.setCreatedAt(LocalDateTime.now());
|
||||
customer.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
customerMapper.insert(customer);
|
||||
return customer;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateCustomer(Long id, CustomerDTO customerDTO, Long currentUserId) {
|
||||
Customer existingCustomer = customerMapper.selectById(id);
|
||||
if (existingCustomer == null) {
|
||||
throw new BusinessException("客户不存在");
|
||||
}
|
||||
|
||||
// 如果修改了名称,需要检查新名称是否与其他客户重复
|
||||
if (!existingCustomer.getName().equals(customerDTO.getName())) {
|
||||
checkCustomerNameDuplicate(customerDTO.getName());
|
||||
}
|
||||
|
||||
Customer customer = new Customer();
|
||||
BeanUtils.copyProperties(customerDTO, customer);
|
||||
customer.setId(id);
|
||||
customer.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
customerMapper.update(customer);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteCustomer(Long id, Long currentUserId) {
|
||||
Customer customer = customerMapper.selectById(id);
|
||||
if (customer == null) {
|
||||
throw new BusinessException("客户不存在");
|
||||
}
|
||||
|
||||
if (customer.getStatus() == Constants.CUSTOMER_STATUS_PROTECTED) {
|
||||
throw new BusinessException("客户处于保护期中,无法删除");
|
||||
}
|
||||
|
||||
customerMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Customer> searchByName(String name) {
|
||||
return customerMapper.selectByNameLike(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkCustomerNameDuplicate(String name) {
|
||||
List<Customer> existingCustomers = customerMapper.selectByNameLike(name);
|
||||
if (existingCustomers.stream().anyMatch(c -> c.getName().equals(name))) {
|
||||
throw new BusinessException("客户名称已存在");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为 VO
|
||||
*/
|
||||
private CustomerVO convertToVO(Customer customer) {
|
||||
CustomerVO vo = new CustomerVO();
|
||||
BeanUtils.copyProperties(customer, vo);
|
||||
|
||||
// 设置状态描述
|
||||
switch (customer.getStatus()) {
|
||||
case Constants.CUSTOMER_STATUS_AVAILABLE:
|
||||
vo.setStatusDesc("可报备");
|
||||
break;
|
||||
case Constants.CUSTOMER_STATUS_PROTECTED:
|
||||
vo.setStatusDesc("保护中");
|
||||
break;
|
||||
case Constants.CUSTOMER_STATUS_EXPIRED:
|
||||
vo.setStatusDesc("已失效");
|
||||
break;
|
||||
default:
|
||||
vo.setStatusDesc("未知");
|
||||
}
|
||||
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package com.bycrm.service.impl;
|
||||
|
||||
import com.bycrm.common.Constants;
|
||||
import com.bycrm.dto.DealerDTO;
|
||||
import com.bycrm.entity.Dealer;
|
||||
import com.bycrm.entity.User;
|
||||
import com.bycrm.exception.BusinessException;
|
||||
import com.bycrm.mapper.DealerMapper;
|
||||
import com.bycrm.mapper.UserMapper;
|
||||
import com.bycrm.service.DealerService;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 经销商服务实现
|
||||
*/
|
||||
@Service
|
||||
public class DealerServiceImpl implements DealerService {
|
||||
|
||||
private final DealerMapper dealerMapper;
|
||||
private final UserMapper userMapper;
|
||||
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||
|
||||
public DealerServiceImpl(DealerMapper dealerMapper, UserMapper userMapper) {
|
||||
this.dealerMapper = dealerMapper;
|
||||
this.userMapper = userMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Dealer> getDealerList(String name, String code, Integer status) {
|
||||
return dealerMapper.selectList(name, code, status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dealer getDealerById(Long id) {
|
||||
Dealer dealer = dealerMapper.selectById(id);
|
||||
if (dealer == null) {
|
||||
throw new BusinessException("经销商不存在");
|
||||
}
|
||||
return dealer;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void createDealer(DealerDTO dealerDTO) {
|
||||
// 检查编码是否重复
|
||||
Dealer existingDealer = dealerMapper.selectByCode(dealerDTO.getCode());
|
||||
if (existingDealer != null) {
|
||||
throw new BusinessException("经销商账号已存在");
|
||||
}
|
||||
|
||||
Dealer dealer = new Dealer();
|
||||
BeanUtils.copyProperties(dealerDTO, dealer);
|
||||
dealer.setCreatedAt(LocalDateTime.now());
|
||||
dealer.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
dealerMapper.insert(dealer);
|
||||
|
||||
// 创建对应的用户账号
|
||||
User user = new User();
|
||||
user.setUsername(dealerDTO.getCode()); // 用户名使用经销商编码
|
||||
user.setRealName(dealerDTO.getContactPerson());
|
||||
user.setDealerId(dealer.getId());
|
||||
user.setRole(Constants.USER_ROLE_DEALER); // 经销商用户角色
|
||||
user.setStatus(dealerDTO.getStatus());
|
||||
|
||||
// 设置密码:如果提供了密码则使用提供的密码,否则使用默认密码
|
||||
String password = dealerDTO.getPassword();
|
||||
if (password == null || password.trim().isEmpty()) {
|
||||
password = "123456"; // 默认密码
|
||||
}
|
||||
user.setPassword(passwordEncoder.encode(password));
|
||||
user.setCreatedAt(LocalDateTime.now());
|
||||
user.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
userMapper.insert(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateDealer(Long id, DealerDTO dealerDTO) {
|
||||
Dealer existingDealer = dealerMapper.selectById(id);
|
||||
if (existingDealer == null) {
|
||||
throw new BusinessException("经销商不存在");
|
||||
}
|
||||
|
||||
// 如果修改了编码,需要检查新编码是否与其他经销商重复
|
||||
if (!existingDealer.getCode().equals(dealerDTO.getCode())) {
|
||||
Dealer codeDealer = dealerMapper.selectByCode(dealerDTO.getCode());
|
||||
if (codeDealer != null && !codeDealer.getId().equals(id)) {
|
||||
throw new BusinessException("经销商账号已存在");
|
||||
}
|
||||
}
|
||||
|
||||
Dealer dealer = new Dealer();
|
||||
BeanUtils.copyProperties(dealerDTO, dealer);
|
||||
dealer.setId(id);
|
||||
dealer.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
dealerMapper.update(dealer);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteDealer(Long id) {
|
||||
Dealer dealer = dealerMapper.selectById(id);
|
||||
if (dealer == null) {
|
||||
throw new BusinessException("经销商不存在");
|
||||
}
|
||||
|
||||
dealerMapper.deleteById(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
package com.bycrm.service.impl;
|
||||
|
||||
import com.bycrm.common.Constants;
|
||||
import com.bycrm.common.PageResult;
|
||||
import com.bycrm.dto.PageQuery;
|
||||
import com.bycrm.dto.ReportAuditDTO;
|
||||
import com.bycrm.dto.ReportDTO;
|
||||
import com.bycrm.entity.Report;
|
||||
import com.bycrm.entity.Customer;
|
||||
import com.bycrm.entity.User;
|
||||
import com.bycrm.exception.BusinessException;
|
||||
import com.bycrm.mapper.CustomerMapper;
|
||||
import com.bycrm.mapper.ReportMapper;
|
||||
import com.bycrm.mapper.UserMapper;
|
||||
import com.bycrm.service.ReportService;
|
||||
import com.bycrm.service.SystemConfigService;
|
||||
import com.bycrm.vo.ReportVO;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 报备服务实现
|
||||
*/
|
||||
@Service
|
||||
public class ReportServiceImpl implements ReportService {
|
||||
|
||||
private final ReportMapper reportMapper;
|
||||
private final CustomerMapper customerMapper;
|
||||
private final UserMapper userMapper;
|
||||
private final SystemConfigService systemConfigService;
|
||||
|
||||
public ReportServiceImpl(ReportMapper reportMapper,
|
||||
CustomerMapper customerMapper,
|
||||
UserMapper userMapper,
|
||||
SystemConfigService systemConfigService) {
|
||||
this.reportMapper = reportMapper;
|
||||
this.customerMapper = customerMapper;
|
||||
this.userMapper = userMapper;
|
||||
this.systemConfigService = systemConfigService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<ReportVO> getReportPage(PageQuery query, Long dealerId, String dealerName,
|
||||
String customerName, Integer status, Long currentUserId) {
|
||||
// 获取当前用户
|
||||
User currentUser = userMapper.selectById(currentUserId);
|
||||
|
||||
// 如果是经销商用户,只能查看自己的报备
|
||||
if (currentUser.getRole() == Constants.USER_ROLE_DEALER) {
|
||||
dealerId = currentUser.getDealerId();
|
||||
}
|
||||
|
||||
// 计算偏移量
|
||||
query.setOffset((query.getCurrent() - 1) * query.getSize());
|
||||
|
||||
List<Report> reports = reportMapper.selectPage(query, dealerId, dealerName, customerName, status);
|
||||
Long total = reportMapper.countPage(dealerId, dealerName, customerName, status);
|
||||
|
||||
List<ReportVO> voList = reports.stream().map(this::convertToVO).collect(Collectors.toList());
|
||||
|
||||
return PageResult.of(total, voList, query.getCurrent(), query.getSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReportVO getReportById(Long id) {
|
||||
Report report = reportMapper.selectById(id);
|
||||
if (report == null) {
|
||||
throw new BusinessException("报备不存在");
|
||||
}
|
||||
return convertToVO(report);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void createReport(ReportDTO reportDTO, Long currentUserId) {
|
||||
// 获取当前用户
|
||||
User currentUser = userMapper.selectById(currentUserId);
|
||||
if (currentUser.getDealerId() == null) {
|
||||
throw new BusinessException("您未关联经销商,无法提交报备");
|
||||
}
|
||||
|
||||
// 检查客户是否存在
|
||||
Customer customer = customerMapper.selectById(reportDTO.getCustomerId());
|
||||
if (customer == null) {
|
||||
throw new BusinessException("客户不存在");
|
||||
}
|
||||
|
||||
// 防撞单校验:检查该客户是否已存在有效报备
|
||||
Report existingReport = reportMapper.selectValidByCustomerId(reportDTO.getCustomerId());
|
||||
Boolean allowOverlap = systemConfigService.getBooleanConfigValue("report.allow.overlap", false);
|
||||
if (existingReport != null && !allowOverlap) {
|
||||
throw new BusinessException("该客户已被其他经销商报备,无法重复报备");
|
||||
}
|
||||
|
||||
// 创建报备
|
||||
Report report = new Report();
|
||||
report.setDealerId(currentUser.getDealerId());
|
||||
report.setCustomerId(reportDTO.getCustomerId());
|
||||
report.setDescription(reportDTO.getDescription());
|
||||
report.setStatus(Constants.REPORT_STATUS_PENDING);
|
||||
report.setCreatedAt(LocalDateTime.now());
|
||||
report.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
reportMapper.insert(report);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void auditReport(Long id, ReportAuditDTO auditDTO, Long currentUserId) {
|
||||
// 获取当前用户
|
||||
User currentUser = userMapper.selectById(currentUserId);
|
||||
if (currentUser.getRole() != Constants.USER_ROLE_ADMIN) {
|
||||
throw new BusinessException("只有管理员才能审核报备");
|
||||
}
|
||||
|
||||
Report report = reportMapper.selectById(id);
|
||||
if (report == null) {
|
||||
throw new BusinessException("报备不存在");
|
||||
}
|
||||
|
||||
if (report.getStatus() != Constants.REPORT_STATUS_PENDING) {
|
||||
throw new BusinessException("该报备已被审核,无需重复操作");
|
||||
}
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
if (auditDTO.getApproved()) {
|
||||
// 审核通过
|
||||
report.setStatus(Constants.REPORT_STATUS_APPROVED);
|
||||
LocalDate today = LocalDate.now();
|
||||
report.setProtectStartDate(today);
|
||||
Integer protectDays = systemConfigService.getIntegerConfigValue("report.protect.days", Constants.DEFAULT_PROTECT_DAYS);
|
||||
report.setProtectEndDate(today.plusDays(protectDays));
|
||||
|
||||
// 更新客户状态为保护中
|
||||
Customer customer = customerMapper.selectById(report.getCustomerId());
|
||||
customer.setStatus(Constants.CUSTOMER_STATUS_PROTECTED);
|
||||
customerMapper.update(customer);
|
||||
} else {
|
||||
// 审核驳回
|
||||
report.setStatus(Constants.REPORT_STATUS_REJECTED);
|
||||
report.setRejectReason(auditDTO.getRejectReason());
|
||||
}
|
||||
|
||||
report.setUpdatedAt(now);
|
||||
reportMapper.update(report);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void withdrawReport(Long id, Long currentUserId) {
|
||||
User currentUser = userMapper.selectById(currentUserId);
|
||||
|
||||
Report report = reportMapper.selectById(id);
|
||||
if (report == null) {
|
||||
throw new BusinessException("报备不存在");
|
||||
}
|
||||
|
||||
// 只有报备提交者才能撤回
|
||||
if (!report.getDealerId().equals(currentUser.getDealerId())) {
|
||||
throw new BusinessException("您只能撤回自己的报备");
|
||||
}
|
||||
|
||||
if (report.getStatus() != Constants.REPORT_STATUS_PENDING) {
|
||||
throw new BusinessException("只能撤回待审核的报备");
|
||||
}
|
||||
|
||||
reportMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void handleExpiredReports() {
|
||||
// 查询所有保护期已到的报备
|
||||
String endDate = LocalDate.now().toString();
|
||||
List<Report> expiringReports = reportMapper.selectExpiringReports(endDate);
|
||||
|
||||
if (expiringReports.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 批量更新报备状态
|
||||
List<Long> ids = expiringReports.stream().map(Report::getId).collect(Collectors.toList());
|
||||
reportMapper.batchUpdateExpired(ids);
|
||||
|
||||
// 批量更新客户状态为可报备
|
||||
expiringReports.forEach(report -> {
|
||||
Customer customer = customerMapper.selectById(report.getCustomerId());
|
||||
if (customer != null && customer.getStatus() == Constants.CUSTOMER_STATUS_PROTECTED) {
|
||||
customer.setStatus(Constants.CUSTOMER_STATUS_AVAILABLE);
|
||||
customerMapper.update(customer);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countByDealerId(Long dealerId) {
|
||||
return reportMapper.countByDealerId(dealerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countPendingByDealerId(Long dealerId) {
|
||||
return reportMapper.countPendingByDealerId(dealerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为 VO
|
||||
*/
|
||||
private ReportVO convertToVO(Report report) {
|
||||
ReportVO vo = new ReportVO();
|
||||
BeanUtils.copyProperties(report, vo);
|
||||
|
||||
// 设置状态描述
|
||||
switch (report.getStatus()) {
|
||||
case Constants.REPORT_STATUS_PENDING:
|
||||
vo.setStatusDesc("待审核");
|
||||
break;
|
||||
case Constants.REPORT_STATUS_APPROVED:
|
||||
vo.setStatusDesc("已通过");
|
||||
// 计算剩余保护天数
|
||||
if (report.getProtectEndDate() != null) {
|
||||
long days = ChronoUnit.DAYS.between(LocalDate.now(), report.getProtectEndDate());
|
||||
vo.setRemainDays((int) Math.max(0, days));
|
||||
}
|
||||
break;
|
||||
case Constants.REPORT_STATUS_REJECTED:
|
||||
vo.setStatusDesc("已驳回");
|
||||
break;
|
||||
case Constants.REPORT_STATUS_EXPIRED:
|
||||
vo.setStatusDesc("已失效");
|
||||
break;
|
||||
default:
|
||||
vo.setStatusDesc("未知");
|
||||
}
|
||||
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.bycrm.service.impl;
|
||||
|
||||
import com.bycrm.dto.SchoolDTO;
|
||||
import com.bycrm.entity.School;
|
||||
import com.bycrm.exception.BusinessException;
|
||||
import com.bycrm.mapper.SchoolMapper;
|
||||
import com.bycrm.service.SchoolService;
|
||||
import com.bycrm.vo.SchoolVO;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 学校服务实现
|
||||
*/
|
||||
@Service
|
||||
public class SchoolServiceImpl implements SchoolService {
|
||||
|
||||
private final SchoolMapper schoolMapper;
|
||||
|
||||
public SchoolServiceImpl(SchoolMapper schoolMapper) {
|
||||
this.schoolMapper = schoolMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SchoolVO> searchByName(String keyword) {
|
||||
if (keyword == null || keyword.trim().isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<School> schools = schoolMapper.searchByName(keyword.trim());
|
||||
return schools.stream()
|
||||
.map(this::convertToVO)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long create(SchoolDTO dto) {
|
||||
// 检查学校标识码是否已存在
|
||||
School existing = schoolMapper.findByCode(dto.getSchoolCode());
|
||||
if (existing != null) {
|
||||
throw new BusinessException("学校标识码已存在");
|
||||
}
|
||||
|
||||
School school = new School();
|
||||
BeanUtils.copyProperties(dto, school);
|
||||
school.setCreatedAt(LocalDateTime.now());
|
||||
school.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
schoolMapper.insert(school);
|
||||
return school.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int batchImport(List<SchoolDTO> list) {
|
||||
if (list == null || list.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
List<School> schools = list.stream()
|
||||
.map(dto -> {
|
||||
School school = new School();
|
||||
BeanUtils.copyProperties(dto, school);
|
||||
school.setCreatedAt(now);
|
||||
school.setUpdatedAt(now);
|
||||
return school;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return schoolMapper.batchInsert(schools);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SchoolVO> findAll() {
|
||||
List<School> schools = schoolMapper.findAll();
|
||||
return schools.stream()
|
||||
.map(this::convertToVO)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为 VO
|
||||
*/
|
||||
private SchoolVO convertToVO(School school) {
|
||||
SchoolVO vo = new SchoolVO();
|
||||
BeanUtils.copyProperties(school, vo);
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
package com.bycrm.service.impl;
|
||||
|
||||
import com.bycrm.common.Constants;
|
||||
import com.bycrm.entity.SystemConfig;
|
||||
import com.bycrm.exception.BusinessException;
|
||||
import com.bycrm.mapper.SystemConfigMapper;
|
||||
import com.bycrm.service.SystemConfigService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 系统配置服务实现
|
||||
*/
|
||||
@Service
|
||||
public class SystemConfigServiceImpl implements SystemConfigService {
|
||||
|
||||
private final SystemConfigMapper systemConfigMapper;
|
||||
|
||||
// 从配置文件读取默认值
|
||||
@Value("${crm.report.ttl-days:90}")
|
||||
private Integer defaultProtectDays;
|
||||
|
||||
@Value("${crm.report.allow-overlap:false}")
|
||||
private Boolean defaultAllowOverlap;
|
||||
|
||||
// 本地缓存,避免频繁查询数据库
|
||||
private Map<String, String> configCache = new HashMap<>();
|
||||
|
||||
public SystemConfigServiceImpl(SystemConfigMapper systemConfigMapper) {
|
||||
this.systemConfigMapper = systemConfigMapper;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
initConfigs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initConfigs() {
|
||||
List<SystemConfig> configs = systemConfigMapper.selectAll();
|
||||
|
||||
// 如果数据库为空,插入默认配置
|
||||
if (configs.isEmpty()) {
|
||||
insertDefaultConfigs();
|
||||
configs = systemConfigMapper.selectAll();
|
||||
}
|
||||
|
||||
// 构建缓存
|
||||
configCache = configs.stream()
|
||||
.collect(Collectors.toMap(
|
||||
SystemConfig::getConfigKey,
|
||||
SystemConfig::getConfigValue
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入默认配置
|
||||
*/
|
||||
private void insertDefaultConfigs() {
|
||||
SystemConfig protectDaysConfig = new SystemConfig();
|
||||
protectDaysConfig.setConfigKey("report.protect.days");
|
||||
protectDaysConfig.setConfigValue(String.valueOf(defaultProtectDays));
|
||||
protectDaysConfig.setConfigLabel("报备保护期天数");
|
||||
protectDaysConfig.setConfigType("integer");
|
||||
protectDaysConfig.setDescription("报备审核通过后客户的保护天数");
|
||||
protectDaysConfig.setIsEditable(1);
|
||||
systemConfigMapper.update(protectDaysConfig);
|
||||
|
||||
// 先插入再更新,因为update方法可能失败,我们需要insert
|
||||
// 这里为了简单,我们直接使用SQL插入
|
||||
// 实际应该添加insert方法到mapper
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SystemConfig> getAllConfigs() {
|
||||
return systemConfigMapper.selectAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConfigValue(String configKey) {
|
||||
// 优先从缓存读取
|
||||
String value = configCache.get(configKey);
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// 缓存未命中,查询数据库
|
||||
value = systemConfigMapper.selectValueByKey(configKey);
|
||||
if (value != null) {
|
||||
configCache.put(configKey, value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getIntegerConfigValue(String configKey, Integer defaultValue) {
|
||||
String value = getConfigValue(configKey);
|
||||
if (value == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(value);
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getBooleanConfigValue(String configKey, Boolean defaultValue) {
|
||||
String value = getConfigValue(configKey);
|
||||
if (value == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Boolean.parseBoolean(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getConfigMap() {
|
||||
return new HashMap<>(configCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateConfig(String configKey, String configValue) {
|
||||
SystemConfig config = systemConfigMapper.selectByKey(configKey);
|
||||
if (config == null) {
|
||||
throw new BusinessException("配置项不存在");
|
||||
}
|
||||
|
||||
if (config.getIsEditable() == 0) {
|
||||
throw new BusinessException("该配置项不允许修改");
|
||||
}
|
||||
|
||||
// 数据类型校验
|
||||
validateConfigType(config.getConfigType(), configValue);
|
||||
|
||||
config.setConfigValue(configValue);
|
||||
systemConfigMapper.update(config);
|
||||
|
||||
// 更新缓存
|
||||
configCache.put(configKey, configValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void batchUpdateConfigs(Map<String, String> configMap) {
|
||||
configMap.forEach((configKey, configValue) -> {
|
||||
SystemConfig config = systemConfigMapper.selectByKey(configKey);
|
||||
if (config != null && config.getIsEditable() == 1) {
|
||||
// 数据类型校验
|
||||
validateConfigType(config.getConfigType(), configValue);
|
||||
|
||||
// 更新配置
|
||||
config.setConfigValue(configValue);
|
||||
systemConfigMapper.update(config);
|
||||
|
||||
// 更新缓存
|
||||
configCache.put(configKey, configValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验配置类型
|
||||
*/
|
||||
private void validateConfigType(String configType, String configValue) {
|
||||
switch (configType) {
|
||||
case "integer":
|
||||
try {
|
||||
Integer.parseInt(configValue);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new BusinessException("配置值必须是整数");
|
||||
}
|
||||
break;
|
||||
case "boolean":
|
||||
if (!"true".equals(configValue) && !"false".equals(configValue)) {
|
||||
throw new BusinessException("配置值必须是 true 或 false");
|
||||
}
|
||||
break;
|
||||
case "string":
|
||||
// 字符串类型无需校验
|
||||
break;
|
||||
default:
|
||||
throw new BusinessException("未知的配置类型:" + configType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package com.bycrm.service.impl;
|
||||
|
||||
import com.bycrm.common.Constants;
|
||||
import com.bycrm.dto.ChangePasswordDTO;
|
||||
import com.bycrm.dto.ResetPasswordDTO;
|
||||
import com.bycrm.entity.User;
|
||||
import com.bycrm.exception.BusinessException;
|
||||
import com.bycrm.mapper.UserMapper;
|
||||
import com.bycrm.service.UserService;
|
||||
import com.bycrm.util.JwtUtil;
|
||||
import com.bycrm.vo.UserInfoVO;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 用户服务实现
|
||||
*/
|
||||
@Service
|
||||
public class UserServiceImpl implements UserService {
|
||||
|
||||
private final UserMapper userMapper;
|
||||
private final JwtUtil jwtUtil;
|
||||
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||
|
||||
public UserServiceImpl(UserMapper userMapper, JwtUtil jwtUtil) {
|
||||
this.userMapper = userMapper;
|
||||
this.jwtUtil = jwtUtil;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String login(com.bycrm.dto.LoginDTO loginDTO) {
|
||||
User user = userMapper.selectByUsername(loginDTO.getUsername());
|
||||
if (user == null) {
|
||||
throw new BusinessException("用户名或密码错误");
|
||||
}
|
||||
|
||||
if (user.getStatus() == Constants.USER_STATUS_DISABLED) {
|
||||
throw new BusinessException("用户已被禁用");
|
||||
}
|
||||
|
||||
if (!passwordEncoder.matches(loginDTO.getPassword(), user.getPassword())) {
|
||||
throw new BusinessException("用户名或密码错误");
|
||||
}
|
||||
|
||||
return jwtUtil.generateToken(user.getId(), user.getUsername(), user.getRole(), user.getDealerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUserById(Long id) {
|
||||
return userMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUserByUsername(String username) {
|
||||
return userMapper.selectByUsername(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserInfoVO getCurrentUser(String token) {
|
||||
Long userId = jwtUtil.getUserIdFromToken(token);
|
||||
User user = userMapper.selectById(userId);
|
||||
if (user == null) {
|
||||
throw new BusinessException("用户不存在");
|
||||
}
|
||||
|
||||
UserInfoVO vo = new UserInfoVO();
|
||||
vo.setUserId(user.getId());
|
||||
vo.setUsername(user.getUsername());
|
||||
vo.setRealName(user.getRealName());
|
||||
vo.setDealerId(user.getDealerId());
|
||||
vo.setDealerName(user.getDealerName());
|
||||
vo.setRole(user.getRole());
|
||||
vo.setRoleDesc(user.getRole() == Constants.USER_ROLE_ADMIN ? "管理员" : "经销商用户");
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changePassword(Long userId, ChangePasswordDTO dto) {
|
||||
User user = userMapper.selectById(userId);
|
||||
if (user == null) {
|
||||
throw new BusinessException("用户不存在");
|
||||
}
|
||||
|
||||
// 验证原密码
|
||||
if (!passwordEncoder.matches(dto.getOldPassword(), user.getPassword())) {
|
||||
throw new BusinessException("原密码错误");
|
||||
}
|
||||
|
||||
// 新密码不能与原密码相同
|
||||
if (dto.getOldPassword().equals(dto.getNewPassword())) {
|
||||
throw new BusinessException("新密码不能与原密码相同");
|
||||
}
|
||||
|
||||
// 加密新密码并更新
|
||||
String encodedPassword = passwordEncoder.encode(dto.getNewPassword());
|
||||
user.setPassword(encodedPassword);
|
||||
userMapper.update(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetPassword(ResetPasswordDTO dto) {
|
||||
User user = userMapper.selectById(dto.getUserId());
|
||||
if (user == null) {
|
||||
throw new BusinessException("用户不存在");
|
||||
}
|
||||
|
||||
// 管理员不能重置自己的密码(应使用修改密码功能)
|
||||
if (user.getRole() == Constants.USER_ROLE_ADMIN) {
|
||||
throw new BusinessException("不能重置管理员密码");
|
||||
}
|
||||
|
||||
// 加密新密码并更新
|
||||
String encodedPassword = passwordEncoder.encode(dto.getNewPassword());
|
||||
user.setPassword(encodedPassword);
|
||||
userMapper.update(user);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||
String rawPassword = "59cce3254e6d76ec6bad2d84ae56b5da3e118b2f22d0d2b2d780356cbe3c0881";
|
||||
String encodedPassword = passwordEncoder.encode(rawPassword);
|
||||
System.out.println("Encoded Password: " + encodedPassword);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user