feat(quotation): 添加代理商系数配置功能

- 新增RatioAgentController控制器,提供动态表头获取接口
- 添加QuotationModelRatioAgent和QuotationModelRatioAgentItem实体类
- 生成对应的Mapper、Service接口及实现类
- 修改CodeGeneratorTest测试类,更新代码生成目标表名
- 调整ModelPriceConfigVO,移除id字段
- 更新PriceConfigController中的价格配置逻辑,添加版本状态初始化
- 优化价格项目区域数据的添加和更新流程
This commit is contained in:
曹鹏飞 2026-02-27 16:16:16 +08:00
parent 6b4ce63ff4
commit 6e5a1375cd
14 changed files with 354 additions and 15 deletions

View File

@ -13,7 +13,7 @@ import java.util.Objects;
@Accessors(chain = true)
public class ModelPriceConfigVO {
private Long id;
// private Long id;
/**
* 机型表batch_number

View File

@ -304,6 +304,8 @@ public class PriceConfigController extends ControllerBase {
List<QuotationModelPriceItem> itemsForAdd = new ArrayList<>();
price.setId(IdUtil.getSnowflakeNextId());
price.setConfigId(null);
price.setPriceVersion(null);
price.setPriceStatus(0);
price.setUpdateById(AdminUserUtil.getUserId());
price.setUpdateBy(AdminUserUtil.getUserName());
price.setUpdateTime(LocalDateTime.now());
@ -328,7 +330,6 @@ public class PriceConfigController extends ControllerBase {
area.setId(IdUtil.getSnowflakeNextId());
area.setPriceId(price.getId());
area.setAmount(new BigDecimal(map.get(category.getCode())));
areasForAdd.add(area);
} else {
areasForAdd.add(new QuotationModelPriceItemArea()
.setAreaId(category.getId())
@ -370,31 +371,41 @@ public class PriceConfigController extends ControllerBase {
.orElse(null);
if (Objects.nonNull(area)) {
area.setAmount(new BigDecimal(map.get(category.getCode())));
areasForAdd.add(area);
}else {
areasForAdd.add(new QuotationModelPriceItemArea()
.setAreaId(category.getId())
.setPriceId(price.getId())
.setPriceItemId(0L)
.setAmount(new BigDecimal(map.get(category.getCode())))
);
}
}
}
}
}
for (QuotationModelPriceItem item : dbItems) {
Long itemId = IdUtil.getSnowflakeNextId();
item.setUpdateById(AdminUserUtil.getUserId());
item.setUpdateBy(AdminUserUtil.getUserName());
item.setUpdateTime(LocalDateTime.now());
item.setPriceId(price.getId());
areasForAdd.stream()
.filter(area -> area.getPriceItemId().equals(item.getId()))
.forEach(area -> area.setPriceItemId(itemId));
item.setId(itemId);
}
priceService.save(price);
if (CollectionUtil.isNotEmpty(itemsForAdd)) {
priceItemService.saveBatch(itemsForAdd);
}
if (CollectionUtil.isNotEmpty(dbItems)) {
for (QuotationModelPriceItem item : dbItems) {
Long itemId = IdUtil.getSnowflakeNextId();
item.setUpdateById(AdminUserUtil.getUserId());
item.setUpdateBy(AdminUserUtil.getUserName());
item.setUpdateTime(LocalDateTime.now());
item.setPriceId(price.getId());
areasForAdd.stream()
.filter(area -> area.getPriceItemId().equals(item.getId()))
.forEach(area -> area.setPriceItemId(itemId));
item.setId(itemId);
}
priceItemService.saveBatch(dbItems);
}
if (CollectionUtil.isNotEmpty(areasForAdd)) {
for (QuotationModelPriceItemArea area : areasForAdd) {
area.setId(IdUtil.getSnowflakeNextId());
area.setPriceId(price.getId());
}
priceItemAreaService.saveBatch(areasForAdd);
}
}

View File

@ -0,0 +1,100 @@
package com.nflg.mobilebroken.quotation.controller.admin;
import cn.hutool.core.util.StrUtil;
import com.nflg.mobilebroken.common.constant.Constant;
import com.nflg.mobilebroken.common.pojo.ApiResult;
import com.nflg.mobilebroken.common.pojo.vo.DynamicHeaderVO;
import com.nflg.mobilebroken.quotation.controller.ControllerBase;
import com.nflg.mobilebroken.repository.entity.AppUser;
import com.nflg.mobilebroken.repository.entity.DictionaryItem;
import com.nflg.mobilebroken.repository.entity.TBaseCustomer;
import com.nflg.mobilebroken.repository.service.IAppUserService;
import com.nflg.mobilebroken.repository.service.IDictionaryItemService;
import com.nflg.mobilebroken.repository.service.ITBaseCustomerService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* 代理商配置系数
*/
@RestController
@RequestMapping("/ratio/agent")
public class RatioAgentController extends ControllerBase {
@Resource
private IAppUserService appUserService;
@Resource
private ITBaseCustomerService customerService;
@Resource
private IDictionaryItemService dictionaryItemService;
/**
* 获取动态表头
*/
@GetMapping("/headers")
public ApiResult<List<DynamicHeaderVO>> getHeaders() {
List<DynamicHeaderVO> vos = new ArrayList<>();
vos.add(new DynamicHeaderVO()
.setProp("appUser")
.setLabel("代理商账号")
.setChildren(new ArrayList<>() {
{
add(new DynamicHeaderVO().setProp("modelNo").setLabel("机型"));
}
})
);
List<TBaseCustomer> customers = customerService.lambdaQuery()
.select(TBaseCustomer::getId, TBaseCustomer::getCategoryId)
.eq(TBaseCustomer::getDelIs, 0)
.eq(TBaseCustomer::getEnableState, 1)
.list();
List<DictionaryItem> categories = dictionaryItemService.getListByDictionaryCode(Constant.DICTIONARY_DIRECT_SALES_CATEGORY);
List<AppUser> users = appUserService.lambdaQuery()
.eq(AppUser::getIsDel, false)
.eq(AppUser::getIsPrimary, true)
.list();
users.forEach(user -> {
TBaseCustomer customer = customers.stream()
.filter(cit -> StrUtil.split(user.getCompanyId(), ',').contains(cit.getId().toString()))
.findFirst()
.orElse(null);
String categoryName;
if (Objects.nonNull(customer)) {
DictionaryItem category = categories.stream()
.filter(cit -> cit.getId().equals(customer.getCategoryId()))
.findFirst()
.orElse(null);
if (Objects.nonNull(category)) {
categoryName = category.getName();
} else {
categoryName = "未知";
}
} else {
categoryName = "未知";
}
DynamicHeaderVO avo = new DynamicHeaderVO()
.setProp(user.getId().toString())
.setLabel(user.getName())
.setChildren(new ArrayList<>() {
{
add(new DynamicHeaderVO().setProp("standardPrice").setLabel("标配价(" + categoryName + ")"));
add(new DynamicHeaderVO().setProp("standardRatio").setLabel("标配系数"));
add(new DynamicHeaderVO().setProp("optionalRatio").setLabel("选配系数"));
add(new DynamicHeaderVO().setProp("salePrice").setLabel("市场价(" + categoryName + ")"));
}
});
vos.add(avo);
});
return ApiResult.success(vos);
}
}

View File

@ -0,0 +1,62 @@
package com.nflg.mobilebroken.repository.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
/**
* <p>
* 报价-代理商系数
* </p>
*
* @author 代码生成器生成
* @since 2026
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("quotation_model_ratio_agent")
public class QuotationModelRatioAgent implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
/**
* 年份
*/
private String year;
/**
* 版本号
*/
private String version;
/**
* 状态0草稿1已发布2已废弃
*/
private Integer staus;
/**
* 创建人类型0内部用户1代理商账号
*/
private Integer createByType;
/**
* 创建人id
*/
private Integer createById;
/**
* 创建人
*/
private String createBy;
/**
* 创建时间
*/
private LocalDateTime createTime;
}

