feat(appUser): 优化代理商报价代码生成逻辑并支持Redis缓存

- 使用Redis缓存报价代码索引,提升报价代码生成性能
- 替换原有序列号生成服务,改用Redis自增策略生成报价代码
- 在编辑客户时,新增根据配置自动生成所属代理商报价代码功能
- 添加初始化APP用户报价代码接口,支持批量生成报价代码
- 修正代码格式及部分逻辑细节,提高代码可读性和维护性
- 在CustomerController中增加事务管理及日志记录功能
This commit is contained in:
曹鹏飞 2026-05-13 11:34:29 +08:00
parent b8ca2a9905
commit 6acd9f8a52
3 changed files with 85 additions and 18 deletions

View File

@ -31,6 +31,8 @@ import com.nflg.mobilebroken.repository.service.IAppUserService;
import com.nflg.mobilebroken.repository.service.ITBaseAreaService;
import com.nflg.mobilebroken.repository.service.ITBaseCustomerService;
import com.nflg.mobilebroken.starter.annotation.MethodInfoMark;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.ttzero.excel.entity.ListSheet;
@ -40,6 +42,7 @@ import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@ -48,6 +51,7 @@ import java.util.stream.Collectors;
/**
* 客户管理
*/
@Slf4j
@RestController
@RequestMapping("/customer")
public class CustomerController extends ControllerBase {
@ -120,6 +124,7 @@ public class CustomerController extends ControllerBase {
* @param customerDTO
* @return
*/
@Transactional
@PostMapping("updateCompany")
@MethodInfoMark(value = "编辑", menuName = "客户管理")
@ApiMark(moduleName = "客户管理", apiName = "编辑")
@ -135,6 +140,23 @@ public class CustomerController extends ControllerBase {
//检查公司名称是否已存在
TBaseCustomer oldEnt = baseCustomerService.getById(customerDTO.getId());
VUtils.trueThrow(Objects.isNull(oldEnt)).throwMessage(STATE.PageError, customerDTO.getAgencyCompanyName() + "公司不存在");
if (customerDTO.getQuotationUse() && !oldEnt.getQuotationUse()) {
//该公司对应的代理商需要生成报价代码
List<AppUser> appUsers = appUserService.lambdaQuery()
.eq(AppUser::getType, 0)
.isNull(AppUser::getQuotationCode)
.apply("FIND_IN_SET({0}, companyId) > 0", customerDTO.getId())
.orderByAsc(AppUser::getId)
.list();
if (CollUtil.isNotEmpty(appUsers)) {
appUsers.forEach(appUser -> {
String quotationCode = appUserService.getAppUserQuotationCode(Arrays.stream(StrUtil.splitToInt(appUser.getCompanyId(), ",")).boxed().collect(Collectors.toList()));
log.info("生成报价代码【{}】:{}", appUser.getName(), quotationCode);
appUser.setQuotationCode(quotationCode);
});
appUserService.updateBatchById(appUsers);
}
}
BeanUtil.copyProperties(customerDTO, oldEnt);
oldEnt.setAreaCode(StrUtil.join(",", customerDTO.getAreaList().stream().map(CustomerAreaDTO::getAreaCode).collect(Collectors.toList())));
oldEnt.setAreaName(StrUtil.join(",", customerDTO.getAreaList().stream().map(CustomerAreaDTO::getAreaName).collect(Collectors.toList())));
@ -203,6 +225,7 @@ public class CustomerController extends ControllerBase {
EecExcelUtil.setResponseExcelHeader(response, "客户列表");
final ListSheet<CustomerExcelVO> listSheet = new ListSheet<CustomerExcelVO>() {
int i = 0;
@Override
protected List<CustomerExcelVO> more() {
List<TBaseCustomer> list = baseCustomerService.list();

View File

@ -5,10 +5,7 @@ import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.nflg.mobilebroken.common.pojo.ApiResult;
import com.nflg.mobilebroken.common.util.VUtils;
import com.nflg.mobilebroken.repository.entity.AdminUser;
import com.nflg.mobilebroken.repository.entity.ProductModel;
import com.nflg.mobilebroken.repository.entity.TBaseArea;
import com.nflg.mobilebroken.repository.entity.TBaseCustomer;
import com.nflg.mobilebroken.repository.entity.*;
import com.nflg.mobilebroken.repository.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
@ -18,9 +15,7 @@ import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.sql.Struct;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@ -47,6 +42,12 @@ public class TestController extends ControllerBase {
@Resource
private IAdminBaseSerialNumberService serialNumberService;
@Resource
private IAppUserService appUserService;
@Resource
private ITBaseCustomerService customerService;
/**
* 初始化机型表的BatchNumber字段数据
*/
@ -133,8 +134,8 @@ public class TestController extends ControllerBase {
* 初始化内部用户报价代码字段数据
*/
@PostMapping("initAdminUserQuotationCode")
public ApiResult<Void> initAdminUserQuotationCode(){
List<AdminUser> adminUsers=adminUserService.lambdaQuery()
public ApiResult<Void> initAdminUserQuotationCode() {
List<AdminUser> adminUsers = adminUserService.lambdaQuery()
.isNull(AdminUser::getQuotationCode)
.orderByAsc(AdminUser::getId)
.list();
@ -150,4 +151,36 @@ public class TestController extends ControllerBase {
return ApiResult.success();
}
/**
* 初始化APP用户报价代码字段数据
*/
@PostMapping("initAppUserQuotationCode")
public ApiResult<Void> initAppUserQuotationCode() {
Set<Integer> customers = customerService.getForQuotation()
.stream()
.map(TBaseCustomer::getId)
.collect(Collectors.toSet());
List<AppUser> appUsers = appUserService.lambdaQuery()
.eq(AppUser::getType, 0)
.isNull(AppUser::getQuotationCode)
.orderByAsc(AppUser::getId)
.list();
appUsers.removeIf(appUser -> customers.stream()
.noneMatch(customerId -> Arrays.stream(StrUtil.splitToInt(appUser.getCompanyId(), ","))
.boxed()
.collect(Collectors.toList())
.contains(customerId)
)
);
if (CollectionUtil.isNotEmpty(appUsers)) {
appUsers.forEach(appUser -> {
String quotationCode = appUserService.getAppUserQuotationCode(Arrays.stream(StrUtil.splitToInt(appUser.getCompanyId(), ",")).boxed().collect(Collectors.toList()));
log.info("生成报价代码【{}】:{}", appUser.getName(), quotationCode);
appUser.setQuotationCode(quotationCode);
});
appUserService.updateBatchById(appUsers);
return ApiResult.success();
}
return ApiResult.success();
}
}

View File

@ -19,6 +19,7 @@ import com.nflg.mobilebroken.common.util.VUtils;
import com.nflg.mobilebroken.repository.entity.*;
import com.nflg.mobilebroken.repository.mapper.AppUserMapper;
import com.nflg.mobilebroken.repository.service.*;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@ -80,7 +81,7 @@ public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> impl
private IDictionaryItemService dictionaryItemService;
@Resource
private IAdminBaseSerialNumberService adminBaseSerialNumberService;
private RedisTemplate<String, Integer> redisTemplate;
@Override
public String getAppUserQuotationCode(List<Integer> companyId) {
@ -105,7 +106,7 @@ public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> impl
.filter(StrUtil::isNotBlank)
.collect(Collectors.toSet());
VUtils.trueThrowBusinessError(CollectionUtil.isEmpty(uniqueAreaCodes)).throwMessage("存在未维护区域信息的代理公司,请先维护区域信息");
String specialCode = "";
String specialCode = "A";
List<TBaseArea> areas = adminAreaService.lambdaQuery()
.in(TBaseArea::getAreaCode, uniqueAreaCodes)
.list();
@ -117,7 +118,7 @@ public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> impl
// 如果是只有一个公司或区域就返回区域报价代码
if (areas.size() == 1) {
VUtils.trueThrowBusinessError(StrUtil.isBlank(areas.get(0).getAreaQuoteCode())).throwMessage("区域报价代码没有维护,请先维护");
specialCode = areas.get(0).getAreaQuoteCode();
specialCode += areas.get(0).getAreaQuoteCode();
}
// 如果存在多个公司或区域需要查询上级
Set<Integer> parentIds = areas.stream()
@ -130,7 +131,7 @@ public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> impl
// 如果只有一个上级就返回上级报价代码
if (parentAreas.size() == 1) {
VUtils.trueThrowBusinessError(StrUtil.isBlank(parentAreas.get(0).getAreaQuoteCode())).throwMessage("区域报价代码没有维护,请先维护");
specialCode = parentAreas.get(0).getAreaQuoteCode();
specialCode += parentAreas.get(0).getAreaQuoteCode();
} else {
// 多个上级区别处理合并相同上级的单独列出一个上级的
Map<Integer, Long> parentCountMap = areas.stream()
@ -168,9 +169,19 @@ public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> impl
specialCode += "-" + baseArea.getAreaQuoteCode();
}
}
String code = adminBaseSerialNumberService.generateSerialNumber(1, "", specialCode, false, 6);
return code;
String key = "quotation:appUser:quotationCode:" + specialCode;
Integer index = redisTemplate.opsForValue().get(key);
if (Objects.isNull(index)) {
AppUser lastUser = lambdaQuery()
.likeRight(AppUser::getQuotationCode, specialCode)
.orderByDesc(AppUser::getQuotationCode)
.last("limit 1")
.one();
index = Objects.isNull(lastUser) ? 0 : Integer.parseInt(lastUser.getQuotationCode().replace(specialCode, ""));
}
index++;
redisTemplate.opsForValue().set(key, index);
return specialCode + String.format("%06d", index);
}
@ -531,8 +542,8 @@ public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> impl
@Override
public List<AppUser> getEndUsers() {
return lambdaQuery()
.eq(AppUser::getIsDel,0)
.eq(AppUser::getType,1)
.eq(AppUser::getIsDel, 0)
.eq(AppUser::getType, 1)
.list();
}