View File

@ -0,0 +1,52 @@
package com.nflg.mobilebroken.repository.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
/**
* <p>
* 报价-代理商系数-子项
* </p>
*
* @author 代码生成器生成
* @since 2026
*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("quotation_model_ratio_agent_item")
public class QuotationModelRatioAgentItem implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
/**
* 系数id
*/
private Long ratioId;
/**
* 机型id
*/
private Integer modelId;
/**
* 代理商账号id
*/
private Integer userId;
/**
* 标配系数
*/
private BigDecimal standardRatio;
/**
* 选配系数
*/
private BigDecimal optionalRatio;
}

View File

@ -0,0 +1,16 @@
package com.nflg.mobilebroken.repository.mapper;
import com.nflg.mobilebroken.repository.entity.QuotationModelRatioAgentItem;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 报价-代理商系数-子项 Mapper 接口
* </p>
*
* @author 代码生成器生成
* @since 2026
*/
public interface QuotationModelRatioAgentItemMapper extends BaseMapper<QuotationModelRatioAgentItem> {
}

View File

@ -0,0 +1,16 @@
package com.nflg.mobilebroken.repository.mapper;
import com.nflg.mobilebroken.repository.entity.QuotationModelRatioAgent;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 报价-代理商系数 Mapper 接口
* </p>
*
* @author 代码生成器生成
* @since 2026
*/
public interface QuotationModelRatioAgentMapper extends BaseMapper<QuotationModelRatioAgent> {
}

View File

@ -0,0 +1,16 @@
package com.nflg.mobilebroken.repository.service;
import com.nflg.mobilebroken.repository.entity.QuotationModelRatioAgentItem;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 报价-代理商系数-子项 服务类
* </p>
*
* @author 代码生成器生成
* @since 2026
*/
public interface IQuotationModelRatioAgentItemService extends IService<QuotationModelRatioAgentItem> {
}

View File

@ -0,0 +1,16 @@
package com.nflg.mobilebroken.repository.service;
import com.nflg.mobilebroken.repository.entity.QuotationModelRatioAgent;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 报价-代理商系数 服务类
* </p>
*
* @author 代码生成器生成
* @since 2026
*/
public interface IQuotationModelRatioAgentService extends IService<QuotationModelRatioAgent> {
}

View File

@ -0,0 +1,20 @@
package com.nflg.mobilebroken.repository.service.impl;
import com.nflg.mobilebroken.repository.entity.QuotationModelRatioAgentItem;
import com.nflg.mobilebroken.repository.mapper.QuotationModelRatioAgentItemMapper;
import com.nflg.mobilebroken.repository.service.IQuotationModelRatioAgentItemService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 报价-代理商系数-子项 服务实现类
* </p>
*
* @author 代码生成器生成
* @since 2026
*/
@Service
public class QuotationModelRatioAgentItemServiceImpl extends ServiceImpl<QuotationModelRatioAgentItemMapper, QuotationModelRatioAgentItem> implements IQuotationModelRatioAgentItemService {
}

View File

@ -0,0 +1,20 @@
package com.nflg.mobilebroken.repository.service.impl;
import com.nflg.mobilebroken.repository.entity.QuotationModelRatioAgent;
import com.nflg.mobilebroken.repository.mapper.QuotationModelRatioAgentMapper;
import com.nflg.mobilebroken.repository.service.IQuotationModelRatioAgentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 报价-代理商系数 服务实现类
* </p>
*
* @author 代码生成器生成
* @since 2026
*/
@Service
public class QuotationModelRatioAgentServiceImpl extends ServiceImpl<QuotationModelRatioAgentMapper, QuotationModelRatioAgent> implements IQuotationModelRatioAgentService {
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nflg.mobilebroken.repository.mapper.QuotationModelRatioAgentItemMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nflg.mobilebroken.repository.mapper.QuotationModelRatioAgentMapper">
</mapper>

View File

@ -33,7 +33,7 @@ public class CodeGeneratorTest {
, Paths.get(System.getProperty("user.dir")) + "/src/main/resources/mapper"))
)
.strategyConfig(builder -> {
builder.addInclude("quotation_model_forbid") //只生成指定表
builder.addInclude("quotation_model_ratio_agent_item") //只生成指定表
.entityBuilder()
.enableLombok()
.enableChainModel()